1 /* ------------------------------------------------------------------ */
2 /* Decimal 32-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 decimal32 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  7      // make decNumbers with space for 7
33 #include "decNumber.h"        // base number library
34 #include "decNumberLocal.h"   // decNumber local types, etc.
35 #include "decimal32.h"        // our primary include
36 
37 /* Utility tables and routines [in decimal64.c] */
38 extern const uInt   COMBEXP[32], COMBMSD[32];
39 extern const uShort DPD2BIN[1024];
40 extern const uShort BIN2DPD[1000];
41 extern const uByte  BIN2CHAR[4001];
42 
43 extern void decDigitsToDPD(const decNumber *, uInt *, Int);
44 extern void decDigitsFromDPD(decNumber *, const uInt *, Int);
45 
46 #if DECTRACE || DECCHECK
47 void decimal32Show(const decimal32 *);            // for debug
48 extern void decNumberShow(const decNumber *);     // ..
49 #endif
50 
51 /* Useful macro */
52 // Clear a structure (e.g., a decNumber)
53 #define DEC_clear(d) memset(d, 0, sizeof(*d))
54 
55 #if !DECENDIAN || DECTRACE || DECCHECK
56 /* compile-time endian tester [assumes sizeof(int)>1] */
57 static  const  Int mfcone=1;                 // constant 1
58 static  const  Flag *mfctop=(Flag *)&mfcone; // -> top byte
59 #define LITEND mfctop[0]           // named flag; 1=little-endian
60 #endif
61 
62 /* ------------------------------------------------------------------ */
63 /* decimal32FromNumber -- convert decNumber to decimal32              */
64 /*                                                                    */
65 /*   ds is the target decimal32                                       */
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 DECIMAL32_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 /* ------------------------------------------------------------------ */
decimal32FromNumber(decimal32 * d32,const decNumber * dn,decContext * set)79 decimal32 * decimal32FromNumber(decimal32 *d32, 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 targ=0;                     // target 32-bit
88 
89   // If the number has too many digits, or the exponent could be
90   // out of range then reduce the number under the appropriate
91   // constraints.  This could push the number to Infinity or zero,
92   // so this check and rounding must be done before generating the
93   // decimal32]
94   ae=dn->exponent+dn->digits-1;              // [0 if special]
95   if (dn->digits>DECIMAL32_Pmax              // too many digits
96    || ae>DECIMAL32_Emax                      // likely overflow
97    || ae<DECIMAL32_Emin) {                   // likely underflow
98     decContextDefault(&dc, DEC_INIT_DECIMAL32); // [no traps]
99     dc.round=set->round;                     // use supplied rounding
100     decNumberPlus(&dw, dn, &dc);             // (round and check)
101     // [this changes -0 to 0, so enforce the sign...]
102     dw.bits|=dn->bits&DECNEG;
103     status=dc.status;                        // save status
104     dn=&dw;                                  // use the work number
105     } // maybe out of range
106 
107   if (dn->bits&DECSPECIAL) {                      // a special value
108     if (dn->bits&DECINF) targ=DECIMAL_Inf<<24;
109      else {                                       // sNaN or qNaN
110       if ((*dn->lsu!=0 || dn->digits>1)           // non-zero coefficient
111        && (dn->digits<DECIMAL32_Pmax)) {          // coefficient fits
112         decDigitsToDPD(dn, &targ, 0);
113         }
114       if (dn->bits&DECNAN) targ|=DECIMAL_NaN<<24;
115        else targ|=DECIMAL_sNaN<<24;
116       } // a NaN
117     } // special
118 
119    else { // is finite
120     if (decNumberIsZero(dn)) {               // is a zero
121       // set and clamp exponent
122       if (dn->exponent<-DECIMAL32_Bias) {
123         exp=0;                               // low clamp
124         status|=DEC_Clamped;
125         }
126        else {
127         exp=dn->exponent+DECIMAL32_Bias;     // bias exponent
128         if (exp>DECIMAL32_Ehigh) {           // top clamp
129           exp=DECIMAL32_Ehigh;
130           status|=DEC_Clamped;
131           }
132         }
133       comb=(exp>>3) & 0x18;             // msd=0, exp top 2 bits ..
134       }
135      else {                             // non-zero finite number
136       uInt msd;                         // work
137       Int pad=0;                        // coefficient pad digits
138 
139       // the dn is known to fit, but it may need to be padded
140       exp=(uInt)(dn->exponent+DECIMAL32_Bias);    // bias exponent
141       if (exp>DECIMAL32_Ehigh) {                  // fold-down case
142         pad=exp-DECIMAL32_Ehigh;
143         exp=DECIMAL32_Ehigh;                      // [to maximum]
144         status|=DEC_Clamped;
145         }
146 
147       // fastpath common case
148       if (DECDPUN==3 && pad==0) {
149         targ=BIN2DPD[dn->lsu[0]];
150         if (dn->digits>3) targ|=(uInt)(BIN2DPD[dn->lsu[1]])<<10;
151         msd=(dn->digits==7 ? dn->lsu[2] : 0);
152         }
153        else { // general case
154         decDigitsToDPD(dn, &targ, pad);
155         // save and clear the top digit
156         msd=targ>>20;
157         targ&=0x000fffff;
158         }
159 
160       // create the combination field
161       if (msd>=8) comb=0x18 | ((exp>>5) & 0x06) | (msd & 0x01);
162              else comb=((exp>>3) & 0x18) | msd;
163       }
164     targ|=comb<<26;                // add combination field ..
165     targ|=(exp&0x3f)<<20;          // .. and exponent continuation
166     } // finite
167 
168   if (dn->bits&DECNEG) targ|=0x80000000;  // add sign bit
169 
170   // now write to storage; this may be endian, or not
171   #if DECENDIAN
172   // DECENDIAN -- direct store
173   pu=(uInt *)d32->bytes;           // overlay
174   *pu=targ;                        // directly store the int
175   #else
176   // not DECENDIAN -- use network byte order
177   if (LITEND) {                    // little-endian needs reversal
178     uByte *pb;                     // work
179     for (pb=&d32->bytes[3]; pb>=d32->bytes; pb--) {
180       *pb=(uByte)(targ&0xff);
181       targ>>=8;
182       } // i
183     }
184    else { // big-endian; it's the right way round already
185     pu=(uInt *)d32->bytes;         // overlay
186     *pu=targ;                      // directly store the int
187     }
188   #endif
189 
190   if (status!=0) decContextSetStatus(set, status); // pass on status
191   // decimal32Show(d32);
192   return d32;
193   } // decimal32FromNumber
194 
195 /* ------------------------------------------------------------------ */
196 /* decimal32ToNumber -- convert decimal32 to decNumber                */
197 /*   d32 is the source decimal32                                      */
198 /*   dn is the target number, with appropriate space                  */
199 /* No error is possible.                                              */
200 /* ------------------------------------------------------------------ */
decimal32ToNumber(const decimal32 * d32,decNumber * dn)201 decNumber * decimal32ToNumber(const decimal32 *d32, decNumber *dn) {
202   uInt msd;                        // coefficient MSD
203   uInt exp;                        // exponent top two bits
204   uInt comb;                       // combination field
205   uInt *pu;                        // work
206   uInt sour;                       // source 32-bit
207 
208   // load source from storage; this may be endian, or not
209   #if DECENDIAN
210   // DECENDIAN -- direct load
211   pu=(uInt *)d32->bytes;           // overlay
212   sour=*pu;                        // directly load the int
213   #else
214   // not DECENDIAN -- use network byte order
215   if (LITEND) {                    // little-endian needs reversal
216     const uByte *pb;               // work
217     sour=0;                        // [keep compiler quiet]
218     for (pb=d32->bytes; pb<=&d32->bytes[3]; pb++) {
219       sour<<=8;
220       sour|=*pb;
221       } // i
222     }
223    else { // big-endian; it's the right way round already
224     pu=(uInt *)d32->bytes;         // overlay
225     sour=*pu;                      // directly load the int
226     }
227   #endif
228 
229   comb=(sour>>26)&0x1f;            // combination field
230 
231   decNumberZero(dn);               // clean number
232   if (sour&0x80000000) dn->bits=DECNEG; // set sign if negative
233 
234   msd=COMBMSD[comb];               // decode the combination field
235   exp=COMBEXP[comb];               // ..
236 
237   if (exp==3) {                    // is a special
238     if (msd==0) {
239       dn->bits|=DECINF;
240       return dn;                   // no coefficient needed
241       }
242     else if (sour&0x02000000) dn->bits|=DECSNAN;
243     else dn->bits|=DECNAN;
244     msd=0;                         // no top digit
245     }
246    else {                          // is a finite number
247     dn->exponent=(exp<<6)+((sour>>20)&0x3f)-DECIMAL32_Bias; // unbiased
248     }
249 
250   // get the coefficient
251   sour&=0x000fffff;                // clean coefficient continuation
252   if (msd) {                       // non-zero msd
253     sour|=msd<<20;                 // prefix to coefficient
254     decDigitsFromDPD(dn, &sour, 3); // process 3 declets
255     return dn;
256     }
257   // msd=0
258   if (!sour) return dn;            // easy: coefficient is 0
259   if (sour&0x000ffc00)             // need 2 declets?
260     decDigitsFromDPD(dn, &sour, 2); // process 2 declets
261    else
262     decDigitsFromDPD(dn, &sour, 1); // process 1 declet
263   return dn;
264   } // decimal32ToNumber
265 
266 /* ------------------------------------------------------------------ */
267 /* to-scientific-string -- conversion to numeric string               */
268 /* to-engineering-string -- conversion to numeric string              */
269 /*                                                                    */
270 /*   decimal32ToString(d32, string);                                  */
271 /*   decimal32ToEngString(d32, string);                               */
272 /*                                                                    */
273 /*  d32 is the decimal32 format number to convert                     */
274 /*  string is the string where the result will be laid out            */
275 /*                                                                    */
276 /*  string must be at least 24 characters                             */
277 /*                                                                    */
278 /*  No error is possible, and no status can be set.                   */
279 /* ------------------------------------------------------------------ */
decimal32ToEngString(const decimal32 * d32,char * string)280 char * decimal32ToEngString(const decimal32 *d32, char *string){
281   decNumber dn;                         // work
282   decimal32ToNumber(d32, &dn);
283   decNumberToEngString(&dn, string);
284   return string;
285   } // decimal32ToEngString
286 
decimal32ToString(const decimal32 * d32,char * string)287 char * decimal32ToString(const decimal32 *d32, char *string){
288   uInt msd;                        // coefficient MSD
289   Int  exp;                        // exponent top two bits or full
290   uInt comb;                       // combination field
291   char *cstart;                    // coefficient start
292   char *c;                         // output pointer in string
293   uInt *pu;                        // work
294   char *s, *t;                     // .. (source, target)
295   Int  dpd;                        // ..
296   Int  pre, e;                     // ..
297   const uByte *u;                  // ..
298   uInt sour;                       // source 32-bit
299 
300   // load source from storage; this may be endian, or not
301   #if DECENDIAN
302   // DECENDIAN -- direct load
303   pu=(uInt *)d32->bytes;           // overlay
304   sour=*pu;                        // directly load the int
305   #else
306   // not DECENDIAN -- use network byte order
307   if (LITEND) {                    // little-endian needs reversal
308     const uByte *pb;               // work
309     sour=0;                        // [keep compiler quiet]
310     for (pb=d32->bytes; pb<=&d32->bytes[3]; pb++) {
311       sour<<=8;
312       sour|=*pb;
313       } // i
314     }
315    else { // big-endian; it's the right way round already
316     pu=(uInt *)d32->bytes;         // overlay
317     sour=*pu;                      // directly load the int
318     }
319   #endif
320 
321   c=string;                        // where result will go
322   if (((Int)sour)<0) *c++='-';     // handle sign
323 
324   comb=(sour>>26)&0x1f;            // combination field
325   msd=COMBMSD[comb];               // decode the combination field
326   exp=COMBEXP[comb];               // ..
327 
328   if (exp==3) {
329     if (msd==0) {                  // infinity
330       strcpy(c, "Infinity");
331       return string;               // easy
332       }
333     if (sour&0x02000000) *c++='s'; // sNaN
334     strcpy(c, "NaN");              // complete word
335     c+=3;                          // step past
336     if ((sour&0x000fffff)==0) return string; // zero payload
337     // otherwise drop through to add integer; set correct exp
338     exp=0; msd=0;                  // setup for following code
339     }
340    else exp=(exp<<6)+((sour>>20)&0x3f)-DECIMAL32_Bias; // unbiased
341 
342   // convert 7 digits of significand to characters
343   cstart=c;                        // save start of coefficient
344   if (msd) *c++='0'+(char)msd;     // non-zero most significant digit
345 
346   // Now decode the declets.  After extracting each one, it is
347   // decoded to binary and then to a 4-char sequence by table lookup;
348   // the 4-chars are a 1-char length (significant digits, except 000
349   // has length 0).  This allows us to left-align the first declet
350   // with non-zero content, then remaining ones are full 3-char
351   // length.  We use fixed-length memcpys because variable-length
352   // causes a subroutine call in GCC.  (These are length 4 for speed
353   // and are safe because the array has an extra terminator byte.)
354   #define dpd2char u=&BIN2CHAR[DPD2BIN[dpd]*4];                   \
355                    if (c!=cstart) {memcpy(c, u+1, 4); c+=3;}      \
356                     else if (*u)  {memcpy(c, u+4-*u, 4); c+=*u;}
357 
358   dpd=(sour>>10)&0x3ff;            // declet 1
359   dpd2char;
360   dpd=(sour)&0x3ff;                // declet 2
361   dpd2char;
362 
363   if (c==cstart) *c++='0';         // all zeros -- make 0
364 
365   if (exp==0) {                    // integer or NaN case -- easy
366     *c='\0';                       // terminate
367     return string;
368     }
369 
370   /* non-0 exponent */
371   e=0;                             // assume no E
372   pre=c-cstart+exp;
373   // [here, pre-exp is the digits count (==1 for zero)]
374   if (exp>0 || pre<-5) {           // need exponential form
375     e=pre-1;                       // calculate E value
376     pre=1;                         // assume one digit before '.'
377     } // exponential form
378 
379   /* modify the coefficient, adding 0s, '.', and E+nn as needed */
380   s=c-1;                           // source (LSD)
381   if (pre>0) {                     // ddd.ddd (plain), perhaps with E
382     char *dotat=cstart+pre;
383     if (dotat<c) {                 // if embedded dot needed...
384       t=c;                              // target
385       for (; s>=dotat; s--, t--) *t=*s; // open the gap; leave t at gap
386       *t='.';                           // insert the dot
387       c++;                              // length increased by one
388       }
389 
390     // finally add the E-part, if needed; it will never be 0, and has
391     // a maximum length of 3 digits (E-101 case)
392     if (e!=0) {
393       *c++='E';                    // starts with E
394       *c++='+';                    // assume positive
395       if (e<0) {
396         *(c-1)='-';                // oops, need '-'
397         e=-e;                      // uInt, please
398         }
399       u=&BIN2CHAR[e*4];            // -> length byte
400       memcpy(c, u+4-*u, 4);        // copy fixed 4 characters [is safe]
401       c+=*u;                       // bump pointer appropriately
402       }
403     *c='\0';                       // add terminator
404     //printf("res %s\n", string);
405     return string;
406     } // pre>0
407 
408   /* -5<=pre<=0: here for plain 0.ddd or 0.000ddd forms (can never have E) */
409   t=c+1-pre;
410   *(t+1)='\0';                          // can add terminator now
411   for (; s>=cstart; s--, t--) *t=*s;    // shift whole coefficient right
412   c=cstart;
413   *c++='0';                             // always starts with 0.
414   *c++='.';
415   for (; pre<0; pre++) *c++='0';        // add any 0's after '.'
416   //printf("res %s\n", string);
417   return string;
418   } // decimal32ToString
419 
420 /* ------------------------------------------------------------------ */
421 /* to-number -- conversion from numeric string                        */
422 /*                                                                    */
423 /*   decimal32FromString(result, string, set);                        */
424 /*                                                                    */
425 /*  result  is the decimal32 format number which gets the result of   */
426 /*          the conversion                                            */
427 /*  *string is the character string which should contain a valid      */
428 /*          number (which may be a special value)                     */
429 /*  set     is the context                                            */
430 /*                                                                    */
431 /* The context is supplied to this routine is used for error handling */
432 /* (setting of status and traps) and for the rounding mode, only.     */
433 /* If an error occurs, the result will be a valid decimal32 NaN.      */
434 /* ------------------------------------------------------------------ */
decimal32FromString(decimal32 * result,const char * string,decContext * set)435 decimal32 * decimal32FromString(decimal32 *result, const char *string,
436                                 decContext *set) {
437   decContext dc;                             // work
438   decNumber dn;                              // ..
439 
440   decContextDefault(&dc, DEC_INIT_DECIMAL32); // no traps, please
441   dc.round=set->round;                        // use supplied rounding
442 
443   decNumberFromString(&dn, string, &dc);     // will round if needed
444   decimal32FromNumber(result, &dn, &dc);
445   if (dc.status!=0) {                        // something happened
446     decContextSetStatus(set, dc.status);     // .. pass it on
447     }
448   return result;
449   } // decimal32FromString
450 
451 #if DECTRACE || DECCHECK
452 /* ------------------------------------------------------------------ */
453 /* decimal32Show -- display a decimal32 in hexadecimal [debug aid]    */
454 /*   d32 -- the number to show                                        */
455 /* ------------------------------------------------------------------ */
456 // Also shows sign/cob/expconfields extracted - valid bigendian only
decimal32Show(const decimal32 * d32)457 void decimal32Show(const decimal32 *d32) {
458   char buf[DECIMAL32_Bytes*2+1];
459   Int i, j=0;
460 
461   #if DECENDIAN
462   if (LITEND) {
463     for (i=0; i<DECIMAL32_Bytes; i++, j+=2) {
464       sprintf(&buf[j], "%02x", d32->bytes[3-i]);
465       }
466     printf(" D32> %s [S:%d Cb:%02x Ec:%02x] LittleEndian\n", buf,
467            d32->bytes[3]>>7, (d32->bytes[3]>>2)&0x1f,
468            ((d32->bytes[3]&0x3)<<4)| (d32->bytes[2]>>4));
469     }
470    else {
471   #endif
472     for (i=0; i<DECIMAL32_Bytes; i++, j+=2) {
473       sprintf(&buf[j], "%02x", d32->bytes[i]);
474       }
475     printf(" D32> %s [S:%d Cb:%02x Ec:%02x] BigEndian\n", buf,
476            decimal32Sign(d32), decimal32Comb(d32), decimal32ExpCon(d32));
477   #if DECENDIAN
478     }
479   #endif
480   } // decimal32Show
481 #endif
482