Commit f988ec96 by Ben Elliston Committed by Ben Elliston

decNumber.c, [...]: Upgrade to decNumber 3.61.

	* decNumber.c, decNumber.h, decNumberLocal.h, decDouble.c,
	decDouble.h, decSingle.c, decContext.c, decSingle.h, decPacked.c,
	decCommon.c, decContext.h, decQuad.c, decPacked.h, decQuad.h,
	decDPD.h, decBasic.c: Upgrade to decNumber 3.61.
	* dpd/decimal128.h, dpd/decimal32.c, dpd/decimal32.h,
	dpd/decimal64.c, dpd/decimal128.c, dpd/decimal64.h: Likewise.

From-SVN: r145222
parent 7cdc1972
2009-03-29 Ben Elliston <bje@au.ibm.com>
* decNumber.c, decNumber.h, decNumberLocal.h, decDouble.c,
decDouble.h, decSingle.c, decContext.c, decSingle.h, decPacked.c,
decCommon.c, decContext.h, decQuad.c, decPacked.h, decQuad.h,
decDPD.h, decBasic.c: Upgrade to decNumber 3.61.
* dpd/decimal128.h, dpd/decimal32.c, dpd/decimal32.h,
dpd/decimal64.c, dpd/decimal128.c, dpd/decimal64.h: Likewise.
2009-02-10 Joseph Myers <joseph@codesourcery.com> 2009-02-10 Joseph Myers <joseph@codesourcery.com>
* Makefile.in (clean): Don't remove makedepend$(EXEEXT). * Makefile.in (clean): Don't remove makedepend$(EXEEXT).
......
...@@ -32,8 +32,8 @@ ...@@ -32,8 +32,8 @@
/* decBasic.c -- common base code for Basic decimal types */ /* decBasic.c -- common base code for Basic decimal types */
/* ------------------------------------------------------------------ */ /* ------------------------------------------------------------------ */
/* This module comprises code that is shared between decDouble and */ /* This module comprises code that is shared between decDouble and */
/* decQuad (but not decSingle). The main arithmetic operations are */ /* decQuad (but not decSingle). The main arithmetic operations are */
/* here (Add, Subtract, Multiply, FMA, and Division operators). */ /* here (Add, Subtract, Multiply, FMA, and Division operators). */
/* */ /* */
/* Unlike decNumber, parameterization takes place at compile time */ /* Unlike decNumber, parameterization takes place at compile time */
/* rather than at runtime. The parameters are set in the decDouble.c */ /* rather than at runtime. The parameters are set in the decDouble.c */
...@@ -59,7 +59,7 @@ ...@@ -59,7 +59,7 @@
#define DIVIDE 0x80000000 /* Divide operations [as flags] */ #define DIVIDE 0x80000000 /* Divide operations [as flags] */
#define REMAINDER 0x40000000 /* .. */ #define REMAINDER 0x40000000 /* .. */
#define DIVIDEINT 0x20000000 /* .. */ #define DIVIDEINT 0x20000000 /* .. */
#define REMNEAR 0x10000000 /* .. */ #define REMNEAR 0x10000000 /* .. */
/* Private functions (local, used only by routines in this module) */ /* Private functions (local, used only by routines in this module) */
static decFloat *decDivide(decFloat *, const decFloat *, static decFloat *decDivide(decFloat *, const decFloat *,
...@@ -81,7 +81,7 @@ static uInt decToInt32(const decFloat *, decContext *, enum rounding, ...@@ -81,7 +81,7 @@ static uInt decToInt32(const decFloat *, decContext *, enum rounding,
/* decCanonical -- copy a decFloat, making canonical */ /* decCanonical -- copy a decFloat, making canonical */
/* */ /* */
/* result gets the canonicalized df */ /* result gets the canonicalized df */
/* df is the decFloat to copy and make canonical */ /* df is the decFloat to copy and make canonical */
/* returns result */ /* returns result */
/* */ /* */
/* This is exposed via decFloatCanonical for Double and Quad only. */ /* This is exposed via decFloatCanonical for Double and Quad only. */
...@@ -141,14 +141,14 @@ static decFloat * decCanonical(decFloat *result, const decFloat *df) { ...@@ -141,14 +141,14 @@ static decFloat * decCanonical(decFloat *result, const decFloat *df) {
uoff-=32; uoff-=32;
dpd|=encode<<(10-uoff); /* get pending bits */ dpd|=encode<<(10-uoff); /* get pending bits */
} }
dpd&=0x3ff; /* clear uninteresting bits */ dpd&=0x3ff; /* clear uninteresting bits */
if (dpd<0x16e) continue; /* must be canonical */ if (dpd<0x16e) continue; /* must be canonical */
canon=BIN2DPD[DPD2BIN[dpd]]; /* determine canonical declet */ canon=BIN2DPD[DPD2BIN[dpd]]; /* determine canonical declet */
if (canon==dpd) continue; /* have canonical declet */ if (canon==dpd) continue; /* have canonical declet */
/* need to replace declet */ /* need to replace declet */
if (uoff>=10) { /* all within current word */ if (uoff>=10) { /* all within current word */
encode&=~(0x3ff<<(uoff-10)); /* clear the 10 bits ready for replace */ encode&=~(0x3ff<<(uoff-10)); /* clear the 10 bits ready for replace */
encode|=canon<<(uoff-10); /* insert the canonical form */ encode|=canon<<(uoff-10); /* insert the canonical form */
DFWORD(result, inword)=encode; /* .. and save */ DFWORD(result, inword)=encode; /* .. and save */
continue; continue;
} }
...@@ -167,16 +167,16 @@ static decFloat * decCanonical(decFloat *result, const decFloat *df) { ...@@ -167,16 +167,16 @@ static decFloat * decCanonical(decFloat *result, const decFloat *df) {
/* decDivide -- divide operations */ /* decDivide -- divide operations */
/* */ /* */
/* result gets the result of dividing dfl by dfr: */ /* result gets the result of dividing dfl by dfr: */
/* dfl is the first decFloat (lhs) */ /* dfl is the first decFloat (lhs) */
/* dfr is the second decFloat (rhs) */ /* dfr is the second decFloat (rhs) */
/* set is the context */ /* set is the context */
/* op is the operation selector */ /* op is the operation selector */
/* returns result */ /* returns result */
/* */ /* */
/* op is one of DIVIDE, REMAINDER, DIVIDEINT, or REMNEAR. */ /* op is one of DIVIDE, REMAINDER, DIVIDEINT, or REMNEAR. */
/* ------------------------------------------------------------------ */ /* ------------------------------------------------------------------ */
#define DIVCOUNT 0 /* 1 to instrument subtractions counter */ #define DIVCOUNT 0 /* 1 to instrument subtractions counter */
#define DIVBASE BILLION /* the base used for divide */ #define DIVBASE ((uInt)BILLION) /* the base used for divide */
#define DIVOPLEN DECPMAX9 /* operand length ('digits' base 10**9) */ #define DIVOPLEN DECPMAX9 /* operand length ('digits' base 10**9) */
#define DIVACCLEN (DIVOPLEN*3) /* accumulator length (ditto) */ #define DIVACCLEN (DIVOPLEN*3) /* accumulator length (ditto) */
static decFloat * decDivide(decFloat *result, const decFloat *dfl, static decFloat * decDivide(decFloat *result, const decFloat *dfl,
...@@ -184,17 +184,18 @@ static decFloat * decDivide(decFloat *result, const decFloat *dfl, ...@@ -184,17 +184,18 @@ static decFloat * decDivide(decFloat *result, const decFloat *dfl,
decFloat quotient; /* for remainders */ decFloat quotient; /* for remainders */
bcdnum num; /* for final conversion */ bcdnum num; /* for final conversion */
uInt acc[DIVACCLEN]; /* coefficent in base-billion .. */ uInt acc[DIVACCLEN]; /* coefficent in base-billion .. */
uInt div[DIVOPLEN]; /* divisor in base-billion .. */ uInt div[DIVOPLEN]; /* divisor in base-billion .. */
uInt quo[DIVOPLEN+1]; /* quotient in base-billion .. */ uInt quo[DIVOPLEN+1]; /* quotient in base-billion .. */
uByte bcdacc[(DIVOPLEN+1)*9+2]; /* for quotient in BCD, +1, +1 */ uByte bcdacc[(DIVOPLEN+1)*9+2]; /* for quotient in BCD, +1, +1 */
uInt *msua, *msud, *msuq; /* -> msu of acc, div, and quo */ uInt *msua, *msud, *msuq; /* -> msu of acc, div, and quo */
Int divunits, accunits; /* lengths */ Int divunits, accunits; /* lengths */
Int quodigits; /* digits in quotient */ Int quodigits; /* digits in quotient */
uInt *lsua, *lsuq; /* -> current acc and quo lsus */ uInt *lsua, *lsuq; /* -> current acc and quo lsus */
Int length, multiplier; /* work */ Int length, multiplier; /* work */
uInt carry, sign; /* .. */ uInt carry, sign; /* .. */
uInt *ua, *ud, *uq; /* .. */ uInt *ua, *ud, *uq; /* .. */
uByte *ub; /* .. */ uByte *ub; /* .. */
uInt uiwork; /* for macros */
uInt divtop; /* top unit of div adjusted for estimating */ uInt divtop; /* top unit of div adjusted for estimating */
#if DIVCOUNT #if DIVCOUNT
static uInt maxcount=0; /* worst-seen subtractions count */ static uInt maxcount=0; /* worst-seen subtractions count */
...@@ -235,7 +236,7 @@ static decFloat * decDivide(decFloat *result, const decFloat *dfl, ...@@ -235,7 +236,7 @@ static decFloat * decDivide(decFloat *result, const decFloat *dfl,
if (op&(REMAINDER|REMNEAR)) return decInvalid(result, set); /* bad rem */ if (op&(REMAINDER|REMNEAR)) return decInvalid(result, set); /* bad rem */
set->status|=DEC_Division_by_zero; set->status|=DEC_Division_by_zero;
DFWORD(result, 0)=num.sign; DFWORD(result, 0)=num.sign;
return decInfinity(result, result); /* x/0 -> signed Infinity */ return decInfinity(result, result); /* x/0 -> signed Infinity */
} }
num.exponent=GETEXPUN(dfl)-GETEXPUN(dfr); /* ideal exponent */ num.exponent=GETEXPUN(dfl)-GETEXPUN(dfr); /* ideal exponent */
if (DFISZERO(dfl)) { /* 0/x (x!=0) */ if (DFISZERO(dfl)) { /* 0/x (x!=0) */
...@@ -246,7 +247,7 @@ static decFloat * decDivide(decFloat *result, const decFloat *dfl, ...@@ -246,7 +247,7 @@ static decFloat * decDivide(decFloat *result, const decFloat *dfl,
DFWORD(result, 0)|=num.sign; /* add sign */ DFWORD(result, 0)|=num.sign; /* add sign */
return result; return result;
} }
if (!(op&DIVIDE)) { /* a remainder */ if (!(op&DIVIDE)) { /* a remainder */
/* exponent is the minimum of the operands */ /* exponent is the minimum of the operands */
num.exponent=MINI(GETEXPUN(dfl), GETEXPUN(dfr)); num.exponent=MINI(GETEXPUN(dfl), GETEXPUN(dfr));
/* if the result is zero the sign shall be sign of dfl */ /* if the result is zero the sign shall be sign of dfl */
...@@ -289,7 +290,7 @@ static decFloat * decDivide(decFloat *result, const decFloat *dfl, ...@@ -289,7 +290,7 @@ static decFloat * decDivide(decFloat *result, const decFloat *dfl,
#endif #endif
/* set msu and lsu pointers */ /* set msu and lsu pointers */
msua=acc+DIVACCLEN-1; /* [leading zeros removed below] */ msua=acc+DIVACCLEN-1; /* [leading zeros removed below] */
msuq=quo+DIVOPLEN; msuq=quo+DIVOPLEN;
/*[loop for div will terminate because operands are non-zero] */ /*[loop for div will terminate because operands are non-zero] */
for (msud=div+DIVOPLEN-1; *msud==0;) msud--; for (msud=div+DIVOPLEN-1; *msud==0;) msud--;
...@@ -298,7 +299,7 @@ static decFloat * decDivide(decFloat *result, const decFloat *dfl, ...@@ -298,7 +299,7 @@ static decFloat * decDivide(decFloat *result, const decFloat *dfl,
/* This moves one position towards the least possible for each */ /* This moves one position towards the least possible for each */
/* iteration */ /* iteration */
divunits=(Int)(msud-div+1); /* precalculate */ divunits=(Int)(msud-div+1); /* precalculate */
lsua=msua-divunits+1; /* initial working lsu of acc */ lsua=msua-divunits+1; /* initial working lsu of acc */
lsuq=msuq; /* and of quo */ lsuq=msuq; /* and of quo */
/* set up the estimator for the multiplier; this is the msu of div, */ /* set up the estimator for the multiplier; this is the msu of div, */
...@@ -371,7 +372,7 @@ static decFloat * decDivide(decFloat *result, const decFloat *dfl, ...@@ -371,7 +372,7 @@ static decFloat * decDivide(decFloat *result, const decFloat *dfl,
for (ud=msud, ua=msua; ud>div; ud--, ua--) if (*ud!=*ua) break; for (ud=msud, ua=msua; ud>div; ud--, ua--) if (*ud!=*ua) break;
/* [now at first mismatch or lsu] */ /* [now at first mismatch or lsu] */
if (*ud>*ua) break; /* next time... */ if (*ud>*ua) break; /* next time... */
if (*ud==*ua) { /* all compared equal */ if (*ud==*ua) { /* all compared equal */
*lsuq+=1; /* increment result */ *lsuq+=1; /* increment result */
msua=lsua; /* collapse acc units */ msua=lsua; /* collapse acc units */
*msua=0; /* .. to a zero */ *msua=0; /* .. to a zero */
...@@ -418,10 +419,11 @@ static decFloat * decDivide(decFloat *result, const decFloat *dfl, ...@@ -418,10 +419,11 @@ static decFloat * decDivide(decFloat *result, const decFloat *dfl,
} }
else if (divunits==1) { else if (divunits==1) {
mul=(uLong)*msua * DIVBASE + *(msua-1); mul=(uLong)*msua * DIVBASE + *(msua-1);
mul/=*msud; /* no more to the right */ mul/=*msud; /* no more to the right */
} }
else { else {
mul=(uLong)(*msua) * (uInt)(DIVBASE<<2) + (*(msua-1)<<2); mul=(uLong)(*msua) * (uInt)(DIVBASE<<2)
+ (*(msua-1)<<2);
mul/=divtop; /* [divtop already allows for sticky bits] */ mul/=divtop; /* [divtop already allows for sticky bits] */
} }
multiplier=(Int)mul; multiplier=(Int)mul;
...@@ -540,10 +542,10 @@ static decFloat * decDivide(decFloat *result, const decFloat *dfl, ...@@ -540,10 +542,10 @@ static decFloat * decDivide(decFloat *result, const decFloat *dfl,
/* most significant end [offset by one into bcdacc to leave room */ /* most significant end [offset by one into bcdacc to leave room */
/* for a possible carry digit if rounding for REMNEAR is needed] */ /* for a possible carry digit if rounding for REMNEAR is needed] */
for (uq=msuq, ub=bcdacc+1; uq>=lsuq; uq--, ub+=9) { for (uq=msuq, ub=bcdacc+1; uq>=lsuq; uq--, ub+=9) {
uInt top, mid, rem; /* work */ uInt top, mid, rem; /* work */
if (*uq==0) { /* no split needed */ if (*uq==0) { /* no split needed */
UINTAT(ub)=0; /* clear 9 BCD8s */ UBFROMUI(ub, 0); /* clear 9 BCD8s */
UINTAT(ub+4)=0; /* .. */ UBFROMUI(ub+4, 0); /* .. */
*(ub+8)=0; /* .. */ *(ub+8)=0; /* .. */
continue; continue;
} }
...@@ -558,11 +560,11 @@ static decFloat * decDivide(decFloat *result, const decFloat *dfl, ...@@ -558,11 +560,11 @@ static decFloat * decDivide(decFloat *result, const decFloat *dfl,
mid=rem/divsplit6; mid=rem/divsplit6;
rem=rem%divsplit6; rem=rem%divsplit6;
/* lay out the nine BCD digits (plus one unwanted byte) */ /* lay out the nine BCD digits (plus one unwanted byte) */
UINTAT(ub) =UINTAT(&BIN2BCD8[top*4]); UBFROMUI(ub, UBTOUI(&BIN2BCD8[top*4]));
UINTAT(ub+3)=UINTAT(&BIN2BCD8[mid*4]); UBFROMUI(ub+3, UBTOUI(&BIN2BCD8[mid*4]));
UINTAT(ub+6)=UINTAT(&BIN2BCD8[rem*4]); UBFROMUI(ub+6, UBTOUI(&BIN2BCD8[rem*4]));
} /* BCD conversion loop */ } /* BCD conversion loop */
ub--; /* -> lsu */ ub--; /* -> lsu */
/* complete the bcdnum; quodigits is correct, so the position of */ /* complete the bcdnum; quodigits is correct, so the position of */
/* the first non-zero is known */ /* the first non-zero is known */
...@@ -642,7 +644,7 @@ static decFloat * decDivide(decFloat *result, const decFloat *dfl, ...@@ -642,7 +644,7 @@ static decFloat * decDivide(decFloat *result, const decFloat *dfl,
num.msd--; /* use the 0 .. */ num.msd--; /* use the 0 .. */
num.lsd=num.msd; /* .. at the new MSD place */ num.lsd=num.msd; /* .. at the new MSD place */
} }
if (reround!=0) { /* discarding non-zero */ if (reround!=0) { /* discarding non-zero */
uInt bump=0; uInt bump=0;
/* rounding is DEC_ROUND_HALF_EVEN always */ /* rounding is DEC_ROUND_HALF_EVEN always */
if (reround>5) bump=1; /* >0.5 goes up */ if (reround>5) bump=1; /* >0.5 goes up */
...@@ -651,7 +653,7 @@ static decFloat * decDivide(decFloat *result, const decFloat *dfl, ...@@ -651,7 +653,7 @@ static decFloat * decDivide(decFloat *result, const decFloat *dfl,
if (bump!=0) { /* need increment */ if (bump!=0) { /* need increment */
/* increment the coefficient; this might end up with 1000... */ /* increment the coefficient; this might end up with 1000... */
ub=num.lsd; ub=num.lsd;
for (; UINTAT(ub-3)==0x09090909; ub-=4) UINTAT(ub-3)=0; for (; UBTOUI(ub-3)==0x09090909; ub-=4) UBFROMUI(ub-3, 0);
for (; *ub==9; ub--) *ub=0; /* at most 3 more */ for (; *ub==9; ub--) *ub=0; /* at most 3 more */
*ub+=1; *ub+=1;
if (ub<num.msd) num.msd--; /* carried */ if (ub<num.msd) num.msd--; /* carried */
...@@ -680,7 +682,7 @@ static decFloat * decDivide(decFloat *result, const decFloat *dfl, ...@@ -680,7 +682,7 @@ static decFloat * decDivide(decFloat *result, const decFloat *dfl,
/* */ /* */
/* num gets the result of multiplying dfl and dfr */ /* num gets the result of multiplying dfl and dfr */
/* bcdacc .. with the coefficient in this array */ /* bcdacc .. with the coefficient in this array */
/* dfl is the first decFloat (lhs) */ /* dfl is the first decFloat (lhs) */
/* dfr is the second decFloat (rhs) */ /* dfr is the second decFloat (rhs) */
/* */ /* */
/* This effects the multiplication of two decFloats, both known to be */ /* This effects the multiplication of two decFloats, both known to be */
...@@ -695,7 +697,7 @@ static decFloat * decDivide(decFloat *result, const decFloat *dfl, ...@@ -695,7 +697,7 @@ static decFloat * decDivide(decFloat *result, const decFloat *dfl,
/* variables (Ints and uInts) or smaller; the other uses uLongs (for */ /* variables (Ints and uInts) or smaller; the other uses uLongs (for */
/* multiplication and addition only). Both implementations cover */ /* multiplication and addition only). Both implementations cover */
/* both arithmetic sizes (DOUBLE and QUAD) in order to allow timing */ /* both arithmetic sizes (DOUBLE and QUAD) in order to allow timing */
/* comparisons. In any one compilation only one implementation for */ /* comparisons. In any one compilation only one implementation for */
/* each size can be used, and if DECUSE64 is 0 then use of the 32-bit */ /* each size can be used, and if DECUSE64 is 0 then use of the 32-bit */
/* version is forced. */ /* version is forced. */
/* */ /* */
...@@ -704,7 +706,7 @@ static decFloat * decDivide(decFloat *result, const decFloat *dfl, ...@@ -704,7 +706,7 @@ static decFloat * decDivide(decFloat *result, const decFloat *dfl,
/* during lazy carry splitting because the initial quotient estimate */ /* during lazy carry splitting because the initial quotient estimate */
/* (est) can exceed 32 bits. */ /* (est) can exceed 32 bits. */
#define MULTBASE BILLION /* the base used for multiply */ #define MULTBASE ((uInt)BILLION) /* the base used for multiply */
#define MULOPLEN DECPMAX9 /* operand length ('digits' base 10**9) */ #define MULOPLEN DECPMAX9 /* operand length ('digits' base 10**9) */
#define MULACCLEN (MULOPLEN*2) /* accumulator length (ditto) */ #define MULACCLEN (MULOPLEN*2) /* accumulator length (ditto) */
#define LEADZEROS (MULACCLEN*9 - DECPMAX*2) /* leading zeros always */ #define LEADZEROS (MULACCLEN*9 - DECPMAX*2) /* leading zeros always */
...@@ -723,11 +725,12 @@ static void decFiniteMultiply(bcdnum *num, uByte *bcdacc, ...@@ -723,11 +725,12 @@ static void decFiniteMultiply(bcdnum *num, uByte *bcdacc,
uInt bufl[MULOPLEN]; /* left coefficient (base-billion) */ uInt bufl[MULOPLEN]; /* left coefficient (base-billion) */
uInt bufr[MULOPLEN]; /* right coefficient (base-billion) */ uInt bufr[MULOPLEN]; /* right coefficient (base-billion) */
uInt *ui, *uj; /* work */ uInt *ui, *uj; /* work */
uByte *ub; /* .. */ uByte *ub; /* .. */
uInt uiwork; /* for macros */
#if DECUSE64 #if DECUSE64
uLong accl[MULACCLEN]; /* lazy accumulator (base-billion+) */ uLong accl[MULACCLEN]; /* lazy accumulator (base-billion+) */
uLong *pl; /* work -> lazy accumulator */ uLong *pl; /* work -> lazy accumulator */
uInt acc[MULACCLEN]; /* coefficent in base-billion .. */ uInt acc[MULACCLEN]; /* coefficent in base-billion .. */
#else #else
uInt acc[MULACCLEN*2]; /* accumulator in base-billion .. */ uInt acc[MULACCLEN*2]; /* accumulator in base-billion .. */
...@@ -760,7 +763,7 @@ static void decFiniteMultiply(bcdnum *num, uByte *bcdacc, ...@@ -760,7 +763,7 @@ static void decFiniteMultiply(bcdnum *num, uByte *bcdacc,
/* zero the accumulator */ /* zero the accumulator */
#if MULACCLEN==4 #if MULACCLEN==4
accl[0]=0; accl[1]=0; accl[2]=0; accl[3]=0; accl[0]=0; accl[1]=0; accl[2]=0; accl[3]=0;
#else /* use a loop */ #else /* use a loop */
/* MULACCLEN is a multiple of four, asserted above */ /* MULACCLEN is a multiple of four, asserted above */
for (pl=accl; pl<accl+MULACCLEN; pl+=4) { for (pl=accl; pl<accl+MULACCLEN; pl+=4) {
*pl=0; *(pl+1)=0; *(pl+2)=0; *(pl+3)=0;/* [reduce overhead] */ *pl=0; *(pl+1)=0; *(pl+2)=0; *(pl+3)=0;/* [reduce overhead] */
...@@ -812,8 +815,8 @@ static void decFiniteMultiply(bcdnum *num, uByte *bcdacc, ...@@ -812,8 +815,8 @@ static void decFiniteMultiply(bcdnum *num, uByte *bcdacc,
/* */ /* */
/* Type OPLEN A B maxX maxError maxCorrection */ /* Type OPLEN A B maxX maxError maxCorrection */
/* --------------------------------------------------------- */ /* --------------------------------------------------------- */
/* DOUBLE 2 29 32 <2*10**18 0.63 1 */ /* DOUBLE 2 29 32 <2*10**18 0.63 1 */
/* QUAD 4 30 31 <4*10**18 1.17 2 */ /* QUAD 4 30 31 <4*10**18 1.17 2 */
/* */ /* */
/* In the OPLEN==2 case there is most choice, but the value for B */ /* In the OPLEN==2 case there is most choice, but the value for B */
/* of 32 has a big advantage as then the calculation of the */ /* of 32 has a big advantage as then the calculation of the */
...@@ -840,7 +843,7 @@ static void decFiniteMultiply(bcdnum *num, uByte *bcdacc, ...@@ -840,7 +843,7 @@ static void decFiniteMultiply(bcdnum *num, uByte *bcdacc,
for (pl=accl, pa=acc; pl<accl+MULACCLEN; pl++, pa++) { /* each column position */ for (pl=accl, pa=acc; pl<accl+MULACCLEN; pl++, pa++) { /* each column position */
uInt lo, hop; /* work */ uInt lo, hop; /* work */
uInt est; /* cannot exceed 4E+9 */ uInt est; /* cannot exceed 4E+9 */
if (*pl>MULTBASE) { if (*pl>=MULTBASE) {
/* *pl holds a binary number which needs to be split */ /* *pl holds a binary number which needs to be split */
hop=(uInt)(*pl>>MULSHIFTA); hop=(uInt)(*pl>>MULSHIFTA);
est=(uInt)(((uLong)hop*MULMAGIC)>>MULSHIFTB); est=(uInt)(((uLong)hop*MULMAGIC)>>MULSHIFTB);
...@@ -905,7 +908,7 @@ static void decFiniteMultiply(bcdnum *num, uByte *bcdacc, ...@@ -905,7 +908,7 @@ static void decFiniteMultiply(bcdnum *num, uByte *bcdacc,
/* quotient/remainder has to be calculated for base-billion (1E+9). */ /* quotient/remainder has to be calculated for base-billion (1E+9). */
/* For this, Clark & Cowlishaw's quotient estimation approach (also */ /* For this, Clark & Cowlishaw's quotient estimation approach (also */
/* used in decNumber) is needed, because 64-bit divide is generally */ /* used in decNumber) is needed, because 64-bit divide is generally */
/* extremely slow on 32-bit machines. This algorithm splits X */ /* extremely slow on 32-bit machines. This algorithm splits X */
/* using: */ /* using: */
/* */ /* */
/* magic=2**(A+B)/1E+9; // 'magic number' */ /* magic=2**(A+B)/1E+9; // 'magic number' */
...@@ -927,8 +930,8 @@ static void decFiniteMultiply(bcdnum *num, uByte *bcdacc, ...@@ -927,8 +930,8 @@ static void decFiniteMultiply(bcdnum *num, uByte *bcdacc,
/* */ /* */
/* Type OPLEN A B maxX maxError maxCorrection */ /* Type OPLEN A B maxX maxError maxCorrection */
/* --------------------------------------------------------- */ /* --------------------------------------------------------- */
/* DOUBLE 2 29 32 <2*10**18 0.63 1 */ /* DOUBLE 2 29 32 <2*10**18 0.63 1 */
/* QUAD 4 30 31 <4*10**18 1.17 2 */ /* QUAD 4 30 31 <4*10**18 1.17 2 */
/* */ /* */
/* In the OPLEN==2 case there is most choice, but the value for B */ /* In the OPLEN==2 case there is most choice, but the value for B */
/* of 32 has a big advantage as then the calculation of the */ /* of 32 has a big advantage as then the calculation of the */
...@@ -952,15 +955,15 @@ static void decFiniteMultiply(bcdnum *num, uByte *bcdacc, ...@@ -952,15 +955,15 @@ static void decFiniteMultiply(bcdnum *num, uByte *bcdacc,
printf("\n"); printf("\n");
#endif #endif
for (pa=acc;; pa++) { /* each low uInt */ for (pa=acc;; pa++) { /* each low uInt */
uInt hi, lo; /* words of exact multiply result */ uInt hi, lo; /* words of exact multiply result */
uInt hop, estlo; /* work */ uInt hop, estlo; /* work */
#if QUAD #if QUAD
uInt esthi; /* .. */ uInt esthi; /* .. */
#endif #endif
lo=*pa; lo=*pa;
hi=*(pa+MULACCLEN); /* top 32 bits */ hi=*(pa+MULACCLEN); /* top 32 bits */
/* hi and lo now hold a binary number which needs to be split */ /* hi and lo now hold a binary number which needs to be split */
#if DOUBLE #if DOUBLE
...@@ -1032,7 +1035,7 @@ static void decFiniteMultiply(bcdnum *num, uByte *bcdacc, ...@@ -1032,7 +1035,7 @@ static void decFiniteMultiply(bcdnum *num, uByte *bcdacc,
uInt top, mid, rem; /* work */ uInt top, mid, rem; /* work */
/* *pa is non-zero -- split the base-billion acc digit into */ /* *pa is non-zero -- split the base-billion acc digit into */
/* hi, mid, and low three-digits */ /* hi, mid, and low three-digits */
#define mulsplit9 1000000 /* divisor */ #define mulsplit9 1000000 /* divisor */
#define mulsplit6 1000 /* divisor */ #define mulsplit6 1000 /* divisor */
/* The splitting is done by simple divides and remainders, */ /* The splitting is done by simple divides and remainders, */
/* assuming the compiler will optimize these where useful */ /* assuming the compiler will optimize these where useful */
...@@ -1042,13 +1045,13 @@ static void decFiniteMultiply(bcdnum *num, uByte *bcdacc, ...@@ -1042,13 +1045,13 @@ static void decFiniteMultiply(bcdnum *num, uByte *bcdacc,
mid=rem/mulsplit6; mid=rem/mulsplit6;
rem=rem%mulsplit6; rem=rem%mulsplit6;
/* lay out the nine BCD digits (plus one unwanted byte) */ /* lay out the nine BCD digits (plus one unwanted byte) */
UINTAT(ub) =UINTAT(&BIN2BCD8[top*4]); UBFROMUI(ub, UBTOUI(&BIN2BCD8[top*4]));
UINTAT(ub+3)=UINTAT(&BIN2BCD8[mid*4]); UBFROMUI(ub+3, UBTOUI(&BIN2BCD8[mid*4]));
UINTAT(ub+6)=UINTAT(&BIN2BCD8[rem*4]); UBFROMUI(ub+6, UBTOUI(&BIN2BCD8[rem*4]));
} }
else { /* *pa==0 */ else { /* *pa==0 */
UINTAT(ub)=0; /* clear 9 BCD8s */ UBFROMUI(ub, 0); /* clear 9 BCD8s */
UINTAT(ub+4)=0; /* .. */ UBFROMUI(ub+4, 0); /* .. */
*(ub+8)=0; /* .. */ *(ub+8)=0; /* .. */
} }
if (pa==acc) break; if (pa==acc) break;
...@@ -1068,7 +1071,7 @@ static void decFiniteMultiply(bcdnum *num, uByte *bcdacc, ...@@ -1068,7 +1071,7 @@ static void decFiniteMultiply(bcdnum *num, uByte *bcdacc,
/* decFloatAbs -- absolute value, heeding NaNs, etc. */ /* decFloatAbs -- absolute value, heeding NaNs, etc. */
/* */ /* */
/* result gets the canonicalized df with sign 0 */ /* result gets the canonicalized df with sign 0 */
/* df is the decFloat to abs */ /* df is the decFloat to abs */
/* set is the context */ /* set is the context */
/* returns result */ /* returns result */
/* */ /* */
...@@ -1090,26 +1093,45 @@ decFloat * decFloatAbs(decFloat *result, const decFloat *df, ...@@ -1090,26 +1093,45 @@ decFloat * decFloatAbs(decFloat *result, const decFloat *df,
/* decFloatAdd -- add two decFloats */ /* decFloatAdd -- add two decFloats */
/* */ /* */
/* result gets the result of adding dfl and dfr: */ /* result gets the result of adding dfl and dfr: */
/* dfl is the first decFloat (lhs) */ /* dfl is the first decFloat (lhs) */
/* dfr is the second decFloat (rhs) */ /* dfr is the second decFloat (rhs) */
/* set is the context */ /* set is the context */
/* returns result */ /* returns result */
/* */ /* */
/* ------------------------------------------------------------------ */ /* ------------------------------------------------------------------ */
#if QUAD
/* Table for testing MSDs for fastpath elimination; returns the MSD of */
/* a decDouble or decQuad (top 6 bits tested) ignoring the sign. */
/* Infinities return -32 and NaNs return -128 so that summing the two */
/* MSDs also allows rapid tests for the Specials (see code below). */
const Int DECTESTMSD[64]={
0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7,
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 8, 9, 8, 9, -32, -128,
0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7,
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 8, 9, 8, 9, -32, -128};
#else
/* The table for testing MSDs is shared between the modules */
extern const Int DECTESTMSD[64];
#endif
decFloat * decFloatAdd(decFloat *result, decFloat * decFloatAdd(decFloat *result,
const decFloat *dfl, const decFloat *dfr, const decFloat *dfl, const decFloat *dfr,
decContext *set) { decContext *set) {
bcdnum num; /* for final conversion */ bcdnum num; /* for final conversion */
Int expl, expr; /* left and right exponents */ Int bexpl, bexpr; /* left and right biased exponents */
uInt *ui, *uj; /* work */ uByte *ub, *us, *ut; /* work */
uByte *ub; /* .. */ uInt uiwork; /* for macros */
#if QUAD
uShort uswork; /* .. */
#endif
uInt sourhil, sourhir; /* top words from source decFloats */ uInt sourhil, sourhir; /* top words from source decFloats */
/* [valid only until specials */ /* [valid only through end of */
/* handled or exponents decoded] */ /* fastpath code -- before swap] */
uInt diffsign; /* non-zero if signs differ */ uInt diffsign; /* non-zero if signs differ */
uInt carry; /* carry: 0 or 1 before add loop */ uInt carry; /* carry: 0 or 1 before add loop */
Int overlap; /* coefficient overlap (if full) */ Int overlap; /* coefficient overlap (if full) */
Int summ; /* sum of the MSDs */
/* the following buffers hold coefficients with various alignments */ /* the following buffers hold coefficients with various alignments */
/* (see commentary and diagrams below) */ /* (see commentary and diagrams below) */
uByte acc[4+2+DECPMAX*3+8]; uByte acc[4+2+DECPMAX*3+8];
...@@ -1117,48 +1139,116 @@ decFloat * decFloatAdd(decFloat *result, ...@@ -1117,48 +1139,116 @@ decFloat * decFloatAdd(decFloat *result,
uByte *umsd, *ulsd; /* local MSD and LSD pointers */ uByte *umsd, *ulsd; /* local MSD and LSD pointers */
#if DECLITEND #if DECLITEND
#define CARRYPAT 0x01000000 /* carry=1 pattern */ #define CARRYPAT 0x01000000 /* carry=1 pattern */
#else #else
#define CARRYPAT 0x00000001 /* carry=1 pattern */ #define CARRYPAT 0x00000001 /* carry=1 pattern */
#endif #endif
/* Start decoding the arguments */ /* Start decoding the arguments */
/* the initial exponents are placed into the opposite Ints to */ /* The initial exponents are placed into the opposite Ints to */
/* that which might be expected; there are two sets of data to */ /* that which might be expected; there are two sets of data to */
/* keep track of (each decFloat and the corresponding exponent), */ /* keep track of (each decFloat and the corresponding exponent), */
/* and this scheme means that at the swap point (after comparing */ /* and this scheme means that at the swap point (after comparing */
/* exponents) only one pair of words needs to be swapped */ /* exponents) only one pair of words needs to be swapped */
/* whichever path is taken (thereby minimising worst-case path) */ /* whichever path is taken (thereby minimising worst-case path). */
/* The calculated exponents will be nonsense when the arguments are */
/* Special, but are not used in that path */
sourhil=DFWORD(dfl, 0); /* LHS top word */ sourhil=DFWORD(dfl, 0); /* LHS top word */
expr=DECCOMBEXP[sourhil>>26]; /* get exponent high bits (in place) */ summ=DECTESTMSD[sourhil>>26]; /* get first MSD for testing */
bexpr=DECCOMBEXP[sourhil>>26]; /* get exponent high bits (in place) */
bexpr+=GETECON(dfl); /* .. + continuation */
sourhir=DFWORD(dfr, 0); /* RHS top word */ sourhir=DFWORD(dfr, 0); /* RHS top word */
expl=DECCOMBEXP[sourhir>>26]; summ+=DECTESTMSD[sourhir>>26]; /* sum MSDs for testing */
bexpl=DECCOMBEXP[sourhir>>26];
bexpl+=GETECON(dfr);
/* here bexpr has biased exponent from lhs, and vice versa */
diffsign=(sourhil^sourhir)&DECFLOAT_Sign; diffsign=(sourhil^sourhir)&DECFLOAT_Sign;
if (EXPISSPECIAL(expl | expr)) { /* either is special? */ /* now determine whether to take a fast path or the full-function */
if (DFISNAN(dfl) || DFISNAN(dfr)) return decNaNs(result, dfl, dfr, set); /* slow path. The slow path must be taken when: */
/* one or two infinities */ /* -- both numbers are finite, and: */
/* two infinities with different signs is invalid */ /* the exponents are different, or */
if (diffsign && DFISINF(dfl) && DFISINF(dfr)) /* the signs are different, or */
return decInvalid(result, set); /* the sum of the MSDs is >8 (hence might overflow) */
if (DFISINF(dfl)) return decInfinity(result, dfl); /* LHS is infinite */ /* specialness and the sum of the MSDs can be tested at once using */
return decInfinity(result, dfr); /* RHS must be Infinite */ /* the summ value just calculated, so the test for specials is no */
} /* longer on the worst-case path (as of 3.60) */
if (summ<=8) { /* MSD+MSD is good, or there is a special */
if (summ<0) { /* there is a special */
/* Inf+Inf would give -64; Inf+finite is -32 or higher */
if (summ<-64) return decNaNs(result, dfl, dfr, set); /* one or two NaNs */
/* two infinities with different signs is invalid */
if (summ==-64 && diffsign) return decInvalid(result, set);
if (DFISINF(dfl)) return decInfinity(result, dfl); /* LHS is infinite */
return decInfinity(result, dfr); /* RHS must be Inf */
}
/* Here when both arguments are finite; fast path is possible */
/* (currently only for aligned and same-sign) */
if (bexpr==bexpl && !diffsign) {
uInt tac[DECLETS+1]; /* base-1000 coefficient */
uInt encode; /* work */
/* Get one coefficient as base-1000 and add the other */
GETCOEFFTHOU(dfl, tac); /* least-significant goes to [0] */
ADDCOEFFTHOU(dfr, tac);
/* here the sum of the MSDs (plus any carry) will be <10 due to */
/* the fastpath test earlier */
/* construct the result; low word is the same for both formats */
encode =BIN2DPD[tac[0]];
encode|=BIN2DPD[tac[1]]<<10;
encode|=BIN2DPD[tac[2]]<<20;
encode|=BIN2DPD[tac[3]]<<30;
DFWORD(result, (DECBYTES/4)-1)=encode;
/* collect next two declets (all that remains, for Double) */
encode =BIN2DPD[tac[3]]>>2;
encode|=BIN2DPD[tac[4]]<<8;
/* Here when both arguments are finite */ #if QUAD
/* complete and lay out middling words */
encode|=BIN2DPD[tac[5]]<<18;
encode|=BIN2DPD[tac[6]]<<28;
DFWORD(result, 2)=encode;
encode =BIN2DPD[tac[6]]>>4;
encode|=BIN2DPD[tac[7]]<<6;
encode|=BIN2DPD[tac[8]]<<16;
encode|=BIN2DPD[tac[9]]<<26;
DFWORD(result, 1)=encode;
/* and final two declets */
encode =BIN2DPD[tac[9]]>>6;
encode|=BIN2DPD[tac[10]]<<4;
#endif
/* complete exponent gathering (keeping swapped) */ /* add exponent continuation and sign (from either argument) */
expr+=GETECON(dfl)-DECBIAS; /* .. + continuation and unbias */ encode|=sourhil & (ECONMASK | DECFLOAT_Sign);
expl+=GETECON(dfr)-DECBIAS;
/* here expr has exponent from lhs, and vice versa */ /* create lookup index = MSD + top two bits of biased exponent <<4 */
tac[DECLETS]|=(bexpl>>DECECONL)<<4;
encode|=DECCOMBFROM[tac[DECLETS]]; /* add constructed combination field */
DFWORD(result, 0)=encode; /* complete */
/* decFloatShow(result, ">"); */
return result;
} /* fast path OK */
/* drop through to slow path */
} /* low sum or Special(s) */
/* Slow path required -- arguments are finite and might overflow, */
/* or require alignment, or might have different signs */
/* now swap either exponents or argument pointers */ /* now swap either exponents or argument pointers */
if (expl<=expr) { if (bexpl<=bexpr) {
/* original left is bigger */ /* original left is bigger */
Int expswap=expl; Int bexpswap=bexpl;
expl=expr; bexpl=bexpr;
expr=expswap; bexpr=bexpswap;
/* printf("left bigger\n"); */ /* printf("left bigger\n"); */
} }
else { else {
...@@ -1167,7 +1257,7 @@ decFloat * decFloatAdd(decFloat *result, ...@@ -1167,7 +1257,7 @@ decFloat * decFloatAdd(decFloat *result,
dfr=dfswap; dfr=dfswap;
/* printf("right bigger\n"); */ /* printf("right bigger\n"); */
} }
/* [here dfl and expl refer to the datum with the larger exponent, */ /* [here dfl and bexpl refer to the datum with the larger exponent, */
/* of if the exponents are equal then the original LHS argument] */ /* of if the exponents are equal then the original LHS argument] */
/* if lhs is zero then result will be the rhs (now known to have */ /* if lhs is zero then result will be the rhs (now known to have */
...@@ -1209,19 +1299,19 @@ decFloat * decFloatAdd(decFloat *result, ...@@ -1209,19 +1299,19 @@ decFloat * decFloatAdd(decFloat *result,
#if DOUBLE #if DOUBLE
#define COFF 4 /* offset into acc */ #define COFF 4 /* offset into acc */
#elif QUAD #elif QUAD
USHORTAT(acc+4)=0; /* prefix 00 */ UBFROMUS(acc+4, 0); /* prefix 00 */
#define COFF 6 /* offset into acc */ #define COFF 6 /* offset into acc */
#endif #endif
GETCOEFF(dfl, acc+COFF); /* decode from decFloat */ GETCOEFF(dfl, acc+COFF); /* decode from decFloat */
ulsd=acc+COFF+DECPMAX-1; ulsd=acc+COFF+DECPMAX-1;
umsd=acc+4; /* [having this here avoids */ umsd=acc+4; /* [having this here avoids */
/* weird GCC optimizer failure] */
#if DECTRACE #if DECTRACE
{bcdnum tum; {bcdnum tum;
tum.msd=umsd; tum.msd=umsd;
tum.lsd=ulsd; tum.lsd=ulsd;
tum.exponent=expl; tum.exponent=bexpl-DECBIAS;
tum.sign=DFWORD(dfl, 0) & DECFLOAT_Sign; tum.sign=DFWORD(dfl, 0) & DECFLOAT_Sign;
decShowNum(&tum, "dflx");} decShowNum(&tum, "dflx");}
#endif #endif
...@@ -1235,16 +1325,16 @@ decFloat * decFloatAdd(decFloat *result, ...@@ -1235,16 +1325,16 @@ decFloat * decFloatAdd(decFloat *result,
carry=0; /* assume no carry */ carry=0; /* assume no carry */
if (diffsign) { if (diffsign) {
carry=CARRYPAT; /* for +1 during add */ carry=CARRYPAT; /* for +1 during add */
UINTAT(acc+ 4)=0x09090909-UINTAT(acc+ 4); UBFROMUI(acc+ 4, 0x09090909-UBTOUI(acc+ 4));
UINTAT(acc+ 8)=0x09090909-UINTAT(acc+ 8); UBFROMUI(acc+ 8, 0x09090909-UBTOUI(acc+ 8));
UINTAT(acc+12)=0x09090909-UINTAT(acc+12); UBFROMUI(acc+12, 0x09090909-UBTOUI(acc+12));
UINTAT(acc+16)=0x09090909-UINTAT(acc+16); UBFROMUI(acc+16, 0x09090909-UBTOUI(acc+16));
#if QUAD #if QUAD
UINTAT(acc+20)=0x09090909-UINTAT(acc+20); UBFROMUI(acc+20, 0x09090909-UBTOUI(acc+20));
UINTAT(acc+24)=0x09090909-UINTAT(acc+24); UBFROMUI(acc+24, 0x09090909-UBTOUI(acc+24));
UINTAT(acc+28)=0x09090909-UINTAT(acc+28); UBFROMUI(acc+28, 0x09090909-UBTOUI(acc+28));
UINTAT(acc+32)=0x09090909-UINTAT(acc+32); UBFROMUI(acc+32, 0x09090909-UBTOUI(acc+32));
UINTAT(acc+36)=0x09090909-UINTAT(acc+36); UBFROMUI(acc+36, 0x09090909-UBTOUI(acc+36));
#endif #endif
} /* diffsign */ } /* diffsign */
...@@ -1252,9 +1342,9 @@ decFloat * decFloatAdd(decFloat *result, ...@@ -1252,9 +1342,9 @@ decFloat * decFloatAdd(decFloat *result,
/* it can be put straight into acc (with an appropriate gap, if */ /* it can be put straight into acc (with an appropriate gap, if */
/* needed) because no actual addition will be needed (except */ /* needed) because no actual addition will be needed (except */
/* possibly to complete ten's complement) */ /* possibly to complete ten's complement) */
overlap=DECPMAX-(expl-expr); overlap=DECPMAX-(bexpl-bexpr);
#if DECTRACE #if DECTRACE
printf("exps: %ld %ld\n", (LI)expl, (LI)expr); printf("exps: %ld %ld\n", (LI)(bexpl-DECBIAS), (LI)(bexpr-DECBIAS));
printf("Overlap=%ld carry=%08lx\n", (LI)overlap, (LI)carry); printf("Overlap=%ld carry=%08lx\n", (LI)overlap, (LI)carry);
#endif #endif
...@@ -1274,13 +1364,13 @@ decFloat * decFloatAdd(decFloat *result, ...@@ -1274,13 +1364,13 @@ decFloat * decFloatAdd(decFloat *result,
/* safe because the lhs is non-zero]. */ /* safe because the lhs is non-zero]. */
gap=-overlap; gap=-overlap;
if (gap>DECPMAX) { if (gap>DECPMAX) {
expr+=gap-1; bexpr+=gap-1;
gap=DECPMAX; gap=DECPMAX;
} }
ub=ulsd+gap+1; /* where MSD will go */ ub=ulsd+gap+1; /* where MSD will go */
/* Fill the gap with 0s; note that there is no addition to do */ /* Fill the gap with 0s; note that there is no addition to do */
ui=&UINTAT(acc+COFF+DECPMAX); /* start of gap */ ut=acc+COFF+DECPMAX; /* start of gap */
for (; ui<&UINTAT(ub); ui++) *ui=0; /* mind the gap */ for (; ut<ub; ut+=4) UBFROMUI(ut, 0); /* mind the gap */
if (overlap<-DECPMAX) { /* gap was > DECPMAX */ if (overlap<-DECPMAX) { /* gap was > DECPMAX */
*ub=(uByte)(!DFISZERO(dfr)); /* make sticky digit */ *ub=(uByte)(!DFISZERO(dfr)); /* make sticky digit */
} }
...@@ -1294,63 +1384,74 @@ decFloat * decFloatAdd(decFloat *result, ...@@ -1294,63 +1384,74 @@ decFloat * decFloatAdd(decFloat *result,
else { /* overlap>0 */ else { /* overlap>0 */
/* coefficients overlap (perhaps completely, although also */ /* coefficients overlap (perhaps completely, although also */
/* perhaps only where zeros) */ /* perhaps only where zeros) */
ub=buf+COFF+DECPMAX-overlap; /* where MSD will go */ if (overlap==DECPMAX) { /* aligned */
/* Fill the prefix gap with 0s; 8 will cover most common */ ub=buf+COFF; /* where msd will go */
/* unalignments, so start with direct assignments (a loop is */ #if QUAD
/* then used for any remaining -- the loop (and the one in a */ UBFROMUS(buf+4, 0); /* clear quad's 00 */
/* moment) is not then on the critical path because the number */ #endif
/* of additions is reduced by (at least) two in this case) */ GETCOEFF(dfr, ub); /* decode from decFloat */
UINTAT(buf+4)=0; /* [clears decQuad 00 too] */
UINTAT(buf+8)=0;
if (ub>buf+12) {
ui=&UINTAT(buf+12); /* start of any remaining */
for (; ui<&UINTAT(ub); ui++) *ui=0; /* fill them */
}
GETCOEFF(dfr, ub); /* decode from decFloat */
/* now move tail of rhs across to main acc; again use direct */
/* assignment for 8 digits-worth */
UINTAT(acc+COFF+DECPMAX)=UINTAT(buf+COFF+DECPMAX);
UINTAT(acc+COFF+DECPMAX+4)=UINTAT(buf+COFF+DECPMAX+4);
if (buf+COFF+DECPMAX+8<ub+DECPMAX) {
uj=&UINTAT(buf+COFF+DECPMAX+8); /* source */
ui=&UINTAT(acc+COFF+DECPMAX+8); /* target */
for (; uj<&UINTAT(ub+DECPMAX); ui++, uj++) *ui=*uj;
} }
else { /* unaligned */
ub=buf+COFF+DECPMAX-overlap; /* where MSD will go */
/* Fill the prefix gap with 0s; 8 will cover most common */
/* unalignments, so start with direct assignments (a loop is */
/* then used for any remaining -- the loop (and the one in a */
/* moment) is not then on the critical path because the number */
/* of additions is reduced by (at least) two in this case) */
UBFROMUI(buf+4, 0); /* [clears decQuad 00 too] */
UBFROMUI(buf+8, 0);
if (ub>buf+12) {
ut=buf+12; /* start any remaining */
for (; ut<ub; ut+=4) UBFROMUI(ut, 0); /* fill them */
}
GETCOEFF(dfr, ub); /* decode from decFloat */
/* now move tail of rhs across to main acc; again use direct */
/* copies for 8 digits-worth */
UBFROMUI(acc+COFF+DECPMAX, UBTOUI(buf+COFF+DECPMAX));
UBFROMUI(acc+COFF+DECPMAX+4, UBTOUI(buf+COFF+DECPMAX+4));
if (buf+COFF+DECPMAX+8<ub+DECPMAX) {
us=buf+COFF+DECPMAX+8; /* source */
ut=acc+COFF+DECPMAX+8; /* target */
for (; us<ub+DECPMAX; us+=4, ut+=4) UBFROMUI(ut, UBTOUI(us));
}
} /* unaligned */
ulsd=acc+(ub-buf+DECPMAX-1); /* update LSD pointer */ ulsd=acc+(ub-buf+DECPMAX-1); /* update LSD pointer */
/* now do the add of the non-tail; this is all nicely aligned, */ /* Now do the add of the non-tail; this is all nicely aligned, */
/* and is over a multiple of four digits (because for Quad two */ /* and is over a multiple of four digits (because for Quad two */
/* two 0 digits were added on the left); words in both acc and */ /* zero digits were added on the left); words in both acc and */
/* buf (buf especially) will often be zero */ /* buf (buf especially) will often be zero */
/* [byte-by-byte add, here, is about 15% slower than the by-fours] */ /* [byte-by-byte add, here, is about 15% slower total effect than */
/* the by-fours] */
/* Now effect the add; this is harder on a little-endian */ /* Now effect the add; this is harder on a little-endian */
/* machine as the inter-digit carry cannot use the usual BCD */ /* machine as the inter-digit carry cannot use the usual BCD */
/* addition trick because the bytes are loaded in the wrong order */ /* addition trick because the bytes are loaded in the wrong order */
/* [this loop could be unrolled, but probably scarcely worth it] */ /* [this loop could be unrolled, but probably scarcely worth it] */
ui=&UINTAT(acc+COFF+DECPMAX-4); /* target LSW (acc) */ ut=acc+COFF+DECPMAX-4; /* target LSW (acc) */
uj=&UINTAT(buf+COFF+DECPMAX-4); /* source LSW (buf, to add to acc) */ us=buf+COFF+DECPMAX-4; /* source LSW (buf, to add to acc) */
#if !DECLITEND #if !DECLITEND
for (; ui>=&UINTAT(acc+4); ui--, uj--) { for (; ut>=acc+4; ut-=4, us-=4) { /* big-endian add loop */
/* bcd8 add */ /* bcd8 add */
carry+=*uj; /* rhs + carry */ carry+=UBTOUI(us); /* rhs + carry */
if (carry==0) continue; /* no-op */ if (carry==0) continue; /* no-op */
carry+=*ui; /* lhs */ carry+=UBTOUI(ut); /* lhs */
/* Big-endian BCD adjust (uses internal carry) */ /* Big-endian BCD adjust (uses internal carry) */
carry+=0x76f6f6f6; /* note top nibble not all bits */ carry+=0x76f6f6f6; /* note top nibble not all bits */
*ui=(carry & 0x0f0f0f0f) - ((carry & 0x60606060)>>4); /* BCD adjust */ /* apply BCD adjust and save */
UBFROMUI(ut, (carry & 0x0f0f0f0f) - ((carry & 0x60606060)>>4));
carry>>=31; /* true carry was at far left */ carry>>=31; /* true carry was at far left */
} /* add loop */ } /* add loop */
#else #else
for (; ui>=&UINTAT(acc+4); ui--, uj--) { for (; ut>=acc+4; ut-=4, us-=4) { /* little-endian add loop */
/* bcd8 add */ /* bcd8 add */
carry+=*uj; /* rhs + carry */ carry+=UBTOUI(us); /* rhs + carry */
if (carry==0) continue; /* no-op [common if unaligned] */ if (carry==0) continue; /* no-op [common if unaligned] */
carry+=*ui; /* lhs */ carry+=UBTOUI(ut); /* lhs */
/* Little-endian BCD adjust; inter-digit carry must be manual */ /* Little-endian BCD adjust; inter-digit carry must be manual */
/* because the lsb from the array will be in the most-significant */ /* because the lsb from the array will be in the most-significant */
/* byte of carry */ /* byte of carry */
...@@ -1359,12 +1460,13 @@ decFloat * decFloatAdd(decFloat *result, ...@@ -1359,12 +1460,13 @@ decFloat * decFloatAdd(decFloat *result,
carry+=(carry & 0x00800000)>>15; carry+=(carry & 0x00800000)>>15;
carry+=(carry & 0x00008000)>>15; carry+=(carry & 0x00008000)>>15;
carry-=(carry & 0x60606060)>>4; /* BCD adjust back */ carry-=(carry & 0x60606060)>>4; /* BCD adjust back */
*ui=carry & 0x0f0f0f0f; /* clear debris and save */ UBFROMUI(ut, carry & 0x0f0f0f0f); /* clear debris and save */
/* here, final carry-out bit is at 0x00000080; move it ready */ /* here, final carry-out bit is at 0x00000080; move it ready */
/* for next word-add (i.e., to 0x01000000) */ /* for next word-add (i.e., to 0x01000000) */
carry=(carry & 0x00000080)<<17; carry=(carry & 0x00000080)<<17;
} /* add loop */ } /* add loop */
#endif #endif
#if DECTRACE #if DECTRACE
{bcdnum tum; {bcdnum tum;
printf("Add done, carry=%08lx, diffsign=%ld\n", (LI)carry, (LI)diffsign); printf("Add done, carry=%08lx, diffsign=%ld\n", (LI)carry, (LI)diffsign);
...@@ -1392,36 +1494,36 @@ decFloat * decFloatAdd(decFloat *result, ...@@ -1392,36 +1494,36 @@ decFloat * decFloatAdd(decFloat *result,
*(ulsd+1)=0; *(ulsd+1)=0;
#endif #endif
/* there are always at least four coefficient words */ /* there are always at least four coefficient words */
UINTAT(umsd) =0x09090909-UINTAT(umsd); UBFROMUI(umsd, 0x09090909-UBTOUI(umsd));
UINTAT(umsd+4) =0x09090909-UINTAT(umsd+4); UBFROMUI(umsd+4, 0x09090909-UBTOUI(umsd+4));
UINTAT(umsd+8) =0x09090909-UINTAT(umsd+8); UBFROMUI(umsd+8, 0x09090909-UBTOUI(umsd+8));
UINTAT(umsd+12)=0x09090909-UINTAT(umsd+12); UBFROMUI(umsd+12, 0x09090909-UBTOUI(umsd+12));
#if DOUBLE #if DOUBLE
#define BNEXT 16 #define BNEXT 16
#elif QUAD #elif QUAD
UINTAT(umsd+16)=0x09090909-UINTAT(umsd+16); UBFROMUI(umsd+16, 0x09090909-UBTOUI(umsd+16));
UINTAT(umsd+20)=0x09090909-UINTAT(umsd+20); UBFROMUI(umsd+20, 0x09090909-UBTOUI(umsd+20));
UINTAT(umsd+24)=0x09090909-UINTAT(umsd+24); UBFROMUI(umsd+24, 0x09090909-UBTOUI(umsd+24));
UINTAT(umsd+28)=0x09090909-UINTAT(umsd+28); UBFROMUI(umsd+28, 0x09090909-UBTOUI(umsd+28));
UINTAT(umsd+32)=0x09090909-UINTAT(umsd+32); UBFROMUI(umsd+32, 0x09090909-UBTOUI(umsd+32));
#define BNEXT 36 #define BNEXT 36
#endif #endif
if (ulsd>=umsd+BNEXT) { /* unaligned */ if (ulsd>=umsd+BNEXT) { /* unaligned */
/* eight will handle most unaligments for Double; 16 for Quad */ /* eight will handle most unaligments for Double; 16 for Quad */
UINTAT(umsd+BNEXT)=0x09090909-UINTAT(umsd+BNEXT); UBFROMUI(umsd+BNEXT, 0x09090909-UBTOUI(umsd+BNEXT));
UINTAT(umsd+BNEXT+4)=0x09090909-UINTAT(umsd+BNEXT+4); UBFROMUI(umsd+BNEXT+4, 0x09090909-UBTOUI(umsd+BNEXT+4));
#if DOUBLE #if DOUBLE
#define BNEXTY (BNEXT+8) #define BNEXTY (BNEXT+8)
#elif QUAD #elif QUAD
UINTAT(umsd+BNEXT+8)=0x09090909-UINTAT(umsd+BNEXT+8); UBFROMUI(umsd+BNEXT+8, 0x09090909-UBTOUI(umsd+BNEXT+8));
UINTAT(umsd+BNEXT+12)=0x09090909-UINTAT(umsd+BNEXT+12); UBFROMUI(umsd+BNEXT+12, 0x09090909-UBTOUI(umsd+BNEXT+12));
#define BNEXTY (BNEXT+16) #define BNEXTY (BNEXT+16)
#endif #endif
if (ulsd>=umsd+BNEXTY) { /* very unaligned */ if (ulsd>=umsd+BNEXTY) { /* very unaligned */
ui=&UINTAT(umsd+BNEXTY); /* -> continue */ ut=umsd+BNEXTY; /* -> continue */
for (;;ui++) { for (;;ut+=4) {
*ui=0x09090909-*ui; /* invert four digits */ UBFROMUI(ut, 0x09090909-UBTOUI(ut)); /* invert four digits */
if (ui>=&UINTAT(ulsd-3)) break; /* all done */ if (ut>=ulsd-3) break; /* all done */
} }
} }
} }
...@@ -1446,10 +1548,10 @@ decFloat * decFloatAdd(decFloat *result, ...@@ -1446,10 +1548,10 @@ decFloat * decFloatAdd(decFloat *result,
umsd=acc+COFF+DECPMAX-1; /* so far, so zero */ umsd=acc+COFF+DECPMAX-1; /* so far, so zero */
if (ulsd>umsd) { /* more to check */ if (ulsd>umsd) { /* more to check */
umsd++; /* to align after checked area */ umsd++; /* to align after checked area */
for (; UINTAT(umsd)==0 && umsd+3<ulsd;) umsd+=4; for (; UBTOUI(umsd)==0 && umsd+3<ulsd;) umsd+=4;
for (; *umsd==0 && umsd<ulsd;) umsd++; for (; *umsd==0 && umsd<ulsd;) umsd++;
} }
if (*umsd==0) { /* must be true zero (and diffsign) */ if (*umsd==0) { /* must be true zero (and diffsign) */
num.sign=0; /* assume + */ num.sign=0; /* assume + */
if (set->round==DEC_ROUND_FLOOR) num.sign=DECFLOAT_Sign; if (set->round==DEC_ROUND_FLOOR) num.sign=DECFLOAT_Sign;
} }
...@@ -1468,9 +1570,9 @@ decFloat * decFloatAdd(decFloat *result, ...@@ -1468,9 +1570,9 @@ decFloat * decFloatAdd(decFloat *result,
#endif #endif
} /* same sign */ } /* same sign */
num.msd=umsd; /* set MSD .. */ num.msd=umsd; /* set MSD .. */
num.lsd=ulsd; /* .. and LSD */ num.lsd=ulsd; /* .. and LSD */
num.exponent=expr; /* set exponent to smaller */ num.exponent=bexpr-DECBIAS; /* set exponent to smaller, unbiassed */
#if DECTRACE #if DECTRACE
decFloatShow(dfl, "dfl"); decFloatShow(dfl, "dfl");
...@@ -1484,12 +1586,12 @@ decFloat * decFloatAdd(decFloat *result, ...@@ -1484,12 +1586,12 @@ decFloat * decFloatAdd(decFloat *result,
/* decFloatAnd -- logical digitwise AND of two decFloats */ /* decFloatAnd -- logical digitwise AND of two decFloats */
/* */ /* */
/* result gets the result of ANDing dfl and dfr */ /* result gets the result of ANDing dfl and dfr */
/* dfl is the first decFloat (lhs) */ /* dfl is the first decFloat (lhs) */
/* dfr is the second decFloat (rhs) */ /* dfr is the second decFloat (rhs) */
/* set is the context */ /* set is the context */
/* returns result, which will be canonical with sign=0 */ /* returns result, which will be canonical with sign=0 */
/* */ /* */
/* The operands must be positive, finite with exponent q=0, and */ /* The operands must be positive, finite with exponent q=0, and */
/* comprise just zeros and ones; if not, Invalid operation results. */ /* comprise just zeros and ones; if not, Invalid operation results. */
/* ------------------------------------------------------------------ */ /* ------------------------------------------------------------------ */
decFloat * decFloatAnd(decFloat *result, decFloat * decFloatAnd(decFloat *result,
...@@ -1516,7 +1618,7 @@ decFloat * decFloatAnd(decFloat *result, ...@@ -1516,7 +1618,7 @@ decFloat * decFloatAnd(decFloat *result,
/* decFloatCanonical -- copy a decFloat, making canonical */ /* decFloatCanonical -- copy a decFloat, making canonical */
/* */ /* */
/* result gets the canonicalized df */ /* result gets the canonicalized df */
/* df is the decFloat to copy and make canonical */ /* df is the decFloat to copy and make canonical */
/* returns result */ /* returns result */
/* */ /* */
/* This works on specials, too; no error or exception is possible. */ /* This works on specials, too; no error or exception is possible. */
...@@ -1528,7 +1630,7 @@ decFloat * decFloatCanonical(decFloat *result, const decFloat *df) { ...@@ -1528,7 +1630,7 @@ decFloat * decFloatCanonical(decFloat *result, const decFloat *df) {
/* ------------------------------------------------------------------ */ /* ------------------------------------------------------------------ */
/* decFloatClass -- return the class of a decFloat */ /* decFloatClass -- return the class of a decFloat */
/* */ /* */
/* df is the decFloat to test */ /* df is the decFloat to test */
/* returns the decClass that df falls into */ /* returns the decClass that df falls into */
/* ------------------------------------------------------------------ */ /* ------------------------------------------------------------------ */
enum decClass decFloatClass(const decFloat *df) { enum decClass decFloatClass(const decFloat *df) {
...@@ -1560,7 +1662,7 @@ enum decClass decFloatClass(const decFloat *df) { ...@@ -1560,7 +1662,7 @@ enum decClass decFloatClass(const decFloat *df) {
/* ------------------------------------------------------------------ */ /* ------------------------------------------------------------------ */
/* decFloatClassString -- return the class of a decFloat as a string */ /* decFloatClassString -- return the class of a decFloat as a string */
/* */ /* */
/* df is the decFloat to test */ /* df is the decFloat to test */
/* returns a constant string describing the class df falls into */ /* returns a constant string describing the class df falls into */
/* ------------------------------------------------------------------ */ /* ------------------------------------------------------------------ */
const char *decFloatClassString(const decFloat *df) { const char *decFloatClassString(const decFloat *df) {
...@@ -1579,10 +1681,10 @@ const char *decFloatClassString(const decFloat *df) { ...@@ -1579,10 +1681,10 @@ const char *decFloatClassString(const decFloat *df) {
} /* decFloatClassString */ } /* decFloatClassString */
/* ------------------------------------------------------------------ */ /* ------------------------------------------------------------------ */
/* decFloatCompare -- compare two decFloats; quiet NaNs allowed */ /* decFloatCompare -- compare two decFloats; quiet NaNs allowed */
/* */ /* */
/* result gets the result of comparing dfl and dfr */ /* result gets the result of comparing dfl and dfr */
/* dfl is the first decFloat (lhs) */ /* dfl is the first decFloat (lhs) */
/* dfr is the second decFloat (rhs) */ /* dfr is the second decFloat (rhs) */
/* set is the context */ /* set is the context */
/* returns result, which may be -1, 0, 1, or NaN (Unordered) */ /* returns result, which may be -1, 0, 1, or NaN (Unordered) */
...@@ -1606,7 +1708,7 @@ decFloat * decFloatCompare(decFloat *result, ...@@ -1606,7 +1708,7 @@ decFloat * decFloatCompare(decFloat *result,
/* decFloatCompareSignal -- compare two decFloats; all NaNs signal */ /* decFloatCompareSignal -- compare two decFloats; all NaNs signal */
/* */ /* */
/* result gets the result of comparing dfl and dfr */ /* result gets the result of comparing dfl and dfr */
/* dfl is the first decFloat (lhs) */ /* dfl is the first decFloat (lhs) */
/* dfr is the second decFloat (rhs) */ /* dfr is the second decFloat (rhs) */
/* set is the context */ /* set is the context */
/* returns result, which may be -1, 0, 1, or NaN (Unordered) */ /* returns result, which may be -1, 0, 1, or NaN (Unordered) */
...@@ -1633,17 +1735,21 @@ decFloat * decFloatCompareSignal(decFloat *result, ...@@ -1633,17 +1735,21 @@ decFloat * decFloatCompareSignal(decFloat *result,
/* decFloatCompareTotal -- compare two decFloats with total ordering */ /* decFloatCompareTotal -- compare two decFloats with total ordering */
/* */ /* */
/* result gets the result of comparing dfl and dfr */ /* result gets the result of comparing dfl and dfr */
/* dfl is the first decFloat (lhs) */ /* dfl is the first decFloat (lhs) */
/* dfr is the second decFloat (rhs) */ /* dfr is the second decFloat (rhs) */
/* returns result, which may be -1, 0, or 1 */ /* returns result, which may be -1, 0, or 1 */
/* ------------------------------------------------------------------ */ /* ------------------------------------------------------------------ */
decFloat * decFloatCompareTotal(decFloat *result, decFloat * decFloatCompareTotal(decFloat *result,
const decFloat *dfl, const decFloat *dfr) { const decFloat *dfl, const decFloat *dfr) {
Int comp; /* work */ Int comp; /* work */
uInt uiwork; /* for macros */
#if QUAD
uShort uswork; /* .. */
#endif
if (DFISNAN(dfl) || DFISNAN(dfr)) { if (DFISNAN(dfl) || DFISNAN(dfr)) {
Int nanl, nanr; /* work */ Int nanl, nanr; /* work */
/* morph NaNs to +/- 1 or 2, leave numbers as 0 */ /* morph NaNs to +/- 1 or 2, leave numbers as 0 */
nanl=DFISSNAN(dfl)+DFISQNAN(dfl)*2; /* quiet > signalling */ nanl=DFISSNAN(dfl)+DFISQNAN(dfl)*2; /* quiet > signalling */
if (DFISSIGNED(dfl)) nanl=-nanl; if (DFISSIGNED(dfl)) nanl=-nanl;
nanr=DFISSNAN(dfr)+DFISQNAN(dfr)*2; nanr=DFISSNAN(dfr)+DFISQNAN(dfr)*2;
if (DFISSIGNED(dfr)) nanr=-nanr; if (DFISSIGNED(dfr)) nanr=-nanr;
...@@ -1654,23 +1760,22 @@ decFloat * decFloatCompareTotal(decFloat *result, ...@@ -1654,23 +1760,22 @@ decFloat * decFloatCompareTotal(decFloat *result,
uByte bufl[DECPMAX+4]; /* for LHS coefficient + foot */ uByte bufl[DECPMAX+4]; /* for LHS coefficient + foot */
uByte bufr[DECPMAX+4]; /* for RHS coefficient + foot */ uByte bufr[DECPMAX+4]; /* for RHS coefficient + foot */
uByte *ub, *uc; /* work */ uByte *ub, *uc; /* work */
Int sigl; /* signum of LHS */ Int sigl; /* signum of LHS */
sigl=(DFISSIGNED(dfl) ? -1 : +1); sigl=(DFISSIGNED(dfl) ? -1 : +1);
/* decode the coefficients */ /* decode the coefficients */
/* (shift both right two if Quad to make a multiple of four) */ /* (shift both right two if Quad to make a multiple of four) */
#if QUAD #if QUAD
ub = bufl; /* avoid type-pun violation */ UBFROMUS(bufl, 0);
USHORTAT(ub)=0; UBFROMUS(bufr, 0);
uc = bufr; /* avoid type-pun violation */
USHORTAT(uc)=0;
#endif #endif
GETCOEFF(dfl, bufl+QUAD*2); /* decode from decFloat */ GETCOEFF(dfl, bufl+QUAD*2); /* decode from decFloat */
GETCOEFF(dfr, bufr+QUAD*2); /* .. */ GETCOEFF(dfr, bufr+QUAD*2); /* .. */
/* all multiples of four, here */ /* all multiples of four, here */
comp=0; /* assume equal */ comp=0; /* assume equal */
for (ub=bufl, uc=bufr; ub<bufl+DECPMAX+QUAD*2; ub+=4, uc+=4) { for (ub=bufl, uc=bufr; ub<bufl+DECPMAX+QUAD*2; ub+=4, uc+=4) {
if (UINTAT(ub)==UINTAT(uc)) continue; /* so far so same */ uInt ui=UBTOUI(ub);
if (ui==UBTOUI(uc)) continue; /* so far so same */
/* about to find a winner; go by bytes in case little-endian */ /* about to find a winner; go by bytes in case little-endian */
for (;; ub++, uc++) { for (;; ub++, uc++) {
if (*ub==*uc) continue; if (*ub==*uc) continue;
...@@ -1696,7 +1801,7 @@ decFloat * decFloatCompareTotal(decFloat *result, ...@@ -1696,7 +1801,7 @@ decFloat * decFloatCompareTotal(decFloat *result,
/* decFloatCompareTotalMag -- compare magnitudes with total ordering */ /* decFloatCompareTotalMag -- compare magnitudes with total ordering */
/* */ /* */
/* result gets the result of comparing abs(dfl) and abs(dfr) */ /* result gets the result of comparing abs(dfl) and abs(dfr) */
/* dfl is the first decFloat (lhs) */ /* dfl is the first decFloat (lhs) */
/* dfr is the second decFloat (rhs) */ /* dfr is the second decFloat (rhs) */
/* returns result, which may be -1, 0, or 1 */ /* returns result, which may be -1, 0, or 1 */
/* ------------------------------------------------------------------ */ /* ------------------------------------------------------------------ */
...@@ -1747,7 +1852,7 @@ decFloat * decFloatCopyAbs(decFloat *result, const decFloat *dfl) { ...@@ -1747,7 +1852,7 @@ decFloat * decFloatCopyAbs(decFloat *result, const decFloat *dfl) {
/* ------------------------------------------------------------------ */ /* ------------------------------------------------------------------ */
/* decFloatCopyNegate -- copy a decFloat as-is with inverted sign bit */ /* decFloatCopyNegate -- copy a decFloat as-is with inverted sign bit */
/* */ /* */
/* result gets the copy of dfl with sign bit inverted */ /* result gets the copy of dfl with sign bit inverted */
/* dfl is the decFloat to copy */ /* dfl is the decFloat to copy */
/* returns result */ /* returns result */
/* */ /* */
...@@ -1760,10 +1865,10 @@ decFloat * decFloatCopyNegate(decFloat *result, const decFloat *dfl) { ...@@ -1760,10 +1865,10 @@ decFloat * decFloatCopyNegate(decFloat *result, const decFloat *dfl) {
} /* decFloatCopyNegate */ } /* decFloatCopyNegate */
/* ------------------------------------------------------------------ */ /* ------------------------------------------------------------------ */
/* decFloatCopySign -- copy a decFloat with the sign of another */ /* decFloatCopySign -- copy a decFloat with the sign of another */
/* */ /* */
/* result gets the result of copying dfl with the sign of dfr */ /* result gets the result of copying dfl with the sign of dfr */
/* dfl is the first decFloat (lhs) */ /* dfl is the first decFloat (lhs) */
/* dfr is the second decFloat (rhs) */ /* dfr is the second decFloat (rhs) */
/* returns result */ /* returns result */
/* */ /* */
...@@ -1795,7 +1900,7 @@ decFloat * decFloatCopySign(decFloat *result, ...@@ -1795,7 +1900,7 @@ decFloat * decFloatCopySign(decFloat *result,
/* next one is used when it is known that the declet must be */ /* next one is used when it is known that the declet must be */
/* non-zero, or is the final zero declet */ /* non-zero, or is the final zero declet */
#define dpdlendun(n, form) {dpd=(form)&0x3ff; \ #define dpdlendun(n, form) {dpd=(form)&0x3ff; \
if (dpd==0) return 1; \ if (dpd==0) return 1; \
return (DECPMAX-1-3*(n))-(3-DPD2BCD8[dpd*4+3]);} return (DECPMAX-1-3*(n))-(3-DPD2BCD8[dpd*4+3]);}
uInt decFloatDigits(const decFloat *df) { uInt decFloatDigits(const decFloat *df) {
...@@ -1819,7 +1924,7 @@ uInt decFloatDigits(const decFloat *df) { ...@@ -1819,7 +1924,7 @@ uInt decFloatDigits(const decFloat *df) {
} /* [cannot drop through] */ } /* [cannot drop through] */
sourlo=DFWORD(df, 1); /* sourhi not involved now */ sourlo=DFWORD(df, 1); /* sourhi not involved now */
if (sourlo&0xfff00000) { /* in one of first two */ if (sourlo&0xfff00000) { /* in one of first two */
dpdlenchk(1, sourlo>>30); /* very rare */ dpdlenchk(1, sourlo>>30); /* very rare */
dpdlendun(2, sourlo>>20); dpdlendun(2, sourlo>>20);
} /* [cannot drop through] */ } /* [cannot drop through] */
dpdlenchk(3, sourlo>>10); dpdlenchk(3, sourlo>>10);
...@@ -1850,7 +1955,7 @@ uInt decFloatDigits(const decFloat *df) { ...@@ -1850,7 +1955,7 @@ uInt decFloatDigits(const decFloat *df) {
} /* [cannot drop through] */ } /* [cannot drop through] */
sourlo=DFWORD(df, 3); sourlo=DFWORD(df, 3);
if (sourlo&0xfff00000) { /* in one of first two */ if (sourlo&0xfff00000) { /* in one of first two */
dpdlenchk(7, sourlo>>30); /* very rare */ dpdlenchk(7, sourlo>>30); /* very rare */
dpdlendun(8, sourlo>>20); dpdlendun(8, sourlo>>20);
} /* [cannot drop through] */ } /* [cannot drop through] */
dpdlenchk(9, sourlo>>10); dpdlenchk(9, sourlo>>10);
...@@ -1863,7 +1968,7 @@ uInt decFloatDigits(const decFloat *df) { ...@@ -1863,7 +1968,7 @@ uInt decFloatDigits(const decFloat *df) {
/* decFloatDivide -- divide a decFloat by another */ /* decFloatDivide -- divide a decFloat by another */
/* */ /* */
/* result gets the result of dividing dfl by dfr: */ /* result gets the result of dividing dfl by dfr: */
/* dfl is the first decFloat (lhs) */ /* dfl is the first decFloat (lhs) */
/* dfr is the second decFloat (rhs) */ /* dfr is the second decFloat (rhs) */
/* set is the context */ /* set is the context */
/* returns result */ /* returns result */
...@@ -1880,7 +1985,7 @@ decFloat * decFloatDivide(decFloat *result, ...@@ -1880,7 +1985,7 @@ decFloat * decFloatDivide(decFloat *result,
/* decFloatDivideInteger -- integer divide a decFloat by another */ /* decFloatDivideInteger -- integer divide a decFloat by another */
/* */ /* */
/* result gets the result of dividing dfl by dfr: */ /* result gets the result of dividing dfl by dfr: */
/* dfl is the first decFloat (lhs) */ /* dfl is the first decFloat (lhs) */
/* dfr is the second decFloat (rhs) */ /* dfr is the second decFloat (rhs) */
/* set is the context */ /* set is the context */
/* returns result */ /* returns result */
...@@ -1896,9 +2001,9 @@ decFloat * decFloatDivideInteger(decFloat *result, ...@@ -1896,9 +2001,9 @@ decFloat * decFloatDivideInteger(decFloat *result,
/* decFloatFMA -- multiply and add three decFloats, fused */ /* decFloatFMA -- multiply and add three decFloats, fused */
/* */ /* */
/* result gets the result of (dfl*dfr)+dff with a single rounding */ /* result gets the result of (dfl*dfr)+dff with a single rounding */
/* dfl is the first decFloat (lhs) */ /* dfl is the first decFloat (lhs) */
/* dfr is the second decFloat (rhs) */ /* dfr is the second decFloat (rhs) */
/* dff is the final decFloat (fhs) */ /* dff is the final decFloat (fhs) */
/* set is the context */ /* set is the context */
/* returns result */ /* returns result */
/* */ /* */
...@@ -1906,21 +2011,23 @@ decFloat * decFloatDivideInteger(decFloat *result, ...@@ -1906,21 +2011,23 @@ decFloat * decFloatDivideInteger(decFloat *result,
decFloat * decFloatFMA(decFloat *result, const decFloat *dfl, decFloat * decFloatFMA(decFloat *result, const decFloat *dfl,
const decFloat *dfr, const decFloat *dff, const decFloat *dfr, const decFloat *dff,
decContext *set) { decContext *set) {
/* The accumulator has the bytes needed for FiniteMultiply, plus */ /* The accumulator has the bytes needed for FiniteMultiply, plus */
/* one byte to the left in case of carry, plus DECPMAX+2 to the */ /* one byte to the left in case of carry, plus DECPMAX+2 to the */
/* right for the final addition (up to full fhs + round & sticky) */ /* right for the final addition (up to full fhs + round & sticky) */
#define FMALEN (1+ (DECPMAX9*18) +DECPMAX+2) #define FMALEN (ROUNDUP4(1+ (DECPMAX9*18+1) +DECPMAX+2))
uByte acc[FMALEN]; /* for multiplied coefficient in BCD */ uByte acc[FMALEN]; /* for multiplied coefficient in BCD */
/* .. and for final result */ /* .. and for final result */
bcdnum mul; /* for multiplication result */ bcdnum mul; /* for multiplication result */
bcdnum fin; /* for final operand, expanded */ bcdnum fin; /* for final operand, expanded */
uByte coe[DECPMAX]; /* dff coefficient in BCD */ uByte coe[ROUNDUP4(DECPMAX)]; /* dff coefficient in BCD */
bcdnum *hi, *lo; /* bcdnum with higher/lower exponent */ bcdnum *hi, *lo; /* bcdnum with higher/lower exponent */
uInt diffsign; /* non-zero if signs differ */ uInt diffsign; /* non-zero if signs differ */
uInt hipad; /* pad digit for hi if needed */ uInt hipad; /* pad digit for hi if needed */
Int padding; /* excess exponent */ Int padding; /* excess exponent */
uInt carry; /* +1 for ten's complement and during add */ uInt carry; /* +1 for ten's complement and during add */
uByte *ub, *uh, *ul; /* work */ uByte *ub, *uh, *ul; /* work */
uInt uiwork; /* for macros */
/* handle all the special values [any special operand leads to a */ /* handle all the special values [any special operand leads to a */
/* special result] */ /* special result] */
...@@ -1971,8 +2078,8 @@ decFloat * decFloatFMA(decFloat *result, const decFloat *dfl, ...@@ -1971,8 +2078,8 @@ decFloat * decFloatFMA(decFloat *result, const decFloat *dfl,
GETCOEFF(dff, coe); /* extract the coefficient */ GETCOEFF(dff, coe); /* extract the coefficient */
/* now set hi and lo so that hi points to whichever of mul and fin */ /* now set hi and lo so that hi points to whichever of mul and fin */
/* has the higher exponent and lo point to the other [don't care if */ /* has the higher exponent and lo points to the other [don't care, */
/* the same] */ /* if the same]. One coefficient will be in acc, the other in coe. */
if (mul.exponent>=fin.exponent) { if (mul.exponent>=fin.exponent) {
hi=&mul; hi=&mul;
lo=&fin; lo=&fin;
...@@ -1983,22 +2090,23 @@ decFloat * decFloatFMA(decFloat *result, const decFloat *dfl, ...@@ -1983,22 +2090,23 @@ decFloat * decFloatFMA(decFloat *result, const decFloat *dfl,
} }
/* remove leading zeros on both operands; this will save time later */ /* remove leading zeros on both operands; this will save time later */
/* and make testing for zero trivial */ /* and make testing for zero trivial (tests are safe because acc */
for (; UINTAT(hi->msd)==0 && hi->msd+3<hi->lsd;) hi->msd+=4; /* and coe are rounded up to uInts) */
for (; UBTOUI(hi->msd)==0 && hi->msd+3<hi->lsd;) hi->msd+=4;
for (; *hi->msd==0 && hi->msd<hi->lsd;) hi->msd++; for (; *hi->msd==0 && hi->msd<hi->lsd;) hi->msd++;
for (; UINTAT(lo->msd)==0 && lo->msd+3<lo->lsd;) lo->msd+=4; for (; UBTOUI(lo->msd)==0 && lo->msd+3<lo->lsd;) lo->msd+=4;
for (; *lo->msd==0 && lo->msd<lo->lsd;) lo->msd++; for (; *lo->msd==0 && lo->msd<lo->lsd;) lo->msd++;
/* if hi is zero then result will be lo (which has the smaller */ /* if hi is zero then result will be lo (which has the smaller */
/* exponent), which also may need to be tested for zero for the */ /* exponent), which also may need to be tested for zero for the */
/* weird IEEE 754 sign rules */ /* weird IEEE 754 sign rules */
if (*hi->msd==0 && hi->msd==hi->lsd) { /* hi is zero */ if (*hi->msd==0) { /* hi is zero */
/* "When the sum of two operands with opposite signs is */ /* "When the sum of two operands with opposite signs is */
/* exactly zero, the sign of that sum shall be '+' in all */ /* exactly zero, the sign of that sum shall be '+' in all */
/* rounding modes except round toward -Infinity, in which */ /* rounding modes except round toward -Infinity, in which */
/* mode that sign shall be '-'." */ /* mode that sign shall be '-'." */
if (diffsign) { if (diffsign) {
if (*lo->msd==0 && lo->msd==lo->lsd) { /* lo is zero */ if (*lo->msd==0) { /* lo is zero */
lo->sign=0; lo->sign=0;
if (set->round==DEC_ROUND_FLOOR) lo->sign=DECFLOAT_Sign; if (set->round==DEC_ROUND_FLOOR) lo->sign=DECFLOAT_Sign;
} /* diffsign && lo=0 */ } /* diffsign && lo=0 */
...@@ -2006,10 +2114,11 @@ decFloat * decFloatFMA(decFloat *result, const decFloat *dfl, ...@@ -2006,10 +2114,11 @@ decFloat * decFloatFMA(decFloat *result, const decFloat *dfl,
return decFinalize(result, lo, set); /* may need clamping */ return decFinalize(result, lo, set); /* may need clamping */
} /* numfl is zero */ } /* numfl is zero */
/* [here, both are minimal length and hi is non-zero] */ /* [here, both are minimal length and hi is non-zero] */
/* (if lo is zero then padding with zeros may be needed, below) */
/* if signs differ, take the ten's complement of hi (zeros to the */ /* if signs differ, take the ten's complement of hi (zeros to the */
/* right do not matter because the complement of zero is zero); */ /* right do not matter because the complement of zero is zero); the */
/* the +1 is done later, as part of the addition, inserted at the */ /* +1 is done later, as part of the addition, inserted at the */
/* correct digit */ /* correct digit */
hipad=0; hipad=0;
carry=0; carry=0;
...@@ -2017,7 +2126,7 @@ decFloat * decFloatFMA(decFloat *result, const decFloat *dfl, ...@@ -2017,7 +2126,7 @@ decFloat * decFloatFMA(decFloat *result, const decFloat *dfl,
hipad=9; hipad=9;
carry=1; carry=1;
/* exactly the correct number of digits must be inverted */ /* exactly the correct number of digits must be inverted */
for (uh=hi->msd; uh<hi->lsd-3; uh+=4) UINTAT(uh)=0x09090909-UINTAT(uh); for (uh=hi->msd; uh<hi->lsd-3; uh+=4) UBFROMUI(uh, 0x09090909-UBTOUI(uh));
for (; uh<=hi->lsd; uh++) *uh=(uByte)(0x09-*uh); for (; uh<=hi->lsd; uh++) *uh=(uByte)(0x09-*uh);
} }
...@@ -2032,7 +2141,8 @@ decFloat * decFloatFMA(decFloat *result, const decFloat *dfl, ...@@ -2032,7 +2141,8 @@ decFloat * decFloatFMA(decFloat *result, const decFloat *dfl,
/* printf("FMA pad %ld\n", (LI)padding); */ /* printf("FMA pad %ld\n", (LI)padding); */
/* the result of the addition will be built into the accumulator, */ /* the result of the addition will be built into the accumulator, */
/* starting from the far right; this could be either hi or lo */ /* starting from the far right; this could be either hi or lo, and */
/* will be aligned */
ub=acc+FMALEN-1; /* where lsd of result will go */ ub=acc+FMALEN-1; /* where lsd of result will go */
ul=lo->lsd; /* lsd of rhs */ ul=lo->lsd; /* lsd of rhs */
...@@ -2042,45 +2152,43 @@ decFloat * decFloatFMA(decFloat *result, const decFloat *dfl, ...@@ -2042,45 +2152,43 @@ decFloat * decFloatFMA(decFloat *result, const decFloat *dfl,
/* digit at the right place, as it stays clear of hi digits */ /* digit at the right place, as it stays clear of hi digits */
/* [it must be DECPMAX+2 because during a subtraction the msd */ /* [it must be DECPMAX+2 because during a subtraction the msd */
/* could become 0 after a borrow from 1.000 to 0.9999...] */ /* could become 0 after a borrow from 1.000 to 0.9999...] */
Int hilen=(Int)(hi->lsd-hi->msd+1); /* lengths */
Int lolen=(Int)(lo->lsd-lo->msd+1); /* .. */ Int hilen=(Int)(hi->lsd-hi->msd+1); /* length of hi */
Int newexp=MINI(hi->exponent, hi->exponent+hilen-DECPMAX)-3; Int lolen=(Int)(lo->lsd-lo->msd+1); /* and of lo */
Int reduce=newexp-lo->exponent;
if (reduce>0) { /* [= case gives reduce=0 nop] */ if (hilen+padding-lolen > DECPMAX+2) { /* can reduce lo to single */
/* make sure it is virtually at least DECPMAX from hi->msd, at */
/* least to right of hi->lsd (in case of destructive subtract), */
/* and separated by at least two digits from either of those */
/* (the tricky DOUBLE case is when hi is a 1 that will become a */
/* 0.9999... by subtraction: */
/* hi: 1 E+16 */
/* lo: .................1000000000000000 E-16 */
/* which for the addition pads to: */
/* hi: 1000000000000000000 E-16 */
/* lo: .................1000000000000000 E-16 */
Int newexp=MINI(hi->exponent, hi->exponent+hilen-DECPMAX)-3;
/* printf("FMA reduce: %ld\n", (LI)reduce); */ /* printf("FMA reduce: %ld\n", (LI)reduce); */
if (reduce>=lolen) { /* eating all */ lo->lsd=lo->msd; /* to single digit [maybe 0] */
lo->lsd=lo->msd; /* reduce to single digit */ lo->exponent=newexp; /* new lowest exponent */
lo->exponent=newexp; /* [known to be non-zero] */ padding=hi->exponent-lo->exponent; /* recalculate */
} ul=lo->lsd; /* .. and repoint */
else { /* < */ }
uByte *up=lo->lsd;
lo->lsd=lo->lsd-reduce; /* padding is still > 0, but will fit in acc (less leading carry slot) */
if (*lo->lsd==0) /* could need sticky bit */
for (; up>lo->lsd; up--) { /* search discarded digits */
if (*up!=0) { /* found one... */
*lo->lsd=1; /* set sticky bit */
break;
}
}
lo->exponent+=reduce;
}
padding=hi->exponent-lo->exponent; /* recalculate */
ul=lo->lsd; /* .. */
} /* maybe reduce */
/* padding is now <= DECPMAX+2 but still > 0; tricky DOUBLE case */
/* is when hi is a 1 that will become a 0.9999... by subtraction: */
/* hi: 1 E+16 */
/* lo: .................1000000000000000 E-16 */
/* which for the addition pads and reduces to: */
/* hi: 1000000000000000000 E-2 */
/* lo: .................1 E-2 */
#if DECCHECK #if DECCHECK
if (padding>DECPMAX+2) printf("FMA excess padding: %ld\n", (LI)padding);
if (padding<=0) printf("FMA low padding: %ld\n", (LI)padding); if (padding<=0) printf("FMA low padding: %ld\n", (LI)padding);
if (hilen+padding+1>FMALEN)
printf("FMA excess hilen+padding: %ld+%ld \n", (LI)hilen, (LI)padding);
/* printf("FMA padding: %ld\n", (LI)padding); */ /* printf("FMA padding: %ld\n", (LI)padding); */
#endif #endif
/* padding digits can now be set in the result; one or more of */ /* padding digits can now be set in the result; one or more of */
/* these will come from lo; others will be zeros in the gap */ /* these will come from lo; others will be zeros in the gap */
for (; ul-3>=lo->msd && padding>3; padding-=4, ul-=4, ub-=4) {
UBFROMUI(ub-3, UBTOUI(ul-3)); /* [cannot overlap] */
}
for (; ul>=lo->msd && padding>0; padding--, ul--, ub--) *ub=*ul; for (; ul>=lo->msd && padding>0; padding--, ul--, ub--) *ub=*ul;
for (;padding>0; padding--, ub--) *ub=0; /* mind the gap */ for (;padding>0; padding--, ub--) *ub=0; /* mind the gap */
} }
...@@ -2088,23 +2196,39 @@ decFloat * decFloatFMA(decFloat *result, const decFloat *dfl, ...@@ -2088,23 +2196,39 @@ decFloat * decFloatFMA(decFloat *result, const decFloat *dfl,
/* addition now complete to the right of the rightmost digit of hi */ /* addition now complete to the right of the rightmost digit of hi */
uh=hi->lsd; uh=hi->lsd;
/* carry was set up depending on ten's complement above; do the add... */ /* dow do the add from hi->lsd to the left */
/* [bytewise, because either operand can run out at any time] */
/* carry was set up depending on ten's complement above */
/* first assume both operands have some digits */
for (;; ub--) { for (;; ub--) {
uInt hid, lod; if (uh<hi->msd || ul<lo->msd) break;
if (uh<hi->msd) { *ub=(uByte)(carry+(*uh--)+(*ul--));
carry=0;
if (*ub<10) continue;
*ub-=10;
carry=1;
} /* both loop */
if (ul<lo->msd) { /* to left of lo */
for (;; ub--) {
if (uh<hi->msd) break;
*ub=(uByte)(carry+(*uh--)); /* [+0] */
carry=0;
if (*ub<10) continue;
*ub-=10;
carry=1;
} /* hi loop */
}
else { /* to left of hi */
for (;; ub--) {
if (ul<lo->msd) break; if (ul<lo->msd) break;
hid=hipad; *ub=(uByte)(carry+hipad+(*ul--));
} carry=0;
else hid=*uh--; if (*ub<10) continue;
if (ul<lo->msd) lod=0;
else lod=*ul--;
*ub=(uByte)(carry+hid+lod);
if (*ub<10) carry=0;
else {
*ub-=10; *ub-=10;
carry=1; carry=1;
} } /* lo loop */
} /* addition loop */ }
/* addition complete -- now handle carry, borrow, etc. */ /* addition complete -- now handle carry, borrow, etc. */
/* use lo to set up the num (its exponent is already correct, and */ /* use lo to set up the num (its exponent is already correct, and */
...@@ -2122,7 +2246,7 @@ decFloat * decFloatFMA(decFloat *result, const decFloat *dfl, ...@@ -2122,7 +2246,7 @@ decFloat * decFloatFMA(decFloat *result, const decFloat *dfl,
if (!carry) { /* no carry out means hi<lo */ if (!carry) { /* no carry out means hi<lo */
/* borrowed -- take ten's complement of the right digits */ /* borrowed -- take ten's complement of the right digits */
lo->sign=hi->sign; /* sign is lhs sign */ lo->sign=hi->sign; /* sign is lhs sign */
for (ul=lo->msd; ul<lo->lsd-3; ul+=4) UINTAT(ul)=0x09090909-UINTAT(ul); for (ul=lo->msd; ul<lo->lsd-3; ul+=4) UBFROMUI(ul, 0x09090909-UBTOUI(ul));
for (; ul<=lo->lsd; ul++) *ul=(uByte)(0x09-*ul); /* [leaves ul at lsd+1] */ for (; ul<=lo->lsd; ul++) *ul=(uByte)(0x09-*ul); /* [leaves ul at lsd+1] */
/* complete the ten's complement by adding 1 [cannot overrun] */ /* complete the ten's complement by adding 1 [cannot overrun] */
for (ul--; *ul==9; ul--) *ul=0; for (ul--; *ul==9; ul--) *ul=0;
...@@ -2133,7 +2257,7 @@ decFloat * decFloatFMA(decFloat *result, const decFloat *dfl, ...@@ -2133,7 +2257,7 @@ decFloat * decFloatFMA(decFloat *result, const decFloat *dfl,
/* all done except for the special IEEE 754 exact-zero-result */ /* all done except for the special IEEE 754 exact-zero-result */
/* rule (see above); while testing for zero, strip leading */ /* rule (see above); while testing for zero, strip leading */
/* zeros (which will save decFinalize doing it) */ /* zeros (which will save decFinalize doing it) */
for (; UINTAT(lo->msd)==0 && lo->msd+3<lo->lsd;) lo->msd+=4; for (; UBTOUI(lo->msd)==0 && lo->msd+3<lo->lsd;) lo->msd+=4;
for (; *lo->msd==0 && lo->msd<lo->lsd;) lo->msd++; for (; *lo->msd==0 && lo->msd<lo->lsd;) lo->msd++;
if (*lo->msd==0) { /* must be true zero (and diffsign) */ if (*lo->msd==0) { /* must be true zero (and diffsign) */
lo->sign=0; /* assume + */ lo->sign=0; /* assume + */
...@@ -2143,11 +2267,18 @@ decFloat * decFloatFMA(decFloat *result, const decFloat *dfl, ...@@ -2143,11 +2267,18 @@ decFloat * decFloatFMA(decFloat *result, const decFloat *dfl,
} /* subtraction gave positive result */ } /* subtraction gave positive result */
} /* diffsign */ } /* diffsign */
#if DECCHECK
/* assert no left underrun */
if (lo->msd<acc) {
printf("FMA underrun by %ld \n", (LI)(acc-lo->msd));
}
#endif
return decFinalize(result, lo, set); /* round, check, and lay out */ return decFinalize(result, lo, set); /* round, check, and lay out */
} /* decFloatFMA */ } /* decFloatFMA */
/* ------------------------------------------------------------------ */ /* ------------------------------------------------------------------ */
/* decFloatFromInt -- initialise a decFloat from an Int */ /* decFloatFromInt -- initialise a decFloat from an Int */
/* */ /* */
/* result gets the converted Int */ /* result gets the converted Int */
/* n is the Int to convert */ /* n is the Int to convert */
...@@ -2213,7 +2344,7 @@ decFloat * decFloatFromUInt32(decFloat *result, uInt u) { ...@@ -2213,7 +2344,7 @@ decFloat * decFloatFromUInt32(decFloat *result, uInt u) {
/* decFloatInvert -- logical digitwise INVERT of a decFloat */ /* decFloatInvert -- logical digitwise INVERT of a decFloat */
/* */ /* */
/* result gets the result of INVERTing df */ /* result gets the result of INVERTing df */
/* df is the decFloat to invert */ /* df is the decFloat to invert */
/* set is the context */ /* set is the context */
/* returns result, which will be canonical with sign=0 */ /* returns result, which will be canonical with sign=0 */
/* */ /* */
...@@ -2241,12 +2372,12 @@ decFloat * decFloatInvert(decFloat *result, const decFloat *df, ...@@ -2241,12 +2372,12 @@ decFloat * decFloatInvert(decFloat *result, const decFloat *df,
/* ------------------------------------------------------------------ */ /* ------------------------------------------------------------------ */
/* decFloatIs -- decFloat tests (IsSigned, etc.) */ /* decFloatIs -- decFloat tests (IsSigned, etc.) */
/* */ /* */
/* df is the decFloat to test */ /* df is the decFloat to test */
/* returns 0 or 1 in an int32_t */ /* returns 0 or 1 in a uInt */
/* */ /* */
/* Many of these could be macros, but having them as real functions */ /* Many of these could be macros, but having them as real functions */
/* is a bit cleaner (and they can be referred to here by the generic */ /* is a little cleaner (and they can be referred to here by the */
/* names) */ /* generic names) */
/* ------------------------------------------------------------------ */ /* ------------------------------------------------------------------ */
uInt decFloatIsCanonical(const decFloat *df) { uInt decFloatIsCanonical(const decFloat *df) {
if (DFISSPECIAL(df)) { if (DFISSPECIAL(df)) {
...@@ -2333,10 +2464,10 @@ uInt decFloatIsZero(const decFloat *df) { ...@@ -2333,10 +2464,10 @@ uInt decFloatIsZero(const decFloat *df) {
} /* decFloatIs... */ } /* decFloatIs... */
/* ------------------------------------------------------------------ */ /* ------------------------------------------------------------------ */
/* decFloatLogB -- return adjusted exponent, by 754r rules */ /* decFloatLogB -- return adjusted exponent, by 754 rules */
/* */ /* */
/* result gets the adjusted exponent as an integer, or a NaN etc. */ /* result gets the adjusted exponent as an integer, or a NaN etc. */
/* df is the decFloat to be examined */ /* df is the decFloat to be examined */
/* set is the context */ /* set is the context */
/* returns result */ /* returns result */
/* */ /* */
...@@ -2353,12 +2484,12 @@ decFloat * decFloatLogB(decFloat *result, const decFloat *df, ...@@ -2353,12 +2484,12 @@ decFloat * decFloatLogB(decFloat *result, const decFloat *df,
if (DFISNAN(df)) return decNaNs(result, df, NULL, set); if (DFISNAN(df)) return decNaNs(result, df, NULL, set);
if (DFISINF(df)) { if (DFISINF(df)) {
DFWORD(result, 0)=0; /* need +ve */ DFWORD(result, 0)=0; /* need +ve */
return decInfinity(result, result); /* canonical +Infinity */ return decInfinity(result, result); /* canonical +Infinity */
} }
if (DFISZERO(df)) { if (DFISZERO(df)) {
set->status|=DEC_Division_by_zero; /* as per 754r */ set->status|=DEC_Division_by_zero; /* as per 754 */
DFWORD(result, 0)=DECFLOAT_Sign; /* make negative */ DFWORD(result, 0)=DECFLOAT_Sign; /* make negative */
return decInfinity(result, result); /* canonical -Infinity */ return decInfinity(result, result); /* canonical -Infinity */
} }
ae=GETEXPUN(df) /* get unbiased exponent .. */ ae=GETEXPUN(df) /* get unbiased exponent .. */
+decFloatDigits(df)-1; /* .. and make adjusted exponent */ +decFloatDigits(df)-1; /* .. and make adjusted exponent */
...@@ -2381,10 +2512,10 @@ decFloat * decFloatLogB(decFloat *result, const decFloat *df, ...@@ -2381,10 +2512,10 @@ decFloat * decFloatLogB(decFloat *result, const decFloat *df,
} /* decFloatLogB */ } /* decFloatLogB */
/* ------------------------------------------------------------------ */ /* ------------------------------------------------------------------ */
/* decFloatMax -- return maxnum of two operands */ /* decFloatMax -- return maxnum of two operands */
/* */ /* */
/* result gets the chosen decFloat */ /* result gets the chosen decFloat */
/* dfl is the first decFloat (lhs) */ /* dfl is the first decFloat (lhs) */
/* dfr is the second decFloat (rhs) */ /* dfr is the second decFloat (rhs) */
/* set is the context */ /* set is the context */
/* returns result */ /* returns result */
...@@ -2416,7 +2547,7 @@ decFloat * decFloatMax(decFloat *result, ...@@ -2416,7 +2547,7 @@ decFloat * decFloatMax(decFloat *result,
/* decFloatMaxMag -- return maxnummag of two operands */ /* decFloatMaxMag -- return maxnummag of two operands */
/* */ /* */
/* result gets the chosen decFloat */ /* result gets the chosen decFloat */
/* dfl is the first decFloat (lhs) */ /* dfl is the first decFloat (lhs) */
/* dfr is the second decFloat (rhs) */ /* dfr is the second decFloat (rhs) */
/* set is the context */ /* set is the context */
/* returns result */ /* returns result */
...@@ -2440,10 +2571,10 @@ decFloat * decFloatMaxMag(decFloat *result, ...@@ -2440,10 +2571,10 @@ decFloat * decFloatMaxMag(decFloat *result,
} /* decFloatMaxMag */ } /* decFloatMaxMag */
/* ------------------------------------------------------------------ */ /* ------------------------------------------------------------------ */
/* decFloatMin -- return minnum of two operands */ /* decFloatMin -- return minnum of two operands */
/* */ /* */
/* result gets the chosen decFloat */ /* result gets the chosen decFloat */
/* dfl is the first decFloat (lhs) */ /* dfl is the first decFloat (lhs) */
/* dfr is the second decFloat (rhs) */ /* dfr is the second decFloat (rhs) */
/* set is the context */ /* set is the context */
/* returns result */ /* returns result */
...@@ -2475,7 +2606,7 @@ decFloat * decFloatMin(decFloat *result, ...@@ -2475,7 +2606,7 @@ decFloat * decFloatMin(decFloat *result,
/* decFloatMinMag -- return minnummag of two operands */ /* decFloatMinMag -- return minnummag of two operands */
/* */ /* */
/* result gets the chosen decFloat */ /* result gets the chosen decFloat */
/* dfl is the first decFloat (lhs) */ /* dfl is the first decFloat (lhs) */
/* dfr is the second decFloat (rhs) */ /* dfr is the second decFloat (rhs) */
/* set is the context */ /* set is the context */
/* returns result */ /* returns result */
...@@ -2501,8 +2632,8 @@ decFloat * decFloatMinMag(decFloat *result, ...@@ -2501,8 +2632,8 @@ decFloat * decFloatMinMag(decFloat *result,
/* ------------------------------------------------------------------ */ /* ------------------------------------------------------------------ */
/* decFloatMinus -- negate value, heeding NaNs, etc. */ /* decFloatMinus -- negate value, heeding NaNs, etc. */
/* */ /* */
/* result gets the canonicalized 0-df */ /* result gets the canonicalized 0-df */
/* df is the decFloat to minus */ /* df is the decFloat to minus */
/* set is the context */ /* set is the context */
/* returns result */ /* returns result */
/* */ /* */
...@@ -2524,8 +2655,8 @@ decFloat * decFloatMinus(decFloat *result, const decFloat *df, ...@@ -2524,8 +2655,8 @@ decFloat * decFloatMinus(decFloat *result, const decFloat *df,
/* ------------------------------------------------------------------ */ /* ------------------------------------------------------------------ */
/* decFloatMultiply -- multiply two decFloats */ /* decFloatMultiply -- multiply two decFloats */
/* */ /* */
/* result gets the result of multiplying dfl and dfr: */ /* result gets the result of multiplying dfl and dfr: */
/* dfl is the first decFloat (lhs) */ /* dfl is the first decFloat (lhs) */
/* dfr is the second decFloat (rhs) */ /* dfr is the second decFloat (rhs) */
/* set is the context */ /* set is the context */
/* returns result */ /* returns result */
...@@ -2535,7 +2666,7 @@ decFloat * decFloatMultiply(decFloat *result, ...@@ -2535,7 +2666,7 @@ decFloat * decFloatMultiply(decFloat *result,
const decFloat *dfl, const decFloat *dfr, const decFloat *dfl, const decFloat *dfr,
decContext *set) { decContext *set) {
bcdnum num; /* for final conversion */ bcdnum num; /* for final conversion */
uByte bcdacc[DECPMAX9*18+1]; /* for coefficent in BCD */ uByte bcdacc[DECPMAX9*18+1]; /* for coefficent in BCD */
if (DFISSPECIAL(dfl) || DFISSPECIAL(dfr)) { /* either is special? */ if (DFISSPECIAL(dfl) || DFISSPECIAL(dfr)) { /* either is special? */
/* NaNs are handled as usual */ /* NaNs are handled as usual */
...@@ -2561,7 +2692,7 @@ decFloat * decFloatMultiply(decFloat *result, ...@@ -2561,7 +2692,7 @@ decFloat * decFloatMultiply(decFloat *result,
/* set is the context */ /* set is the context */
/* returns result */ /* returns result */
/* */ /* */
/* This is 754r nextdown; Invalid is the only status possible (from */ /* This is 754 nextdown; Invalid is the only status possible (from */
/* an sNaN). */ /* an sNaN). */
/* ------------------------------------------------------------------ */ /* ------------------------------------------------------------------ */
decFloat * decFloatNextMinus(decFloat *result, const decFloat *dfl, decFloat * decFloatNextMinus(decFloat *result, const decFloat *dfl,
...@@ -2580,19 +2711,19 @@ decFloat * decFloatNextMinus(decFloat *result, const decFloat *dfl, ...@@ -2580,19 +2711,19 @@ decFloat * decFloatNextMinus(decFloat *result, const decFloat *dfl,
/* here (but can be done with normal add if the sign of zero is */ /* here (but can be done with normal add if the sign of zero is */
/* treated carefully, because no Inexactitude is interesting); */ /* treated carefully, because no Inexactitude is interesting); */
/* rounding to -Infinity then pushes the result to next below */ /* rounding to -Infinity then pushes the result to next below */
decFloatZero(&delta); /* set up tiny delta */ decFloatZero(&delta); /* set up tiny delta */
DFWORD(&delta, DECWORDS-1)=1; /* coefficient=1 */ DFWORD(&delta, DECWORDS-1)=1; /* coefficient=1 */
DFWORD(&delta, 0)=DECFLOAT_Sign; /* Sign=1 + biased exponent=0 */ DFWORD(&delta, 0)=DECFLOAT_Sign; /* Sign=1 + biased exponent=0 */
/* set up for the directional round */ /* set up for the directional round */
saveround=set->round; /* save mode */ saveround=set->round; /* save mode */
set->round=DEC_ROUND_FLOOR; /* .. round towards -Infinity */ set->round=DEC_ROUND_FLOOR; /* .. round towards -Infinity */
savestat=set->status; /* save status */ savestat=set->status; /* save status */
decFloatAdd(result, dfl, &delta, set); decFloatAdd(result, dfl, &delta, set);
/* Add rules mess up the sign when going from +Ntiny to 0 */ /* Add rules mess up the sign when going from +Ntiny to 0 */
if (DFISZERO(result)) DFWORD(result, 0)^=DECFLOAT_Sign; /* correct */ if (DFISZERO(result)) DFWORD(result, 0)^=DECFLOAT_Sign; /* correct */
set->status&=DEC_Invalid_operation; /* preserve only sNaN status */ set->status&=DEC_Invalid_operation; /* preserve only sNaN status */
set->status|=savestat; /* restore pending flags */ set->status|=savestat; /* restore pending flags */
set->round=saveround; /* .. and mode */ set->round=saveround; /* .. and mode */
return result; return result;
} /* decFloatNextMinus */ } /* decFloatNextMinus */
...@@ -2604,7 +2735,7 @@ decFloat * decFloatNextMinus(decFloat *result, const decFloat *dfl, ...@@ -2604,7 +2735,7 @@ decFloat * decFloatNextMinus(decFloat *result, const decFloat *dfl,
/* set is the context */ /* set is the context */
/* returns result */ /* returns result */
/* */ /* */
/* This is 754r nextup; Invalid is the only status possible (from */ /* This is 754 nextup; Invalid is the only status possible (from */
/* an sNaN). */ /* an sNaN). */
/* ------------------------------------------------------------------ */ /* ------------------------------------------------------------------ */
decFloat * decFloatNextPlus(decFloat *result, const decFloat *dfl, decFloat * decFloatNextPlus(decFloat *result, const decFloat *dfl,
...@@ -2624,19 +2755,19 @@ decFloat * decFloatNextPlus(decFloat *result, const decFloat *dfl, ...@@ -2624,19 +2755,19 @@ decFloat * decFloatNextPlus(decFloat *result, const decFloat *dfl,
/* here (but can be done with normal add if the sign of zero is */ /* here (but can be done with normal add if the sign of zero is */
/* treated carefully, because no Inexactitude is interesting); */ /* treated carefully, because no Inexactitude is interesting); */
/* rounding to +Infinity then pushes the result to next above */ /* rounding to +Infinity then pushes the result to next above */
decFloatZero(&delta); /* set up tiny delta */ decFloatZero(&delta); /* set up tiny delta */
DFWORD(&delta, DECWORDS-1)=1; /* coefficient=1 */ DFWORD(&delta, DECWORDS-1)=1; /* coefficient=1 */
DFWORD(&delta, 0)=0; /* Sign=0 + biased exponent=0 */ DFWORD(&delta, 0)=0; /* Sign=0 + biased exponent=0 */
/* set up for the directional round */ /* set up for the directional round */
saveround=set->round; /* save mode */ saveround=set->round; /* save mode */
set->round=DEC_ROUND_CEILING; /* .. round towards +Infinity */ set->round=DEC_ROUND_CEILING; /* .. round towards +Infinity */
savestat=set->status; /* save status */ savestat=set->status; /* save status */
decFloatAdd(result, dfl, &delta, set); decFloatAdd(result, dfl, &delta, set);
/* Add rules mess up the sign when going from -Ntiny to -0 */ /* Add rules mess up the sign when going from -Ntiny to -0 */
if (DFISZERO(result)) DFWORD(result, 0)^=DECFLOAT_Sign; /* correct */ if (DFISZERO(result)) DFWORD(result, 0)^=DECFLOAT_Sign; /* correct */
set->status&=DEC_Invalid_operation; /* preserve only sNaN status */ set->status&=DEC_Invalid_operation; /* preserve only sNaN status */
set->status|=savestat; /* restore pending flags */ set->status|=savestat; /* restore pending flags */
set->round=saveround; /* .. and mode */ set->round=saveround; /* .. and mode */
return result; return result;
} /* decFloatNextPlus */ } /* decFloatNextPlus */
...@@ -2649,8 +2780,9 @@ decFloat * decFloatNextPlus(decFloat *result, const decFloat *dfl, ...@@ -2649,8 +2780,9 @@ decFloat * decFloatNextPlus(decFloat *result, const decFloat *dfl,
/* set is the context */ /* set is the context */
/* returns result */ /* returns result */
/* */ /* */
/* This is 754r nextafter; status may be set unless the result is a */ /* This is 754-1985 nextafter, as modified during revision (dropped */
/* normal number. */ /* from 754-2008); status may be set unless the result is a normal */
/* number. */
/* ------------------------------------------------------------------ */ /* ------------------------------------------------------------------ */
decFloat * decFloatNextToward(decFloat *result, decFloat * decFloatNextToward(decFloat *result,
const decFloat *dfl, const decFloat *dfr, const decFloat *dfl, const decFloat *dfr,
...@@ -2676,7 +2808,7 @@ decFloat * decFloatNextToward(decFloat *result, ...@@ -2676,7 +2808,7 @@ decFloat * decFloatNextToward(decFloat *result,
} }
saveround=set->round; /* save mode */ saveround=set->round; /* save mode */
set->round=DEC_ROUND_CEILING; /* .. round towards +Infinity */ set->round=DEC_ROUND_CEILING; /* .. round towards +Infinity */
deltatop=0; /* positive delta */ deltatop=0; /* positive delta */
} }
else { /* lhs>rhs, do NextMinus, see above for commentary */ else { /* lhs>rhs, do NextMinus, see above for commentary */
if (DFISINF(dfl) && !DFISSIGNED(dfl)) { /* +Infinity special case */ if (DFISINF(dfl) && !DFISSIGNED(dfl)) { /* +Infinity special case */
...@@ -2684,23 +2816,23 @@ decFloat * decFloatNextToward(decFloat *result, ...@@ -2684,23 +2816,23 @@ decFloat * decFloatNextToward(decFloat *result,
return result; return result;
} }
saveround=set->round; /* save mode */ saveround=set->round; /* save mode */
set->round=DEC_ROUND_FLOOR; /* .. round towards -Infinity */ set->round=DEC_ROUND_FLOOR; /* .. round towards -Infinity */
deltatop=DECFLOAT_Sign; /* negative delta */ deltatop=DECFLOAT_Sign; /* negative delta */
} }
savestat=set->status; /* save status */ savestat=set->status; /* save status */
/* Here, Inexact is needed where appropriate (and hence Underflow, */ /* Here, Inexact is needed where appropriate (and hence Underflow, */
/* etc.). Therefore the tiny delta which is otherwise */ /* etc.). Therefore the tiny delta which is otherwise */
/* unrepresentable (see NextPlus and NextMinus) is constructed */ /* unrepresentable (see NextPlus and NextMinus) is constructed */
/* using the multiplication of FMA. */ /* using the multiplication of FMA. */
decFloatZero(&delta); /* set up tiny delta */ decFloatZero(&delta); /* set up tiny delta */
DFWORD(&delta, DECWORDS-1)=1; /* coefficient=1 */ DFWORD(&delta, DECWORDS-1)=1; /* coefficient=1 */
DFWORD(&delta, 0)=deltatop; /* Sign + biased exponent=0 */ DFWORD(&delta, 0)=deltatop; /* Sign + biased exponent=0 */
decFloatFromString(&pointone, "1E-1", set); /* set up multiplier */ decFloatFromString(&pointone, "1E-1", set); /* set up multiplier */
decFloatFMA(result, &delta, &pointone, dfl, set); decFloatFMA(result, &delta, &pointone, dfl, set);
/* [Delta is truly tiny, so no need to correct sign of zero] */ /* [Delta is truly tiny, so no need to correct sign of zero] */
/* use new status unless the result is normal */ /* use new status unless the result is normal */
if (decFloatIsNormal(result)) set->status=savestat; /* else goes forward */ if (decFloatIsNormal(result)) set->status=savestat; /* else goes forward */
set->round=saveround; /* restore mode */ set->round=saveround; /* restore mode */
return result; return result;
} /* decFloatNextToward */ } /* decFloatNextToward */
...@@ -2708,12 +2840,12 @@ decFloat * decFloatNextToward(decFloat *result, ...@@ -2708,12 +2840,12 @@ decFloat * decFloatNextToward(decFloat *result,
/* decFloatOr -- logical digitwise OR of two decFloats */ /* decFloatOr -- logical digitwise OR of two decFloats */
/* */ /* */
/* result gets the result of ORing dfl and dfr */ /* result gets the result of ORing dfl and dfr */
/* dfl is the first decFloat (lhs) */ /* dfl is the first decFloat (lhs) */
/* dfr is the second decFloat (rhs) */ /* dfr is the second decFloat (rhs) */
/* set is the context */ /* set is the context */
/* returns result, which will be canonical with sign=0 */ /* returns result, which will be canonical with sign=0 */
/* */ /* */
/* The operands must be positive, finite with exponent q=0, and */ /* The operands must be positive, finite with exponent q=0, and */
/* comprise just zeros and ones; if not, Invalid operation results. */ /* comprise just zeros and ones; if not, Invalid operation results. */
/* ------------------------------------------------------------------ */ /* ------------------------------------------------------------------ */
decFloat * decFloatOr(decFloat *result, decFloat * decFloatOr(decFloat *result,
...@@ -2739,14 +2871,14 @@ decFloat * decFloatOr(decFloat *result, ...@@ -2739,14 +2871,14 @@ decFloat * decFloatOr(decFloat *result,
/* ------------------------------------------------------------------ */ /* ------------------------------------------------------------------ */
/* decFloatPlus -- add value to 0, heeding NaNs, etc. */ /* decFloatPlus -- add value to 0, heeding NaNs, etc. */
/* */ /* */
/* result gets the canonicalized 0+df */ /* result gets the canonicalized 0+df */
/* df is the decFloat to plus */ /* df is the decFloat to plus */
/* set is the context */ /* set is the context */
/* returns result */ /* returns result */
/* */ /* */
/* This has the same effect as 0+df where the exponent of the zero is */ /* This has the same effect as 0+df where the exponent of the zero is */
/* the same as that of df (if df is finite). */ /* the same as that of df (if df is finite). */
/* The effect is also the same as decFloatCopy except that NaNs */ /* The effect is also the same as decFloatCopy except that NaNs */
/* are handled normally (the sign of a NaN is not affected, and an */ /* are handled normally (the sign of a NaN is not affected, and an */
/* sNaN will signal), the result is canonical, and zero gets sign 0. */ /* sNaN will signal), the result is canonical, and zero gets sign 0. */
/* ------------------------------------------------------------------ */ /* ------------------------------------------------------------------ */
...@@ -2762,7 +2894,7 @@ decFloat * decFloatPlus(decFloat *result, const decFloat *df, ...@@ -2762,7 +2894,7 @@ decFloat * decFloatPlus(decFloat *result, const decFloat *df,
/* decFloatQuantize -- quantize a decFloat */ /* decFloatQuantize -- quantize a decFloat */
/* */ /* */
/* result gets the result of quantizing dfl to match dfr */ /* result gets the result of quantizing dfl to match dfr */
/* dfl is the first decFloat (lhs) */ /* dfl is the first decFloat (lhs) */
/* dfr is the second decFloat (rhs), which sets the exponent */ /* dfr is the second decFloat (rhs), which sets the exponent */
/* set is the context */ /* set is the context */
/* returns result */ /* returns result */
...@@ -2775,16 +2907,19 @@ decFloat * decFloatQuantize(decFloat *result, ...@@ -2775,16 +2907,19 @@ decFloat * decFloatQuantize(decFloat *result,
decContext *set) { decContext *set) {
Int explb, exprb; /* left and right biased exponents */ Int explb, exprb; /* left and right biased exponents */
uByte *ulsd; /* local LSD pointer */ uByte *ulsd; /* local LSD pointer */
uInt *ui; /* work */ uByte *ub, *uc; /* work */
uByte *ub; /* .. */
Int drop; /* .. */ Int drop; /* .. */
uInt dpd; /* .. */ uInt dpd; /* .. */
uInt encode; /* encoding accumulator */ uInt encode; /* encoding accumulator */
uInt sourhil, sourhir; /* top words from source decFloats */ uInt sourhil, sourhir; /* top words from source decFloats */
uInt uiwork; /* for macros */
#if QUAD
uShort uswork; /* .. */
#endif
/* the following buffer holds the coefficient for manipulation */ /* the following buffer holds the coefficient for manipulation */
uByte buf[4+DECPMAX*3]; /* + space for zeros to left or right */ uByte buf[4+DECPMAX*3+2*QUAD]; /* + space for zeros to left or right */
#if DECTRACE #if DECTRACE
bcdnum num; /* for trace displays */ bcdnum num; /* for trace displays */
#endif #endif
/* Start decoding the arguments */ /* Start decoding the arguments */
...@@ -2827,7 +2962,7 @@ decFloat * decFloatQuantize(decFloat *result, ...@@ -2827,7 +2962,7 @@ decFloat * decFloatQuantize(decFloat *result,
decShowNum(&num, "dfl"); decShowNum(&num, "dfl");
#endif #endif
if (drop>0) { /* [most common case] */ if (drop>0) { /* [most common case] */
/* (this code is very similar to that in decFloatFinalize, but */ /* (this code is very similar to that in decFloatFinalize, but */
/* has many differences so is duplicated here -- so any changes */ /* has many differences so is duplicated here -- so any changes */
/* may need to be made there, too) */ /* may need to be made there, too) */
...@@ -2838,7 +2973,7 @@ decFloat * decFloatQuantize(decFloat *result, ...@@ -2838,7 +2973,7 @@ decFloat * decFloatQuantize(decFloat *result,
/* there is at least one zero needed to the left, in all but one */ /* there is at least one zero needed to the left, in all but one */
/* exceptional (all-nines) case, so place four zeros now; this is */ /* exceptional (all-nines) case, so place four zeros now; this is */
/* needed almost always and makes rounding all-nines by fours safe */ /* needed almost always and makes rounding all-nines by fours safe */
UINTAT(BUFOFF-4)=0; UBFROMUI(BUFOFF-4, 0);
/* Three cases here: */ /* Three cases here: */
/* 1. new LSD is in coefficient (almost always) */ /* 1. new LSD is in coefficient (almost always) */
...@@ -2849,7 +2984,7 @@ decFloat * decFloatQuantize(decFloat *result, ...@@ -2849,7 +2984,7 @@ decFloat * decFloatQuantize(decFloat *result,
/* [duplicate check-stickies code to save a test] */ /* [duplicate check-stickies code to save a test] */
/* [by-digit check for stickies as runs of zeros are rare] */ /* [by-digit check for stickies as runs of zeros are rare] */
if (drop<DECPMAX) { /* NB lengths not addresses */ if (drop<DECPMAX) { /* NB lengths not addresses */
roundat=BUFOFF+DECPMAX-drop; roundat=BUFOFF+DECPMAX-drop;
reround=*roundat; reround=*roundat;
for (ub=roundat+1; ub<BUFOFF+DECPMAX; ub++) { for (ub=roundat+1; ub<BUFOFF+DECPMAX; ub++) {
...@@ -2932,7 +3067,7 @@ decFloat * decFloatQuantize(decFloat *result, ...@@ -2932,7 +3067,7 @@ decFloat * decFloatQuantize(decFloat *result,
/* increment the coefficient; this could give 1000... (after */ /* increment the coefficient; this could give 1000... (after */
/* the all nines case) */ /* the all nines case) */
ub=ulsd; ub=ulsd;
for (; UINTAT(ub-3)==0x09090909; ub-=4) UINTAT(ub-3)=0; for (; UBTOUI(ub-3)==0x09090909; ub-=4) UBFROMUI(ub-3, 0);
/* now at most 3 digits left to non-9 (usually just the one) */ /* now at most 3 digits left to non-9 (usually just the one) */
for (; *ub==9; ub--) *ub=0; for (; *ub==9; ub--) *ub=0;
*ub+=1; *ub+=1;
...@@ -2945,8 +3080,8 @@ decFloat * decFloatQuantize(decFloat *result, ...@@ -2945,8 +3080,8 @@ decFloat * decFloatQuantize(decFloat *result,
/* available in the coefficent -- the first word to the left was */ /* available in the coefficent -- the first word to the left was */
/* cleared earlier for safe carry; now add any more needed */ /* cleared earlier for safe carry; now add any more needed */
if (drop>4) { if (drop>4) {
UINTAT(BUFOFF-8)=0; /* must be at least 5 */ UBFROMUI(BUFOFF-8, 0); /* must be at least 5 */
for (ui=&UINTAT(BUFOFF-12); ui>&UINTAT(ulsd-DECPMAX-3); ui--) *ui=0; for (uc=BUFOFF-12; uc>ulsd-DECPMAX-3; uc-=4) UBFROMUI(uc, 0);
} }
} /* need round (drop>0) */ } /* need round (drop>0) */
...@@ -2967,18 +3102,21 @@ decFloat * decFloatQuantize(decFloat *result, ...@@ -2967,18 +3102,21 @@ decFloat * decFloatQuantize(decFloat *result,
#else #else
static const uInt dmask[]={0, 0xff000000, 0xffff0000, 0xffffff00}; static const uInt dmask[]={0, 0xff000000, 0xffff0000, 0xffffff00};
#endif #endif
for (ui=&UINTAT(BUFOFF+DECPMAX);; ui++) { /* note that here zeros to the right are added by fours, so in */
*ui=0; /* the Quad case this could write 36 zeros if the coefficient has */
if (UINTAT(&UBYTEAT(ui)-DECPMAX)!=0) { /* could be bad */ /* fewer than three significant digits (hence the +2*QUAD for buf) */
for (uc=BUFOFF+DECPMAX;; uc+=4) {
UBFROMUI(uc, 0);
if (UBTOUI(uc-DECPMAX)!=0) { /* could be bad */
/* if all four digits should be zero, definitely bad */ /* if all four digits should be zero, definitely bad */
if (ui<=&UINTAT(BUFOFF+DECPMAX+(-drop)-4)) if (uc<=BUFOFF+DECPMAX+(-drop)-4)
return decInvalid(result, set); return decInvalid(result, set);
/* must be a 1- to 3-digit sequence; check more carefully */ /* must be a 1- to 3-digit sequence; check more carefully */
if ((UINTAT(&UBYTEAT(ui)-DECPMAX)&dmask[(-drop)%4])!=0) if ((UBTOUI(uc-DECPMAX)&dmask[(-drop)%4])!=0)
return decInvalid(result, set); return decInvalid(result, set);
break; /* no need for loop end test */ break; /* no need for loop end test */
} }
if (ui>=&UINTAT(BUFOFF+DECPMAX+(-drop)-4)) break; /* done */ if (uc>=BUFOFF+DECPMAX+(-drop)-4) break; /* done */
} }
ulsd=BUFOFF+DECPMAX+(-drop)-1; ulsd=BUFOFF+DECPMAX+(-drop)-1;
} /* pad and check leading zeros */ } /* pad and check leading zeros */
...@@ -3045,7 +3183,7 @@ decFloat * decFloatQuantize(decFloat *result, ...@@ -3045,7 +3183,7 @@ decFloat * decFloatQuantize(decFloat *result,
/* decFloatReduce -- reduce finite coefficient to minimum length */ /* decFloatReduce -- reduce finite coefficient to minimum length */
/* */ /* */
/* result gets the reduced decFloat */ /* result gets the reduced decFloat */
/* df is the source decFloat */ /* df is the source decFloat */
/* set is the context */ /* set is the context */
/* returns result, which will be canonical */ /* returns result, which will be canonical */
/* */ /* */
...@@ -3085,7 +3223,7 @@ decFloat * decFloatReduce(decFloat *result, const decFloat *df, ...@@ -3085,7 +3223,7 @@ decFloat * decFloatReduce(decFloat *result, const decFloat *df,
/* decFloatRemainder -- integer divide and return remainder */ /* decFloatRemainder -- integer divide and return remainder */
/* */ /* */
/* result gets the remainder of dividing dfl by dfr: */ /* result gets the remainder of dividing dfl by dfr: */
/* dfl is the first decFloat (lhs) */ /* dfl is the first decFloat (lhs) */
/* dfr is the second decFloat (rhs) */ /* dfr is the second decFloat (rhs) */
/* set is the context */ /* set is the context */
/* returns result */ /* returns result */
...@@ -3101,7 +3239,7 @@ decFloat * decFloatRemainder(decFloat *result, ...@@ -3101,7 +3239,7 @@ decFloat * decFloatRemainder(decFloat *result,
/* decFloatRemainderNear -- integer divide to nearest and remainder */ /* decFloatRemainderNear -- integer divide to nearest and remainder */
/* */ /* */
/* result gets the remainder of dividing dfl by dfr: */ /* result gets the remainder of dividing dfl by dfr: */
/* dfl is the first decFloat (lhs) */ /* dfl is the first decFloat (lhs) */
/* dfr is the second decFloat (rhs) */ /* dfr is the second decFloat (rhs) */
/* set is the context */ /* set is the context */
/* returns result */ /* returns result */
...@@ -3145,7 +3283,7 @@ decFloat * decFloatRotate(decFloat *result, ...@@ -3145,7 +3283,7 @@ decFloat * decFloatRotate(decFloat *result,
if (DFISNAN(dfl)||DFISNAN(dfr)) return decNaNs(result, dfl, dfr, set); if (DFISNAN(dfl)||DFISNAN(dfr)) return decNaNs(result, dfl, dfr, set);
if (!DFISINT(dfr)) return decInvalid(result, set); if (!DFISINT(dfr)) return decInvalid(result, set);
digits=decFloatDigits(dfr); /* calculate digits */ digits=decFloatDigits(dfr); /* calculate digits */
if (digits>2) return decInvalid(result, set); /* definitely out of range */ if (digits>2) return decInvalid(result, set); /* definitely out of range */
rotate=DPD2BIN[DFWORD(dfr, DECWORDS-1)&0x3ff]; /* is in bottom declet */ rotate=DPD2BIN[DFWORD(dfr, DECWORDS-1)&0x3ff]; /* is in bottom declet */
if (rotate>DECPMAX) return decInvalid(result, set); /* too big */ if (rotate>DECPMAX) return decInvalid(result, set); /* too big */
/* [from here on no error or status change is possible] */ /* [from here on no error or status change is possible] */
...@@ -3178,16 +3316,16 @@ decFloat * decFloatRotate(decFloat *result, ...@@ -3178,16 +3316,16 @@ decFloat * decFloatRotate(decFloat *result,
num.lsd=num.msd+DECPMAX-1; num.lsd=num.msd+DECPMAX-1;
num.sign=DFWORD(dfl, 0)&DECFLOAT_Sign; num.sign=DFWORD(dfl, 0)&DECFLOAT_Sign;
num.exponent=GETEXPUN(dfl); num.exponent=GETEXPUN(dfl);
savestat=set->status; /* record */ savestat=set->status; /* record */
decFinalize(result, &num, set); decFinalize(result, &num, set);
set->status=savestat; /* restore */ set->status=savestat; /* restore */
return result; return result;
} /* decFloatRotate */ } /* decFloatRotate */
/* ------------------------------------------------------------------ */ /* ------------------------------------------------------------------ */
/* decFloatSameQuantum -- test decFloats for same quantum */ /* decFloatSameQuantum -- test decFloats for same quantum */
/* */ /* */
/* dfl is the first decFloat (lhs) */ /* dfl is the first decFloat (lhs) */
/* dfr is the second decFloat (rhs) */ /* dfr is the second decFloat (rhs) */
/* returns 1 if the operands have the same quantum, 0 otherwise */ /* returns 1 if the operands have the same quantum, 0 otherwise */
/* */ /* */
...@@ -3204,11 +3342,11 @@ uInt decFloatSameQuantum(const decFloat *dfl, const decFloat *dfr) { ...@@ -3204,11 +3342,11 @@ uInt decFloatSameQuantum(const decFloat *dfl, const decFloat *dfr) {
} /* decFloatSameQuantum */ } /* decFloatSameQuantum */
/* ------------------------------------------------------------------ */ /* ------------------------------------------------------------------ */
/* decFloatScaleB -- multiply by a power of 10, as per 754r */ /* decFloatScaleB -- multiply by a power of 10, as per 754 */
/* */ /* */
/* result gets the result of the operation */ /* result gets the result of the operation */
/* dfl is the first decFloat (lhs) */ /* dfl is the first decFloat (lhs) */
/* dfr is the second decFloat (rhs), am integer (with q=0) */ /* dfr is the second decFloat (rhs), am integer (with q=0) */
/* set is the context */ /* set is the context */
/* returns result */ /* returns result */
/* */ /* */
...@@ -3229,10 +3367,10 @@ decFloat * decFloatScaleB(decFloat *result, ...@@ -3229,10 +3367,10 @@ decFloat * decFloatScaleB(decFloat *result,
digits=decFloatDigits(dfr); /* calculate digits */ digits=decFloatDigits(dfr); /* calculate digits */
#if DOUBLE #if DOUBLE
if (digits>3) return decInvalid(result, set); /* definitely out of range */ if (digits>3) return decInvalid(result, set); /* definitely out of range */
expr=DPD2BIN[DFWORD(dfr, 1)&0x3ff]; /* must be in bottom declet */ expr=DPD2BIN[DFWORD(dfr, 1)&0x3ff]; /* must be in bottom declet */
#elif QUAD #elif QUAD
if (digits>5) return decInvalid(result, set); /* definitely out of range */ if (digits>5) return decInvalid(result, set); /* definitely out of range */
expr=DPD2BIN[DFWORD(dfr, 3)&0x3ff] /* in bottom 2 declets .. */ expr=DPD2BIN[DFWORD(dfr, 3)&0x3ff] /* in bottom 2 declets .. */
+DPD2BIN[(DFWORD(dfr, 3)>>10)&0x3ff]*1000; /* .. */ +DPD2BIN[(DFWORD(dfr, 3)>>10)&0x3ff]*1000; /* .. */
#endif #endif
...@@ -3241,7 +3379,7 @@ decFloat * decFloatScaleB(decFloat *result, ...@@ -3241,7 +3379,7 @@ decFloat * decFloatScaleB(decFloat *result,
if (DFISINF(dfl)) return decInfinity(result, dfl); /* canonical */ if (DFISINF(dfl)) return decInfinity(result, dfl); /* canonical */
if (DFISSIGNED(dfr)) expr=-expr; if (DFISSIGNED(dfr)) expr=-expr;
/* dfl is finite and expr is valid */ /* dfl is finite and expr is valid */
*result=*dfl; /* copy to target */ *result=*dfl; /* copy to target */
return decFloatSetExponent(result, set, GETEXPUN(result)+expr); return decFloatSetExponent(result, set, GETEXPUN(result)+expr);
} /* decFloatScaleB */ } /* decFloatScaleB */
...@@ -3266,23 +3404,24 @@ decFloat * decFloatScaleB(decFloat *result, ...@@ -3266,23 +3404,24 @@ decFloat * decFloatScaleB(decFloat *result,
decFloat * decFloatShift(decFloat *result, decFloat * decFloatShift(decFloat *result,
const decFloat *dfl, const decFloat *dfr, const decFloat *dfl, const decFloat *dfr,
decContext *set) { decContext *set) {
Int shift; /* dfr as an Int */ Int shift; /* dfr as an Int */
uByte buf[DECPMAX*2]; /* coefficient + padding */ uByte buf[DECPMAX*2]; /* coefficient + padding */
uInt digits, savestat; /* work */ uInt digits, savestat; /* work */
bcdnum num; /* .. */ bcdnum num; /* .. */
uInt uiwork; /* for macros */
if (DFISNAN(dfl)||DFISNAN(dfr)) return decNaNs(result, dfl, dfr, set); if (DFISNAN(dfl)||DFISNAN(dfr)) return decNaNs(result, dfl, dfr, set);
if (!DFISINT(dfr)) return decInvalid(result, set); if (!DFISINT(dfr)) return decInvalid(result, set);
digits=decFloatDigits(dfr); /* calculate digits */ digits=decFloatDigits(dfr); /* calculate digits */
if (digits>2) return decInvalid(result, set); /* definitely out of range */ if (digits>2) return decInvalid(result, set); /* definitely out of range */
shift=DPD2BIN[DFWORD(dfr, DECWORDS-1)&0x3ff]; /* is in bottom declet */ shift=DPD2BIN[DFWORD(dfr, DECWORDS-1)&0x3ff]; /* is in bottom declet */
if (shift>DECPMAX) return decInvalid(result, set); /* too big */ if (shift>DECPMAX) return decInvalid(result, set); /* too big */
/* [from here on no error or status change is possible] */ /* [from here on no error or status change is possible] */
if (DFISINF(dfl)) return decInfinity(result, dfl); /* canonical */ if (DFISINF(dfl)) return decInfinity(result, dfl); /* canonical */
/* handle no-shift and all-shift (clear to zero) cases */ /* handle no-shift and all-shift (clear to zero) cases */
if (shift==0) return decCanonical(result, dfl); if (shift==0) return decCanonical(result, dfl);
if (shift==DECPMAX) { /* zero with sign */ if (shift==DECPMAX) { /* zero with sign */
uByte sign=(uByte)(DFBYTE(dfl, 0)&0x80); /* save sign bit */ uByte sign=(uByte)(DFBYTE(dfl, 0)&0x80); /* save sign bit */
decFloatZero(result); /* make +0 */ decFloatZero(result); /* make +0 */
DFBYTE(result, 0)=(uByte)(DFBYTE(result, 0)|sign); /* and set sign */ DFBYTE(result, 0)=(uByte)(DFBYTE(result, 0)|sign); /* and set sign */
...@@ -3299,23 +3438,23 @@ decFloat * decFloatShift(decFloat *result, ...@@ -3299,23 +3438,23 @@ decFloat * decFloatShift(decFloat *result,
num.lsd=buf+DECPMAX-shift-1; num.lsd=buf+DECPMAX-shift-1;
} }
else { /* shift left -- zero padding needed to right */ else { /* shift left -- zero padding needed to right */
UINTAT(buf+DECPMAX)=0; /* 8 will handle most cases */ UBFROMUI(buf+DECPMAX, 0); /* 8 will handle most cases */
UINTAT(buf+DECPMAX+4)=0; /* .. */ UBFROMUI(buf+DECPMAX+4, 0); /* .. */
if (shift>8) memset(buf+DECPMAX+8, 0, 8+QUAD*18); /* all other cases */ if (shift>8) memset(buf+DECPMAX+8, 0, 8+QUAD*18); /* all other cases */
num.msd+=shift; num.msd+=shift;
num.lsd=num.msd+DECPMAX-1; num.lsd=num.msd+DECPMAX-1;
} }
savestat=set->status; /* record */ savestat=set->status; /* record */
decFinalize(result, &num, set); decFinalize(result, &num, set);
set->status=savestat; /* restore */ set->status=savestat; /* restore */
return result; return result;
} /* decFloatShift */ } /* decFloatShift */
/* ------------------------------------------------------------------ */ /* ------------------------------------------------------------------ */
/* decFloatSubtract -- subtract a decFloat from another */ /* decFloatSubtract -- subtract a decFloat from another */
/* */ /* */
/* result gets the result of subtracting dfr from dfl: */ /* result gets the result of subtracting dfr from dfl: */
/* dfl is the first decFloat (lhs) */ /* dfl is the first decFloat (lhs) */
/* dfr is the second decFloat (rhs) */ /* dfr is the second decFloat (rhs) */
/* set is the context */ /* set is the context */
/* returns result */ /* returns result */
...@@ -3333,9 +3472,9 @@ decFloat * decFloatSubtract(decFloat *result, ...@@ -3333,9 +3472,9 @@ decFloat * decFloatSubtract(decFloat *result,
} /* decFloatSubtract */ } /* decFloatSubtract */
/* ------------------------------------------------------------------ */ /* ------------------------------------------------------------------ */
/* decFloatToInt -- round to 32-bit binary integer (4 flavours) */ /* decFloatToInt -- round to 32-bit binary integer (4 flavours) */
/* */ /* */
/* df is the decFloat to round */ /* df is the decFloat to round */
/* set is the context */ /* set is the context */
/* round is the rounding mode to use */ /* round is the rounding mode to use */
/* returns a uInt or an Int, rounded according to the name */ /* returns a uInt or an Int, rounded according to the name */
...@@ -3361,12 +3500,12 @@ Int decFloatToInt32Exact(const decFloat *df, decContext *set, ...@@ -3361,12 +3500,12 @@ Int decFloatToInt32Exact(const decFloat *df, decContext *set,
return (Int)decToInt32(df, set, round, 1, 0);} return (Int)decToInt32(df, set, round, 1, 0);}
/* ------------------------------------------------------------------ */ /* ------------------------------------------------------------------ */
/* decFloatToIntegral -- round to integral value (two flavours) */ /* decFloatToIntegral -- round to integral value (two flavours) */
/* */ /* */
/* result gets the result */ /* result gets the result */
/* df is the decFloat to round */ /* df is the decFloat to round */
/* set is the context */ /* set is the context */
/* round is the rounding mode to use */ /* round is the rounding mode to use */
/* returns result */ /* returns result */
/* */ /* */
/* No exceptions, even Inexact, are raised except for sNaN input, or */ /* No exceptions, even Inexact, are raised except for sNaN input, or */
...@@ -3384,12 +3523,12 @@ decFloat * decFloatToIntegralExact(decFloat *result, const decFloat *df, ...@@ -3384,12 +3523,12 @@ decFloat * decFloatToIntegralExact(decFloat *result, const decFloat *df,
/* decFloatXor -- logical digitwise XOR of two decFloats */ /* decFloatXor -- logical digitwise XOR of two decFloats */
/* */ /* */
/* result gets the result of XORing dfl and dfr */ /* result gets the result of XORing dfl and dfr */
/* dfl is the first decFloat (lhs) */ /* dfl is the first decFloat (lhs) */
/* dfr is the second decFloat (rhs) */ /* dfr is the second decFloat (rhs) */
/* set is the context */ /* set is the context */
/* returns result, which will be canonical with sign=0 */ /* returns result, which will be canonical with sign=0 */
/* */ /* */
/* The operands must be positive, finite with exponent q=0, and */ /* The operands must be positive, finite with exponent q=0, and */
/* comprise just zeros and ones; if not, Invalid operation results. */ /* comprise just zeros and ones; if not, Invalid operation results. */
/* ------------------------------------------------------------------ */ /* ------------------------------------------------------------------ */
decFloat * decFloatXor(decFloat *result, decFloat * decFloatXor(decFloat *result,
...@@ -3432,14 +3571,14 @@ static decFloat *decInvalid(decFloat *result, decContext *set) { ...@@ -3432,14 +3571,14 @@ static decFloat *decInvalid(decFloat *result, decContext *set) {
/* decInfinity -- set canonical Infinity with sign from a decFloat */ /* decInfinity -- set canonical Infinity with sign from a decFloat */
/* */ /* */
/* result gets a canonical Infinity */ /* result gets a canonical Infinity */
/* df is source decFloat (only the sign is used) */ /* df is source decFloat (only the sign is used) */
/* returns result */ /* returns result */
/* */ /* */
/* df may be the same as result */ /* df may be the same as result */
/* ------------------------------------------------------------------ */ /* ------------------------------------------------------------------ */
static decFloat *decInfinity(decFloat *result, const decFloat *df) { static decFloat *decInfinity(decFloat *result, const decFloat *df) {
uInt sign=DFWORD(df, 0); /* save source signword */ uInt sign=DFWORD(df, 0); /* save source signword */
decFloatZero(result); /* clear everything */ decFloatZero(result); /* clear everything */
DFWORD(result, 0)=DECFLOAT_Inf | (sign & DECFLOAT_Sign); DFWORD(result, 0)=DECFLOAT_Inf | (sign & DECFLOAT_Sign);
return result; return result;
} /* decInfinity */ } /* decInfinity */
...@@ -3449,7 +3588,7 @@ static decFloat *decInfinity(decFloat *result, const decFloat *df) { ...@@ -3449,7 +3588,7 @@ static decFloat *decInfinity(decFloat *result, const decFloat *df) {
/* */ /* */
/* result gets the result of handling dfl and dfr, one or both of */ /* result gets the result of handling dfl and dfr, one or both of */
/* which is a NaN */ /* which is a NaN */
/* dfl is the first decFloat (lhs) */ /* dfl is the first decFloat (lhs) */
/* dfr is the second decFloat (rhs) -- may be NULL for a single- */ /* dfr is the second decFloat (rhs) -- may be NULL for a single- */
/* operand operation */ /* operand operation */
/* set is the context */ /* set is the context */
...@@ -3476,19 +3615,20 @@ static decFloat *decNaNs(decFloat *result, ...@@ -3476,19 +3615,20 @@ static decFloat *decNaNs(decFloat *result,
} /* decNaNs */ } /* decNaNs */
/* ------------------------------------------------------------------ */ /* ------------------------------------------------------------------ */
/* decNumCompare -- numeric comparison of two decFloats */ /* decNumCompare -- numeric comparison of two decFloats */
/* */ /* */
/* dfl is the left-hand decFloat, which is not a NaN */ /* dfl is the left-hand decFloat, which is not a NaN */
/* dfr is the right-hand decFloat, which is not a NaN */ /* dfr is the right-hand decFloat, which is not a NaN */
/* tot is 1 for total order compare, 0 for simple numeric */ /* tot is 1 for total order compare, 0 for simple numeric */
/* returns -1, 0, or +1 for dfl<dfr, dfl=dfr, dfl>dfr */ /* returns -1, 0, or +1 for dfl<dfr, dfl=dfr, dfl>dfr */
/* */ /* */
/* No error is possible; status and mode are unchanged. */ /* No error is possible; status and mode are unchanged. */
/* ------------------------------------------------------------------ */ /* ------------------------------------------------------------------ */
static Int decNumCompare(const decFloat *dfl, const decFloat *dfr, Flag tot) { static Int decNumCompare(const decFloat *dfl, const decFloat *dfr, Flag tot) {
Int sigl, sigr; /* LHS and RHS non-0 signums */ Int sigl, sigr; /* LHS and RHS non-0 signums */
Int shift; /* shift needed to align operands */ Int shift; /* shift needed to align operands */
uByte *ub, *uc; /* work */ uByte *ub, *uc; /* work */
uInt uiwork; /* for macros */
/* buffers +2 if Quad (36 digits), need double plus 4 for safe padding */ /* buffers +2 if Quad (36 digits), need double plus 4 for safe padding */
uByte bufl[DECPMAX*2+QUAD*2+4]; /* for LHS coefficient + padding */ uByte bufl[DECPMAX*2+QUAD*2+4]; /* for LHS coefficient + padding */
uByte bufr[DECPMAX*2+QUAD*2+4]; /* for RHS coefficient + padding */ uByte bufr[DECPMAX*2+QUAD*2+4]; /* for RHS coefficient + padding */
...@@ -3512,7 +3652,7 @@ static Int decNumCompare(const decFloat *dfl, const decFloat *dfr, Flag tot) { ...@@ -3512,7 +3652,7 @@ static Int decNumCompare(const decFloat *dfl, const decFloat *dfr, Flag tot) {
sigr=-sigl; /* sign to return if abs(RHS) wins */ sigr=-sigl; /* sign to return if abs(RHS) wins */
if (DFISINF(dfl)) { if (DFISINF(dfl)) {
if (DFISINF(dfr)) return 0; /* both infinite & same sign */ if (DFISINF(dfr)) return 0; /* both infinite & same sign */
return sigl; /* inf > n */ return sigl; /* inf > n */
} }
if (DFISINF(dfr)) return sigr; /* n < inf [dfl is finite] */ if (DFISINF(dfr)) return sigr; /* n < inf [dfl is finite] */
...@@ -3544,17 +3684,16 @@ static Int decNumCompare(const decFloat *dfl, const decFloat *dfr, Flag tot) { ...@@ -3544,17 +3684,16 @@ static Int decNumCompare(const decFloat *dfl, const decFloat *dfr, Flag tot) {
/* decode the coefficients */ /* decode the coefficients */
/* (shift both right two if Quad to make a multiple of four) */ /* (shift both right two if Quad to make a multiple of four) */
#if QUAD #if QUAD
ub=bufl; /* avoid type-pun violation */ UBFROMUI(bufl, 0);
UINTAT(ub)=0; UBFROMUI(bufr, 0);
uc=bufr; /* avoid type-pun violation */
UINTAT(uc)=0;
#endif #endif
GETCOEFF(dfl, bufl+QUAD*2); /* decode from decFloat */ GETCOEFF(dfl, bufl+QUAD*2); /* decode from decFloat */
GETCOEFF(dfr, bufr+QUAD*2); /* .. */ GETCOEFF(dfr, bufr+QUAD*2); /* .. */
if (shift==0) { /* aligned; common and easy */ if (shift==0) { /* aligned; common and easy */
/* all multiples of four, here */ /* all multiples of four, here */
for (ub=bufl, uc=bufr; ub<bufl+DECPMAX+QUAD*2; ub+=4, uc+=4) { for (ub=bufl, uc=bufr; ub<bufl+DECPMAX+QUAD*2; ub+=4, uc+=4) {
if (UINTAT(ub)==UINTAT(uc)) continue; /* so far so same */ uInt ui=UBTOUI(ub);
if (ui==UBTOUI(uc)) continue; /* so far so same */
/* about to find a winner; go by bytes in case little-endian */ /* about to find a winner; go by bytes in case little-endian */
for (;; ub++, uc++) { for (;; ub++, uc++) {
if (*ub>*uc) return sigl; /* difference found */ if (*ub>*uc) return sigl; /* difference found */
...@@ -3565,17 +3704,17 @@ static Int decNumCompare(const decFloat *dfl, const decFloat *dfr, Flag tot) { ...@@ -3565,17 +3704,17 @@ static Int decNumCompare(const decFloat *dfl, const decFloat *dfr, Flag tot) {
else if (shift>0) { /* lhs to left */ else if (shift>0) { /* lhs to left */
ub=bufl; /* RHS pointer */ ub=bufl; /* RHS pointer */
/* pad bufl so right-aligned; most shifts will fit in 8 */ /* pad bufl so right-aligned; most shifts will fit in 8 */
UINTAT(bufl+DECPMAX+QUAD*2)=0; /* add eight zeros */ UBFROMUI(bufl+DECPMAX+QUAD*2, 0); /* add eight zeros */
UINTAT(bufl+DECPMAX+QUAD*2+4)=0; /* .. */ UBFROMUI(bufl+DECPMAX+QUAD*2+4, 0); /* .. */
if (shift>8) { if (shift>8) {
/* more than eight; fill the rest, and also worth doing the */ /* more than eight; fill the rest, and also worth doing the */
/* lead-in by fours */ /* lead-in by fours */
uByte *up; /* work */ uByte *up; /* work */
uByte *upend=bufl+DECPMAX+QUAD*2+shift; uByte *upend=bufl+DECPMAX+QUAD*2+shift;
for (up=bufl+DECPMAX+QUAD*2+8; up<upend; up+=4) UINTAT(up)=0; for (up=bufl+DECPMAX+QUAD*2+8; up<upend; up+=4) UBFROMUI(up, 0);
/* [pads up to 36 in all for Quad] */ /* [pads up to 36 in all for Quad] */
for (;; ub+=4) { for (;; ub+=4) {
if (UINTAT(ub)!=0) return sigl; if (UBTOUI(ub)!=0) return sigl;
if (ub+4>bufl+shift-4) break; if (ub+4>bufl+shift-4) break;
} }
} }
...@@ -3585,7 +3724,8 @@ static Int decNumCompare(const decFloat *dfl, const decFloat *dfr, Flag tot) { ...@@ -3585,7 +3724,8 @@ static Int decNumCompare(const decFloat *dfl, const decFloat *dfr, Flag tot) {
/* comparison can go for the full length of bufr, which is a */ /* comparison can go for the full length of bufr, which is a */
/* multiple of 4 bytes */ /* multiple of 4 bytes */
for (uc=bufr; ; uc+=4, ub+=4) { for (uc=bufr; ; uc+=4, ub+=4) {
if (UINTAT(uc)!=UINTAT(ub)) { /* mismatch found */ uInt ui=UBTOUI(ub);
if (ui!=UBTOUI(uc)) { /* mismatch found */
for (;; uc++, ub++) { /* check from left [little-endian?] */ for (;; uc++, ub++) { /* check from left [little-endian?] */
if (*ub>*uc) return sigl; /* difference found */ if (*ub>*uc) return sigl; /* difference found */
if (*ub<*uc) return sigr; /* .. */ if (*ub<*uc) return sigr; /* .. */
...@@ -3598,17 +3738,17 @@ static Int decNumCompare(const decFloat *dfl, const decFloat *dfr, Flag tot) { ...@@ -3598,17 +3738,17 @@ static Int decNumCompare(const decFloat *dfl, const decFloat *dfr, Flag tot) {
else { /* shift<0) .. RHS is to left of LHS; mirror shift>0 */ else { /* shift<0) .. RHS is to left of LHS; mirror shift>0 */
uc=bufr; /* RHS pointer */ uc=bufr; /* RHS pointer */
/* pad bufr so right-aligned; most shifts will fit in 8 */ /* pad bufr so right-aligned; most shifts will fit in 8 */
UINTAT(bufr+DECPMAX+QUAD*2)=0; /* add eight zeros */ UBFROMUI(bufr+DECPMAX+QUAD*2, 0); /* add eight zeros */
UINTAT(bufr+DECPMAX+QUAD*2+4)=0; /* .. */ UBFROMUI(bufr+DECPMAX+QUAD*2+4, 0); /* .. */
if (shift<-8) { if (shift<-8) {
/* more than eight; fill the rest, and also worth doing the */ /* more than eight; fill the rest, and also worth doing the */
/* lead-in by fours */ /* lead-in by fours */
uByte *up; /* work */ uByte *up; /* work */
uByte *upend=bufr+DECPMAX+QUAD*2-shift; uByte *upend=bufr+DECPMAX+QUAD*2-shift;
for (up=bufr+DECPMAX+QUAD*2+8; up<upend; up+=4) UINTAT(up)=0; for (up=bufr+DECPMAX+QUAD*2+8; up<upend; up+=4) UBFROMUI(up, 0);
/* [pads up to 36 in all for Quad] */ /* [pads up to 36 in all for Quad] */
for (;; uc+=4) { for (;; uc+=4) {
if (UINTAT(uc)!=0) return sigr; if (UBTOUI(uc)!=0) return sigr;
if (uc+4>bufr-shift-4) break; if (uc+4>bufr-shift-4) break;
} }
} }
...@@ -3618,7 +3758,8 @@ static Int decNumCompare(const decFloat *dfl, const decFloat *dfr, Flag tot) { ...@@ -3618,7 +3758,8 @@ static Int decNumCompare(const decFloat *dfl, const decFloat *dfr, Flag tot) {
/* comparison can go for the full length of bufl, which is a */ /* comparison can go for the full length of bufl, which is a */
/* multiple of 4 bytes */ /* multiple of 4 bytes */
for (ub=bufl; ; ub+=4, uc+=4) { for (ub=bufl; ; ub+=4, uc+=4) {
if (UINTAT(ub)!=UINTAT(uc)) { /* mismatch found */ uInt ui=UBTOUI(ub);
if (ui!=UBTOUI(uc)) { /* mismatch found */
for (;; ub++, uc++) { /* check from left [little-endian?] */ for (;; ub++, uc++) { /* check from left [little-endian?] */
if (*ub>*uc) return sigl; /* difference found */ if (*ub>*uc) return sigl; /* difference found */
if (*ub<*uc) return sigr; /* .. */ if (*ub<*uc) return sigr; /* .. */
...@@ -3639,10 +3780,10 @@ static Int decNumCompare(const decFloat *dfl, const decFloat *dfr, Flag tot) { ...@@ -3639,10 +3780,10 @@ static Int decNumCompare(const decFloat *dfl, const decFloat *dfr, Flag tot) {
/* ------------------------------------------------------------------ */ /* ------------------------------------------------------------------ */
/* decToInt32 -- local routine to effect ToInteger conversions */ /* decToInt32 -- local routine to effect ToInteger conversions */
/* */ /* */
/* df is the decFloat to convert */ /* df is the decFloat to convert */
/* set is the context */ /* set is the context */
/* rmode is the rounding mode to use */ /* rmode is the rounding mode to use */
/* exact is 1 if Inexact should be signalled */ /* exact is 1 if Inexact should be signalled */
/* unsign is 1 if the result a uInt, 0 if an Int (cast to uInt) */ /* unsign is 1 if the result a uInt, 0 if an Int (cast to uInt) */
/* returns 32-bit result as a uInt */ /* returns 32-bit result as a uInt */
/* */ /* */
...@@ -3652,13 +3793,13 @@ static Int decNumCompare(const decFloat *dfl, const decFloat *dfr, Flag tot) { ...@@ -3652,13 +3793,13 @@ static Int decNumCompare(const decFloat *dfl, const decFloat *dfr, Flag tot) {
static uInt decToInt32(const decFloat *df, decContext *set, static uInt decToInt32(const decFloat *df, decContext *set,
enum rounding rmode, Flag exact, Flag unsign) { enum rounding rmode, Flag exact, Flag unsign) {
Int exp; /* exponent */ Int exp; /* exponent */
uInt sourhi, sourpen, sourlo; /* top word from source decFloat .. */ uInt sourhi, sourpen, sourlo; /* top word from source decFloat .. */
uInt hi, lo; /* .. penultimate, least, etc. */ uInt hi, lo; /* .. penultimate, least, etc. */
decFloat zero, result; /* work */ decFloat zero, result; /* work */
Int i; /* .. */ Int i; /* .. */
/* Start decoding the argument */ /* Start decoding the argument */
sourhi=DFWORD(df, 0); /* top word */ sourhi=DFWORD(df, 0); /* top word */
exp=DECCOMBEXP[sourhi>>26]; /* get exponent high bits (in place) */ exp=DECCOMBEXP[sourhi>>26]; /* get exponent high bits (in place) */
if (EXPISSPECIAL(exp)) { /* is special? */ if (EXPISSPECIAL(exp)) { /* is special? */
set->status|=DEC_Invalid_operation; /* signal */ set->status|=DEC_Invalid_operation; /* signal */
...@@ -3730,10 +3871,10 @@ static uInt decToInt32(const decFloat *df, decContext *set, ...@@ -3730,10 +3871,10 @@ static uInt decToInt32(const decFloat *df, decContext *set,
/* decToIntegral -- local routine to effect ToIntegral value */ /* decToIntegral -- local routine to effect ToIntegral value */
/* */ /* */
/* result gets the result */ /* result gets the result */
/* df is the decFloat to round */ /* df is the decFloat to round */
/* set is the context */ /* set is the context */
/* rmode is the rounding mode to use */ /* rmode is the rounding mode to use */
/* exact is 1 if Inexact should be signalled */ /* exact is 1 if Inexact should be signalled */
/* returns result */ /* returns result */
/* ------------------------------------------------------------------ */ /* ------------------------------------------------------------------ */
static decFloat * decToIntegral(decFloat *result, const decFloat *df, static decFloat * decToIntegral(decFloat *result, const decFloat *df,
...@@ -3746,7 +3887,7 @@ static decFloat * decToIntegral(decFloat *result, const decFloat *df, ...@@ -3746,7 +3887,7 @@ static decFloat * decToIntegral(decFloat *result, const decFloat *df,
decFloat zero; /* work */ decFloat zero; /* work */
/* Start decoding the argument */ /* Start decoding the argument */
sourhi=DFWORD(df, 0); /* top word */ sourhi=DFWORD(df, 0); /* top word */
exp=DECCOMBEXP[sourhi>>26]; /* get exponent high bits (in place) */ exp=DECCOMBEXP[sourhi>>26]; /* get exponent high bits (in place) */
if (EXPISSPECIAL(exp)) { /* is special? */ if (EXPISSPECIAL(exp)) { /* is special? */
...@@ -3762,12 +3903,12 @@ static decFloat * decToIntegral(decFloat *result, const decFloat *df, ...@@ -3762,12 +3903,12 @@ static decFloat * decToIntegral(decFloat *result, const decFloat *df,
if (exp>=0) return decCanonical(result, df); /* already integral */ if (exp>=0) return decCanonical(result, df); /* already integral */
saveround=set->round; /* save rounding mode .. */ saveround=set->round; /* save rounding mode .. */
savestatus=set->status; /* .. and status */ savestatus=set->status; /* .. and status */
set->round=rmode; /* set mode */ set->round=rmode; /* set mode */
decFloatZero(&zero); /* make 0E+0 */ decFloatZero(&zero); /* make 0E+0 */
decFloatQuantize(result, df, &zero, set); /* 'integrate'; cannot fail */ decFloatQuantize(result, df, &zero, set); /* 'integrate'; cannot fail */
set->round=saveround; /* restore rounding mode .. */ set->round=saveround; /* restore rounding mode .. */
if (!exact) set->status=savestatus; /* .. and status, unless exact */ if (!exact) set->status=savestatus; /* .. and status, unless exact */
return result; return result;
} /* decToIntegral */ } /* decToIntegral */
...@@ -104,15 +104,15 @@ static decFloat * decFinalize(decFloat *, bcdnum *, decContext *); ...@@ -104,15 +104,15 @@ static decFloat * decFinalize(decFloat *, bcdnum *, decContext *);
static Flag decBiStr(const char *, const char *, const char *); static Flag decBiStr(const char *, const char *, const char *);
/* Macros and private tables; those which are not format-dependent */ /* Macros and private tables; those which are not format-dependent */
/* are only included if decQuad is being built. */ /* are only included if decQuad is being built. */
/* ------------------------------------------------------------------ */ /* ------------------------------------------------------------------ */
/* Combination field lookup tables (uInts to save measurable work) */ /* Combination field lookup tables (uInts to save measurable work) */
/* */ /* */
/* DECCOMBEXP - 2 most-significant-bits of exponent (00, 01, or */ /* DECCOMBEXP - 2 most-significant-bits of exponent (00, 01, or */
/* 10), shifted left for format, or DECFLOAT_Inf/NaN */ /* 10), shifted left for format, or DECFLOAT_Inf/NaN */
/* DECCOMBWEXP - The same, for the next-wider format (unless QUAD) */ /* DECCOMBWEXP - The same, for the next-wider format (unless QUAD) */
/* DECCOMBMSD - 4-bit most-significant-digit */ /* DECCOMBMSD - 4-bit most-significant-digit */
/* [0 if the index is a special (Infinity or NaN)] */ /* [0 if the index is a special (Infinity or NaN)] */
/* DECCOMBFROM - 5-bit combination field from EXP top bits and MSD */ /* DECCOMBFROM - 5-bit combination field from EXP top bits and MSD */
/* (placed in uInt so no shift is needed) */ /* (placed in uInt so no shift is needed) */
...@@ -123,7 +123,7 @@ static Flag decBiStr(const char *, const char *, const char *); ...@@ -123,7 +123,7 @@ static Flag decBiStr(const char *, const char *, const char *);
/* DECCOMBFROM is indexed by expTopTwoBits*16 + msd */ /* DECCOMBFROM is indexed by expTopTwoBits*16 + msd */
/* */ /* */
/* DECCOMBMSD and DECCOMBFROM are not format-dependent and so are */ /* DECCOMBMSD and DECCOMBFROM are not format-dependent and so are */
/* only included once, when QUAD is being built */ /* only included once, when QUAD is being built */
/* ------------------------------------------------------------------ */ /* ------------------------------------------------------------------ */
static const uInt DECCOMBEXP[64]={ static const uInt DECCOMBEXP[64]={
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
...@@ -161,7 +161,7 @@ static const uInt DECCOMBWEXP[64]={ ...@@ -161,7 +161,7 @@ static const uInt DECCOMBWEXP[64]={
#if QUAD #if QUAD
const uInt DECCOMBMSD[64]={ const uInt DECCOMBMSD[64]={
0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7,
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 8, 9, 8, 9, 0, 1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 8, 9, 8, 9, 0, 0,
0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7,
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 8, 9, 8, 9, 0, 0}; 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 8, 9, 8, 9, 0, 0};
...@@ -223,7 +223,7 @@ static Flag decBiStr(const char *targ, const char *str1, const char *str2) { ...@@ -223,7 +223,7 @@ static Flag decBiStr(const char *targ, const char *str1, const char *str2) {
/* returns df */ /* returns df */
/* */ /* */
/* The num descriptor may point to a bcd8 string of any length; this */ /* The num descriptor may point to a bcd8 string of any length; this */
/* string may have leading insignificant zeros. If it has more than */ /* string may have leading insignificant zeros. If it has more than */
/* DECPMAX digits then the final digit can be a round-for-reround */ /* DECPMAX digits then the final digit can be a round-for-reround */
/* digit (i.e., it may include a sticky bit residue). */ /* digit (i.e., it may include a sticky bit residue). */
/* */ /* */
...@@ -248,8 +248,9 @@ static decFloat * decFinalize(decFloat *df, bcdnum *num, ...@@ -248,8 +248,9 @@ static decFloat * decFinalize(decFloat *df, bcdnum *num,
decContext *set) { decContext *set) {
uByte *ub; /* work */ uByte *ub; /* work */
uInt dpd; /* .. */ uInt dpd; /* .. */
uByte *umsd=num->msd; /* local copy */ uInt uiwork; /* for macros */
uByte *ulsd=num->lsd; /* .. */ uByte *umsd=num->msd; /* local copy */
uByte *ulsd=num->lsd; /* .. */
uInt encode; /* encoding accumulator */ uInt encode; /* encoding accumulator */
Int length; /* coefficient length */ Int length; /* coefficient length */
...@@ -275,11 +276,11 @@ static decFloat * decFinalize(decFloat *df, bcdnum *num, ...@@ -275,11 +276,11 @@ static decFloat * decFinalize(decFloat *df, bcdnum *num,
length=(uInt)(ulsd-umsd+1); /* coefficient length */ length=(uInt)(ulsd-umsd+1); /* coefficient length */
if (!NUMISSPECIAL(num)) { if (!NUMISSPECIAL(num)) {
Int drop; /* digits to be dropped */ Int drop; /* digits to be dropped */
/* skip leading insignificant zeros to calculate an exact length */ /* skip leading insignificant zeros to calculate an exact length */
/* [this is quite expensive] */ /* [this is quite expensive] */
if (*umsd==0) { if (*umsd==0) {
for (; UINTAT(umsd)==0 && umsd+3<ulsd;) umsd+=4; for (; umsd+3<ulsd && UBTOUI(umsd)==0;) umsd+=4;
for (; *umsd==0 && umsd<ulsd;) umsd++; for (; *umsd==0 && umsd<ulsd;) umsd++;
length=ulsd-umsd+1; /* recalculate */ length=ulsd-umsd+1; /* recalculate */
} }
...@@ -305,12 +306,12 @@ static decFloat * decFinalize(decFloat *df, bcdnum *num, ...@@ -305,12 +306,12 @@ static decFloat * decFinalize(decFloat *df, bcdnum *num,
roundat=umsd+length-drop; roundat=umsd+length-drop;
reround=*roundat; reround=*roundat;
for (ub=roundat+1; ub<=ulsd; ub++) { for (ub=roundat+1; ub<=ulsd; ub++) {
if (*ub!=0) { /* non-zero to be discarded */ if (*ub!=0) { /* non-zero to be discarded */
reround=DECSTICKYTAB[reround]; /* apply sticky bit */ reround=DECSTICKYTAB[reround]; /* apply sticky bit */
break; /* [remainder don't-care] */ break; /* [remainder don't-care] */
} }
} /* check stickies */ } /* check stickies */
ulsd=roundat-1; /* new LSD */ ulsd=roundat-1; /* new LSD */
} }
else { /* edge case */ else { /* edge case */
if (drop==length) { if (drop==length) {
...@@ -322,7 +323,7 @@ static decFloat * decFinalize(decFloat *df, bcdnum *num, ...@@ -322,7 +323,7 @@ static decFloat * decFinalize(decFloat *df, bcdnum *num,
reround=0; reround=0;
} }
for (ub=roundat+1; ub<=ulsd; ub++) { for (ub=roundat+1; ub<=ulsd; ub++) {
if (*ub!=0) { /* non-zero to be discarded */ if (*ub!=0) { /* non-zero to be discarded */
reround=DECSTICKYTAB[reround]; /* apply sticky bit */ reround=DECSTICKYTAB[reround]; /* apply sticky bit */
break; /* [remainder don't-care] */ break; /* [remainder don't-care] */
} }
...@@ -331,7 +332,7 @@ static decFloat * decFinalize(decFloat *df, bcdnum *num, ...@@ -331,7 +332,7 @@ static decFloat * decFinalize(decFloat *df, bcdnum *num,
ulsd=umsd; /* .. */ ulsd=umsd; /* .. */
} }
if (reround!=0) { /* discarding non-zero */ if (reround!=0) { /* discarding non-zero */
uInt bump=0; uInt bump=0;
set->status|=DEC_Inexact; set->status|=DEC_Inexact;
/* if adjusted exponent [exp+digits-1] is < EMIN then num is */ /* if adjusted exponent [exp+digits-1] is < EMIN then num is */
...@@ -342,7 +343,7 @@ static decFloat * decFinalize(decFloat *df, bcdnum *num, ...@@ -342,7 +343,7 @@ static decFloat * decFinalize(decFloat *df, bcdnum *num,
/* next decide whether increment of the coefficient is needed */ /* next decide whether increment of the coefficient is needed */
if (set->round==DEC_ROUND_HALF_EVEN) { /* fastpath slowest case */ if (set->round==DEC_ROUND_HALF_EVEN) { /* fastpath slowest case */
if (reround>5) bump=1; /* >0.5 goes up */ if (reround>5) bump=1; /* >0.5 goes up */
else if (reround==5) /* exactly 0.5000 .. */ else if (reround==5) /* exactly 0.5000 .. */
bump=*ulsd & 0x01; /* .. up iff [new] lsd is odd */ bump=*ulsd & 0x01; /* .. up iff [new] lsd is odd */
} /* r-h-e */ } /* r-h-e */
else switch (set->round) { else switch (set->round) {
...@@ -382,13 +383,15 @@ static decFloat * decFinalize(decFloat *df, bcdnum *num, ...@@ -382,13 +383,15 @@ static decFloat * decFinalize(decFloat *df, bcdnum *num,
#endif #endif
break;} break;}
} /* switch (not r-h-e) */ } /* switch (not r-h-e) */
/* printf("ReRound: %ld bump: %ld\n", (LI)reround, (LI)bump); */ /* printf("ReRound: %ld bump: %ld\n", (LI)reround, (LI)bump); */
if (bump!=0) { /* need increment */ if (bump!=0) { /* need increment */
/* increment the coefficient; this might end up with 1000... */ /* increment the coefficient; this might end up with 1000... */
/* (after the all nines case) */ /* (after the all nines case) */
ub=ulsd; ub=ulsd;
for(; ub-3>=umsd && UINTAT(ub-3)==0x09090909; ub-=4) UINTAT(ub-3)=0; for(; ub-3>=umsd && UBTOUI(ub-3)==0x09090909; ub-=4) {
UBFROMUI(ub-3, 0); /* to 00000000 */
}
/* [note ub could now be to left of msd, and it is not safe */ /* [note ub could now be to left of msd, and it is not safe */
/* to write to the the left of the msd] */ /* to write to the the left of the msd] */
/* now at most 3 digits left to non-9 (usually just the one) */ /* now at most 3 digits left to non-9 (usually just the one) */
...@@ -436,7 +439,7 @@ static decFloat * decFinalize(decFloat *df, bcdnum *num, ...@@ -436,7 +439,7 @@ static decFloat * decFinalize(decFloat *df, bcdnum *num,
else if ((num->exponent+length-1)>DECEMAX) { /* > Nmax */ else if ((num->exponent+length-1)>DECEMAX) { /* > Nmax */
/* Overflow -- these could go straight to encoding, here, but */ /* Overflow -- these could go straight to encoding, here, but */
/* instead num is adjusted to keep the code cleaner */ /* instead num is adjusted to keep the code cleaner */
Flag needmax=0; /* 1 for finite result */ Flag needmax=0; /* 1 for finite result */
set->status|=(DEC_Overflow | DEC_Inexact); set->status|=(DEC_Overflow | DEC_Inexact);
switch (set->round) { switch (set->round) {
case DEC_ROUND_DOWN: { case DEC_ROUND_DOWN: {
...@@ -453,12 +456,12 @@ static decFloat * decFinalize(decFloat *df, bcdnum *num, ...@@ -453,12 +456,12 @@ static decFloat * decFinalize(decFloat *df, bcdnum *num,
break;} /* r-f */ break;} /* r-f */
default: break; /* Infinity in all other cases */ default: break; /* Infinity in all other cases */
} }
if (!needmax) { /* easy .. set Infinity */ if (!needmax) { /* easy .. set Infinity */
num->exponent=DECFLOAT_Inf; num->exponent=DECFLOAT_Inf;
*umsd=0; /* be clean: coefficient to 0 */ *umsd=0; /* be clean: coefficient to 0 */
ulsd=umsd; /* .. */ ulsd=umsd; /* .. */
} }
else { /* return Nmax */ else { /* return Nmax */
umsd=allnines; /* use constant array */ umsd=allnines; /* use constant array */
ulsd=allnines+DECPMAX-1; ulsd=allnines+DECPMAX-1;
num->exponent=DECEMAX-(DECPMAX-1); num->exponent=DECEMAX-(DECPMAX-1);
...@@ -475,8 +478,8 @@ static decFloat * decFinalize(decFloat *df, bcdnum *num, ...@@ -475,8 +478,8 @@ static decFloat * decFinalize(decFloat *df, bcdnum *num,
uByte *t=buffer; /* safe target */ uByte *t=buffer; /* safe target */
uByte *tlsd=buffer+(ulsd-umsd)+shift; /* target LSD */ uByte *tlsd=buffer+(ulsd-umsd)+shift; /* target LSD */
/* printf("folddown shift=%ld\n", (LI)shift); */ /* printf("folddown shift=%ld\n", (LI)shift); */
for (; s<=ulsd; s+=4, t+=4) UINTAT(t)=UINTAT(s); for (; s<=ulsd; s+=4, t+=4) UBFROMUI(t, UBTOUI(s));
for (t=tlsd-shift+1; t<=tlsd; t+=4) UINTAT(t)=0; /* pad */ for (t=tlsd-shift+1; t<=tlsd; t+=4) UBFROMUI(t, 0); /* pad 0s */
num->exponent-=shift; num->exponent-=shift;
umsd=buffer; umsd=buffer;
ulsd=tlsd; ulsd=tlsd;
...@@ -492,23 +495,23 @@ static decFloat * decFinalize(decFloat *df, bcdnum *num, ...@@ -492,23 +495,23 @@ static decFloat * decFinalize(decFloat *df, bcdnum *num,
/*------------------------------------------------------------------*/ /*------------------------------------------------------------------*/
/* Following code does not alter coefficient (could be allnines array) */ /* Following code does not alter coefficient (could be allnines array) */
/* fast path possible when DECPMAX digits */
if (length==DECPMAX) { if (length==DECPMAX) {
return decFloatFromBCD(df, num->exponent, umsd, num->sign); return decFloatFromBCD(df, num->exponent, umsd, num->sign);
} } /* full-length */
/* Here when length is short */ /* slower path when not a full-length number; must care about length */
/* [coefficient length here will be < DECPMAX] */
if (!NUMISSPECIAL(num)) { /* is still finite */ if (!NUMISSPECIAL(num)) { /* is still finite */
/* encode the combination field and exponent continuation */ /* encode the combination field and exponent continuation */
uInt uexp=(uInt)(num->exponent+DECBIAS); /* biased exponent */ uInt uexp=(uInt)(num->exponent+DECBIAS); /* biased exponent */
uInt code=(uexp>>DECECONL)<<4; /* top two bits of exp */ uInt code=(uexp>>DECECONL)<<4; /* top two bits of exp */
/* [msd=0] */ /* [msd==0] */
/* look up the combination field and make high word */ /* look up the combination field and make high word */
encode=DECCOMBFROM[code]; /* indexed by (0-2)*16+msd */ encode=DECCOMBFROM[code]; /* indexed by (0-2)*16+msd */
encode|=(uexp<<(32-6-DECECONL)) & 0x03ffffff; /* exponent continuation */ encode|=(uexp<<(32-6-DECECONL)) & 0x03ffffff; /* exponent continuation */
} }
else encode=num->exponent; /* special [already in word] */ else encode=num->exponent; /* special [already in word] */
/* [coefficient length here will be < DECPMAX] */
encode|=num->sign; /* add sign */ encode|=num->sign; /* add sign */
/* private macro to extract a declet, n (where 0<=n<DECLETS and 0 */ /* private macro to extract a declet, n (where 0<=n<DECLETS and 0 */
...@@ -519,7 +522,7 @@ static decFloat * decFinalize(decFloat *df, bcdnum *num, ...@@ -519,7 +522,7 @@ static decFloat * decFinalize(decFloat *df, bcdnum *num,
/* working pointer, uInt *ub. */ /* working pointer, uInt *ub. */
/* As not full-length then chances are there are many leading zeros */ /* As not full-length then chances are there are many leading zeros */
/* [and there may be a partial triad] */ /* [and there may be a partial triad] */
#define getDPD(dpd, n) ub=ulsd-(3*(n))-2; \ #define getDPDt(dpd, n) ub=ulsd-(3*(n))-2; \
if (ub<umsd-2) dpd=0; \ if (ub<umsd-2) dpd=0; \
else if (ub>=umsd) dpd=BCD2DPD[(*ub*256)+(*(ub+1)*16)+*(ub+2)]; \ else if (ub>=umsd) dpd=BCD2DPD[(*ub*256)+(*(ub+1)*16)+*(ub+2)]; \
else {dpd=*(ub+2); if (ub+1==umsd) dpd+=*(ub+1)*16; dpd=BCD2DPD[dpd];} else {dpd=*(ub+2); if (ub+1==umsd) dpd+=*(ub+1)*16; dpd=BCD2DPD[dpd];}
...@@ -528,48 +531,48 @@ static decFloat * decFinalize(decFloat *df, bcdnum *num, ...@@ -528,48 +531,48 @@ static decFloat * decFinalize(decFloat *df, bcdnum *num,
/* according to endianness; in all cases complete the sign word */ /* according to endianness; in all cases complete the sign word */
/* first */ /* first */
#if DECPMAX==7 #if DECPMAX==7
getDPD(dpd, 1); getDPDt(dpd, 1);
encode|=dpd<<10; encode|=dpd<<10;
getDPD(dpd, 0); getDPDt(dpd, 0);
encode|=dpd; encode|=dpd;
DFWORD(df, 0)=encode; /* just the one word */ DFWORD(df, 0)=encode; /* just the one word */
#elif DECPMAX==16 #elif DECPMAX==16
getDPD(dpd, 4); encode|=dpd<<8; getDPDt(dpd, 4); encode|=dpd<<8;
getDPD(dpd, 3); encode|=dpd>>2; getDPDt(dpd, 3); encode|=dpd>>2;
DFWORD(df, 0)=encode; DFWORD(df, 0)=encode;
encode=dpd<<30; encode=dpd<<30;
getDPD(dpd, 2); encode|=dpd<<20; getDPDt(dpd, 2); encode|=dpd<<20;
getDPD(dpd, 1); encode|=dpd<<10; getDPDt(dpd, 1); encode|=dpd<<10;
getDPD(dpd, 0); encode|=dpd; getDPDt(dpd, 0); encode|=dpd;
DFWORD(df, 1)=encode; DFWORD(df, 1)=encode;
#elif DECPMAX==34 #elif DECPMAX==34
getDPD(dpd,10); encode|=dpd<<4; getDPDt(dpd,10); encode|=dpd<<4;
getDPD(dpd, 9); encode|=dpd>>6; getDPDt(dpd, 9); encode|=dpd>>6;
DFWORD(df, 0)=encode; DFWORD(df, 0)=encode;
encode=dpd<<26; encode=dpd<<26;
getDPD(dpd, 8); encode|=dpd<<16; getDPDt(dpd, 8); encode|=dpd<<16;
getDPD(dpd, 7); encode|=dpd<<6; getDPDt(dpd, 7); encode|=dpd<<6;
getDPD(dpd, 6); encode|=dpd>>4; getDPDt(dpd, 6); encode|=dpd>>4;
DFWORD(df, 1)=encode; DFWORD(df, 1)=encode;
encode=dpd<<28; encode=dpd<<28;
getDPD(dpd, 5); encode|=dpd<<18; getDPDt(dpd, 5); encode|=dpd<<18;
getDPD(dpd, 4); encode|=dpd<<8; getDPDt(dpd, 4); encode|=dpd<<8;
getDPD(dpd, 3); encode|=dpd>>2; getDPDt(dpd, 3); encode|=dpd>>2;
DFWORD(df, 2)=encode; DFWORD(df, 2)=encode;
encode=dpd<<30; encode=dpd<<30;
getDPD(dpd, 2); encode|=dpd<<20; getDPDt(dpd, 2); encode|=dpd<<20;
getDPD(dpd, 1); encode|=dpd<<10; getDPDt(dpd, 1); encode|=dpd<<10;
getDPD(dpd, 0); encode|=dpd; getDPDt(dpd, 0); encode|=dpd;
DFWORD(df, 3)=encode; DFWORD(df, 3)=encode;
#endif #endif
/* printf("Status: %08lx\n", (LI)set->status); */ /* printf("Status: %08lx\n", (LI)set->status); */
/* decFloatShow(df, "final"); */ /* decFloatShow(df, "final2"); */
return df; return df;
} /* decFinalize */ } /* decFinalize */
...@@ -579,12 +582,12 @@ static decFloat * decFinalize(decFloat *df, bcdnum *num, ...@@ -579,12 +582,12 @@ static decFloat * decFinalize(decFloat *df, bcdnum *num,
/* df is the target decFloat */ /* df is the target decFloat */
/* exp is the in-range unbiased exponent, q, or a special value in */ /* exp is the in-range unbiased exponent, q, or a special value in */
/* the form returned by decFloatGetExponent */ /* the form returned by decFloatGetExponent */
/* bcdar holds DECPMAX digits to set the coefficient from, one */ /* bcdar holds DECPMAX digits to set the coefficient from, one */
/* digit in each byte (BCD8 encoding); the first (MSD) is ignored */ /* digit in each byte (BCD8 encoding); the first (MSD) is ignored */
/* if df is a NaN; all are ignored if df is infinite. */ /* if df is a NaN; all are ignored if df is infinite. */
/* All bytes must be in 0-9; results undefined otherwise. */ /* All bytes must be in 0-9; results are undefined otherwise. */
/* sig is DECFLOAT_Sign to set the sign bit, 0 otherwise */ /* sig is DECFLOAT_Sign to set the sign bit, 0 otherwise */
/* returns df, which will be canonical */ /* returns df, which will be canonical */
/* */ /* */
/* No error is possible, and no status will be set. */ /* No error is possible, and no status will be set. */
/* ------------------------------------------------------------------ */ /* ------------------------------------------------------------------ */
...@@ -609,53 +612,53 @@ decFloat * decFloatFromBCD(decFloat *df, Int exp, const uByte *bcdar, ...@@ -609,53 +612,53 @@ decFloat * decFloatFromBCD(decFloat *df, Int exp, const uByte *bcdar,
/* and put the corresponding DPD code into dpd. */ /* and put the corresponding DPD code into dpd. */
/* Use of a working pointer, uInt *ub, is assumed. */ /* Use of a working pointer, uInt *ub, is assumed. */
#define getDPDf(dpd, n) ub=bcdar+DECPMAX-1-(3*(n))-2; \ #define getDPDb(dpd, n) ub=bcdar+DECPMAX-1-(3*(n))-2; \
dpd=BCD2DPD[(*ub*256)+(*(ub+1)*16)+*(ub+2)]; dpd=BCD2DPD[(*ub*256)+(*(ub+1)*16)+*(ub+2)];
/* place the declets in the encoding words and copy to result (df), */ /* place the declets in the encoding words and copy to result (df), */
/* according to endianness; in all cases complete the sign word */ /* according to endianness; in all cases complete the sign word */
/* first */ /* first */
#if DECPMAX==7 #if DECPMAX==7
getDPDf(dpd, 1); getDPDb(dpd, 1);
encode|=dpd<<10; encode|=dpd<<10;
getDPDf(dpd, 0); getDPDb(dpd, 0);
encode|=dpd; encode|=dpd;
DFWORD(df, 0)=encode; /* just the one word */ DFWORD(df, 0)=encode; /* just the one word */
#elif DECPMAX==16 #elif DECPMAX==16
getDPDf(dpd, 4); encode|=dpd<<8; getDPDb(dpd, 4); encode|=dpd<<8;
getDPDf(dpd, 3); encode|=dpd>>2; getDPDb(dpd, 3); encode|=dpd>>2;
DFWORD(df, 0)=encode; DFWORD(df, 0)=encode;
encode=dpd<<30; encode=dpd<<30;
getDPDf(dpd, 2); encode|=dpd<<20; getDPDb(dpd, 2); encode|=dpd<<20;
getDPDf(dpd, 1); encode|=dpd<<10; getDPDb(dpd, 1); encode|=dpd<<10;
getDPDf(dpd, 0); encode|=dpd; getDPDb(dpd, 0); encode|=dpd;
DFWORD(df, 1)=encode; DFWORD(df, 1)=encode;
#elif DECPMAX==34 #elif DECPMAX==34
getDPDf(dpd,10); encode|=dpd<<4; getDPDb(dpd,10); encode|=dpd<<4;
getDPDf(dpd, 9); encode|=dpd>>6; getDPDb(dpd, 9); encode|=dpd>>6;
DFWORD(df, 0)=encode; DFWORD(df, 0)=encode;
encode=dpd<<26; encode=dpd<<26;
getDPDf(dpd, 8); encode|=dpd<<16; getDPDb(dpd, 8); encode|=dpd<<16;
getDPDf(dpd, 7); encode|=dpd<<6; getDPDb(dpd, 7); encode|=dpd<<6;
getDPDf(dpd, 6); encode|=dpd>>4; getDPDb(dpd, 6); encode|=dpd>>4;
DFWORD(df, 1)=encode; DFWORD(df, 1)=encode;
encode=dpd<<28; encode=dpd<<28;
getDPDf(dpd, 5); encode|=dpd<<18; getDPDb(dpd, 5); encode|=dpd<<18;
getDPDf(dpd, 4); encode|=dpd<<8; getDPDb(dpd, 4); encode|=dpd<<8;
getDPDf(dpd, 3); encode|=dpd>>2; getDPDb(dpd, 3); encode|=dpd>>2;
DFWORD(df, 2)=encode; DFWORD(df, 2)=encode;
encode=dpd<<30; encode=dpd<<30;
getDPDf(dpd, 2); encode|=dpd<<20; getDPDb(dpd, 2); encode|=dpd<<20;
getDPDf(dpd, 1); encode|=dpd<<10; getDPDb(dpd, 1); encode|=dpd<<10;
getDPDf(dpd, 0); encode|=dpd; getDPDb(dpd, 0); encode|=dpd;
DFWORD(df, 3)=encode; DFWORD(df, 3)=encode;
#endif #endif
/* decFloatShow(df, "final"); */ /* decFloatShow(df, "fromB"); */
return df; return df;
} /* decFloatFromBCD */ } /* decFloatFromBCD */
...@@ -671,7 +674,7 @@ decFloat * decFloatFromBCD(decFloat *df, Int exp, const uByte *bcdar, ...@@ -671,7 +674,7 @@ decFloat * decFloatFromBCD(decFloat *df, Int exp, const uByte *bcdar,
/* and QUAD the first (pad) nibble is also ignored in all cases. */ /* and QUAD the first (pad) nibble is also ignored in all cases. */
/* All coefficient nibbles must be in 0-9 and sign in A-F; results */ /* All coefficient nibbles must be in 0-9 and sign in A-F; results */
/* are undefined otherwise. */ /* are undefined otherwise. */
/* returns df, which will be canonical */ /* returns df, which will be canonical */
/* */ /* */
/* No error is possible, and no status will be set. */ /* No error is possible, and no status will be set. */
/* ------------------------------------------------------------------ */ /* ------------------------------------------------------------------ */
...@@ -691,7 +694,7 @@ decFloat * decFloatFromPacked(decFloat *df, Int exp, const uByte *packed) { ...@@ -691,7 +694,7 @@ decFloat * decFloatFromPacked(decFloat *df, Int exp, const uByte *packed) {
*op++=*ip>>4; *op++=*ip>>4;
*op++=(uByte)(*ip&0x0f); /* [final nibble is sign] */ *op++=(uByte)(*ip&0x0f); /* [final nibble is sign] */
} }
op--; /* -> sign byte */ op--; /* -> sign byte */
if (*op==DECPMINUS || *op==DECPMINUSALT) sig=DECFLOAT_Sign; if (*op==DECPMINUS || *op==DECPMINUSALT) sig=DECFLOAT_Sign;
if (EXPISSPECIAL(exp)) { /* Infinity or NaN */ if (EXPISSPECIAL(exp)) { /* Infinity or NaN */
...@@ -702,7 +705,71 @@ decFloat * decFloatFromPacked(decFloat *df, Int exp, const uByte *packed) { ...@@ -702,7 +705,71 @@ decFloat * decFloatFromPacked(decFloat *df, Int exp, const uByte *packed) {
} /* decFloatFromPacked */ } /* decFloatFromPacked */
/* ------------------------------------------------------------------ */ /* ------------------------------------------------------------------ */
/* decFloatFromString -- conversion from numeric string */ /* decFloatFromPackedChecked -- set from exponent and packed; checked */
/* */
/* df is the target decFloat */
/* exp is the in-range unbiased exponent, q, or a special value in */
/* the form returned by decFloatGetExponent */
/* packed holds DECPMAX packed decimal digits plus a sign nibble */
/* (all 6 codes are OK); the first (MSD) must be 0 if df is a NaN */
/* and all digits must be 0 if df is infinite. For DOUBLE and */
/* QUAD the first (pad) nibble must be 0. */
/* All coefficient nibbles must be in 0-9 and sign in A-F. */
/* returns df, which will be canonical or NULL if any of the */
/* requirements are not met (if this case df is unchanged); that */
/* is, the input data must be as returned by decFloatToPacked, */
/* except that all six sign codes are acccepted. */
/* */
/* No status will be set. */
/* ------------------------------------------------------------------ */
decFloat * decFloatFromPackedChecked(decFloat *df, Int exp,
const uByte *packed) {
uByte bcdar[DECPMAX+2]; /* work [+1 for pad, +1 for sign] */
const uByte *ip; /* .. */
uByte *op; /* .. */
Int sig=0; /* sign */
/* expand coefficient and sign to BCDAR */
#if SINGLE
op=bcdar+1; /* no pad digit */
#else
op=bcdar; /* first (pad) digit here */
#endif
for (ip=packed; ip<packed+((DECPMAX+2)/2); ip++) {
*op=*ip>>4;
if (*op>9) return NULL;
op++;
*op=(uByte)(*ip&0x0f); /* [final nibble is sign] */
if (*op>9 && ip<packed+((DECPMAX+2)/2)-1) return NULL;
op++;
}
op--; /* -> sign byte */
if (*op<=9) return NULL; /* bad sign */
if (*op==DECPMINUS || *op==DECPMINUSALT) sig=DECFLOAT_Sign;
#if !SINGLE
if (bcdar[0]!=0) return NULL; /* bad pad nibble */
#endif
if (EXPISNAN(exp)) { /* a NaN */
if (bcdar[1]!=0) return NULL; /* bad msd */
} /* NaN */
else if (EXPISINF(exp)) { /* is infinite */
Int i;
for (i=0; i<DECPMAX; i++) {
if (bcdar[i+1]!=0) return NULL; /* should be all zeros */
}
} /* infinity */
else { /* finite */
/* check the exponent is in range */
if (exp>DECEMAX-DECPMAX+1) return NULL;
if (exp<DECEMIN-DECPMAX+1) return NULL;
}
return decFloatFromBCD(df, exp, bcdar+1, sig);
} /* decFloatFromPacked */
/* ------------------------------------------------------------------ */
/* decFloatFromString -- conversion from numeric string */
/* */ /* */
/* result is the decFloat format number which gets the result of */ /* result is the decFloat format number which gets the result of */
/* the conversion */ /* the conversion */
...@@ -710,12 +777,12 @@ decFloat * decFloatFromPacked(decFloat *df, Int exp, const uByte *packed) { ...@@ -710,12 +777,12 @@ decFloat * decFloatFromPacked(decFloat *df, Int exp, const uByte *packed) {
/* number (which may be a special value), \0-terminated */ /* number (which may be a special value), \0-terminated */
/* If there are too many significant digits in the */ /* If there are too many significant digits in the */
/* coefficient it will be rounded. */ /* coefficient it will be rounded. */
/* set is the context */ /* set is the context */
/* returns result */ /* returns result */
/* */ /* */
/* The length of the coefficient and the size of the exponent are */ /* The length of the coefficient and the size of the exponent are */
/* checked by this routine, so the correct error (Underflow or */ /* checked by this routine, so the correct error (Underflow or */
/* Overflow) can be reported or rounding applied, as necessary. */ /* Overflow) can be reported or rounding applied, as necessary. */
/* */ /* */
/* There is no limit to the coefficient length for finite inputs; */ /* There is no limit to the coefficient length for finite inputs; */
/* NaN payloads must be integers with no more than DECPMAX-1 digits. */ /* NaN payloads must be integers with no more than DECPMAX-1 digits. */
...@@ -726,20 +793,21 @@ decFloat * decFloatFromPacked(decFloat *df, Int exp, const uByte *packed) { ...@@ -726,20 +793,21 @@ decFloat * decFloatFromPacked(decFloat *df, Int exp, const uByte *packed) {
decFloat * decFloatFromString(decFloat *result, const char *string, decFloat * decFloatFromString(decFloat *result, const char *string,
decContext *set) { decContext *set) {
Int digits; /* count of digits in coefficient */ Int digits; /* count of digits in coefficient */
const char *dotchar=NULL; /* where dot was found [NULL if none] */ const char *dotchar=NULL; /* where dot was found [NULL if none] */
const char *cfirst=string; /* -> first character of decimal part */ const char *cfirst=string; /* -> first character of decimal part */
const char *c; /* work */ const char *c; /* work */
uByte *ub; /* .. */ uByte *ub; /* .. */
uInt uiwork; /* for macros */
bcdnum num; /* collects data for finishing */ bcdnum num; /* collects data for finishing */
uInt error=DEC_Conversion_syntax; /* assume the worst */ uInt error=DEC_Conversion_syntax; /* assume the worst */
uByte buffer[ROUNDUP(DECSTRING+11, 8)]; /* room for most coefficents, */ uByte buffer[ROUNDUP(DECSTRING+11, 8)]; /* room for most coefficents, */
/* some common rounding, +3, & pad */ /* some common rounding, +3, & pad */
#if DECTRACE #if DECTRACE
/* printf("FromString %s ...\n", string); */ /* printf("FromString %s ...\n", string); */
#endif #endif
for(;;) { /* once-only 'loop' */ for(;;) { /* once-only 'loop' */
num.sign=0; /* assume non-negative */ num.sign=0; /* assume non-negative */
num.msd=buffer; /* MSD is here always */ num.msd=buffer; /* MSD is here always */
/* detect and validate the coefficient, including any leading, */ /* detect and validate the coefficient, including any leading, */
...@@ -810,7 +878,7 @@ decFloat * decFloatFromString(decFloat *result, const char *string, ...@@ -810,7 +878,7 @@ decFloat * decFloatFromString(decFloat *result, const char *string,
exp-=(Int)(clast-dotchar); /* adjust exponent */ exp-=(Int)(clast-dotchar); /* adjust exponent */
/* [the '.' can now be ignored] */ /* [the '.' can now be ignored] */
} }
num.exponent=exp; /* exponent is good; store it */ num.exponent=exp; /* exponent is good; store it */
/* Here when whole string has been inspected and syntax is good */ /* Here when whole string has been inspected and syntax is good */
/* cfirst->first digit or dot, clast->last digit or dot */ /* cfirst->first digit or dot, clast->last digit or dot */
...@@ -832,8 +900,8 @@ decFloat * decFloatFromString(decFloat *result, const char *string, ...@@ -832,8 +900,8 @@ decFloat * decFloatFromString(decFloat *result, const char *string,
/* as usual, go by fours when safe; NB it has been asserted */ /* as usual, go by fours when safe; NB it has been asserted */
/* that a '.' does not have the same mask as a digit */ /* that a '.' does not have the same mask as a digit */
if (c<=clast-3 /* safe for four */ if (c<=clast-3 /* safe for four */
&& (UINTAT(c)&0xf0f0f0f0)==CHARMASK) { /* test four */ && (UBTOUI(c)&0xf0f0f0f0)==CHARMASK) { /* test four */
UINTAT(ub)=UINTAT(c)&0x0f0f0f0f; /* to BCD8 */ UBFROMUI(ub, UBTOUI(c)&0x0f0f0f0f); /* to BCD8 */
ub+=4; ub+=4;
c+=4; c+=4;
continue; continue;
...@@ -846,7 +914,7 @@ decFloat * decFloatFromString(decFloat *result, const char *string, ...@@ -846,7 +914,7 @@ decFloat * decFloatFromString(decFloat *result, const char *string,
} }
} /* had dot */ } /* had dot */
/* Now no dot; do this by fours (where safe) */ /* Now no dot; do this by fours (where safe) */
for (; c<=clast-3; c+=4, ub+=4) UINTAT(ub)=UINTAT(c)&0x0f0f0f0f; for (; c<=clast-3; c+=4, ub+=4) UBFROMUI(ub, UBTOUI(c)&0x0f0f0f0f);
for (; c<=clast; c++, ub++) *ub=(uByte)(*c-'0'); for (; c<=clast; c++, ub++) *ub=(uByte)(*c-'0');
num.lsd=buffer+digits-1; /* record new LSD */ num.lsd=buffer+digits-1; /* record new LSD */
} /* fits */ } /* fits */
...@@ -857,7 +925,7 @@ decFloat * decFloatFromString(decFloat *result, const char *string, ...@@ -857,7 +925,7 @@ decFloat * decFloatFromString(decFloat *result, const char *string,
if (*cfirst=='.') cfirst++; /* step past dot at start */ if (*cfirst=='.') cfirst++; /* step past dot at start */
if (*cfirst=='0') { /* [cfirst always -> digit] */ if (*cfirst=='0') { /* [cfirst always -> digit] */
for (; cfirst<clast; cfirst++) { for (; cfirst<clast; cfirst++) {
if (*cfirst!='0') { /* non-zero found */ if (*cfirst!='0') { /* non-zero found */
if (*cfirst=='.') continue; /* [ignore] */ if (*cfirst=='.') continue; /* [ignore] */
break; /* done */ break; /* done */
} }
...@@ -871,8 +939,8 @@ decFloat * decFloatFromString(decFloat *result, const char *string, ...@@ -871,8 +939,8 @@ decFloat * decFloatFromString(decFloat *result, const char *string,
for (c=cfirst; c<=clast && ub<=buffer+DECPMAX; c++) { for (c=cfirst; c<=clast && ub<=buffer+DECPMAX; c++) {
/* (see commentary just above) */ /* (see commentary just above) */
if (c<=clast-3 /* safe for four */ if (c<=clast-3 /* safe for four */
&& (UINTAT(c)&0xf0f0f0f0)==CHARMASK) { /* four digits */ && (UBTOUI(c)&0xf0f0f0f0)==CHARMASK) { /* four digits */
UINTAT(ub)=UINTAT(c)&0x0f0f0f0f; /* to BCD8 */ UBFROMUI(ub, UBTOUI(c)&0x0f0f0f0f); /* to BCD8 */
ub+=4; ub+=4;
c+=3; /* [will become 4] */ c+=3; /* [will become 4] */
continue; continue;
...@@ -881,7 +949,7 @@ decFloat * decFloatFromString(decFloat *result, const char *string, ...@@ -881,7 +949,7 @@ decFloat * decFloatFromString(decFloat *result, const char *string,
*ub++=(uByte)(*c-'0'); *ub++=(uByte)(*c-'0');
} }
ub--; /* -> LSD */ ub--; /* -> LSD */
for (; c<=clast; c++) { /* inspect remaining chars */ for (; c<=clast; c++) { /* inspect remaining chars */
if (*c!='0') { /* sticky bit needed */ if (*c!='0') { /* sticky bit needed */
if (*c=='.') continue; /* [ignore] */ if (*c=='.') continue; /* [ignore] */
*ub=DECSTICKYTAB[*ub]; /* update round-for-reround */ *ub=DECSTICKYTAB[*ub]; /* update round-for-reround */
...@@ -925,7 +993,7 @@ decFloat * decFloatFromString(decFloat *result, const char *string, ...@@ -925,7 +993,7 @@ decFloat * decFloatFromString(decFloat *result, const char *string,
*ub=(uByte)(*c-'0'); /* good bcd8 */ *ub=(uByte)(*c-'0'); /* good bcd8 */
} }
if (*c!='\0') break; /* not all digits, or too many */ if (*c!='\0') break; /* not all digits, or too many */
num.lsd=ub-1; /* record new LSD */ num.lsd=ub-1; /* record new LSD */
} }
} /* NaN or sNaN */ } /* NaN or sNaN */
error=0; /* syntax is OK */ error=0; /* syntax is OK */
...@@ -938,8 +1006,8 @@ decFloat * decFloatFromString(decFloat *result, const char *string, ...@@ -938,8 +1006,8 @@ decFloat * decFloatFromString(decFloat *result, const char *string,
if (error!=0) { if (error!=0) {
set->status|=error; set->status|=error;
num.exponent=DECFLOAT_qNaN; /* set up quiet NaN */ num.exponent=DECFLOAT_qNaN; /* set up quiet NaN */
num.sign=0; /* .. with 0 sign */ num.sign=0; /* .. with 0 sign */
buffer[0]=0; /* .. and coefficient */ buffer[0]=0; /* .. and coefficient */
num.lsd=buffer; /* .. */ num.lsd=buffer; /* .. */
/* decShowNum(&num, "oops"); */ /* decShowNum(&num, "oops"); */
...@@ -957,7 +1025,7 @@ decFloat * decFloatFromString(decFloat *result, const char *string, ...@@ -957,7 +1025,7 @@ decFloat * decFloatFromString(decFloat *result, const char *string,
/* result is the decFloat format number which gets the result of */ /* result is the decFloat format number which gets the result of */
/* the conversion */ /* the conversion */
/* wider is the decFloatWider format number which will be narrowed */ /* wider is the decFloatWider format number which will be narrowed */
/* set is the context */ /* set is the context */
/* returns result */ /* returns result */
/* */ /* */
/* Narrowing can cause rounding, overflow, etc., but not Invalid */ /* Narrowing can cause rounding, overflow, etc., but not Invalid */
...@@ -968,7 +1036,7 @@ decFloat * decFloatFromString(decFloat *result, const char *string, ...@@ -968,7 +1036,7 @@ decFloat * decFloatFromString(decFloat *result, const char *string,
decFloat * decFloatFromWider(decFloat *result, const decFloatWider *wider, decFloat * decFloatFromWider(decFloat *result, const decFloatWider *wider,
decContext *set) { decContext *set) {
bcdnum num; /* collects data for finishing */ bcdnum num; /* collects data for finishing */
uByte bcdar[DECWPMAX]; /* room for wider coefficient */ uByte bcdar[DECWPMAX]; /* room for wider coefficient */
uInt widerhi=DFWWORD(wider, 0); /* top word */ uInt widerhi=DFWWORD(wider, 0); /* top word */
Int exp; Int exp;
...@@ -979,7 +1047,7 @@ decFloat * decFloatFromWider(decFloat *result, const decFloatWider *wider, ...@@ -979,7 +1047,7 @@ decFloat * decFloatFromWider(decFloat *result, const decFloatWider *wider,
num.sign=widerhi&0x80000000; /* extract sign [DECFLOAT_Sign=Neg] */ num.sign=widerhi&0x80000000; /* extract sign [DECFLOAT_Sign=Neg] */
/* decode the wider combination field to exponent */ /* decode the wider combination field to exponent */
exp=DECCOMBWEXP[widerhi>>26]; /* decode from wider combination field */ exp=DECCOMBWEXP[widerhi>>26]; /* decode from wider combination field */
/* if it is a special there's nothing to do unless sNaN; if it's */ /* if it is a special there's nothing to do unless sNaN; if it's */
/* finite then add the (wider) exponent continuation and unbias */ /* finite then add the (wider) exponent continuation and unbias */
if (EXPISSPECIAL(exp)) exp=widerhi&0x7e000000; /* include sNaN selector */ if (EXPISSPECIAL(exp)) exp=widerhi&0x7e000000; /* include sNaN selector */
...@@ -1001,7 +1069,7 @@ decFloat * decFloatFromWider(decFloat *result, const decFloatWider *wider, ...@@ -1001,7 +1069,7 @@ decFloat * decFloatFromWider(decFloat *result, const decFloatWider *wider,
/* returns the sign of the coefficient (DECFLOAT_Sign if negative, */ /* returns the sign of the coefficient (DECFLOAT_Sign if negative, */
/* 0 otherwise) */ /* 0 otherwise) */
/* */ /* */
/* No error is possible, and no status will be set. If df is a */ /* No error is possible, and no status will be set. If df is a */
/* special value the array is set to zeros (for Infinity) or to the */ /* special value the array is set to zeros (for Infinity) or to the */
/* payload of a qNaN or sNaN. */ /* payload of a qNaN or sNaN. */
/* ------------------------------------------------------------------ */ /* ------------------------------------------------------------------ */
...@@ -1015,12 +1083,12 @@ Int decFloatGetCoefficient(const decFloat *df, uByte *bcdar) { ...@@ -1015,12 +1083,12 @@ Int decFloatGetCoefficient(const decFloat *df, uByte *bcdar) {
} /* decFloatGetCoefficient */ } /* decFloatGetCoefficient */
/* ------------------------------------------------------------------ */ /* ------------------------------------------------------------------ */
/* decFloatGetExponent -- get unbiased exponent */ /* decFloatGetExponent -- get unbiased exponent */
/* */ /* */
/* df is the decFloat from which to extract the exponent */ /* df is the decFloat from which to extract the exponent */
/* returns the exponent, q. */ /* returns the exponent, q. */
/* */ /* */
/* No error is possible, and no status will be set. If df is a */ /* No error is possible, and no status will be set. If df is a */
/* special value the first seven bits of the decFloat are returned, */ /* special value the first seven bits of the decFloat are returned, */
/* left adjusted and with the first (sign) bit set to 0 (followed by */ /* left adjusted and with the first (sign) bit set to 0 (followed by */
/* 25 0 bits). e.g., -sNaN would return 0x7e000000 (DECFLOAT_sNaN). */ /* 25 0 bits). e.g., -sNaN would return 0x7e000000 (DECFLOAT_sNaN). */
...@@ -1034,11 +1102,11 @@ Int decFloatGetExponent(const decFloat *df) { ...@@ -1034,11 +1102,11 @@ Int decFloatGetExponent(const decFloat *df) {
/* decFloatSetCoefficient -- set coefficient from BCD8 */ /* decFloatSetCoefficient -- set coefficient from BCD8 */
/* */ /* */
/* df is the target decFloat (and source of exponent/special value) */ /* df is the target decFloat (and source of exponent/special value) */
/* bcdar holds DECPMAX digits to set the coefficient from, one */ /* bcdar holds DECPMAX digits to set the coefficient from, one */
/* digit in each byte (BCD8 encoding); the first (MSD) is ignored */ /* digit in each byte (BCD8 encoding); the first (MSD) is ignored */
/* if df is a NaN; all are ignored if df is infinite. */ /* if df is a NaN; all are ignored if df is infinite. */
/* sig is DECFLOAT_Sign to set the sign bit, 0 otherwise */ /* sig is DECFLOAT_Sign to set the sign bit, 0 otherwise */
/* returns df, which will be canonical */ /* returns df, which will be canonical */
/* */ /* */
/* No error is possible, and no status will be set. */ /* No error is possible, and no status will be set. */
/* ------------------------------------------------------------------ */ /* ------------------------------------------------------------------ */
...@@ -1060,18 +1128,18 @@ decFloat * decFloatSetCoefficient(decFloat *df, const uByte *bcdar, ...@@ -1060,18 +1128,18 @@ decFloat * decFloatSetCoefficient(decFloat *df, const uByte *bcdar,
} /* decFloatSetCoefficient */ } /* decFloatSetCoefficient */
/* ------------------------------------------------------------------ */ /* ------------------------------------------------------------------ */
/* decFloatSetExponent -- set exponent or special value */ /* decFloatSetExponent -- set exponent or special value */
/* */ /* */
/* df is the target decFloat (and source of coefficient/payload) */ /* df is the target decFloat (and source of coefficient/payload) */
/* set is the context for reporting status */ /* set is the context for reporting status */
/* exp is the unbiased exponent, q, or a special value in the form */ /* exp is the unbiased exponent, q, or a special value in the form */
/* returned by decFloatGetExponent */ /* returned by decFloatGetExponent */
/* returns df, which will be canonical */ /* returns df, which will be canonical */
/* */ /* */
/* No error is possible, but Overflow or Underflow might occur. */ /* No error is possible, but Overflow or Underflow might occur. */
/* ------------------------------------------------------------------ */ /* ------------------------------------------------------------------ */
decFloat * decFloatSetExponent(decFloat *df, decContext *set, Int exp) { decFloat * decFloatSetExponent(decFloat *df, decContext *set, Int exp) {
uByte bcdcopy[DECPMAX]; /* for coefficient */ uByte bcdcopy[DECPMAX]; /* for coefficient */
bcdnum num; /* work */ bcdnum num; /* work */
num.exponent=exp; num.exponent=exp;
num.sign=decFloatGetCoefficient(df, bcdcopy); /* extract coefficient */ num.sign=decFloatGetCoefficient(df, bcdcopy); /* extract coefficient */
...@@ -1095,15 +1163,15 @@ uInt decFloatRadix(const decFloat *df) { ...@@ -1095,15 +1163,15 @@ uInt decFloatRadix(const decFloat *df) {
} /* decFloatRadix */ } /* decFloatRadix */
/* ------------------------------------------------------------------ */ /* ------------------------------------------------------------------ */
/* decFloatShow -- printf a decFloat in hexadecimal and decimal */ /* decFloatShow -- printf a decFloat in hexadecimal and decimal */
/* df is the decFloat to show */ /* df is the decFloat to show */
/* tag is a tag string displayed with the number */ /* tag is a tag string displayed with the number */
/* */ /* */
/* This is a debug aid; the precise format of the string may change. */ /* This is a debug aid; the precise format of the string may change. */
/* ------------------------------------------------------------------ */ /* ------------------------------------------------------------------ */
void decFloatShow(const decFloat *df, const char *tag) { void decFloatShow(const decFloat *df, const char *tag) {
char hexbuf[DECBYTES*2+DECBYTES/4+1]; /* NB blank after every fourth */ char hexbuf[DECBYTES*2+DECBYTES/4+1]; /* NB blank after every fourth */
char buff[DECSTRING]; /* for value in decimal */ char buff[DECSTRING]; /* for value in decimal */
Int i, j=0; Int i, j=0;
for (i=0; i<DECBYTES; i++) { for (i=0; i<DECBYTES; i++) {
...@@ -1126,7 +1194,7 @@ void decFloatShow(const decFloat *df, const char *tag) { ...@@ -1126,7 +1194,7 @@ void decFloatShow(const decFloat *df, const char *tag) {
/* */ /* */
/* df is the source decFloat */ /* df is the source decFloat */
/* exp will be set to the unbiased exponent, q, or to a special */ /* exp will be set to the unbiased exponent, q, or to a special */
/* value in the form returned by decFloatGetExponent */ /* value in the form returned by decFloatGetExponent */
/* bcdar is where DECPMAX bytes will be written, one BCD digit in */ /* bcdar is where DECPMAX bytes will be written, one BCD digit in */
/* each byte (BCD8 encoding); if df is a NaN the first byte will */ /* each byte (BCD8 encoding); if df is a NaN the first byte will */
/* be zero, and if it is infinite they will all be zero */ /* be zero, and if it is infinite they will all be zero */
...@@ -1156,7 +1224,7 @@ Int decFloatToBCD(const decFloat *df, Int *exp, uByte *bcdar) { ...@@ -1156,7 +1224,7 @@ Int decFloatToBCD(const decFloat *df, Int *exp, uByte *bcdar) {
/* ------------------------------------------------------------------ */ /* ------------------------------------------------------------------ */
/* decFloatToEngString -- conversion to numeric string, engineering */ /* decFloatToEngString -- conversion to numeric string, engineering */
/* */ /* */
/* df is the decFloat format number to convert */ /* df is the decFloat format number to convert */
/* string is the string where the result will be laid out */ /* string is the string where the result will be laid out */
/* */ /* */
/* string must be at least DECPMAX+9 characters (the worst case is */ /* string must be at least DECPMAX+9 characters (the worst case is */
...@@ -1169,11 +1237,14 @@ char * decFloatToEngString(const decFloat *df, char *string){ ...@@ -1169,11 +1237,14 @@ char * decFloatToEngString(const decFloat *df, char *string){
uInt msd; /* coefficient MSD */ uInt msd; /* coefficient MSD */
Int exp; /* exponent top two bits or full */ Int exp; /* exponent top two bits or full */
uInt comb; /* combination field */ uInt comb; /* combination field */
char *cstart; /* coefficient start */ char *cstart; /* coefficient start */
char *c; /* output pointer in string */ char *c; /* output pointer in string */
char *s, *t; /* .. (source, target) */ char *s, *t; /* .. (source, target) */
Int pre, e; /* work */ Int pre, e; /* work */
const uByte *u; /* .. */ const uByte *u; /* .. */
uInt uiwork; /* for macros [one compiler needs */
/* volatile here to avoid bug, but */
/* that doubles execution time] */
/* Source words; macro handles endianness */ /* Source words; macro handles endianness */
uInt sourhi=DFWORD(df, 0); /* word with sign */ uInt sourhi=DFWORD(df, 0); /* word with sign */
...@@ -1188,12 +1259,12 @@ char * decFloatToEngString(const decFloat *df, char *string){ ...@@ -1188,12 +1259,12 @@ char * decFloatToEngString(const decFloat *df, char *string){
c=string; /* where result will go */ c=string; /* where result will go */
if (((Int)sourhi)<0) *c++='-'; /* handle sign */ if (((Int)sourhi)<0) *c++='-'; /* handle sign */
comb=sourhi>>26; /* sign+combination field */ comb=sourhi>>26; /* sign+combination field */
msd=DECCOMBMSD[comb]; /* decode the combination field */ msd=DECCOMBMSD[comb]; /* decode the combination field */
exp=DECCOMBEXP[comb]; /* .. */ exp=DECCOMBEXP[comb]; /* .. */
if (EXPISSPECIAL(exp)) { /* special */ if (EXPISSPECIAL(exp)) { /* special */
if (exp==DECFLOAT_Inf) { /* infinity */ if (exp==DECFLOAT_Inf) { /* infinity */
strcpy(c, "Inf"); strcpy(c, "Inf");
strcpy(c+3, "inity"); strcpy(c+3, "inity");
return string; /* easy */ return string; /* easy */
} }
...@@ -1225,44 +1296,44 @@ char * decFloatToEngString(const decFloat *df, char *string){ ...@@ -1225,44 +1296,44 @@ char * decFloatToEngString(const decFloat *df, char *string){
/* are the three encoded BCD8 digits followed by a 1-byte length */ /* are the three encoded BCD8 digits followed by a 1-byte length */
/* (significant digits, except that 000 has length 0). This allows */ /* (significant digits, except that 000 has length 0). This allows */
/* us to left-align the first declet with non-zero content, then */ /* us to left-align the first declet with non-zero content, then */
/* the remaining ones are full 3-char length. Fixed-length copies */ /* the remaining ones are full 3-char length. Fixed-length copies */
/* are used because variable-length memcpy causes a subroutine call */ /* are used because variable-length memcpy causes a subroutine call */
/* in at least two compilers. (The copies are length 4 for speed */ /* in at least two compilers. (The copies are length 4 for speed */
/* and are safe because the last item in the array is of length */ /* and are safe because the last item in the array is of length */
/* three and has the length byte following.) */ /* three and has the length byte following.) */
#define dpd2char(dpdin) u=&DPD2BCD8[((dpdin)&0x3ff)*4]; \ #define dpd2char(dpdin) u=&DPD2BCD8[((dpdin)&0x3ff)*4]; \
if (c!=cstart) {UINTAT(c)=UINTAT(u)|CHARMASK; c+=3;} \ if (c!=cstart) {UBFROMUI(c, UBTOUI(u)|CHARMASK); c+=3;} \
else if (*(u+3)) { \ else if (*(u+3)) { \
UINTAT(c)=UINTAT(u+3-*(u+3))|CHARMASK; c+=*(u+3);} UBFROMUI(c, UBTOUI(u+3-*(u+3))|CHARMASK); c+=*(u+3);}
#if DECPMAX==7 #if DECPMAX==7
dpd2char(sourhi>>10); /* declet 1 */ dpd2char(sourhi>>10); /* declet 1 */
dpd2char(sourhi); /* declet 2 */ dpd2char(sourhi); /* declet 2 */
#elif DECPMAX==16 #elif DECPMAX==16
dpd2char(sourhi>>8); /* declet 1 */ dpd2char(sourhi>>8); /* declet 1 */
dpd2char((sourhi<<2) | (sourlo>>30)); /* declet 2 */ dpd2char((sourhi<<2) | (sourlo>>30)); /* declet 2 */
dpd2char(sourlo>>20); /* declet 3 */ dpd2char(sourlo>>20); /* declet 3 */
dpd2char(sourlo>>10); /* declet 4 */ dpd2char(sourlo>>10); /* declet 4 */
dpd2char(sourlo); /* declet 5 */ dpd2char(sourlo); /* declet 5 */
#elif DECPMAX==34 #elif DECPMAX==34
dpd2char(sourhi>>4); /* declet 1 */ dpd2char(sourhi>>4); /* declet 1 */
dpd2char((sourhi<<6) | (sourmh>>26)); /* declet 2 */ dpd2char((sourhi<<6) | (sourmh>>26)); /* declet 2 */
dpd2char(sourmh>>16); /* declet 3 */ dpd2char(sourmh>>16); /* declet 3 */
dpd2char(sourmh>>6); /* declet 4 */ dpd2char(sourmh>>6); /* declet 4 */
dpd2char((sourmh<<4) | (sourml>>28)); /* declet 5 */ dpd2char((sourmh<<4) | (sourml>>28)); /* declet 5 */
dpd2char(sourml>>18); /* declet 6 */ dpd2char(sourml>>18); /* declet 6 */
dpd2char(sourml>>8); /* declet 7 */ dpd2char(sourml>>8); /* declet 7 */
dpd2char((sourml<<2) | (sourlo>>30)); /* declet 8 */ dpd2char((sourml<<2) | (sourlo>>30)); /* declet 8 */
dpd2char(sourlo>>20); /* declet 9 */ dpd2char(sourlo>>20); /* declet 9 */
dpd2char(sourlo>>10); /* declet 10 */ dpd2char(sourlo>>10); /* declet 10 */
dpd2char(sourlo); /* declet 11 */ dpd2char(sourlo); /* declet 11 */
#endif #endif
if (c==cstart) *c++='0'; /* all zeros, empty -- make "0" */ if (c==cstart) *c++='0'; /* all zeros, empty -- make "0" */
if (exp==0) { /* integer or NaN case -- easy */ if (exp==0) { /* integer or NaN case -- easy */
*c='\0'; /* terminate */ *c='\0'; /* terminate */
return string; return string;
} }
...@@ -1275,7 +1346,7 @@ char * decFloatToEngString(const decFloat *df, char *string){ ...@@ -1275,7 +1346,7 @@ char * decFloatToEngString(const decFloat *df, char *string){
if (exp>0 || pre<-5) { /* need exponential form */ if (exp>0 || pre<-5) { /* need exponential form */
e=pre-1; /* calculate E value */ e=pre-1; /* calculate E value */
pre=1; /* assume one digit before '.' */ pre=1; /* assume one digit before '.' */
if (e!=0) { /* engineering: may need to adjust */ if (e!=0) { /* engineering: may need to adjust */
Int adj; /* adjustment */ Int adj; /* adjustment */
/* The C remainder operator is undefined for negative numbers, so */ /* The C remainder operator is undefined for negative numbers, so */
/* a positive remainder calculation must be used here */ /* a positive remainder calculation must be used here */
...@@ -1310,8 +1381,8 @@ char * decFloatToEngString(const decFloat *df, char *string){ ...@@ -1310,8 +1381,8 @@ char * decFloatToEngString(const decFloat *df, char *string){
/* because there is still space for exponent */ /* because there is still space for exponent */
s=dotat+ROUNDDOWN4(c-dotat); /* source */ s=dotat+ROUNDDOWN4(c-dotat); /* source */
t=s+1; /* target */ t=s+1; /* target */
/* open the gap */ /* open the gap [cannot use memcpy] */
for (; s>=dotat; s-=4, t-=4) UINTAT(t)=UINTAT(s); for (; s>=dotat; s-=4, t-=4) UBFROMUI(t, UBTOUI(s));
*dotat='.'; *dotat='.';
c++; /* length increased by one */ c++; /* length increased by one */
} /* need dot? */ } /* need dot? */
...@@ -1321,24 +1392,24 @@ char * decFloatToEngString(const decFloat *df, char *string){ ...@@ -1321,24 +1392,24 @@ char * decFloatToEngString(const decFloat *df, char *string){
/* -5<=pre<=0: here for plain 0.ddd or 0.000ddd forms (may have /* -5<=pre<=0: here for plain 0.ddd or 0.000ddd forms (may have
E, but only for 0.00E+3 kind of case -- with plenty of spare E, but only for 0.00E+3 kind of case -- with plenty of spare
space in this case */ space in this case */
pre=-pre+2; /* gap width, including "0." */ pre=-pre+2; /* gap width, including "0." */
t=cstart+ROUNDDOWN4(c-cstart)+pre; /* preferred first target point */ t=cstart+ROUNDDOWN4(c-cstart)+pre; /* preferred first target point */
/* backoff if too far to the right */ /* backoff if too far to the right */
if (t>string+DECSTRING-5) t=string+DECSTRING-5; /* adjust to fit */ if (t>string+DECSTRING-5) t=string+DECSTRING-5; /* adjust to fit */
/* now shift the entire coefficient to the right, being careful not */ /* now shift the entire coefficient to the right, being careful not */
/* to access to the left of string */ /* to access to the left of string [cannot use memcpy] */
for (s=t-pre; s>=string; s-=4, t-=4) UINTAT(t)=UINTAT(s); for (s=t-pre; s>=string; s-=4, t-=4) UBFROMUI(t, UBTOUI(s));
/* for Quads and Singles there may be a character or two left... */ /* for Quads and Singles there may be a character or two left... */
s+=3; /* where next would come from */ s+=3; /* where next would come from */
for(; s>=cstart; s--, t--) *(t+3)=*(s); for(; s>=cstart; s--, t--) *(t+3)=*(s);
/* now have fill 0. through 0.00000; use overlaps to avoid tests */ /* now have fill 0. through 0.00000; use overlaps to avoid tests */
if (pre>=4) { if (pre>=4) {
UINTAT(cstart+pre-4)=UINTAT("0000"); memcpy(cstart+pre-4, "0000", 4);
UINTAT(cstart)=UINTAT("0.00"); memcpy(cstart, "0.00", 4);
} }
else { /* 2 or 3 */ else { /* 2 or 3 */
*(cstart+pre-1)='0'; *(cstart+pre-1)='0';
USHORTAT(cstart)=USHORTAT("0."); memcpy(cstart, "0.", 2);
} }
c+=pre; /* to end */ c+=pre; /* to end */
} }
...@@ -1346,7 +1417,7 @@ char * decFloatToEngString(const decFloat *df, char *string){ ...@@ -1346,7 +1417,7 @@ char * decFloatToEngString(const decFloat *df, char *string){
/* finally add the E-part, if needed; it will never be 0, and has */ /* finally add the E-part, if needed; it will never be 0, and has */
/* a maximum length of 3 or 4 digits (asserted above) */ /* a maximum length of 3 or 4 digits (asserted above) */
if (e!=0) { if (e!=0) {
USHORTAT(c)=USHORTAT("E+"); /* starts with E, assume + */ memcpy(c, "E+", 2); /* starts with E, assume + */
c++; c++;
if (e<0) { if (e<0) {
*c='-'; /* oops, need '-' */ *c='-'; /* oops, need '-' */
...@@ -1355,15 +1426,15 @@ char * decFloatToEngString(const decFloat *df, char *string){ ...@@ -1355,15 +1426,15 @@ char * decFloatToEngString(const decFloat *df, char *string){
c++; c++;
/* Three-character exponents are easy; 4-character a little trickier */ /* Three-character exponents are easy; 4-character a little trickier */
#if DECEMAXD<=3 #if DECEMAXD<=3
u=&BIN2BCD8[e*4]; /* -> 3 digits + length byte */ u=&BIN2BCD8[e*4]; /* -> 3 digits + length byte */
/* copy fixed 4 characters [is safe], starting at non-zero */ /* copy fixed 4 characters [is safe], starting at non-zero */
/* and with character mask to convert BCD to char */ /* and with character mask to convert BCD to char */
UINTAT(c)=UINTAT(u+3-*(u+3))|CHARMASK; UBFROMUI(c, UBTOUI(u+3-*(u+3))|CHARMASK);
c+=*(u+3); /* bump pointer appropriately */ c+=*(u+3); /* bump pointer appropriately */
#elif DECEMAXD==4 #elif DECEMAXD==4
if (e<1000) { /* 3 (or fewer) digits case */ if (e<1000) { /* 3 (or fewer) digits case */
u=&BIN2BCD8[e*4]; /* -> 3 digits + length byte */ u=&BIN2BCD8[e*4]; /* -> 3 digits + length byte */
UINTAT(c)=UINTAT(u+3-*(u+3))|CHARMASK; /* [as above] */ UBFROMUI(c, UBTOUI(u+3-*(u+3))|CHARMASK); /* [as above] */
c+=*(u+3); /* bump pointer appropriately */ c+=*(u+3); /* bump pointer appropriately */
} }
else { /* 4-digits */ else { /* 4-digits */
...@@ -1371,7 +1442,7 @@ char * decFloatToEngString(const decFloat *df, char *string){ ...@@ -1371,7 +1442,7 @@ char * decFloatToEngString(const decFloat *df, char *string){
Int rem=e-(1000*thou); /* e%1000 */ Int rem=e-(1000*thou); /* e%1000 */
*c++=(char)('0'+(char)thou); /* the thousands digit */ *c++=(char)('0'+(char)thou); /* the thousands digit */
u=&BIN2BCD8[rem*4]; /* -> 3 digits + length byte */ u=&BIN2BCD8[rem*4]; /* -> 3 digits + length byte */
UINTAT(c)=UINTAT(u)|CHARMASK; /* copy fixed 3+1 characters [is safe] */ UBFROMUI(c, UBTOUI(u)|CHARMASK);/* copy fixed 3+1 characters [is safe] */
c+=3; /* bump pointer, always 3 digits */ c+=3; /* bump pointer, always 3 digits */
} }
#endif #endif
...@@ -1386,7 +1457,7 @@ char * decFloatToEngString(const decFloat *df, char *string){ ...@@ -1386,7 +1457,7 @@ char * decFloatToEngString(const decFloat *df, char *string){
/* */ /* */
/* df is the source decFloat */ /* df is the source decFloat */
/* exp will be set to the unbiased exponent, q, or to a special */ /* exp will be set to the unbiased exponent, q, or to a special */
/* value in the form returned by decFloatGetExponent */ /* value in the form returned by decFloatGetExponent */
/* packed is where DECPMAX nibbles will be written with the sign as */ /* packed is where DECPMAX nibbles will be written with the sign as */
/* final nibble (0x0c for +, 0x0d for -); a NaN has a first nibble */ /* final nibble (0x0c for +, 0x0d for -); a NaN has a first nibble */
/* of zero, and an infinity is all zeros. decDouble and decQuad */ /* of zero, and an infinity is all zeros. decDouble and decQuad */
...@@ -1432,7 +1503,7 @@ Int decFloatToPacked(const decFloat *df, Int *exp, uByte *packed) { ...@@ -1432,7 +1503,7 @@ Int decFloatToPacked(const decFloat *df, Int *exp, uByte *packed) {
/* ------------------------------------------------------------------ */ /* ------------------------------------------------------------------ */
/* decFloatToString -- conversion to numeric string */ /* decFloatToString -- conversion to numeric string */
/* */ /* */
/* df is the decFloat format number to convert */ /* df is the decFloat format number to convert */
/* string is the string where the result will be laid out */ /* string is the string where the result will be laid out */
/* */ /* */
/* string must be at least DECPMAX+9 characters (the worst case is */ /* string must be at least DECPMAX+9 characters (the worst case is */
...@@ -1445,11 +1516,14 @@ char * decFloatToString(const decFloat *df, char *string){ ...@@ -1445,11 +1516,14 @@ char * decFloatToString(const decFloat *df, char *string){
uInt msd; /* coefficient MSD */ uInt msd; /* coefficient MSD */
Int exp; /* exponent top two bits or full */ Int exp; /* exponent top two bits or full */
uInt comb; /* combination field */ uInt comb; /* combination field */
char *cstart; /* coefficient start */ char *cstart; /* coefficient start */
char *c; /* output pointer in string */ char *c; /* output pointer in string */
char *s, *t; /* .. (source, target) */ char *s, *t; /* .. (source, target) */
Int pre, e; /* work */ Int pre, e; /* work */
const uByte *u; /* .. */ const uByte *u; /* .. */
uInt uiwork; /* for macros [one compiler needs */
/* volatile here to avoid bug, but */
/* that doubles execution time] */
/* Source words; macro handles endianness */ /* Source words; macro handles endianness */
uInt sourhi=DFWORD(df, 0); /* word with sign */ uInt sourhi=DFWORD(df, 0); /* word with sign */
...@@ -1464,10 +1538,14 @@ char * decFloatToString(const decFloat *df, char *string){ ...@@ -1464,10 +1538,14 @@ char * decFloatToString(const decFloat *df, char *string){
c=string; /* where result will go */ c=string; /* where result will go */
if (((Int)sourhi)<0) *c++='-'; /* handle sign */ if (((Int)sourhi)<0) *c++='-'; /* handle sign */
comb=sourhi>>26; /* sign+combination field */ comb=sourhi>>26; /* sign+combination field */
msd=DECCOMBMSD[comb]; /* decode the combination field */ msd=DECCOMBMSD[comb]; /* decode the combination field */
exp=DECCOMBEXP[comb]; /* .. */ exp=DECCOMBEXP[comb]; /* .. */
if (EXPISSPECIAL(exp)) { /* special */ if (!EXPISSPECIAL(exp)) { /* finite */
/* complete exponent; top two bits are in place */
exp+=GETECON(df)-DECBIAS; /* .. + continuation and unbias */
}
else { /* IS special */
if (exp==DECFLOAT_Inf) { /* infinity */ if (exp==DECFLOAT_Inf) { /* infinity */
strcpy(c, "Infinity"); strcpy(c, "Infinity");
return string; /* easy */ return string; /* easy */
...@@ -1487,9 +1565,6 @@ char * decFloatToString(const decFloat *df, char *string){ ...@@ -1487,9 +1565,6 @@ char * decFloatToString(const decFloat *df, char *string){
/* otherwise drop through to add integer; set correct exp etc. */ /* otherwise drop through to add integer; set correct exp etc. */
exp=0; msd=0; /* setup for following code */ exp=0; msd=0; /* setup for following code */
} }
else { /* complete exponent; top two bits are in place */
exp+=GETECON(df)-DECBIAS; /* .. + continuation and unbias */
}
/* convert the digits of the significand to characters */ /* convert the digits of the significand to characters */
cstart=c; /* save start of coefficient */ cstart=c; /* save start of coefficient */
...@@ -1500,38 +1575,38 @@ char * decFloatToString(const decFloat *df, char *string){ ...@@ -1500,38 +1575,38 @@ char * decFloatToString(const decFloat *df, char *string){
/* are the three encoded BCD8 digits followed by a 1-byte length */ /* are the three encoded BCD8 digits followed by a 1-byte length */
/* (significant digits, except that 000 has length 0). This allows */ /* (significant digits, except that 000 has length 0). This allows */
/* us to left-align the first declet with non-zero content, then */ /* us to left-align the first declet with non-zero content, then */
/* the remaining ones are full 3-char length. Fixed-length copies */ /* the remaining ones are full 3-char length. Fixed-length copies */
/* are used because variable-length memcpy causes a subroutine call */ /* are used because variable-length memcpy causes a subroutine call */
/* in at least two compilers. (The copies are length 4 for speed */ /* in at least two compilers. (The copies are length 4 for speed */
/* and are safe because the last item in the array is of length */ /* and are safe because the last item in the array is of length */
/* three and has the length byte following.) */ /* three and has the length byte following.) */
#define dpd2char(dpdin) u=&DPD2BCD8[((dpdin)&0x3ff)*4]; \ #define dpd2char(dpdin) u=&DPD2BCD8[((dpdin)&0x3ff)*4]; \
if (c!=cstart) {UINTAT(c)=UINTAT(u)|CHARMASK; c+=3;} \ if (c!=cstart) {UBFROMUI(c, UBTOUI(u)|CHARMASK); c+=3;} \
else if (*(u+3)) { \ else if (*(u+3)) { \
UINTAT(c)=UINTAT(u+3-*(u+3))|CHARMASK; c+=*(u+3);} UBFROMUI(c, UBTOUI(u+3-*(u+3))|CHARMASK); c+=*(u+3);}
#if DECPMAX==7 #if DECPMAX==7
dpd2char(sourhi>>10); /* declet 1 */ dpd2char(sourhi>>10); /* declet 1 */
dpd2char(sourhi); /* declet 2 */ dpd2char(sourhi); /* declet 2 */
#elif DECPMAX==16 #elif DECPMAX==16
dpd2char(sourhi>>8); /* declet 1 */ dpd2char(sourhi>>8); /* declet 1 */
dpd2char((sourhi<<2) | (sourlo>>30)); /* declet 2 */ dpd2char((sourhi<<2) | (sourlo>>30)); /* declet 2 */
dpd2char(sourlo>>20); /* declet 3 */ dpd2char(sourlo>>20); /* declet 3 */
dpd2char(sourlo>>10); /* declet 4 */ dpd2char(sourlo>>10); /* declet 4 */
dpd2char(sourlo); /* declet 5 */ dpd2char(sourlo); /* declet 5 */
#elif DECPMAX==34 #elif DECPMAX==34
dpd2char(sourhi>>4); /* declet 1 */ dpd2char(sourhi>>4); /* declet 1 */
dpd2char((sourhi<<6) | (sourmh>>26)); /* declet 2 */ dpd2char((sourhi<<6) | (sourmh>>26)); /* declet 2 */
dpd2char(sourmh>>16); /* declet 3 */ dpd2char(sourmh>>16); /* declet 3 */
dpd2char(sourmh>>6); /* declet 4 */ dpd2char(sourmh>>6); /* declet 4 */
dpd2char((sourmh<<4) | (sourml>>28)); /* declet 5 */ dpd2char((sourmh<<4) | (sourml>>28)); /* declet 5 */
dpd2char(sourml>>18); /* declet 6 */ dpd2char(sourml>>18); /* declet 6 */
dpd2char(sourml>>8); /* declet 7 */ dpd2char(sourml>>8); /* declet 7 */
dpd2char((sourml<<2) | (sourlo>>30)); /* declet 8 */ dpd2char((sourml<<2) | (sourlo>>30)); /* declet 8 */
dpd2char(sourlo>>20); /* declet 9 */ dpd2char(sourlo>>20); /* declet 9 */
dpd2char(sourlo>>10); /* declet 10 */ dpd2char(sourlo>>10); /* declet 10 */
dpd2char(sourlo); /* declet 11 */ dpd2char(sourlo); /* declet 11 */
#endif #endif
...@@ -1556,12 +1631,13 @@ char * decFloatToString(const decFloat *df, char *string){ ...@@ -1556,12 +1631,13 @@ char * decFloatToString(const decFloat *df, char *string){
if (pre>0) { /* ddd.ddd (plain), perhaps with E */ if (pre>0) { /* ddd.ddd (plain), perhaps with E */
char *dotat=cstart+pre; char *dotat=cstart+pre;
if (dotat<c) { /* if embedded dot needed... */ if (dotat<c) { /* if embedded dot needed... */
/* [memmove is a disaster, here] */
/* move by fours; there must be space for junk at the end */ /* move by fours; there must be space for junk at the end */
/* because there is still space for exponent */ /* because exponent is still possible */
s=dotat+ROUNDDOWN4(c-dotat); /* source */ s=dotat+ROUNDDOWN4(c-dotat); /* source */
t=s+1; /* target */ t=s+1; /* target */
/* open the gap */ /* open the gap [cannot use memcpy] */
for (; s>=dotat; s-=4, t-=4) UINTAT(t)=UINTAT(s); for (; s>=dotat; s-=4, t-=4) UBFROMUI(t, UBTOUI(s));
*dotat='.'; *dotat='.';
c++; /* length increased by one */ c++; /* length increased by one */
} /* need dot? */ } /* need dot? */
...@@ -1569,10 +1645,10 @@ char * decFloatToString(const decFloat *df, char *string){ ...@@ -1569,10 +1645,10 @@ char * decFloatToString(const decFloat *df, char *string){
/* finally add the E-part, if needed; it will never be 0, and has */ /* finally add the E-part, if needed; it will never be 0, and has */
/* a maximum length of 3 or 4 digits (asserted above) */ /* a maximum length of 3 or 4 digits (asserted above) */
if (e!=0) { if (e!=0) {
USHORTAT(c)=USHORTAT("E+"); /* starts with E, assume + */ memcpy(c, "E+", 2); /* starts with E, assume + */
c++; c++;
if (e<0) { if (e<0) {
*c='-'; /* oops, need '-' */ *c='-'; /* oops, need '-' */
e=-e; /* uInt, please */ e=-e; /* uInt, please */
} }
c++; c++;
...@@ -1581,21 +1657,21 @@ char * decFloatToString(const decFloat *df, char *string){ ...@@ -1581,21 +1657,21 @@ char * decFloatToString(const decFloat *df, char *string){
u=&BIN2BCD8[e*4]; /* -> 3 digits + length byte */ u=&BIN2BCD8[e*4]; /* -> 3 digits + length byte */
/* copy fixed 4 characters [is safe], starting at non-zero */ /* copy fixed 4 characters [is safe], starting at non-zero */
/* and with character mask to convert BCD to char */ /* and with character mask to convert BCD to char */
UINTAT(c)=UINTAT(u+3-*(u+3))|CHARMASK; UBFROMUI(c, UBTOUI(u+3-*(u+3))|CHARMASK);
c+=*(u+3); /* bump pointer appropriately */ c+=*(u+3); /* bump pointer appropriately */
#elif DECEMAXD==4 #elif DECEMAXD==4
if (e<1000) { /* 3 (or fewer) digits case */ if (e<1000) { /* 3 (or fewer) digits case */
u=&BIN2BCD8[e*4]; /* -> 3 digits + length byte */ u=&BIN2BCD8[e*4]; /* -> 3 digits + length byte */
UINTAT(c)=UINTAT(u+3-*(u+3))|CHARMASK; /* [as above] */ UBFROMUI(c, UBTOUI(u+3-*(u+3))|CHARMASK); /* [as above] */
c+=*(u+3); /* bump pointer appropriately */ c+=*(u+3); /* bump pointer appropriately */
} }
else { /* 4-digits */ else { /* 4-digits */
Int thou=((e>>3)*1049)>>17; /* e/1000 */ Int thou=((e>>3)*1049)>>17; /* e/1000 */
Int rem=e-(1000*thou); /* e%1000 */ Int rem=e-(1000*thou); /* e%1000 */
*c++=(char)('0'+(char)thou); /* the thousands digit */ *c++=(char)('0'+(char)thou); /* the thousands digit */
u=&BIN2BCD8[rem*4]; /* -> 3 digits + length byte */ u=&BIN2BCD8[rem*4]; /* -> 3 digits + length byte */
UINTAT(c)=UINTAT(u)|CHARMASK; /* copy fixed 3+1 characters [is safe] */ UBFROMUI(c, UBTOUI(u)|CHARMASK); /* copy fixed 3+1 characters [is safe] */
c+=3; /* bump pointer, always 3 digits */ c+=3; /* bump pointer, always 3 digits */
} }
#endif #endif
} }
...@@ -1618,19 +1694,19 @@ char * decFloatToString(const decFloat *df, char *string){ ...@@ -1618,19 +1694,19 @@ char * decFloatToString(const decFloat *df, char *string){
/* backoff if too far to the right */ /* backoff if too far to the right */
if (t>string+DECSTRING-5) t=string+DECSTRING-5; /* adjust to fit */ if (t>string+DECSTRING-5) t=string+DECSTRING-5; /* adjust to fit */
/* now shift the entire coefficient to the right, being careful not */ /* now shift the entire coefficient to the right, being careful not */
/* to access to the left of string */ /* to access to the left of string [cannot use memcpy] */
for (s=t-pre; s>=string; s-=4, t-=4) UINTAT(t)=UINTAT(s); for (s=t-pre; s>=string; s-=4, t-=4) UBFROMUI(t, UBTOUI(s));
/* for Quads and Singles there may be a character or two left... */ /* for Quads and Singles there may be a character or two left... */
s+=3; /* where next would come from */ s+=3; /* where next would come from */
for(; s>=cstart; s--, t--) *(t+3)=*(s); for(; s>=cstart; s--, t--) *(t+3)=*(s);
/* now have fill 0. through 0.00000; use overlaps to avoid tests */ /* now have fill 0. through 0.00000; use overlaps to avoid tests */
if (pre>=4) { if (pre>=4) {
UINTAT(cstart+pre-4)=UINTAT("0000"); memcpy(cstart+pre-4, "0000", 4);
UINTAT(cstart)=UINTAT("0.00"); memcpy(cstart, "0.00", 4);
} }
else { /* 2 or 3 */ else { /* 2 or 3 */
*(cstart+pre-1)='0'; *(cstart+pre-1)='0';
USHORTAT(cstart)=USHORTAT("0."); memcpy(cstart, "0.", 2);
} }
*(c+pre)='\0'; /* terminate */ *(c+pre)='\0'; /* terminate */
return string; return string;
...@@ -1665,7 +1741,7 @@ decFloatWider * decFloatToWider(const decFloat *source, decFloatWider *wider) { ...@@ -1665,7 +1741,7 @@ decFloatWider * decFloatToWider(const decFloat *source, decFloatWider *wider) {
code|=(exp<<(32-6-DECWECONL)) & 0x03ffffff; /* add exponent continuation */ code|=(exp<<(32-6-DECWECONL)) & 0x03ffffff; /* add exponent continuation */
code|=DFWORD(source, 0)&0x80000000; /* add sign */ code|=DFWORD(source, 0)&0x80000000; /* add sign */
DFWWORD(wider, 0)=code; /* .. and place top word in wider */ DFWWORD(wider, 0)=code; /* .. and place top word in wider */
msd=GETMSD(source); /* get source coefficient MSD [0-9] */ msd=GETMSD(source); /* get source coefficient MSD [0-9] */
} }
/* Copy the coefficient and clear any 'unused' words to left */ /* Copy the coefficient and clear any 'unused' words to left */
#if SINGLE #if SINGLE
...@@ -1723,6 +1799,7 @@ decFloat * decFloatZero(decFloat *df){ ...@@ -1723,6 +1799,7 @@ decFloat * decFloatZero(decFloat *df){
void decShowNum(const bcdnum *num, const char *tag) { void decShowNum(const bcdnum *num, const char *tag) {
const char *csign="+"; /* sign character */ const char *csign="+"; /* sign character */
uByte *ub; /* work */ uByte *ub; /* work */
uInt uiwork; /* for macros */
if (num->sign==DECFLOAT_Sign) csign="-"; if (num->sign==DECFLOAT_Sign) csign="-";
printf(">%s> ", tag); printf(">%s> ", tag);
...@@ -1747,7 +1824,7 @@ decFloat * decFloatZero(decFloat *df){ ...@@ -1747,7 +1824,7 @@ decFloat * decFloatZero(decFloat *df){
if (e==0) *c++='0'; /* 0-length case */ if (e==0) *c++='0'; /* 0-length case */
else if (e<1000) { /* 3 (or fewer) digits case */ else if (e<1000) { /* 3 (or fewer) digits case */
u=&BIN2BCD8[e*4]; /* -> 3 digits + length byte */ u=&BIN2BCD8[e*4]; /* -> 3 digits + length byte */
UINTAT(c)=UINTAT(u+3-*(u+3))|CHARMASK; /* [as above] */ UBFROMUI(c, UBTOUI(u+3-*(u+3))|CHARMASK); /* [as above] */
c+=*(u+3); /* bump pointer appropriately */ c+=*(u+3); /* bump pointer appropriately */
} }
else { /* 4-digits */ else { /* 4-digits */
...@@ -1755,7 +1832,7 @@ decFloat * decFloatZero(decFloat *df){ ...@@ -1755,7 +1832,7 @@ decFloat * decFloatZero(decFloat *df){
Int rem=e-(1000*thou); /* e%1000 */ Int rem=e-(1000*thou); /* e%1000 */
*c++=(char)('0'+(char)thou); /* the thousands digit */ *c++=(char)('0'+(char)thou); /* the thousands digit */
u=&BIN2BCD8[rem*4]; /* -> 3 digits + length byte */ u=&BIN2BCD8[rem*4]; /* -> 3 digits + length byte */
UINTAT(c)=UINTAT(u)|CHARMASK; /* copy fixed 3+1 characters [is safe] */ UBFROMUI(c, UBTOUI(u)|CHARMASK); /* copy fixed 3+1 characters [is safe] */
c+=3; /* bump pointer, always 3 digits */ c+=3; /* bump pointer, always 3 digits */
} }
*c='\0'; /* add terminator */ *c='\0'; /* add terminator */
......
...@@ -38,15 +38,13 @@ ...@@ -38,15 +38,13 @@
#include <string.h> /* for strcmp */ #include <string.h> /* for strcmp */
#include <stdio.h> /* for printf if DECCHECK */ #include <stdio.h> /* for printf if DECCHECK */
#include "dconfig.h" /* for GCC definitions */ #include "dconfig.h" /* for GCC definitions */
#include "decContext.h" /* context and base types */ #include "decContext.h" /* context and base types */
#include "decNumberLocal.h" /* decNumber local types, etc. */ #include "decNumberLocal.h" /* decNumber local types, etc. */
#if DECCHECK
/* compile-time endian tester [assumes sizeof(Int)>1] */ /* compile-time endian tester [assumes sizeof(Int)>1] */
static const Int mfcone=1; /* constant 1 */ static const Int mfcone=1; /* constant 1 */
static const Flag *mfctop=(Flag *)&mfcone; /* -> top byte */ static const Flag *mfctop=(const Flag *)&mfcone; /* -> top byte */
#define LITEND *mfctop /* named flag; 1=little-endian */ #define LITEND *mfctop /* named flag; 1=little-endian */
#endif
/* ------------------------------------------------------------------ */ /* ------------------------------------------------------------------ */
/* round-for-reround digits */ /* round-for-reround digits */
...@@ -64,7 +62,7 @@ const uInt DECPOWERS[10]={1, 10, 100, 1000, 10000, 100000, 1000000, ...@@ -64,7 +62,7 @@ const uInt DECPOWERS[10]={1, 10, 100, 1000, 10000, 100000, 1000000,
/* */ /* */
/* context is the context structure to be queried */ /* context is the context structure to be queried */
/* mask indicates the bits to be cleared (the status bit that */ /* mask indicates the bits to be cleared (the status bit that */
/* corresponds to each 1 bit in the mask is cleared) */ /* corresponds to each 1 bit in the mask is cleared) */
/* returns context */ /* returns context */
/* */ /* */
/* No error is possible. */ /* No error is possible. */
...@@ -80,9 +78,9 @@ decContext *decContextClearStatus(decContext *context, uInt mask) { ...@@ -80,9 +78,9 @@ decContext *decContextClearStatus(decContext *context, uInt mask) {
/* context is the structure to be initialized */ /* context is the structure to be initialized */
/* kind selects the required set of default values, one of: */ /* kind selects the required set of default values, one of: */
/* DEC_INIT_BASE -- select ANSI X3-274 defaults */ /* DEC_INIT_BASE -- select ANSI X3-274 defaults */
/* DEC_INIT_DECIMAL32 -- select IEEE 754r defaults, 32-bit */ /* DEC_INIT_DECIMAL32 -- select IEEE 754 defaults, 32-bit */
/* DEC_INIT_DECIMAL64 -- select IEEE 754r defaults, 64-bit */ /* DEC_INIT_DECIMAL64 -- select IEEE 754 defaults, 64-bit */
/* DEC_INIT_DECIMAL128 -- select IEEE 754r defaults, 128-bit */ /* DEC_INIT_DECIMAL128 -- select IEEE 754 defaults, 128-bit */
/* For any other value a valid context is returned, but with */ /* For any other value a valid context is returned, but with */
/* Invalid_operation set in the status field. */ /* Invalid_operation set in the status field. */
/* returns a context structure with the appropriate initial values. */ /* returns a context structure with the appropriate initial values. */
...@@ -105,11 +103,11 @@ decContext * decContextDefault(decContext *context, Int kind) { ...@@ -105,11 +103,11 @@ decContext * decContextDefault(decContext *context, Int kind) {
break; break;
case DEC_INIT_DECIMAL32: case DEC_INIT_DECIMAL32:
context->digits=7; /* digits */ context->digits=7; /* digits */
context->emax=96; /* Emax */ context->emax=96; /* Emax */
context->emin=-95; /* Emin */ context->emin=-95; /* Emin */
context->round=DEC_ROUND_HALF_EVEN; /* 0.5 to nearest even */ context->round=DEC_ROUND_HALF_EVEN; /* 0.5 to nearest even */
context->traps=0; /* no traps set */ context->traps=0; /* no traps set */
context->clamp=1; /* clamp exponents */ context->clamp=1; /* clamp exponents */
#if DECSUBSET #if DECSUBSET
context->extended=1; /* set */ context->extended=1; /* set */
#endif #endif
...@@ -119,8 +117,8 @@ decContext * decContextDefault(decContext *context, Int kind) { ...@@ -119,8 +117,8 @@ decContext * decContextDefault(decContext *context, Int kind) {
context->emax=384; /* Emax */ context->emax=384; /* Emax */
context->emin=-383; /* Emin */ context->emin=-383; /* Emin */
context->round=DEC_ROUND_HALF_EVEN; /* 0.5 to nearest even */ context->round=DEC_ROUND_HALF_EVEN; /* 0.5 to nearest even */
context->traps=0; /* no traps set */ context->traps=0; /* no traps set */
context->clamp=1; /* clamp exponents */ context->clamp=1; /* clamp exponents */
#if DECSUBSET #if DECSUBSET
context->extended=1; /* set */ context->extended=1; /* set */
#endif #endif
...@@ -130,8 +128,8 @@ decContext * decContextDefault(decContext *context, Int kind) { ...@@ -130,8 +128,8 @@ decContext * decContextDefault(decContext *context, Int kind) {
context->emax=6144; /* Emax */ context->emax=6144; /* Emax */
context->emin=-6143; /* Emin */ context->emin=-6143; /* Emin */
context->round=DEC_ROUND_HALF_EVEN; /* 0.5 to nearest even */ context->round=DEC_ROUND_HALF_EVEN; /* 0.5 to nearest even */
context->traps=0; /* no traps set */ context->traps=0; /* no traps set */
context->clamp=1; /* clamp exponents */ context->clamp=1; /* clamp exponents */
#if DECSUBSET #if DECSUBSET
context->extended=1; /* set */ context->extended=1; /* set */
#endif #endif
...@@ -142,15 +140,6 @@ decContext * decContextDefault(decContext *context, Int kind) { ...@@ -142,15 +140,6 @@ decContext * decContextDefault(decContext *context, Int kind) {
decContextSetStatus(context, DEC_Invalid_operation); /* trap */ decContextSetStatus(context, DEC_Invalid_operation); /* trap */
} }
#if DECCHECK
if (LITEND!=DECLITEND) {
const char *adj;
if (LITEND) adj="little";
else adj="big";
printf("Warning: DECLITEND is set to %d, but this computer appears to be %s-endian\n",
DECLITEND, adj);
}
#endif
return context;} /* decContextDefault */ return context;} /* decContextDefault */
/* ------------------------------------------------------------------ */ /* ------------------------------------------------------------------ */
...@@ -166,7 +155,7 @@ enum rounding decContextGetRounding(decContext *context) { ...@@ -166,7 +155,7 @@ enum rounding decContextGetRounding(decContext *context) {
} /* decContextGetRounding */ } /* decContextGetRounding */
/* ------------------------------------------------------------------ */ /* ------------------------------------------------------------------ */
/* decContextGetStatus -- return current status */ /* decContextGetStatus -- return current status */
/* */ /* */
/* context is the context structure to be queried */ /* context is the context structure to be queried */
/* returns status */ /* returns status */
...@@ -181,8 +170,8 @@ uInt decContextGetStatus(decContext *context) { ...@@ -181,8 +170,8 @@ uInt decContextGetStatus(decContext *context) {
/* decContextRestoreStatus -- restore bits in current status */ /* decContextRestoreStatus -- restore bits in current status */
/* */ /* */
/* context is the context structure to be updated */ /* context is the context structure to be updated */
/* newstatus is the source for the bits to be restored */ /* newstatus is the source for the bits to be restored */
/* mask indicates the bits to be restored (the status bit that */ /* mask indicates the bits to be restored (the status bit that */
/* corresponds to each 1 bit in the mask is set to the value of */ /* corresponds to each 1 bit in the mask is set to the value of */
/* the correspnding bit in newstatus) */ /* the correspnding bit in newstatus) */
/* returns context */ /* returns context */
...@@ -252,7 +241,7 @@ decContext * decContextSetStatus(decContext *context, uInt status) { ...@@ -252,7 +241,7 @@ decContext * decContextSetStatus(decContext *context, uInt status) {
/* */ /* */
/* returns the context structure, unless the string is equal to */ /* returns the context structure, unless the string is equal to */
/* DEC_Condition_MU or is not recognized. In these cases NULL is */ /* DEC_Condition_MU or is not recognized. In these cases NULL is */
/* returned. */ /* returned. */
/* ------------------------------------------------------------------ */ /* ------------------------------------------------------------------ */
decContext * decContextSetStatusFromString(decContext *context, decContext * decContextSetStatusFromString(decContext *context,
const char *string) { const char *string) {
...@@ -303,7 +292,7 @@ decContext * decContextSetStatusFromString(decContext *context, ...@@ -303,7 +292,7 @@ decContext * decContextSetStatusFromString(decContext *context,
/* */ /* */
/* returns the context structure, unless the string is equal to */ /* returns the context structure, unless the string is equal to */
/* DEC_Condition_MU or is not recognized. In these cases NULL is */ /* DEC_Condition_MU or is not recognized. In these cases NULL is */
/* returned. */ /* returned. */
/* ------------------------------------------------------------------ */ /* ------------------------------------------------------------------ */
decContext * decContextSetStatusFromStringQuiet(decContext *context, decContext * decContextSetStatusFromStringQuiet(decContext *context,
const char *string) { const char *string) {
...@@ -356,11 +345,11 @@ decContext * decContextSetStatusQuiet(decContext *context, uInt status) { ...@@ -356,11 +345,11 @@ decContext * decContextSetStatusQuiet(decContext *context, uInt status) {
return context;} /* decContextSetStatusQuiet */ return context;} /* decContextSetStatusQuiet */
/* ------------------------------------------------------------------ */ /* ------------------------------------------------------------------ */
/* decContextStatusToString -- convert status flags to a string */ /* decContextStatusToString -- convert status flags to a string */
/* */ /* */
/* context is a context with valid status field */ /* context is a context with valid status field */
/* */ /* */
/* returns a constant string describing the condition. If multiple */ /* returns a constant string describing the condition. If multiple */
/* (or no) flags are set, a generic constant message is returned. */ /* (or no) flags are set, a generic constant message is returned. */
/* ------------------------------------------------------------------ */ /* ------------------------------------------------------------------ */
const char *decContextStatusToString(const decContext *context) { const char *decContextStatusToString(const decContext *context) {
...@@ -385,11 +374,41 @@ const char *decContextStatusToString(const decContext *context) { ...@@ -385,11 +374,41 @@ const char *decContextStatusToString(const decContext *context) {
#if DECSUBSET #if DECSUBSET
if (status==DEC_Lost_digits ) return DEC_Condition_LD; if (status==DEC_Lost_digits ) return DEC_Condition_LD;
#endif #endif
if (status==0 ) return DEC_Condition_ZE; if (status==0 ) return DEC_Condition_ZE;
return DEC_Condition_MU; /* Multiple errors */ return DEC_Condition_MU; /* Multiple errors */
} /* decContextStatusToString */ } /* decContextStatusToString */
/* ------------------------------------------------------------------ */ /* ------------------------------------------------------------------ */
/* decContextTestEndian -- test whether DECLITEND is set correctly */
/* */
/* quiet is 1 to suppress message; 0 otherwise */
/* returns 0 if DECLITEND is correct */
/* 1 if DECLITEND is incorrect and should be 1 */
/* -1 if DECLITEND is incorrect and should be 0 */
/* */
/* A message is displayed if the return value is not 0 and quiet==0. */
/* */
/* No error is possible. */
/* ------------------------------------------------------------------ */
Int decContextTestEndian(Flag quiet) {
Int res=0; /* optimist */
uInt dle=(uInt)DECLITEND; /* unsign */
if (dle>1) dle=1; /* ensure 0 or 1 */
if (LITEND!=DECLITEND) {
const char *adj;
if (!quiet) {
if (LITEND) adj="little";
else adj="big";
printf("Warning: DECLITEND is set to %d, but this computer appears to be %s-endian\n",
DECLITEND, adj);
}
res=(Int)LITEND-dle;
}
return res;
} /* decContextTestEndian */
/* ------------------------------------------------------------------ */
/* decContextTestSavedStatus -- test bits in saved status */ /* decContextTestSavedStatus -- test bits in saved status */
/* */ /* */
/* oldstatus is the status word to be tested */ /* oldstatus is the status word to be tested */
......
...@@ -34,7 +34,7 @@ ...@@ -34,7 +34,7 @@
/* */ /* */
/* Context variables must always have valid values: */ /* Context variables must always have valid values: */
/* */ /* */
/* status -- [any bits may be cleared, but not set, by user] */ /* status -- [any bits may be cleared, but not set, by user] */
/* round -- must be one of the enumerated rounding modes */ /* round -- must be one of the enumerated rounding modes */
/* */ /* */
/* The following variables are implied for fixed size formats (i.e., */ /* The following variables are implied for fixed size formats (i.e., */
...@@ -54,36 +54,42 @@ ...@@ -54,36 +54,42 @@
#define DECCONTEXT #define DECCONTEXT
#define DECCNAME "decContext" /* Short name */ #define DECCNAME "decContext" /* Short name */
#define DECCFULLNAME "Decimal Context Descriptor" /* Verbose name */ #define DECCFULLNAME "Decimal Context Descriptor" /* Verbose name */
#define DECCAUTHOR "Mike Cowlishaw" /* Who to blame */ #define DECCAUTHOR "Mike Cowlishaw" /* Who to blame */
#include "gstdint.h" /* C99 standard integers */ #if !defined(int32_t)
#include <stdint.h> /* C99 standard integers */
#endif
#include <stdio.h> /* for printf, etc. */ #include <stdio.h> /* for printf, etc. */
#include <signal.h> /* for traps */ #include <signal.h> /* for traps */
/* Extended flags setting -- set this to 0 to use only IEEE flags */ /* Extended flags setting -- set this to 0 to use only IEEE flags */
#if !defined(DECEXTFLAG)
#define DECEXTFLAG 1 /* 1=enable extended flags */ #define DECEXTFLAG 1 /* 1=enable extended flags */
#endif
/* Conditional code flag -- set this to 0 for best performance */ /* Conditional code flag -- set this to 0 for best performance */
#if !defined(DECSUBSET)
#define DECSUBSET 0 /* 1=enable subset arithmetic */ #define DECSUBSET 0 /* 1=enable subset arithmetic */
#endif
/* Context for operations, with associated constants */ /* Context for operations, with associated constants */
enum rounding { enum rounding {
DEC_ROUND_CEILING, /* round towards +infinity */ DEC_ROUND_CEILING, /* round towards +infinity */
DEC_ROUND_UP, /* round away from 0 */ DEC_ROUND_UP, /* round away from 0 */
DEC_ROUND_HALF_UP, /* 0.5 rounds up */ DEC_ROUND_HALF_UP, /* 0.5 rounds up */
DEC_ROUND_HALF_EVEN, /* 0.5 rounds to nearest even */ DEC_ROUND_HALF_EVEN, /* 0.5 rounds to nearest even */
DEC_ROUND_HALF_DOWN, /* 0.5 rounds down */ DEC_ROUND_HALF_DOWN, /* 0.5 rounds down */
DEC_ROUND_DOWN, /* round towards 0 (truncate) */ DEC_ROUND_DOWN, /* round towards 0 (truncate) */
DEC_ROUND_FLOOR, /* round towards -infinity */ DEC_ROUND_FLOOR, /* round towards -infinity */
DEC_ROUND_05UP, /* round for reround */ DEC_ROUND_05UP, /* round for reround */
DEC_ROUND_MAX /* enum must be less than this */ DEC_ROUND_MAX /* enum must be less than this */
}; };
#define DEC_ROUND_DEFAULT DEC_ROUND_HALF_EVEN; #define DEC_ROUND_DEFAULT DEC_ROUND_HALF_EVEN;
typedef struct { typedef struct {
int32_t digits; /* working precision */ int32_t digits; /* working precision */
int32_t emax; /* maximum positive exponent */ int32_t emax; /* maximum positive exponent */
int32_t emin; /* minimum negative exponent */ int32_t emin; /* minimum negative exponent */
enum rounding round; /* rounding mode */ enum rounding round; /* rounding mode */
uint32_t traps; /* trap-enabler flags */ uint32_t traps; /* trap-enabler flags */
uint32_t status; /* status flags */ uint32_t status; /* status flags */
...@@ -102,9 +108,9 @@ ...@@ -102,9 +108,9 @@
#define DEC_MIN_EMIN -999999999 #define DEC_MIN_EMIN -999999999
#define DEC_MAX_MATH 999999 /* max emax, etc., for math funcs. */ #define DEC_MAX_MATH 999999 /* max emax, etc., for math funcs. */
/* Classifications for decimal numbers, aligned with 754r (note */ /* Classifications for decimal numbers, aligned with 754 (note that */
/* that 'normal' and 'subnormal' are meaningful only with a */ /* 'normal' and 'subnormal' are meaningful only with a decContext */
/* decContext or a fixed size format). */ /* or a fixed size format). */
enum decClass { enum decClass {
DEC_CLASS_SNAN, DEC_CLASS_SNAN,
DEC_CLASS_QNAN, DEC_CLASS_QNAN,
...@@ -139,15 +145,15 @@ ...@@ -139,15 +145,15 @@
#define DEC_Division_impossible 0x00000004 #define DEC_Division_impossible 0x00000004
#define DEC_Division_undefined 0x00000008 #define DEC_Division_undefined 0x00000008
#define DEC_Insufficient_storage 0x00000010 /* [when malloc fails] */ #define DEC_Insufficient_storage 0x00000010 /* [when malloc fails] */
#define DEC_Inexact 0x00000020 #define DEC_Inexact 0x00000020
#define DEC_Invalid_context 0x00000040 #define DEC_Invalid_context 0x00000040
#define DEC_Invalid_operation 0x00000080 #define DEC_Invalid_operation 0x00000080
#if DECSUBSET #if DECSUBSET
#define DEC_Lost_digits 0x00000100 #define DEC_Lost_digits 0x00000100
#endif #endif
#define DEC_Overflow 0x00000200 #define DEC_Overflow 0x00000200
#define DEC_Clamped 0x00000400 #define DEC_Clamped 0x00000400
#define DEC_Rounded 0x00000800 #define DEC_Rounded 0x00000800
#define DEC_Subnormal 0x00001000 #define DEC_Subnormal 0x00001000
#define DEC_Underflow 0x00002000 #define DEC_Underflow 0x00002000
#else #else
...@@ -157,43 +163,43 @@ ...@@ -157,43 +163,43 @@
#define DEC_Division_impossible 0x00000010 #define DEC_Division_impossible 0x00000010
#define DEC_Division_undefined 0x00000010 #define DEC_Division_undefined 0x00000010
#define DEC_Insufficient_storage 0x00000010 /* [when malloc fails] */ #define DEC_Insufficient_storage 0x00000010 /* [when malloc fails] */
#define DEC_Inexact 0x00000001 #define DEC_Inexact 0x00000001
#define DEC_Invalid_context 0x00000010 #define DEC_Invalid_context 0x00000010
#define DEC_Invalid_operation 0x00000010 #define DEC_Invalid_operation 0x00000010
#if DECSUBSET #if DECSUBSET
#define DEC_Lost_digits 0x00000000 #define DEC_Lost_digits 0x00000000
#endif #endif
#define DEC_Overflow 0x00000008 #define DEC_Overflow 0x00000008
#define DEC_Clamped 0x00000000 #define DEC_Clamped 0x00000000
#define DEC_Rounded 0x00000000 #define DEC_Rounded 0x00000000
#define DEC_Subnormal 0x00000000 #define DEC_Subnormal 0x00000000
#define DEC_Underflow 0x00000004 #define DEC_Underflow 0x00000004
#endif #endif
/* IEEE 854 groupings for the flags */ /* IEEE 754 groupings for the flags */
/* [DEC_Clamped, DEC_Lost_digits, DEC_Rounded, and DEC_Subnormal */ /* [DEC_Clamped, DEC_Lost_digits, DEC_Rounded, and DEC_Subnormal */
/* are not in IEEE 854] */ /* are not in IEEE 754] */
#define DEC_IEEE_854_Division_by_zero (DEC_Division_by_zero) #define DEC_IEEE_754_Division_by_zero (DEC_Division_by_zero)
#if DECSUBSET #if DECSUBSET
#define DEC_IEEE_854_Inexact (DEC_Inexact | DEC_Lost_digits) #define DEC_IEEE_754_Inexact (DEC_Inexact | DEC_Lost_digits)
#else #else
#define DEC_IEEE_854_Inexact (DEC_Inexact) #define DEC_IEEE_754_Inexact (DEC_Inexact)
#endif #endif
#define DEC_IEEE_854_Invalid_operation (DEC_Conversion_syntax | \ #define DEC_IEEE_754_Invalid_operation (DEC_Conversion_syntax | \
DEC_Division_impossible | \ DEC_Division_impossible | \
DEC_Division_undefined | \ DEC_Division_undefined | \
DEC_Insufficient_storage | \ DEC_Insufficient_storage | \
DEC_Invalid_context | \ DEC_Invalid_context | \
DEC_Invalid_operation) DEC_Invalid_operation)
#define DEC_IEEE_854_Overflow (DEC_Overflow) #define DEC_IEEE_754_Overflow (DEC_Overflow)
#define DEC_IEEE_854_Underflow (DEC_Underflow) #define DEC_IEEE_754_Underflow (DEC_Underflow)
/* flags which are normally errors (result is qNaN, infinite, or 0) */ /* flags which are normally errors (result is qNaN, infinite, or 0) */
#define DEC_Errors (DEC_IEEE_854_Division_by_zero | \ #define DEC_Errors (DEC_IEEE_754_Division_by_zero | \
DEC_IEEE_854_Invalid_operation | \ DEC_IEEE_754_Invalid_operation | \
DEC_IEEE_854_Overflow | DEC_IEEE_854_Underflow) DEC_IEEE_754_Overflow | DEC_IEEE_754_Underflow)
/* flags which cause a result to become qNaN */ /* flags which cause a result to become qNaN */
#define DEC_NaNs DEC_IEEE_854_Invalid_operation #define DEC_NaNs DEC_IEEE_754_Invalid_operation
/* flags which are normally for information only (finite results) */ /* flags which are normally for information only (finite results) */
#if DECSUBSET #if DECSUBSET
...@@ -203,6 +209,13 @@ ...@@ -203,6 +209,13 @@
#define DEC_Information (DEC_Clamped | DEC_Rounded | DEC_Inexact) #define DEC_Information (DEC_Clamped | DEC_Rounded | DEC_Inexact)
#endif #endif
/* IEEE 854 names (for compatibility with older decNumber versions) */
#define DEC_IEEE_854_Division_by_zero DEC_IEEE_754_Division_by_zero
#define DEC_IEEE_854_Inexact DEC_IEEE_754_Inexact
#define DEC_IEEE_854_Invalid_operation DEC_IEEE_754_Invalid_operation
#define DEC_IEEE_854_Overflow DEC_IEEE_754_Overflow
#define DEC_IEEE_854_Underflow DEC_IEEE_754_Underflow
/* Name strings for the exceptional conditions */ /* Name strings for the exceptional conditions */
#define DEC_Condition_CS "Conversion syntax" #define DEC_Condition_CS "Conversion syntax"
#define DEC_Condition_DZ "Division by zero" #define DEC_Condition_DZ "Division by zero"
...@@ -226,7 +239,7 @@ ...@@ -226,7 +239,7 @@
/* including terminator */ /* including terminator */
/* Initialization descriptors, used by decContextDefault */ /* Initialization descriptors, used by decContextDefault */
#define DEC_INIT_BASE 0 #define DEC_INIT_BASE 0
#define DEC_INIT_DECIMAL32 32 #define DEC_INIT_DECIMAL32 32
#define DEC_INIT_DECIMAL64 64 #define DEC_INIT_DECIMAL64 64
#define DEC_INIT_DECIMAL128 128 #define DEC_INIT_DECIMAL128 128
...@@ -251,6 +264,7 @@ ...@@ -251,6 +264,7 @@
extern decContext * decContextSetStatusFromStringQuiet(decContext *, const char *); extern decContext * decContextSetStatusFromStringQuiet(decContext *, const char *);
extern decContext * decContextSetStatusQuiet(decContext *, uint32_t); extern decContext * decContextSetStatusQuiet(decContext *, uint32_t);
extern const char * decContextStatusToString(const decContext *); extern const char * decContextStatusToString(const decContext *);
extern int32_t decContextTestEndian(uint8_t);
extern uint32_t decContextTestSavedStatus(uint32_t, uint32_t); extern uint32_t decContextTestSavedStatus(uint32_t, uint32_t);
extern uint32_t decContextTestStatus(decContext *, uint32_t); extern uint32_t decContextTestStatus(decContext *, uint32_t);
extern decContext * decContextZeroStatus(decContext *); extern decContext * decContextZeroStatus(decContext *);
......
...@@ -30,10 +30,9 @@ ...@@ -30,10 +30,9 @@
/* ------------------------------------------------------------------------ */ /* ------------------------------------------------------------------------ */
/* Binary Coded Decimal and Densely Packed Decimal conversion lookup tables */ /* Binary Coded Decimal and Densely Packed Decimal conversion lookup tables */
/* [Automatically generated -- do not edit. 2007.05.05] */ /* [Automatically generated -- do not edit. 2008.06.21] */
/* ------------------------------------------------------------------------ */ /* ------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------ */ /* For details, see DPDecimal.html on the General Decimal Arithmetic page. */
/* For details, see: http://www2.hursley.ibm.com/decimal/DPDecimal.html */
#include "decDPDSymbols.h" #include "decDPDSymbols.h"
...@@ -43,9 +42,9 @@ ...@@ -43,9 +42,9 @@
/* uint16_t BIN2DPD[1000]; -- Bin -> DPD (999 => 2457) */ /* uint16_t BIN2DPD[1000]; -- Bin -> DPD (999 => 2457) */
/* uint8_t BIN2CHAR[4001]; -- Bin -> CHAR (999 => '\3' '9' '9' '9') */ /* uint8_t BIN2CHAR[4001]; -- Bin -> CHAR (999 => '\3' '9' '9' '9') */
/* uint8_t BIN2BCD8[4000]; -- Bin -> bytes (999 => 9 9 9 3) */ /* uint8_t BIN2BCD8[4000]; -- Bin -> bytes (999 => 9 9 9 3) */
/* uint16_t DPD2BCD[1024]; -- DPD -> BCD (0x3FF => 0x999) */ /* uint16_t DPD2BCD[1024]; -- DPD -> BCD (0x3FF => 0x999) */
/* uint16_t DPD2BIN[1024]; -- DPD -> BIN (0x3FF => 999) */ /* uint16_t DPD2BIN[1024]; -- DPD -> BIN (0x3FF => 999) */
/* uint32_t DPD2BINK[1024]; -- DPD -> BIN * 1000 (0x3FF => 999000) */ /* uint32_t DPD2BINK[1024]; -- DPD -> BIN * 1000 (0x3FF => 999000) */
/* uint32_t DPD2BINM[1024]; -- DPD -> BIN * 1E+6 (0x3FF => 999000000) */ /* uint32_t DPD2BINM[1024]; -- DPD -> BIN * 1E+6 (0x3FF => 999000000) */
/* uint8_t DPD2BCD8[4096]; -- DPD -> bytes (x3FF => 9 9 9 3) */ /* uint8_t DPD2BCD8[4096]; -- DPD -> bytes (x3FF => 9 9 9 3) */
/* */ /* */
...@@ -53,10 +52,10 @@ ...@@ -53,10 +52,10 @@
/* in the table entry. BIN2CHAR entries are a single byte length (0 for */ /* in the table entry. BIN2CHAR entries are a single byte length (0 for */
/* value 0) followed by three digit characters; a trailing terminator is */ /* value 0) followed by three digit characters; a trailing terminator is */
/* included to allow 4-char moves always. BIN2BCD8 and DPD2BCD8 entries */ /* included to allow 4-char moves always. BIN2BCD8 and DPD2BCD8 entries */
/* are similar with the three BCD8 digits followed by a one-byte length */ /* are similar with the three BCD8 digits followed by a one-byte length */
/* (again, length=0 for value 0). */ /* (again, length=0 for value 0). */
/* */ /* */
/* To use a table, its name, prefixed with DEC_, must be defined with a */ /* To use a table, its name, prefixed with DEC_, must be defined with a */
/* value of 1 before this header file is included. For example: */ /* value of 1 before this header file is included. For example: */
/* #define DEC_BCD2DPD 1 */ /* #define DEC_BCD2DPD 1 */
/* This mechanism allows software to only include tables that are needed. */ /* This mechanism allows software to only include tables that are needed. */
...@@ -513,7 +512,7 @@ const uint16_t DPD2BIN[1024]={ 0, 1, 2, 3, 4, 5, 6, 7, ...@@ -513,7 +512,7 @@ const uint16_t DPD2BIN[1024]={ 0, 1, 2, 3, 4, 5, 6, 7,
#if defined(DEC_DPD2BINK) && DEC_DPD2BINK==1 && !defined(DECDPD2BINK) #if defined(DEC_DPD2BINK) && DEC_DPD2BINK==1 && !defined(DECDPD2BINK)
#define DECDPD2BINK #define DECDPD2BINK
const uint32_t DPD2BINK[1024]={ 0, 1000, 2000, 3000, 4000, 5000, const uint32_t DPD2BINK[1024]={ 0, 1000, 2000, 3000, 4000, 5000,
6000, 7000, 8000, 9000, 80000, 81000, 800000, 801000, 880000, 881000, 6000, 7000, 8000, 9000, 80000, 81000, 800000, 801000, 880000, 881000,
10000, 11000, 12000, 13000, 14000, 15000, 16000, 17000, 18000, 19000, 10000, 11000, 12000, 13000, 14000, 15000, 16000, 17000, 18000, 19000,
90000, 91000, 810000, 811000, 890000, 891000, 20000, 21000, 22000, 23000, 90000, 91000, 810000, 811000, 890000, 891000, 20000, 21000, 22000, 23000,
...@@ -621,24 +620,24 @@ const uint32_t DPD2BINK[1024]={ 0, 1000, 2000, 3000, 4000, 5000, ...@@ -621,24 +620,24 @@ const uint32_t DPD2BINK[1024]={ 0, 1000, 2000, 3000, 4000, 5000,
#if defined(DEC_DPD2BINM) && DEC_DPD2BINM==1 && !defined(DECDPD2BINM) #if defined(DEC_DPD2BINM) && DEC_DPD2BINM==1 && !defined(DECDPD2BINM)
#define DECDPD2BINM #define DECDPD2BINM
const uint32_t DPD2BINM[1024]={0, 1000000, 2000000, 3000000, 4000000, const uint32_t DPD2BINM[1024]={0, 1000000, 2000000, 3000000, 4000000,
5000000, 6000000, 7000000, 8000000, 9000000, 80000000, 81000000, 5000000, 6000000, 7000000, 8000000, 9000000, 80000000, 81000000,
800000000, 801000000, 880000000, 881000000, 10000000, 11000000, 12000000, 800000000, 801000000, 880000000, 881000000, 10000000, 11000000, 12000000,
13000000, 14000000, 15000000, 16000000, 17000000, 18000000, 19000000, 13000000, 14000000, 15000000, 16000000, 17000000, 18000000, 19000000,
90000000, 91000000, 810000000, 811000000, 890000000, 891000000, 20000000, 90000000, 91000000, 810000000, 811000000, 890000000, 891000000, 20000000,
21000000, 22000000, 23000000, 24000000, 25000000, 26000000, 27000000, 21000000, 22000000, 23000000, 24000000, 25000000, 26000000, 27000000,
28000000, 29000000, 82000000, 83000000, 820000000, 821000000, 808000000, 28000000, 29000000, 82000000, 83000000, 820000000, 821000000, 808000000,
809000000, 30000000, 31000000, 32000000, 33000000, 34000000, 35000000, 809000000, 30000000, 31000000, 32000000, 33000000, 34000000, 35000000,
36000000, 37000000, 38000000, 39000000, 92000000, 93000000, 830000000, 36000000, 37000000, 38000000, 39000000, 92000000, 93000000, 830000000,
831000000, 818000000, 819000000, 40000000, 41000000, 42000000, 43000000, 831000000, 818000000, 819000000, 40000000, 41000000, 42000000, 43000000,
44000000, 45000000, 46000000, 47000000, 48000000, 49000000, 84000000, 44000000, 45000000, 46000000, 47000000, 48000000, 49000000, 84000000,
85000000, 840000000, 841000000, 88000000, 89000000, 50000000, 51000000, 85000000, 840000000, 841000000, 88000000, 89000000, 50000000, 51000000,
52000000, 53000000, 54000000, 55000000, 56000000, 57000000, 58000000, 52000000, 53000000, 54000000, 55000000, 56000000, 57000000, 58000000,
59000000, 94000000, 95000000, 850000000, 851000000, 98000000, 99000000, 59000000, 94000000, 95000000, 850000000, 851000000, 98000000, 99000000,
60000000, 61000000, 62000000, 63000000, 64000000, 65000000, 66000000, 60000000, 61000000, 62000000, 63000000, 64000000, 65000000, 66000000,
67000000, 68000000, 69000000, 86000000, 87000000, 860000000, 861000000, 67000000, 68000000, 69000000, 86000000, 87000000, 860000000, 861000000,
888000000, 889000000, 70000000, 71000000, 72000000, 73000000, 74000000, 888000000, 889000000, 70000000, 71000000, 72000000, 73000000, 74000000,
75000000, 76000000, 77000000, 78000000, 79000000, 96000000, 97000000, 75000000, 76000000, 77000000, 78000000, 79000000, 96000000, 97000000,
870000000, 871000000, 898000000, 899000000, 100000000, 101000000, 102000000, 870000000, 871000000, 898000000, 899000000, 100000000, 101000000, 102000000,
103000000, 104000000, 105000000, 106000000, 107000000, 108000000, 109000000, 103000000, 104000000, 105000000, 106000000, 107000000, 108000000, 109000000,
180000000, 181000000, 900000000, 901000000, 980000000, 981000000, 110000000, 180000000, 181000000, 900000000, 901000000, 980000000, 981000000, 110000000,
......
...@@ -34,19 +34,19 @@ ...@@ -34,19 +34,19 @@
/* This module comprises decDouble operations (including conversions) */ /* This module comprises decDouble operations (including conversions) */
/* ------------------------------------------------------------------ */ /* ------------------------------------------------------------------ */
#include "decContext.h" /* public includes */ #include "decContext.h" /* public includes */
#include "decDouble.h" /* .. */ #include "decDouble.h" /* .. */
/* Constant mappings for shared code */ /* Constant mappings for shared code */
#define DECPMAX DECDOUBLE_Pmax #define DECPMAX DECDOUBLE_Pmax
#define DECEMIN DECDOUBLE_Emin #define DECEMIN DECDOUBLE_Emin
#define DECEMAX DECDOUBLE_Emax #define DECEMAX DECDOUBLE_Emax
#define DECEMAXD DECDOUBLE_EmaxD #define DECEMAXD DECDOUBLE_EmaxD
#define DECBYTES DECDOUBLE_Bytes #define DECBYTES DECDOUBLE_Bytes
#define DECSTRING DECDOUBLE_String #define DECSTRING DECDOUBLE_String
#define DECECONL DECDOUBLE_EconL #define DECECONL DECDOUBLE_EconL
#define DECBIAS DECDOUBLE_Bias #define DECBIAS DECDOUBLE_Bias
#define DECLETS DECDOUBLE_Declets #define DECLETS DECDOUBLE_Declets
#define DECQTINY (-DECDOUBLE_Bias) #define DECQTINY (-DECDOUBLE_Bias)
/* parameters of next-wider format */ /* parameters of next-wider format */
#define DECWBYTES DECQUAD_Bytes #define DECWBYTES DECQUAD_Bytes
...@@ -55,100 +55,98 @@ ...@@ -55,100 +55,98 @@
#define DECWBIAS DECQUAD_Bias #define DECWBIAS DECQUAD_Bias
/* Type and function mappings for shared code */ /* Type and function mappings for shared code */
#define decFloat decDouble /* Type name */ #define decFloat decDouble /* Type name */
#define decFloatWider decQuad /* Type name */ #define decFloatWider decQuad /* Type name */
/* Utilities and conversions (binary results, extractors, etc.) */ /* Utilities and conversions (binary results, extractors, etc.) */
#define decFloatFromBCD decDoubleFromBCD #define decFloatFromBCD decDoubleFromBCD
#define decFloatFromInt32 decDoubleFromInt32 #define decFloatFromInt32 decDoubleFromInt32
#define decFloatFromPacked decDoubleFromPacked #define decFloatFromPacked decDoubleFromPacked
#define decFloatFromString decDoubleFromString #define decFloatFromPackedChecked decDoubleFromPackedChecked
#define decFloatFromUInt32 decDoubleFromUInt32 #define decFloatFromString decDoubleFromString
#define decFloatFromWider decDoubleFromWider #define decFloatFromUInt32 decDoubleFromUInt32
#define decFloatGetCoefficient decDoubleGetCoefficient #define decFloatFromWider decDoubleFromWider
#define decFloatGetExponent decDoubleGetExponent #define decFloatGetCoefficient decDoubleGetCoefficient
#define decFloatSetCoefficient decDoubleSetCoefficient #define decFloatGetExponent decDoubleGetExponent
#define decFloatSetExponent decDoubleSetExponent #define decFloatSetCoefficient decDoubleSetCoefficient
#define decFloatShow decDoubleShow #define decFloatSetExponent decDoubleSetExponent
#define decFloatToBCD decDoubleToBCD #define decFloatShow decDoubleShow
#define decFloatToEngString decDoubleToEngString #define decFloatToBCD decDoubleToBCD
#define decFloatToInt32 decDoubleToInt32 #define decFloatToEngString decDoubleToEngString
#define decFloatToInt32Exact decDoubleToInt32Exact #define decFloatToInt32 decDoubleToInt32
#define decFloatToPacked decDoubleToPacked #define decFloatToInt32Exact decDoubleToInt32Exact
#define decFloatToString decDoubleToString #define decFloatToPacked decDoubleToPacked
#define decFloatToUInt32 decDoubleToUInt32 #define decFloatToString decDoubleToString
#define decFloatToUInt32Exact decDoubleToUInt32Exact #define decFloatToUInt32 decDoubleToUInt32
#define decFloatToWider decDoubleToWider #define decFloatToUInt32Exact decDoubleToUInt32Exact
#define decFloatZero decDoubleZero #define decFloatToWider decDoubleToWider
#define decFloatZero decDoubleZero
/* Computational (result is a decFloat) */ /* Computational (result is a decFloat) */
#define decFloatAbs decDoubleAbs #define decFloatAbs decDoubleAbs
#define decFloatAdd decDoubleAdd #define decFloatAdd decDoubleAdd
#define decFloatAnd decDoubleAnd #define decFloatAnd decDoubleAnd
#define decFloatDivide decDoubleDivide #define decFloatDivide decDoubleDivide
#define decFloatDivideInteger decDoubleDivideInteger #define decFloatDivideInteger decDoubleDivideInteger
#define decFloatFMA decDoubleFMA #define decFloatFMA decDoubleFMA
#define decFloatInvert decDoubleInvert #define decFloatInvert decDoubleInvert
#define decFloatLogB decDoubleLogB #define decFloatLogB decDoubleLogB
#define decFloatMax decDoubleMax #define decFloatMax decDoubleMax
#define decFloatMaxMag decDoubleMaxMag #define decFloatMaxMag decDoubleMaxMag
#define decFloatMin decDoubleMin #define decFloatMin decDoubleMin
#define decFloatMinMag decDoubleMinMag #define decFloatMinMag decDoubleMinMag
#define decFloatMinus decDoubleMinus #define decFloatMinus decDoubleMinus
#define decFloatMultiply decDoubleMultiply #define decFloatMultiply decDoubleMultiply
#define decFloatNextMinus decDoubleNextMinus #define decFloatNextMinus decDoubleNextMinus
#define decFloatNextPlus decDoubleNextPlus #define decFloatNextPlus decDoubleNextPlus
#define decFloatNextToward decDoubleNextToward #define decFloatNextToward decDoubleNextToward
#define decFloatOr decDoubleOr #define decFloatOr decDoubleOr
#define decFloatPlus decDoublePlus #define decFloatPlus decDoublePlus
#define decFloatQuantize decDoubleQuantize #define decFloatQuantize decDoubleQuantize
#define decFloatReduce decDoubleReduce #define decFloatReduce decDoubleReduce
#define decFloatRemainder decDoubleRemainder #define decFloatRemainder decDoubleRemainder
#define decFloatRemainderNear decDoubleRemainderNear #define decFloatRemainderNear decDoubleRemainderNear
#define decFloatRotate decDoubleRotate #define decFloatRotate decDoubleRotate
#define decFloatScaleB decDoubleScaleB #define decFloatScaleB decDoubleScaleB
#define decFloatShift decDoubleShift #define decFloatShift decDoubleShift
#define decFloatSubtract decDoubleSubtract #define decFloatSubtract decDoubleSubtract
#define decFloatToIntegralValue decDoubleToIntegralValue #define decFloatToIntegralValue decDoubleToIntegralValue
#define decFloatToIntegralExact decDoubleToIntegralExact #define decFloatToIntegralExact decDoubleToIntegralExact
#define decFloatXor decDoubleXor #define decFloatXor decDoubleXor
/* Comparisons */ /* Comparisons */
#define decFloatCompare decDoubleCompare #define decFloatCompare decDoubleCompare
#define decFloatCompareSignal decDoubleCompareSignal #define decFloatCompareSignal decDoubleCompareSignal
#define decFloatCompareTotal decDoubleCompareTotal #define decFloatCompareTotal decDoubleCompareTotal
#define decFloatCompareTotalMag decDoubleCompareTotalMag #define decFloatCompareTotalMag decDoubleCompareTotalMag
/* Copies */ /* Copies */
#define decFloatCanonical decDoubleCanonical #define decFloatCanonical decDoubleCanonical
#define decFloatCopy decDoubleCopy #define decFloatCopy decDoubleCopy
#define decFloatCopyAbs decDoubleCopyAbs #define decFloatCopyAbs decDoubleCopyAbs
#define decFloatCopyNegate decDoubleCopyNegate #define decFloatCopyNegate decDoubleCopyNegate
#define decFloatCopySign decDoubleCopySign #define decFloatCopySign decDoubleCopySign
/* Non-computational */ /* Non-computational */
#define decFloatClass decDoubleClass #define decFloatClass decDoubleClass
#define decFloatClassString decDoubleClassString #define decFloatClassString decDoubleClassString
#define decFloatDigits decDoubleDigits #define decFloatDigits decDoubleDigits
#define decFloatIsCanonical decDoubleIsCanonical #define decFloatIsCanonical decDoubleIsCanonical
#define decFloatIsFinite decDoubleIsFinite #define decFloatIsFinite decDoubleIsFinite
#define decFloatIsInfinite decDoubleIsInfinite #define decFloatIsInfinite decDoubleIsInfinite
#define decFloatIsInteger decDoubleIsInteger #define decFloatIsInteger decDoubleIsInteger
#define decFloatIsNaN decDoubleIsNaN #define decFloatIsNaN decDoubleIsNaN
#define decFloatIsNormal decDoubleIsNormal #define decFloatIsNormal decDoubleIsNormal
#define decFloatIsSignaling decDoubleIsSignaling #define decFloatIsSignaling decDoubleIsSignaling
#define decFloatIsSignalling decDoubleIsSignalling #define decFloatIsSignalling decDoubleIsSignalling
#define decFloatIsSigned decDoubleIsSigned #define decFloatIsSigned decDoubleIsSigned
#define decFloatIsSubnormal decDoubleIsSubnormal #define decFloatIsSubnormal decDoubleIsSubnormal
#define decFloatIsZero decDoubleIsZero #define decFloatIsZero decDoubleIsZero
#define decFloatRadix decDoubleRadix #define decFloatRadix decDoubleRadix
#define decFloatSameQuantum decDoubleSameQuantum #define decFloatSameQuantum decDoubleSameQuantum
#define decFloatVersion decDoubleVersion #define decFloatVersion decDoubleVersion
#include "decNumberLocal.h" /* local includes (need DECPMAX) */ #include "decNumberLocal.h" /* local includes (need DECPMAX) */
#include "decCommon.c" /* non-arithmetic decFloat routines */ #include "decCommon.c" /* non-arithmetic decFloat routines */
#include "decBasic.c" /* basic formats routines */ #include "decBasic.c" /* basic formats routines */
/* Below here will move to shared file as completed */
...@@ -31,24 +31,22 @@ ...@@ -31,24 +31,22 @@
/* ------------------------------------------------------------------ */ /* ------------------------------------------------------------------ */
/* decDouble.h -- Decimal 64-bit format module header */ /* decDouble.h -- Decimal 64-bit format module header */
/* ------------------------------------------------------------------ */ /* ------------------------------------------------------------------ */
/* Please see decFloats.h for an overview and documentation details. */
/* ------------------------------------------------------------------ */
#if !defined(DECDOUBLE) #if !defined(DECDOUBLE)
#define DECDOUBLE #define DECDOUBLE
#define DECDOUBLENAME "decimalDouble" /* Short name */ #define DECDOUBLENAME "decimalDouble" /* Short name */
#define DECDOUBLETITLE "Decimal 64-bit datum" /* Verbose name */ #define DECDOUBLETITLE "Decimal 64-bit datum" /* Verbose name */
#define DECDOUBLEAUTHOR "Mike Cowlishaw" /* Who to blame */ #define DECDOUBLEAUTHOR "Mike Cowlishaw" /* Who to blame */
/* parameters for decDoubles */ /* parameters for decDoubles */
#define DECDOUBLE_Bytes 8 /* length */ #define DECDOUBLE_Bytes 8 /* length */
#define DECDOUBLE_Pmax 16 /* maximum precision (digits) */ #define DECDOUBLE_Pmax 16 /* maximum precision (digits) */
#define DECDOUBLE_Emin -383 /* minimum adjusted exponent */ #define DECDOUBLE_Emin -383 /* minimum adjusted exponent */
#define DECDOUBLE_Emax 384 /* maximum adjusted exponent */ #define DECDOUBLE_Emax 384 /* maximum adjusted exponent */
#define DECDOUBLE_EmaxD 3 /* maximum exponent digits */ #define DECDOUBLE_EmaxD 3 /* maximum exponent digits */
#define DECDOUBLE_Bias 398 /* bias for the exponent */ #define DECDOUBLE_Bias 398 /* bias for the exponent */
#define DECDOUBLE_String 25 /* maximum string length, +1 */ #define DECDOUBLE_String 25 /* maximum string length, +1 */
#define DECDOUBLE_EconL 8 /* exponent continuation length */ #define DECDOUBLE_EconL 8 /* exponent continuation length */
#define DECDOUBLE_Declets 5 /* count of declets */ #define DECDOUBLE_Declets 5 /* count of declets */
/* highest biased exponent (Elimit-1) */ /* highest biased exponent (Elimit-1) */
...@@ -58,11 +56,14 @@ ...@@ -58,11 +56,14 @@
#include "decContext.h" #include "decContext.h"
#include "decQuad.h" #include "decQuad.h"
/* The decDouble decimal 64-bit type, accessible by various types */ /* The decDouble decimal 64-bit type, accessible by all sizes */
typedef union { typedef union {
uint8_t bytes[DECDOUBLE_Bytes]; /* fields: 1, 5, 8, 50 bits */ uint8_t bytes[DECDOUBLE_Bytes]; /* fields: 1, 5, 8, 50 bits */
uint16_t shorts[DECDOUBLE_Bytes/2]; uint16_t shorts[DECDOUBLE_Bytes/2];
uint32_t words[DECDOUBLE_Bytes/4]; uint32_t words[DECDOUBLE_Bytes/4];
#if DECUSE64
uint64_t longs[DECDOUBLE_Bytes/8];
#endif
} decDouble; } decDouble;
/* ---------------------------------------------------------------- */ /* ---------------------------------------------------------------- */
...@@ -75,6 +76,7 @@ ...@@ -75,6 +76,7 @@
extern decDouble * decDoubleFromBCD(decDouble *, int32_t, const uint8_t *, int32_t); extern decDouble * decDoubleFromBCD(decDouble *, int32_t, const uint8_t *, int32_t);
extern decDouble * decDoubleFromInt32(decDouble *, int32_t); extern decDouble * decDoubleFromInt32(decDouble *, int32_t);
extern decDouble * decDoubleFromPacked(decDouble *, int32_t, const uint8_t *); extern decDouble * decDoubleFromPacked(decDouble *, int32_t, const uint8_t *);
extern decDouble * decDoubleFromPackedChecked(decDouble *, int32_t, const uint8_t *);
extern decDouble * decDoubleFromString(decDouble *, const char *, decContext *); extern decDouble * decDoubleFromString(decDouble *, const char *, decContext *);
extern decDouble * decDoubleFromUInt32(decDouble *, uint32_t); extern decDouble * decDoubleFromUInt32(decDouble *, uint32_t);
extern decDouble * decDoubleFromWider(decDouble *, const decQuad *, decContext *); extern decDouble * decDoubleFromWider(decDouble *, const decQuad *, decContext *);
...@@ -160,7 +162,8 @@ ...@@ -160,7 +162,8 @@
/* decNumber conversions; these are implemented as macros so as not */ /* decNumber conversions; these are implemented as macros so as not */
/* to force a dependency on decimal64 and decNumber in decDouble. */ /* to force a dependency on decimal64 and decNumber in decDouble. */
/* decDoubleFromNumber returns a decimal64 * to avoid warnings. */
#define decDoubleToNumber(dq, dn) decimal64ToNumber((decimal64 *)(dq), dn) #define decDoubleToNumber(dq, dn) decimal64ToNumber((decimal64 *)(dq), dn)
#define decDoubleFromNumber(dq, dn, set) (decDouble *)decimal64FromNumber((decimal64 *)(dq), dn, set) #define decDoubleFromNumber(dq, dn, set) decimal64FromNumber((decimal64 *)(dq), dn, set)
#endif #endif
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -46,7 +46,7 @@ ...@@ -46,7 +46,7 @@
#define DECNEG 0x80 /* Sign; 1=negative, 0=positive or zero */ #define DECNEG 0x80 /* Sign; 1=negative, 0=positive or zero */
#define DECINF 0x40 /* 1=Infinity */ #define DECINF 0x40 /* 1=Infinity */
#define DECNAN 0x20 /* 1=NaN */ #define DECNAN 0x20 /* 1=NaN */
#define DECSNAN 0x10 /* 1=sNaN */ #define DECSNAN 0x10 /* 1=sNaN */
/* The remaining bits are reserved; they must be 0 */ /* The remaining bits are reserved; they must be 0 */
#define DECSPECIAL (DECINF|DECNAN|DECSNAN) /* any special value */ #define DECSPECIAL (DECINF|DECNAN|DECSNAN) /* any special value */
...@@ -124,7 +124,7 @@ ...@@ -124,7 +124,7 @@
uint8_t * decNumberGetBCD(const decNumber *, uint8_t *); uint8_t * decNumberGetBCD(const decNumber *, uint8_t *);
decNumber * decNumberSetBCD(decNumber *, const uint8_t *, uint32_t); decNumber * decNumberSetBCD(decNumber *, const uint8_t *, uint32_t);
/* Operators and elementary functions */ /* Operators and elementary functions */
decNumber * decNumberAbs(decNumber *, const decNumber *, decContext *); decNumber * decNumberAbs(decNumber *, const decNumber *, decContext *);
decNumber * decNumberAdd(decNumber *, const decNumber *, const decNumber *, decContext *); decNumber * decNumberAdd(decNumber *, const decNumber *, const decNumber *, decContext *);
decNumber * decNumberAnd(decNumber *, const decNumber *, const decNumber *, decContext *); decNumber * decNumberAnd(decNumber *, const decNumber *, const decNumber *, decContext *);
...@@ -185,7 +185,7 @@ ...@@ -185,7 +185,7 @@
/* Macros for testing decNumber *dn */ /* Macros for testing decNumber *dn */
#define decNumberIsCanonical(dn) (1) /* All decNumbers are saintly */ #define decNumberIsCanonical(dn) (1) /* All decNumbers are saintly */
#define decNumberIsFinite(dn) (((dn)->bits&DECSPECIAL)==0) #define decNumberIsFinite(dn) (((dn)->bits&DECSPECIAL)==0)
#define decNumberIsInfinite(dn) (((dn)->bits&DECINF)!=0) #define decNumberIsInfinite(dn) (((dn)->bits&DECINF)!=0)
#define decNumberIsNaN(dn) (((dn)->bits&(DECNAN|DECSNAN))!=0) #define decNumberIsNaN(dn) (((dn)->bits&(DECNAN|DECSNAN))!=0)
#define decNumberIsNegative(dn) (((dn)->bits&DECNEG)!=0) #define decNumberIsNegative(dn) (((dn)->bits&DECNEG)!=0)
......
...@@ -31,42 +31,48 @@ ...@@ -31,42 +31,48 @@
/* ------------------------------------------------------------------ */ /* ------------------------------------------------------------------ */
/* decNumber package local type, tuning, and macro definitions */ /* decNumber package local type, tuning, and macro definitions */
/* ------------------------------------------------------------------ */ /* ------------------------------------------------------------------ */
/* This header file is included by all modules in the decNumber */ /* This header file is included by all modules in the decNumber */
/* library, and contains local type definitions, tuning parameters, */ /* library, and contains local type definitions, tuning parameters, */
/* etc. It should not need to be used by application programs. */ /* etc. It should not need to be used by application programs. */
/* decNumber.h or one of decDouble (etc.) must be included first. */ /* decNumber.h or one of decDouble (etc.) must be included first. */
/* ------------------------------------------------------------------ */ /* ------------------------------------------------------------------ */
#if !defined(DECNUMBERLOC) #if !defined(DECNUMBERLOC)
#define DECNUMBERLOC #define DECNUMBERLOC
#define DECVERSION "decNumber 3.53" /* Package Version [16 max.] */ #define DECVERSION "decNumber 3.61" /* Package Version [16 max.] */
#define DECNLAUTHOR "Mike Cowlishaw" /* Who to blame */ #define DECNLAUTHOR "Mike Cowlishaw" /* Who to blame */
#include <stdlib.h> /* for abs */ #include <stdlib.h> /* for abs */
#include <string.h> /* for memset, strcpy */ #include <string.h> /* for memset, strcpy */
#include "dconfig.h" /* for WORDS_BIGENDIAN */
/* Conditional code flag -- set this to match hardware platform */ /* Conditional code flag -- set this to match hardware platform */
/* 1=little-endian, 0=big-endian */ #if !defined(DECLITEND)
#if WORDS_BIGENDIAN #define DECLITEND 1 /* 1=little-endian, 0=big-endian */
#define DECLITEND 0
#else
#define DECLITEND 1
#endif #endif
/* Conditional code flag -- set this to 1 for best performance */ /* Conditional code flag -- set this to 1 for best performance */
#if !defined(DECUSE64)
#define DECUSE64 1 /* 1=use int64s, 0=int32 & smaller only */ #define DECUSE64 1 /* 1=use int64s, 0=int32 & smaller only */
#endif
/* Conditional check flags -- set these to 0 for best performance */ /* Conditional check flags -- set these to 0 for best performance */
#if !defined(DECCHECK)
#define DECCHECK 0 /* 1 to enable robust checking */ #define DECCHECK 0 /* 1 to enable robust checking */
#endif
#if !defined(DECALLOC)
#define DECALLOC 0 /* 1 to enable memory accounting */ #define DECALLOC 0 /* 1 to enable memory accounting */
#endif
#if !defined(DECTRACE)
#define DECTRACE 0 /* 1 to trace certain internals, etc. */ #define DECTRACE 0 /* 1 to trace certain internals, etc. */
#endif
/* Tuning parameter for decNumber (arbitrary precision) module */ /* Tuning parameter for decNumber (arbitrary precision) module */
#if !defined(DECBUFFER)
#define DECBUFFER 36 /* Size basis for local buffers. This */ #define DECBUFFER 36 /* Size basis for local buffers. This */
/* should be a common maximum precision */ /* should be a common maximum precision */
/* rounded up to a multiple of 4; must */ /* rounded up to a multiple of 4; must */
/* be zero or positive. */ /* be zero or positive. */
#endif
/* ---------------------------------------------------------------- */ /* ---------------------------------------------------------------- */
/* Definitions for all modules (general-purpose) */ /* Definitions for all modules (general-purpose) */
...@@ -76,33 +82,33 @@ ...@@ -76,33 +82,33 @@
/* not use int or long directly. */ /* not use int or long directly. */
#define Flag uint8_t #define Flag uint8_t
#define Byte int8_t #define Byte int8_t
#define uByte uint8_t #define uByte uint8_t
#define Short int16_t #define Short int16_t
#define uShort uint16_t #define uShort uint16_t
#define Int int32_t #define Int int32_t
#define uInt uint32_t #define uInt uint32_t
#define Unit decNumberUnit #define Unit decNumberUnit
#if DECUSE64 #if DECUSE64
#define Long int64_t #define Long int64_t
#define uLong uint64_t #define uLong uint64_t
#endif #endif
/* Development-use definitions */ /* Development-use definitions */
typedef long int LI; /* for printf arguments only */ typedef long int LI; /* for printf arguments only */
#define DECNOINT 0 /* 1 to check no internal use of 'int' */ #define DECNOINT 0 /* 1 to check no internal use of 'int' */
/* or stdint types */
#if DECNOINT #if DECNOINT
/* if these interfere with your C includes, do not set DECNOINT */ /* if these interfere with your C includes, do not set DECNOINT */
#define int ? /* enable to ensure that plain C 'int' */ #define int ? /* enable to ensure that plain C 'int' */
#define long ?? /* .. or 'long' types are not used */ #define long ?? /* .. or 'long' types are not used */
#endif #endif
/* Shared lookup tables */ /* Shared lookup tables */
extern const uByte DECSTICKYTAB[10]; /* re-round digits if sticky */ extern const uByte DECSTICKYTAB[10]; /* re-round digits if sticky */
extern const uInt DECPOWERS[10]; /* powers of ten table */ extern const uInt DECPOWERS[10]; /* powers of ten table */
/* The following are included from decDPD.h */ /* The following are included from decDPD.h */
#include "decDPDSymbols.h" extern const uShort DPD2BIN[1024]; /* DPD -> 0-999 */
extern const uShort DPD2BIN[1024]; /* DPD -> 0-999 */ extern const uShort BIN2DPD[1000]; /* 0-999 -> DPD */
extern const uShort BIN2DPD[1000]; /* 0-999 -> DPD */
extern const uInt DPD2BINK[1024]; /* DPD -> 0-999000 */ extern const uInt DPD2BINK[1024]; /* DPD -> 0-999000 */
extern const uInt DPD2BINM[1024]; /* DPD -> 0-999000000 */ extern const uInt DPD2BINM[1024]; /* DPD -> 0-999000000 */
extern const uByte DPD2BCD8[4096]; /* DPD -> ddd + len */ extern const uByte DPD2BCD8[4096]; /* DPD -> ddd + len */
...@@ -111,32 +117,42 @@ ...@@ -111,32 +117,42 @@
/* LONGMUL32HI -- set w=(u*v)>>32, where w, u, and v are uInts */ /* LONGMUL32HI -- set w=(u*v)>>32, where w, u, and v are uInts */
/* (that is, sets w to be the high-order word of the 64-bit result; */ /* (that is, sets w to be the high-order word of the 64-bit result; */
/* the low-order word is simply u*v.) */ /* the low-order word is simply u*v.) */
/* This version is derived from Knuth via Hacker's Delight; */ /* This version is derived from Knuth via Hacker's Delight; */
/* it seems to optimize better than some others tried */ /* it seems to optimize better than some others tried */
#define LONGMUL32HI(w, u, v) { \ #define LONGMUL32HI(w, u, v) { \
uInt u0, u1, v0, v1, w0, w1, w2, t; \ uInt u0, u1, v0, v1, w0, w1, w2, t; \
u0=u & 0xffff; u1=u>>16; \ u0=u & 0xffff; u1=u>>16; \
v0=v & 0xffff; v1=v>>16; \ v0=v & 0xffff; v1=v>>16; \
w0=u0*v0; \ w0=u0*v0; \
t=u1*v0 + (w0>>16); \ t=u1*v0 + (w0>>16); \
w1=t & 0xffff; w2=t>>16; \ w1=t & 0xffff; w2=t>>16; \
w1=u0*v1 + w1; \ w1=u0*v1 + w1; \
(w)=u1*v1 + w2 + (w1>>16);} (w)=u1*v1 + w2 + (w1>>16);}
/* ROUNDUP -- round an integer up to a multiple of n */ /* ROUNDUP -- round an integer up to a multiple of n */
#define ROUNDUP(i, n) ((((i)+(n)-1)/n)*n) #define ROUNDUP(i, n) ((((i)+(n)-1)/n)*n)
#define ROUNDUP4(i) (((i)+3)&~3) /* special for n=4 */
/* ROUNDDOWN -- round an integer down to a multiple of n */ /* ROUNDDOWN -- round an integer down to a multiple of n */
#define ROUNDDOWN(i, n) (((i)/n)*n) #define ROUNDDOWN(i, n) (((i)/n)*n)
#define ROUNDDOWN4(i) ((i)&~3) /* special for n=4 */ #define ROUNDDOWN4(i) ((i)&~3) /* special for n=4 */
/* References to multi-byte sequences under different sizes; these */
/* require locally declared variables, but do not violate strict */
/* aliasing or alignment (as did the UINTAT simple cast to uInt). */
/* Variables needed are uswork, uiwork, etc. [so do not use at same */
/* level in an expression, e.g., UBTOUI(x)==UBTOUI(y) may fail]. */
/* References to multi-byte sequences under different sizes */ /* Return a uInt, etc., from bytes starting at a char* or uByte* */
/* Refer to a uInt from four bytes starting at a char* or uByte*, */ #define UBTOUS(b) (memcpy((void *)&uswork, b, 2), uswork)
/* etc. */ #define UBTOUI(b) (memcpy((void *)&uiwork, b, 4), uiwork)
#define UINTAT(b) (*((uInt *)(b)))
#define USHORTAT(b) (*((uShort *)(b))) /* Store a uInt, etc., into bytes starting at a char* or uByte*. */
#define UBYTEAT(b) (*((uByte *)(b))) /* Returns i, evaluated, for convenience; has to use uiwork because */
/* i may be an expression. */
#define UBFROMUS(b, i) (uswork=(i), memcpy(b, (void *)&uswork, 2), uswork)
#define UBFROMUI(b, i) (uiwork=(i), memcpy(b, (void *)&uiwork, 4), uiwork)
/* X10 and X100 -- multiply integer i by 10 or 100 */ /* X10 and X100 -- multiply integer i by 10 or 100 */
/* [shifts are usually faster than multiply; could be conditional] */ /* [shifts are usually faster than multiply; could be conditional] */
...@@ -149,7 +165,7 @@ ...@@ -149,7 +165,7 @@
/* Useful constants */ /* Useful constants */
#define BILLION 1000000000 /* 10**9 */ #define BILLION 1000000000 /* 10**9 */
/* CHARMASK: 0x30303030 for ASCII/UTF8; 0xF0F0F0F0 for EBCDIC */ /* CHARMASK: 0x30303030 for ASCII/UTF8; 0xF0F0F0F0 for EBCDIC */
#define CHARMASK ((((((((uInt)'0')<<8)+'0')<<8)+'0')<<8)+'0') #define CHARMASK ((((((((uInt)'0')<<8)+'0')<<8)+'0')<<8)+'0')
...@@ -172,7 +188,7 @@ ...@@ -172,7 +188,7 @@
#error Minimum exponent mismatch #error Minimum exponent mismatch
#endif #endif
/* Set DECDPUNMAX -- the maximum integer that fits in DECDPUN */ /* Set DECDPUNMAX -- the maximum integer that fits in DECDPUN */
/* digits, and D2UTABLE -- the initializer for the D2U table */ /* digits, and D2UTABLE -- the initializer for the D2U table */
#if DECDPUN==1 #if DECDPUN==1
#define DECDPUNMAX 9 #define DECDPUNMAX 9
...@@ -253,7 +269,7 @@ ...@@ -253,7 +269,7 @@
/* D2N -- return the number of decNumber structs that would be */ /* D2N -- return the number of decNumber structs that would be */
/* needed to contain that number of digits (and the initial */ /* needed to contain that number of digits (and the initial */
/* decNumber struct) safely. Note that one Unit is included in the */ /* decNumber struct) safely. Note that one Unit is included in the */
/* initial structure. Used for allocating space that is aligned on */ /* initial structure. Used for allocating space that is aligned on */
/* a decNumber struct boundary. */ /* a decNumber struct boundary. */
#define D2N(d) \ #define D2N(d) \
((((SD2U(d)-1)*sizeof(Unit))+sizeof(decNumber)*2-1)/sizeof(decNumber)) ((((SD2U(d)-1)*sizeof(Unit))+sizeof(decNumber)*2-1)/sizeof(decNumber))
...@@ -261,7 +277,7 @@ ...@@ -261,7 +277,7 @@
/* TODIGIT -- macro to remove the leading digit from the unsigned */ /* TODIGIT -- macro to remove the leading digit from the unsigned */
/* integer u at column cut (counting from the right, LSD=0) and */ /* integer u at column cut (counting from the right, LSD=0) and */
/* place it as an ASCII character into the character pointed to by */ /* place it as an ASCII character into the character pointed to by */
/* c. Note that cut must be <= 9, and the maximum value for u is */ /* c. Note that cut must be <= 9, and the maximum value for u is */
/* 2,000,000,000 (as is needed for negative exponents of */ /* 2,000,000,000 (as is needed for negative exponents of */
/* subnormals). The unsigned integer pow is used as a temporary */ /* subnormals). The unsigned integer pow is used as a temporary */
/* variable. */ /* variable. */
...@@ -274,7 +290,7 @@ ...@@ -274,7 +290,7 @@
pow/=2; \ pow/=2; \
if ((u)>=pow) {(u)-=pow; *(c)+=4;} \ if ((u)>=pow) {(u)-=pow; *(c)+=4;} \
pow/=2; \ pow/=2; \
} \ } \
if ((u)>=pow) {(u)-=pow; *(c)+=2;} \ if ((u)>=pow) {(u)-=pow; *(c)+=2;} \
pow/=2; \ pow/=2; \
if ((u)>=pow) {(u)-=pow; *(c)+=1;} \ if ((u)>=pow) {(u)-=pow; *(c)+=1;} \
...@@ -289,9 +305,9 @@ ...@@ -289,9 +305,9 @@
/* number, whose coefficient is a string of bcd8 uBytes */ /* number, whose coefficient is a string of bcd8 uBytes */
typedef struct { typedef struct {
uByte *msd; /* -> most significant digit */ uByte *msd; /* -> most significant digit */
uByte *lsd; /* -> least ditto */ uByte *lsd; /* -> least ditto */
uInt sign; /* 0=positive, DECFLOAT_Sign=negative */ uInt sign; /* 0=positive, DECFLOAT_Sign=negative */
Int exponent; /* Unadjusted signed exponent (q), or */ Int exponent; /* Unadjusted signed exponent (q), or */
/* DECFLOAT_NaN etc. for a special */ /* DECFLOAT_NaN etc. for a special */
} bcdnum; } bcdnum;
...@@ -308,12 +324,12 @@ ...@@ -308,12 +324,12 @@
#define DECWORDS (DECBYTES/4) #define DECWORDS (DECBYTES/4)
#define DECWWORDS (DECWBYTES/4) #define DECWWORDS (DECWBYTES/4)
#if DECLITEND #if DECLITEND
#define DFWORD(df, off) ((df)->words[DECWORDS-1-(off)]) #define DFBYTE(df, off) ((df)->bytes[DECBYTES-1-(off)])
#define DFBYTE(df, off) ((df)->bytes[DECBYTES-1-(off)]) #define DFWORD(df, off) ((df)->words[DECWORDS-1-(off)])
#define DFWWORD(dfw, off) ((dfw)->words[DECWWORDS-1-(off)]) #define DFWWORD(dfw, off) ((dfw)->words[DECWWORDS-1-(off)])
#else #else
#define DFWORD(df, off) ((df)->words[off]) #define DFBYTE(df, off) ((df)->bytes[off])
#define DFBYTE(df, off) ((df)->bytes[off]) #define DFWORD(df, off) ((df)->words[off])
#define DFWWORD(dfw, off) ((dfw)->words[off]) #define DFWWORD(dfw, off) ((dfw)->words[off])
#endif #endif
...@@ -326,7 +342,6 @@ ...@@ -326,7 +342,6 @@
#define DFISSNAN(df) ((DFWORD(df, 0)&0x7e000000)==0x7e000000) #define DFISSNAN(df) ((DFWORD(df, 0)&0x7e000000)==0x7e000000)
/* Shared lookup tables */ /* Shared lookup tables */
#include "decCommonSymbols.h"
extern const uInt DECCOMBMSD[64]; /* Combination field -> MSD */ extern const uInt DECCOMBMSD[64]; /* Combination field -> MSD */
extern const uInt DECCOMBFROM[48]; /* exp+msd -> Combination */ extern const uInt DECCOMBFROM[48]; /* exp+msd -> Combination */
...@@ -338,7 +353,7 @@ ...@@ -338,7 +353,7 @@
/* Format-dependent macros and constants */ /* Format-dependent macros and constants */
#if defined(DECPMAX) #if defined(DECPMAX)
/* Useful constants */ /* Useful constants */
#define DECPMAX9 (ROUNDUP(DECPMAX, 9)/9) /* 'Pmax' in 10**9s */ #define DECPMAX9 (ROUNDUP(DECPMAX, 9)/9) /* 'Pmax' in 10**9s */
/* Top words for a zero */ /* Top words for a zero */
#define SINGLEZERO 0x22500000 #define SINGLEZERO 0x22500000
...@@ -350,10 +365,10 @@ ...@@ -350,10 +365,10 @@
/* DFISZERO -- test for (any) zero */ /* DFISZERO -- test for (any) zero */
/* DFISCCZERO -- test for coefficient continuation being zero */ /* DFISCCZERO -- test for coefficient continuation being zero */
/* DFISCC01 -- test for coefficient contains only 0s and 1s */ /* DFISCC01 -- test for coefficient contains only 0s and 1s */
/* DFISINT -- test for finite and exponent q=0 */ /* DFISINT -- test for finite and exponent q=0 */
/* DFISUINT01 -- test for sign=0, finite, exponent q=0, and */ /* DFISUINT01 -- test for sign=0, finite, exponent q=0, and */
/* MSD=0 or 1 */ /* MSD=0 or 1 */
/* ZEROWORD is also defined here. */ /* ZEROWORD is also defined here. */
/* In DFISZERO the first test checks the least-significant word */ /* In DFISZERO the first test checks the least-significant word */
/* (most likely to be non-zero); the penultimate tests MSD and */ /* (most likely to be non-zero); the penultimate tests MSD and */
/* DPDs in the signword, and the final test excludes specials and */ /* DPDs in the signword, and the final test excludes specials and */
...@@ -407,26 +422,36 @@ ...@@ -407,26 +422,36 @@
|| ((dpd)&(((uInt)0x6e)<<(k)))!=(((uInt)0x6e)<<(k))) || ((dpd)&(((uInt)0x6e)<<(k)))!=(((uInt)0x6e)<<(k)))
/* declet is at offset k (a multiple of 2) in a pair of uInts: */ /* declet is at offset k (a multiple of 2) in a pair of uInts: */
/* [the top 2 bits will always be in the more-significant uInt] */ /* [the top 2 bits will always be in the more-significant uInt] */
#define CANONDPDTWO(hi, lo, k) (((hi)&(0x300>>(32-(k))))==0 \ #define CANONDPDTWO(hi, lo, k) (((hi)&(0x300>>(32-(k))))==0 \
|| ((hi)&(0x6e>>(32-(k))))!=(0x6e>>(32-(k))) \ || ((hi)&(0x6e>>(32-(k))))!=(0x6e>>(32-(k))) \
|| ((lo)&(((uInt)0x6e)<<(k)))!=(((uInt)0x6e)<<(k))) || ((lo)&(((uInt)0x6e)<<(k)))!=(((uInt)0x6e)<<(k)))
/* Macro to test whether a full-length (length DECPMAX) BCD8 */ /* Macro to test whether a full-length (length DECPMAX) BCD8 */
/* coefficient is zero */ /* coefficient, starting at uByte u, is all zeros */
/* test just the LSWord first, then the remainder */ /* Test just the LSWord first, then the remainder as a sequence */
/* of tests in order to avoid same-level use of UBTOUI */
#if DECPMAX==7 #if DECPMAX==7
#define ISCOEFFZERO(u) (UINTAT((u)+DECPMAX-4)==0 \ #define ISCOEFFZERO(u) ( \
&& UINTAT((u)+DECPMAX-7)==0) UBTOUI((u)+DECPMAX-4)==0 \
&& UBTOUS((u)+DECPMAX-6)==0 \
&& *(u)==0)
#elif DECPMAX==16 #elif DECPMAX==16
#define ISCOEFFZERO(u) (UINTAT((u)+DECPMAX-4)==0 \ #define ISCOEFFZERO(u) ( \
&& (UINTAT((u)+DECPMAX-8)+UINTAT((u)+DECPMAX-12) \ UBTOUI((u)+DECPMAX-4)==0 \
+UINTAT((u)+DECPMAX-16))==0) && UBTOUI((u)+DECPMAX-8)==0 \
&& UBTOUI((u)+DECPMAX-12)==0 \
&& UBTOUI(u)==0)
#elif DECPMAX==34 #elif DECPMAX==34
#define ISCOEFFZERO(u) (UINTAT((u)+DECPMAX-4)==0 \ #define ISCOEFFZERO(u) ( \
&& (UINTAT((u)+DECPMAX-8) +UINTAT((u)+DECPMAX-12) \ UBTOUI((u)+DECPMAX-4)==0 \
+UINTAT((u)+DECPMAX-16)+UINTAT((u)+DECPMAX-20) \ && UBTOUI((u)+DECPMAX-8)==0 \
+UINTAT((u)+DECPMAX-24)+UINTAT((u)+DECPMAX-28) \ && UBTOUI((u)+DECPMAX-12)==0 \
+UINTAT((u)+DECPMAX-32)+USHORTAT((u)+DECPMAX-34))==0) && UBTOUI((u)+DECPMAX-16)==0 \
&& UBTOUI((u)+DECPMAX-20)==0 \
&& UBTOUI((u)+DECPMAX-24)==0 \
&& UBTOUI((u)+DECPMAX-28)==0 \
&& UBTOUI((u)+DECPMAX-32)==0 \
&& UBTOUS(u)==0)
#endif #endif
/* Macros and masks for the exponent continuation field and MSD */ /* Macros and masks for the exponent continuation field and MSD */
...@@ -448,29 +473,24 @@ ...@@ -448,29 +473,24 @@
#define ECONNANMASK ((0x01ffffff>>(32-6-DECECONL))<<(32-6-DECECONL)) #define ECONNANMASK ((0x01ffffff>>(32-6-DECECONL))<<(32-6-DECECONL))
/* Macros to decode the coefficient in a finite decFloat *df into */ /* Macros to decode the coefficient in a finite decFloat *df into */
/* a BCD string (uByte *bcdin) of length DECPMAX uBytes */ /* a BCD string (uByte *bcdin) of length DECPMAX uBytes. */
/* In-line sequence to convert 10 bits at right end of uInt dpd */
/* to three BCD8 digits starting at uByte u. Note that an extra */
/* byte is written to the right of the three digits because this */
/* moves four at a time for speed; the alternative macro moves */
/* exactly three bytes */
#define dpd2bcd8(u, dpd) { \
UINTAT(u)=UINTAT(&DPD2BCD8[((dpd)&0x3ff)*4]);}
#define dpd2bcd83(u, dpd) { \ /* In-line sequence to convert least significant 10 bits of uInt */
*(u)=DPD2BCD8[((dpd)&0x3ff)*4]; \ /* dpd to three BCD8 digits starting at uByte u. Note that an */
*(u+1)=DPD2BCD8[((dpd)&0x3ff)*4+1]; \ /* extra byte is written to the right of the three digits because */
*(u+2)=DPD2BCD8[((dpd)&0x3ff)*4+2];} /* four bytes are moved at a time for speed; the alternative */
/* macro moves exactly three bytes (usually slower). */
#define dpd2bcd8(u, dpd) memcpy(u, &DPD2BCD8[((dpd)&0x3ff)*4], 4)
#define dpd2bcd83(u, dpd) memcpy(u, &DPD2BCD8[((dpd)&0x3ff)*4], 3)
/* Decode the declets. After extracting each one, it is decoded */ /* Decode the declets. After extracting each one, it is decoded */
/* to BCD8 using a table lookup (also used for variable-length */ /* to BCD8 using a table lookup (also used for variable-length */
/* decode). Each DPD decode is 3 bytes BCD8 plus a one-byte */ /* decode). Each DPD decode is 3 bytes BCD8 plus a one-byte */
/* length which is not used, here). Fixed-length 4-byte moves */ /* length which is not used, here). Fixed-length 4-byte moves */
/* are fast, however, almost everywhere, and so are used except */ /* are fast, however, almost everywhere, and so are used except */
/* for the final three bytes (to avoid overrun). The code below */ /* for the final three bytes (to avoid overrun). The code below */
/* is 36 instructions for Doubles and about 70 for Quads, even */ /* is 36 instructions for Doubles and about 70 for Quads, even */
/* on IA32. */ /* on IA32. */
/* Two macros are defined for each format: */ /* Two macros are defined for each format: */
/* GETCOEFF extracts the coefficient of the current format */ /* GETCOEFF extracts the coefficient of the current format */
...@@ -478,7 +498,7 @@ ...@@ -478,7 +498,7 @@
/* The latter is a copy of the next-wider GETCOEFF using DFWWORD. */ /* The latter is a copy of the next-wider GETCOEFF using DFWWORD. */
#if DECPMAX==7 #if DECPMAX==7
#define GETCOEFF(df, bcd) { \ #define GETCOEFF(df, bcd) { \
uInt sourhi=DFWORD(df, 0); \ uInt sourhi=DFWORD(df, 0); \
*(bcd)=(uByte)DECCOMBMSD[sourhi>>26]; \ *(bcd)=(uByte)DECCOMBMSD[sourhi>>26]; \
dpd2bcd8(bcd+1, sourhi>>10); \ dpd2bcd8(bcd+1, sourhi>>10); \
...@@ -494,7 +514,7 @@ ...@@ -494,7 +514,7 @@
dpd2bcd83(bcd+13, sourlo);} dpd2bcd83(bcd+13, sourlo);}
#elif DECPMAX==16 #elif DECPMAX==16
#define GETCOEFF(df, bcd) { \ #define GETCOEFF(df, bcd) { \
uInt sourhi=DFWORD(df, 0); \ uInt sourhi=DFWORD(df, 0); \
uInt sourlo=DFWORD(df, 1); \ uInt sourlo=DFWORD(df, 1); \
*(bcd)=(uByte)DECCOMBMSD[sourhi>>26]; \ *(bcd)=(uByte)DECCOMBMSD[sourhi>>26]; \
...@@ -522,7 +542,7 @@ ...@@ -522,7 +542,7 @@
dpd2bcd83(bcd+31, sourlo);} dpd2bcd83(bcd+31, sourlo);}
#elif DECPMAX==34 #elif DECPMAX==34
#define GETCOEFF(df, bcd) { \ #define GETCOEFF(df, bcd) { \
uInt sourhi=DFWORD(df, 0); \ uInt sourhi=DFWORD(df, 0); \
uInt sourmh=DFWORD(df, 1); \ uInt sourmh=DFWORD(df, 1); \
uInt sourml=DFWORD(df, 2); \ uInt sourml=DFWORD(df, 2); \
...@@ -540,12 +560,12 @@ ...@@ -540,12 +560,12 @@
dpd2bcd8(bcd+28, sourlo>>10); \ dpd2bcd8(bcd+28, sourlo>>10); \
dpd2bcd83(bcd+31, sourlo);} dpd2bcd83(bcd+31, sourlo);}
#define GETWCOEFF(df, bcd) {??} /* [should never be used] */ #define GETWCOEFF(df, bcd) {??} /* [should never be used] */
#endif #endif
/* Macros to decode the coefficient in a finite decFloat *df into */ /* Macros to decode the coefficient in a finite decFloat *df into */
/* a base-billion uInt array, with the least-significant */ /* a base-billion uInt array, with the least-significant */
/* 0-999999999 'digit' at offset 0. */ /* 0-999999999 'digit' at offset 0. */
/* Decode the declets. After extracting each one, it is decoded */ /* Decode the declets. After extracting each one, it is decoded */
/* to binary using a table lookup. Three tables are used; one */ /* to binary using a table lookup. Three tables are used; one */
...@@ -597,8 +617,8 @@ ...@@ -597,8 +617,8 @@
#endif #endif
/* Macros to decode the coefficient in a finite decFloat *df into */ /* Macros to decode the coefficient in a finite decFloat *df into */
/* a base-thousand uInt array, with the least-significant 0-999 */ /* a base-thousand uInt array (of size DECLETS+1, to allow for */
/* 'digit' at offset 0. */ /* the MSD), with the least-significant 0-999 'digit' at offset 0.*/
/* Decode the declets. After extracting each one, it is decoded */ /* Decode the declets. After extracting each one, it is decoded */
/* to binary using a table lookup. */ /* to binary using a table lookup. */
...@@ -640,9 +660,72 @@ ...@@ -640,9 +660,72 @@
(buf)[9]=DPD2BIN[((sourhi<<6) | (sourmh>>26))&0x3ff]; \ (buf)[9]=DPD2BIN[((sourhi<<6) | (sourmh>>26))&0x3ff]; \
(buf)[10]=DPD2BIN[(sourhi>>4)&0x3ff]; \ (buf)[10]=DPD2BIN[(sourhi>>4)&0x3ff]; \
(buf)[11]=DECCOMBMSD[sourhi>>26];} (buf)[11]=DECCOMBMSD[sourhi>>26];}
#endif
/* Macros to decode the coefficient in a finite decFloat *df and */
/* add to a base-thousand uInt array (as for GETCOEFFTHOU). */
/* After the addition then most significant 'digit' in the array */
/* might have a value larger then 10 (with a maximum of 19). */
#if DECPMAX==7
#define ADDCOEFFTHOU(df, buf) { \
uInt sourhi=DFWORD(df, 0); \
(buf)[0]+=DPD2BIN[sourhi&0x3ff]; \
if (buf[0]>999) {buf[0]-=1000; buf[1]++;} \
(buf)[1]+=DPD2BIN[(sourhi>>10)&0x3ff]; \
if (buf[1]>999) {buf[1]-=1000; buf[2]++;} \
(buf)[2]+=DECCOMBMSD[sourhi>>26];}
#elif DECPMAX==16
#define ADDCOEFFTHOU(df, buf) { \
uInt sourhi, sourlo; \
sourlo=DFWORD(df, 1); \
(buf)[0]+=DPD2BIN[sourlo&0x3ff]; \
if (buf[0]>999) {buf[0]-=1000; buf[1]++;} \
(buf)[1]+=DPD2BIN[(sourlo>>10)&0x3ff]; \
if (buf[1]>999) {buf[1]-=1000; buf[2]++;} \
(buf)[2]+=DPD2BIN[(sourlo>>20)&0x3ff]; \
if (buf[2]>999) {buf[2]-=1000; buf[3]++;} \
sourhi=DFWORD(df, 0); \
(buf)[3]+=DPD2BIN[((sourhi<<2) | (sourlo>>30))&0x3ff]; \
if (buf[3]>999) {buf[3]-=1000; buf[4]++;} \
(buf)[4]+=DPD2BIN[(sourhi>>8)&0x3ff]; \
if (buf[4]>999) {buf[4]-=1000; buf[5]++;} \
(buf)[5]+=DECCOMBMSD[sourhi>>26];}
#elif DECPMAX==34
#define ADDCOEFFTHOU(df, buf) { \
uInt sourhi, sourmh, sourml, sourlo; \
sourlo=DFWORD(df, 3); \
(buf)[0]+=DPD2BIN[sourlo&0x3ff]; \
if (buf[0]>999) {buf[0]-=1000; buf[1]++;} \
(buf)[1]+=DPD2BIN[(sourlo>>10)&0x3ff]; \
if (buf[1]>999) {buf[1]-=1000; buf[2]++;} \
(buf)[2]+=DPD2BIN[(sourlo>>20)&0x3ff]; \
if (buf[2]>999) {buf[2]-=1000; buf[3]++;} \
sourml=DFWORD(df, 2); \
(buf)[3]+=DPD2BIN[((sourml<<2) | (sourlo>>30))&0x3ff]; \
if (buf[3]>999) {buf[3]-=1000; buf[4]++;} \
(buf)[4]+=DPD2BIN[(sourml>>8)&0x3ff]; \
if (buf[4]>999) {buf[4]-=1000; buf[5]++;} \
(buf)[5]+=DPD2BIN[(sourml>>18)&0x3ff]; \
if (buf[5]>999) {buf[5]-=1000; buf[6]++;} \
sourmh=DFWORD(df, 1); \
(buf)[6]+=DPD2BIN[((sourmh<<4) | (sourml>>28))&0x3ff]; \
if (buf[6]>999) {buf[6]-=1000; buf[7]++;} \
(buf)[7]+=DPD2BIN[(sourmh>>6)&0x3ff]; \
if (buf[7]>999) {buf[7]-=1000; buf[8]++;} \
(buf)[8]+=DPD2BIN[(sourmh>>16)&0x3ff]; \
if (buf[8]>999) {buf[8]-=1000; buf[9]++;} \
sourhi=DFWORD(df, 0); \
(buf)[9]+=DPD2BIN[((sourhi<<6) | (sourmh>>26))&0x3ff]; \
if (buf[9]>999) {buf[9]-=1000; buf[10]++;} \
(buf)[10]+=DPD2BIN[(sourhi>>4)&0x3ff]; \
if (buf[10]>999) {buf[10]-=1000; buf[11]++;} \
(buf)[11]+=DECCOMBMSD[sourhi>>26];}
#endif #endif
/* Set a decFloat to the maximum positive finite number (Nmax) */ /* Set a decFloat to the maximum positive finite number (Nmax) */
#if DECPMAX==7 #if DECPMAX==7
#define DFSETNMAX(df) \ #define DFSETNMAX(df) \
......
...@@ -31,12 +31,12 @@ ...@@ -31,12 +31,12 @@
/* ------------------------------------------------------------------ */ /* ------------------------------------------------------------------ */
/* Packed Decimal conversion module */ /* Packed Decimal conversion module */
/* ------------------------------------------------------------------ */ /* ------------------------------------------------------------------ */
/* This module comprises the routines for Packed Decimal format */ /* This module comprises the routines for Packed Decimal format */
/* numbers. Conversions are supplied to and from decNumber, which in */ /* numbers. Conversions are supplied to and from decNumber, which in */
/* turn supports: */ /* turn supports: */
/* conversions to and from string */ /* conversions to and from string */
/* arithmetic routines */ /* arithmetic routines */
/* utilities. */ /* utilities. */
/* Conversions from decNumber to and from densely packed decimal */ /* Conversions from decNumber to and from densely packed decimal */
/* formats are provided by the decimal32 through decimal128 modules. */ /* formats are provided by the decimal32 through decimal128 modules. */
/* ------------------------------------------------------------------ */ /* ------------------------------------------------------------------ */
...@@ -51,8 +51,8 @@ ...@@ -51,8 +51,8 @@
/* */ /* */
/* bcd is the BCD bytes */ /* bcd is the BCD bytes */
/* length is the length of the BCD array */ /* length is the length of the BCD array */
/* scale is the scale result */ /* scale is the scale result */
/* dn is the decNumber */ /* dn is the decNumber */
/* returns bcd, or NULL if error */ /* returns bcd, or NULL if error */
/* */ /* */
/* The number is converted to a BCD packed decimal byte array, */ /* The number is converted to a BCD packed decimal byte array, */
...@@ -67,7 +67,7 @@ ...@@ -67,7 +67,7 @@
/* as necessary. */ /* as necessary. */
/* */ /* */
/* If there is an error (that is, the decNumber has too many digits */ /* If there is an error (that is, the decNumber has too many digits */
/* to fit in length bytes, or it is a NaN or Infinity), NULL is */ /* to fit in length bytes, or it is a NaN or Infinity), NULL is */
/* returned and the bcd and scale results are unchanged. Otherwise */ /* returned and the bcd and scale results are unchanged. Otherwise */
/* bcd is returned. */ /* bcd is returned. */
/* ------------------------------------------------------------------ */ /* ------------------------------------------------------------------ */
...@@ -86,9 +86,9 @@ uByte * decPackedFromNumber(uByte *bcd, Int length, Int *scale, ...@@ -86,9 +86,9 @@ uByte * decPackedFromNumber(uByte *bcd, Int length, Int *scale,
if (dn->digits>length*2-1 /* too long .. */ if (dn->digits>length*2-1 /* too long .. */
||(dn->bits & DECSPECIAL)) return NULL; /* .. or special -- hopeless */ ||(dn->bits & DECSPECIAL)) return NULL; /* .. or special -- hopeless */
if (dn->bits&DECNEG) obyte=DECPMINUS; /* set the sign .. */ if (dn->bits&DECNEG) obyte=DECPMINUS; /* set the sign .. */
else obyte=DECPPLUS; else obyte=DECPPLUS;
*scale=-dn->exponent; /* .. and scale */ *scale=-dn->exponent; /* .. and scale */
/* loop from lowest (rightmost) byte */ /* loop from lowest (rightmost) byte */
out=bcd+length-1; /* -> final byte */ out=bcd+length-1; /* -> final byte */
...@@ -141,7 +141,7 @@ uByte * decPackedFromNumber(uByte *bcd, Int length, Int *scale, ...@@ -141,7 +141,7 @@ uByte * decPackedFromNumber(uByte *bcd, Int length, Int *scale,
/* bcd is the BCD bytes */ /* bcd is the BCD bytes */
/* length is the length of the BCD array */ /* length is the length of the BCD array */
/* scale is the scale associated with the BCD integer */ /* scale is the scale associated with the BCD integer */
/* dn is the decNumber [with space for length*2 digits] */ /* dn is the decNumber [with space for length*2 digits] */
/* returns dn, or NULL if error */ /* returns dn, or NULL if error */
/* */ /* */
/* The BCD packed decimal byte array, together with an associated */ /* The BCD packed decimal byte array, together with an associated */
...@@ -157,7 +157,7 @@ uByte * decPackedFromNumber(uByte *bcd, Int length, Int *scale, ...@@ -157,7 +157,7 @@ uByte * decPackedFromNumber(uByte *bcd, Int length, Int *scale,
/* no error is possible unless the adjusted exponent is out of range, */ /* no error is possible unless the adjusted exponent is out of range, */
/* no sign nibble was found, or a sign nibble was found before the */ /* no sign nibble was found, or a sign nibble was found before the */
/* final nibble. In these error cases, NULL is returned and the */ /* final nibble. In these error cases, NULL is returned and the */
/* decNumber will be 0. */ /* decNumber will be 0. */
/* ------------------------------------------------------------------ */ /* ------------------------------------------------------------------ */
decNumber * decPackedToNumber(const uByte *bcd, Int length, decNumber * decPackedToNumber(const uByte *bcd, Int length,
const Int *scale, decNumber *dn) { const Int *scale, decNumber *dn) {
...@@ -165,7 +165,7 @@ decNumber * decPackedToNumber(const uByte *bcd, Int length, ...@@ -165,7 +165,7 @@ decNumber * decPackedToNumber(const uByte *bcd, Int length,
const uByte *first; /* -> first non-zero byte */ const uByte *first; /* -> first non-zero byte */
uInt nib; /* work nibble */ uInt nib; /* work nibble */
Unit *up=dn->lsu; /* output pointer */ Unit *up=dn->lsu; /* output pointer */
Int digits; /* digits count */ Int digits; /* digits count */
Int cut=0; /* phase of output */ Int cut=0; /* phase of output */
decNumberZero(dn); /* default result */ decNumberZero(dn); /* default result */
...@@ -182,7 +182,7 @@ decNumber * decPackedToNumber(const uByte *bcd, Int length, ...@@ -182,7 +182,7 @@ decNumber * decPackedToNumber(const uByte *bcd, Int length,
/* leave as 1] */ /* leave as 1] */
/* check the adjusted exponent; note that scale could be unbounded */ /* check the adjusted exponent; note that scale could be unbounded */
dn->exponent=-*scale; /* set the exponent */ dn->exponent=-*scale; /* set the exponent */
if (*scale>=0) { /* usual case */ if (*scale>=0) { /* usual case */
if ((dn->digits-*scale-1)<-DECNUMMAXE) { /* underflow */ if ((dn->digits-*scale-1)<-DECNUMMAXE) { /* underflow */
decNumberZero(dn); decNumberZero(dn);
......
...@@ -36,7 +36,7 @@ ...@@ -36,7 +36,7 @@
#define DECPACKED #define DECPACKED
#define DECPNAME "decPacked" /* Short name */ #define DECPNAME "decPacked" /* Short name */
#define DECPFULLNAME "Packed Decimal conversions" /* Verbose name */ #define DECPFULLNAME "Packed Decimal conversions" /* Verbose name */
#define DECPAUTHOR "Mike Cowlishaw" /* Who to blame */ #define DECPAUTHOR "Mike Cowlishaw" /* Who to blame */
#define DECPACKED_DefP 32 /* default precision */ #define DECPACKED_DefP 32 /* default precision */
...@@ -47,12 +47,12 @@ ...@@ -47,12 +47,12 @@
/* Sign nibble constants */ /* Sign nibble constants */
#if !defined(DECPPLUSALT) #if !defined(DECPPLUSALT)
#define DECPPLUSALT 0x0A /* alternate plus nibble */ #define DECPPLUSALT 0x0A /* alternate plus nibble */
#define DECPMINUSALT 0x0B /* alternate minus nibble */ #define DECPMINUSALT 0x0B /* alternate minus nibble */
#define DECPPLUS 0x0C /* preferred plus nibble */ #define DECPPLUS 0x0C /* preferred plus nibble */
#define DECPMINUS 0x0D /* preferred minus nibble */ #define DECPMINUS 0x0D /* preferred minus nibble */
#define DECPPLUSALT2 0x0E /* alternate plus nibble */ #define DECPPLUSALT2 0x0E /* alternate plus nibble */
#define DECPUNSIGNED 0x0F /* alternate plus nibble (unsigned) */ #define DECPUNSIGNED 0x0F /* alternate plus nibble (unsigned) */
#endif #endif
/* ---------------------------------------------------------------- */ /* ---------------------------------------------------------------- */
......
...@@ -34,111 +34,111 @@ ...@@ -34,111 +34,111 @@
/* This module comprises decQuad operations (including conversions) */ /* This module comprises decQuad operations (including conversions) */
/* ------------------------------------------------------------------ */ /* ------------------------------------------------------------------ */
#include "decContext.h" /* public includes */ #include "decContext.h" /* public includes */
#include "decQuad.h" /* .. */ #include "decQuad.h" /* .. */
/* Constant mappings for shared code */ /* Constant mappings for shared code */
#define DECPMAX DECQUAD_Pmax #define DECPMAX DECQUAD_Pmax
#define DECEMIN DECQUAD_Emin #define DECEMIN DECQUAD_Emin
#define DECEMAX DECQUAD_Emax #define DECEMAX DECQUAD_Emax
#define DECEMAXD DECQUAD_EmaxD #define DECEMAXD DECQUAD_EmaxD
#define DECBYTES DECQUAD_Bytes #define DECBYTES DECQUAD_Bytes
#define DECSTRING DECQUAD_String #define DECSTRING DECQUAD_String
#define DECECONL DECQUAD_EconL #define DECECONL DECQUAD_EconL
#define DECBIAS DECQUAD_Bias #define DECBIAS DECQUAD_Bias
#define DECLETS DECQUAD_Declets #define DECLETS DECQUAD_Declets
#define DECQTINY (-DECQUAD_Bias) #define DECQTINY (-DECQUAD_Bias)
/* Type and function mappings for shared code */ /* Type and function mappings for shared code */
#define decFloat decQuad /* Type name */ #define decFloat decQuad /* Type name */
/* Utilities and conversions (binary results, extractors, etc.) */ /* Utilities and conversions (binary results, extractors, etc.) */
#define decFloatFromBCD decQuadFromBCD #define decFloatFromBCD decQuadFromBCD
#define decFloatFromInt32 decQuadFromInt32 #define decFloatFromInt32 decQuadFromInt32
#define decFloatFromPacked decQuadFromPacked #define decFloatFromPacked decQuadFromPacked
#define decFloatFromString decQuadFromString #define decFloatFromPackedChecked decQuadFromPackedChecked
#define decFloatFromUInt32 decQuadFromUInt32 #define decFloatFromString decQuadFromString
#define decFloatFromWider decQuadFromWider #define decFloatFromUInt32 decQuadFromUInt32
#define decFloatGetCoefficient decQuadGetCoefficient #define decFloatFromWider decQuadFromWider
#define decFloatGetExponent decQuadGetExponent #define decFloatGetCoefficient decQuadGetCoefficient
#define decFloatSetCoefficient decQuadSetCoefficient #define decFloatGetExponent decQuadGetExponent
#define decFloatSetExponent decQuadSetExponent #define decFloatSetCoefficient decQuadSetCoefficient
#define decFloatShow decQuadShow #define decFloatSetExponent decQuadSetExponent
#define decFloatToBCD decQuadToBCD #define decFloatShow decQuadShow
#define decFloatToEngString decQuadToEngString #define decFloatToBCD decQuadToBCD
#define decFloatToInt32 decQuadToInt32 #define decFloatToEngString decQuadToEngString
#define decFloatToInt32Exact decQuadToInt32Exact #define decFloatToInt32 decQuadToInt32
#define decFloatToPacked decQuadToPacked #define decFloatToInt32Exact decQuadToInt32Exact
#define decFloatToString decQuadToString #define decFloatToPacked decQuadToPacked
#define decFloatToUInt32 decQuadToUInt32 #define decFloatToString decQuadToString
#define decFloatToUInt32Exact decQuadToUInt32Exact #define decFloatToUInt32 decQuadToUInt32
#define decFloatToWider decQuadToWider #define decFloatToUInt32Exact decQuadToUInt32Exact
#define decFloatZero decQuadZero #define decFloatToWider decQuadToWider
#define decFloatZero decQuadZero
/* Computational (result is a decFloat) */ /* Computational (result is a decFloat) */
#define decFloatAbs decQuadAbs #define decFloatAbs decQuadAbs
#define decFloatAdd decQuadAdd #define decFloatAdd decQuadAdd
#define decFloatAnd decQuadAnd #define decFloatAnd decQuadAnd
#define decFloatDivide decQuadDivide #define decFloatDivide decQuadDivide
#define decFloatDivideInteger decQuadDivideInteger #define decFloatDivideInteger decQuadDivideInteger
#define decFloatFMA decQuadFMA #define decFloatFMA decQuadFMA
#define decFloatInvert decQuadInvert #define decFloatInvert decQuadInvert
#define decFloatLogB decQuadLogB #define decFloatLogB decQuadLogB
#define decFloatMax decQuadMax #define decFloatMax decQuadMax
#define decFloatMaxMag decQuadMaxMag #define decFloatMaxMag decQuadMaxMag
#define decFloatMin decQuadMin #define decFloatMin decQuadMin
#define decFloatMinMag decQuadMinMag #define decFloatMinMag decQuadMinMag
#define decFloatMinus decQuadMinus #define decFloatMinus decQuadMinus
#define decFloatMultiply decQuadMultiply #define decFloatMultiply decQuadMultiply
#define decFloatNextMinus decQuadNextMinus #define decFloatNextMinus decQuadNextMinus
#define decFloatNextPlus decQuadNextPlus #define decFloatNextPlus decQuadNextPlus
#define decFloatNextToward decQuadNextToward #define decFloatNextToward decQuadNextToward
#define decFloatOr decQuadOr #define decFloatOr decQuadOr
#define decFloatPlus decQuadPlus #define decFloatPlus decQuadPlus
#define decFloatQuantize decQuadQuantize #define decFloatQuantize decQuadQuantize
#define decFloatReduce decQuadReduce #define decFloatReduce decQuadReduce
#define decFloatRemainder decQuadRemainder #define decFloatRemainder decQuadRemainder
#define decFloatRemainderNear decQuadRemainderNear #define decFloatRemainderNear decQuadRemainderNear
#define decFloatRotate decQuadRotate #define decFloatRotate decQuadRotate
#define decFloatScaleB decQuadScaleB #define decFloatScaleB decQuadScaleB
#define decFloatShift decQuadShift #define decFloatShift decQuadShift
#define decFloatSubtract decQuadSubtract #define decFloatSubtract decQuadSubtract
#define decFloatToIntegralValue decQuadToIntegralValue #define decFloatToIntegralValue decQuadToIntegralValue
#define decFloatToIntegralExact decQuadToIntegralExact #define decFloatToIntegralExact decQuadToIntegralExact
#define decFloatXor decQuadXor #define decFloatXor decQuadXor
/* Comparisons */ /* Comparisons */
#define decFloatCompare decQuadCompare #define decFloatCompare decQuadCompare
#define decFloatCompareSignal decQuadCompareSignal #define decFloatCompareSignal decQuadCompareSignal
#define decFloatCompareTotal decQuadCompareTotal #define decFloatCompareTotal decQuadCompareTotal
#define decFloatCompareTotalMag decQuadCompareTotalMag #define decFloatCompareTotalMag decQuadCompareTotalMag
/* Copies */ /* Copies */
#define decFloatCanonical decQuadCanonical #define decFloatCanonical decQuadCanonical
#define decFloatCopy decQuadCopy #define decFloatCopy decQuadCopy
#define decFloatCopyAbs decQuadCopyAbs #define decFloatCopyAbs decQuadCopyAbs
#define decFloatCopyNegate decQuadCopyNegate #define decFloatCopyNegate decQuadCopyNegate
#define decFloatCopySign decQuadCopySign #define decFloatCopySign decQuadCopySign
/* Non-computational */ /* Non-computational */
#define decFloatClass decQuadClass #define decFloatClass decQuadClass
#define decFloatClassString decQuadClassString #define decFloatClassString decQuadClassString
#define decFloatDigits decQuadDigits #define decFloatDigits decQuadDigits
#define decFloatIsCanonical decQuadIsCanonical #define decFloatIsCanonical decQuadIsCanonical
#define decFloatIsFinite decQuadIsFinite #define decFloatIsFinite decQuadIsFinite
#define decFloatIsInfinite decQuadIsInfinite #define decFloatIsInfinite decQuadIsInfinite
#define decFloatIsInteger decQuadIsInteger #define decFloatIsInteger decQuadIsInteger
#define decFloatIsNaN decQuadIsNaN #define decFloatIsNaN decQuadIsNaN
#define decFloatIsNormal decQuadIsNormal #define decFloatIsNormal decQuadIsNormal
#define decFloatIsSignaling decQuadIsSignaling #define decFloatIsSignaling decQuadIsSignaling
#define decFloatIsSignalling decQuadIsSignalling #define decFloatIsSignalling decQuadIsSignalling
#define decFloatIsSigned decQuadIsSigned #define decFloatIsSigned decQuadIsSigned
#define decFloatIsSubnormal decQuadIsSubnormal #define decFloatIsSubnormal decQuadIsSubnormal
#define decFloatIsZero decQuadIsZero #define decFloatIsZero decQuadIsZero
#define decFloatRadix decQuadRadix #define decFloatRadix decQuadRadix
#define decFloatSameQuantum decQuadSameQuantum #define decFloatSameQuantum decQuadSameQuantum
#define decFloatVersion decQuadVersion #define decFloatVersion decQuadVersion
#include "decNumberLocal.h" /* local includes (need DECPMAX) */ #include "decNumberLocal.h" /* local includes (need DECPMAX) */
#include "decCommon.c" /* non-arithmetic decFloat routines */ #include "decCommon.c" /* non-arithmetic decFloat routines */
......
...@@ -31,27 +31,25 @@ ...@@ -31,27 +31,25 @@
/* ------------------------------------------------------------------ */ /* ------------------------------------------------------------------ */
/* decQuad.h -- Decimal 128-bit format module header */ /* decQuad.h -- Decimal 128-bit format module header */
/* ------------------------------------------------------------------ */ /* ------------------------------------------------------------------ */
/* Please see decFloats.h for an overview and documentation details. */
/* ------------------------------------------------------------------ */
/* This include file is always included by decSingle and decDouble, */ /* This include file is always included by decSingle and decDouble, */
/* and therefore also holds useful constants used by all three. */ /* and therefore also holds useful constants used by all three. */
#if !defined(DECQUAD) #if !defined(DECQUAD)
#define DECQUAD #define DECQUAD
#define DECQUADNAME "decimalQuad" /* Short name */ #define DECQUADNAME "decimalQuad" /* Short name */
#define DECQUADTITLE "Decimal 128-bit datum" /* Verbose name */ #define DECQUADTITLE "Decimal 128-bit datum" /* Verbose name */
#define DECQUADAUTHOR "Mike Cowlishaw" /* Who to blame */ #define DECQUADAUTHOR "Mike Cowlishaw" /* Who to blame */
/* parameters for decQuads */ /* parameters for decQuads */
#define DECQUAD_Bytes 16 /* length */ #define DECQUAD_Bytes 16 /* length */
#define DECQUAD_Pmax 34 /* maximum precision (digits) */ #define DECQUAD_Pmax 34 /* maximum precision (digits) */
#define DECQUAD_Emin -6143 /* minimum adjusted exponent */ #define DECQUAD_Emin -6143 /* minimum adjusted exponent */
#define DECQUAD_Emax 6144 /* maximum adjusted exponent */ #define DECQUAD_Emax 6144 /* maximum adjusted exponent */
#define DECQUAD_EmaxD 4 /* maximum exponent digits */ #define DECQUAD_EmaxD 4 /* maximum exponent digits */
#define DECQUAD_Bias 6176 /* bias for the exponent */ #define DECQUAD_Bias 6176 /* bias for the exponent */
#define DECQUAD_String 43 /* maximum string length, +1 */ #define DECQUAD_String 43 /* maximum string length, +1 */
#define DECQUAD_EconL 12 /* exponent continuation length */ #define DECQUAD_EconL 12 /* exponent continuation length */
#define DECQUAD_Declets 11 /* count of declets */ #define DECQUAD_Declets 11 /* count of declets */
/* highest biased exponent (Elimit-1) */ /* highest biased exponent (Elimit-1) */
#define DECQUAD_Ehigh (DECQUAD_Emax + DECQUAD_Bias - (DECQUAD_Pmax-1)) #define DECQUAD_Ehigh (DECQUAD_Emax + DECQUAD_Bias - (DECQUAD_Pmax-1))
...@@ -59,11 +57,14 @@ ...@@ -59,11 +57,14 @@
/* Required include */ /* Required include */
#include "decContext.h" #include "decContext.h"
/* The decQuad decimal 128-bit type, accessible by various types */ /* The decQuad decimal 128-bit type, accessible by all sizes */
typedef union { typedef union {
uint8_t bytes[DECQUAD_Bytes]; /* fields: 1, 5, 12, 110 bits */ uint8_t bytes[DECQUAD_Bytes]; /* fields: 1, 5, 12, 110 bits */
uint16_t shorts[DECQUAD_Bytes/2]; uint16_t shorts[DECQUAD_Bytes/2];
uint32_t words[DECQUAD_Bytes/4]; uint32_t words[DECQUAD_Bytes/4];
#if DECUSE64
uint64_t longs[DECQUAD_Bytes/8];
#endif
} decQuad; } decQuad;
/* ---------------------------------------------------------------- */ /* ---------------------------------------------------------------- */
...@@ -72,21 +73,21 @@ ...@@ -72,21 +73,21 @@
/* sign and special values [top 32-bits; last two bits are don't-care /* sign and special values [top 32-bits; last two bits are don't-care
for Infinity on input, last bit don't-care for NaNs] */ for Infinity on input, last bit don't-care for NaNs] */
#define DECFLOAT_Sign 0x80000000 /* 1 00000 00 Sign */ #define DECFLOAT_Sign 0x80000000 /* 1 00000 00 Sign */
#define DECFLOAT_NaN 0x7c000000 /* 0 11111 00 NaN generic */ #define DECFLOAT_NaN 0x7c000000 /* 0 11111 00 NaN generic */
#define DECFLOAT_qNaN 0x7c000000 /* 0 11111 00 qNaN */ #define DECFLOAT_qNaN 0x7c000000 /* 0 11111 00 qNaN */
#define DECFLOAT_sNaN 0x7e000000 /* 0 11111 10 sNaN */ #define DECFLOAT_sNaN 0x7e000000 /* 0 11111 10 sNaN */
#define DECFLOAT_Inf 0x78000000 /* 0 11110 00 Infinity */ #define DECFLOAT_Inf 0x78000000 /* 0 11110 00 Infinity */
#define DECFLOAT_MinSp 0x78000000 /* minimum special value */ #define DECFLOAT_MinSp 0x78000000 /* minimum special value */
/* [specials are all >=MinSp] */ /* [specials are all >=MinSp] */
/* Sign nibble constants */ /* Sign nibble constants */
#if !defined(DECPPLUSALT) #if !defined(DECPPLUSALT)
#define DECPPLUSALT 0x0A /* alternate plus nibble */ #define DECPPLUSALT 0x0A /* alternate plus nibble */
#define DECPMINUSALT 0x0B /* alternate minus nibble */ #define DECPMINUSALT 0x0B /* alternate minus nibble */
#define DECPPLUS 0x0C /* preferred plus nibble */ #define DECPPLUS 0x0C /* preferred plus nibble */
#define DECPMINUS 0x0D /* preferred minus nibble */ #define DECPMINUS 0x0D /* preferred minus nibble */
#define DECPPLUSALT2 0x0E /* alternate plus nibble */ #define DECPPLUSALT2 0x0E /* alternate plus nibble */
#define DECPUNSIGNED 0x0F /* alternate plus nibble (unsigned) */ #define DECPUNSIGNED 0x0F /* alternate plus nibble (unsigned) */
#endif #endif
/* ---------------------------------------------------------------- */ /* ---------------------------------------------------------------- */
...@@ -99,6 +100,7 @@ ...@@ -99,6 +100,7 @@
extern decQuad * decQuadFromBCD(decQuad *, int32_t, const uint8_t *, int32_t); extern decQuad * decQuadFromBCD(decQuad *, int32_t, const uint8_t *, int32_t);
extern decQuad * decQuadFromInt32(decQuad *, int32_t); extern decQuad * decQuadFromInt32(decQuad *, int32_t);
extern decQuad * decQuadFromPacked(decQuad *, int32_t, const uint8_t *); extern decQuad * decQuadFromPacked(decQuad *, int32_t, const uint8_t *);
extern decQuad * decQuadFromPackedChecked(decQuad *, int32_t, const uint8_t *);
extern decQuad * decQuadFromString(decQuad *, const char *, decContext *); extern decQuad * decQuadFromString(decQuad *, const char *, decContext *);
extern decQuad * decQuadFromUInt32(decQuad *, uint32_t); extern decQuad * decQuadFromUInt32(decQuad *, uint32_t);
extern int32_t decQuadGetCoefficient(const decQuad *, uint8_t *); extern int32_t decQuadGetCoefficient(const decQuad *, uint8_t *);
...@@ -182,7 +184,8 @@ ...@@ -182,7 +184,8 @@
/* decNumber conversions; these are implemented as macros so as not */ /* decNumber conversions; these are implemented as macros so as not */
/* to force a dependency on decimal128 and decNumber in decQuad. */ /* to force a dependency on decimal128 and decNumber in decQuad. */
/* decQuadFromNumber returns a decimal128 * to avoid warnings. */
#define decQuadToNumber(dq, dn) decimal128ToNumber((decimal128 *)(dq), dn) #define decQuadToNumber(dq, dn) decimal128ToNumber((decimal128 *)(dq), dn)
#define decQuadFromNumber(dq, dn, set) (decQuad *)decimal128FromNumber((decimal128 *)(dq), dn, set) #define decQuadFromNumber(dq, dn, set) decimal128FromNumber((decimal128 *)(dq), dn, set)
#endif #endif
...@@ -31,22 +31,20 @@ ...@@ -31,22 +31,20 @@
/* ------------------------------------------------------------------ */ /* ------------------------------------------------------------------ */
/* decSingle.c -- decSingle operations module */ /* decSingle.c -- decSingle operations module */
/* ------------------------------------------------------------------ */ /* ------------------------------------------------------------------ */
/* This module comprises decSingle operations (including conversions) */
/* ------------------------------------------------------------------ */
#include "decContext.h" /* public includes */ #include "decContext.h" /* public includes */
#include "decSingle.h" /* public includes */ #include "decSingle.h" /* public includes */
/* Constant mappings for shared code */ /* Constant mappings for shared code */
#define DECPMAX DECSINGLE_Pmax #define DECPMAX DECSINGLE_Pmax
#define DECEMIN DECSINGLE_Emin #define DECEMIN DECSINGLE_Emin
#define DECEMAX DECSINGLE_Emax #define DECEMAX DECSINGLE_Emax
#define DECEMAXD DECSINGLE_EmaxD #define DECEMAXD DECSINGLE_EmaxD
#define DECBYTES DECSINGLE_Bytes #define DECBYTES DECSINGLE_Bytes
#define DECSTRING DECSINGLE_String #define DECSTRING DECSINGLE_String
#define DECECONL DECSINGLE_EconL #define DECECONL DECSINGLE_EconL
#define DECBIAS DECSINGLE_Bias #define DECBIAS DECSINGLE_Bias
#define DECLETS DECSINGLE_Declets #define DECLETS DECSINGLE_Declets
#define DECQTINY (-DECSINGLE_Bias) #define DECQTINY (-DECSINGLE_Bias)
/* parameters of next-wider format */ /* parameters of next-wider format */
#define DECWBYTES DECDOUBLE_Bytes #define DECWBYTES DECDOUBLE_Bytes
...@@ -55,29 +53,30 @@ ...@@ -55,29 +53,30 @@
#define DECWBIAS DECDOUBLE_Bias #define DECWBIAS DECDOUBLE_Bias
/* Type and function mappings for shared code */ /* Type and function mappings for shared code */
#define decFloat decSingle /* Type name */ #define decFloat decSingle /* Type name */
#define decFloatWider decDouble /* Type name */ #define decFloatWider decDouble /* Type name */
/* Utility (binary results, extractors, etc.) */ /* Utility (binary results, extractors, etc.) */
#define decFloatFromBCD decSingleFromBCD #define decFloatFromBCD decSingleFromBCD
#define decFloatFromPacked decSingleFromPacked #define decFloatFromPacked decSingleFromPacked
#define decFloatFromString decSingleFromString #define decFloatFromPackedChecked decSingleFromPackedChecked
#define decFloatFromWider decSingleFromWider #define decFloatFromString decSingleFromString
#define decFloatGetCoefficient decSingleGetCoefficient #define decFloatFromWider decSingleFromWider
#define decFloatGetExponent decSingleGetExponent #define decFloatGetCoefficient decSingleGetCoefficient
#define decFloatSetCoefficient decSingleSetCoefficient #define decFloatGetExponent decSingleGetExponent
#define decFloatSetExponent decSingleSetExponent #define decFloatSetCoefficient decSingleSetCoefficient
#define decFloatShow decSingleShow #define decFloatSetExponent decSingleSetExponent
#define decFloatToBCD decSingleToBCD #define decFloatShow decSingleShow
#define decFloatToEngString decSingleToEngString #define decFloatToBCD decSingleToBCD
#define decFloatToPacked decSingleToPacked #define decFloatToEngString decSingleToEngString
#define decFloatToString decSingleToString #define decFloatToPacked decSingleToPacked
#define decFloatToWider decSingleToWider #define decFloatToString decSingleToString
#define decFloatZero decSingleZero #define decFloatToWider decSingleToWider
#define decFloatZero decSingleZero
/* Non-computational */ /* Non-computational */
#define decFloatRadix decSingleRadix #define decFloatRadix decSingleRadix
#define decFloatVersion decSingleVersion #define decFloatVersion decSingleVersion
#include "decNumberLocal.h" /* local includes (need DECPMAX) */ #include "decNumberLocal.h" /* local includes (need DECPMAX) */
#include "decCommon.c" /* non-basic decFloat routines */ #include "decCommon.c" /* non-basic decFloat routines */
......
...@@ -31,24 +31,22 @@ ...@@ -31,24 +31,22 @@
/* ------------------------------------------------------------------ */ /* ------------------------------------------------------------------ */
/* decSingle.h -- Decimal 32-bit format module header */ /* decSingle.h -- Decimal 32-bit format module header */
/* ------------------------------------------------------------------ */ /* ------------------------------------------------------------------ */
/* Please see decFloats.h for an overview and documentation details. */
/* ------------------------------------------------------------------ */
#if !defined(DECSINGLE) #if !defined(DECSINGLE)
#define DECSINGLE #define DECSINGLE
#define DECSINGLENAME "decSingle" /* Short name */ #define DECSINGLENAME "decSingle" /* Short name */
#define DECSINGLETITLE "Decimal 32-bit datum" /* Verbose name */ #define DECSINGLETITLE "Decimal 32-bit datum" /* Verbose name */
#define DECSINGLEAUTHOR "Mike Cowlishaw" /* Who to blame */ #define DECSINGLEAUTHOR "Mike Cowlishaw" /* Who to blame */
/* parameters for decSingles */ /* parameters for decSingles */
#define DECSINGLE_Bytes 4 /* length */ #define DECSINGLE_Bytes 4 /* length */
#define DECSINGLE_Pmax 7 /* maximum precision (digits) */ #define DECSINGLE_Pmax 7 /* maximum precision (digits) */
#define DECSINGLE_Emin -95 /* minimum adjusted exponent */ #define DECSINGLE_Emin -95 /* minimum adjusted exponent */
#define DECSINGLE_Emax 96 /* maximum adjusted exponent */ #define DECSINGLE_Emax 96 /* maximum adjusted exponent */
#define DECSINGLE_EmaxD 3 /* maximum exponent digits */ #define DECSINGLE_EmaxD 3 /* maximum exponent digits */
#define DECSINGLE_Bias 101 /* bias for the exponent */ #define DECSINGLE_Bias 101 /* bias for the exponent */
#define DECSINGLE_String 16 /* maximum string length, +1 */ #define DECSINGLE_String 16 /* maximum string length, +1 */
#define DECSINGLE_EconL 6 /* exponent continuation length */ #define DECSINGLE_EconL 6 /* exponent continuation length */
#define DECSINGLE_Declets 2 /* count of declets */ #define DECSINGLE_Declets 2 /* count of declets */
/* highest biased exponent (Elimit-1) */ /* highest biased exponent (Elimit-1) */
...@@ -59,11 +57,11 @@ ...@@ -59,11 +57,11 @@
#include "decQuad.h" #include "decQuad.h"
#include "decDouble.h" #include "decDouble.h"
/* The decSingle decimal 32-bit type, accessible by various types */ /* The decSingle decimal 32-bit type, accessible by all sizes */
typedef union { typedef union {
uint8_t bytes[DECSINGLE_Bytes]; /* fields: 1, 5, 6, 20 bits */ uint8_t bytes[DECSINGLE_Bytes]; /* fields: 1, 5, 6, 20 bits */
uint16_t shorts[DECSINGLE_Bytes/2]; uint16_t shorts[DECSINGLE_Bytes/2];
uint32_t words[DECSINGLE_Bytes/4]; uint32_t words[DECSINGLE_Bytes/4];
} decSingle; } decSingle;
/* ---------------------------------------------------------------- */ /* ---------------------------------------------------------------- */
...@@ -75,6 +73,7 @@ ...@@ -75,6 +73,7 @@
/* Utilities (binary argument(s) or result, extractors, etc.) */ /* Utilities (binary argument(s) or result, extractors, etc.) */
extern decSingle * decSingleFromBCD(decSingle *, int32_t, const uint8_t *, int32_t); extern decSingle * decSingleFromBCD(decSingle *, int32_t, const uint8_t *, int32_t);
extern decSingle * decSingleFromPacked(decSingle *, int32_t, const uint8_t *); extern decSingle * decSingleFromPacked(decSingle *, int32_t, const uint8_t *);
extern decSingle * decSingleFromPackedChecked(decSingle *, int32_t, const uint8_t *);
extern decSingle * decSingleFromString(decSingle *, const char *, decContext *); extern decSingle * decSingleFromString(decSingle *, const char *, decContext *);
extern decSingle * decSingleFromWider(decSingle *, const decDouble *, decContext *); extern decSingle * decSingleFromWider(decSingle *, const decDouble *, decContext *);
extern int32_t decSingleGetCoefficient(const decSingle *, uint8_t *); extern int32_t decSingleGetCoefficient(const decSingle *, uint8_t *);
...@@ -97,7 +96,8 @@ ...@@ -97,7 +96,8 @@
/* decNumber conversions; these are implemented as macros so as not */ /* decNumber conversions; these are implemented as macros so as not */
/* to force a dependency on decimal32 and decNumber in decSingle. */ /* to force a dependency on decimal32 and decNumber in decSingle. */
/* decSingleFromNumber returns a decimal32 * to avoid warnings. */
#define decSingleToNumber(dq, dn) decimal32ToNumber((decimal32 *)(dq), dn) #define decSingleToNumber(dq, dn) decimal32ToNumber((decimal32 *)(dq), dn)
#define decSingleFromNumber(dq, dn, set) (decSingle *)decimal32FromNumber((decimal32 *)(dq), dn, set) #define decSingleFromNumber(dq, dn, set) decimal32FromNumber((decimal32 *)(dq), dn, set)
#endif #endif
...@@ -42,11 +42,11 @@ ...@@ -42,11 +42,11 @@
#include <string.h> /* [for memset/memcpy] */ #include <string.h> /* [for memset/memcpy] */
#include <stdio.h> /* [for printf] */ #include <stdio.h> /* [for printf] */
#include "dconfig.h" /* GCC definitions */ #include "dconfig.h" /* GCC definitions */
#define DECNUMDIGITS 34 /* make decNumbers with space for 34 */ #define DECNUMDIGITS 34 /* make decNumbers with space for 34 */
#include "decNumber.h" /* base number library */ #include "decNumber.h" /* base number library */
#include "decNumberLocal.h" /* decNumber local types, etc. */ #include "decNumberLocal.h" /* decNumber local types, etc. */
#include "decimal128.h" /* our primary include */ #include "decimal128.h" /* our primary include */
/* Utility routines and tables [in decimal64.c] */ /* Utility routines and tables [in decimal64.c] */
extern const uInt COMBEXP[32], COMBMSD[32]; extern const uInt COMBEXP[32], COMBMSD[32];
...@@ -71,7 +71,7 @@ extern void decNumberShow(const decNumber *); /* .. */ ...@@ -71,7 +71,7 @@ extern void decNumberShow(const decNumber *); /* .. */
/* */ /* */
/* ds is the target decimal128 */ /* ds is the target decimal128 */
/* dn is the source number (assumed valid) */ /* dn is the source number (assumed valid) */
/* set is the context, used only for reporting errors */ /* set is the context, used only for reporting errors */
/* */ /* */
/* The set argument is used only for status reporting and for the */ /* The set argument is used only for status reporting and for the */
/* rounding mode (used if the coefficient is more than DECIMAL128_Pmax*/ /* rounding mode (used if the coefficient is more than DECIMAL128_Pmax*/
...@@ -89,8 +89,8 @@ decimal128 * decimal128FromNumber(decimal128 *d128, const decNumber *dn, ...@@ -89,8 +89,8 @@ decimal128 * decimal128FromNumber(decimal128 *d128, const decNumber *dn,
Int ae; /* adjusted exponent */ Int ae; /* adjusted exponent */
decNumber dw; /* work */ decNumber dw; /* work */
decContext dc; /* .. */ decContext dc; /* .. */
uInt *pu; /* .. */
uInt comb, exp; /* .. */ uInt comb, exp; /* .. */
uInt uiwork; /* for macros */
uInt targar[4]={0,0,0,0}; /* target 128-bit */ uInt targar[4]={0,0,0,0}; /* target 128-bit */
#define targhi targar[3] /* name the word with the sign */ #define targhi targar[3] /* name the word with the sign */
#define targmh targar[2] /* name the words */ #define targmh targar[2] /* name the words */
...@@ -102,7 +102,7 @@ decimal128 * decimal128FromNumber(decimal128 *d128, const decNumber *dn, ...@@ -102,7 +102,7 @@ decimal128 * decimal128FromNumber(decimal128 *d128, const decNumber *dn,
/* constraints. This could push the number to Infinity or zero, */ /* constraints. This could push the number to Infinity or zero, */
/* so this check and rounding must be done before generating the */ /* so this check and rounding must be done before generating the */
/* decimal128] */ /* decimal128] */
ae=dn->exponent+dn->digits-1; /* [0 if special] */ ae=dn->exponent+dn->digits-1; /* [0 if special] */
if (dn->digits>DECIMAL128_Pmax /* too many digits */ if (dn->digits>DECIMAL128_Pmax /* too many digits */
|| ae>DECIMAL128_Emax /* likely overflow */ || ae>DECIMAL128_Emax /* likely overflow */
|| ae<DECIMAL128_Emin) { /* likely underflow */ || ae<DECIMAL128_Emin) { /* likely underflow */
...@@ -118,7 +118,7 @@ decimal128 * decimal128FromNumber(decimal128 *d128, const decNumber *dn, ...@@ -118,7 +118,7 @@ decimal128 * decimal128FromNumber(decimal128 *d128, const decNumber *dn,
if (dn->bits&DECSPECIAL) { /* a special value */ if (dn->bits&DECSPECIAL) { /* a special value */
if (dn->bits&DECINF) targhi=DECIMAL_Inf<<24; if (dn->bits&DECINF) targhi=DECIMAL_Inf<<24;
else { /* sNaN or qNaN */ else { /* sNaN or qNaN */
if ((*dn->lsu!=0 || dn->digits>1) /* non-zero coefficient */ if ((*dn->lsu!=0 || dn->digits>1) /* non-zero coefficient */
&& (dn->digits<DECIMAL128_Pmax)) { /* coefficient fits */ && (dn->digits<DECIMAL128_Pmax)) { /* coefficient fits */
decDigitsToDPD(dn, targar, 0); decDigitsToDPD(dn, targar, 0);
} }
...@@ -144,11 +144,11 @@ decimal128 * decimal128FromNumber(decimal128 *d128, const decNumber *dn, ...@@ -144,11 +144,11 @@ decimal128 * decimal128FromNumber(decimal128 *d128, const decNumber *dn,
comb=(exp>>9) & 0x18; /* msd=0, exp top 2 bits .. */ comb=(exp>>9) & 0x18; /* msd=0, exp top 2 bits .. */
} }
else { /* non-zero finite number */ else { /* non-zero finite number */
uInt msd; /* work */ uInt msd; /* work */
Int pad=0; /* coefficient pad digits */ Int pad=0; /* coefficient pad digits */
/* the dn is known to fit, but it may need to be padded */ /* the dn is known to fit, but it may need to be padded */
exp=(uInt)(dn->exponent+DECIMAL128_Bias); /* bias exponent */ exp=(uInt)(dn->exponent+DECIMAL128_Bias); /* bias exponent */
if (exp>DECIMAL128_Ehigh) { /* fold-down case */ if (exp>DECIMAL128_Ehigh) { /* fold-down case */
pad=exp-DECIMAL128_Ehigh; pad=exp-DECIMAL128_Ehigh;
exp=DECIMAL128_Ehigh; /* [to maximum] */ exp=DECIMAL128_Ehigh; /* [to maximum] */
...@@ -172,18 +172,19 @@ decimal128 * decimal128FromNumber(decimal128 *d128, const decNumber *dn, ...@@ -172,18 +172,19 @@ decimal128 * decimal128FromNumber(decimal128 *d128, const decNumber *dn,
if (dn->bits&DECNEG) targhi|=0x80000000; /* add sign bit */ if (dn->bits&DECNEG) targhi|=0x80000000; /* add sign bit */
/* now write to storage; this is endian */ /* now write to storage; this is endian */
pu=(uInt *)d128->bytes; /* overlay */
if (DECLITEND) { if (DECLITEND) {
pu[0]=targlo; /* directly store the low int */ /* lo -> hi */
pu[1]=targml; /* then the mid-low */ UBFROMUI(d128->bytes, targlo);
pu[2]=targmh; /* then the mid-high */ UBFROMUI(d128->bytes+4, targml);
pu[3]=targhi; /* then the high int */ UBFROMUI(d128->bytes+8, targmh);
UBFROMUI(d128->bytes+12, targhi);
} }
else { else {
pu[0]=targhi; /* directly store the high int */ /* hi -> lo */
pu[1]=targmh; /* then the mid-high */ UBFROMUI(d128->bytes, targhi);
pu[2]=targml; /* then the mid-low */ UBFROMUI(d128->bytes+4, targmh);
pu[3]=targlo; /* then the low int */ UBFROMUI(d128->bytes+8, targml);
UBFROMUI(d128->bytes+12, targlo);
} }
if (status!=0) decContextSetStatus(set, status); /* pass on status */ if (status!=0) decContextSetStatus(set, status); /* pass on status */
...@@ -201,8 +202,8 @@ decNumber * decimal128ToNumber(const decimal128 *d128, decNumber *dn) { ...@@ -201,8 +202,8 @@ decNumber * decimal128ToNumber(const decimal128 *d128, decNumber *dn) {
uInt msd; /* coefficient MSD */ uInt msd; /* coefficient MSD */
uInt exp; /* exponent top two bits */ uInt exp; /* exponent top two bits */
uInt comb; /* combination field */ uInt comb; /* combination field */
const uInt *pu; /* work */ Int need; /* work */
Int need; /* .. */ uInt uiwork; /* for macros */
uInt sourar[4]; /* source 128-bit */ uInt sourar[4]; /* source 128-bit */
#define sourhi sourar[3] /* name the word with the sign */ #define sourhi sourar[3] /* name the word with the sign */
#define sourmh sourar[2] /* and the mid-high word */ #define sourmh sourar[2] /* and the mid-high word */
...@@ -210,18 +211,17 @@ decNumber * decimal128ToNumber(const decimal128 *d128, decNumber *dn) { ...@@ -210,18 +211,17 @@ decNumber * decimal128ToNumber(const decimal128 *d128, decNumber *dn) {
#define sourlo sourar[0] /* and the lowest word */ #define sourlo sourar[0] /* and the lowest word */
/* load source from storage; this is endian */ /* load source from storage; this is endian */
pu=(const uInt *)d128->bytes; /* overlay */
if (DECLITEND) { if (DECLITEND) {
sourlo=pu[0]; /* directly load the low int */ sourlo=UBTOUI(d128->bytes ); /* directly load the low int */
sourml=pu[1]; /* then the mid-low */ sourml=UBTOUI(d128->bytes+4 ); /* then the mid-low */
sourmh=pu[2]; /* then the mid-high */ sourmh=UBTOUI(d128->bytes+8 ); /* then the mid-high */
sourhi=pu[3]; /* then the high int */ sourhi=UBTOUI(d128->bytes+12); /* then the high int */
} }
else { else {
sourhi=pu[0]; /* directly load the high int */ sourhi=UBTOUI(d128->bytes ); /* directly load the high int */
sourmh=pu[1]; /* then the mid-high */ sourmh=UBTOUI(d128->bytes+4 ); /* then the mid-high */
sourml=pu[2]; /* then the mid-low */ sourml=UBTOUI(d128->bytes+8 ); /* then the mid-low */
sourlo=pu[3]; /* then the low int */ sourlo=UBTOUI(d128->bytes+12); /* then the low int */
} }
comb=(sourhi>>26)&0x1f; /* combination field */ comb=(sourhi>>26)&0x1f; /* combination field */
...@@ -232,7 +232,7 @@ decNumber * decimal128ToNumber(const decimal128 *d128, decNumber *dn) { ...@@ -232,7 +232,7 @@ decNumber * decimal128ToNumber(const decimal128 *d128, decNumber *dn) {
msd=COMBMSD[comb]; /* decode the combination field */ msd=COMBMSD[comb]; /* decode the combination field */
exp=COMBEXP[comb]; /* .. */ exp=COMBEXP[comb]; /* .. */
if (exp==3) { /* is a special */ if (exp==3) { /* is a special */
if (msd==0) { if (msd==0) {
dn->bits|=DECINF; dn->bits|=DECINF;
return dn; /* no coefficient needed */ return dn; /* no coefficient needed */
...@@ -265,7 +265,7 @@ decNumber * decimal128ToNumber(const decimal128 *d128, decNumber *dn) { ...@@ -265,7 +265,7 @@ decNumber * decimal128ToNumber(const decimal128 *d128, decNumber *dn) {
} /* decimal128ToNumber */ } /* decimal128ToNumber */
/* ------------------------------------------------------------------ */ /* ------------------------------------------------------------------ */
/* to-scientific-string -- conversion to numeric string */ /* to-scientific-string -- conversion to numeric string */
/* to-engineering-string -- conversion to numeric string */ /* to-engineering-string -- conversion to numeric string */
/* */ /* */
/* decimal128ToString(d128, string); */ /* decimal128ToString(d128, string); */
...@@ -279,7 +279,7 @@ decNumber * decimal128ToNumber(const decimal128 *d128, decNumber *dn) { ...@@ -279,7 +279,7 @@ decNumber * decimal128ToNumber(const decimal128 *d128, decNumber *dn) {
/* No error is possible, and no status can be set. */ /* No error is possible, and no status can be set. */
/* ------------------------------------------------------------------ */ /* ------------------------------------------------------------------ */
char * decimal128ToEngString(const decimal128 *d128, char *string){ char * decimal128ToEngString(const decimal128 *d128, char *string){
decNumber dn; /* work */ decNumber dn; /* work */
decimal128ToNumber(d128, &dn); decimal128ToNumber(d128, &dn);
decNumberToEngString(&dn, string); decNumberToEngString(&dn, string);
return string; return string;
...@@ -289,13 +289,13 @@ char * decimal128ToString(const decimal128 *d128, char *string){ ...@@ -289,13 +289,13 @@ char * decimal128ToString(const decimal128 *d128, char *string){
uInt msd; /* coefficient MSD */ uInt msd; /* coefficient MSD */
Int exp; /* exponent top two bits or full */ Int exp; /* exponent top two bits or full */
uInt comb; /* combination field */ uInt comb; /* combination field */
char *cstart; /* coefficient start */ char *cstart; /* coefficient start */
char *c; /* output pointer in string */ char *c; /* output pointer in string */
const uInt *pu; /* work */ const uByte *u; /* work */
char *s, *t; /* .. (source, target) */ char *s, *t; /* .. (source, target) */
Int dpd; /* .. */ Int dpd; /* .. */
Int pre, e; /* .. */ Int pre, e; /* .. */
const uByte *u; /* .. */ uInt uiwork; /* for macros */
uInt sourar[4]; /* source 128-bit */ uInt sourar[4]; /* source 128-bit */
#define sourhi sourar[3] /* name the word with the sign */ #define sourhi sourar[3] /* name the word with the sign */
...@@ -304,18 +304,17 @@ char * decimal128ToString(const decimal128 *d128, char *string){ ...@@ -304,18 +304,17 @@ char * decimal128ToString(const decimal128 *d128, char *string){
#define sourlo sourar[0] /* and the lowest word */ #define sourlo sourar[0] /* and the lowest word */
/* load source from storage; this is endian */ /* load source from storage; this is endian */
pu=(const uInt *)d128->bytes; /* overlay */
if (DECLITEND) { if (DECLITEND) {
sourlo=pu[0]; /* directly load the low int */ sourlo=UBTOUI(d128->bytes ); /* directly load the low int */
sourml=pu[1]; /* then the mid-low */ sourml=UBTOUI(d128->bytes+4 ); /* then the mid-low */
sourmh=pu[2]; /* then the mid-high */ sourmh=UBTOUI(d128->bytes+8 ); /* then the mid-high */
sourhi=pu[3]; /* then the high int */ sourhi=UBTOUI(d128->bytes+12); /* then the high int */
} }
else { else {
sourhi=pu[0]; /* directly load the high int */ sourhi=UBTOUI(d128->bytes ); /* directly load the high int */
sourmh=pu[1]; /* then the mid-high */ sourmh=UBTOUI(d128->bytes+4 ); /* then the mid-high */
sourml=pu[2]; /* then the mid-low */ sourml=UBTOUI(d128->bytes+8 ); /* then the mid-low */
sourlo=pu[3]; /* then the low int */ sourlo=UBTOUI(d128->bytes+12); /* then the low int */
} }
c=string; /* where result will go */ c=string; /* where result will go */
...@@ -327,7 +326,7 @@ char * decimal128ToString(const decimal128 *d128, char *string){ ...@@ -327,7 +326,7 @@ char * decimal128ToString(const decimal128 *d128, char *string){
if (exp==3) { if (exp==3) {
if (msd==0) { /* infinity */ if (msd==0) { /* infinity */
strcpy(c, "Inf"); strcpy(c, "Inf");
strcpy(c+3, "inity"); strcpy(c+3, "inity");
return string; /* easy */ return string; /* easy */
} }
...@@ -353,12 +352,12 @@ char * decimal128ToString(const decimal128 *d128, char *string){ ...@@ -353,12 +352,12 @@ char * decimal128ToString(const decimal128 *d128, char *string){
/* length. We use fixed-length memcpys because variable-length */ /* length. We use fixed-length memcpys because variable-length */
/* causes a subroutine call in GCC. (These are length 4 for speed */ /* causes a subroutine call in GCC. (These are length 4 for speed */
/* and are safe because the array has an extra terminator byte.) */ /* and are safe because the array has an extra terminator byte.) */
#define dpd2char u=&BIN2CHAR[DPD2BIN[dpd]*4]; \ #define dpd2char u=&BIN2CHAR[DPD2BIN[dpd]*4]; \
if (c!=cstart) {memcpy(c, u+1, 4); c+=3;} \ if (c!=cstart) {memcpy(c, u+1, 4); c+=3;} \
else if (*u) {memcpy(c, u+4-*u, 4); c+=*u;} else if (*u) {memcpy(c, u+4-*u, 4); c+=*u;}
dpd=(sourhi>>4)&0x3ff; /* declet 1 */ dpd=(sourhi>>4)&0x3ff; /* declet 1 */
dpd2char; dpd2char;
dpd=((sourhi&0xf)<<6) | (sourmh>>26); /* declet 2 */ dpd=((sourhi&0xf)<<6) | (sourmh>>26); /* declet 2 */
dpd2char; dpd2char;
dpd=(sourmh>>16)&0x3ff; /* declet 3 */ dpd=(sourmh>>16)&0x3ff; /* declet 3 */
dpd2char; dpd2char;
...@@ -381,7 +380,7 @@ char * decimal128ToString(const decimal128 *d128, char *string){ ...@@ -381,7 +380,7 @@ char * decimal128ToString(const decimal128 *d128, char *string){
if (c==cstart) *c++='0'; /* all zeros -- make 0 */ if (c==cstart) *c++='0'; /* all zeros -- make 0 */
if (exp==0) { /* integer or NaN case -- easy */ if (exp==0) { /* integer or NaN case -- easy */
*c='\0'; /* terminate */ *c='\0'; /* terminate */
return string; return string;
} }
...@@ -409,8 +408,8 @@ char * decimal128ToString(const decimal128 *d128, char *string){ ...@@ -409,8 +408,8 @@ char * decimal128ToString(const decimal128 *d128, char *string){
/* finally add the E-part, if needed; it will never be 0, and has */ /* finally add the E-part, if needed; it will never be 0, and has */
/* a maximum length of 4 digits */ /* a maximum length of 4 digits */
if (e!=0) { if (e!=0) {
*c++='E'; /* starts with E */ *c++='E'; /* starts with E */
*c++='+'; /* assume positive */ *c++='+'; /* assume positive */
if (e<0) { if (e<0) {
*(c-1)='-'; /* oops, need '-' */ *(c-1)='-'; /* oops, need '-' */
e=-e; /* uInt, please */ e=-e; /* uInt, please */
...@@ -449,13 +448,13 @@ char * decimal128ToString(const decimal128 *d128, char *string){ ...@@ -449,13 +448,13 @@ char * decimal128ToString(const decimal128 *d128, char *string){
/* ------------------------------------------------------------------ */ /* ------------------------------------------------------------------ */
/* to-number -- conversion from numeric string */ /* to-number -- conversion from numeric string */
/* */ /* */
/* decimal128FromString(result, string, set); */ /* decimal128FromString(result, string, set); */
/* */ /* */
/* result is the decimal128 format number which gets the result of */ /* result is the decimal128 format number which gets the result of */
/* the conversion */ /* the conversion */
/* *string is the character string which should contain a valid */ /* *string is the character string which should contain a valid */
/* number (which may be a special value) */ /* number (which may be a special value) */
/* set is the context */ /* set is the context */
/* */ /* */
/* The context is supplied to this routine is used for error handling */ /* The context is supplied to this routine is used for error handling */
/* (setting of status and traps) and for the rounding mode, only. */ /* (setting of status and traps) and for the rounding mode, only. */
...@@ -464,7 +463,7 @@ char * decimal128ToString(const decimal128 *d128, char *string){ ...@@ -464,7 +463,7 @@ char * decimal128ToString(const decimal128 *d128, char *string){
decimal128 * decimal128FromString(decimal128 *result, const char *string, decimal128 * decimal128FromString(decimal128 *result, const char *string,
decContext *set) { decContext *set) {
decContext dc; /* work */ decContext dc; /* work */
decNumber dn; /* .. */ decNumber dn; /* .. */
decContextDefault(&dc, DEC_INIT_DECIMAL128); /* no traps, please */ decContextDefault(&dc, DEC_INIT_DECIMAL128); /* no traps, please */
dc.round=set->round; /* use supplied rounding */ dc.round=set->round; /* use supplied rounding */
...@@ -483,8 +482,8 @@ decimal128 * decimal128FromString(decimal128 *result, const char *string, ...@@ -483,8 +482,8 @@ decimal128 * decimal128FromString(decimal128 *result, const char *string,
/* returns 1 if the encoding of d128 is canonical, 0 otherwise */ /* returns 1 if the encoding of d128 is canonical, 0 otherwise */
/* No error is possible. */ /* No error is possible. */
/* ------------------------------------------------------------------ */ /* ------------------------------------------------------------------ */
uint32_t decimal128IsCanonical(const decimal128 *d128) { uInt decimal128IsCanonical(const decimal128 *d128) {
decNumber dn; /* work */ decNumber dn; /* work */
decimal128 canon; /* .. */ decimal128 canon; /* .. */
decContext dc; /* .. */ decContext dc; /* .. */
decContextDefault(&dc, DEC_INIT_DECIMAL128); decContextDefault(&dc, DEC_INIT_DECIMAL128);
...@@ -501,7 +500,7 @@ uint32_t decimal128IsCanonical(const decimal128 *d128) { ...@@ -501,7 +500,7 @@ uint32_t decimal128IsCanonical(const decimal128 *d128) {
/* No error is possible. */ /* No error is possible. */
/* ------------------------------------------------------------------ */ /* ------------------------------------------------------------------ */
decimal128 * decimal128Canonical(decimal128 *result, const decimal128 *d128) { decimal128 * decimal128Canonical(decimal128 *result, const decimal128 *d128) {
decNumber dn; /* work */ decNumber dn; /* work */
decContext dc; /* .. */ decContext dc; /* .. */
decContextDefault(&dc, DEC_INIT_DECIMAL128); decContextDefault(&dc, DEC_INIT_DECIMAL128);
decimal128ToNumber(d128, &dn); decimal128ToNumber(d128, &dn);
...@@ -532,13 +531,13 @@ decimal128 * decimal128Canonical(decimal128 *result, const decimal128 *d128) { ...@@ -532,13 +531,13 @@ decimal128 * decimal128Canonical(decimal128 *result, const decimal128 *d128) {
/* This assumes range has been checked and exponent previously 0; */ /* This assumes range has been checked and exponent previously 0; */
/* type of exponent must be unsigned */ /* type of exponent must be unsigned */
#define decimal128SetExpCon(d, e) { \ #define decimal128SetExpCon(d, e) { \
(d)->bytes[0]|=(uint8_t)((e)>>10); \ (d)->bytes[0]|=(uByte)((e)>>10); \
(d)->bytes[1] =(uint8_t)(((e)&0x3fc)>>2); \ (d)->bytes[1] =(uByte)(((e)&0x3fc)>>2); \
(d)->bytes[2]|=(uint8_t)(((e)&0x03)<<6);} (d)->bytes[2]|=(uByte)(((e)&0x03)<<6);}
/* ------------------------------------------------------------------ */ /* ------------------------------------------------------------------ */
/* decimal128Show -- display a decimal128 in hexadecimal [debug aid] */ /* decimal128Show -- display a decimal128 in hexadecimal [debug aid] */
/* d128 -- the number to show */ /* d128 -- the number to show */
/* ------------------------------------------------------------------ */ /* ------------------------------------------------------------------ */
/* Also shows sign/cob/expconfields extracted */ /* Also shows sign/cob/expconfields extracted */
void decimal128Show(const decimal128 *d128) { void decimal128Show(const decimal128 *d128) {
......
...@@ -29,7 +29,7 @@ ...@@ -29,7 +29,7 @@
02110-1301, USA. */ 02110-1301, USA. */
/* ------------------------------------------------------------------ */ /* ------------------------------------------------------------------ */
/* Decimal 128-bit format module header */ /* Decimal 128-bit format module header */
/* ------------------------------------------------------------------ */ /* ------------------------------------------------------------------ */
#if !defined(DECIMAL128) #if !defined(DECIMAL128)
...@@ -46,7 +46,7 @@ ...@@ -46,7 +46,7 @@
#define DECIMAL128_Bias 6176 /* bias for the exponent */ #define DECIMAL128_Bias 6176 /* bias for the exponent */
#define DECIMAL128_String 43 /* maximum string length, +1 */ #define DECIMAL128_String 43 /* maximum string length, +1 */
#define DECIMAL128_EconL 12 /* exp. continuation length */ #define DECIMAL128_EconL 12 /* exp. continuation length */
/* highest biased exponent (Elimit-1) */ /* highest biased exponent (Elimit-1) */
#define DECIMAL128_Ehigh (DECIMAL128_Emax+DECIMAL128_Bias-DECIMAL128_Pmax+1) #define DECIMAL128_Ehigh (DECIMAL128_Emax+DECIMAL128_Bias-DECIMAL128_Pmax+1)
/* check enough digits, if pre-defined */ /* check enough digits, if pre-defined */
...@@ -71,20 +71,20 @@ ...@@ -71,20 +71,20 @@
/* special values [top byte excluding sign bit; last two bits are */ /* special values [top byte excluding sign bit; last two bits are */
/* don't-care for Infinity on input, last bit don't-care for NaN] */ /* don't-care for Infinity on input, last bit don't-care for NaN] */
#if !defined(DECIMAL_NaN) #if !defined(DECIMAL_NaN)
#define DECIMAL_NaN 0x7c /* 0 11111 00 NaN */ #define DECIMAL_NaN 0x7c /* 0 11111 00 NaN */
#define DECIMAL_sNaN 0x7e /* 0 11111 10 sNaN */ #define DECIMAL_sNaN 0x7e /* 0 11111 10 sNaN */
#define DECIMAL_Inf 0x78 /* 0 11110 00 Infinity */ #define DECIMAL_Inf 0x78 /* 0 11110 00 Infinity */
#endif #endif
#include "decimal128Local.h" #include "decimal128Local.h"
/* ---------------------------------------------------------------- */ /* ---------------------------------------------------------------- */
/* Routines */ /* Routines */
/* ---------------------------------------------------------------- */ /* ---------------------------------------------------------------- */
#include "decimal128Symbols.h" #include "decimal128Symbols.h"
/* String conversions */ /* String conversions */
decimal128 * decimal128FromString(decimal128 *, const char *, decContext *); decimal128 * decimal128FromString(decimal128 *, const char *, decContext *);
char * decimal128ToString(const decimal128 *, char *); char * decimal128ToString(const decimal128 *, char *);
char * decimal128ToEngString(const decimal128 *, char *); char * decimal128ToEngString(const decimal128 *, char *);
...@@ -94,7 +94,7 @@ ...@@ -94,7 +94,7 @@
decContext *); decContext *);
decNumber * decimal128ToNumber(const decimal128 *, decNumber *); decNumber * decimal128ToNumber(const decimal128 *, decNumber *);
/* Format-dependent utilities */ /* Format-dependent utilities */
uint32_t decimal128IsCanonical(const decimal128 *); uint32_t decimal128IsCanonical(const decimal128 *);
decimal128 * decimal128Canonical(decimal128 *, const decimal128 *); decimal128 * decimal128Canonical(decimal128 *, const decimal128 *);
......
...@@ -29,7 +29,7 @@ ...@@ -29,7 +29,7 @@
02110-1301, USA. */ 02110-1301, USA. */
/* ------------------------------------------------------------------ */ /* ------------------------------------------------------------------ */
/* Decimal 32-bit format module */ /* Decimal 32-bit format module */
/* ------------------------------------------------------------------ */ /* ------------------------------------------------------------------ */
/* This module comprises the routines for decimal32 format numbers. */ /* This module comprises the routines for decimal32 format numbers. */
/* Conversions are supplied to and from decNumber and String. */ /* Conversions are supplied to and from decNumber and String. */
...@@ -42,8 +42,8 @@ ...@@ -42,8 +42,8 @@
#include <string.h> /* [for memset/memcpy] */ #include <string.h> /* [for memset/memcpy] */
#include <stdio.h> /* [for printf] */ #include <stdio.h> /* [for printf] */
#include "dconfig.h" /* GCC definitions */ #include "dconfig.h" /* GCC definitions */
#define DECNUMDIGITS 7 /* make decNumbers with space for 7 */ #define DECNUMDIGITS 7 /* make decNumbers with space for 7 */
#include "decNumber.h" /* base number library */ #include "decNumber.h" /* base number library */
#include "decNumberLocal.h" /* decNumber local types, etc. */ #include "decNumberLocal.h" /* decNumber local types, etc. */
#include "decimal32.h" /* our primary include */ #include "decimal32.h" /* our primary include */
...@@ -69,9 +69,9 @@ extern void decNumberShow(const decNumber *); /* .. */ ...@@ -69,9 +69,9 @@ extern void decNumberShow(const decNumber *); /* .. */
/* ------------------------------------------------------------------ */ /* ------------------------------------------------------------------ */
/* decimal32FromNumber -- convert decNumber to decimal32 */ /* decimal32FromNumber -- convert decNumber to decimal32 */
/* */ /* */
/* ds is the target decimal32 */ /* ds is the target decimal32 */
/* dn is the source number (assumed valid) */ /* dn is the source number (assumed valid) */
/* set is the context, used only for reporting errors */ /* set is the context, used only for reporting errors */
/* */ /* */
/* The set argument is used only for status reporting and for the */ /* The set argument is used only for status reporting and for the */
/* rounding mode (used if the coefficient is more than DECIMAL32_Pmax */ /* rounding mode (used if the coefficient is more than DECIMAL32_Pmax */
...@@ -89,8 +89,8 @@ decimal32 * decimal32FromNumber(decimal32 *d32, const decNumber *dn, ...@@ -89,8 +89,8 @@ decimal32 * decimal32FromNumber(decimal32 *d32, const decNumber *dn,
Int ae; /* adjusted exponent */ Int ae; /* adjusted exponent */
decNumber dw; /* work */ decNumber dw; /* work */
decContext dc; /* .. */ decContext dc; /* .. */
uInt *pu; /* .. */
uInt comb, exp; /* .. */ uInt comb, exp; /* .. */
uInt uiwork; /* for macros */
uInt targ=0; /* target 32-bit */ uInt targ=0; /* target 32-bit */
/* If the number has too many digits, or the exponent could be */ /* If the number has too many digits, or the exponent could be */
...@@ -98,9 +98,9 @@ decimal32 * decimal32FromNumber(decimal32 *d32, const decNumber *dn, ...@@ -98,9 +98,9 @@ decimal32 * decimal32FromNumber(decimal32 *d32, const decNumber *dn,
/* constraints. This could push the number to Infinity or zero, */ /* constraints. This could push the number to Infinity or zero, */
/* so this check and rounding must be done before generating the */ /* so this check and rounding must be done before generating the */
/* decimal32] */ /* decimal32] */
ae=dn->exponent+dn->digits-1; /* [0 if special] */ ae=dn->exponent+dn->digits-1; /* [0 if special] */
if (dn->digits>DECIMAL32_Pmax /* too many digits */ if (dn->digits>DECIMAL32_Pmax /* too many digits */
|| ae>DECIMAL32_Emax /* likely overflow */ || ae>DECIMAL32_Emax /* likely overflow */
|| ae<DECIMAL32_Emin) { /* likely underflow */ || ae<DECIMAL32_Emin) { /* likely underflow */
decContextDefault(&dc, DEC_INIT_DECIMAL32); /* [no traps] */ decContextDefault(&dc, DEC_INIT_DECIMAL32); /* [no traps] */
dc.round=set->round; /* use supplied rounding */ dc.round=set->round; /* use supplied rounding */
...@@ -114,7 +114,7 @@ decimal32 * decimal32FromNumber(decimal32 *d32, const decNumber *dn, ...@@ -114,7 +114,7 @@ decimal32 * decimal32FromNumber(decimal32 *d32, const decNumber *dn,
if (dn->bits&DECSPECIAL) { /* a special value */ if (dn->bits&DECSPECIAL) { /* a special value */
if (dn->bits&DECINF) targ=DECIMAL_Inf<<24; if (dn->bits&DECINF) targ=DECIMAL_Inf<<24;
else { /* sNaN or qNaN */ else { /* sNaN or qNaN */
if ((*dn->lsu!=0 || dn->digits>1) /* non-zero coefficient */ if ((*dn->lsu!=0 || dn->digits>1) /* non-zero coefficient */
&& (dn->digits<DECIMAL32_Pmax)) { /* coefficient fits */ && (dn->digits<DECIMAL32_Pmax)) { /* coefficient fits */
decDigitsToDPD(dn, &targ, 0); decDigitsToDPD(dn, &targ, 0);
} }
...@@ -140,7 +140,7 @@ decimal32 * decimal32FromNumber(decimal32 *d32, const decNumber *dn, ...@@ -140,7 +140,7 @@ decimal32 * decimal32FromNumber(decimal32 *d32, const decNumber *dn,
comb=(exp>>3) & 0x18; /* msd=0, exp top 2 bits .. */ comb=(exp>>3) & 0x18; /* msd=0, exp top 2 bits .. */
} }
else { /* non-zero finite number */ else { /* non-zero finite number */
uInt msd; /* work */ uInt msd; /* work */
Int pad=0; /* coefficient pad digits */ Int pad=0; /* coefficient pad digits */
/* the dn is known to fit, but it may need to be padded */ /* the dn is known to fit, but it may need to be padded */
...@@ -175,8 +175,7 @@ decimal32 * decimal32FromNumber(decimal32 *d32, const decNumber *dn, ...@@ -175,8 +175,7 @@ decimal32 * decimal32FromNumber(decimal32 *d32, const decNumber *dn,
if (dn->bits&DECNEG) targ|=0x80000000; /* add sign bit */ if (dn->bits&DECNEG) targ|=0x80000000; /* add sign bit */
/* now write to storage; this is endian */ /* now write to storage; this is endian */
pu=(uInt *)d32->bytes; /* overlay */ UBFROMUI(d32->bytes, targ); /* directly store the int */
*pu=targ; /* directly store the int */
if (status!=0) decContextSetStatus(set, status); /* pass on status */ if (status!=0) decContextSetStatus(set, status); /* pass on status */
/* decimal32Show(d32); */ /* decimal32Show(d32); */
...@@ -194,13 +193,12 @@ decNumber * decimal32ToNumber(const decimal32 *d32, decNumber *dn) { ...@@ -194,13 +193,12 @@ decNumber * decimal32ToNumber(const decimal32 *d32, decNumber *dn) {
uInt exp; /* exponent top two bits */ uInt exp; /* exponent top two bits */
uInt comb; /* combination field */ uInt comb; /* combination field */
uInt sour; /* source 32-bit */ uInt sour; /* source 32-bit */
const uInt *pu; /* work */ uInt uiwork; /* for macros */
/* load source from storage; this is endian */ /* load source from storage; this is endian */
pu=(const uInt *)d32->bytes; /* overlay */ sour=UBTOUI(d32->bytes); /* directly load the int */
sour=*pu; /* directly load the int */
comb=(sour>>26)&0x1f; /* combination field */ comb=(sour>>26)&0x1f; /* combination field */
decNumberZero(dn); /* clean number */ decNumberZero(dn); /* clean number */
if (sour&0x80000000) dn->bits=DECNEG; /* set sign if negative */ if (sour&0x80000000) dn->bits=DECNEG; /* set sign if negative */
...@@ -208,7 +206,7 @@ decNumber * decimal32ToNumber(const decimal32 *d32, decNumber *dn) { ...@@ -208,7 +206,7 @@ decNumber * decimal32ToNumber(const decimal32 *d32, decNumber *dn) {
msd=COMBMSD[comb]; /* decode the combination field */ msd=COMBMSD[comb]; /* decode the combination field */
exp=COMBEXP[comb]; /* .. */ exp=COMBEXP[comb]; /* .. */
if (exp==3) { /* is a special */ if (exp==3) { /* is a special */
if (msd==0) { if (msd==0) {
dn->bits|=DECINF; dn->bits|=DECINF;
return dn; /* no coefficient needed */ return dn; /* no coefficient needed */
...@@ -229,7 +227,7 @@ decNumber * decimal32ToNumber(const decimal32 *d32, decNumber *dn) { ...@@ -229,7 +227,7 @@ decNumber * decimal32ToNumber(const decimal32 *d32, decNumber *dn) {
return dn; return dn;
} }
/* msd=0 */ /* msd=0 */
if (!sour) return dn; /* easy: coefficient is 0 */ if (!sour) return dn; /* easy: coefficient is 0 */
if (sour&0x000ffc00) /* need 2 declets? */ if (sour&0x000ffc00) /* need 2 declets? */
decDigitsFromDPD(dn, &sour, 2); /* process 2 declets */ decDigitsFromDPD(dn, &sour, 2); /* process 2 declets */
else else
...@@ -238,11 +236,11 @@ decNumber * decimal32ToNumber(const decimal32 *d32, decNumber *dn) { ...@@ -238,11 +236,11 @@ decNumber * decimal32ToNumber(const decimal32 *d32, decNumber *dn) {
} /* decimal32ToNumber */ } /* decimal32ToNumber */
/* ------------------------------------------------------------------ */ /* ------------------------------------------------------------------ */
/* to-scientific-string -- conversion to numeric string */ /* to-scientific-string -- conversion to numeric string */
/* to-engineering-string -- conversion to numeric string */ /* to-engineering-string -- conversion to numeric string */
/* */ /* */
/* decimal32ToString(d32, string); */ /* decimal32ToString(d32, string); */
/* decimal32ToEngString(d32, string); */ /* decimal32ToEngString(d32, string); */
/* */ /* */
/* d32 is the decimal32 format number to convert */ /* d32 is the decimal32 format number to convert */
/* string is the string where the result will be laid out */ /* string is the string where the result will be laid out */
...@@ -252,7 +250,7 @@ decNumber * decimal32ToNumber(const decimal32 *d32, decNumber *dn) { ...@@ -252,7 +250,7 @@ decNumber * decimal32ToNumber(const decimal32 *d32, decNumber *dn) {
/* No error is possible, and no status can be set. */ /* No error is possible, and no status can be set. */
/* ------------------------------------------------------------------ */ /* ------------------------------------------------------------------ */
char * decimal32ToEngString(const decimal32 *d32, char *string){ char * decimal32ToEngString(const decimal32 *d32, char *string){
decNumber dn; /* work */ decNumber dn; /* work */
decimal32ToNumber(d32, &dn); decimal32ToNumber(d32, &dn);
decNumberToEngString(&dn, string); decNumberToEngString(&dn, string);
return string; return string;
...@@ -262,29 +260,28 @@ char * decimal32ToString(const decimal32 *d32, char *string){ ...@@ -262,29 +260,28 @@ char * decimal32ToString(const decimal32 *d32, char *string){
uInt msd; /* coefficient MSD */ uInt msd; /* coefficient MSD */
Int exp; /* exponent top two bits or full */ Int exp; /* exponent top two bits or full */
uInt comb; /* combination field */ uInt comb; /* combination field */
char *cstart; /* coefficient start */ char *cstart; /* coefficient start */
char *c; /* output pointer in string */ char *c; /* output pointer in string */
const uInt *pu; /* work */ const uByte *u; /* work */
const uByte *u; /* .. */
char *s, *t; /* .. (source, target) */ char *s, *t; /* .. (source, target) */
Int dpd; /* .. */ Int dpd; /* .. */
Int pre, e; /* .. */ Int pre, e; /* .. */
uInt uiwork; /* for macros */
uInt sour; /* source 32-bit */ uInt sour; /* source 32-bit */
/* load source from storage; this is endian */ /* load source from storage; this is endian */
pu=(const uInt *)d32->bytes; /* overlay */ sour=UBTOUI(d32->bytes); /* directly load the int */
sour=*pu; /* directly load the int */
c=string; /* where result will go */ c=string; /* where result will go */
if (((Int)sour)<0) *c++='-'; /* handle sign */ if (((Int)sour)<0) *c++='-'; /* handle sign */
comb=(sour>>26)&0x1f; /* combination field */ comb=(sour>>26)&0x1f; /* combination field */
msd=COMBMSD[comb]; /* decode the combination field */ msd=COMBMSD[comb]; /* decode the combination field */
exp=COMBEXP[comb]; /* .. */ exp=COMBEXP[comb]; /* .. */
if (exp==3) { if (exp==3) {
if (msd==0) { /* infinity */ if (msd==0) { /* infinity */
strcpy(c, "Inf"); strcpy(c, "Inf");
strcpy(c+3, "inity"); strcpy(c+3, "inity");
return string; /* easy */ return string; /* easy */
} }
...@@ -309,18 +306,18 @@ char * decimal32ToString(const decimal32 *d32, char *string){ ...@@ -309,18 +306,18 @@ char * decimal32ToString(const decimal32 *d32, char *string){
/* length. We use fixed-length memcpys because variable-length */ /* length. We use fixed-length memcpys because variable-length */
/* causes a subroutine call in GCC. (These are length 4 for speed */ /* causes a subroutine call in GCC. (These are length 4 for speed */
/* and are safe because the array has an extra terminator byte.) */ /* and are safe because the array has an extra terminator byte.) */
#define dpd2char u=&BIN2CHAR[DPD2BIN[dpd]*4]; \ #define dpd2char u=&BIN2CHAR[DPD2BIN[dpd]*4]; \
if (c!=cstart) {memcpy(c, u+1, 4); c+=3;} \ if (c!=cstart) {memcpy(c, u+1, 4); c+=3;} \
else if (*u) {memcpy(c, u+4-*u, 4); c+=*u;} else if (*u) {memcpy(c, u+4-*u, 4); c+=*u;}
dpd=(sour>>10)&0x3ff; /* declet 1 */ dpd=(sour>>10)&0x3ff; /* declet 1 */
dpd2char; dpd2char;
dpd=(sour)&0x3ff; /* declet 2 */ dpd=(sour)&0x3ff; /* declet 2 */
dpd2char; dpd2char;
if (c==cstart) *c++='0'; /* all zeros -- make 0 */ if (c==cstart) *c++='0'; /* all zeros -- make 0 */
if (exp==0) { /* integer or NaN case -- easy */ if (exp==0) { /* integer or NaN case -- easy */
*c='\0'; /* terminate */ *c='\0'; /* terminate */
return string; return string;
} }
...@@ -348,13 +345,13 @@ char * decimal32ToString(const decimal32 *d32, char *string){ ...@@ -348,13 +345,13 @@ char * decimal32ToString(const decimal32 *d32, char *string){
/* finally add the E-part, if needed; it will never be 0, and has */ /* finally add the E-part, if needed; it will never be 0, and has */
/* a maximum length of 3 digits (E-101 case) */ /* a maximum length of 3 digits (E-101 case) */
if (e!=0) { if (e!=0) {
*c++='E'; /* starts with E */ *c++='E'; /* starts with E */
*c++='+'; /* assume positive */ *c++='+'; /* assume positive */
if (e<0) { if (e<0) {
*(c-1)='-'; /* oops, need '-' */ *(c-1)='-'; /* oops, need '-' */
e=-e; /* uInt, please */ e=-e; /* uInt, please */
} }
u=&BIN2CHAR[e*4]; /* -> length byte */ u=&BIN2CHAR[e*4]; /* -> length byte */
memcpy(c, u+4-*u, 4); /* copy fixed 4 characters [is safe] */ memcpy(c, u+4-*u, 4); /* copy fixed 4 characters [is safe] */
c+=*u; /* bump pointer appropriately */ c+=*u; /* bump pointer appropriately */
} }
...@@ -384,7 +381,7 @@ char * decimal32ToString(const decimal32 *d32, char *string){ ...@@ -384,7 +381,7 @@ char * decimal32ToString(const decimal32 *d32, char *string){
/* the conversion */ /* the conversion */
/* *string is the character string which should contain a valid */ /* *string is the character string which should contain a valid */
/* number (which may be a special value) */ /* number (which may be a special value) */
/* set is the context */ /* set is the context */
/* */ /* */
/* The context is supplied to this routine is used for error handling */ /* The context is supplied to this routine is used for error handling */
/* (setting of status and traps) and for the rounding mode, only. */ /* (setting of status and traps) and for the rounding mode, only. */
...@@ -393,7 +390,7 @@ char * decimal32ToString(const decimal32 *d32, char *string){ ...@@ -393,7 +390,7 @@ char * decimal32ToString(const decimal32 *d32, char *string){
decimal32 * decimal32FromString(decimal32 *result, const char *string, decimal32 * decimal32FromString(decimal32 *result, const char *string,
decContext *set) { decContext *set) {
decContext dc; /* work */ decContext dc; /* work */
decNumber dn; /* .. */ decNumber dn; /* .. */
decContextDefault(&dc, DEC_INIT_DECIMAL32); /* no traps, please */ decContextDefault(&dc, DEC_INIT_DECIMAL32); /* no traps, please */
dc.round=set->round; /* use supplied rounding */ dc.round=set->round; /* use supplied rounding */
...@@ -409,11 +406,11 @@ decimal32 * decimal32FromString(decimal32 *result, const char *string, ...@@ -409,11 +406,11 @@ decimal32 * decimal32FromString(decimal32 *result, const char *string,
/* ------------------------------------------------------------------ */ /* ------------------------------------------------------------------ */
/* decimal32IsCanonical -- test whether encoding is canonical */ /* decimal32IsCanonical -- test whether encoding is canonical */
/* d32 is the source decimal32 */ /* d32 is the source decimal32 */
/* returns 1 if the encoding of d32 is canonical, 0 otherwise */ /* returns 1 if the encoding of d32 is canonical, 0 otherwise */
/* No error is possible. */ /* No error is possible. */
/* ------------------------------------------------------------------ */ /* ------------------------------------------------------------------ */
uint32_t decimal32IsCanonical(const decimal32 *d32) { uInt decimal32IsCanonical(const decimal32 *d32) {
decNumber dn; /* work */ decNumber dn; /* work */
decimal32 canon; /* .. */ decimal32 canon; /* .. */
decContext dc; /* .. */ decContext dc; /* .. */
decContextDefault(&dc, DEC_INIT_DECIMAL32); decContextDefault(&dc, DEC_INIT_DECIMAL32);
...@@ -430,7 +427,7 @@ uint32_t decimal32IsCanonical(const decimal32 *d32) { ...@@ -430,7 +427,7 @@ uint32_t decimal32IsCanonical(const decimal32 *d32) {
/* No error is possible. */ /* No error is possible. */
/* ------------------------------------------------------------------ */ /* ------------------------------------------------------------------ */
decimal32 * decimal32Canonical(decimal32 *result, const decimal32 *d32) { decimal32 * decimal32Canonical(decimal32 *result, const decimal32 *d32) {
decNumber dn; /* work */ decNumber dn; /* work */
decContext dc; /* .. */ decContext dc; /* .. */
decContextDefault(&dc, DEC_INIT_DECIMAL32); decContextDefault(&dc, DEC_INIT_DECIMAL32);
decimal32ToNumber(d32, &dn); decimal32ToNumber(d32, &dn);
...@@ -460,8 +457,8 @@ decimal32 * decimal32Canonical(decimal32 *result, const decimal32 *d32) { ...@@ -460,8 +457,8 @@ decimal32 * decimal32Canonical(decimal32 *result, const decimal32 *d32) {
/* This assumes range has been checked and exponent previously 0; */ /* This assumes range has been checked and exponent previously 0; */
/* type of exponent must be unsigned */ /* type of exponent must be unsigned */
#define decimal32SetExpCon(d, e) { \ #define decimal32SetExpCon(d, e) { \
(d)->bytes[0]|=(uint8_t)((e)>>4); \ (d)->bytes[0]|=(uByte)((e)>>4); \
(d)->bytes[1]|=(uint8_t)(((e)&0x0F)<<4);} (d)->bytes[1]|=(uByte)(((e)&0x0F)<<4);}
/* ------------------------------------------------------------------ */ /* ------------------------------------------------------------------ */
/* decimal32Show -- display a decimal32 in hexadecimal [debug aid] */ /* decimal32Show -- display a decimal32 in hexadecimal [debug aid] */
......
...@@ -35,7 +35,7 @@ ...@@ -35,7 +35,7 @@
#if !defined(DECIMAL32) #if !defined(DECIMAL32)
#define DECIMAL32 #define DECIMAL32
#define DEC32NAME "decimal32" /* Short name */ #define DEC32NAME "decimal32" /* Short name */
#define DEC32FULLNAME "Decimal 32-bit Number" /* Verbose name */ #define DEC32FULLNAME "Decimal 32-bit Number" /* Verbose name */
#define DEC32AUTHOR "Mike Cowlishaw" /* Who to blame */ #define DEC32AUTHOR "Mike Cowlishaw" /* Who to blame */
/* parameters for decimal32s */ /* parameters for decimal32s */
...@@ -46,7 +46,7 @@ ...@@ -46,7 +46,7 @@
#define DECIMAL32_Bias 101 /* bias for the exponent */ #define DECIMAL32_Bias 101 /* bias for the exponent */
#define DECIMAL32_String 15 /* maximum string length, +1 */ #define DECIMAL32_String 15 /* maximum string length, +1 */
#define DECIMAL32_EconL 6 /* exp. continuation length */ #define DECIMAL32_EconL 6 /* exp. continuation length */
/* highest biased exponent (Elimit-1) */ /* highest biased exponent (Elimit-1) */
#define DECIMAL32_Ehigh (DECIMAL32_Emax+DECIMAL32_Bias-DECIMAL32_Pmax+1) #define DECIMAL32_Ehigh (DECIMAL32_Emax+DECIMAL32_Bias-DECIMAL32_Pmax+1)
/* check enough digits, if pre-defined */ /* check enough digits, if pre-defined */
...@@ -71,18 +71,18 @@ ...@@ -71,18 +71,18 @@
/* special values [top byte excluding sign bit; last two bits are */ /* special values [top byte excluding sign bit; last two bits are */
/* don't-care for Infinity on input, last bit don't-care for NaN] */ /* don't-care for Infinity on input, last bit don't-care for NaN] */
#if !defined(DECIMAL_NaN) #if !defined(DECIMAL_NaN)
#define DECIMAL_NaN 0x7c /* 0 11111 00 NaN */ #define DECIMAL_NaN 0x7c /* 0 11111 00 NaN */
#define DECIMAL_sNaN 0x7e /* 0 11111 10 sNaN */ #define DECIMAL_sNaN 0x7e /* 0 11111 10 sNaN */
#define DECIMAL_Inf 0x78 /* 0 11110 00 Infinity */ #define DECIMAL_Inf 0x78 /* 0 11110 00 Infinity */
#endif #endif
/* ---------------------------------------------------------------- */ /* ---------------------------------------------------------------- */
/* Routines */ /* Routines */
/* ---------------------------------------------------------------- */ /* ---------------------------------------------------------------- */
#include "decimal32Symbols.h" #include "decimal32Symbols.h"
/* String conversions */ /* String conversions */
decimal32 * decimal32FromString(decimal32 *, const char *, decContext *); decimal32 * decimal32FromString(decimal32 *, const char *, decContext *);
char * decimal32ToString(const decimal32 *, char *); char * decimal32ToString(const decimal32 *, char *);
char * decimal32ToEngString(const decimal32 *, char *); char * decimal32ToEngString(const decimal32 *, char *);
...@@ -92,7 +92,7 @@ ...@@ -92,7 +92,7 @@
decContext *); decContext *);
decNumber * decimal32ToNumber(const decimal32 *, decNumber *); decNumber * decimal32ToNumber(const decimal32 *, decNumber *);
/* Format-dependent utilities */ /* Format-dependent utilities */
uint32_t decimal32IsCanonical(const decimal32 *); uint32_t decimal32IsCanonical(const decimal32 *);
decimal32 * decimal32Canonical(decimal32 *, const decimal32 *); decimal32 * decimal32Canonical(decimal32 *, const decimal32 *);
......
...@@ -29,7 +29,7 @@ ...@@ -29,7 +29,7 @@
02110-1301, USA. */ 02110-1301, USA. */
/* ------------------------------------------------------------------ */ /* ------------------------------------------------------------------ */
/* Decimal 64-bit format module */ /* Decimal 64-bit format module */
/* ------------------------------------------------------------------ */ /* ------------------------------------------------------------------ */
/* This module comprises the routines for decimal64 format numbers. */ /* This module comprises the routines for decimal64 format numbers. */
/* Conversions are supplied to and from decNumber and String. */ /* Conversions are supplied to and from decNumber and String. */
...@@ -42,8 +42,8 @@ ...@@ -42,8 +42,8 @@
#include <string.h> /* [for memset/memcpy] */ #include <string.h> /* [for memset/memcpy] */
#include <stdio.h> /* [for printf] */ #include <stdio.h> /* [for printf] */
#include "dconfig.h" /* GCC definitions */ #include "dconfig.h" /* GCC definitions */
#define DECNUMDIGITS 16 /* make decNumbers with space for 16 */ #define DECNUMDIGITS 16 /* make decNumbers with space for 16 */
#include "decNumber.h" /* base number library */ #include "decNumber.h" /* base number library */
#include "decNumberLocal.h" /* decNumber local types, etc. */ #include "decNumberLocal.h" /* decNumber local types, etc. */
#include "decimal64.h" /* our primary include */ #include "decimal64.h" /* our primary include */
...@@ -75,9 +75,9 @@ extern void decNumberShow(const decNumber *); /* .. */ ...@@ -75,9 +75,9 @@ extern void decNumberShow(const decNumber *); /* .. */
/* ------------------------------------------------------------------ */ /* ------------------------------------------------------------------ */
/* decimal64FromNumber -- convert decNumber to decimal64 */ /* decimal64FromNumber -- convert decNumber to decimal64 */
/* */ /* */
/* ds is the target decimal64 */ /* ds is the target decimal64 */
/* dn is the source number (assumed valid) */ /* dn is the source number (assumed valid) */
/* set is the context, used only for reporting errors */ /* set is the context, used only for reporting errors */
/* */ /* */
/* The set argument is used only for status reporting and for the */ /* The set argument is used only for status reporting and for the */
/* rounding mode (used if the coefficient is more than DECIMAL64_Pmax */ /* rounding mode (used if the coefficient is more than DECIMAL64_Pmax */
...@@ -95,8 +95,8 @@ decimal64 * decimal64FromNumber(decimal64 *d64, const decNumber *dn, ...@@ -95,8 +95,8 @@ decimal64 * decimal64FromNumber(decimal64 *d64, const decNumber *dn,
Int ae; /* adjusted exponent */ Int ae; /* adjusted exponent */
decNumber dw; /* work */ decNumber dw; /* work */
decContext dc; /* .. */ decContext dc; /* .. */
uInt *pu; /* .. */
uInt comb, exp; /* .. */ uInt comb, exp; /* .. */
uInt uiwork; /* for macros */
uInt targar[2]={0, 0}; /* target 64-bit */ uInt targar[2]={0, 0}; /* target 64-bit */
#define targhi targar[1] /* name the word with the sign */ #define targhi targar[1] /* name the word with the sign */
#define targlo targar[0] /* and the other */ #define targlo targar[0] /* and the other */
...@@ -106,9 +106,9 @@ decimal64 * decimal64FromNumber(decimal64 *d64, const decNumber *dn, ...@@ -106,9 +106,9 @@ decimal64 * decimal64FromNumber(decimal64 *d64, const decNumber *dn,
/* constraints. This could push the number to Infinity or zero, */ /* constraints. This could push the number to Infinity or zero, */
/* so this check and rounding must be done before generating the */ /* so this check and rounding must be done before generating the */
/* decimal64] */ /* decimal64] */
ae=dn->exponent+dn->digits-1; /* [0 if special] */ ae=dn->exponent+dn->digits-1; /* [0 if special] */
if (dn->digits>DECIMAL64_Pmax /* too many digits */ if (dn->digits>DECIMAL64_Pmax /* too many digits */
|| ae>DECIMAL64_Emax /* likely overflow */ || ae>DECIMAL64_Emax /* likely overflow */
|| ae<DECIMAL64_Emin) { /* likely underflow */ || ae<DECIMAL64_Emin) { /* likely underflow */
decContextDefault(&dc, DEC_INIT_DECIMAL64); /* [no traps] */ decContextDefault(&dc, DEC_INIT_DECIMAL64); /* [no traps] */
dc.round=set->round; /* use supplied rounding */ dc.round=set->round; /* use supplied rounding */
...@@ -122,7 +122,7 @@ decimal64 * decimal64FromNumber(decimal64 *d64, const decNumber *dn, ...@@ -122,7 +122,7 @@ decimal64 * decimal64FromNumber(decimal64 *d64, const decNumber *dn,
if (dn->bits&DECSPECIAL) { /* a special value */ if (dn->bits&DECSPECIAL) { /* a special value */
if (dn->bits&DECINF) targhi=DECIMAL_Inf<<24; if (dn->bits&DECINF) targhi=DECIMAL_Inf<<24;
else { /* sNaN or qNaN */ else { /* sNaN or qNaN */
if ((*dn->lsu!=0 || dn->digits>1) /* non-zero coefficient */ if ((*dn->lsu!=0 || dn->digits>1) /* non-zero coefficient */
&& (dn->digits<DECIMAL64_Pmax)) { /* coefficient fits */ && (dn->digits<DECIMAL64_Pmax)) { /* coefficient fits */
decDigitsToDPD(dn, targar, 0); decDigitsToDPD(dn, targar, 0);
} }
...@@ -148,7 +148,7 @@ decimal64 * decimal64FromNumber(decimal64 *d64, const decNumber *dn, ...@@ -148,7 +148,7 @@ decimal64 * decimal64FromNumber(decimal64 *d64, const decNumber *dn,
comb=(exp>>5) & 0x18; /* msd=0, exp top 2 bits .. */ comb=(exp>>5) & 0x18; /* msd=0, exp top 2 bits .. */
} }
else { /* non-zero finite number */ else { /* non-zero finite number */
uInt msd; /* work */ uInt msd; /* work */
Int pad=0; /* coefficient pad digits */ Int pad=0; /* coefficient pad digits */
/* the dn is known to fit, but it may need to be padded */ /* the dn is known to fit, but it may need to be padded */
...@@ -193,14 +193,15 @@ decimal64 * decimal64FromNumber(decimal64 *d64, const decNumber *dn, ...@@ -193,14 +193,15 @@ decimal64 * decimal64FromNumber(decimal64 *d64, const decNumber *dn,
if (dn->bits&DECNEG) targhi|=0x80000000; /* add sign bit */ if (dn->bits&DECNEG) targhi|=0x80000000; /* add sign bit */
/* now write to storage; this is now always endian */ /* now write to storage; this is now always endian */
pu=(uInt *)d64->bytes; /* overlay */
if (DECLITEND) { if (DECLITEND) {
pu[0]=targar[0]; /* directly store the low int */ /* lo int then hi */
pu[1]=targar[1]; /* then the high int */ UBFROMUI(d64->bytes, targar[0]);
UBFROMUI(d64->bytes+4, targar[1]);
} }
else { else {
pu[0]=targar[1]; /* directly store the high int */ /* hi int then lo */
pu[1]=targar[0]; /* then the low int */ UBFROMUI(d64->bytes, targar[1]);
UBFROMUI(d64->bytes+4, targar[0]);
} }
if (status!=0) decContextSetStatus(set, status); /* pass on status */ if (status!=0) decContextSetStatus(set, status); /* pass on status */
...@@ -218,21 +219,20 @@ decNumber * decimal64ToNumber(const decimal64 *d64, decNumber *dn) { ...@@ -218,21 +219,20 @@ decNumber * decimal64ToNumber(const decimal64 *d64, decNumber *dn) {
uInt msd; /* coefficient MSD */ uInt msd; /* coefficient MSD */
uInt exp; /* exponent top two bits */ uInt exp; /* exponent top two bits */
uInt comb; /* combination field */ uInt comb; /* combination field */
const uInt *pu; /* work */ Int need; /* work */
Int need; /* .. */ uInt uiwork; /* for macros */
uInt sourar[2]; /* source 64-bit */ uInt sourar[2]; /* source 64-bit */
#define sourhi sourar[1] /* name the word with the sign */ #define sourhi sourar[1] /* name the word with the sign */
#define sourlo sourar[0] /* and the lower word */ #define sourlo sourar[0] /* and the lower word */
/* load source from storage; this is endian */ /* load source from storage; this is endian */
pu=(const uInt *)d64->bytes; /* overlay */
if (DECLITEND) { if (DECLITEND) {
sourlo=pu[0]; /* directly load the low int */ sourlo=UBTOUI(d64->bytes ); /* directly load the low int */
sourhi=pu[1]; /* then the high int */ sourhi=UBTOUI(d64->bytes+4); /* then the high int */
} }
else { else {
sourhi=pu[0]; /* directly load the high int */ sourhi=UBTOUI(d64->bytes ); /* directly load the high int */
sourlo=pu[1]; /* then the low int */ sourlo=UBTOUI(d64->bytes+4); /* then the low int */
} }
comb=(sourhi>>26)&0x1f; /* combination field */ comb=(sourhi>>26)&0x1f; /* combination field */
...@@ -243,7 +243,7 @@ decNumber * decimal64ToNumber(const decimal64 *d64, decNumber *dn) { ...@@ -243,7 +243,7 @@ decNumber * decimal64ToNumber(const decimal64 *d64, decNumber *dn) {
msd=COMBMSD[comb]; /* decode the combination field */ msd=COMBMSD[comb]; /* decode the combination field */
exp=COMBEXP[comb]; /* .. */ exp=COMBEXP[comb]; /* .. */
if (exp==3) { /* is a special */ if (exp==3) { /* is a special */
if (msd==0) { if (msd==0) {
dn->bits|=DECINF; dn->bits|=DECINF;
return dn; /* no coefficient needed */ return dn; /* no coefficient needed */
...@@ -281,11 +281,11 @@ decNumber * decimal64ToNumber(const decimal64 *d64, decNumber *dn) { ...@@ -281,11 +281,11 @@ decNumber * decimal64ToNumber(const decimal64 *d64, decNumber *dn) {
/* ------------------------------------------------------------------ */ /* ------------------------------------------------------------------ */
/* to-scientific-string -- conversion to numeric string */ /* to-scientific-string -- conversion to numeric string */
/* to-engineering-string -- conversion to numeric string */ /* to-engineering-string -- conversion to numeric string */
/* */ /* */
/* decimal64ToString(d64, string); */ /* decimal64ToString(d64, string); */
/* decimal64ToEngString(d64, string); */ /* decimal64ToEngString(d64, string); */
/* */ /* */
/* d64 is the decimal64 format number to convert */ /* d64 is the decimal64 format number to convert */
/* string is the string where the result will be laid out */ /* string is the string where the result will be laid out */
...@@ -295,7 +295,7 @@ decNumber * decimal64ToNumber(const decimal64 *d64, decNumber *dn) { ...@@ -295,7 +295,7 @@ decNumber * decimal64ToNumber(const decimal64 *d64, decNumber *dn) {
/* No error is possible, and no status can be set. */ /* No error is possible, and no status can be set. */
/* ------------------------------------------------------------------ */ /* ------------------------------------------------------------------ */
char * decimal64ToEngString(const decimal64 *d64, char *string){ char * decimal64ToEngString(const decimal64 *d64, char *string){
decNumber dn; /* work */ decNumber dn; /* work */
decimal64ToNumber(d64, &dn); decimal64ToNumber(d64, &dn);
decNumberToEngString(&dn, string); decNumberToEngString(&dn, string);
return string; return string;
...@@ -305,27 +305,26 @@ char * decimal64ToString(const decimal64 *d64, char *string){ ...@@ -305,27 +305,26 @@ char * decimal64ToString(const decimal64 *d64, char *string){
uInt msd; /* coefficient MSD */ uInt msd; /* coefficient MSD */
Int exp; /* exponent top two bits or full */ Int exp; /* exponent top two bits or full */
uInt comb; /* combination field */ uInt comb; /* combination field */
char *cstart; /* coefficient start */ char *cstart; /* coefficient start */
char *c; /* output pointer in string */ char *c; /* output pointer in string */
const uInt *pu; /* work */ const uByte *u; /* work */
char *s, *t; /* .. (source, target) */ char *s, *t; /* .. (source, target) */
Int dpd; /* .. */ Int dpd; /* .. */
Int pre, e; /* .. */ Int pre, e; /* .. */
const uByte *u; /* .. */ uInt uiwork; /* for macros */
uInt sourar[2]; /* source 64-bit */ uInt sourar[2]; /* source 64-bit */
#define sourhi sourar[1] /* name the word with the sign */ #define sourhi sourar[1] /* name the word with the sign */
#define sourlo sourar[0] /* and the lower word */ #define sourlo sourar[0] /* and the lower word */
/* load source from storage; this is endian */ /* load source from storage; this is endian */
pu=(const uInt *)d64->bytes; /* overlay */
if (DECLITEND) { if (DECLITEND) {
sourlo=pu[0]; /* directly load the low int */ sourlo=UBTOUI(d64->bytes ); /* directly load the low int */
sourhi=pu[1]; /* then the high int */ sourhi=UBTOUI(d64->bytes+4); /* then the high int */
} }
else { else {
sourhi=pu[0]; /* directly load the high int */ sourhi=UBTOUI(d64->bytes ); /* directly load the high int */
sourlo=pu[1]; /* then the low int */ sourlo=UBTOUI(d64->bytes+4); /* then the low int */
} }
c=string; /* where result will go */ c=string; /* where result will go */
...@@ -337,7 +336,7 @@ char * decimal64ToString(const decimal64 *d64, char *string){ ...@@ -337,7 +336,7 @@ char * decimal64ToString(const decimal64 *d64, char *string){
if (exp==3) { if (exp==3) {
if (msd==0) { /* infinity */ if (msd==0) { /* infinity */
strcpy(c, "Inf"); strcpy(c, "Inf");
strcpy(c+3, "inity"); strcpy(c+3, "inity");
return string; /* easy */ return string; /* easy */
} }
...@@ -362,7 +361,7 @@ char * decimal64ToString(const decimal64 *d64, char *string){ ...@@ -362,7 +361,7 @@ char * decimal64ToString(const decimal64 *d64, char *string){
/* length. We use fixed-length memcpys because variable-length */ /* length. We use fixed-length memcpys because variable-length */
/* causes a subroutine call in GCC. (These are length 4 for speed */ /* causes a subroutine call in GCC. (These are length 4 for speed */
/* and are safe because the array has an extra terminator byte.) */ /* and are safe because the array has an extra terminator byte.) */
#define dpd2char u=&BIN2CHAR[DPD2BIN[dpd]*4]; \ #define dpd2char u=&BIN2CHAR[DPD2BIN[dpd]*4]; \
if (c!=cstart) {memcpy(c, u+1, 4); c+=3;} \ if (c!=cstart) {memcpy(c, u+1, 4); c+=3;} \
else if (*u) {memcpy(c, u+4-*u, 4); c+=*u;} else if (*u) {memcpy(c, u+4-*u, 4); c+=*u;}
...@@ -379,7 +378,7 @@ char * decimal64ToString(const decimal64 *d64, char *string){ ...@@ -379,7 +378,7 @@ char * decimal64ToString(const decimal64 *d64, char *string){
if (c==cstart) *c++='0'; /* all zeros -- make 0 */ if (c==cstart) *c++='0'; /* all zeros -- make 0 */
if (exp==0) { /* integer or NaN case -- easy */ if (exp==0) { /* integer or NaN case -- easy */
*c='\0'; /* terminate */ *c='\0'; /* terminate */
return string; return string;
} }
...@@ -407,13 +406,13 @@ char * decimal64ToString(const decimal64 *d64, char *string){ ...@@ -407,13 +406,13 @@ char * decimal64ToString(const decimal64 *d64, char *string){
/* finally add the E-part, if needed; it will never be 0, and has */ /* finally add the E-part, if needed; it will never be 0, and has */
/* a maximum length of 3 digits */ /* a maximum length of 3 digits */
if (e!=0) { if (e!=0) {
*c++='E'; /* starts with E */ *c++='E'; /* starts with E */
*c++='+'; /* assume positive */ *c++='+'; /* assume positive */
if (e<0) { if (e<0) {
*(c-1)='-'; /* oops, need '-' */ *(c-1)='-'; /* oops, need '-' */
e=-e; /* uInt, please */ e=-e; /* uInt, please */
} }
u=&BIN2CHAR[e*4]; /* -> length byte */ u=&BIN2CHAR[e*4]; /* -> length byte */
memcpy(c, u+4-*u, 4); /* copy fixed 4 characters [is safe] */ memcpy(c, u+4-*u, 4); /* copy fixed 4 characters [is safe] */
c+=*u; /* bump pointer appropriately */ c+=*u; /* bump pointer appropriately */
} }
...@@ -443,7 +442,7 @@ char * decimal64ToString(const decimal64 *d64, char *string){ ...@@ -443,7 +442,7 @@ char * decimal64ToString(const decimal64 *d64, char *string){
/* the conversion */ /* the conversion */
/* *string is the character string which should contain a valid */ /* *string is the character string which should contain a valid */
/* number (which may be a special value) */ /* number (which may be a special value) */
/* set is the context */ /* set is the context */
/* */ /* */
/* The context is supplied to this routine is used for error handling */ /* The context is supplied to this routine is used for error handling */
/* (setting of status and traps) and for the rounding mode, only. */ /* (setting of status and traps) and for the rounding mode, only. */
...@@ -452,7 +451,7 @@ char * decimal64ToString(const decimal64 *d64, char *string){ ...@@ -452,7 +451,7 @@ char * decimal64ToString(const decimal64 *d64, char *string){
decimal64 * decimal64FromString(decimal64 *result, const char *string, decimal64 * decimal64FromString(decimal64 *result, const char *string,
decContext *set) { decContext *set) {
decContext dc; /* work */ decContext dc; /* work */
decNumber dn; /* .. */ decNumber dn; /* .. */
decContextDefault(&dc, DEC_INIT_DECIMAL64); /* no traps, please */ decContextDefault(&dc, DEC_INIT_DECIMAL64); /* no traps, please */
dc.round=set->round; /* use supplied rounding */ dc.round=set->round; /* use supplied rounding */
...@@ -469,11 +468,11 @@ decimal64 * decimal64FromString(decimal64 *result, const char *string, ...@@ -469,11 +468,11 @@ decimal64 * decimal64FromString(decimal64 *result, const char *string,
/* ------------------------------------------------------------------ */ /* ------------------------------------------------------------------ */
/* decimal64IsCanonical -- test whether encoding is canonical */ /* decimal64IsCanonical -- test whether encoding is canonical */
/* d64 is the source decimal64 */ /* d64 is the source decimal64 */
/* returns 1 if the encoding of d64 is canonical, 0 otherwise */ /* returns 1 if the encoding of d64 is canonical, 0 otherwise */
/* No error is possible. */ /* No error is possible. */
/* ------------------------------------------------------------------ */ /* ------------------------------------------------------------------ */
uint32_t decimal64IsCanonical(const decimal64 *d64) { uInt decimal64IsCanonical(const decimal64 *d64) {
decNumber dn; /* work */ decNumber dn; /* work */
decimal64 canon; /* .. */ decimal64 canon; /* .. */
decContext dc; /* .. */ decContext dc; /* .. */
decContextDefault(&dc, DEC_INIT_DECIMAL64); decContextDefault(&dc, DEC_INIT_DECIMAL64);
...@@ -490,7 +489,7 @@ uint32_t decimal64IsCanonical(const decimal64 *d64) { ...@@ -490,7 +489,7 @@ uint32_t decimal64IsCanonical(const decimal64 *d64) {
/* No error is possible. */ /* No error is possible. */
/* ------------------------------------------------------------------ */ /* ------------------------------------------------------------------ */
decimal64 * decimal64Canonical(decimal64 *result, const decimal64 *d64) { decimal64 * decimal64Canonical(decimal64 *result, const decimal64 *d64) {
decNumber dn; /* work */ decNumber dn; /* work */
decContext dc; /* .. */ decContext dc; /* .. */
decContextDefault(&dc, DEC_INIT_DECIMAL64); decContextDefault(&dc, DEC_INIT_DECIMAL64);
decimal64ToNumber(d64, &dn); decimal64ToNumber(d64, &dn);
...@@ -520,8 +519,8 @@ decimal64 * decimal64Canonical(decimal64 *result, const decimal64 *d64) { ...@@ -520,8 +519,8 @@ decimal64 * decimal64Canonical(decimal64 *result, const decimal64 *d64) {
/* This assumes range has been checked and exponent previously 0; */ /* This assumes range has been checked and exponent previously 0; */
/* type of exponent must be unsigned */ /* type of exponent must be unsigned */
#define decimal64SetExpCon(d, e) { \ #define decimal64SetExpCon(d, e) { \
(d)->bytes[0]|=(uint8_t)((e)>>6); \ (d)->bytes[0]|=(uByte)((e)>>6); \
(d)->bytes[1]|=(uint8_t)(((e)&0x3F)<<2);} (d)->bytes[1]|=(uByte)(((e)&0x3F)<<2);}
/* ------------------------------------------------------------------ */ /* ------------------------------------------------------------------ */
/* decimal64Show -- display a decimal64 in hexadecimal [debug aid] */ /* decimal64Show -- display a decimal64 in hexadecimal [debug aid] */
...@@ -591,12 +590,12 @@ const uInt COMBMSD[32]={0, 1, 2, 3, 4, 5, 6, 7, ...@@ -591,12 +590,12 @@ const uInt COMBMSD[32]={0, 1, 2, 3, 4, 5, 6, 7,
/* ------------------------------------------------------------------ */ /* ------------------------------------------------------------------ */
/* decDigitsToDPD -- pack coefficient into DPD form */ /* decDigitsToDPD -- pack coefficient into DPD form */
/* */ /* */
/* dn is the source number (assumed valid, max DECMAX754 digits) */ /* dn is the source number (assumed valid, max DECMAX754 digits) */
/* targ is 1, 2, or 4-element uInt array, which the caller must */ /* targ is 1, 2, or 4-element uInt array, which the caller must */
/* have cleared to zeros */ /* have cleared to zeros */
/* shift is the number of 0 digits to add on the right (normally 0) */ /* shift is the number of 0 digits to add on the right (normally 0) */
/* */ /* */
/* The coefficient must be known small enough to fit. The full */ /* The coefficient must be known small enough to fit. The full */
/* coefficient is copied, including the leading 'odd' digit. This */ /* coefficient is copied, including the leading 'odd' digit. This */
/* digit is retrieved and packed into the combination field by the */ /* digit is retrieved and packed into the combination field by the */
/* caller. */ /* caller. */
...@@ -625,7 +624,7 @@ void decDigitsToDPD(const decNumber *dn, uInt *targ, Int shift) { ...@@ -625,7 +624,7 @@ void decDigitsToDPD(const decNumber *dn, uInt *targ, Int shift) {
uInt dpd; /* densely packed decimal value */ uInt dpd; /* densely packed decimal value */
uInt bin; /* binary value 0-999 */ uInt bin; /* binary value 0-999 */
uInt *uout=targ; /* -> current output uInt */ uInt *uout=targ; /* -> current output uInt */
uInt uoff=0; /* -> current output offset [from right] */ uInt uoff=0; /* -> current output offset [from right] */
const Unit *inu=dn->lsu; /* -> current input unit */ const Unit *inu=dn->lsu; /* -> current input unit */
Unit uar[DECMAXUNITS]; /* working copy of units, iff shifted */ Unit uar[DECMAXUNITS]; /* working copy of units, iff shifted */
#if DECDPUN!=3 /* not fast path */ #if DECDPUN!=3 /* not fast path */
...@@ -636,7 +635,7 @@ void decDigitsToDPD(const decNumber *dn, uInt *targ, Int shift) { ...@@ -636,7 +635,7 @@ void decDigitsToDPD(const decNumber *dn, uInt *targ, Int shift) {
/* shift the units array to the left by pad digits and copy */ /* shift the units array to the left by pad digits and copy */
/* [this code is a special case of decShiftToMost, which could */ /* [this code is a special case of decShiftToMost, which could */
/* be used instead if exposed and the array were copied first] */ /* be used instead if exposed and the array were copied first] */
const Unit *source; /* .. */ const Unit *source; /* .. */
Unit *target, *first; /* .. */ Unit *target, *first; /* .. */
uInt next=0; /* work */ uInt next=0; /* work */
...@@ -681,12 +680,12 @@ void decDigitsToDPD(const decNumber *dn, uInt *targ, Int shift) { ...@@ -681,12 +680,12 @@ void decDigitsToDPD(const decNumber *dn, uInt *targ, Int shift) {
for(n=0; digits>0; n++) { /* each output bunch */ for(n=0; digits>0; n++) { /* each output bunch */
#if DECDPUN==3 /* fast path, 3-at-a-time */ #if DECDPUN==3 /* fast path, 3-at-a-time */
bin=*inu; /* 3 digits ready for convert */ bin=*inu; /* 3 digits ready for convert */
digits-=3; /* [may go negative] */ digits-=3; /* [may go negative] */
inu++; /* may need another */ inu++; /* may need another */
#else /* must collect digit-by-digit */ #else /* must collect digit-by-digit */
Unit dig; /* current digit */ Unit dig; /* current digit */
Int j; /* digit-in-declet count */ Int j; /* digit-in-declet count */
for (j=0; j<3; j++) { for (j=0; j<3; j++) {
#if DECDPUN<=4 #if DECDPUN<=4
...@@ -698,7 +697,7 @@ void decDigitsToDPD(const decNumber *dn, uInt *targ, Int shift) { ...@@ -698,7 +697,7 @@ void decDigitsToDPD(const decNumber *dn, uInt *targ, Int shift) {
in=in/10; in=in/10;
#endif #endif
if (j==0) bin=dig; if (j==0) bin=dig;
else if (j==1) bin+=X10(dig); else if (j==1) bin+=X10(dig);
else /* j==2 */ bin+=X100(dig); else /* j==2 */ bin+=X100(dig);
digits--; digits--;
if (digits==0) break; /* [also protects *inu below] */ if (digits==0) break; /* [also protects *inu below] */
...@@ -750,12 +749,12 @@ void decDigitsFromDPD(decNumber *dn, const uInt *sour, Int declets) { ...@@ -750,12 +749,12 @@ void decDigitsFromDPD(decNumber *dn, const uInt *sour, Int declets) {
Int n; /* counter */ Int n; /* counter */
Unit *uout=dn->lsu; /* -> current output unit */ Unit *uout=dn->lsu; /* -> current output unit */
Unit *last=uout; /* will be unit containing msd */ Unit *last=uout; /* will be unit containing msd */
const uInt *uin=sour; /* -> current input uInt */ const uInt *uin=sour; /* -> current input uInt */
uInt uoff=0; /* -> current input offset [from right] */ uInt uoff=0; /* -> current input offset [from right] */
#if DECDPUN!=3 #if DECDPUN!=3
uInt bcd; /* BCD result */ uInt bcd; /* BCD result */
uInt nibble; /* work */ uInt nibble; /* work */
Unit out=0; /* accumulator */ Unit out=0; /* accumulator */
Int cut=0; /* power of ten in current unit */ Int cut=0; /* power of ten in current unit */
#endif #endif
...@@ -772,7 +771,7 @@ void decDigitsFromDPD(decNumber *dn, const uInt *sour, Int declets) { ...@@ -772,7 +771,7 @@ void decDigitsFromDPD(decNumber *dn, const uInt *sour, Int declets) {
uoff-=32; uoff-=32;
dpd|=*uin<<(10-uoff); /* get waiting bits */ dpd|=*uin<<(10-uoff); /* get waiting bits */
} }
dpd&=0x3ff; /* clear uninteresting bits */ dpd&=0x3ff; /* clear uninteresting bits */
#if DECDPUN==3 #if DECDPUN==3
if (dpd==0) *uout=0; if (dpd==0) *uout=0;
...@@ -822,9 +821,9 @@ void decDigitsFromDPD(decNumber *dn, const uInt *sour, Int declets) { ...@@ -822,9 +821,9 @@ void decDigitsFromDPD(decNumber *dn, const uInt *sour, Int declets) {
cut++; cut++;
if (cut==DECDPUN) {*uout=out; if (out) {last=uout; out=0;} uout++; cut=0;} if (cut==DECDPUN) {*uout=out; if (out) {last=uout; out=0;} uout++; cut=0;}
} /* n */ } /* n */
if (cut!=0) { /* some more left over */ if (cut!=0) { /* some more left over */
*uout=out; /* write out final unit */ *uout=out; /* write out final unit */
if (out) last=uout; /* and note if non-zero */ if (out) last=uout; /* and note if non-zero */
} }
#endif #endif
...@@ -834,14 +833,14 @@ void decDigitsFromDPD(decNumber *dn, const uInt *sour, Int declets) { ...@@ -834,14 +833,14 @@ void decDigitsFromDPD(decNumber *dn, const uInt *sour, Int declets) {
dn->digits=(last-dn->lsu)*DECDPUN+1; /* floor of digits, plus */ dn->digits=(last-dn->lsu)*DECDPUN+1; /* floor of digits, plus */
/* must be at least 1 digit */ /* must be at least 1 digit */
#if DECDPUN>1 #if DECDPUN>1
if (*last<10) return; /* common odd digit or 0 */ if (*last<10) return; /* common odd digit or 0 */
dn->digits++; /* must be 2 at least */ dn->digits++; /* must be 2 at least */
#if DECDPUN>2 #if DECDPUN>2
if (*last<100) return; /* 10-99 */ if (*last<100) return; /* 10-99 */
dn->digits++; /* must be 3 at least */ dn->digits++; /* must be 3 at least */
#if DECDPUN>3 #if DECDPUN>3
if (*last<1000) return; /* 100-999 */ if (*last<1000) return; /* 100-999 */
dn->digits++; /* must be 4 at least */ dn->digits++; /* must be 4 at least */
#if DECDPUN>4 #if DECDPUN>4
for (pow=&DECPOWERS[4]; *last>=*pow; pow++) dn->digits++; for (pow=&DECPOWERS[4]; *last>=*pow; pow++) dn->digits++;
#endif #endif
......
...@@ -35,7 +35,7 @@ ...@@ -35,7 +35,7 @@
#if !defined(DECIMAL64) #if !defined(DECIMAL64)
#define DECIMAL64 #define DECIMAL64
#define DEC64NAME "decimal64" /* Short name */ #define DEC64NAME "decimal64" /* Short name */
#define DEC64FULLNAME "Decimal 64-bit Number" /* Verbose name */ #define DEC64FULLNAME "Decimal 64-bit Number" /* Verbose name */
#define DEC64AUTHOR "Mike Cowlishaw" /* Who to blame */ #define DEC64AUTHOR "Mike Cowlishaw" /* Who to blame */
...@@ -47,7 +47,7 @@ ...@@ -47,7 +47,7 @@
#define DECIMAL64_Bias 398 /* bias for the exponent */ #define DECIMAL64_Bias 398 /* bias for the exponent */
#define DECIMAL64_String 24 /* maximum string length, +1 */ #define DECIMAL64_String 24 /* maximum string length, +1 */
#define DECIMAL64_EconL 8 /* exp. continuation length */ #define DECIMAL64_EconL 8 /* exp. continuation length */
/* highest biased exponent (Elimit-1) */ /* highest biased exponent (Elimit-1) */
#define DECIMAL64_Ehigh (DECIMAL64_Emax+DECIMAL64_Bias-DECIMAL64_Pmax+1) #define DECIMAL64_Ehigh (DECIMAL64_Emax+DECIMAL64_Bias-DECIMAL64_Pmax+1)
/* check enough digits, if pre-defined */ /* check enough digits, if pre-defined */
...@@ -73,18 +73,18 @@ ...@@ -73,18 +73,18 @@
/* special values [top byte excluding sign bit; last two bits are */ /* special values [top byte excluding sign bit; last two bits are */
/* don't-care for Infinity on input, last bit don't-care for NaN] */ /* don't-care for Infinity on input, last bit don't-care for NaN] */
#if !defined(DECIMAL_NaN) #if !defined(DECIMAL_NaN)
#define DECIMAL_NaN 0x7c /* 0 11111 00 NaN */ #define DECIMAL_NaN 0x7c /* 0 11111 00 NaN */
#define DECIMAL_sNaN 0x7e /* 0 11111 10 sNaN */ #define DECIMAL_sNaN 0x7e /* 0 11111 10 sNaN */
#define DECIMAL_Inf 0x78 /* 0 11110 00 Infinity */ #define DECIMAL_Inf 0x78 /* 0 11110 00 Infinity */
#endif #endif
/* ---------------------------------------------------------------- */ /* ---------------------------------------------------------------- */
/* Routines */ /* Routines */
/* ---------------------------------------------------------------- */ /* ---------------------------------------------------------------- */
#include "decimal64Symbols.h" #include "decimal64Symbols.h"
/* String conversions */ /* String conversions */
decimal64 * decimal64FromString(decimal64 *, const char *, decContext *); decimal64 * decimal64FromString(decimal64 *, const char *, decContext *);
char * decimal64ToString(const decimal64 *, char *); char * decimal64ToString(const decimal64 *, char *);
char * decimal64ToEngString(const decimal64 *, char *); char * decimal64ToEngString(const decimal64 *, char *);
...@@ -94,7 +94,7 @@ ...@@ -94,7 +94,7 @@
decContext *); decContext *);
decNumber * decimal64ToNumber(const decimal64 *, decNumber *); decNumber * decimal64ToNumber(const decimal64 *, decNumber *);
/* Format-dependent utilities */ /* Format-dependent utilities */
uint32_t decimal64IsCanonical(const decimal64 *); uint32_t decimal64IsCanonical(const decimal64 *);
decimal64 * decimal64Canonical(decimal64 *, const decimal64 *); decimal64 * decimal64Canonical(decimal64 *, const decimal64 *);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment