fis-gtm/sr_port/op_div.c

76 lines
1.7 KiB
C

/****************************************************************
* *
* Copyright 2001, 2011 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
* under a license. If you do not know the terms of *
* the license, please stop and do not read further. *
* *
****************************************************************/
#include "mdef.h"
#include "arit.h"
#include "stringpool.h"
#include "eb_muldiv.h"
#include "promodemo.h"
#include "op.h"
LITREF int4 ten_pwr[];
LITREF mval literal_zero;
error_def(ERR_DIVZERO);
error_def(ERR_NUMOFLOW);
void op_div (mval *u, mval *v, mval *q)
{
bool promo;
int4 c, exp;
mval w, z;
MV_FORCE_NUM(u);
MV_FORCE_NUM(v);
if ((v->mvtype & MV_INT) && v->m[1] == 0)
rts_error(VARLSTCNT(1) ERR_DIVZERO);
if (u->mvtype & MV_INT & v->mvtype)
{
promo = eb_mvint_div(u->m[1], v->m[1], q->m);
if (!promo)
{
q->mvtype = MV_NM | MV_INT;
return;
} else
{
w = *u; z = *v;
promote(&w); promote(&z);
u = &w; v = &z;
}
} else if (u->mvtype & MV_INT)
{
w = *u;
promote(&w);
u = &w;
} else if (v->mvtype & MV_INT)
{
w = *v;
promote(&w);
v = &w;
}
c = eb_div(v->m, u->m, q->m);
exp = u->e - v->e + c + MV_XBIAS;
if (EXPHI <= exp)
rts_error(VARLSTCNT(1) ERR_NUMOFLOW);
else if (exp < EXPLO)
*q = literal_zero;
else if (exp < EXP_INT_OVERF && exp > EXP_INT_UNDERF && q->m[0] == 0 && (q->m[1]%ten_pwr[EXP_INT_OVERF-1-exp] == 0))
demote(q, exp, u->sgn ^ v->sgn);
else
{
q->mvtype = MV_NM;
q->sgn = u->sgn ^ v->sgn;
q->e = exp;
}
assert(q->m[1] < MANT_HI);
}