Home | History | Annotate | Line # | Download | only in dpd
      1       1.1  mrg /* Decimal 64-bit format module for the decNumber C Library.
      2  1.1.1.12  mrg    Copyright (C) 2005-2024 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 64-bit format module 				      */
     28       1.1  mrg /* ------------------------------------------------------------------ */
     29       1.1  mrg /* This module comprises the routines for decimal64 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 16      /* make decNumbers with space for 16 */
     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 "decimal64.h"	      /* our primary include */
     45       1.1  mrg 
     46       1.1  mrg /* Utility routines and tables [in decimal64.c]; externs for 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];
     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 decimal64Show(const decimal64 *);		  /* 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 /* define and include the tables to use for conversions */
     65       1.1  mrg #define DEC_BIN2CHAR 1
     66       1.1  mrg #define DEC_DPD2BIN  1
     67       1.1  mrg #define DEC_BIN2DPD  1		   /* used for all sizes */
     68       1.1  mrg #include "decDPD.h"		   /* lookup tables */
     69       1.1  mrg 
     70       1.1  mrg /* ------------------------------------------------------------------ */
     71       1.1  mrg /* decimal64FromNumber -- convert decNumber to decimal64	      */
     72       1.1  mrg /*								      */
     73       1.1  mrg /*   ds is the target decimal64 				      */
     74       1.1  mrg /*   dn is the source number (assumed valid)			      */
     75       1.1  mrg /*   set is the context, used only for reporting errors 	      */
     76       1.1  mrg /*								      */
     77       1.1  mrg /* The set argument is used only for status reporting and for the     */
     78       1.1  mrg /* rounding mode (used if the coefficient is more than DECIMAL64_Pmax */
     79       1.1  mrg /* digits or an overflow is detected).	If the exponent is out of the */
     80       1.1  mrg /* valid range then Overflow or Underflow will be raised.	      */
     81       1.1  mrg /* After Underflow a subnormal result is possible.		      */
     82       1.1  mrg /*								      */
     83       1.1  mrg /* DEC_Clamped is set if the number has to be 'folded down' to fit,   */
     84       1.1  mrg /* by reducing its exponent and multiplying the coefficient by a      */
     85       1.1  mrg /* power of ten, or if the exponent on a zero had to be clamped.      */
     86       1.1  mrg /* ------------------------------------------------------------------ */
     87       1.1  mrg decimal64 * decimal64FromNumber(decimal64 *d64, const decNumber *dn,
     88       1.1  mrg 				decContext *set) {
     89       1.1  mrg   uInt status=0;		   /* status accumulator */
     90       1.1  mrg   Int ae;			   /* adjusted exponent */
     91       1.1  mrg   decNumber  dw;		   /* work */
     92       1.1  mrg   decContext dc;		   /* .. */
     93       1.1  mrg   uInt comb, exp;		   /* .. */
     94       1.1  mrg   uInt uiwork;			   /* for macros */
     95       1.1  mrg   uInt targar[2]={0, 0};	   /* target 64-bit */
     96       1.1  mrg   #define targhi targar[1]	   /* name the word with the sign */
     97       1.1  mrg   #define targlo targar[0]	   /* and the other */
     98       1.1  mrg 
     99       1.1  mrg   /* If the number has too many digits, or the exponent could be */
    100       1.1  mrg   /* out of range then reduce the number under the appropriate */
    101       1.1  mrg   /* constraints.  This could push the number to Infinity or zero, */
    102       1.1  mrg   /* so this check and rounding must be done before generating the */
    103       1.1  mrg   /* decimal64] */
    104       1.1  mrg   ae=dn->exponent+dn->digits-1; 	     /* [0 if special] */
    105       1.1  mrg   if (dn->digits>DECIMAL64_Pmax 	     /* too many digits */
    106       1.1  mrg    || ae>DECIMAL64_Emax 		     /* likely overflow */
    107       1.1  mrg    || ae<DECIMAL64_Emin) {		     /* likely underflow */
    108       1.1  mrg     decContextDefault(&dc, DEC_INIT_DECIMAL64); /* [no traps] */
    109       1.1  mrg     dc.round=set->round;		     /* use supplied rounding */
    110       1.1  mrg     decNumberPlus(&dw, dn, &dc);	     /* (round and check) */
    111       1.1  mrg     /* [this changes -0 to 0, so enforce the sign...] */
    112       1.1  mrg     dw.bits|=dn->bits&DECNEG;
    113       1.1  mrg     status=dc.status;			     /* save status */
    114       1.1  mrg     dn=&dw;				     /* use the work number */
    115       1.1  mrg     } /* maybe out of range */
    116       1.1  mrg 
    117       1.1  mrg   if (dn->bits&DECSPECIAL) {			  /* a special value */
    118       1.1  mrg     if (dn->bits&DECINF) targhi=DECIMAL_Inf<<24;
    119       1.1  mrg      else {					  /* sNaN or qNaN */
    120       1.1  mrg       if ((*dn->lsu!=0 || dn->digits>1) 	  /* non-zero coefficient */
    121       1.1  mrg        && (dn->digits<DECIMAL64_Pmax)) {	  /* coefficient fits */
    122       1.1  mrg 	decDigitsToDPD(dn, targar, 0);
    123       1.1  mrg 	}
    124       1.1  mrg       if (dn->bits&DECNAN) targhi|=DECIMAL_NaN<<24;
    125       1.1  mrg        else targhi|=DECIMAL_sNaN<<24;
    126       1.1  mrg       } /* a NaN */
    127       1.1  mrg     } /* special */
    128       1.1  mrg 
    129       1.1  mrg    else { /* is finite */
    130       1.1  mrg     if (decNumberIsZero(dn)) {		     /* is a zero */
    131       1.1  mrg       /* set and clamp exponent */
    132       1.1  mrg       if (dn->exponent<-DECIMAL64_Bias) {
    133       1.1  mrg 	exp=0;				     /* low clamp */
    134       1.1  mrg 	status|=DEC_Clamped;
    135       1.1  mrg 	}
    136       1.1  mrg        else {
    137       1.1  mrg 	exp=dn->exponent+DECIMAL64_Bias;     /* bias exponent */
    138       1.1  mrg 	if (exp>DECIMAL64_Ehigh) {	     /* top clamp */
    139       1.1  mrg 	  exp=DECIMAL64_Ehigh;
    140       1.1  mrg 	  status|=DEC_Clamped;
    141       1.1  mrg 	  }
    142       1.1  mrg 	}
    143       1.1  mrg       comb=(exp>>5) & 0x18;		/* msd=0, exp top 2 bits .. */
    144       1.1  mrg       }
    145       1.1  mrg      else {				/* non-zero finite number */
    146       1.1  mrg       uInt msd; 			/* work */
    147       1.1  mrg       Int pad=0;			/* coefficient pad digits */
    148       1.1  mrg 
    149       1.1  mrg       /* the dn is known to fit, but it may need to be padded */
    150       1.1  mrg       exp=(uInt)(dn->exponent+DECIMAL64_Bias);	  /* bias exponent */
    151       1.1  mrg       if (exp>DECIMAL64_Ehigh) {		  /* fold-down case */
    152       1.1  mrg 	pad=exp-DECIMAL64_Ehigh;
    153       1.1  mrg 	exp=DECIMAL64_Ehigh;			  /* [to maximum] */
    154       1.1  mrg 	status|=DEC_Clamped;
    155       1.1  mrg 	}
    156       1.1  mrg 
    157       1.1  mrg       /* fastpath common case */
    158       1.1  mrg       if (DECDPUN==3 && pad==0) {
    159       1.1  mrg 	uInt dpd[6]={0,0,0,0,0,0};
    160       1.1  mrg 	uInt i;
    161       1.1  mrg 	Int d=dn->digits;
    162       1.1  mrg 	for (i=0; d>0; i++, d-=3) dpd[i]=BIN2DPD[dn->lsu[i]];
    163       1.1  mrg 	targlo =dpd[0];
    164       1.1  mrg 	targlo|=dpd[1]<<10;
    165       1.1  mrg 	targlo|=dpd[2]<<20;
    166       1.1  mrg 	if (dn->digits>6) {
    167       1.1  mrg 	  targlo|=dpd[3]<<30;
    168       1.1  mrg 	  targhi =dpd[3]>>2;
    169       1.1  mrg 	  targhi|=dpd[4]<<8;
    170       1.1  mrg 	  }
    171       1.1  mrg 	msd=dpd[5];		   /* [did not really need conversion] */
    172       1.1  mrg 	}
    173       1.1  mrg        else { /* general case */
    174       1.1  mrg 	decDigitsToDPD(dn, targar, pad);
    175       1.1  mrg 	/* save and clear the top digit */
    176       1.1  mrg 	msd=targhi>>18;
    177       1.1  mrg 	targhi&=0x0003ffff;
    178       1.1  mrg 	}
    179       1.1  mrg 
    180       1.1  mrg       /* create the combination field */
    181       1.1  mrg       if (msd>=8) comb=0x18 | ((exp>>7) & 0x06) | (msd & 0x01);
    182       1.1  mrg 	     else comb=((exp>>5) & 0x18) | msd;
    183       1.1  mrg       }
    184       1.1  mrg     targhi|=comb<<26;		   /* add combination field .. */
    185       1.1  mrg     targhi|=(exp&0xff)<<18;	   /* .. and exponent continuation */
    186       1.1  mrg     } /* finite */
    187       1.1  mrg 
    188       1.1  mrg   if (dn->bits&DECNEG) targhi|=0x80000000; /* add sign bit */
    189       1.1  mrg 
    190       1.1  mrg   /* now write to storage; this is now always endian */
    191       1.1  mrg   if (DECLITEND) {
    192       1.1  mrg     /* lo int then hi */
    193       1.1  mrg     UBFROMUI(d64->bytes,   targar[0]);
    194       1.1  mrg     UBFROMUI(d64->bytes+4, targar[1]);
    195       1.1  mrg     }
    196       1.1  mrg    else {
    197       1.1  mrg     /* hi int then lo */
    198       1.1  mrg     UBFROMUI(d64->bytes,   targar[1]);
    199       1.1  mrg     UBFROMUI(d64->bytes+4, targar[0]);
    200       1.1  mrg     }
    201       1.1  mrg 
    202       1.1  mrg   if (status!=0) decContextSetStatus(set, status); /* pass on status */
    203       1.1  mrg   /* decimal64Show(d64); */
    204       1.1  mrg   return d64;
    205       1.1  mrg   } /* decimal64FromNumber */
    206       1.1  mrg 
    207       1.1  mrg /* ------------------------------------------------------------------ */
    208       1.1  mrg /* decimal64ToNumber -- convert decimal64 to decNumber		      */
    209       1.1  mrg /*   d64 is the source decimal64				      */
    210       1.1  mrg /*   dn is the target number, with appropriate space		      */
    211       1.1  mrg /* No error is possible.					      */
    212       1.1  mrg /* ------------------------------------------------------------------ */
    213       1.1  mrg decNumber * decimal64ToNumber(const decimal64 *d64, decNumber *dn) {
    214       1.1  mrg   uInt msd;			   /* coefficient MSD */
    215       1.1  mrg   uInt exp;			   /* exponent top two bits */
    216       1.1  mrg   uInt comb;			   /* combination field */
    217       1.1  mrg   Int  need;			   /* work */
    218       1.1  mrg   uInt uiwork;			   /* for macros */
    219       1.1  mrg   uInt sourar[2];		   /* source 64-bit */
    220       1.1  mrg   #define sourhi sourar[1]	   /* name the word with the sign */
    221       1.1  mrg   #define sourlo sourar[0]	   /* and the lower word */
    222       1.1  mrg 
    223       1.1  mrg   /* load source from storage; this is endian */
    224       1.1  mrg   if (DECLITEND) {
    225       1.1  mrg     sourlo=UBTOUI(d64->bytes  );   /* directly load the low int */
    226       1.1  mrg     sourhi=UBTOUI(d64->bytes+4);   /* then the high int */
    227       1.1  mrg     }
    228       1.1  mrg    else {
    229       1.1  mrg     sourhi=UBTOUI(d64->bytes  );   /* directly load the high int */
    230       1.1  mrg     sourlo=UBTOUI(d64->bytes+4);   /* then the low int */
    231       1.1  mrg     }
    232       1.1  mrg 
    233       1.1  mrg   comb=(sourhi>>26)&0x1f;	   /* combination field */
    234       1.1  mrg 
    235       1.1  mrg   decNumberZero(dn);		   /* clean number */
    236       1.1  mrg   if (sourhi&0x80000000) dn->bits=DECNEG; /* set sign if negative */
    237       1.1  mrg 
    238       1.1  mrg   msd=COMBMSD[comb];		   /* decode the combination field */
    239       1.1  mrg   exp=COMBEXP[comb];		   /* .. */
    240       1.1  mrg 
    241       1.1  mrg   if (exp==3) { 		   /* is a special */
    242       1.1  mrg     if (msd==0) {
    243       1.1  mrg       dn->bits|=DECINF;
    244       1.1  mrg       return dn;		   /* no coefficient needed */
    245       1.1  mrg       }
    246       1.1  mrg     else if (sourhi&0x02000000) dn->bits|=DECSNAN;
    247       1.1  mrg     else dn->bits|=DECNAN;
    248       1.1  mrg     msd=0;			   /* no top digit */
    249       1.1  mrg     }
    250       1.1  mrg    else {			   /* is a finite number */
    251       1.1  mrg     dn->exponent=(exp<<8)+((sourhi>>18)&0xff)-DECIMAL64_Bias; /* unbiased */
    252       1.1  mrg     }
    253       1.1  mrg 
    254       1.1  mrg   /* get the coefficient */
    255       1.1  mrg   sourhi&=0x0003ffff;		   /* clean coefficient continuation */
    256       1.1  mrg   if (msd) {			   /* non-zero msd */
    257       1.1  mrg     sourhi|=msd<<18;		   /* prefix to coefficient */
    258       1.1  mrg     need=6;			   /* process 6 declets */
    259       1.1  mrg     }
    260       1.1  mrg    else { /* msd=0 */
    261       1.1  mrg     if (!sourhi) {		   /* top word 0 */
    262       1.1  mrg       if (!sourlo) return dn;	   /* easy: coefficient is 0 */
    263       1.1  mrg       need=3;			   /* process at least 3 declets */
    264       1.1  mrg       if (sourlo&0xc0000000) need++; /* process 4 declets */
    265       1.1  mrg       /* [could reduce some more, here] */
    266       1.1  mrg       }
    267       1.1  mrg      else {			   /* some bits in top word, msd=0 */
    268       1.1  mrg       need=4;			   /* process at least 4 declets */
    269       1.1  mrg       if (sourhi&0x0003ff00) need++; /* top declet!=0, process 5 */
    270       1.1  mrg       }
    271       1.1  mrg     } /*msd=0 */
    272       1.1  mrg 
    273       1.1  mrg   decDigitsFromDPD(dn, sourar, need);	/* process declets */
    274       1.1  mrg   return dn;
    275       1.1  mrg   } /* decimal64ToNumber */
    276       1.1  mrg 
    277       1.1  mrg 
    278       1.1  mrg /* ------------------------------------------------------------------ */
    279       1.1  mrg /* to-scientific-string -- conversion to numeric string 	      */
    280       1.1  mrg /* to-engineering-string -- conversion to numeric string	      */
    281       1.1  mrg /*								      */
    282       1.1  mrg /*   decimal64ToString(d64, string);				      */
    283       1.1  mrg /*   decimal64ToEngString(d64, string); 			      */
    284       1.1  mrg /*								      */
    285       1.1  mrg /*  d64 is the decimal64 format number to convert		      */
    286       1.1  mrg /*  string is the string where the result will be laid out	      */
    287       1.1  mrg /*								      */
    288       1.1  mrg /*  string must be at least 24 characters			      */
    289       1.1  mrg /*								      */
    290       1.1  mrg /*  No error is possible, and no status can be set.		      */
    291       1.1  mrg /* ------------------------------------------------------------------ */
    292       1.1  mrg char * decimal64ToEngString(const decimal64 *d64, char *string){
    293       1.1  mrg   decNumber dn; 			/* work */
    294       1.1  mrg   decimal64ToNumber(d64, &dn);
    295       1.1  mrg   decNumberToEngString(&dn, string);
    296       1.1  mrg   return string;
    297       1.1  mrg   } /* decimal64ToEngString */
    298       1.1  mrg 
    299       1.1  mrg char * decimal64ToString(const decimal64 *d64, char *string){
    300       1.1  mrg   uInt msd;			   /* coefficient MSD */
    301       1.1  mrg   Int  exp;			   /* exponent top two bits or full */
    302       1.1  mrg   uInt comb;			   /* combination field */
    303       1.1  mrg   char *cstart; 		   /* coefficient start */
    304       1.1  mrg   char *c;			   /* output pointer in string */
    305       1.1  mrg   const uByte *u;		   /* work */
    306       1.1  mrg   char *s, *t;			   /* .. (source, target) */
    307       1.1  mrg   Int  dpd;			   /* .. */
    308       1.1  mrg   Int  pre, e;			   /* .. */
    309       1.1  mrg   uInt uiwork;			   /* for macros */
    310       1.1  mrg 
    311       1.1  mrg   uInt sourar[2];		   /* source 64-bit */
    312       1.1  mrg   #define sourhi sourar[1]	   /* name the word with the sign */
    313       1.1  mrg   #define sourlo sourar[0]	   /* and the lower word */
    314       1.1  mrg 
    315       1.1  mrg   /* load source from storage; this is endian */
    316       1.1  mrg   if (DECLITEND) {
    317       1.1  mrg     sourlo=UBTOUI(d64->bytes  );   /* directly load the low int */
    318       1.1  mrg     sourhi=UBTOUI(d64->bytes+4);   /* then the high int */
    319       1.1  mrg     }
    320       1.1  mrg    else {
    321       1.1  mrg     sourhi=UBTOUI(d64->bytes  );   /* directly load the high int */
    322       1.1  mrg     sourlo=UBTOUI(d64->bytes+4);   /* then the low int */
    323       1.1  mrg     }
    324       1.1  mrg 
    325       1.1  mrg   c=string;			   /* where result will go */
    326       1.1  mrg   if (((Int)sourhi)<0) *c++='-';   /* handle sign */
    327       1.1  mrg 
    328       1.1  mrg   comb=(sourhi>>26)&0x1f;	   /* combination field */
    329       1.1  mrg   msd=COMBMSD[comb];		   /* decode the combination field */
    330       1.1  mrg   exp=COMBEXP[comb];		   /* .. */
    331       1.1  mrg 
    332       1.1  mrg   if (exp==3) {
    333       1.1  mrg     if (msd==0) {		   /* infinity */
    334       1.1  mrg       strcpy(c,   "Inf");
    335       1.1  mrg       strcpy(c+3, "inity");
    336       1.1  mrg       return string;		   /* easy */
    337       1.1  mrg       }
    338       1.1  mrg     if (sourhi&0x02000000) *c++='s'; /* sNaN */
    339       1.1  mrg     strcpy(c, "NaN");		   /* complete word */
    340       1.1  mrg     c+=3;			   /* step past */
    341       1.1  mrg     if (sourlo==0 && (sourhi&0x0003ffff)==0) return string; /* zero payload */
    342       1.1  mrg     /* otherwise drop through to add integer; set correct exp */
    343       1.1  mrg     exp=0; msd=0;		   /* setup for following code */
    344       1.1  mrg     }
    345       1.1  mrg    else exp=(exp<<8)+((sourhi>>18)&0xff)-DECIMAL64_Bias;
    346       1.1  mrg 
    347       1.1  mrg   /* convert 16 digits of significand to characters */
    348       1.1  mrg   cstart=c;			   /* save start of coefficient */
    349       1.1  mrg   if (msd) *c++='0'+(char)msd;	   /* non-zero most significant digit */
    350       1.1  mrg 
    351       1.1  mrg   /* Now decode the declets.  After extracting each one, it is */
    352       1.1  mrg   /* decoded to binary and then to a 4-char sequence by table lookup; */
    353       1.1  mrg   /* the 4-chars are a 1-char length (significant digits, except 000 */
    354       1.1  mrg   /* has length 0).  This allows us to left-align the first declet */
    355       1.1  mrg   /* with non-zero content, then remaining ones are full 3-char */
    356       1.1  mrg   /* length.  We use fixed-length memcpys because variable-length */
    357       1.1  mrg   /* causes a subroutine call in GCC.  (These are length 4 for speed */
    358       1.1  mrg   /* and are safe because the array has an extra terminator byte.) */
    359       1.1  mrg   #define dpd2char u=&BIN2CHAR[DPD2BIN[dpd]*4]; 		  \
    360       1.1  mrg 		   if (c!=cstart) {memcpy(c, u+1, 4); c+=3;}	  \
    361       1.1  mrg 		    else if (*u)  {memcpy(c, u+4-*u, 4); c+=*u;}
    362       1.1  mrg 
    363       1.1  mrg   dpd=(sourhi>>8)&0x3ff;		     /* declet 1 */
    364       1.1  mrg   dpd2char;
    365       1.1  mrg   dpd=((sourhi&0xff)<<2) | (sourlo>>30);     /* declet 2 */
    366       1.1  mrg   dpd2char;
    367       1.1  mrg   dpd=(sourlo>>20)&0x3ff;		     /* declet 3 */
    368       1.1  mrg   dpd2char;
    369       1.1  mrg   dpd=(sourlo>>10)&0x3ff;		     /* declet 4 */
    370       1.1  mrg   dpd2char;
    371       1.1  mrg   dpd=(sourlo)&0x3ff;			     /* declet 5 */
    372       1.1  mrg   dpd2char;
    373       1.1  mrg 
    374       1.1  mrg   if (c==cstart) *c++='0';	   /* all zeros -- make 0 */
    375       1.1  mrg 
    376       1.1  mrg   if (exp==0) { 		   /* integer or NaN case -- easy */
    377       1.1  mrg     *c='\0';			   /* terminate */
    378       1.1  mrg     return string;
    379       1.1  mrg     }
    380       1.1  mrg 
    381       1.1  mrg   /* non-0 exponent */
    382       1.1  mrg   e=0;				   /* assume no E */
    383       1.1  mrg   pre=c-cstart+exp;
    384       1.1  mrg   /* [here, pre-exp is the digits count (==1 for zero)] */
    385       1.1  mrg   if (exp>0 || pre<-5) {	   /* need exponential form */
    386       1.1  mrg     e=pre-1;			   /* calculate E value */
    387       1.1  mrg     pre=1;			   /* assume one digit before '.' */
    388       1.1  mrg     } /* exponential form */
    389       1.1  mrg 
    390       1.1  mrg   /* modify the coefficient, adding 0s, '.', and E+nn as needed */
    391       1.1  mrg   s=c-1;			   /* source (LSD) */
    392       1.1  mrg   if (pre>0) {			   /* ddd.ddd (plain), perhaps with E */
    393       1.1  mrg     char *dotat=cstart+pre;
    394       1.1  mrg     if (dotat<c) {		   /* if embedded dot needed... */
    395       1.1  mrg       t=c;				/* target */
    396       1.1  mrg       for (; s>=dotat; s--, t--) *t=*s; /* open the gap; leave t at gap */
    397       1.1  mrg       *t='.';				/* insert the dot */
    398       1.1  mrg       c++;				/* length increased by one */
    399       1.1  mrg       }
    400       1.1  mrg 
    401       1.1  mrg     /* finally add the E-part, if needed; it will never be 0, and has */
    402       1.1  mrg     /* a maximum length of 3 digits */
    403       1.1  mrg     if (e!=0) {
    404       1.1  mrg       *c++='E'; 		   /* starts with E */
    405       1.1  mrg       *c++='+'; 		   /* assume positive */
    406       1.1  mrg       if (e<0) {
    407       1.1  mrg 	*(c-1)='-';		   /* oops, need '-' */
    408       1.1  mrg 	e=-e;			   /* uInt, please */
    409       1.1  mrg 	}
    410       1.1  mrg       u=&BIN2CHAR[e*4]; 	   /* -> length byte */
    411       1.1  mrg       memcpy(c, u+4-*u, 4);	   /* copy fixed 4 characters [is safe] */
    412       1.1  mrg       c+=*u;			   /* bump pointer appropriately */
    413       1.1  mrg       }
    414       1.1  mrg     *c='\0';			   /* add terminator */
    415       1.1  mrg     /*printf("res %s\n", string); */
    416       1.1  mrg     return string;
    417       1.1  mrg     } /* pre>0 */
    418       1.1  mrg 
    419       1.1  mrg   /* -5<=pre<=0: here for plain 0.ddd or 0.000ddd forms (can never have E) */
    420       1.1  mrg   t=c+1-pre;
    421       1.1  mrg   *(t+1)='\0';				/* can add terminator now */
    422       1.1  mrg   for (; s>=cstart; s--, t--) *t=*s;	/* shift whole coefficient right */
    423       1.1  mrg   c=cstart;
    424       1.1  mrg   *c++='0';				/* always starts with 0. */
    425       1.1  mrg   *c++='.';
    426       1.1  mrg   for (; pre<0; pre++) *c++='0';	/* add any 0's after '.' */
    427       1.1  mrg   /*printf("res %s\n", string); */
    428       1.1  mrg   return string;
    429       1.1  mrg   } /* decimal64ToString */
    430       1.1  mrg 
    431       1.1  mrg /* ------------------------------------------------------------------ */
    432       1.1  mrg /* to-number -- conversion from numeric string			      */
    433       1.1  mrg /*								      */
    434       1.1  mrg /*   decimal64FromString(result, string, set);			      */
    435       1.1  mrg /*								      */
    436       1.1  mrg /*  result  is the decimal64 format number which gets the result of   */
    437       1.1  mrg /*	    the conversion					      */
    438       1.1  mrg /*  *string is the character string which should contain a valid      */
    439       1.1  mrg /*	    number (which may be a special value)		      */
    440       1.1  mrg /*  set     is the context					      */
    441       1.1  mrg /*								      */
    442       1.1  mrg /* The context is supplied to this routine is used for error handling */
    443       1.1  mrg /* (setting of status and traps) and for the rounding mode, only.     */
    444       1.1  mrg /* If an error occurs, the result will be a valid decimal64 NaN.      */
    445       1.1  mrg /* ------------------------------------------------------------------ */
    446       1.1  mrg decimal64 * decimal64FromString(decimal64 *result, const char *string,
    447       1.1  mrg 				decContext *set) {
    448       1.1  mrg   decContext dc;			     /* work */
    449       1.1  mrg   decNumber dn; 			     /* .. */
    450       1.1  mrg 
    451       1.1  mrg   decContextDefault(&dc, DEC_INIT_DECIMAL64); /* no traps, please */
    452       1.1  mrg   dc.round=set->round;			      /* use supplied rounding */
    453       1.1  mrg 
    454       1.1  mrg   decNumberFromString(&dn, string, &dc);     /* will round if needed */
    455       1.1  mrg 
    456       1.1  mrg   decimal64FromNumber(result, &dn, &dc);
    457       1.1  mrg   if (dc.status!=0) {			     /* something happened */
    458       1.1  mrg     decContextSetStatus(set, dc.status);     /* .. pass it on */
    459       1.1  mrg     }
    460       1.1  mrg   return result;
    461       1.1  mrg   } /* decimal64FromString */
    462       1.1  mrg 
    463       1.1  mrg /* ------------------------------------------------------------------ */
    464       1.1  mrg /* decimal64IsCanonical -- test whether encoding is canonical	      */
    465       1.1  mrg /*   d64 is the source decimal64				      */
    466       1.1  mrg /*   returns 1 if the encoding of d64 is canonical, 0 otherwise       */
    467       1.1  mrg /* No error is possible.					      */
    468       1.1  mrg /* ------------------------------------------------------------------ */
    469       1.1  mrg uInt decimal64IsCanonical(const decimal64 *d64) {
    470       1.1  mrg   decNumber dn; 			/* work */
    471       1.1  mrg   decimal64 canon;			/* .. */
    472       1.1  mrg   decContext dc;			/* .. */
    473       1.1  mrg   decContextDefault(&dc, DEC_INIT_DECIMAL64);
    474       1.1  mrg   decimal64ToNumber(d64, &dn);
    475       1.1  mrg   decimal64FromNumber(&canon, &dn, &dc);/* canon will now be canonical */
    476       1.1  mrg   return memcmp(d64, &canon, DECIMAL64_Bytes)==0;
    477       1.1  mrg   } /* decimal64IsCanonical */
    478       1.1  mrg 
    479       1.1  mrg /* ------------------------------------------------------------------ */
    480       1.1  mrg /* decimal64Canonical -- copy an encoding, ensuring it is canonical   */
    481       1.1  mrg /*   d64 is the source decimal64				      */
    482       1.1  mrg /*   result is the target (may be the same decimal64)		      */
    483       1.1  mrg /*   returns result						      */
    484       1.1  mrg /* No error is possible.					      */
    485       1.1  mrg /* ------------------------------------------------------------------ */
    486       1.1  mrg decimal64 * decimal64Canonical(decimal64 *result, const decimal64 *d64) {
    487       1.1  mrg   decNumber dn; 			/* work */
    488       1.1  mrg   decContext dc;			/* .. */
    489       1.1  mrg   decContextDefault(&dc, DEC_INIT_DECIMAL64);
    490       1.1  mrg   decimal64ToNumber(d64, &dn);
    491       1.1  mrg   decimal64FromNumber(result, &dn, &dc);/* result will now be canonical */
    492       1.1  mrg   return result;
    493       1.1  mrg   } /* decimal64Canonical */
    494       1.1  mrg 
    495       1.1  mrg #if DECTRACE || DECCHECK
    496       1.1  mrg /* Macros for accessing decimal64 fields.  These assume the
    497       1.1  mrg    argument is a reference (pointer) to the decimal64 structure,
    498       1.1  mrg    and the decimal64 is in network byte order (big-endian) */
    499       1.1  mrg /* Get sign */
    500       1.1  mrg #define decimal64Sign(d)       ((unsigned)(d)->bytes[0]>>7)
    501       1.1  mrg 
    502       1.1  mrg /* Get combination field */
    503       1.1  mrg #define decimal64Comb(d)       (((d)->bytes[0] & 0x7c)>>2)
    504       1.1  mrg 
    505       1.1  mrg /* Get exponent continuation [does not remove bias] */
    506       1.1  mrg #define decimal64ExpCon(d)     ((((d)->bytes[0] & 0x03)<<6)	      \
    507       1.1  mrg 			     | ((unsigned)(d)->bytes[1]>>2))
    508       1.1  mrg 
    509       1.1  mrg /* Set sign [this assumes sign previously 0] */
    510       1.1  mrg #define decimal64SetSign(d, b) {				      \
    511       1.1  mrg   (d)->bytes[0]|=((unsigned)(b)<<7);}
    512       1.1  mrg 
    513       1.1  mrg /* Set exponent continuation [does not apply bias] */
    514       1.1  mrg /* This assumes range has been checked and exponent previously 0; */
    515       1.1  mrg /* type of exponent must be unsigned */
    516       1.1  mrg #define decimal64SetExpCon(d, e) {				      \
    517       1.1  mrg   (d)->bytes[0]|=(uByte)((e)>>6);				      \
    518       1.1  mrg   (d)->bytes[1]|=(uByte)(((e)&0x3F)<<2);}
    519       1.1  mrg 
    520       1.1  mrg /* ------------------------------------------------------------------ */
    521       1.1  mrg /* decimal64Show -- display a decimal64 in hexadecimal [debug aid]    */
    522       1.1  mrg /*   d64 -- the number to show					      */
    523       1.1  mrg /* ------------------------------------------------------------------ */
    524       1.1  mrg /* Also shows sign/cob/expconfields extracted */
    525       1.1  mrg void decimal64Show(const decimal64 *d64) {
    526       1.1  mrg   char buf[DECIMAL64_Bytes*2+1];
    527       1.1  mrg   Int i, j=0;
    528       1.1  mrg 
    529       1.1  mrg   if (DECLITEND) {
    530       1.1  mrg     for (i=0; i<DECIMAL64_Bytes; i++, j+=2) {
    531       1.1  mrg       sprintf(&buf[j], "%02x", d64->bytes[7-i]);
    532       1.1  mrg       }
    533       1.1  mrg     printf(" D64> %s [S:%d Cb:%02x Ec:%02x] LittleEndian\n", buf,
    534       1.1  mrg 	   d64->bytes[7]>>7, (d64->bytes[7]>>2)&0x1f,
    535       1.1  mrg 	   ((d64->bytes[7]&0x3)<<6)| (d64->bytes[6]>>2));
    536       1.1  mrg     }
    537       1.1  mrg    else { /* big-endian */
    538       1.1  mrg     for (i=0; i<DECIMAL64_Bytes; i++, j+=2) {
    539       1.1  mrg       sprintf(&buf[j], "%02x", d64->bytes[i]);
    540       1.1  mrg       }
    541       1.1  mrg     printf(" D64> %s [S:%d Cb:%02x Ec:%02x] BigEndian\n", buf,
    542       1.1  mrg 	   decimal64Sign(d64), decimal64Comb(d64), decimal64ExpCon(d64));
    543       1.1  mrg     }
    544       1.1  mrg   } /* decimal64Show */
    545       1.1  mrg #endif
    546       1.1  mrg 
    547       1.1  mrg /* ================================================================== */
    548       1.1  mrg /* Shared utility routines and tables				      */
    549       1.1  mrg /* ================================================================== */
    550       1.1  mrg /* define and include the conversion tables to use for shared code */
    551       1.1  mrg #if DECDPUN==3
    552       1.1  mrg   #define DEC_DPD2BIN 1
    553       1.1  mrg #else
    554       1.1  mrg   #define DEC_DPD2BCD 1
    555       1.1  mrg #endif
    556       1.1  mrg #include "decDPD.h"	      /* lookup tables */
    557       1.1  mrg 
    558       1.1  mrg /* The maximum number of decNumberUnits needed for a working copy of */
    559       1.1  mrg /* the units array is the ceiling of digits/DECDPUN, where digits is */
    560       1.1  mrg /* the maximum number of digits in any of the formats for which this */
    561       1.1  mrg /* is used.  decimal128.h must not be included in this module, so, as */
    562       1.1  mrg /* a very special case, that number is defined as a literal here. */
    563       1.1  mrg #define DECMAX754   34
    564       1.1  mrg #define DECMAXUNITS ((DECMAX754+DECDPUN-1)/DECDPUN)
    565       1.1  mrg 
    566       1.1  mrg /* ------------------------------------------------------------------ */
    567       1.1  mrg /* Combination field lookup tables (uInts to save measurable work)    */
    568       1.1  mrg /*								      */
    569       1.1  mrg /*	COMBEXP - 2-bit most-significant-bits of exponent	      */
    570       1.1  mrg /*		  [11 if an Infinity or NaN]			      */
    571       1.1  mrg /*	COMBMSD - 4-bit most-significant-digit			      */
    572       1.1  mrg /*		  [0=Infinity, 1=NaN if COMBEXP=11]		      */
    573       1.1  mrg /*								      */
    574       1.1  mrg /* Both are indexed by the 5-bit combination field (0-31)	      */
    575       1.1  mrg /* ------------------------------------------------------------------ */
    576       1.1  mrg const uInt COMBEXP[32]={0, 0, 0, 0, 0, 0, 0, 0,
    577       1.1  mrg 			1, 1, 1, 1, 1, 1, 1, 1,
    578       1.1  mrg 			2, 2, 2, 2, 2, 2, 2, 2,
    579       1.1  mrg 			0, 0, 1, 1, 2, 2, 3, 3};
    580       1.1  mrg const uInt COMBMSD[32]={0, 1, 2, 3, 4, 5, 6, 7,
    581       1.1  mrg 			0, 1, 2, 3, 4, 5, 6, 7,
    582       1.1  mrg 			0, 1, 2, 3, 4, 5, 6, 7,
    583       1.1  mrg 			8, 9, 8, 9, 8, 9, 0, 1};
    584       1.1  mrg 
    585       1.1  mrg /* ------------------------------------------------------------------ */
    586       1.1  mrg /* decDigitsToDPD -- pack coefficient into DPD form		      */
    587       1.1  mrg /*								      */
    588       1.1  mrg /*   dn   is the source number (assumed valid, max DECMAX754 digits)  */
    589       1.1  mrg /*   targ is 1, 2, or 4-element uInt array, which the caller must     */
    590       1.1  mrg /*	  have cleared to zeros 				      */
    591       1.1  mrg /*   shift is the number of 0 digits to add on the right (normally 0) */
    592       1.1  mrg /*								      */
    593       1.1  mrg /* The coefficient must be known small enough to fit.  The full       */
    594       1.1  mrg /* coefficient is copied, including the leading 'odd' digit.  This    */
    595       1.1  mrg /* digit is retrieved and packed into the combination field by the    */
    596       1.1  mrg /* caller.							      */
    597       1.1  mrg /*								      */
    598       1.1  mrg /* The target uInts are altered only as necessary to receive the      */
    599       1.1  mrg /* digits of the decNumber.  When more than one uInt is needed, they  */
    600       1.1  mrg /* are filled from left to right (that is, the uInt at offset 0 will  */
    601       1.1  mrg /* end up with the least-significant digits).			      */
    602       1.1  mrg /*								      */
    603       1.1  mrg /* shift is used for 'fold-down' padding.			      */
    604       1.1  mrg /*								      */
    605       1.1  mrg /* No error is possible.					      */
    606       1.1  mrg /* ------------------------------------------------------------------ */
    607       1.1  mrg #if DECDPUN<=4
    608       1.1  mrg /* Constant multipliers for divide-by-power-of five using reciprocal */
    609       1.1  mrg /* multiply, after removing powers of 2 by shifting, and final shift */
    610       1.1  mrg /* of 17 [we only need up to **4] */
    611       1.1  mrg static const uInt multies[]={131073, 26215, 5243, 1049, 210};
    612       1.1  mrg /* QUOT10 -- macro to return the quotient of unit u divided by 10**n */
    613       1.1  mrg #define QUOT10(u, n) ((((uInt)(u)>>(n))*multies[n])>>17)
    614       1.1  mrg #endif
    615       1.1  mrg void decDigitsToDPD(const decNumber *dn, uInt *targ, Int shift) {
    616       1.1  mrg   Int  cut;		      /* work */
    617       1.1  mrg   Int  digits=dn->digits;     /* digit countdown */
    618       1.1  mrg   uInt dpd;		      /* densely packed decimal value */
    619       1.1  mrg   uInt bin;		      /* binary value 0-999 */
    620       1.1  mrg   uInt *uout=targ;	      /* -> current output uInt */
    621       1.1  mrg   uInt	uoff=0; 	      /* -> current output offset [from right] */
    622       1.1  mrg   const Unit *inu=dn->lsu;    /* -> current input unit */
    623       1.1  mrg   Unit	uar[DECMAXUNITS];     /* working copy of units, iff shifted */
    624       1.1  mrg   #if DECDPUN!=3	      /* not fast path */
    625       1.1  mrg     Unit in;		      /* current unit */
    626       1.1  mrg   #endif
    627       1.1  mrg 
    628       1.1  mrg   if (shift!=0) {	      /* shift towards most significant required */
    629       1.1  mrg     /* shift the units array to the left by pad digits and copy */
    630       1.1  mrg     /* [this code is a special case of decShiftToMost, which could */
    631       1.1  mrg     /* be used instead if exposed and the array were copied first] */
    632       1.1  mrg     const Unit *source; 		/* .. */
    633       1.1  mrg     Unit  *target, *first;		/* .. */
    634       1.1  mrg     uInt  next=0;			/* work */
    635       1.1  mrg 
    636       1.1  mrg     source=dn->lsu+D2U(digits)-1;	/* where msu comes from */
    637       1.1  mrg     target=uar+D2U(digits)-1+D2U(shift);/* where upper part of first cut goes */
    638       1.1  mrg     cut=DECDPUN-MSUDIGITS(shift);	/* where to slice */
    639       1.1  mrg     if (cut==0) {			/* unit-boundary case */
    640       1.1  mrg       for (; source>=dn->lsu; source--, target--) *target=*source;
    641       1.1  mrg       }
    642       1.1  mrg      else {
    643       1.1  mrg       first=uar+D2U(digits+shift)-1;	/* where msu will end up */
    644       1.1  mrg       for (; source>=dn->lsu; source--, target--) {
    645       1.1  mrg 	/* split the source Unit and accumulate remainder for next */
    646       1.1  mrg 	#if DECDPUN<=4
    647       1.1  mrg 	  uInt quot=QUOT10(*source, cut);
    648       1.1  mrg 	  uInt rem=*source-quot*DECPOWERS[cut];
    649       1.1  mrg 	  next+=quot;
    650       1.1  mrg 	#else
    651       1.1  mrg 	  uInt rem=*source%DECPOWERS[cut];
    652       1.1  mrg 	  next+=*source/DECPOWERS[cut];
    653       1.1  mrg 	#endif
    654       1.1  mrg 	if (target<=first) *target=(Unit)next; /* write to target iff valid */
    655       1.1  mrg 	next=rem*DECPOWERS[DECDPUN-cut];       /* save remainder for next Unit */
    656       1.1  mrg 	}
    657       1.1  mrg       } /* shift-move */
    658       1.1  mrg     /* propagate remainder to one below and clear the rest */
    659       1.1  mrg     for (; target>=uar; target--) {
    660       1.1  mrg       *target=(Unit)next;
    661       1.1  mrg       next=0;
    662       1.1  mrg       }
    663       1.1  mrg     digits+=shift;		   /* add count (shift) of zeros added */
    664       1.1  mrg     inu=uar;			   /* use units in working array */
    665       1.1  mrg     }
    666       1.1  mrg 
    667       1.1  mrg   /* now densely pack the coefficient into DPD declets */
    668       1.1  mrg 
    669       1.1  mrg   #if DECDPUN!=3		   /* not fast path */
    670       1.1  mrg     in=*inu;			   /* current unit */
    671       1.1  mrg     cut=0;			   /* at lowest digit */
    672       1.1  mrg     bin=0;			   /* [keep compiler quiet] */
    673       1.1  mrg   #endif
    674       1.1  mrg 
    675  1.1.1.12  mrg   for(; digits>0;) {		   /* each output bunch */
    676       1.1  mrg     #if DECDPUN==3		   /* fast path, 3-at-a-time */
    677       1.1  mrg       bin=*inu; 		   /* 3 digits ready for convert */
    678       1.1  mrg       digits-=3;		   /* [may go negative] */
    679       1.1  mrg       inu++;			   /* may need another */
    680       1.1  mrg 
    681       1.1  mrg     #else			   /* must collect digit-by-digit */
    682       1.1  mrg       Unit dig; 		   /* current digit */
    683       1.1  mrg       Int j;			   /* digit-in-declet count */
    684       1.1  mrg       for (j=0; j<3; j++) {
    685       1.1  mrg 	#if DECDPUN<=4
    686       1.1  mrg 	  Unit temp=(Unit)((uInt)(in*6554)>>16);
    687       1.1  mrg 	  dig=(Unit)(in-X10(temp));
    688       1.1  mrg 	  in=temp;
    689       1.1  mrg 	#else
    690       1.1  mrg 	  dig=in%10;
    691       1.1  mrg 	  in=in/10;
    692       1.1  mrg 	#endif
    693       1.1  mrg 	if (j==0) bin=dig;
    694       1.1  mrg 	 else if (j==1)  bin+=X10(dig);
    695       1.1  mrg 	 else /* j==2 */ bin+=X100(dig);
    696       1.1  mrg 	digits--;
    697       1.1  mrg 	if (digits==0) break;	   /* [also protects *inu below] */
    698       1.1  mrg 	cut++;
    699       1.1  mrg 	if (cut==DECDPUN) {inu++; in=*inu; cut=0;}
    700       1.1  mrg 	}
    701       1.1  mrg     #endif
    702       1.1  mrg     /* here there are 3 digits in bin, or have used all input digits */
    703       1.1  mrg 
    704       1.1  mrg     dpd=BIN2DPD[bin];
    705       1.1  mrg 
    706       1.1  mrg     /* write declet to uInt array */
    707       1.1  mrg     *uout|=dpd<<uoff;
    708       1.1  mrg     uoff+=10;
    709       1.1  mrg     if (uoff<32) continue;	   /* no uInt boundary cross */
    710       1.1  mrg     uout++;
    711       1.1  mrg     uoff-=32;
    712       1.1  mrg     *uout|=dpd>>(10-uoff);	   /* collect top bits */
    713       1.1  mrg     } /* n declets */
    714       1.1  mrg   return;
    715       1.1  mrg   } /* decDigitsToDPD */
    716       1.1  mrg 
    717       1.1  mrg /* ------------------------------------------------------------------ */
    718       1.1  mrg /* decDigitsFromDPD -- unpack a format's coefficient		      */
    719       1.1  mrg /*								      */
    720       1.1  mrg /*   dn is the target number, with 7, 16, or 34-digit space.	      */
    721       1.1  mrg /*   sour is a 1, 2, or 4-element uInt array containing only declets  */
    722       1.1  mrg /*   declets is the number of (right-aligned) declets in sour to      */
    723       1.1  mrg /*     be processed.  This may be 1 more than the obvious number in   */
    724       1.1  mrg /*     a format, as any top digit is prefixed to the coefficient      */
    725       1.1  mrg /*     continuation field.  It also may be as small as 1, as the      */
    726       1.1  mrg /*     caller may pre-process leading zero declets.		      */
    727       1.1  mrg /*								      */
    728       1.1  mrg /* When doing the 'extra declet' case care is taken to avoid writing  */
    729       1.1  mrg /* extra digits when there are leading zeros, as these could overflow */
    730       1.1  mrg /* the units array when DECDPUN is not 3.			      */
    731       1.1  mrg /*								      */
    732       1.1  mrg /* The target uInts are used only as necessary to process declets     */
    733       1.1  mrg /* declets into the decNumber.	When more than one uInt is needed,    */
    734       1.1  mrg /* they are used from left to right (that is, the uInt at offset 0    */
    735       1.1  mrg /* provides the least-significant digits).			      */
    736       1.1  mrg /*								      */
    737       1.1  mrg /* dn->digits is set, but not the sign or exponent.		      */
    738       1.1  mrg /* No error is possible [the redundant 888 codes are allowed].	      */
    739       1.1  mrg /* ------------------------------------------------------------------ */
    740       1.1  mrg void decDigitsFromDPD(decNumber *dn, const uInt *sour, Int declets) {
    741       1.1  mrg 
    742       1.1  mrg   uInt	dpd;			   /* collector for 10 bits */
    743       1.1  mrg   Int	n;			   /* counter */
    744       1.1  mrg   Unit	*uout=dn->lsu;		   /* -> current output unit */
    745       1.1  mrg   Unit	*last=uout;		   /* will be unit containing msd */
    746       1.1  mrg   const uInt *uin=sour; 	   /* -> current input uInt */
    747       1.1  mrg   uInt	uoff=0; 		   /* -> current input offset [from right] */
    748       1.1  mrg 
    749       1.1  mrg   #if DECDPUN!=3
    750       1.1  mrg   uInt	bcd;			   /* BCD result */
    751       1.1  mrg   uInt	nibble; 		   /* work */
    752       1.1  mrg   Unit	out=0;			   /* accumulator */
    753       1.1  mrg   Int	cut=0;			   /* power of ten in current unit */
    754       1.1  mrg   #endif
    755       1.1  mrg   #if DECDPUN>4
    756       1.1  mrg   uInt const *pow;		   /* work */
    757       1.1  mrg   #endif
    758       1.1  mrg 
    759       1.1  mrg   /* Expand the densely-packed integer, right to left */
    760       1.1  mrg   for (n=declets-1; n>=0; n--) {   /* count down declets of 10 bits */
    761       1.1  mrg     dpd=*uin>>uoff;
    762       1.1  mrg     uoff+=10;
    763       1.1  mrg     if (uoff>32) {		   /* crossed uInt boundary */
    764       1.1  mrg       uin++;
    765       1.1  mrg       uoff-=32;
    766       1.1  mrg       dpd|=*uin<<(10-uoff);	   /* get waiting bits */
    767       1.1  mrg       }
    768       1.1  mrg     dpd&=0x3ff; 		   /* clear uninteresting bits */
    769       1.1  mrg 
    770       1.1  mrg   #if DECDPUN==3
    771       1.1  mrg     if (dpd==0) *uout=0;
    772       1.1  mrg      else {
    773       1.1  mrg       *uout=DPD2BIN[dpd];	   /* convert 10 bits to binary 0-999 */
    774       1.1  mrg       last=uout;		   /* record most significant unit */
    775       1.1  mrg       }
    776       1.1  mrg     uout++;
    777       1.1  mrg     } /* n */
    778       1.1  mrg 
    779       1.1  mrg   #else /* DECDPUN!=3 */
    780       1.1  mrg     if (dpd==0) {		   /* fastpath [e.g., leading zeros] */
    781       1.1  mrg       /* write out three 0 digits (nibbles); out may have digit(s) */
    782       1.1  mrg       cut++;
    783       1.1  mrg       if (cut==DECDPUN) {*uout=out; if (out) {last=uout; out=0;} uout++; cut=0;}
    784       1.1  mrg       if (n==0) break;		   /* [as below, works even if MSD=0] */
    785       1.1  mrg       cut++;
    786       1.1  mrg       if (cut==DECDPUN) {*uout=out; if (out) {last=uout; out=0;} uout++; cut=0;}
    787       1.1  mrg       cut++;
    788       1.1  mrg       if (cut==DECDPUN) {*uout=out; if (out) {last=uout; out=0;} uout++; cut=0;}
    789       1.1  mrg       continue;
    790       1.1  mrg       }
    791       1.1  mrg 
    792       1.1  mrg     bcd=DPD2BCD[dpd];		   /* convert 10 bits to 12 bits BCD */
    793       1.1  mrg 
    794       1.1  mrg     /* now accumulate the 3 BCD nibbles into units */
    795       1.1  mrg     nibble=bcd & 0x00f;
    796       1.1  mrg     if (nibble) out=(Unit)(out+nibble*DECPOWERS[cut]);
    797       1.1  mrg     cut++;
    798       1.1  mrg     if (cut==DECDPUN) {*uout=out; if (out) {last=uout; out=0;} uout++; cut=0;}
    799       1.1  mrg     bcd>>=4;
    800       1.1  mrg 
    801       1.1  mrg     /* if this is the last declet and the remaining nibbles in bcd */
    802       1.1  mrg     /* are 00 then process no more nibbles, because this could be */
    803       1.1  mrg     /* the 'odd' MSD declet and writing any more Units would then */
    804       1.1  mrg     /* overflow the unit array */
    805       1.1  mrg     if (n==0 && !bcd) break;
    806       1.1  mrg 
    807       1.1  mrg     nibble=bcd & 0x00f;
    808       1.1  mrg     if (nibble) out=(Unit)(out+nibble*DECPOWERS[cut]);
    809       1.1  mrg     cut++;
    810       1.1  mrg     if (cut==DECDPUN) {*uout=out; if (out) {last=uout; out=0;} uout++; cut=0;}
    811       1.1  mrg     bcd>>=4;
    812       1.1  mrg 
    813       1.1  mrg     nibble=bcd & 0x00f;
    814       1.1  mrg     if (nibble) out=(Unit)(out+nibble*DECPOWERS[cut]);
    815       1.1  mrg     cut++;
    816       1.1  mrg     if (cut==DECDPUN) {*uout=out; if (out) {last=uout; out=0;} uout++; cut=0;}
    817       1.1  mrg     } /* n */
    818       1.1  mrg   if (cut!=0) { 			/* some more left over */
    819       1.1  mrg     *uout=out;				/* write out final unit */
    820       1.1  mrg     if (out) last=uout; 		/* and note if non-zero */
    821       1.1  mrg     }
    822       1.1  mrg   #endif
    823       1.1  mrg 
    824       1.1  mrg   /* here, last points to the most significant unit with digits; */
    825       1.1  mrg   /* inspect it to get the final digits count -- this is essentially */
    826       1.1  mrg   /* the same code as decGetDigits in decNumber.c */
    827       1.1  mrg   dn->digits=(last-dn->lsu)*DECDPUN+1;	/* floor of digits, plus */
    828       1.1  mrg 					/* must be at least 1 digit */
    829       1.1  mrg   #if DECDPUN>1
    830       1.1  mrg   if (*last<10) return; 		/* common odd digit or 0 */
    831       1.1  mrg   dn->digits++; 			/* must be 2 at least */
    832       1.1  mrg   #if DECDPUN>2
    833       1.1  mrg   if (*last<100) return;		/* 10-99 */
    834       1.1  mrg   dn->digits++; 			/* must be 3 at least */
    835       1.1  mrg   #if DECDPUN>3
    836       1.1  mrg   if (*last<1000) return;		/* 100-999 */
    837       1.1  mrg   dn->digits++; 			/* must be 4 at least */
    838       1.1  mrg   #if DECDPUN>4
    839       1.1  mrg   for (pow=&DECPOWERS[4]; *last>=*pow; pow++) dn->digits++;
    840       1.1  mrg   #endif
    841       1.1  mrg   #endif
    842       1.1  mrg   #endif
    843       1.1  mrg   #endif
    844       1.1  mrg   return;
    845       1.1  mrg   } /*decDigitsFromDPD */
    846