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