### Diff for /gforth/engine/dblsub.c between versions 1.7 and 1.8

version 1.7, 2006/10/23 08:45:00 version 1.8, 2006/10/30 15:29:48
Line 24 Line 24
#include "config.h"  #include "config.h"
#include "forth.h"  #include "forth.h"

/* !! a bit machine dependent */
#define HALFCELL_BITS   (CELL_BITS/2)
#define UH(x)           (((UCell)(x))>>HALFCELL_BITS)
#define LH(x)           ((x)&((~(UCell)0)>>HALFCELL_BITS))
#define L2U(x)          (((UCell)(x))<<HALFCELL_BITS)
#define HIGHBIT(x)      (((UCell)(x))>>(CELL_BITS-1))
#define UD2D(ud)        ({UDCell _ud=(ud); (DCell){_ud.hi,_ud.lo};})
#define D2UD(d)         ({DCell _d=(d); (UDCell){_d.hi,_d.lo};})

DCell dnegate(DCell d1)  DCell dnegate(DCell d1)
{  {
DCell res;    DCell res;
Line 72  DCell mmul (Cell a, Cell b)  /* signed m Line 63  DCell mmul (Cell a, Cell b)  /* signed m
res.hi -= a;      res.hi -= a;
return res;    return res;
}  }

UDCell umdiv (UDCell u, UCell v)
/* Divide unsigned double by single precision using shifts and subtracts.
Return quotient in lo, remainder in hi. */
{
int i = CELL_BITS, c = 0;
UCell q = 0, h = u.hi, l = u.lo;
UDCell res;

if (v==0)
throw(BALL_DIVZERO);
if (h>=v)
throw(BALL_RESULTRANGE);
for (;;)
{
if (c || h >= v)
{
q++;
h -= v;
}
if (--i < 0)
break;
c = HIGHBIT (h);
h <<= 1;
h += HIGHBIT (l);
l <<= 1;
q <<= 1;
}
res.hi = h;
res.lo = q;
return res;
}

DCell smdiv (DCell num, Cell denom)     /* symmetric divide procedure, mixed prec */
{
DCell res;
Cell numsign=num.hi;
Cell denomsign=denom;

if (numsign < 0)
num = dnegate (num);
if (denomsign < 0)
denom = -denom;
res = UD2D(umdiv (D2UD(num), denom));
if ((numsign^denomsign)<0) {
res.lo = -res.lo;
if (((Cell)res.lo) > 0) /* note: == 0 is possible */
throw(BALL_RESULTRANGE);
} else {
if (((Cell)res.lo) < 0)
throw(BALL_RESULTRANGE);
}
if (numsign<0)
res.hi = -res.hi;
return res;
}

DCell fmdiv (DCell num, Cell denom)     /* floored divide procedure, mixed prec */
{
/* I have this technique from Andrew Haley */
DCell res;
Cell denomsign=denom;
Cell numsign;

if (denom < 0) {
denom = -denom;
num = dnegate(num);
}
numsign = num.hi;
if (numsign < 0)
num.hi += denom;
res = UD2D(umdiv(D2UD(num),denom));
if ((numsign^((Cell)res.lo)) < 0)
throw(BALL_RESULTRANGE);
if (denomsign<0)
res.hi = -res.hi;
return res;
}

 Removed from v.1.7 changed lines Added in v.1.8

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>