15796c8dcSSimon Schubert /* Decimal 128-bit format module for the decNumber C Library.
2*ef5ccd6cSJohn Marino Copyright (C) 2005-2013 Free Software Foundation, Inc.
35796c8dcSSimon Schubert Contributed by IBM Corporation. Author Mike Cowlishaw.
45796c8dcSSimon Schubert
55796c8dcSSimon Schubert This file is part of GCC.
65796c8dcSSimon Schubert
75796c8dcSSimon Schubert GCC is free software; you can redistribute it and/or modify it under
85796c8dcSSimon Schubert the terms of the GNU General Public License as published by the Free
95796c8dcSSimon Schubert Software Foundation; either version 3, or (at your option) any later
105796c8dcSSimon Schubert version.
115796c8dcSSimon Schubert
125796c8dcSSimon Schubert GCC is distributed in the hope that it will be useful, but WITHOUT ANY
135796c8dcSSimon Schubert WARRANTY; without even the implied warranty of MERCHANTABILITY or
145796c8dcSSimon Schubert FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
155796c8dcSSimon Schubert for more details.
165796c8dcSSimon Schubert
175796c8dcSSimon Schubert Under Section 7 of GPL version 3, you are granted additional
185796c8dcSSimon Schubert permissions described in the GCC Runtime Library Exception, version
195796c8dcSSimon Schubert 3.1, as published by the Free Software Foundation.
205796c8dcSSimon Schubert
215796c8dcSSimon Schubert You should have received a copy of the GNU General Public License and
225796c8dcSSimon Schubert a copy of the GCC Runtime Library Exception along with this program;
235796c8dcSSimon Schubert see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
245796c8dcSSimon Schubert <http://www.gnu.org/licenses/>. */
255796c8dcSSimon Schubert
265796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
275796c8dcSSimon Schubert /* Decimal 128-bit format module */
285796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
295796c8dcSSimon Schubert /* This module comprises the routines for decimal128 format numbers. */
305796c8dcSSimon Schubert /* Conversions are supplied to and from decNumber and String. */
315796c8dcSSimon Schubert /* */
325796c8dcSSimon Schubert /* This is used when decNumber provides operations, either for all */
335796c8dcSSimon Schubert /* operations or as a proxy between decNumber and decSingle. */
345796c8dcSSimon Schubert /* */
355796c8dcSSimon Schubert /* Error handling is the same as decNumber (qv.). */
365796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
375796c8dcSSimon Schubert #include <string.h> /* [for memset/memcpy] */
385796c8dcSSimon Schubert #include <stdio.h> /* [for printf] */
395796c8dcSSimon Schubert
405796c8dcSSimon Schubert #include "dconfig.h" /* GCC definitions */
415796c8dcSSimon Schubert #define DECNUMDIGITS 34 /* make decNumbers with space for 34 */
425796c8dcSSimon Schubert #include "decNumber.h" /* base number library */
435796c8dcSSimon Schubert #include "decNumberLocal.h" /* decNumber local types, etc. */
445796c8dcSSimon Schubert #include "decimal128.h" /* our primary include */
455796c8dcSSimon Schubert
465796c8dcSSimon Schubert /* Utility routines and tables [in decimal64.c] */
475796c8dcSSimon Schubert extern const uInt COMBEXP[32], COMBMSD[32];
485796c8dcSSimon Schubert extern const uShort DPD2BIN[1024];
495796c8dcSSimon Schubert extern const uShort BIN2DPD[1000]; /* [not used] */
505796c8dcSSimon Schubert extern const uByte BIN2CHAR[4001];
515796c8dcSSimon Schubert
525796c8dcSSimon Schubert extern void decDigitsFromDPD(decNumber *, const uInt *, Int);
535796c8dcSSimon Schubert extern void decDigitsToDPD(const decNumber *, uInt *, Int);
545796c8dcSSimon Schubert
555796c8dcSSimon Schubert #if DECTRACE || DECCHECK
565796c8dcSSimon Schubert void decimal128Show(const decimal128 *); /* for debug */
575796c8dcSSimon Schubert extern void decNumberShow(const decNumber *); /* .. */
585796c8dcSSimon Schubert #endif
595796c8dcSSimon Schubert
605796c8dcSSimon Schubert /* Useful macro */
615796c8dcSSimon Schubert /* Clear a structure (e.g., a decNumber) */
625796c8dcSSimon Schubert #define DEC_clear(d) memset(d, 0, sizeof(*d))
635796c8dcSSimon Schubert
645796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
655796c8dcSSimon Schubert /* decimal128FromNumber -- convert decNumber to decimal128 */
665796c8dcSSimon Schubert /* */
675796c8dcSSimon Schubert /* ds is the target decimal128 */
685796c8dcSSimon Schubert /* dn is the source number (assumed valid) */
695796c8dcSSimon Schubert /* set is the context, used only for reporting errors */
705796c8dcSSimon Schubert /* */
715796c8dcSSimon Schubert /* The set argument is used only for status reporting and for the */
725796c8dcSSimon Schubert /* rounding mode (used if the coefficient is more than DECIMAL128_Pmax*/
735796c8dcSSimon Schubert /* digits or an overflow is detected). If the exponent is out of the */
745796c8dcSSimon Schubert /* valid range then Overflow or Underflow will be raised. */
755796c8dcSSimon Schubert /* After Underflow a subnormal result is possible. */
765796c8dcSSimon Schubert /* */
775796c8dcSSimon Schubert /* DEC_Clamped is set if the number has to be 'folded down' to fit, */
785796c8dcSSimon Schubert /* by reducing its exponent and multiplying the coefficient by a */
795796c8dcSSimon Schubert /* power of ten, or if the exponent on a zero had to be clamped. */
805796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
decimal128FromNumber(decimal128 * d128,const decNumber * dn,decContext * set)815796c8dcSSimon Schubert decimal128 * decimal128FromNumber(decimal128 *d128, const decNumber *dn,
825796c8dcSSimon Schubert decContext *set) {
835796c8dcSSimon Schubert uInt status=0; /* status accumulator */
845796c8dcSSimon Schubert Int ae; /* adjusted exponent */
855796c8dcSSimon Schubert decNumber dw; /* work */
865796c8dcSSimon Schubert decContext dc; /* .. */
875796c8dcSSimon Schubert uInt comb, exp; /* .. */
885796c8dcSSimon Schubert uInt uiwork; /* for macros */
895796c8dcSSimon Schubert uInt targar[4]={0,0,0,0}; /* target 128-bit */
905796c8dcSSimon Schubert #define targhi targar[3] /* name the word with the sign */
915796c8dcSSimon Schubert #define targmh targar[2] /* name the words */
925796c8dcSSimon Schubert #define targml targar[1] /* .. */
935796c8dcSSimon Schubert #define targlo targar[0] /* .. */
945796c8dcSSimon Schubert
955796c8dcSSimon Schubert /* If the number has too many digits, or the exponent could be */
965796c8dcSSimon Schubert /* out of range then reduce the number under the appropriate */
975796c8dcSSimon Schubert /* constraints. This could push the number to Infinity or zero, */
985796c8dcSSimon Schubert /* so this check and rounding must be done before generating the */
995796c8dcSSimon Schubert /* decimal128] */
1005796c8dcSSimon Schubert ae=dn->exponent+dn->digits-1; /* [0 if special] */
1015796c8dcSSimon Schubert if (dn->digits>DECIMAL128_Pmax /* too many digits */
1025796c8dcSSimon Schubert || ae>DECIMAL128_Emax /* likely overflow */
1035796c8dcSSimon Schubert || ae<DECIMAL128_Emin) { /* likely underflow */
1045796c8dcSSimon Schubert decContextDefault(&dc, DEC_INIT_DECIMAL128); /* [no traps] */
1055796c8dcSSimon Schubert dc.round=set->round; /* use supplied rounding */
1065796c8dcSSimon Schubert decNumberPlus(&dw, dn, &dc); /* (round and check) */
1075796c8dcSSimon Schubert /* [this changes -0 to 0, so enforce the sign...] */
1085796c8dcSSimon Schubert dw.bits|=dn->bits&DECNEG;
1095796c8dcSSimon Schubert status=dc.status; /* save status */
1105796c8dcSSimon Schubert dn=&dw; /* use the work number */
1115796c8dcSSimon Schubert } /* maybe out of range */
1125796c8dcSSimon Schubert
1135796c8dcSSimon Schubert if (dn->bits&DECSPECIAL) { /* a special value */
1145796c8dcSSimon Schubert if (dn->bits&DECINF) targhi=DECIMAL_Inf<<24;
1155796c8dcSSimon Schubert else { /* sNaN or qNaN */
1165796c8dcSSimon Schubert if ((*dn->lsu!=0 || dn->digits>1) /* non-zero coefficient */
1175796c8dcSSimon Schubert && (dn->digits<DECIMAL128_Pmax)) { /* coefficient fits */
1185796c8dcSSimon Schubert decDigitsToDPD(dn, targar, 0);
1195796c8dcSSimon Schubert }
1205796c8dcSSimon Schubert if (dn->bits&DECNAN) targhi|=DECIMAL_NaN<<24;
1215796c8dcSSimon Schubert else targhi|=DECIMAL_sNaN<<24;
1225796c8dcSSimon Schubert } /* a NaN */
1235796c8dcSSimon Schubert } /* special */
1245796c8dcSSimon Schubert
1255796c8dcSSimon Schubert else { /* is finite */
1265796c8dcSSimon Schubert if (decNumberIsZero(dn)) { /* is a zero */
1275796c8dcSSimon Schubert /* set and clamp exponent */
1285796c8dcSSimon Schubert if (dn->exponent<-DECIMAL128_Bias) {
1295796c8dcSSimon Schubert exp=0; /* low clamp */
1305796c8dcSSimon Schubert status|=DEC_Clamped;
1315796c8dcSSimon Schubert }
1325796c8dcSSimon Schubert else {
1335796c8dcSSimon Schubert exp=dn->exponent+DECIMAL128_Bias; /* bias exponent */
1345796c8dcSSimon Schubert if (exp>DECIMAL128_Ehigh) { /* top clamp */
1355796c8dcSSimon Schubert exp=DECIMAL128_Ehigh;
1365796c8dcSSimon Schubert status|=DEC_Clamped;
1375796c8dcSSimon Schubert }
1385796c8dcSSimon Schubert }
1395796c8dcSSimon Schubert comb=(exp>>9) & 0x18; /* msd=0, exp top 2 bits .. */
1405796c8dcSSimon Schubert }
1415796c8dcSSimon Schubert else { /* non-zero finite number */
1425796c8dcSSimon Schubert uInt msd; /* work */
1435796c8dcSSimon Schubert Int pad=0; /* coefficient pad digits */
1445796c8dcSSimon Schubert
1455796c8dcSSimon Schubert /* the dn is known to fit, but it may need to be padded */
1465796c8dcSSimon Schubert exp=(uInt)(dn->exponent+DECIMAL128_Bias); /* bias exponent */
1475796c8dcSSimon Schubert if (exp>DECIMAL128_Ehigh) { /* fold-down case */
1485796c8dcSSimon Schubert pad=exp-DECIMAL128_Ehigh;
1495796c8dcSSimon Schubert exp=DECIMAL128_Ehigh; /* [to maximum] */
1505796c8dcSSimon Schubert status|=DEC_Clamped;
1515796c8dcSSimon Schubert }
1525796c8dcSSimon Schubert
1535796c8dcSSimon Schubert /* [fastpath for common case is not a win, here] */
1545796c8dcSSimon Schubert decDigitsToDPD(dn, targar, pad);
1555796c8dcSSimon Schubert /* save and clear the top digit */
1565796c8dcSSimon Schubert msd=targhi>>14;
1575796c8dcSSimon Schubert targhi&=0x00003fff;
1585796c8dcSSimon Schubert
1595796c8dcSSimon Schubert /* create the combination field */
1605796c8dcSSimon Schubert if (msd>=8) comb=0x18 | ((exp>>11) & 0x06) | (msd & 0x01);
1615796c8dcSSimon Schubert else comb=((exp>>9) & 0x18) | msd;
1625796c8dcSSimon Schubert }
1635796c8dcSSimon Schubert targhi|=comb<<26; /* add combination field .. */
1645796c8dcSSimon Schubert targhi|=(exp&0xfff)<<14; /* .. and exponent continuation */
1655796c8dcSSimon Schubert } /* finite */
1665796c8dcSSimon Schubert
1675796c8dcSSimon Schubert if (dn->bits&DECNEG) targhi|=0x80000000; /* add sign bit */
1685796c8dcSSimon Schubert
1695796c8dcSSimon Schubert /* now write to storage; this is endian */
1705796c8dcSSimon Schubert if (DECLITEND) {
1715796c8dcSSimon Schubert /* lo -> hi */
1725796c8dcSSimon Schubert UBFROMUI(d128->bytes, targlo);
1735796c8dcSSimon Schubert UBFROMUI(d128->bytes+4, targml);
1745796c8dcSSimon Schubert UBFROMUI(d128->bytes+8, targmh);
1755796c8dcSSimon Schubert UBFROMUI(d128->bytes+12, targhi);
1765796c8dcSSimon Schubert }
1775796c8dcSSimon Schubert else {
1785796c8dcSSimon Schubert /* hi -> lo */
1795796c8dcSSimon Schubert UBFROMUI(d128->bytes, targhi);
1805796c8dcSSimon Schubert UBFROMUI(d128->bytes+4, targmh);
1815796c8dcSSimon Schubert UBFROMUI(d128->bytes+8, targml);
1825796c8dcSSimon Schubert UBFROMUI(d128->bytes+12, targlo);
1835796c8dcSSimon Schubert }
1845796c8dcSSimon Schubert
1855796c8dcSSimon Schubert if (status!=0) decContextSetStatus(set, status); /* pass on status */
1865796c8dcSSimon Schubert /* decimal128Show(d128); */
1875796c8dcSSimon Schubert return d128;
1885796c8dcSSimon Schubert } /* decimal128FromNumber */
1895796c8dcSSimon Schubert
1905796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
1915796c8dcSSimon Schubert /* decimal128ToNumber -- convert decimal128 to decNumber */
1925796c8dcSSimon Schubert /* d128 is the source decimal128 */
1935796c8dcSSimon Schubert /* dn is the target number, with appropriate space */
1945796c8dcSSimon Schubert /* No error is possible. */
1955796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
decimal128ToNumber(const decimal128 * d128,decNumber * dn)1965796c8dcSSimon Schubert decNumber * decimal128ToNumber(const decimal128 *d128, decNumber *dn) {
1975796c8dcSSimon Schubert uInt msd; /* coefficient MSD */
1985796c8dcSSimon Schubert uInt exp; /* exponent top two bits */
1995796c8dcSSimon Schubert uInt comb; /* combination field */
2005796c8dcSSimon Schubert Int need; /* work */
2015796c8dcSSimon Schubert uInt uiwork; /* for macros */
2025796c8dcSSimon Schubert uInt sourar[4]; /* source 128-bit */
2035796c8dcSSimon Schubert #define sourhi sourar[3] /* name the word with the sign */
2045796c8dcSSimon Schubert #define sourmh sourar[2] /* and the mid-high word */
2055796c8dcSSimon Schubert #define sourml sourar[1] /* and the mod-low word */
2065796c8dcSSimon Schubert #define sourlo sourar[0] /* and the lowest word */
2075796c8dcSSimon Schubert
2085796c8dcSSimon Schubert /* load source from storage; this is endian */
2095796c8dcSSimon Schubert if (DECLITEND) {
2105796c8dcSSimon Schubert sourlo=UBTOUI(d128->bytes ); /* directly load the low int */
2115796c8dcSSimon Schubert sourml=UBTOUI(d128->bytes+4 ); /* then the mid-low */
2125796c8dcSSimon Schubert sourmh=UBTOUI(d128->bytes+8 ); /* then the mid-high */
2135796c8dcSSimon Schubert sourhi=UBTOUI(d128->bytes+12); /* then the high int */
2145796c8dcSSimon Schubert }
2155796c8dcSSimon Schubert else {
2165796c8dcSSimon Schubert sourhi=UBTOUI(d128->bytes ); /* directly load the high int */
2175796c8dcSSimon Schubert sourmh=UBTOUI(d128->bytes+4 ); /* then the mid-high */
2185796c8dcSSimon Schubert sourml=UBTOUI(d128->bytes+8 ); /* then the mid-low */
2195796c8dcSSimon Schubert sourlo=UBTOUI(d128->bytes+12); /* then the low int */
2205796c8dcSSimon Schubert }
2215796c8dcSSimon Schubert
2225796c8dcSSimon Schubert comb=(sourhi>>26)&0x1f; /* combination field */
2235796c8dcSSimon Schubert
2245796c8dcSSimon Schubert decNumberZero(dn); /* clean number */
2255796c8dcSSimon Schubert if (sourhi&0x80000000) dn->bits=DECNEG; /* set sign if negative */
2265796c8dcSSimon Schubert
2275796c8dcSSimon Schubert msd=COMBMSD[comb]; /* decode the combination field */
2285796c8dcSSimon Schubert exp=COMBEXP[comb]; /* .. */
2295796c8dcSSimon Schubert
2305796c8dcSSimon Schubert if (exp==3) { /* is a special */
2315796c8dcSSimon Schubert if (msd==0) {
2325796c8dcSSimon Schubert dn->bits|=DECINF;
2335796c8dcSSimon Schubert return dn; /* no coefficient needed */
2345796c8dcSSimon Schubert }
2355796c8dcSSimon Schubert else if (sourhi&0x02000000) dn->bits|=DECSNAN;
2365796c8dcSSimon Schubert else dn->bits|=DECNAN;
2375796c8dcSSimon Schubert msd=0; /* no top digit */
2385796c8dcSSimon Schubert }
2395796c8dcSSimon Schubert else { /* is a finite number */
2405796c8dcSSimon Schubert dn->exponent=(exp<<12)+((sourhi>>14)&0xfff)-DECIMAL128_Bias; /* unbiased */
2415796c8dcSSimon Schubert }
2425796c8dcSSimon Schubert
2435796c8dcSSimon Schubert /* get the coefficient */
2445796c8dcSSimon Schubert sourhi&=0x00003fff; /* clean coefficient continuation */
2455796c8dcSSimon Schubert if (msd) { /* non-zero msd */
2465796c8dcSSimon Schubert sourhi|=msd<<14; /* prefix to coefficient */
2475796c8dcSSimon Schubert need=12; /* process 12 declets */
2485796c8dcSSimon Schubert }
2495796c8dcSSimon Schubert else { /* msd=0 */
2505796c8dcSSimon Schubert if (sourhi) need=11; /* declets to process */
2515796c8dcSSimon Schubert else if (sourmh) need=10;
2525796c8dcSSimon Schubert else if (sourml) need=7;
2535796c8dcSSimon Schubert else if (sourlo) need=4;
2545796c8dcSSimon Schubert else return dn; /* easy: coefficient is 0 */
2555796c8dcSSimon Schubert } /*msd=0 */
2565796c8dcSSimon Schubert
2575796c8dcSSimon Schubert decDigitsFromDPD(dn, sourar, need); /* process declets */
2585796c8dcSSimon Schubert /* decNumberShow(dn); */
2595796c8dcSSimon Schubert return dn;
2605796c8dcSSimon Schubert } /* decimal128ToNumber */
2615796c8dcSSimon Schubert
2625796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
2635796c8dcSSimon Schubert /* to-scientific-string -- conversion to numeric string */
2645796c8dcSSimon Schubert /* to-engineering-string -- conversion to numeric string */
2655796c8dcSSimon Schubert /* */
2665796c8dcSSimon Schubert /* decimal128ToString(d128, string); */
2675796c8dcSSimon Schubert /* decimal128ToEngString(d128, string); */
2685796c8dcSSimon Schubert /* */
2695796c8dcSSimon Schubert /* d128 is the decimal128 format number to convert */
2705796c8dcSSimon Schubert /* string is the string where the result will be laid out */
2715796c8dcSSimon Schubert /* */
2725796c8dcSSimon Schubert /* string must be at least 24 characters */
2735796c8dcSSimon Schubert /* */
2745796c8dcSSimon Schubert /* No error is possible, and no status can be set. */
2755796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
decimal128ToEngString(const decimal128 * d128,char * string)2765796c8dcSSimon Schubert char * decimal128ToEngString(const decimal128 *d128, char *string){
2775796c8dcSSimon Schubert decNumber dn; /* work */
2785796c8dcSSimon Schubert decimal128ToNumber(d128, &dn);
2795796c8dcSSimon Schubert decNumberToEngString(&dn, string);
2805796c8dcSSimon Schubert return string;
2815796c8dcSSimon Schubert } /* decimal128ToEngString */
2825796c8dcSSimon Schubert
decimal128ToString(const decimal128 * d128,char * string)2835796c8dcSSimon Schubert char * decimal128ToString(const decimal128 *d128, char *string){
2845796c8dcSSimon Schubert uInt msd; /* coefficient MSD */
2855796c8dcSSimon Schubert Int exp; /* exponent top two bits or full */
2865796c8dcSSimon Schubert uInt comb; /* combination field */
2875796c8dcSSimon Schubert char *cstart; /* coefficient start */
2885796c8dcSSimon Schubert char *c; /* output pointer in string */
2895796c8dcSSimon Schubert const uByte *u; /* work */
2905796c8dcSSimon Schubert char *s, *t; /* .. (source, target) */
2915796c8dcSSimon Schubert Int dpd; /* .. */
2925796c8dcSSimon Schubert Int pre, e; /* .. */
2935796c8dcSSimon Schubert uInt uiwork; /* for macros */
2945796c8dcSSimon Schubert
2955796c8dcSSimon Schubert uInt sourar[4]; /* source 128-bit */
2965796c8dcSSimon Schubert #define sourhi sourar[3] /* name the word with the sign */
2975796c8dcSSimon Schubert #define sourmh sourar[2] /* and the mid-high word */
2985796c8dcSSimon Schubert #define sourml sourar[1] /* and the mod-low word */
2995796c8dcSSimon Schubert #define sourlo sourar[0] /* and the lowest word */
3005796c8dcSSimon Schubert
3015796c8dcSSimon Schubert /* load source from storage; this is endian */
3025796c8dcSSimon Schubert if (DECLITEND) {
3035796c8dcSSimon Schubert sourlo=UBTOUI(d128->bytes ); /* directly load the low int */
3045796c8dcSSimon Schubert sourml=UBTOUI(d128->bytes+4 ); /* then the mid-low */
3055796c8dcSSimon Schubert sourmh=UBTOUI(d128->bytes+8 ); /* then the mid-high */
3065796c8dcSSimon Schubert sourhi=UBTOUI(d128->bytes+12); /* then the high int */
3075796c8dcSSimon Schubert }
3085796c8dcSSimon Schubert else {
3095796c8dcSSimon Schubert sourhi=UBTOUI(d128->bytes ); /* directly load the high int */
3105796c8dcSSimon Schubert sourmh=UBTOUI(d128->bytes+4 ); /* then the mid-high */
3115796c8dcSSimon Schubert sourml=UBTOUI(d128->bytes+8 ); /* then the mid-low */
3125796c8dcSSimon Schubert sourlo=UBTOUI(d128->bytes+12); /* then the low int */
3135796c8dcSSimon Schubert }
3145796c8dcSSimon Schubert
3155796c8dcSSimon Schubert c=string; /* where result will go */
3165796c8dcSSimon Schubert if (((Int)sourhi)<0) *c++='-'; /* handle sign */
3175796c8dcSSimon Schubert
3185796c8dcSSimon Schubert comb=(sourhi>>26)&0x1f; /* combination field */
3195796c8dcSSimon Schubert msd=COMBMSD[comb]; /* decode the combination field */
3205796c8dcSSimon Schubert exp=COMBEXP[comb]; /* .. */
3215796c8dcSSimon Schubert
3225796c8dcSSimon Schubert if (exp==3) {
3235796c8dcSSimon Schubert if (msd==0) { /* infinity */
3245796c8dcSSimon Schubert strcpy(c, "Inf");
3255796c8dcSSimon Schubert strcpy(c+3, "inity");
3265796c8dcSSimon Schubert return string; /* easy */
3275796c8dcSSimon Schubert }
3285796c8dcSSimon Schubert if (sourhi&0x02000000) *c++='s'; /* sNaN */
3295796c8dcSSimon Schubert strcpy(c, "NaN"); /* complete word */
3305796c8dcSSimon Schubert c+=3; /* step past */
3315796c8dcSSimon Schubert if (sourlo==0 && sourml==0 && sourmh==0
3325796c8dcSSimon Schubert && (sourhi&0x0003ffff)==0) return string; /* zero payload */
3335796c8dcSSimon Schubert /* otherwise drop through to add integer; set correct exp */
3345796c8dcSSimon Schubert exp=0; msd=0; /* setup for following code */
3355796c8dcSSimon Schubert }
3365796c8dcSSimon Schubert else exp=(exp<<12)+((sourhi>>14)&0xfff)-DECIMAL128_Bias; /* unbiased */
3375796c8dcSSimon Schubert
3385796c8dcSSimon Schubert /* convert 34 digits of significand to characters */
3395796c8dcSSimon Schubert cstart=c; /* save start of coefficient */
3405796c8dcSSimon Schubert if (msd) *c++='0'+(char)msd; /* non-zero most significant digit */
3415796c8dcSSimon Schubert
3425796c8dcSSimon Schubert /* Now decode the declets. After extracting each one, it is */
3435796c8dcSSimon Schubert /* decoded to binary and then to a 4-char sequence by table lookup; */
3445796c8dcSSimon Schubert /* the 4-chars are a 1-char length (significant digits, except 000 */
3455796c8dcSSimon Schubert /* has length 0). This allows us to left-align the first declet */
3465796c8dcSSimon Schubert /* with non-zero content, then remaining ones are full 3-char */
3475796c8dcSSimon Schubert /* length. We use fixed-length memcpys because variable-length */
3485796c8dcSSimon Schubert /* causes a subroutine call in GCC. (These are length 4 for speed */
3495796c8dcSSimon Schubert /* and are safe because the array has an extra terminator byte.) */
3505796c8dcSSimon Schubert #define dpd2char u=&BIN2CHAR[DPD2BIN[dpd]*4]; \
3515796c8dcSSimon Schubert if (c!=cstart) {memcpy(c, u+1, 4); c+=3;} \
3525796c8dcSSimon Schubert else if (*u) {memcpy(c, u+4-*u, 4); c+=*u;}
3535796c8dcSSimon Schubert dpd=(sourhi>>4)&0x3ff; /* declet 1 */
3545796c8dcSSimon Schubert dpd2char;
3555796c8dcSSimon Schubert dpd=((sourhi&0xf)<<6) | (sourmh>>26); /* declet 2 */
3565796c8dcSSimon Schubert dpd2char;
3575796c8dcSSimon Schubert dpd=(sourmh>>16)&0x3ff; /* declet 3 */
3585796c8dcSSimon Schubert dpd2char;
3595796c8dcSSimon Schubert dpd=(sourmh>>6)&0x3ff; /* declet 4 */
3605796c8dcSSimon Schubert dpd2char;
3615796c8dcSSimon Schubert dpd=((sourmh&0x3f)<<4) | (sourml>>28); /* declet 5 */
3625796c8dcSSimon Schubert dpd2char;
3635796c8dcSSimon Schubert dpd=(sourml>>18)&0x3ff; /* declet 6 */
3645796c8dcSSimon Schubert dpd2char;
3655796c8dcSSimon Schubert dpd=(sourml>>8)&0x3ff; /* declet 7 */
3665796c8dcSSimon Schubert dpd2char;
3675796c8dcSSimon Schubert dpd=((sourml&0xff)<<2) | (sourlo>>30); /* declet 8 */
3685796c8dcSSimon Schubert dpd2char;
3695796c8dcSSimon Schubert dpd=(sourlo>>20)&0x3ff; /* declet 9 */
3705796c8dcSSimon Schubert dpd2char;
3715796c8dcSSimon Schubert dpd=(sourlo>>10)&0x3ff; /* declet 10 */
3725796c8dcSSimon Schubert dpd2char;
3735796c8dcSSimon Schubert dpd=(sourlo)&0x3ff; /* declet 11 */
3745796c8dcSSimon Schubert dpd2char;
3755796c8dcSSimon Schubert
3765796c8dcSSimon Schubert if (c==cstart) *c++='0'; /* all zeros -- make 0 */
3775796c8dcSSimon Schubert
3785796c8dcSSimon Schubert if (exp==0) { /* integer or NaN case -- easy */
3795796c8dcSSimon Schubert *c='\0'; /* terminate */
3805796c8dcSSimon Schubert return string;
3815796c8dcSSimon Schubert }
3825796c8dcSSimon Schubert
3835796c8dcSSimon Schubert /* non-0 exponent */
3845796c8dcSSimon Schubert e=0; /* assume no E */
3855796c8dcSSimon Schubert pre=c-cstart+exp;
3865796c8dcSSimon Schubert /* [here, pre-exp is the digits count (==1 for zero)] */
3875796c8dcSSimon Schubert if (exp>0 || pre<-5) { /* need exponential form */
3885796c8dcSSimon Schubert e=pre-1; /* calculate E value */
3895796c8dcSSimon Schubert pre=1; /* assume one digit before '.' */
3905796c8dcSSimon Schubert } /* exponential form */
3915796c8dcSSimon Schubert
3925796c8dcSSimon Schubert /* modify the coefficient, adding 0s, '.', and E+nn as needed */
3935796c8dcSSimon Schubert s=c-1; /* source (LSD) */
3945796c8dcSSimon Schubert if (pre>0) { /* ddd.ddd (plain), perhaps with E */
3955796c8dcSSimon Schubert char *dotat=cstart+pre;
3965796c8dcSSimon Schubert if (dotat<c) { /* if embedded dot needed... */
3975796c8dcSSimon Schubert t=c; /* target */
3985796c8dcSSimon Schubert for (; s>=dotat; s--, t--) *t=*s; /* open the gap; leave t at gap */
3995796c8dcSSimon Schubert *t='.'; /* insert the dot */
4005796c8dcSSimon Schubert c++; /* length increased by one */
4015796c8dcSSimon Schubert }
4025796c8dcSSimon Schubert
4035796c8dcSSimon Schubert /* finally add the E-part, if needed; it will never be 0, and has */
4045796c8dcSSimon Schubert /* a maximum length of 4 digits */
4055796c8dcSSimon Schubert if (e!=0) {
4065796c8dcSSimon Schubert *c++='E'; /* starts with E */
4075796c8dcSSimon Schubert *c++='+'; /* assume positive */
4085796c8dcSSimon Schubert if (e<0) {
4095796c8dcSSimon Schubert *(c-1)='-'; /* oops, need '-' */
4105796c8dcSSimon Schubert e=-e; /* uInt, please */
4115796c8dcSSimon Schubert }
4125796c8dcSSimon Schubert if (e<1000) { /* 3 (or fewer) digits case */
4135796c8dcSSimon Schubert u=&BIN2CHAR[e*4]; /* -> length byte */
4145796c8dcSSimon Schubert memcpy(c, u+4-*u, 4); /* copy fixed 4 characters [is safe] */
4155796c8dcSSimon Schubert c+=*u; /* bump pointer appropriately */
4165796c8dcSSimon Schubert }
4175796c8dcSSimon Schubert else { /* 4-digits */
4185796c8dcSSimon Schubert Int thou=((e>>3)*1049)>>17; /* e/1000 */
4195796c8dcSSimon Schubert Int rem=e-(1000*thou); /* e%1000 */
4205796c8dcSSimon Schubert *c++='0'+(char)thou;
4215796c8dcSSimon Schubert u=&BIN2CHAR[rem*4]; /* -> length byte */
4225796c8dcSSimon Schubert memcpy(c, u+1, 4); /* copy fixed 3+1 characters [is safe] */
4235796c8dcSSimon Schubert c+=3; /* bump pointer, always 3 digits */
4245796c8dcSSimon Schubert }
4255796c8dcSSimon Schubert }
4265796c8dcSSimon Schubert *c='\0'; /* add terminator */
4275796c8dcSSimon Schubert /*printf("res %s\n", string); */
4285796c8dcSSimon Schubert return string;
4295796c8dcSSimon Schubert } /* pre>0 */
4305796c8dcSSimon Schubert
4315796c8dcSSimon Schubert /* -5<=pre<=0: here for plain 0.ddd or 0.000ddd forms (can never have E) */
4325796c8dcSSimon Schubert t=c+1-pre;
4335796c8dcSSimon Schubert *(t+1)='\0'; /* can add terminator now */
4345796c8dcSSimon Schubert for (; s>=cstart; s--, t--) *t=*s; /* shift whole coefficient right */
4355796c8dcSSimon Schubert c=cstart;
4365796c8dcSSimon Schubert *c++='0'; /* always starts with 0. */
4375796c8dcSSimon Schubert *c++='.';
4385796c8dcSSimon Schubert for (; pre<0; pre++) *c++='0'; /* add any 0's after '.' */
4395796c8dcSSimon Schubert /*printf("res %s\n", string); */
4405796c8dcSSimon Schubert return string;
4415796c8dcSSimon Schubert } /* decimal128ToString */
4425796c8dcSSimon Schubert
4435796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
4445796c8dcSSimon Schubert /* to-number -- conversion from numeric string */
4455796c8dcSSimon Schubert /* */
4465796c8dcSSimon Schubert /* decimal128FromString(result, string, set); */
4475796c8dcSSimon Schubert /* */
4485796c8dcSSimon Schubert /* result is the decimal128 format number which gets the result of */
4495796c8dcSSimon Schubert /* the conversion */
4505796c8dcSSimon Schubert /* *string is the character string which should contain a valid */
4515796c8dcSSimon Schubert /* number (which may be a special value) */
4525796c8dcSSimon Schubert /* set is the context */
4535796c8dcSSimon Schubert /* */
4545796c8dcSSimon Schubert /* The context is supplied to this routine is used for error handling */
4555796c8dcSSimon Schubert /* (setting of status and traps) and for the rounding mode, only. */
4565796c8dcSSimon Schubert /* If an error occurs, the result will be a valid decimal128 NaN. */
4575796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
decimal128FromString(decimal128 * result,const char * string,decContext * set)4585796c8dcSSimon Schubert decimal128 * decimal128FromString(decimal128 *result, const char *string,
4595796c8dcSSimon Schubert decContext *set) {
4605796c8dcSSimon Schubert decContext dc; /* work */
4615796c8dcSSimon Schubert decNumber dn; /* .. */
4625796c8dcSSimon Schubert
4635796c8dcSSimon Schubert decContextDefault(&dc, DEC_INIT_DECIMAL128); /* no traps, please */
4645796c8dcSSimon Schubert dc.round=set->round; /* use supplied rounding */
4655796c8dcSSimon Schubert
4665796c8dcSSimon Schubert decNumberFromString(&dn, string, &dc); /* will round if needed */
4675796c8dcSSimon Schubert decimal128FromNumber(result, &dn, &dc);
4685796c8dcSSimon Schubert if (dc.status!=0) { /* something happened */
4695796c8dcSSimon Schubert decContextSetStatus(set, dc.status); /* .. pass it on */
4705796c8dcSSimon Schubert }
4715796c8dcSSimon Schubert return result;
4725796c8dcSSimon Schubert } /* decimal128FromString */
4735796c8dcSSimon Schubert
4745796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
4755796c8dcSSimon Schubert /* decimal128IsCanonical -- test whether encoding is canonical */
4765796c8dcSSimon Schubert /* d128 is the source decimal128 */
4775796c8dcSSimon Schubert /* returns 1 if the encoding of d128 is canonical, 0 otherwise */
4785796c8dcSSimon Schubert /* No error is possible. */
4795796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
decimal128IsCanonical(const decimal128 * d128)4805796c8dcSSimon Schubert uInt decimal128IsCanonical(const decimal128 *d128) {
4815796c8dcSSimon Schubert decNumber dn; /* work */
4825796c8dcSSimon Schubert decimal128 canon; /* .. */
4835796c8dcSSimon Schubert decContext dc; /* .. */
4845796c8dcSSimon Schubert decContextDefault(&dc, DEC_INIT_DECIMAL128);
4855796c8dcSSimon Schubert decimal128ToNumber(d128, &dn);
4865796c8dcSSimon Schubert decimal128FromNumber(&canon, &dn, &dc);/* canon will now be canonical */
4875796c8dcSSimon Schubert return memcmp(d128, &canon, DECIMAL128_Bytes)==0;
4885796c8dcSSimon Schubert } /* decimal128IsCanonical */
4895796c8dcSSimon Schubert
4905796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
4915796c8dcSSimon Schubert /* decimal128Canonical -- copy an encoding, ensuring it is canonical */
4925796c8dcSSimon Schubert /* d128 is the source decimal128 */
4935796c8dcSSimon Schubert /* result is the target (may be the same decimal128) */
4945796c8dcSSimon Schubert /* returns result */
4955796c8dcSSimon Schubert /* No error is possible. */
4965796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
decimal128Canonical(decimal128 * result,const decimal128 * d128)4975796c8dcSSimon Schubert decimal128 * decimal128Canonical(decimal128 *result, const decimal128 *d128) {
4985796c8dcSSimon Schubert decNumber dn; /* work */
4995796c8dcSSimon Schubert decContext dc; /* .. */
5005796c8dcSSimon Schubert decContextDefault(&dc, DEC_INIT_DECIMAL128);
5015796c8dcSSimon Schubert decimal128ToNumber(d128, &dn);
5025796c8dcSSimon Schubert decimal128FromNumber(result, &dn, &dc);/* result will now be canonical */
5035796c8dcSSimon Schubert return result;
5045796c8dcSSimon Schubert } /* decimal128Canonical */
5055796c8dcSSimon Schubert
5065796c8dcSSimon Schubert #if DECTRACE || DECCHECK
5075796c8dcSSimon Schubert /* Macros for accessing decimal128 fields. These assume the argument
5085796c8dcSSimon Schubert is a reference (pointer) to the decimal128 structure, and the
5095796c8dcSSimon Schubert decimal128 is in network byte order (big-endian) */
5105796c8dcSSimon Schubert /* Get sign */
5115796c8dcSSimon Schubert #define decimal128Sign(d) ((unsigned)(d)->bytes[0]>>7)
5125796c8dcSSimon Schubert
5135796c8dcSSimon Schubert /* Get combination field */
5145796c8dcSSimon Schubert #define decimal128Comb(d) (((d)->bytes[0] & 0x7c)>>2)
5155796c8dcSSimon Schubert
5165796c8dcSSimon Schubert /* Get exponent continuation [does not remove bias] */
5175796c8dcSSimon Schubert #define decimal128ExpCon(d) ((((d)->bytes[0] & 0x03)<<10) \
5185796c8dcSSimon Schubert | ((unsigned)(d)->bytes[1]<<2) \
5195796c8dcSSimon Schubert | ((unsigned)(d)->bytes[2]>>6))
5205796c8dcSSimon Schubert
5215796c8dcSSimon Schubert /* Set sign [this assumes sign previously 0] */
5225796c8dcSSimon Schubert #define decimal128SetSign(d, b) { \
5235796c8dcSSimon Schubert (d)->bytes[0]|=((unsigned)(b)<<7);}
5245796c8dcSSimon Schubert
5255796c8dcSSimon Schubert /* Set exponent continuation [does not apply bias] */
5265796c8dcSSimon Schubert /* This assumes range has been checked and exponent previously 0; */
5275796c8dcSSimon Schubert /* type of exponent must be unsigned */
5285796c8dcSSimon Schubert #define decimal128SetExpCon(d, e) { \
5295796c8dcSSimon Schubert (d)->bytes[0]|=(uByte)((e)>>10); \
5305796c8dcSSimon Schubert (d)->bytes[1] =(uByte)(((e)&0x3fc)>>2); \
5315796c8dcSSimon Schubert (d)->bytes[2]|=(uByte)(((e)&0x03)<<6);}
5325796c8dcSSimon Schubert
5335796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
5345796c8dcSSimon Schubert /* decimal128Show -- display a decimal128 in hexadecimal [debug aid] */
5355796c8dcSSimon Schubert /* d128 -- the number to show */
5365796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
5375796c8dcSSimon Schubert /* Also shows sign/cob/expconfields extracted */
decimal128Show(const decimal128 * d128)5385796c8dcSSimon Schubert void decimal128Show(const decimal128 *d128) {
5395796c8dcSSimon Schubert char buf[DECIMAL128_Bytes*2+1];
5405796c8dcSSimon Schubert Int i, j=0;
5415796c8dcSSimon Schubert
5425796c8dcSSimon Schubert if (DECLITEND) {
5435796c8dcSSimon Schubert for (i=0; i<DECIMAL128_Bytes; i++, j+=2) {
5445796c8dcSSimon Schubert sprintf(&buf[j], "%02x", d128->bytes[15-i]);
5455796c8dcSSimon Schubert }
5465796c8dcSSimon Schubert printf(" D128> %s [S:%d Cb:%02x Ec:%02x] LittleEndian\n", buf,
5475796c8dcSSimon Schubert d128->bytes[15]>>7, (d128->bytes[15]>>2)&0x1f,
5485796c8dcSSimon Schubert ((d128->bytes[15]&0x3)<<10)|(d128->bytes[14]<<2)|
5495796c8dcSSimon Schubert (d128->bytes[13]>>6));
5505796c8dcSSimon Schubert }
5515796c8dcSSimon Schubert else {
5525796c8dcSSimon Schubert for (i=0; i<DECIMAL128_Bytes; i++, j+=2) {
5535796c8dcSSimon Schubert sprintf(&buf[j], "%02x", d128->bytes[i]);
5545796c8dcSSimon Schubert }
5555796c8dcSSimon Schubert printf(" D128> %s [S:%d Cb:%02x Ec:%02x] BigEndian\n", buf,
5565796c8dcSSimon Schubert decimal128Sign(d128), decimal128Comb(d128),
5575796c8dcSSimon Schubert decimal128ExpCon(d128));
5585796c8dcSSimon Schubert }
5595796c8dcSSimon Schubert } /* decimal128Show */
5605796c8dcSSimon Schubert #endif
561