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