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