1 /* ------------------------------------------------------------------ */
2 /* Decimal 128-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 decimal128 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 34 // make decNumbers with space for 34
33 #include "decNumber.h" // base number library
34 #include "decNumberLocal.h" // decNumber local types, etc.
35 #include "decimal128.h" // our primary include
36
37 /* Utility routines and tables [in decimal64.c] */
38 extern const uInt COMBEXP[32], COMBMSD[32];
39 extern const uShort DPD2BIN[1024];
40 extern const uShort BIN2DPD[1000]; // [not used]
41 extern const uByte BIN2CHAR[4001];
42
43 extern void decDigitsFromDPD(decNumber *, const uInt *, Int);
44 extern void decDigitsToDPD(const decNumber *, uInt *, Int);
45
46 #if DECTRACE || DECCHECK
47 void decimal128Show(const decimal128 *); // for debug
48 extern void decNumberShow(const decNumber *); // ..
49 #endif
50
51 /* compile-time endian tester [assumes sizeof(int)>1] */
52 static const Int mfcone=1; // constant 1
53 static const Flag *mfctop=(Flag *)&mfcone; // -> top byte
54 #define LITEND mfctop[0] // named flag; 1=little-endian
55
56 /* Useful macro */
57 // Clear a structure (e.g., a decNumber)
58 #define DEC_clear(d) memset(d, 0, sizeof(*d))
59
60 /* ------------------------------------------------------------------ */
61 /* decimal128FromNumber -- convert decNumber to decimal128 */
62 /* */
63 /* ds is the target decimal128 */
64 /* dn is the source number (assumed valid) */
65 /* set is the context, used only for reporting errors */
66 /* */
67 /* The set argument is used only for status reporting and for the */
68 /* rounding mode (used if the coefficient is more than DECIMAL128_Pmax*/
69 /* digits or an overflow is detected). If the exponent is out of the */
70 /* valid range then Overflow or Underflow will be raised. */
71 /* After Underflow a subnormal result is possible. */
72 /* */
73 /* DEC_Clamped is set if the number has to be 'folded down' to fit, */
74 /* by reducing its exponent and multiplying the coefficient by a */
75 /* power of ten, or if the exponent on a zero had to be clamped. */
76 /* ------------------------------------------------------------------ */
decimal128FromNumber(decimal128 * d128,const decNumber * dn,decContext * set)77 decimal128 * decimal128FromNumber(decimal128 *d128, const decNumber *dn,
78 decContext *set) {
79 uInt status=0; // status accumulator
80 Int ae; // adjusted exponent
81 decNumber dw; // work
82 decContext dc; // ..
83 uInt *pu; // ..
84 uInt comb, exp; // ..
85 uInt targar[4]={0,0,0,0}; // target 128-bit
86 #define targhi targar[3] // name the word with the sign
87 #define targmh targar[2] // name the words
88 #define targml targar[1] // ..
89 #define targlo targar[0] // ..
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 // decimal128]
96 ae=dn->exponent+dn->digits-1; // [0 if special]
97 if (dn->digits>DECIMAL128_Pmax // too many digits
98 || ae>DECIMAL128_Emax // likely overflow
99 || ae<DECIMAL128_Emin) { // likely underflow
100 decContextDefault(&dc, DEC_INIT_DECIMAL128); // [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<DECIMAL128_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<-DECIMAL128_Bias) {
125 exp=0; // low clamp
126 status|=DEC_Clamped;
127 }
128 else {
129 exp=dn->exponent+DECIMAL128_Bias; // bias exponent
130 if (exp>DECIMAL128_Ehigh) { // top clamp
131 exp=DECIMAL128_Ehigh;
132 status|=DEC_Clamped;
133 }
134 }
135 comb=(exp>>9) & 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+DECIMAL128_Bias); // bias exponent
143 if (exp>DECIMAL128_Ehigh) { // fold-down case
144 pad=exp-DECIMAL128_Ehigh;
145 exp=DECIMAL128_Ehigh; // [to maximum]
146 status|=DEC_Clamped;
147 }
148
149 // [fastpath for common case is not a win, here]
150 decDigitsToDPD(dn, targar, pad);
151 // save and clear the top digit
152 msd=targhi>>14;
153 targhi&=0x00003fff;
154
155 // create the combination field
156 if (msd>=8) comb=0x18 | ((exp>>11) & 0x06) | (msd & 0x01);
157 else comb=((exp>>9) & 0x18) | msd;
158 }
159 targhi|=comb<<26; // add combination field ..
160 targhi|=(exp&0xfff)<<14; // .. and exponent continuation
161 } // finite
162
163 if (dn->bits&DECNEG) targhi|=0x80000000; // add sign bit
164
165 // now write to storage; this may be endian, or not
166 #if DECENDIAN
167 // DECENDIAN -- direct store, in the right order
168 pu=(uInt *)d128->bytes; // overlay
169 if (LITEND) {
170 pu[0]=targlo; // directly store the low int
171 pu[1]=targml; // then the mid-low
172 pu[2]=targmh; // then the mid-high
173 pu[3]=targhi; // then the high int
174 }
175 else {
176 pu[0]=targhi; // directly store the high int
177 pu[1]=targmh; // then the mid-high
178 pu[2]=targml; // then the mid-low
179 pu[3]=targlo; // then the low int
180 }
181 #else
182 // not DECENDIAN -- use network byte order
183 if (LITEND) { // little-endian needs reversal
184 uByte *pb; // work
185 Int off; // ..
186 for (pb=&d128->bytes[15]; pb>=d128->bytes; pb--) {
187 off=3-((pb-d128->bytes)>>2); // 0, then 1, 2, 3
188 *pb=(uByte)(targar[off]&0xff);
189 targar[off]>>=8;
190 } // i
191 }
192 else { // big-endian; it's the right way round already
193 pu=(uInt *)d128->bytes; // overlay
194 pu[0]=targhi; // directly store the high int
195 pu[1]=targmh; // then the mid-high
196 pu[2]=targml; // then the mid-low
197 pu[3]=targlo; // then the low int
198 }
199 #endif
200
201 if (status!=0) decContextSetStatus(set, status); // pass on status
202 // decimal128Show(d128);
203 return d128;
204 } // decimal128FromNumber
205
206 /* ------------------------------------------------------------------ */
207 /* decimal128ToNumber -- convert decimal128 to decNumber */
208 /* d128 is the source decimal128 */
209 /* dn is the target number, with appropriate space */
210 /* No error is possible. */
211 /* ------------------------------------------------------------------ */
decimal128ToNumber(const decimal128 * d128,decNumber * dn)212 decNumber * decimal128ToNumber(const decimal128 *d128, decNumber *dn) {
213 uInt msd; // coefficient MSD
214 uInt exp; // exponent top two bits
215 uInt comb; // combination field
216 uInt *pu; // work
217 Int need; // ..
218 uInt sourar[4]; // source 128-bit
219 #define sourhi sourar[3] // name the word with the sign
220 #define sourmh sourar[2] // and the mid-high word
221 #define sourml sourar[1] // and the mod-low word
222 #define sourlo sourar[0] // and the lowest word
223
224 // load source from storage; this may be endian, or not
225 #if DECENDIAN
226 // DECENDIAN -- direct load, in the right order
227 pu=(uInt *)d128->bytes; // overlay
228 if (LITEND) {
229 sourlo=pu[0]; // directly load the low int
230 sourml=pu[1]; // then the mid-low
231 sourmh=pu[2]; // then the mid-high
232 sourhi=pu[3]; // then the high int
233 }
234 else {
235 sourhi=pu[0]; // directly load the high int
236 sourmh=pu[1]; // then the mid-high
237 sourml=pu[2]; // then the mid-low
238 sourlo=pu[3]; // then the low int
239 }
240 #else
241 // not DECENDIAN -- use network byte order
242 if (LITEND) { // little-endian needs reversal
243 const uByte *pb; // work
244 Int off; // ..
245 for (pb=d128->bytes; pb<=&d128->bytes[15]; pb++) {
246 off=3-((pb-d128->bytes)>>2); // 3, then 2, 1, 0
247 sourar[off]<<=8;
248 sourar[off]|=*pb;
249 } // i
250 }
251 else { // big-endian; it's the right way round already
252 pu=(uInt *)d128->bytes; // overlay
253 sourhi=pu[0]; // directly load the high int
254 sourmh=pu[1]; // then the mid-high
255 sourml=pu[2]; // then the mid-low
256 sourlo=pu[3]; // then the low int
257 }
258 #endif
259
260 comb=(sourhi>>26)&0x1f; // combination field
261
262 decNumberZero(dn); // clean number
263 if (sourhi&0x80000000) dn->bits=DECNEG; // set sign if negative
264
265 msd=COMBMSD[comb]; // decode the combination field
266 exp=COMBEXP[comb]; // ..
267
268 if (exp==3) { // is a special
269 if (msd==0) {
270 dn->bits|=DECINF;
271 return dn; // no coefficient needed
272 }
273 else if (sourhi&0x02000000) dn->bits|=DECSNAN;
274 else dn->bits|=DECNAN;
275 msd=0; // no top digit
276 }
277 else { // is a finite number
278 dn->exponent=(exp<<12)+((sourhi>>14)&0xfff)-DECIMAL128_Bias; // unbiased
279 }
280
281 // get the coefficient
282 sourhi&=0x00003fff; // clean coefficient continuation
283 if (msd) { // non-zero msd
284 sourhi|=msd<<14; // prefix to coefficient
285 need=12; // process 12 declets
286 }
287 else { // msd=0
288 if (sourhi) need=11; // declets to process
289 else if (sourmh) need=10;
290 else if (sourml) need=7;
291 else if (sourlo) need=4;
292 else return dn; // easy: coefficient is 0
293 } //msd=0
294
295 decDigitsFromDPD(dn, sourar, need); // process declets
296 // decNumberShow(dn);
297 return dn;
298 } // decimal128ToNumber
299
300 /* ------------------------------------------------------------------ */
301 /* to-scientific-string -- conversion to numeric string */
302 /* to-engineering-string -- conversion to numeric string */
303 /* */
304 /* decimal128ToString(d128, string); */
305 /* decimal128ToEngString(d128, string); */
306 /* */
307 /* d128 is the decimal128 format number to convert */
308 /* string is the string where the result will be laid out */
309 /* */
310 /* string must be at least 24 characters */
311 /* */
312 /* No error is possible, and no status can be set. */
313 /* ------------------------------------------------------------------ */
decimal128ToEngString(const decimal128 * d128,char * string)314 char * decimal128ToEngString(const decimal128 *d128, char *string){
315 decNumber dn; // work
316 decimal128ToNumber(d128, &dn);
317 decNumberToEngString(&dn, string);
318 return string;
319 } // decimal128ToEngString
320
decimal128ToString(const decimal128 * d128,char * string)321 char * decimal128ToString(const decimal128 *d128, char *string){
322 uInt msd; // coefficient MSD
323 Int exp; // exponent top two bits or full
324 uInt comb; // combination field
325 char *cstart; // coefficient start
326 char *c; // output pointer in string
327 uInt *pu; // work
328 char *s, *t; // .. (source, target)
329 Int dpd; // ..
330 Int pre, e; // ..
331 const uByte *u; // ..
332
333 uInt sourar[4]; // source 128-bit
334 #define sourhi sourar[3] // name the word with the sign
335 #define sourmh sourar[2] // and the mid-high word
336 #define sourml sourar[1] // and the mod-low word
337 #define sourlo sourar[0] // and the lowest word
338
339 // load source from storage; this may be endian, or not
340 #if DECENDIAN
341 // DECENDIAN -- direct load, in the right order
342 pu=(uInt *)d128->bytes; // overlay
343 if (LITEND) {
344 sourlo=pu[0]; // directly load the low int
345 sourml=pu[1]; // then the mid-low
346 sourmh=pu[2]; // then the mid-high
347 sourhi=pu[3]; // then the high int
348 }
349 else {
350 sourhi=pu[0]; // directly load the high int
351 sourmh=pu[1]; // then the mid-high
352 sourml=pu[2]; // then the mid-low
353 sourlo=pu[3]; // then the low int
354 }
355 #else
356 // not DECENDIAN -- use network byte order
357 if (LITEND) { // little-endian needs reversal
358 const uByte *pb; // work
359 Int off; // ..
360 for (pb=d128->bytes; pb<=&d128->bytes[15]; pb++) {
361 off=3-((pb-d128->bytes)>>2); // 3, then 2, 1, 0
362 sourar[off]<<=8;
363 sourar[off]|=*pb;
364 } // i
365 }
366 else { // big-endian; it's the right way round already
367 pu=(uInt *)d128->bytes; // overlay
368 sourhi=pu[0]; // directly load the high int
369 sourmh=pu[1]; // then the mid-high
370 sourml=pu[2]; // then the mid-low
371 sourlo=pu[3]; // 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 && sourml==0 && sourmh==0
391 && (sourhi&0x0003ffff)==0) return string; // zero payload
392 // otherwise drop through to add integer; set correct exp
393 exp=0; msd=0; // setup for following code
394 }
395 else exp=(exp<<12)+((sourhi>>14)&0xfff)-DECIMAL128_Bias; // unbiased
396
397 // convert 34 digits of significand to characters
398 cstart=c; // save start of coefficient
399 if (msd) *c++='0'+(char)msd; // non-zero most significant digit
400
401 // Now decode the declets. After extracting each one, it is
402 // decoded to binary and then to a 4-char sequence by table lookup;
403 // the 4-chars are a 1-char length (significant digits, except 000
404 // has length 0). This allows us to left-align the first declet
405 // with non-zero content, then remaining ones are full 3-char
406 // length. We use fixed-length memcpys because variable-length
407 // causes a subroutine call in GCC. (These are length 4 for speed
408 // and are safe because the array has an extra terminator byte.)
409 #define dpd2char u=&BIN2CHAR[DPD2BIN[dpd]*4]; \
410 if (c!=cstart) {memcpy(c, u+1, 4); c+=3;} \
411 else if (*u) {memcpy(c, u+4-*u, 4); c+=*u;}
412 dpd=(sourhi>>4)&0x3ff; // declet 1
413 dpd2char;
414 dpd=((sourhi&0xf)<<6) | (sourmh>>26); // declet 2
415 dpd2char;
416 dpd=(sourmh>>16)&0x3ff; // declet 3
417 dpd2char;
418 dpd=(sourmh>>6)&0x3ff; // declet 4
419 dpd2char;
420 dpd=((sourmh&0x3f)<<4) | (sourml>>28); // declet 5
421 dpd2char;
422 dpd=(sourml>>18)&0x3ff; // declet 6
423 dpd2char;
424 dpd=(sourml>>8)&0x3ff; // declet 7
425 dpd2char;
426 dpd=((sourml&0xff)<<2) | (sourlo>>30); // declet 8
427 dpd2char;
428 dpd=(sourlo>>20)&0x3ff; // declet 9
429 dpd2char;
430 dpd=(sourlo>>10)&0x3ff; // declet 10
431 dpd2char;
432 dpd=(sourlo)&0x3ff; // declet 11
433 dpd2char;
434
435 if (c==cstart) *c++='0'; // all zeros -- make 0
436
437 if (exp==0) { // integer or NaN case -- easy
438 *c='\0'; // terminate
439 return string;
440 }
441
442 /* non-0 exponent */
443 e=0; // assume no E
444 pre=c-cstart+exp;
445 // [here, pre-exp is the digits count (==1 for zero)]
446 if (exp>0 || pre<-5) { // need exponential form
447 e=pre-1; // calculate E value
448 pre=1; // assume one digit before '.'
449 } // exponential form
450
451 /* modify the coefficient, adding 0s, '.', and E+nn as needed */
452 s=c-1; // source (LSD)
453 if (pre>0) { // ddd.ddd (plain), perhaps with E
454 char *dotat=cstart+pre;
455 if (dotat<c) { // if embedded dot needed...
456 t=c; // target
457 for (; s>=dotat; s--, t--) *t=*s; // open the gap; leave t at gap
458 *t='.'; // insert the dot
459 c++; // length increased by one
460 }
461
462 // finally add the E-part, if needed; it will never be 0, and has
463 // a maximum length of 4 digits
464 if (e!=0) {
465 *c++='E'; // starts with E
466 *c++='+'; // assume positive
467 if (e<0) {
468 *(c-1)='-'; // oops, need '-'
469 e=-e; // uInt, please
470 }
471 if (e<1000) { // 3 (or fewer) digits case
472 u=&BIN2CHAR[e*4]; // -> length byte
473 memcpy(c, u+4-*u, 4); // copy fixed 4 characters [is safe]
474 c+=*u; // bump pointer appropriately
475 }
476 else { // 4-digits
477 Int thou=((e>>3)*1049)>>17; // e/1000
478 Int rem=e-(1000*thou); // e%1000
479 *c++='0'+(char)thou;
480 u=&BIN2CHAR[rem*4]; // -> length byte
481 memcpy(c, u+1, 4); // copy fixed 3+1 characters [is safe]
482 c+=3; // bump pointer, always 3 digits
483 }
484 }
485 *c='\0'; // add terminator
486 //printf("res %s\n", string);
487 return string;
488 } // pre>0
489
490 /* -5<=pre<=0: here for plain 0.ddd or 0.000ddd forms (can never have E) */
491 t=c+1-pre;
492 *(t+1)='\0'; // can add terminator now
493 for (; s>=cstart; s--, t--) *t=*s; // shift whole coefficient right
494 c=cstart;
495 *c++='0'; // always starts with 0.
496 *c++='.';
497 for (; pre<0; pre++) *c++='0'; // add any 0's after '.'
498 //printf("res %s\n", string);
499 return string;
500 } // decimal128ToString
501
502 /* ------------------------------------------------------------------ */
503 /* to-number -- conversion from numeric string */
504 /* */
505 /* decimal128FromString(result, string, set); */
506 /* */
507 /* result is the decimal128 format number which gets the result of */
508 /* the conversion */
509 /* *string is the character string which should contain a valid */
510 /* number (which may be a special value) */
511 /* set is the context */
512 /* */
513 /* The context is supplied to this routine is used for error handling */
514 /* (setting of status and traps) and for the rounding mode, only. */
515 /* If an error occurs, the result will be a valid decimal128 NaN. */
516 /* ------------------------------------------------------------------ */
decimal128FromString(decimal128 * result,const char * string,decContext * set)517 decimal128 * decimal128FromString(decimal128 *result, const char *string,
518 decContext *set) {
519 decContext dc; // work
520 decNumber dn; // ..
521
522 decContextDefault(&dc, DEC_INIT_DECIMAL128); // no traps, please
523 dc.round=set->round; // use supplied rounding
524
525 decNumberFromString(&dn, string, &dc); // will round if needed
526 decimal128FromNumber(result, &dn, &dc);
527 if (dc.status!=0) { // something happened
528 decContextSetStatus(set, dc.status); // .. pass it on
529 }
530 return result;
531 } // decimal128FromString
532
533 #if DECTRACE || DECCHECK
534 /* ------------------------------------------------------------------ */
535 /* decimal128Show -- display a decimal128 in hexadecimal [debug aid] */
536 /* d128 -- the number to show */
537 /* ------------------------------------------------------------------ */
538 // Also shows sign/cob/expconfields extracted
decimal128Show(const decimal128 * d128)539 void decimal128Show(const decimal128 *d128) {
540 char buf[DECIMAL128_Bytes*2+1];
541 Int i, j=0;
542
543 #if DECENDIAN
544 if (LITEND) {
545 for (i=0; i<DECIMAL128_Bytes; i++, j+=2) {
546 sprintf(&buf[j], "%02x", d128->bytes[15-i]);
547 }
548 printf(" D128> %s [S:%d Cb:%02x Ec:%02x] LittleEndian\n", buf,
549 d128->bytes[15]>>7, (d128->bytes[15]>>2)&0x1f,
550 ((d128->bytes[15]&0x3)<<10)|(d128->bytes[14]<<2)|
551 (d128->bytes[13]>>6));
552 }
553 else {
554 #endif
555 for (i=0; i<DECIMAL128_Bytes; i++, j+=2) {
556 sprintf(&buf[j], "%02x", d128->bytes[i]);
557 }
558 printf(" D128> %s [S:%d Cb:%02x Ec:%02x] BigEndian\n", buf,
559 decimal128Sign(d128), decimal128Comb(d128),
560 decimal128ExpCon(d128));
561 #if DECENDIAN
562 }
563 #endif
564 } // decimal128Show
565 #endif
566