Home | History | Annotate | Line # | Download | only in dpd
decimal128.c revision 1.1.1.5
      1      1.1  mrg /* Decimal 128-bit format module for the decNumber C Library.
      2  1.1.1.5  mrg    Copyright (C) 2005-2017 Free Software Foundation, Inc.
      3      1.1  mrg    Contributed by IBM Corporation.  Author Mike Cowlishaw.
      4      1.1  mrg 
      5      1.1  mrg    This file is part of GCC.
      6      1.1  mrg 
      7      1.1  mrg    GCC is free software; you can redistribute it and/or modify it under
      8      1.1  mrg    the terms of the GNU General Public License as published by the Free
      9      1.1  mrg    Software Foundation; either version 3, or (at your option) any later
     10      1.1  mrg    version.
     11      1.1  mrg 
     12      1.1  mrg    GCC is distributed in the hope that it will be useful, but WITHOUT ANY
     13      1.1  mrg    WARRANTY; without even the implied warranty of MERCHANTABILITY or
     14      1.1  mrg    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
     15      1.1  mrg    for more details.
     16      1.1  mrg 
     17      1.1  mrg Under Section 7 of GPL version 3, you are granted additional
     18      1.1  mrg permissions described in the GCC Runtime Library Exception, version
     19      1.1  mrg 3.1, as published by the Free Software Foundation.
     20      1.1  mrg 
     21      1.1  mrg You should have received a copy of the GNU General Public License and
     22      1.1  mrg a copy of the GCC Runtime Library Exception along with this program;
     23      1.1  mrg see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
     24      1.1  mrg <http://www.gnu.org/licenses/>.  */
     25      1.1  mrg 
     26      1.1  mrg /* ------------------------------------------------------------------ */
     27      1.1  mrg /* Decimal 128-bit format module				      */
     28      1.1  mrg /* ------------------------------------------------------------------ */
     29      1.1  mrg /* This module comprises the routines for decimal128 format numbers.  */
     30      1.1  mrg /* Conversions are supplied to and from decNumber and String.	      */
     31      1.1  mrg /*								      */
     32      1.1  mrg /* This is used when decNumber provides operations, either for all    */
     33      1.1  mrg /* operations or as a proxy between decNumber and decSingle.	      */
     34      1.1  mrg /*								      */
     35      1.1  mrg /* Error handling is the same as decNumber (qv.).		      */
     36      1.1  mrg /* ------------------------------------------------------------------ */
     37      1.1  mrg #include <string.h>	      /* [for memset/memcpy] */
     38      1.1  mrg #include <stdio.h>	      /* [for printf] */
     39      1.1  mrg 
     40      1.1  mrg #include "dconfig.h"          /* GCC definitions */
     41      1.1  mrg #define  DECNUMDIGITS 34      /* make decNumbers with space for 34 */
     42      1.1  mrg #include "decNumber.h"	      /* base number library */
     43      1.1  mrg #include "decNumberLocal.h"   /* decNumber local types, etc. */
     44      1.1  mrg #include "decimal128.h"       /* our primary include */
     45      1.1  mrg 
     46      1.1  mrg /* Utility routines and tables [in decimal64.c] */
     47      1.1  mrg extern const uInt   COMBEXP[32], COMBMSD[32];
     48      1.1  mrg extern const uShort DPD2BIN[1024];
     49      1.1  mrg extern const uShort BIN2DPD[1000];	/* [not used] */
     50      1.1  mrg extern const uByte  BIN2CHAR[4001];
     51      1.1  mrg 
     52      1.1  mrg extern void decDigitsFromDPD(decNumber *, const uInt *, Int);
     53      1.1  mrg extern void decDigitsToDPD(const decNumber *, uInt *, Int);
     54      1.1  mrg 
     55      1.1  mrg #if DECTRACE || DECCHECK
     56      1.1  mrg void decimal128Show(const decimal128 *);	  /* for debug */
     57      1.1  mrg extern void decNumberShow(const decNumber *);	  /* .. */
     58      1.1  mrg #endif
     59      1.1  mrg 
     60      1.1  mrg /* Useful macro */
     61      1.1  mrg /* Clear a structure (e.g., a decNumber) */
     62      1.1  mrg #define DEC_clear(d) memset(d, 0, sizeof(*d))
     63      1.1  mrg 
     64      1.1  mrg /* ------------------------------------------------------------------ */
     65      1.1  mrg /* decimal128FromNumber -- convert decNumber to decimal128	      */
     66      1.1  mrg /*								      */
     67      1.1  mrg /*   ds is the target decimal128				      */
     68      1.1  mrg /*   dn is the source number (assumed valid)			      */
     69      1.1  mrg /*   set is the context, used only for reporting errors 	      */
     70      1.1  mrg /*								      */
     71      1.1  mrg /* The set argument is used only for status reporting and for the     */
     72      1.1  mrg /* rounding mode (used if the coefficient is more than DECIMAL128_Pmax*/
     73      1.1  mrg /* digits or an overflow is detected).	If the exponent is out of the */
     74      1.1  mrg /* valid range then Overflow or Underflow will be raised.	      */
     75      1.1  mrg /* After Underflow a subnormal result is possible.		      */
     76      1.1  mrg /*								      */
     77      1.1  mrg /* DEC_Clamped is set if the number has to be 'folded down' to fit,   */
     78      1.1  mrg /* by reducing its exponent and multiplying the coefficient by a      */
     79      1.1  mrg /* power of ten, or if the exponent on a zero had to be clamped.      */
     80      1.1  mrg /* ------------------------------------------------------------------ */
     81      1.1  mrg decimal128 * decimal128FromNumber(decimal128 *d128, const decNumber *dn,
     82      1.1  mrg 				  decContext *set) {
     83      1.1  mrg   uInt status=0;		   /* status accumulator */
     84      1.1  mrg   Int ae;			   /* adjusted exponent */
     85      1.1  mrg   decNumber  dw;		   /* work */
     86      1.1  mrg   decContext dc;		   /* .. */
     87      1.1  mrg   uInt comb, exp;		   /* .. */
     88      1.1  mrg   uInt uiwork;			   /* for macros */
     89      1.1  mrg   uInt targar[4]={0,0,0,0};	   /* target 128-bit */
     90      1.1  mrg   #define targhi targar[3]	   /* name the word with the sign */
     91      1.1  mrg   #define targmh targar[2]	   /* name the words */
     92      1.1  mrg   #define targml targar[1]	   /* .. */
     93      1.1  mrg   #define targlo targar[0]	   /* .. */
     94      1.1  mrg 
     95      1.1  mrg   /* If the number has too many digits, or the exponent could be */
     96      1.1  mrg   /* out of range then reduce the number under the appropriate */
     97      1.1  mrg   /* constraints.  This could push the number to Infinity or zero, */
     98      1.1  mrg   /* so this check and rounding must be done before generating the */
     99      1.1  mrg   /* decimal128] */
    100      1.1  mrg   ae=dn->exponent+dn->digits-1; 	     /* [0 if special] */
    101      1.1  mrg   if (dn->digits>DECIMAL128_Pmax	     /* too many digits */
    102      1.1  mrg    || ae>DECIMAL128_Emax		     /* likely overflow */
    103      1.1  mrg    || ae<DECIMAL128_Emin) {		     /* likely underflow */
    104      1.1  mrg     decContextDefault(&dc, DEC_INIT_DECIMAL128); /* [no traps] */
    105      1.1  mrg     dc.round=set->round;		     /* use supplied rounding */
    106      1.1  mrg     decNumberPlus(&dw, dn, &dc);	     /* (round and check) */
    107      1.1  mrg     /* [this changes -0 to 0, so enforce the sign...] */
    108      1.1  mrg     dw.bits|=dn->bits&DECNEG;
    109      1.1  mrg     status=dc.status;			     /* save status */
    110      1.1  mrg     dn=&dw;				     /* use the work number */
    111      1.1  mrg     } /* maybe out of range */
    112      1.1  mrg 
    113      1.1  mrg   if (dn->bits&DECSPECIAL) {			  /* a special value */
    114      1.1  mrg     if (dn->bits&DECINF) targhi=DECIMAL_Inf<<24;
    115      1.1  mrg      else {					  /* sNaN or qNaN */
    116      1.1  mrg       if ((*dn->lsu!=0 || dn->digits>1) 	  /* non-zero coefficient */
    117      1.1  mrg        && (dn->digits<DECIMAL128_Pmax)) {	  /* coefficient fits */
    118      1.1  mrg 	decDigitsToDPD(dn, targar, 0);
    119      1.1  mrg 	}
    120      1.1  mrg       if (dn->bits&DECNAN) targhi|=DECIMAL_NaN<<24;
    121      1.1  mrg        else targhi|=DECIMAL_sNaN<<24;
    122      1.1  mrg       } /* a NaN */
    123      1.1  mrg     } /* special */
    124      1.1  mrg 
    125      1.1  mrg    else { /* is finite */
    126      1.1  mrg     if (decNumberIsZero(dn)) {		     /* is a zero */
    127      1.1  mrg       /* set and clamp exponent */
    128      1.1  mrg       if (dn->exponent<-DECIMAL128_Bias) {
    129      1.1  mrg 	exp=0;				     /* low clamp */
    130      1.1  mrg 	status|=DEC_Clamped;
    131      1.1  mrg 	}
    132      1.1  mrg        else {
    133      1.1  mrg 	exp=dn->exponent+DECIMAL128_Bias;    /* bias exponent */
    134      1.1  mrg 	if (exp>DECIMAL128_Ehigh) {	     /* top clamp */
    135      1.1  mrg 	  exp=DECIMAL128_Ehigh;
    136      1.1  mrg 	  status|=DEC_Clamped;
    137      1.1  mrg 	  }
    138      1.1  mrg 	}
    139      1.1  mrg       comb=(exp>>9) & 0x18;		/* msd=0, exp top 2 bits .. */
    140      1.1  mrg       }
    141      1.1  mrg      else {				/* non-zero finite number */
    142      1.1  mrg       uInt msd; 			/* work */
    143      1.1  mrg       Int pad=0;			/* coefficient pad digits */
    144      1.1  mrg 
    145      1.1  mrg       /* the dn is known to fit, but it may need to be padded */
    146      1.1  mrg       exp=(uInt)(dn->exponent+DECIMAL128_Bias);    /* bias exponent */
    147      1.1  mrg       if (exp>DECIMAL128_Ehigh) {		   /* fold-down case */
    148      1.1  mrg 	pad=exp-DECIMAL128_Ehigh;
    149      1.1  mrg 	exp=DECIMAL128_Ehigh;			   /* [to maximum] */
    150      1.1  mrg 	status|=DEC_Clamped;
    151      1.1  mrg 	}
    152      1.1  mrg 
    153      1.1  mrg       /* [fastpath for common case is not a win, here] */
    154      1.1  mrg       decDigitsToDPD(dn, targar, pad);
    155      1.1  mrg       /* save and clear the top digit */
    156      1.1  mrg       msd=targhi>>14;
    157      1.1  mrg       targhi&=0x00003fff;
    158      1.1  mrg 
    159      1.1  mrg       /* create the combination field */
    160      1.1  mrg       if (msd>=8) comb=0x18 | ((exp>>11) & 0x06) | (msd & 0x01);
    161      1.1  mrg 	     else comb=((exp>>9) & 0x18) | msd;
    162      1.1  mrg       }
    163      1.1  mrg     targhi|=comb<<26;		   /* add combination field .. */
    164      1.1  mrg     targhi|=(exp&0xfff)<<14;	   /* .. and exponent continuation */
    165      1.1  mrg     } /* finite */
    166      1.1  mrg 
    167      1.1  mrg   if (dn->bits&DECNEG) targhi|=0x80000000; /* add sign bit */
    168      1.1  mrg 
    169      1.1  mrg   /* now write to storage; this is endian */
    170      1.1  mrg   if (DECLITEND) {
    171      1.1  mrg     /* lo -> hi */
    172      1.1  mrg     UBFROMUI(d128->bytes,    targlo);
    173      1.1  mrg     UBFROMUI(d128->bytes+4,  targml);
    174      1.1  mrg     UBFROMUI(d128->bytes+8,  targmh);
    175      1.1  mrg     UBFROMUI(d128->bytes+12, targhi);
    176      1.1  mrg     }
    177      1.1  mrg    else {
    178      1.1  mrg     /* hi -> lo */
    179      1.1  mrg     UBFROMUI(d128->bytes,    targhi);
    180      1.1  mrg     UBFROMUI(d128->bytes+4,  targmh);
    181      1.1  mrg     UBFROMUI(d128->bytes+8,  targml);
    182      1.1  mrg     UBFROMUI(d128->bytes+12, targlo);
    183      1.1  mrg     }
    184      1.1  mrg 
    185      1.1  mrg   if (status!=0) decContextSetStatus(set, status); /* pass on status */
    186      1.1  mrg   /* decimal128Show(d128); */
    187      1.1  mrg   return d128;
    188      1.1  mrg   } /* decimal128FromNumber */
    189      1.1  mrg 
    190      1.1  mrg /* ------------------------------------------------------------------ */
    191      1.1  mrg /* decimal128ToNumber -- convert decimal128 to decNumber	      */
    192      1.1  mrg /*   d128 is the source decimal128				      */
    193      1.1  mrg /*   dn is the target number, with appropriate space		      */
    194      1.1  mrg /* No error is possible.					      */
    195      1.1  mrg /* ------------------------------------------------------------------ */
    196      1.1  mrg decNumber * decimal128ToNumber(const decimal128 *d128, decNumber *dn) {
    197      1.1  mrg   uInt msd;			   /* coefficient MSD */
    198      1.1  mrg   uInt exp;			   /* exponent top two bits */
    199      1.1  mrg   uInt comb;			   /* combination field */
    200      1.1  mrg   Int  need;			   /* work */
    201      1.1  mrg   uInt uiwork;			   /* for macros */
    202      1.1  mrg   uInt sourar[4];		   /* source 128-bit */
    203      1.1  mrg   #define sourhi sourar[3]	   /* name the word with the sign */
    204      1.1  mrg   #define sourmh sourar[2]	   /* and the mid-high word */
    205      1.1  mrg   #define sourml sourar[1]	   /* and the mod-low word */
    206      1.1  mrg   #define sourlo sourar[0]	   /* and the lowest word */
    207      1.1  mrg 
    208      1.1  mrg   /* load source from storage; this is endian */
    209      1.1  mrg   if (DECLITEND) {
    210      1.1  mrg     sourlo=UBTOUI(d128->bytes	); /* directly load the low int */
    211      1.1  mrg     sourml=UBTOUI(d128->bytes+4 ); /* then the mid-low */
    212      1.1  mrg     sourmh=UBTOUI(d128->bytes+8 ); /* then the mid-high */
    213      1.1  mrg     sourhi=UBTOUI(d128->bytes+12); /* then the high int */
    214      1.1  mrg     }
    215      1.1  mrg    else {
    216      1.1  mrg     sourhi=UBTOUI(d128->bytes	); /* directly load the high int */
    217      1.1  mrg     sourmh=UBTOUI(d128->bytes+4 ); /* then the mid-high */
    218      1.1  mrg     sourml=UBTOUI(d128->bytes+8 ); /* then the mid-low */
    219      1.1  mrg     sourlo=UBTOUI(d128->bytes+12); /* then the low int */
    220      1.1  mrg     }
    221      1.1  mrg 
    222      1.1  mrg   comb=(sourhi>>26)&0x1f;	   /* combination field */
    223      1.1  mrg 
    224      1.1  mrg   decNumberZero(dn);		   /* clean number */
    225      1.1  mrg   if (sourhi&0x80000000) dn->bits=DECNEG; /* set sign if negative */
    226      1.1  mrg 
    227      1.1  mrg   msd=COMBMSD[comb];		   /* decode the combination field */
    228      1.1  mrg   exp=COMBEXP[comb];		   /* .. */
    229      1.1  mrg 
    230      1.1  mrg   if (exp==3) { 		   /* is a special */
    231      1.1  mrg     if (msd==0) {
    232      1.1  mrg       dn->bits|=DECINF;
    233      1.1  mrg       return dn;		   /* no coefficient needed */
    234      1.1  mrg       }
    235      1.1  mrg     else if (sourhi&0x02000000) dn->bits|=DECSNAN;
    236      1.1  mrg     else dn->bits|=DECNAN;
    237      1.1  mrg     msd=0;			   /* no top digit */
    238      1.1  mrg     }
    239      1.1  mrg    else {			   /* is a finite number */
    240      1.1  mrg     dn->exponent=(exp<<12)+((sourhi>>14)&0xfff)-DECIMAL128_Bias; /* unbiased */
    241      1.1  mrg     }
    242      1.1  mrg 
    243      1.1  mrg   /* get the coefficient */
    244      1.1  mrg   sourhi&=0x00003fff;		   /* clean coefficient continuation */
    245      1.1  mrg   if (msd) {			   /* non-zero msd */
    246      1.1  mrg     sourhi|=msd<<14;		   /* prefix to coefficient */
    247      1.1  mrg     need=12;			   /* process 12 declets */
    248      1.1  mrg     }
    249      1.1  mrg    else { /* msd=0 */
    250      1.1  mrg     if (sourhi) need=11;	   /* declets to process */
    251      1.1  mrg      else if (sourmh) need=10;
    252      1.1  mrg      else if (sourml) need=7;
    253      1.1  mrg      else if (sourlo) need=4;
    254      1.1  mrg      else return dn;		   /* easy: coefficient is 0 */
    255      1.1  mrg     } /*msd=0 */
    256      1.1  mrg 
    257      1.1  mrg   decDigitsFromDPD(dn, sourar, need);	/* process declets */
    258      1.1  mrg   /* decNumberShow(dn); */
    259      1.1  mrg   return dn;
    260      1.1  mrg   } /* decimal128ToNumber */
    261      1.1  mrg 
    262      1.1  mrg /* ------------------------------------------------------------------ */
    263      1.1  mrg /* to-scientific-string -- conversion to numeric string 	      */
    264      1.1  mrg /* to-engineering-string -- conversion to numeric string	      */
    265      1.1  mrg /*								      */
    266      1.1  mrg /*   decimal128ToString(d128, string);				      */
    267      1.1  mrg /*   decimal128ToEngString(d128, string);			      */
    268      1.1  mrg /*								      */
    269      1.1  mrg /*  d128 is the decimal128 format number to convert		      */
    270      1.1  mrg /*  string is the string where the result will be laid out	      */
    271      1.1  mrg /*								      */
    272      1.1  mrg /*  string must be at least 24 characters			      */
    273      1.1  mrg /*								      */
    274      1.1  mrg /*  No error is possible, and no status can be set.		      */
    275      1.1  mrg /* ------------------------------------------------------------------ */
    276      1.1  mrg char * decimal128ToEngString(const decimal128 *d128, char *string){
    277      1.1  mrg   decNumber dn; 			/* work */
    278      1.1  mrg   decimal128ToNumber(d128, &dn);
    279      1.1  mrg   decNumberToEngString(&dn, string);
    280      1.1  mrg   return string;
    281      1.1  mrg   } /* decimal128ToEngString */
    282      1.1  mrg 
    283      1.1  mrg char * decimal128ToString(const decimal128 *d128, char *string){
    284      1.1  mrg   uInt msd;			   /* coefficient MSD */
    285      1.1  mrg   Int  exp;			   /* exponent top two bits or full */
    286      1.1  mrg   uInt comb;			   /* combination field */
    287      1.1  mrg   char *cstart; 		   /* coefficient start */
    288      1.1  mrg   char *c;			   /* output pointer in string */
    289      1.1  mrg   const uByte *u;		   /* work */
    290      1.1  mrg   char *s, *t;			   /* .. (source, target) */
    291      1.1  mrg   Int  dpd;			   /* .. */
    292      1.1  mrg   Int  pre, e;			   /* .. */
    293      1.1  mrg   uInt uiwork;			   /* for macros */
    294      1.1  mrg 
    295      1.1  mrg   uInt sourar[4];		   /* source 128-bit */
    296      1.1  mrg   #define sourhi sourar[3]	   /* name the word with the sign */
    297      1.1  mrg   #define sourmh sourar[2]	   /* and the mid-high word */
    298      1.1  mrg   #define sourml sourar[1]	   /* and the mod-low word */
    299      1.1  mrg   #define sourlo sourar[0]	   /* and the lowest word */
    300      1.1  mrg 
    301      1.1  mrg   /* load source from storage; this is endian */
    302      1.1  mrg   if (DECLITEND) {
    303      1.1  mrg     sourlo=UBTOUI(d128->bytes	); /* directly load the low int */
    304      1.1  mrg     sourml=UBTOUI(d128->bytes+4 ); /* then the mid-low */
    305      1.1  mrg     sourmh=UBTOUI(d128->bytes+8 ); /* then the mid-high */
    306      1.1  mrg     sourhi=UBTOUI(d128->bytes+12); /* then the high int */
    307      1.1  mrg     }
    308      1.1  mrg    else {
    309      1.1  mrg     sourhi=UBTOUI(d128->bytes	); /* directly load the high int */
    310      1.1  mrg     sourmh=UBTOUI(d128->bytes+4 ); /* then the mid-high */
    311      1.1  mrg     sourml=UBTOUI(d128->bytes+8 ); /* then the mid-low */
    312      1.1  mrg     sourlo=UBTOUI(d128->bytes+12); /* then the low int */
    313      1.1  mrg     }
    314      1.1  mrg 
    315      1.1  mrg   c=string;			   /* where result will go */
    316      1.1  mrg   if (((Int)sourhi)<0) *c++='-';   /* handle sign */
    317      1.1  mrg 
    318      1.1  mrg   comb=(sourhi>>26)&0x1f;	   /* combination field */
    319      1.1  mrg   msd=COMBMSD[comb];		   /* decode the combination field */
    320      1.1  mrg   exp=COMBEXP[comb];		   /* .. */
    321      1.1  mrg 
    322      1.1  mrg   if (exp==3) {
    323      1.1  mrg     if (msd==0) {		   /* infinity */
    324      1.1  mrg       strcpy(c,   "Inf");
    325      1.1  mrg       strcpy(c+3, "inity");
    326      1.1  mrg       return string;		   /* easy */
    327      1.1  mrg       }
    328      1.1  mrg     if (sourhi&0x02000000) *c++='s'; /* sNaN */
    329      1.1  mrg     strcpy(c, "NaN");		   /* complete word */
    330      1.1  mrg     c+=3;			   /* step past */
    331      1.1  mrg     if (sourlo==0 && sourml==0 && sourmh==0
    332      1.1  mrg      && (sourhi&0x0003ffff)==0) return string; /* zero payload */
    333      1.1  mrg     /* otherwise drop through to add integer; set correct exp */
    334      1.1  mrg     exp=0; msd=0;		   /* setup for following code */
    335      1.1  mrg     }
    336      1.1  mrg    else exp=(exp<<12)+((sourhi>>14)&0xfff)-DECIMAL128_Bias; /* unbiased */
    337      1.1  mrg 
    338      1.1  mrg   /* convert 34 digits of significand to characters */
    339      1.1  mrg   cstart=c;			   /* save start of coefficient */
    340      1.1  mrg   if (msd) *c++='0'+(char)msd;	   /* non-zero most significant digit */
    341      1.1  mrg 
    342      1.1  mrg   /* Now decode the declets.  After extracting each one, it is */
    343      1.1  mrg   /* decoded to binary and then to a 4-char sequence by table lookup; */
    344      1.1  mrg   /* the 4-chars are a 1-char length (significant digits, except 000 */
    345      1.1  mrg   /* has length 0).  This allows us to left-align the first declet */
    346      1.1  mrg   /* with non-zero content, then remaining ones are full 3-char */
    347      1.1  mrg   /* length.  We use fixed-length memcpys because variable-length */
    348      1.1  mrg   /* causes a subroutine call in GCC.  (These are length 4 for speed */
    349      1.1  mrg   /* and are safe because the array has an extra terminator byte.) */
    350      1.1  mrg   #define dpd2char u=&BIN2CHAR[DPD2BIN[dpd]*4]; 		  \
    351      1.1  mrg 		   if (c!=cstart) {memcpy(c, u+1, 4); c+=3;}	  \
    352      1.1  mrg 		    else if (*u)  {memcpy(c, u+4-*u, 4); c+=*u;}
    353      1.1  mrg   dpd=(sourhi>>4)&0x3ff;		     /* declet 1 */
    354      1.1  mrg   dpd2char;
    355      1.1  mrg   dpd=((sourhi&0xf)<<6) | (sourmh>>26);      /* declet 2 */
    356      1.1  mrg   dpd2char;
    357      1.1  mrg   dpd=(sourmh>>16)&0x3ff;		     /* declet 3 */
    358      1.1  mrg   dpd2char;
    359      1.1  mrg   dpd=(sourmh>>6)&0x3ff;		     /* declet 4 */
    360      1.1  mrg   dpd2char;
    361      1.1  mrg   dpd=((sourmh&0x3f)<<4) | (sourml>>28);     /* declet 5 */
    362      1.1  mrg   dpd2char;
    363      1.1  mrg   dpd=(sourml>>18)&0x3ff;		     /* declet 6 */
    364      1.1  mrg   dpd2char;
    365      1.1  mrg   dpd=(sourml>>8)&0x3ff;		     /* declet 7 */
    366      1.1  mrg   dpd2char;
    367      1.1  mrg   dpd=((sourml&0xff)<<2) | (sourlo>>30);     /* declet 8 */
    368      1.1  mrg   dpd2char;
    369      1.1  mrg   dpd=(sourlo>>20)&0x3ff;		     /* declet 9 */
    370      1.1  mrg   dpd2char;
    371      1.1  mrg   dpd=(sourlo>>10)&0x3ff;		     /* declet 10 */
    372      1.1  mrg   dpd2char;
    373      1.1  mrg   dpd=(sourlo)&0x3ff;			     /* declet 11 */
    374      1.1  mrg   dpd2char;
    375      1.1  mrg 
    376      1.1  mrg   if (c==cstart) *c++='0';	   /* all zeros -- make 0 */
    377      1.1  mrg 
    378      1.1  mrg   if (exp==0) { 		   /* integer or NaN case -- easy */
    379      1.1  mrg     *c='\0';			   /* terminate */
    380      1.1  mrg     return string;
    381      1.1  mrg     }
    382      1.1  mrg 
    383      1.1  mrg   /* non-0 exponent */
    384      1.1  mrg   e=0;				   /* assume no E */
    385      1.1  mrg   pre=c-cstart+exp;
    386      1.1  mrg   /* [here, pre-exp is the digits count (==1 for zero)] */
    387      1.1  mrg   if (exp>0 || pre<-5) {	   /* need exponential form */
    388      1.1  mrg     e=pre-1;			   /* calculate E value */
    389      1.1  mrg     pre=1;			   /* assume one digit before '.' */
    390      1.1  mrg     } /* exponential form */
    391      1.1  mrg 
    392      1.1  mrg   /* modify the coefficient, adding 0s, '.', and E+nn as needed */
    393      1.1  mrg   s=c-1;			   /* source (LSD) */
    394      1.1  mrg   if (pre>0) {			   /* ddd.ddd (plain), perhaps with E */
    395      1.1  mrg     char *dotat=cstart+pre;
    396      1.1  mrg     if (dotat<c) {		   /* if embedded dot needed... */
    397      1.1  mrg       t=c;				/* target */
    398      1.1  mrg       for (; s>=dotat; s--, t--) *t=*s; /* open the gap; leave t at gap */
    399      1.1  mrg       *t='.';				/* insert the dot */
    400      1.1  mrg       c++;				/* length increased by one */
    401      1.1  mrg       }
    402      1.1  mrg 
    403      1.1  mrg     /* finally add the E-part, if needed; it will never be 0, and has */
    404      1.1  mrg     /* a maximum length of 4 digits */
    405      1.1  mrg     if (e!=0) {
    406      1.1  mrg       *c++='E'; 		   /* starts with E */
    407      1.1  mrg       *c++='+'; 		   /* assume positive */
    408      1.1  mrg       if (e<0) {
    409      1.1  mrg 	*(c-1)='-';		   /* oops, need '-' */
    410      1.1  mrg 	e=-e;			   /* uInt, please */
    411      1.1  mrg 	}
    412      1.1  mrg       if (e<1000) {		   /* 3 (or fewer) digits case */
    413      1.1  mrg 	u=&BIN2CHAR[e*4];	   /* -> length byte */
    414      1.1  mrg 	memcpy(c, u+4-*u, 4);	   /* copy fixed 4 characters [is safe] */
    415      1.1  mrg 	c+=*u;			   /* bump pointer appropriately */
    416      1.1  mrg 	}
    417      1.1  mrg        else {			   /* 4-digits */
    418      1.1  mrg 	Int thou=((e>>3)*1049)>>17; /* e/1000 */
    419      1.1  mrg 	Int rem=e-(1000*thou);	    /* e%1000 */
    420      1.1  mrg 	*c++='0'+(char)thou;
    421      1.1  mrg 	u=&BIN2CHAR[rem*4];	   /* -> length byte */
    422      1.1  mrg 	memcpy(c, u+1, 4);	   /* copy fixed 3+1 characters [is safe] */
    423      1.1  mrg 	c+=3;			   /* bump pointer, always 3 digits */
    424      1.1  mrg 	}
    425      1.1  mrg       }
    426      1.1  mrg     *c='\0';			   /* add terminator */
    427      1.1  mrg     /*printf("res %s\n", string); */
    428      1.1  mrg     return string;
    429      1.1  mrg     } /* pre>0 */
    430      1.1  mrg 
    431      1.1  mrg   /* -5<=pre<=0: here for plain 0.ddd or 0.000ddd forms (can never have E) */
    432      1.1  mrg   t=c+1-pre;
    433      1.1  mrg   *(t+1)='\0';				/* can add terminator now */
    434      1.1  mrg   for (; s>=cstart; s--, t--) *t=*s;	/* shift whole coefficient right */
    435      1.1  mrg   c=cstart;
    436      1.1  mrg   *c++='0';				/* always starts with 0. */
    437      1.1  mrg   *c++='.';
    438      1.1  mrg   for (; pre<0; pre++) *c++='0';	/* add any 0's after '.' */
    439      1.1  mrg   /*printf("res %s\n", string); */
    440      1.1  mrg   return string;
    441      1.1  mrg   } /* decimal128ToString */
    442      1.1  mrg 
    443      1.1  mrg /* ------------------------------------------------------------------ */
    444      1.1  mrg /* to-number -- conversion from numeric string			      */
    445      1.1  mrg /*								      */
    446      1.1  mrg /*   decimal128FromString(result, string, set); 		      */
    447      1.1  mrg /*								      */
    448      1.1  mrg /*  result  is the decimal128 format number which gets the result of  */
    449      1.1  mrg /*	    the conversion					      */
    450      1.1  mrg /*  *string is the character string which should contain a valid      */
    451      1.1  mrg /*	    number (which may be a special value)		      */
    452      1.1  mrg /*  set     is the context					      */
    453      1.1  mrg /*								      */
    454      1.1  mrg /* The context is supplied to this routine is used for error handling */
    455      1.1  mrg /* (setting of status and traps) and for the rounding mode, only.     */
    456      1.1  mrg /* If an error occurs, the result will be a valid decimal128 NaN.     */
    457      1.1  mrg /* ------------------------------------------------------------------ */
    458      1.1  mrg decimal128 * decimal128FromString(decimal128 *result, const char *string,
    459      1.1  mrg 				  decContext *set) {
    460      1.1  mrg   decContext dc;			     /* work */
    461      1.1  mrg   decNumber dn; 			     /* .. */
    462      1.1  mrg 
    463      1.1  mrg   decContextDefault(&dc, DEC_INIT_DECIMAL128); /* no traps, please */
    464      1.1  mrg   dc.round=set->round;			       /* use supplied rounding */
    465      1.1  mrg 
    466      1.1  mrg   decNumberFromString(&dn, string, &dc);     /* will round if needed */
    467      1.1  mrg   decimal128FromNumber(result, &dn, &dc);
    468      1.1  mrg   if (dc.status!=0) {			     /* something happened */
    469      1.1  mrg     decContextSetStatus(set, dc.status);     /* .. pass it on */
    470      1.1  mrg     }
    471      1.1  mrg   return result;
    472      1.1  mrg   } /* decimal128FromString */
    473      1.1  mrg 
    474      1.1  mrg /* ------------------------------------------------------------------ */
    475      1.1  mrg /* decimal128IsCanonical -- test whether encoding is canonical	      */
    476      1.1  mrg /*   d128 is the source decimal128				      */
    477      1.1  mrg /*   returns 1 if the encoding of d128 is canonical, 0 otherwise      */
    478      1.1  mrg /* No error is possible.					      */
    479      1.1  mrg /* ------------------------------------------------------------------ */
    480      1.1  mrg uInt decimal128IsCanonical(const decimal128 *d128) {
    481      1.1  mrg   decNumber dn; 			/* work */
    482      1.1  mrg   decimal128 canon;			 /* .. */
    483      1.1  mrg   decContext dc;			/* .. */
    484      1.1  mrg   decContextDefault(&dc, DEC_INIT_DECIMAL128);
    485      1.1  mrg   decimal128ToNumber(d128, &dn);
    486      1.1  mrg   decimal128FromNumber(&canon, &dn, &dc);/* canon will now be canonical */
    487      1.1  mrg   return memcmp(d128, &canon, DECIMAL128_Bytes)==0;
    488      1.1  mrg   } /* decimal128IsCanonical */
    489      1.1  mrg 
    490      1.1  mrg /* ------------------------------------------------------------------ */
    491      1.1  mrg /* decimal128Canonical -- copy an encoding, ensuring it is canonical  */
    492      1.1  mrg /*   d128 is the source decimal128				      */
    493      1.1  mrg /*   result is the target (may be the same decimal128)		      */
    494      1.1  mrg /*   returns result						      */
    495      1.1  mrg /* No error is possible.					      */
    496      1.1  mrg /* ------------------------------------------------------------------ */
    497      1.1  mrg decimal128 * decimal128Canonical(decimal128 *result, const decimal128 *d128) {
    498      1.1  mrg   decNumber dn; 			/* work */
    499      1.1  mrg   decContext dc;			/* .. */
    500      1.1  mrg   decContextDefault(&dc, DEC_INIT_DECIMAL128);
    501      1.1  mrg   decimal128ToNumber(d128, &dn);
    502      1.1  mrg   decimal128FromNumber(result, &dn, &dc);/* result will now be canonical */
    503      1.1  mrg   return result;
    504      1.1  mrg   } /* decimal128Canonical */
    505      1.1  mrg 
    506      1.1  mrg #if DECTRACE || DECCHECK
    507      1.1  mrg /* Macros for accessing decimal128 fields.  These assume the argument
    508      1.1  mrg    is a reference (pointer) to the decimal128 structure, and the
    509      1.1  mrg    decimal128 is in network byte order (big-endian) */
    510      1.1  mrg /* Get sign */
    511      1.1  mrg #define decimal128Sign(d)	((unsigned)(d)->bytes[0]>>7)
    512      1.1  mrg 
    513      1.1  mrg /* Get combination field */
    514      1.1  mrg #define decimal128Comb(d)	(((d)->bytes[0] & 0x7c)>>2)
    515      1.1  mrg 
    516      1.1  mrg /* Get exponent continuation [does not remove bias] */
    517      1.1  mrg #define decimal128ExpCon(d)	((((d)->bytes[0] & 0x03)<<10)	      \
    518      1.1  mrg 			      | ((unsigned)(d)->bytes[1]<<2)	      \
    519      1.1  mrg 			      | ((unsigned)(d)->bytes[2]>>6))
    520      1.1  mrg 
    521      1.1  mrg /* Set sign [this assumes sign previously 0] */
    522      1.1  mrg #define decimal128SetSign(d, b) {				      \
    523      1.1  mrg   (d)->bytes[0]|=((unsigned)(b)<<7);}
    524      1.1  mrg 
    525      1.1  mrg /* Set exponent continuation [does not apply bias] */
    526      1.1  mrg /* This assumes range has been checked and exponent previously 0; */
    527      1.1  mrg /* type of exponent must be unsigned */
    528      1.1  mrg #define decimal128SetExpCon(d, e) {				      \
    529      1.1  mrg   (d)->bytes[0]|=(uByte)((e)>>10);				      \
    530      1.1  mrg   (d)->bytes[1] =(uByte)(((e)&0x3fc)>>2);			      \
    531      1.1  mrg   (d)->bytes[2]|=(uByte)(((e)&0x03)<<6);}
    532      1.1  mrg 
    533      1.1  mrg /* ------------------------------------------------------------------ */
    534      1.1  mrg /* decimal128Show -- display a decimal128 in hexadecimal [debug aid]  */
    535      1.1  mrg /*   d128 -- the number to show 				      */
    536      1.1  mrg /* ------------------------------------------------------------------ */
    537      1.1  mrg /* Also shows sign/cob/expconfields extracted */
    538      1.1  mrg void decimal128Show(const decimal128 *d128) {
    539      1.1  mrg   char buf[DECIMAL128_Bytes*2+1];
    540      1.1  mrg   Int i, j=0;
    541      1.1  mrg 
    542      1.1  mrg   if (DECLITEND) {
    543      1.1  mrg     for (i=0; i<DECIMAL128_Bytes; i++, j+=2) {
    544      1.1  mrg       sprintf(&buf[j], "%02x", d128->bytes[15-i]);
    545      1.1  mrg       }
    546      1.1  mrg     printf(" D128> %s [S:%d Cb:%02x Ec:%02x] LittleEndian\n", buf,
    547      1.1  mrg 	   d128->bytes[15]>>7, (d128->bytes[15]>>2)&0x1f,
    548      1.1  mrg 	   ((d128->bytes[15]&0x3)<<10)|(d128->bytes[14]<<2)|
    549      1.1  mrg 	   (d128->bytes[13]>>6));
    550      1.1  mrg     }
    551      1.1  mrg    else {
    552      1.1  mrg     for (i=0; i<DECIMAL128_Bytes; i++, j+=2) {
    553      1.1  mrg       sprintf(&buf[j], "%02x", d128->bytes[i]);
    554      1.1  mrg       }
    555      1.1  mrg     printf(" D128> %s [S:%d Cb:%02x Ec:%02x] BigEndian\n", buf,
    556      1.1  mrg 	   decimal128Sign(d128), decimal128Comb(d128),
    557      1.1  mrg 	   decimal128ExpCon(d128));
    558      1.1  mrg     }
    559      1.1  mrg   } /* decimal128Show */
    560      1.1  mrg #endif
    561