163d1a8abSmrg /* Decimal 128-bit format module for the decNumber C Library.
2*ec02198aSmrg    Copyright (C) 2005-2020 Free Software Foundation, Inc.
363d1a8abSmrg    Contributed by IBM Corporation.  Author Mike Cowlishaw.
463d1a8abSmrg 
563d1a8abSmrg    This file is part of GCC.
663d1a8abSmrg 
763d1a8abSmrg    GCC is free software; you can redistribute it and/or modify it under
863d1a8abSmrg    the terms of the GNU General Public License as published by the Free
963d1a8abSmrg    Software Foundation; either version 3, or (at your option) any later
1063d1a8abSmrg    version.
1163d1a8abSmrg 
1263d1a8abSmrg    GCC is distributed in the hope that it will be useful, but WITHOUT ANY
1363d1a8abSmrg    WARRANTY; without even the implied warranty of MERCHANTABILITY or
1463d1a8abSmrg    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
1563d1a8abSmrg    for more details.
1663d1a8abSmrg 
1763d1a8abSmrg Under Section 7 of GPL version 3, you are granted additional
1863d1a8abSmrg permissions described in the GCC Runtime Library Exception, version
1963d1a8abSmrg 3.1, as published by the Free Software Foundation.
2063d1a8abSmrg 
2163d1a8abSmrg You should have received a copy of the GNU General Public License and
2263d1a8abSmrg a copy of the GCC Runtime Library Exception along with this program;
2363d1a8abSmrg see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
2463d1a8abSmrg <http://www.gnu.org/licenses/>.  */
2563d1a8abSmrg 
2663d1a8abSmrg /* ------------------------------------------------------------------ */
2763d1a8abSmrg /* Decimal 128-bit format module				      */
2863d1a8abSmrg /* ------------------------------------------------------------------ */
2963d1a8abSmrg /* This module comprises the routines for decimal128 format numbers.  */
3063d1a8abSmrg /* Conversions are supplied to and from decNumber and String.	      */
3163d1a8abSmrg /*								      */
3263d1a8abSmrg /* This is used when decNumber provides operations, either for all    */
3363d1a8abSmrg /* operations or as a proxy between decNumber and decSingle.	      */
3463d1a8abSmrg /*								      */
3563d1a8abSmrg /* Error handling is the same as decNumber (qv.).		      */
3663d1a8abSmrg /* ------------------------------------------------------------------ */
3763d1a8abSmrg #include <string.h>	      /* [for memset/memcpy] */
3863d1a8abSmrg #include <stdio.h>	      /* [for printf] */
3963d1a8abSmrg 
4063d1a8abSmrg #include "dconfig.h"          /* GCC definitions */
4163d1a8abSmrg #define  DECNUMDIGITS 34      /* make decNumbers with space for 34 */
4263d1a8abSmrg #include "decNumber.h"	      /* base number library */
4363d1a8abSmrg #include "decNumberLocal.h"   /* decNumber local types, etc. */
4463d1a8abSmrg #include "decimal128.h"       /* our primary include */
4563d1a8abSmrg 
4663d1a8abSmrg /* Utility routines and tables [in decimal64.c] */
4763d1a8abSmrg extern const uInt   COMBEXP[32], COMBMSD[32];
4863d1a8abSmrg extern const uShort DPD2BIN[1024];
4963d1a8abSmrg extern const uShort BIN2DPD[1000];	/* [not used] */
5063d1a8abSmrg extern const uByte  BIN2CHAR[4001];
5163d1a8abSmrg 
5263d1a8abSmrg extern void decDigitsFromDPD(decNumber *, const uInt *, Int);
5363d1a8abSmrg extern void decDigitsToDPD(const decNumber *, uInt *, Int);
5463d1a8abSmrg 
5563d1a8abSmrg #if DECTRACE || DECCHECK
5663d1a8abSmrg void decimal128Show(const decimal128 *);	  /* for debug */
5763d1a8abSmrg extern void decNumberShow(const decNumber *);	  /* .. */
5863d1a8abSmrg #endif
5963d1a8abSmrg 
6063d1a8abSmrg /* Useful macro */
6163d1a8abSmrg /* Clear a structure (e.g., a decNumber) */
6263d1a8abSmrg #define DEC_clear(d) memset(d, 0, sizeof(*d))
6363d1a8abSmrg 
6463d1a8abSmrg /* ------------------------------------------------------------------ */
6563d1a8abSmrg /* decimal128FromNumber -- convert decNumber to decimal128	      */
6663d1a8abSmrg /*								      */
6763d1a8abSmrg /*   ds is the target decimal128				      */
6863d1a8abSmrg /*   dn is the source number (assumed valid)			      */
6963d1a8abSmrg /*   set is the context, used only for reporting errors 	      */
7063d1a8abSmrg /*								      */
7163d1a8abSmrg /* The set argument is used only for status reporting and for the     */
7263d1a8abSmrg /* rounding mode (used if the coefficient is more than DECIMAL128_Pmax*/
7363d1a8abSmrg /* digits or an overflow is detected).	If the exponent is out of the */
7463d1a8abSmrg /* valid range then Overflow or Underflow will be raised.	      */
7563d1a8abSmrg /* After Underflow a subnormal result is possible.		      */
7663d1a8abSmrg /*								      */
7763d1a8abSmrg /* DEC_Clamped is set if the number has to be 'folded down' to fit,   */
7863d1a8abSmrg /* by reducing its exponent and multiplying the coefficient by a      */
7963d1a8abSmrg /* power of ten, or if the exponent on a zero had to be clamped.      */
8063d1a8abSmrg /* ------------------------------------------------------------------ */
decimal128FromNumber(decimal128 * d128,const decNumber * dn,decContext * set)8163d1a8abSmrg decimal128 * decimal128FromNumber(decimal128 *d128, const decNumber *dn,
8263d1a8abSmrg 				  decContext *set) {
8363d1a8abSmrg   uInt status=0;		   /* status accumulator */
8463d1a8abSmrg   Int ae;			   /* adjusted exponent */
8563d1a8abSmrg   decNumber  dw;		   /* work */
8663d1a8abSmrg   decContext dc;		   /* .. */
8763d1a8abSmrg   uInt comb, exp;		   /* .. */
8863d1a8abSmrg   uInt uiwork;			   /* for macros */
8963d1a8abSmrg   uInt targar[4]={0,0,0,0};	   /* target 128-bit */
9063d1a8abSmrg   #define targhi targar[3]	   /* name the word with the sign */
9163d1a8abSmrg   #define targmh targar[2]	   /* name the words */
9263d1a8abSmrg   #define targml targar[1]	   /* .. */
9363d1a8abSmrg   #define targlo targar[0]	   /* .. */
9463d1a8abSmrg 
9563d1a8abSmrg   /* If the number has too many digits, or the exponent could be */
9663d1a8abSmrg   /* out of range then reduce the number under the appropriate */
9763d1a8abSmrg   /* constraints.  This could push the number to Infinity or zero, */
9863d1a8abSmrg   /* so this check and rounding must be done before generating the */
9963d1a8abSmrg   /* decimal128] */
10063d1a8abSmrg   ae=dn->exponent+dn->digits-1; 	     /* [0 if special] */
10163d1a8abSmrg   if (dn->digits>DECIMAL128_Pmax	     /* too many digits */
10263d1a8abSmrg    || ae>DECIMAL128_Emax		     /* likely overflow */
10363d1a8abSmrg    || ae<DECIMAL128_Emin) {		     /* likely underflow */
10463d1a8abSmrg     decContextDefault(&dc, DEC_INIT_DECIMAL128); /* [no traps] */
10563d1a8abSmrg     dc.round=set->round;		     /* use supplied rounding */
10663d1a8abSmrg     decNumberPlus(&dw, dn, &dc);	     /* (round and check) */
10763d1a8abSmrg     /* [this changes -0 to 0, so enforce the sign...] */
10863d1a8abSmrg     dw.bits|=dn->bits&DECNEG;
10963d1a8abSmrg     status=dc.status;			     /* save status */
11063d1a8abSmrg     dn=&dw;				     /* use the work number */
11163d1a8abSmrg     } /* maybe out of range */
11263d1a8abSmrg 
11363d1a8abSmrg   if (dn->bits&DECSPECIAL) {			  /* a special value */
11463d1a8abSmrg     if (dn->bits&DECINF) targhi=DECIMAL_Inf<<24;
11563d1a8abSmrg      else {					  /* sNaN or qNaN */
11663d1a8abSmrg       if ((*dn->lsu!=0 || dn->digits>1) 	  /* non-zero coefficient */
11763d1a8abSmrg        && (dn->digits<DECIMAL128_Pmax)) {	  /* coefficient fits */
11863d1a8abSmrg 	decDigitsToDPD(dn, targar, 0);
11963d1a8abSmrg 	}
12063d1a8abSmrg       if (dn->bits&DECNAN) targhi|=DECIMAL_NaN<<24;
12163d1a8abSmrg        else targhi|=DECIMAL_sNaN<<24;
12263d1a8abSmrg       } /* a NaN */
12363d1a8abSmrg     } /* special */
12463d1a8abSmrg 
12563d1a8abSmrg    else { /* is finite */
12663d1a8abSmrg     if (decNumberIsZero(dn)) {		     /* is a zero */
12763d1a8abSmrg       /* set and clamp exponent */
12863d1a8abSmrg       if (dn->exponent<-DECIMAL128_Bias) {
12963d1a8abSmrg 	exp=0;				     /* low clamp */
13063d1a8abSmrg 	status|=DEC_Clamped;
13163d1a8abSmrg 	}
13263d1a8abSmrg        else {
13363d1a8abSmrg 	exp=dn->exponent+DECIMAL128_Bias;    /* bias exponent */
13463d1a8abSmrg 	if (exp>DECIMAL128_Ehigh) {	     /* top clamp */
13563d1a8abSmrg 	  exp=DECIMAL128_Ehigh;
13663d1a8abSmrg 	  status|=DEC_Clamped;
13763d1a8abSmrg 	  }
13863d1a8abSmrg 	}
13963d1a8abSmrg       comb=(exp>>9) & 0x18;		/* msd=0, exp top 2 bits .. */
14063d1a8abSmrg       }
14163d1a8abSmrg      else {				/* non-zero finite number */
14263d1a8abSmrg       uInt msd; 			/* work */
14363d1a8abSmrg       Int pad=0;			/* coefficient pad digits */
14463d1a8abSmrg 
14563d1a8abSmrg       /* the dn is known to fit, but it may need to be padded */
14663d1a8abSmrg       exp=(uInt)(dn->exponent+DECIMAL128_Bias);    /* bias exponent */
14763d1a8abSmrg       if (exp>DECIMAL128_Ehigh) {		   /* fold-down case */
14863d1a8abSmrg 	pad=exp-DECIMAL128_Ehigh;
14963d1a8abSmrg 	exp=DECIMAL128_Ehigh;			   /* [to maximum] */
15063d1a8abSmrg 	status|=DEC_Clamped;
15163d1a8abSmrg 	}
15263d1a8abSmrg 
15363d1a8abSmrg       /* [fastpath for common case is not a win, here] */
15463d1a8abSmrg       decDigitsToDPD(dn, targar, pad);
15563d1a8abSmrg       /* save and clear the top digit */
15663d1a8abSmrg       msd=targhi>>14;
15763d1a8abSmrg       targhi&=0x00003fff;
15863d1a8abSmrg 
15963d1a8abSmrg       /* create the combination field */
16063d1a8abSmrg       if (msd>=8) comb=0x18 | ((exp>>11) & 0x06) | (msd & 0x01);
16163d1a8abSmrg 	     else comb=((exp>>9) & 0x18) | msd;
16263d1a8abSmrg       }
16363d1a8abSmrg     targhi|=comb<<26;		   /* add combination field .. */
16463d1a8abSmrg     targhi|=(exp&0xfff)<<14;	   /* .. and exponent continuation */
16563d1a8abSmrg     } /* finite */
16663d1a8abSmrg 
16763d1a8abSmrg   if (dn->bits&DECNEG) targhi|=0x80000000; /* add sign bit */
16863d1a8abSmrg 
16963d1a8abSmrg   /* now write to storage; this is endian */
17063d1a8abSmrg   if (DECLITEND) {
17163d1a8abSmrg     /* lo -> hi */
17263d1a8abSmrg     UBFROMUI(d128->bytes,    targlo);
17363d1a8abSmrg     UBFROMUI(d128->bytes+4,  targml);
17463d1a8abSmrg     UBFROMUI(d128->bytes+8,  targmh);
17563d1a8abSmrg     UBFROMUI(d128->bytes+12, targhi);
17663d1a8abSmrg     }
17763d1a8abSmrg    else {
17863d1a8abSmrg     /* hi -> lo */
17963d1a8abSmrg     UBFROMUI(d128->bytes,    targhi);
18063d1a8abSmrg     UBFROMUI(d128->bytes+4,  targmh);
18163d1a8abSmrg     UBFROMUI(d128->bytes+8,  targml);
18263d1a8abSmrg     UBFROMUI(d128->bytes+12, targlo);
18363d1a8abSmrg     }
18463d1a8abSmrg 
18563d1a8abSmrg   if (status!=0) decContextSetStatus(set, status); /* pass on status */
18663d1a8abSmrg   /* decimal128Show(d128); */
18763d1a8abSmrg   return d128;
18863d1a8abSmrg   } /* decimal128FromNumber */
18963d1a8abSmrg 
19063d1a8abSmrg /* ------------------------------------------------------------------ */
19163d1a8abSmrg /* decimal128ToNumber -- convert decimal128 to decNumber	      */
19263d1a8abSmrg /*   d128 is the source decimal128				      */
19363d1a8abSmrg /*   dn is the target number, with appropriate space		      */
19463d1a8abSmrg /* No error is possible.					      */
19563d1a8abSmrg /* ------------------------------------------------------------------ */
decimal128ToNumber(const decimal128 * d128,decNumber * dn)19663d1a8abSmrg decNumber * decimal128ToNumber(const decimal128 *d128, decNumber *dn) {
19763d1a8abSmrg   uInt msd;			   /* coefficient MSD */
19863d1a8abSmrg   uInt exp;			   /* exponent top two bits */
19963d1a8abSmrg   uInt comb;			   /* combination field */
20063d1a8abSmrg   Int  need;			   /* work */
20163d1a8abSmrg   uInt uiwork;			   /* for macros */
20263d1a8abSmrg   uInt sourar[4];		   /* source 128-bit */
20363d1a8abSmrg   #define sourhi sourar[3]	   /* name the word with the sign */
20463d1a8abSmrg   #define sourmh sourar[2]	   /* and the mid-high word */
20563d1a8abSmrg   #define sourml sourar[1]	   /* and the mod-low word */
20663d1a8abSmrg   #define sourlo sourar[0]	   /* and the lowest word */
20763d1a8abSmrg 
20863d1a8abSmrg   /* load source from storage; this is endian */
20963d1a8abSmrg   if (DECLITEND) {
21063d1a8abSmrg     sourlo=UBTOUI(d128->bytes	); /* directly load the low int */
21163d1a8abSmrg     sourml=UBTOUI(d128->bytes+4 ); /* then the mid-low */
21263d1a8abSmrg     sourmh=UBTOUI(d128->bytes+8 ); /* then the mid-high */
21363d1a8abSmrg     sourhi=UBTOUI(d128->bytes+12); /* then the high int */
21463d1a8abSmrg     }
21563d1a8abSmrg    else {
21663d1a8abSmrg     sourhi=UBTOUI(d128->bytes	); /* directly load the high int */
21763d1a8abSmrg     sourmh=UBTOUI(d128->bytes+4 ); /* then the mid-high */
21863d1a8abSmrg     sourml=UBTOUI(d128->bytes+8 ); /* then the mid-low */
21963d1a8abSmrg     sourlo=UBTOUI(d128->bytes+12); /* then the low int */
22063d1a8abSmrg     }
22163d1a8abSmrg 
22263d1a8abSmrg   comb=(sourhi>>26)&0x1f;	   /* combination field */
22363d1a8abSmrg 
22463d1a8abSmrg   decNumberZero(dn);		   /* clean number */
22563d1a8abSmrg   if (sourhi&0x80000000) dn->bits=DECNEG; /* set sign if negative */
22663d1a8abSmrg 
22763d1a8abSmrg   msd=COMBMSD[comb];		   /* decode the combination field */
22863d1a8abSmrg   exp=COMBEXP[comb];		   /* .. */
22963d1a8abSmrg 
23063d1a8abSmrg   if (exp==3) { 		   /* is a special */
23163d1a8abSmrg     if (msd==0) {
23263d1a8abSmrg       dn->bits|=DECINF;
23363d1a8abSmrg       return dn;		   /* no coefficient needed */
23463d1a8abSmrg       }
23563d1a8abSmrg     else if (sourhi&0x02000000) dn->bits|=DECSNAN;
23663d1a8abSmrg     else dn->bits|=DECNAN;
23763d1a8abSmrg     msd=0;			   /* no top digit */
23863d1a8abSmrg     }
23963d1a8abSmrg    else {			   /* is a finite number */
24063d1a8abSmrg     dn->exponent=(exp<<12)+((sourhi>>14)&0xfff)-DECIMAL128_Bias; /* unbiased */
24163d1a8abSmrg     }
24263d1a8abSmrg 
24363d1a8abSmrg   /* get the coefficient */
24463d1a8abSmrg   sourhi&=0x00003fff;		   /* clean coefficient continuation */
24563d1a8abSmrg   if (msd) {			   /* non-zero msd */
24663d1a8abSmrg     sourhi|=msd<<14;		   /* prefix to coefficient */
24763d1a8abSmrg     need=12;			   /* process 12 declets */
24863d1a8abSmrg     }
24963d1a8abSmrg    else { /* msd=0 */
25063d1a8abSmrg     if (sourhi) need=11;	   /* declets to process */
25163d1a8abSmrg      else if (sourmh) need=10;
25263d1a8abSmrg      else if (sourml) need=7;
25363d1a8abSmrg      else if (sourlo) need=4;
25463d1a8abSmrg      else return dn;		   /* easy: coefficient is 0 */
25563d1a8abSmrg     } /*msd=0 */
25663d1a8abSmrg 
25763d1a8abSmrg   decDigitsFromDPD(dn, sourar, need);	/* process declets */
25863d1a8abSmrg   /* decNumberShow(dn); */
25963d1a8abSmrg   return dn;
26063d1a8abSmrg   } /* decimal128ToNumber */
26163d1a8abSmrg 
26263d1a8abSmrg /* ------------------------------------------------------------------ */
26363d1a8abSmrg /* to-scientific-string -- conversion to numeric string 	      */
26463d1a8abSmrg /* to-engineering-string -- conversion to numeric string	      */
26563d1a8abSmrg /*								      */
26663d1a8abSmrg /*   decimal128ToString(d128, string);				      */
26763d1a8abSmrg /*   decimal128ToEngString(d128, string);			      */
26863d1a8abSmrg /*								      */
26963d1a8abSmrg /*  d128 is the decimal128 format number to convert		      */
27063d1a8abSmrg /*  string is the string where the result will be laid out	      */
27163d1a8abSmrg /*								      */
27263d1a8abSmrg /*  string must be at least 24 characters			      */
27363d1a8abSmrg /*								      */
27463d1a8abSmrg /*  No error is possible, and no status can be set.		      */
27563d1a8abSmrg /* ------------------------------------------------------------------ */
decimal128ToEngString(const decimal128 * d128,char * string)27663d1a8abSmrg char * decimal128ToEngString(const decimal128 *d128, char *string){
27763d1a8abSmrg   decNumber dn; 			/* work */
27863d1a8abSmrg   decimal128ToNumber(d128, &dn);
27963d1a8abSmrg   decNumberToEngString(&dn, string);
28063d1a8abSmrg   return string;
28163d1a8abSmrg   } /* decimal128ToEngString */
28263d1a8abSmrg 
decimal128ToString(const decimal128 * d128,char * string)28363d1a8abSmrg char * decimal128ToString(const decimal128 *d128, char *string){
28463d1a8abSmrg   uInt msd;			   /* coefficient MSD */
28563d1a8abSmrg   Int  exp;			   /* exponent top two bits or full */
28663d1a8abSmrg   uInt comb;			   /* combination field */
28763d1a8abSmrg   char *cstart; 		   /* coefficient start */
28863d1a8abSmrg   char *c;			   /* output pointer in string */
28963d1a8abSmrg   const uByte *u;		   /* work */
29063d1a8abSmrg   char *s, *t;			   /* .. (source, target) */
29163d1a8abSmrg   Int  dpd;			   /* .. */
29263d1a8abSmrg   Int  pre, e;			   /* .. */
29363d1a8abSmrg   uInt uiwork;			   /* for macros */
29463d1a8abSmrg 
29563d1a8abSmrg   uInt sourar[4];		   /* source 128-bit */
29663d1a8abSmrg   #define sourhi sourar[3]	   /* name the word with the sign */
29763d1a8abSmrg   #define sourmh sourar[2]	   /* and the mid-high word */
29863d1a8abSmrg   #define sourml sourar[1]	   /* and the mod-low word */
29963d1a8abSmrg   #define sourlo sourar[0]	   /* and the lowest word */
30063d1a8abSmrg 
30163d1a8abSmrg   /* load source from storage; this is endian */
30263d1a8abSmrg   if (DECLITEND) {
30363d1a8abSmrg     sourlo=UBTOUI(d128->bytes	); /* directly load the low int */
30463d1a8abSmrg     sourml=UBTOUI(d128->bytes+4 ); /* then the mid-low */
30563d1a8abSmrg     sourmh=UBTOUI(d128->bytes+8 ); /* then the mid-high */
30663d1a8abSmrg     sourhi=UBTOUI(d128->bytes+12); /* then the high int */
30763d1a8abSmrg     }
30863d1a8abSmrg    else {
30963d1a8abSmrg     sourhi=UBTOUI(d128->bytes	); /* directly load the high int */
31063d1a8abSmrg     sourmh=UBTOUI(d128->bytes+4 ); /* then the mid-high */
31163d1a8abSmrg     sourml=UBTOUI(d128->bytes+8 ); /* then the mid-low */
31263d1a8abSmrg     sourlo=UBTOUI(d128->bytes+12); /* then the low int */
31363d1a8abSmrg     }
31463d1a8abSmrg 
31563d1a8abSmrg   c=string;			   /* where result will go */
31663d1a8abSmrg   if (((Int)sourhi)<0) *c++='-';   /* handle sign */
31763d1a8abSmrg 
31863d1a8abSmrg   comb=(sourhi>>26)&0x1f;	   /* combination field */
31963d1a8abSmrg   msd=COMBMSD[comb];		   /* decode the combination field */
32063d1a8abSmrg   exp=COMBEXP[comb];		   /* .. */
32163d1a8abSmrg 
32263d1a8abSmrg   if (exp==3) {
32363d1a8abSmrg     if (msd==0) {		   /* infinity */
32463d1a8abSmrg       strcpy(c,   "Inf");
32563d1a8abSmrg       strcpy(c+3, "inity");
32663d1a8abSmrg       return string;		   /* easy */
32763d1a8abSmrg       }
32863d1a8abSmrg     if (sourhi&0x02000000) *c++='s'; /* sNaN */
32963d1a8abSmrg     strcpy(c, "NaN");		   /* complete word */
33063d1a8abSmrg     c+=3;			   /* step past */
33163d1a8abSmrg     if (sourlo==0 && sourml==0 && sourmh==0
33263d1a8abSmrg      && (sourhi&0x0003ffff)==0) return string; /* zero payload */
33363d1a8abSmrg     /* otherwise drop through to add integer; set correct exp */
33463d1a8abSmrg     exp=0; msd=0;		   /* setup for following code */
33563d1a8abSmrg     }
33663d1a8abSmrg    else exp=(exp<<12)+((sourhi>>14)&0xfff)-DECIMAL128_Bias; /* unbiased */
33763d1a8abSmrg 
33863d1a8abSmrg   /* convert 34 digits of significand to characters */
33963d1a8abSmrg   cstart=c;			   /* save start of coefficient */
34063d1a8abSmrg   if (msd) *c++='0'+(char)msd;	   /* non-zero most significant digit */
34163d1a8abSmrg 
34263d1a8abSmrg   /* Now decode the declets.  After extracting each one, it is */
34363d1a8abSmrg   /* decoded to binary and then to a 4-char sequence by table lookup; */
34463d1a8abSmrg   /* the 4-chars are a 1-char length (significant digits, except 000 */
34563d1a8abSmrg   /* has length 0).  This allows us to left-align the first declet */
34663d1a8abSmrg   /* with non-zero content, then remaining ones are full 3-char */
34763d1a8abSmrg   /* length.  We use fixed-length memcpys because variable-length */
34863d1a8abSmrg   /* causes a subroutine call in GCC.  (These are length 4 for speed */
34963d1a8abSmrg   /* and are safe because the array has an extra terminator byte.) */
35063d1a8abSmrg   #define dpd2char u=&BIN2CHAR[DPD2BIN[dpd]*4]; 		  \
35163d1a8abSmrg 		   if (c!=cstart) {memcpy(c, u+1, 4); c+=3;}	  \
35263d1a8abSmrg 		    else if (*u)  {memcpy(c, u+4-*u, 4); c+=*u;}
35363d1a8abSmrg   dpd=(sourhi>>4)&0x3ff;		     /* declet 1 */
35463d1a8abSmrg   dpd2char;
35563d1a8abSmrg   dpd=((sourhi&0xf)<<6) | (sourmh>>26);      /* declet 2 */
35663d1a8abSmrg   dpd2char;
35763d1a8abSmrg   dpd=(sourmh>>16)&0x3ff;		     /* declet 3 */
35863d1a8abSmrg   dpd2char;
35963d1a8abSmrg   dpd=(sourmh>>6)&0x3ff;		     /* declet 4 */
36063d1a8abSmrg   dpd2char;
36163d1a8abSmrg   dpd=((sourmh&0x3f)<<4) | (sourml>>28);     /* declet 5 */
36263d1a8abSmrg   dpd2char;
36363d1a8abSmrg   dpd=(sourml>>18)&0x3ff;		     /* declet 6 */
36463d1a8abSmrg   dpd2char;
36563d1a8abSmrg   dpd=(sourml>>8)&0x3ff;		     /* declet 7 */
36663d1a8abSmrg   dpd2char;
36763d1a8abSmrg   dpd=((sourml&0xff)<<2) | (sourlo>>30);     /* declet 8 */
36863d1a8abSmrg   dpd2char;
36963d1a8abSmrg   dpd=(sourlo>>20)&0x3ff;		     /* declet 9 */
37063d1a8abSmrg   dpd2char;
37163d1a8abSmrg   dpd=(sourlo>>10)&0x3ff;		     /* declet 10 */
37263d1a8abSmrg   dpd2char;
37363d1a8abSmrg   dpd=(sourlo)&0x3ff;			     /* declet 11 */
37463d1a8abSmrg   dpd2char;
37563d1a8abSmrg 
37663d1a8abSmrg   if (c==cstart) *c++='0';	   /* all zeros -- make 0 */
37763d1a8abSmrg 
37863d1a8abSmrg   if (exp==0) { 		   /* integer or NaN case -- easy */
37963d1a8abSmrg     *c='\0';			   /* terminate */
38063d1a8abSmrg     return string;
38163d1a8abSmrg     }
38263d1a8abSmrg 
38363d1a8abSmrg   /* non-0 exponent */
38463d1a8abSmrg   e=0;				   /* assume no E */
38563d1a8abSmrg   pre=c-cstart+exp;
38663d1a8abSmrg   /* [here, pre-exp is the digits count (==1 for zero)] */
38763d1a8abSmrg   if (exp>0 || pre<-5) {	   /* need exponential form */
38863d1a8abSmrg     e=pre-1;			   /* calculate E value */
38963d1a8abSmrg     pre=1;			   /* assume one digit before '.' */
39063d1a8abSmrg     } /* exponential form */
39163d1a8abSmrg 
39263d1a8abSmrg   /* modify the coefficient, adding 0s, '.', and E+nn as needed */
39363d1a8abSmrg   s=c-1;			   /* source (LSD) */
39463d1a8abSmrg   if (pre>0) {			   /* ddd.ddd (plain), perhaps with E */
39563d1a8abSmrg     char *dotat=cstart+pre;
39663d1a8abSmrg     if (dotat<c) {		   /* if embedded dot needed... */
39763d1a8abSmrg       t=c;				/* target */
39863d1a8abSmrg       for (; s>=dotat; s--, t--) *t=*s; /* open the gap; leave t at gap */
39963d1a8abSmrg       *t='.';				/* insert the dot */
40063d1a8abSmrg       c++;				/* length increased by one */
40163d1a8abSmrg       }
40263d1a8abSmrg 
40363d1a8abSmrg     /* finally add the E-part, if needed; it will never be 0, and has */
40463d1a8abSmrg     /* a maximum length of 4 digits */
40563d1a8abSmrg     if (e!=0) {
40663d1a8abSmrg       *c++='E'; 		   /* starts with E */
40763d1a8abSmrg       *c++='+'; 		   /* assume positive */
40863d1a8abSmrg       if (e<0) {
40963d1a8abSmrg 	*(c-1)='-';		   /* oops, need '-' */
41063d1a8abSmrg 	e=-e;			   /* uInt, please */
41163d1a8abSmrg 	}
41263d1a8abSmrg       if (e<1000) {		   /* 3 (or fewer) digits case */
41363d1a8abSmrg 	u=&BIN2CHAR[e*4];	   /* -> length byte */
41463d1a8abSmrg 	memcpy(c, u+4-*u, 4);	   /* copy fixed 4 characters [is safe] */
41563d1a8abSmrg 	c+=*u;			   /* bump pointer appropriately */
41663d1a8abSmrg 	}
41763d1a8abSmrg        else {			   /* 4-digits */
41863d1a8abSmrg 	Int thou=((e>>3)*1049)>>17; /* e/1000 */
41963d1a8abSmrg 	Int rem=e-(1000*thou);	    /* e%1000 */
42063d1a8abSmrg 	*c++='0'+(char)thou;
42163d1a8abSmrg 	u=&BIN2CHAR[rem*4];	   /* -> length byte */
42263d1a8abSmrg 	memcpy(c, u+1, 4);	   /* copy fixed 3+1 characters [is safe] */
42363d1a8abSmrg 	c+=3;			   /* bump pointer, always 3 digits */
42463d1a8abSmrg 	}
42563d1a8abSmrg       }
42663d1a8abSmrg     *c='\0';			   /* add terminator */
42763d1a8abSmrg     /*printf("res %s\n", string); */
42863d1a8abSmrg     return string;
42963d1a8abSmrg     } /* pre>0 */
43063d1a8abSmrg 
43163d1a8abSmrg   /* -5<=pre<=0: here for plain 0.ddd or 0.000ddd forms (can never have E) */
43263d1a8abSmrg   t=c+1-pre;
43363d1a8abSmrg   *(t+1)='\0';				/* can add terminator now */
43463d1a8abSmrg   for (; s>=cstart; s--, t--) *t=*s;	/* shift whole coefficient right */
43563d1a8abSmrg   c=cstart;
43663d1a8abSmrg   *c++='0';				/* always starts with 0. */
43763d1a8abSmrg   *c++='.';
43863d1a8abSmrg   for (; pre<0; pre++) *c++='0';	/* add any 0's after '.' */
43963d1a8abSmrg   /*printf("res %s\n", string); */
44063d1a8abSmrg   return string;
44163d1a8abSmrg   } /* decimal128ToString */
44263d1a8abSmrg 
44363d1a8abSmrg /* ------------------------------------------------------------------ */
44463d1a8abSmrg /* to-number -- conversion from numeric string			      */
44563d1a8abSmrg /*								      */
44663d1a8abSmrg /*   decimal128FromString(result, string, set); 		      */
44763d1a8abSmrg /*								      */
44863d1a8abSmrg /*  result  is the decimal128 format number which gets the result of  */
44963d1a8abSmrg /*	    the conversion					      */
45063d1a8abSmrg /*  *string is the character string which should contain a valid      */
45163d1a8abSmrg /*	    number (which may be a special value)		      */
45263d1a8abSmrg /*  set     is the context					      */
45363d1a8abSmrg /*								      */
45463d1a8abSmrg /* The context is supplied to this routine is used for error handling */
45563d1a8abSmrg /* (setting of status and traps) and for the rounding mode, only.     */
45663d1a8abSmrg /* If an error occurs, the result will be a valid decimal128 NaN.     */
45763d1a8abSmrg /* ------------------------------------------------------------------ */
decimal128FromString(decimal128 * result,const char * string,decContext * set)45863d1a8abSmrg decimal128 * decimal128FromString(decimal128 *result, const char *string,
45963d1a8abSmrg 				  decContext *set) {
46063d1a8abSmrg   decContext dc;			     /* work */
46163d1a8abSmrg   decNumber dn; 			     /* .. */
46263d1a8abSmrg 
46363d1a8abSmrg   decContextDefault(&dc, DEC_INIT_DECIMAL128); /* no traps, please */
46463d1a8abSmrg   dc.round=set->round;			       /* use supplied rounding */
46563d1a8abSmrg 
46663d1a8abSmrg   decNumberFromString(&dn, string, &dc);     /* will round if needed */
46763d1a8abSmrg   decimal128FromNumber(result, &dn, &dc);
46863d1a8abSmrg   if (dc.status!=0) {			     /* something happened */
46963d1a8abSmrg     decContextSetStatus(set, dc.status);     /* .. pass it on */
47063d1a8abSmrg     }
47163d1a8abSmrg   return result;
47263d1a8abSmrg   } /* decimal128FromString */
47363d1a8abSmrg 
47463d1a8abSmrg /* ------------------------------------------------------------------ */
47563d1a8abSmrg /* decimal128IsCanonical -- test whether encoding is canonical	      */
47663d1a8abSmrg /*   d128 is the source decimal128				      */
47763d1a8abSmrg /*   returns 1 if the encoding of d128 is canonical, 0 otherwise      */
47863d1a8abSmrg /* No error is possible.					      */
47963d1a8abSmrg /* ------------------------------------------------------------------ */
decimal128IsCanonical(const decimal128 * d128)48063d1a8abSmrg uInt decimal128IsCanonical(const decimal128 *d128) {
48163d1a8abSmrg   decNumber dn; 			/* work */
48263d1a8abSmrg   decimal128 canon;			 /* .. */
48363d1a8abSmrg   decContext dc;			/* .. */
48463d1a8abSmrg   decContextDefault(&dc, DEC_INIT_DECIMAL128);
48563d1a8abSmrg   decimal128ToNumber(d128, &dn);
48663d1a8abSmrg   decimal128FromNumber(&canon, &dn, &dc);/* canon will now be canonical */
48763d1a8abSmrg   return memcmp(d128, &canon, DECIMAL128_Bytes)==0;
48863d1a8abSmrg   } /* decimal128IsCanonical */
48963d1a8abSmrg 
49063d1a8abSmrg /* ------------------------------------------------------------------ */
49163d1a8abSmrg /* decimal128Canonical -- copy an encoding, ensuring it is canonical  */
49263d1a8abSmrg /*   d128 is the source decimal128				      */
49363d1a8abSmrg /*   result is the target (may be the same decimal128)		      */
49463d1a8abSmrg /*   returns result						      */
49563d1a8abSmrg /* No error is possible.					      */
49663d1a8abSmrg /* ------------------------------------------------------------------ */
decimal128Canonical(decimal128 * result,const decimal128 * d128)49763d1a8abSmrg decimal128 * decimal128Canonical(decimal128 *result, const decimal128 *d128) {
49863d1a8abSmrg   decNumber dn; 			/* work */
49963d1a8abSmrg   decContext dc;			/* .. */
50063d1a8abSmrg   decContextDefault(&dc, DEC_INIT_DECIMAL128);
50163d1a8abSmrg   decimal128ToNumber(d128, &dn);
50263d1a8abSmrg   decimal128FromNumber(result, &dn, &dc);/* result will now be canonical */
50363d1a8abSmrg   return result;
50463d1a8abSmrg   } /* decimal128Canonical */
50563d1a8abSmrg 
50663d1a8abSmrg #if DECTRACE || DECCHECK
50763d1a8abSmrg /* Macros for accessing decimal128 fields.  These assume the argument
50863d1a8abSmrg    is a reference (pointer) to the decimal128 structure, and the
50963d1a8abSmrg    decimal128 is in network byte order (big-endian) */
51063d1a8abSmrg /* Get sign */
51163d1a8abSmrg #define decimal128Sign(d)	((unsigned)(d)->bytes[0]>>7)
51263d1a8abSmrg 
51363d1a8abSmrg /* Get combination field */
51463d1a8abSmrg #define decimal128Comb(d)	(((d)->bytes[0] & 0x7c)>>2)
51563d1a8abSmrg 
51663d1a8abSmrg /* Get exponent continuation [does not remove bias] */
51763d1a8abSmrg #define decimal128ExpCon(d)	((((d)->bytes[0] & 0x03)<<10)	      \
51863d1a8abSmrg 			      | ((unsigned)(d)->bytes[1]<<2)	      \
51963d1a8abSmrg 			      | ((unsigned)(d)->bytes[2]>>6))
52063d1a8abSmrg 
52163d1a8abSmrg /* Set sign [this assumes sign previously 0] */
52263d1a8abSmrg #define decimal128SetSign(d, b) {				      \
52363d1a8abSmrg   (d)->bytes[0]|=((unsigned)(b)<<7);}
52463d1a8abSmrg 
52563d1a8abSmrg /* Set exponent continuation [does not apply bias] */
52663d1a8abSmrg /* This assumes range has been checked and exponent previously 0; */
52763d1a8abSmrg /* type of exponent must be unsigned */
52863d1a8abSmrg #define decimal128SetExpCon(d, e) {				      \
52963d1a8abSmrg   (d)->bytes[0]|=(uByte)((e)>>10);				      \
53063d1a8abSmrg   (d)->bytes[1] =(uByte)(((e)&0x3fc)>>2);			      \
53163d1a8abSmrg   (d)->bytes[2]|=(uByte)(((e)&0x03)<<6);}
53263d1a8abSmrg 
53363d1a8abSmrg /* ------------------------------------------------------------------ */
53463d1a8abSmrg /* decimal128Show -- display a decimal128 in hexadecimal [debug aid]  */
53563d1a8abSmrg /*   d128 -- the number to show 				      */
53663d1a8abSmrg /* ------------------------------------------------------------------ */
53763d1a8abSmrg /* Also shows sign/cob/expconfields extracted */
decimal128Show(const decimal128 * d128)53863d1a8abSmrg void decimal128Show(const decimal128 *d128) {
53963d1a8abSmrg   char buf[DECIMAL128_Bytes*2+1];
54063d1a8abSmrg   Int i, j=0;
54163d1a8abSmrg 
54263d1a8abSmrg   if (DECLITEND) {
54363d1a8abSmrg     for (i=0; i<DECIMAL128_Bytes; i++, j+=2) {
54463d1a8abSmrg       sprintf(&buf[j], "%02x", d128->bytes[15-i]);
54563d1a8abSmrg       }
54663d1a8abSmrg     printf(" D128> %s [S:%d Cb:%02x Ec:%02x] LittleEndian\n", buf,
54763d1a8abSmrg 	   d128->bytes[15]>>7, (d128->bytes[15]>>2)&0x1f,
54863d1a8abSmrg 	   ((d128->bytes[15]&0x3)<<10)|(d128->bytes[14]<<2)|
54963d1a8abSmrg 	   (d128->bytes[13]>>6));
55063d1a8abSmrg     }
55163d1a8abSmrg    else {
55263d1a8abSmrg     for (i=0; i<DECIMAL128_Bytes; i++, j+=2) {
55363d1a8abSmrg       sprintf(&buf[j], "%02x", d128->bytes[i]);
55463d1a8abSmrg       }
55563d1a8abSmrg     printf(" D128> %s [S:%d Cb:%02x Ec:%02x] BigEndian\n", buf,
55663d1a8abSmrg 	   decimal128Sign(d128), decimal128Comb(d128),
55763d1a8abSmrg 	   decimal128ExpCon(d128));
55863d1a8abSmrg     }
55963d1a8abSmrg   } /* decimal128Show */
56063d1a8abSmrg #endif
561