dec_number 0.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (66) hide show
  1. data/README +20 -0
  2. data/dec_number.gemspec +13 -0
  3. data/ext/dec_number/Gemfile +4 -0
  4. data/ext/dec_number/NOTES +10 -0
  5. data/ext/dec_number/decNumber/ICU-license.html +45 -0
  6. data/ext/dec_number/decNumber/Makefile.am +3 -0
  7. data/ext/dec_number/decNumber/Makefile.in +680 -0
  8. data/ext/dec_number/decNumber/aclocal.m4 +8988 -0
  9. data/ext/dec_number/decNumber/autom4te.cache/output.0 +5107 -0
  10. data/ext/dec_number/decNumber/autom4te.cache/output.1 +6026 -0
  11. data/ext/dec_number/decNumber/autom4te.cache/output.2 +13468 -0
  12. data/ext/dec_number/decNumber/autom4te.cache/output.3 +13472 -0
  13. data/ext/dec_number/decNumber/autom4te.cache/requests +407 -0
  14. data/ext/dec_number/decNumber/autom4te.cache/traces.0 +352 -0
  15. data/ext/dec_number/decNumber/autom4te.cache/traces.1 +772 -0
  16. data/ext/dec_number/decNumber/autom4te.cache/traces.2 +591 -0
  17. data/ext/dec_number/decNumber/autom4te.cache/traces.3 +2362 -0
  18. data/ext/dec_number/decNumber/config.guess +1501 -0
  19. data/ext/dec_number/decNumber/config.h.in +142 -0
  20. data/ext/dec_number/decNumber/config.sub +1705 -0
  21. data/ext/dec_number/decNumber/configure +13468 -0
  22. data/ext/dec_number/decNumber/configure.ac +36 -0
  23. data/ext/dec_number/decNumber/decBasic.c +3908 -0
  24. data/ext/dec_number/decNumber/decCommon.c +1835 -0
  25. data/ext/dec_number/decNumber/decContext.c +437 -0
  26. data/ext/dec_number/decNumber/decContext.h +254 -0
  27. data/ext/dec_number/decNumber/decDPD.h +1185 -0
  28. data/ext/dec_number/decNumber/decDouble.c +140 -0
  29. data/ext/dec_number/decNumber/decDouble.h +155 -0
  30. data/ext/dec_number/decNumber/decNumber.c +8141 -0
  31. data/ext/dec_number/decNumber/decNumber.h +182 -0
  32. data/ext/dec_number/decNumber/decNumberLocal.h +757 -0
  33. data/ext/dec_number/decNumber/decPacked.c +220 -0
  34. data/ext/dec_number/decNumber/decPacked.h +52 -0
  35. data/ext/dec_number/decNumber/decQuad.c +135 -0
  36. data/ext/dec_number/decNumber/decQuad.h +177 -0
  37. data/ext/dec_number/decNumber/decSingle.c +71 -0
  38. data/ext/dec_number/decNumber/decSingle.h +86 -0
  39. data/ext/dec_number/decNumber/decimal128.c +553 -0
  40. data/ext/dec_number/decNumber/decimal128.h +81 -0
  41. data/ext/dec_number/decNumber/decimal32.c +476 -0
  42. data/ext/dec_number/decNumber/decimal32.h +81 -0
  43. data/ext/dec_number/decNumber/decimal64.c +839 -0
  44. data/ext/dec_number/decNumber/decimal64.h +83 -0
  45. data/ext/dec_number/decNumber/decnumber.pdf +0 -0
  46. data/ext/dec_number/decNumber/depcomp +630 -0
  47. data/ext/dec_number/decNumber/example1.c +38 -0
  48. data/ext/dec_number/decNumber/example2.c +52 -0
  49. data/ext/dec_number/decNumber/example3.c +64 -0
  50. data/ext/dec_number/decNumber/example4.c +61 -0
  51. data/ext/dec_number/decNumber/example5.c +36 -0
  52. data/ext/dec_number/decNumber/example6.c +61 -0
  53. data/ext/dec_number/decNumber/example7.c +35 -0
  54. data/ext/dec_number/decNumber/example8.c +39 -0
  55. data/ext/dec_number/decNumber/install-sh +520 -0
  56. data/ext/dec_number/decNumber/libdecNumber.a +0 -0
  57. data/ext/dec_number/decNumber/ltmain.sh +8745 -0
  58. data/ext/dec_number/decNumber/missing +376 -0
  59. data/ext/dec_number/decNumber/readme.txt +81 -0
  60. data/ext/dec_number/dec_number.c +464 -0
  61. data/ext/dec_number/extconf.rb +52 -0
  62. data/ext/dec_number/extconf2.rb +50 -0
  63. data/ext/dec_number/recompile.sh +3 -0
  64. data/ext/dec_number/test_dec_number.rb +236 -0
  65. data/ext/dec_number/test_numeric.rb +235 -0
  66. metadata +111 -0
@@ -0,0 +1,839 @@
1
+ /* ------------------------------------------------------------------ */
2
+ /* Decimal 64-bit format module */
3
+ /* ------------------------------------------------------------------ */
4
+ /* Copyright (c) IBM Corporation, 2000, 2009. 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, on the General Decimal Arithmetic page. */
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
+ /* This is used when decNumber provides operations, either for all */
23
+ /* operations or as a proxy between decNumber and decSingle. */
24
+ /* */
25
+ /* Error handling is the same as decNumber (qv.). */
26
+ /* ------------------------------------------------------------------ */
27
+ #include <string.h> // [for memset/memcpy]
28
+ #include <stdio.h> // [for printf]
29
+
30
+ #define DECNUMDIGITS 16 // make decNumbers with space for 16
31
+ #include "decNumber.h" // base number library
32
+ #include "decNumberLocal.h" // decNumber local types, etc.
33
+ #include "decimal64.h" // our primary include
34
+
35
+ /* Utility routines and tables [in decimal64.c]; externs for C++ */
36
+ // DPD2BIN and the reverse are renamed to prevent link-time conflict
37
+ // if decQuad is also built in the same executable
38
+ #define DPD2BIN DPD2BINx
39
+ #define BIN2DPD BIN2DPDx
40
+ extern const uInt COMBEXP[32], COMBMSD[32];
41
+ extern const uShort DPD2BIN[1024];
42
+ extern const uShort BIN2DPD[1000];
43
+ extern const uByte BIN2CHAR[4001];
44
+
45
+ extern void decDigitsFromDPD(decNumber *, const uInt *, Int);
46
+ extern void decDigitsToDPD(const decNumber *, uInt *, Int);
47
+
48
+ #if DECTRACE || DECCHECK
49
+ void decimal64Show(const decimal64 *); // for debug
50
+ extern void decNumberShow(const decNumber *); // ..
51
+ #endif
52
+
53
+ /* Useful macro */
54
+ // Clear a structure (e.g., a decNumber)
55
+ #define DEC_clear(d) memset(d, 0, sizeof(*d))
56
+
57
+ /* define and include the tables to use for conversions */
58
+ #define DEC_BIN2CHAR 1
59
+ #define DEC_DPD2BIN 1
60
+ #define DEC_BIN2DPD 1 // used for all sizes
61
+ #include "decDPD.h" // lookup tables
62
+
63
+ /* ------------------------------------------------------------------ */
64
+ /* decimal64FromNumber -- convert decNumber to decimal64 */
65
+ /* */
66
+ /* ds is the target decimal64 */
67
+ /* dn is the source number (assumed valid) */
68
+ /* set is the context, used only for reporting errors */
69
+ /* */
70
+ /* The set argument is used only for status reporting and for the */
71
+ /* rounding mode (used if the coefficient is more than DECIMAL64_Pmax */
72
+ /* digits or an overflow is detected). If the exponent is out of the */
73
+ /* valid range then Overflow or Underflow will be raised. */
74
+ /* After Underflow a subnormal result is possible. */
75
+ /* */
76
+ /* DEC_Clamped is set if the number has to be 'folded down' to fit, */
77
+ /* by reducing its exponent and multiplying the coefficient by a */
78
+ /* power of ten, or if the exponent on a zero had to be clamped. */
79
+ /* ------------------------------------------------------------------ */
80
+ decimal64 * decimal64FromNumber(decimal64 *d64, const decNumber *dn,
81
+ decContext *set) {
82
+ uInt status=0; // status accumulator
83
+ Int ae; // adjusted exponent
84
+ decNumber dw; // work
85
+ decContext dc; // ..
86
+ uInt comb, exp; // ..
87
+ uInt uiwork; // for macros
88
+ uInt targar[2]={0, 0}; // target 64-bit
89
+ #define targhi targar[1] // name the word with the sign
90
+ #define targlo targar[0] // and the other
91
+
92
+ // If the number has too many digits, or the exponent could be
93
+ // out of range then reduce the number under the appropriate
94
+ // constraints. This could push the number to Infinity or zero,
95
+ // so this check and rounding must be done before generating the
96
+ // decimal64]
97
+ ae=dn->exponent+dn->digits-1; // [0 if special]
98
+ if (dn->digits>DECIMAL64_Pmax // too many digits
99
+ || ae>DECIMAL64_Emax // likely overflow
100
+ || ae<DECIMAL64_Emin) { // likely underflow
101
+ decContextDefault(&dc, DEC_INIT_DECIMAL64); // [no traps]
102
+ dc.round=set->round; // use supplied rounding
103
+ decNumberPlus(&dw, dn, &dc); // (round and check)
104
+ // [this changes -0 to 0, so enforce the sign...]
105
+ dw.bits|=dn->bits&DECNEG;
106
+ status=dc.status; // save status
107
+ dn=&dw; // use the work number
108
+ } // maybe out of range
109
+
110
+ if (dn->bits&DECSPECIAL) { // a special value
111
+ if (dn->bits&DECINF) targhi=DECIMAL_Inf<<24;
112
+ else { // sNaN or qNaN
113
+ if ((*dn->lsu!=0 || dn->digits>1) // non-zero coefficient
114
+ && (dn->digits<DECIMAL64_Pmax)) { // coefficient fits
115
+ decDigitsToDPD(dn, targar, 0);
116
+ }
117
+ if (dn->bits&DECNAN) targhi|=DECIMAL_NaN<<24;
118
+ else targhi|=DECIMAL_sNaN<<24;
119
+ } // a NaN
120
+ } // special
121
+
122
+ else { // is finite
123
+ if (decNumberIsZero(dn)) { // is a zero
124
+ // set and clamp exponent
125
+ if (dn->exponent<-DECIMAL64_Bias) {
126
+ exp=0; // low clamp
127
+ status|=DEC_Clamped;
128
+ }
129
+ else {
130
+ exp=dn->exponent+DECIMAL64_Bias; // bias exponent
131
+ if (exp>DECIMAL64_Ehigh) { // top clamp
132
+ exp=DECIMAL64_Ehigh;
133
+ status|=DEC_Clamped;
134
+ }
135
+ }
136
+ comb=(exp>>5) & 0x18; // msd=0, exp top 2 bits ..
137
+ }
138
+ else { // non-zero finite number
139
+ uInt msd; // work
140
+ Int pad=0; // coefficient pad digits
141
+
142
+ // the dn is known to fit, but it may need to be padded
143
+ exp=(uInt)(dn->exponent+DECIMAL64_Bias); // bias exponent
144
+ if (exp>DECIMAL64_Ehigh) { // fold-down case
145
+ pad=exp-DECIMAL64_Ehigh;
146
+ exp=DECIMAL64_Ehigh; // [to maximum]
147
+ status|=DEC_Clamped;
148
+ }
149
+
150
+ // fastpath common case
151
+ if (DECDPUN==3 && pad==0) {
152
+ uInt dpd[6]={0,0,0,0,0,0};
153
+ uInt i;
154
+ Int d=dn->digits;
155
+ for (i=0; d>0; i++, d-=3) dpd[i]=BIN2DPD[dn->lsu[i]];
156
+ targlo =dpd[0];
157
+ targlo|=dpd[1]<<10;
158
+ targlo|=dpd[2]<<20;
159
+ if (dn->digits>6) {
160
+ targlo|=dpd[3]<<30;
161
+ targhi =dpd[3]>>2;
162
+ targhi|=dpd[4]<<8;
163
+ }
164
+ msd=dpd[5]; // [did not really need conversion]
165
+ }
166
+ else { // general case
167
+ decDigitsToDPD(dn, targar, pad);
168
+ // save and clear the top digit
169
+ msd=targhi>>18;
170
+ targhi&=0x0003ffff;
171
+ }
172
+
173
+ // create the combination field
174
+ if (msd>=8) comb=0x18 | ((exp>>7) & 0x06) | (msd & 0x01);
175
+ else comb=((exp>>5) & 0x18) | msd;
176
+ }
177
+ targhi|=comb<<26; // add combination field ..
178
+ targhi|=(exp&0xff)<<18; // .. and exponent continuation
179
+ } // finite
180
+
181
+ if (dn->bits&DECNEG) targhi|=0x80000000; // add sign bit
182
+
183
+ // now write to storage; this is now always endian
184
+ if (DECLITEND) {
185
+ // lo int then hi
186
+ UBFROMUI(d64->bytes, targar[0]);
187
+ UBFROMUI(d64->bytes+4, targar[1]);
188
+ }
189
+ else {
190
+ // hi int then lo
191
+ UBFROMUI(d64->bytes, targar[1]);
192
+ UBFROMUI(d64->bytes+4, targar[0]);
193
+ }
194
+
195
+ if (status!=0) decContextSetStatus(set, status); // pass on status
196
+ // decimal64Show(d64);
197
+ return d64;
198
+ } // decimal64FromNumber
199
+
200
+ /* ------------------------------------------------------------------ */
201
+ /* decimal64ToNumber -- convert decimal64 to decNumber */
202
+ /* d64 is the source decimal64 */
203
+ /* dn is the target number, with appropriate space */
204
+ /* No error is possible. */
205
+ /* ------------------------------------------------------------------ */
206
+ decNumber * decimal64ToNumber(const decimal64 *d64, decNumber *dn) {
207
+ uInt msd; // coefficient MSD
208
+ uInt exp; // exponent top two bits
209
+ uInt comb; // combination field
210
+ Int need; // work
211
+ uInt uiwork; // for macros
212
+ uInt sourar[2]; // source 64-bit
213
+ #define sourhi sourar[1] // name the word with the sign
214
+ #define sourlo sourar[0] // and the lower word
215
+
216
+ // load source from storage; this is endian
217
+ if (DECLITEND) {
218
+ sourlo=UBTOUI(d64->bytes ); // directly load the low int
219
+ sourhi=UBTOUI(d64->bytes+4); // then the high int
220
+ }
221
+ else {
222
+ sourhi=UBTOUI(d64->bytes ); // directly load the high int
223
+ sourlo=UBTOUI(d64->bytes+4); // then the low int
224
+ }
225
+
226
+ comb=(sourhi>>26)&0x1f; // combination field
227
+
228
+ decNumberZero(dn); // clean number
229
+ if (sourhi&0x80000000) dn->bits=DECNEG; // set sign if negative
230
+
231
+ msd=COMBMSD[comb]; // decode the combination field
232
+ exp=COMBEXP[comb]; // ..
233
+
234
+ if (exp==3) { // is a special
235
+ if (msd==0) {
236
+ dn->bits|=DECINF;
237
+ return dn; // no coefficient needed
238
+ }
239
+ else if (sourhi&0x02000000) dn->bits|=DECSNAN;
240
+ else dn->bits|=DECNAN;
241
+ msd=0; // no top digit
242
+ }
243
+ else { // is a finite number
244
+ dn->exponent=(exp<<8)+((sourhi>>18)&0xff)-DECIMAL64_Bias; // unbiased
245
+ }
246
+
247
+ // get the coefficient
248
+ sourhi&=0x0003ffff; // clean coefficient continuation
249
+ if (msd) { // non-zero msd
250
+ sourhi|=msd<<18; // prefix to coefficient
251
+ need=6; // process 6 declets
252
+ }
253
+ else { // msd=0
254
+ if (!sourhi) { // top word 0
255
+ if (!sourlo) return dn; // easy: coefficient is 0
256
+ need=3; // process at least 3 declets
257
+ if (sourlo&0xc0000000) need++; // process 4 declets
258
+ // [could reduce some more, here]
259
+ }
260
+ else { // some bits in top word, msd=0
261
+ need=4; // process at least 4 declets
262
+ if (sourhi&0x0003ff00) need++; // top declet!=0, process 5
263
+ }
264
+ } //msd=0
265
+
266
+ decDigitsFromDPD(dn, sourar, need); // process declets
267
+ return dn;
268
+ } // decimal64ToNumber
269
+
270
+
271
+ /* ------------------------------------------------------------------ */
272
+ /* to-scientific-string -- conversion to numeric string */
273
+ /* to-engineering-string -- conversion to numeric string */
274
+ /* */
275
+ /* decimal64ToString(d64, string); */
276
+ /* decimal64ToEngString(d64, string); */
277
+ /* */
278
+ /* d64 is the decimal64 format number to convert */
279
+ /* string is the string where the result will be laid out */
280
+ /* */
281
+ /* string must be at least 24 characters */
282
+ /* */
283
+ /* No error is possible, and no status can be set. */
284
+ /* ------------------------------------------------------------------ */
285
+ char * decimal64ToEngString(const decimal64 *d64, char *string){
286
+ decNumber dn; // work
287
+ decimal64ToNumber(d64, &dn);
288
+ decNumberToEngString(&dn, string);
289
+ return string;
290
+ } // decimal64ToEngString
291
+
292
+ char * decimal64ToString(const decimal64 *d64, char *string){
293
+ uInt msd; // coefficient MSD
294
+ Int exp; // exponent top two bits or full
295
+ uInt comb; // combination field
296
+ char *cstart; // coefficient start
297
+ char *c; // output pointer in string
298
+ const uByte *u; // work
299
+ char *s, *t; // .. (source, target)
300
+ Int dpd; // ..
301
+ Int pre, e; // ..
302
+ uInt uiwork; // for macros
303
+
304
+ uInt sourar[2]; // source 64-bit
305
+ #define sourhi sourar[1] // name the word with the sign
306
+ #define sourlo sourar[0] // and the lower word
307
+
308
+ // load source from storage; this is endian
309
+ if (DECLITEND) {
310
+ sourlo=UBTOUI(d64->bytes ); // directly load the low int
311
+ sourhi=UBTOUI(d64->bytes+4); // then the high int
312
+ }
313
+ else {
314
+ sourhi=UBTOUI(d64->bytes ); // directly load the high int
315
+ sourlo=UBTOUI(d64->bytes+4); // then the low int
316
+ }
317
+
318
+ c=string; // where result will go
319
+ if (((Int)sourhi)<0) *c++='-'; // handle sign
320
+
321
+ comb=(sourhi>>26)&0x1f; // combination field
322
+ msd=COMBMSD[comb]; // decode the combination field
323
+ exp=COMBEXP[comb]; // ..
324
+
325
+ if (exp==3) {
326
+ if (msd==0) { // infinity
327
+ strcpy(c, "Inf");
328
+ strcpy(c+3, "inity");
329
+ return string; // easy
330
+ }
331
+ if (sourhi&0x02000000) *c++='s'; // sNaN
332
+ strcpy(c, "NaN"); // complete word
333
+ c+=3; // step past
334
+ if (sourlo==0 && (sourhi&0x0003ffff)==0) return string; // zero payload
335
+ // otherwise drop through to add integer; set correct exp
336
+ exp=0; msd=0; // setup for following code
337
+ }
338
+ else exp=(exp<<8)+((sourhi>>18)&0xff)-DECIMAL64_Bias;
339
+
340
+ // convert 16 digits of significand to characters
341
+ cstart=c; // save start of coefficient
342
+ if (msd) *c++='0'+(char)msd; // non-zero most significant digit
343
+
344
+ // Now decode the declets. After extracting each one, it is
345
+ // decoded to binary and then to a 4-char sequence by table lookup;
346
+ // the 4-chars are a 1-char length (significant digits, except 000
347
+ // has length 0). This allows us to left-align the first declet
348
+ // with non-zero content, then remaining ones are full 3-char
349
+ // length. We use fixed-length memcpys because variable-length
350
+ // causes a subroutine call in GCC. (These are length 4 for speed
351
+ // and are safe because the array has an extra terminator byte.)
352
+ #define dpd2char u=&BIN2CHAR[DPD2BIN[dpd]*4]; \
353
+ if (c!=cstart) {memcpy(c, u+1, 4); c+=3;} \
354
+ else if (*u) {memcpy(c, u+4-*u, 4); c+=*u;}
355
+
356
+ dpd=(sourhi>>8)&0x3ff; // declet 1
357
+ dpd2char;
358
+ dpd=((sourhi&0xff)<<2) | (sourlo>>30); // declet 2
359
+ dpd2char;
360
+ dpd=(sourlo>>20)&0x3ff; // declet 3
361
+ dpd2char;
362
+ dpd=(sourlo>>10)&0x3ff; // declet 4
363
+ dpd2char;
364
+ dpd=(sourlo)&0x3ff; // declet 5
365
+ dpd2char;
366
+
367
+ if (c==cstart) *c++='0'; // all zeros -- make 0
368
+
369
+ if (exp==0) { // integer or NaN case -- easy
370
+ *c='\0'; // terminate
371
+ return string;
372
+ }
373
+
374
+ /* non-0 exponent */
375
+ e=0; // assume no E
376
+ pre=c-cstart+exp;
377
+ // [here, pre-exp is the digits count (==1 for zero)]
378
+ if (exp>0 || pre<-5) { // need exponential form
379
+ e=pre-1; // calculate E value
380
+ pre=1; // assume one digit before '.'
381
+ } // exponential form
382
+
383
+ /* modify the coefficient, adding 0s, '.', and E+nn as needed */
384
+ s=c-1; // source (LSD)
385
+ if (pre>0) { // ddd.ddd (plain), perhaps with E
386
+ char *dotat=cstart+pre;
387
+ if (dotat<c) { // if embedded dot needed...
388
+ t=c; // target
389
+ for (; s>=dotat; s--, t--) *t=*s; // open the gap; leave t at gap
390
+ *t='.'; // insert the dot
391
+ c++; // length increased by one
392
+ }
393
+
394
+ // finally add the E-part, if needed; it will never be 0, and has
395
+ // a maximum length of 3 digits
396
+ if (e!=0) {
397
+ *c++='E'; // starts with E
398
+ *c++='+'; // assume positive
399
+ if (e<0) {
400
+ *(c-1)='-'; // oops, need '-'
401
+ e=-e; // uInt, please
402
+ }
403
+ u=&BIN2CHAR[e*4]; // -> length byte
404
+ memcpy(c, u+4-*u, 4); // copy fixed 4 characters [is safe]
405
+ c+=*u; // bump pointer appropriately
406
+ }
407
+ *c='\0'; // add terminator
408
+ //printf("res %s\n", string);
409
+ return string;
410
+ } // pre>0
411
+
412
+ /* -5<=pre<=0: here for plain 0.ddd or 0.000ddd forms (can never have E) */
413
+ t=c+1-pre;
414
+ *(t+1)='\0'; // can add terminator now
415
+ for (; s>=cstart; s--, t--) *t=*s; // shift whole coefficient right
416
+ c=cstart;
417
+ *c++='0'; // always starts with 0.
418
+ *c++='.';
419
+ for (; pre<0; pre++) *c++='0'; // add any 0's after '.'
420
+ //printf("res %s\n", string);
421
+ return string;
422
+ } // decimal64ToString
423
+
424
+ /* ------------------------------------------------------------------ */
425
+ /* to-number -- conversion from numeric string */
426
+ /* */
427
+ /* decimal64FromString(result, string, set); */
428
+ /* */
429
+ /* result is the decimal64 format number which gets the result of */
430
+ /* the conversion */
431
+ /* *string is the character string which should contain a valid */
432
+ /* number (which may be a special value) */
433
+ /* set is the context */
434
+ /* */
435
+ /* The context is supplied to this routine is used for error handling */
436
+ /* (setting of status and traps) and for the rounding mode, only. */
437
+ /* If an error occurs, the result will be a valid decimal64 NaN. */
438
+ /* ------------------------------------------------------------------ */
439
+ decimal64 * decimal64FromString(decimal64 *result, const char *string,
440
+ decContext *set) {
441
+ decContext dc; // work
442
+ decNumber dn; // ..
443
+
444
+ decContextDefault(&dc, DEC_INIT_DECIMAL64); // no traps, please
445
+ dc.round=set->round; // use supplied rounding
446
+
447
+ decNumberFromString(&dn, string, &dc); // will round if needed
448
+
449
+ decimal64FromNumber(result, &dn, &dc);
450
+ if (dc.status!=0) { // something happened
451
+ decContextSetStatus(set, dc.status); // .. pass it on
452
+ }
453
+ return result;
454
+ } // decimal64FromString
455
+
456
+ /* ------------------------------------------------------------------ */
457
+ /* decimal64IsCanonical -- test whether encoding is canonical */
458
+ /* d64 is the source decimal64 */
459
+ /* returns 1 if the encoding of d64 is canonical, 0 otherwise */
460
+ /* No error is possible. */
461
+ /* ------------------------------------------------------------------ */
462
+ uInt decimal64IsCanonical(const decimal64 *d64) {
463
+ decNumber dn; // work
464
+ decimal64 canon; // ..
465
+ decContext dc; // ..
466
+ decContextDefault(&dc, DEC_INIT_DECIMAL64);
467
+ decimal64ToNumber(d64, &dn);
468
+ decimal64FromNumber(&canon, &dn, &dc);// canon will now be canonical
469
+ return memcmp(d64, &canon, DECIMAL64_Bytes)==0;
470
+ } // decimal64IsCanonical
471
+
472
+ /* ------------------------------------------------------------------ */
473
+ /* decimal64Canonical -- copy an encoding, ensuring it is canonical */
474
+ /* d64 is the source decimal64 */
475
+ /* result is the target (may be the same decimal64) */
476
+ /* returns result */
477
+ /* No error is possible. */
478
+ /* ------------------------------------------------------------------ */
479
+ decimal64 * decimal64Canonical(decimal64 *result, const decimal64 *d64) {
480
+ decNumber dn; // work
481
+ decContext dc; // ..
482
+ decContextDefault(&dc, DEC_INIT_DECIMAL64);
483
+ decimal64ToNumber(d64, &dn);
484
+ decimal64FromNumber(result, &dn, &dc);// result will now be canonical
485
+ return result;
486
+ } // decimal64Canonical
487
+
488
+ #if DECTRACE || DECCHECK
489
+ /* Macros for accessing decimal64 fields. These assume the
490
+ argument is a reference (pointer) to the decimal64 structure,
491
+ and the decimal64 is in network byte order (big-endian) */
492
+ // Get sign
493
+ #define decimal64Sign(d) ((unsigned)(d)->bytes[0]>>7)
494
+
495
+ // Get combination field
496
+ #define decimal64Comb(d) (((d)->bytes[0] & 0x7c)>>2)
497
+
498
+ // Get exponent continuation [does not remove bias]
499
+ #define decimal64ExpCon(d) ((((d)->bytes[0] & 0x03)<<6) \
500
+ | ((unsigned)(d)->bytes[1]>>2))
501
+
502
+ // Set sign [this assumes sign previously 0]
503
+ #define decimal64SetSign(d, b) { \
504
+ (d)->bytes[0]|=((unsigned)(b)<<7);}
505
+
506
+ // Set exponent continuation [does not apply bias]
507
+ // This assumes range has been checked and exponent previously 0;
508
+ // type of exponent must be unsigned
509
+ #define decimal64SetExpCon(d, e) { \
510
+ (d)->bytes[0]|=(uByte)((e)>>6); \
511
+ (d)->bytes[1]|=(uByte)(((e)&0x3F)<<2);}
512
+
513
+ /* ------------------------------------------------------------------ */
514
+ /* decimal64Show -- display a decimal64 in hexadecimal [debug aid] */
515
+ /* d64 -- the number to show */
516
+ /* ------------------------------------------------------------------ */
517
+ // Also shows sign/cob/expconfields extracted
518
+ void decimal64Show(const decimal64 *d64) {
519
+ char buf[DECIMAL64_Bytes*2+1];
520
+ Int i, j=0;
521
+
522
+ if (DECLITEND) {
523
+ for (i=0; i<DECIMAL64_Bytes; i++, j+=2) {
524
+ sprintf(&buf[j], "%02x", d64->bytes[7-i]);
525
+ }
526
+ printf(" D64> %s [S:%d Cb:%02x Ec:%02x] LittleEndian\n", buf,
527
+ d64->bytes[7]>>7, (d64->bytes[7]>>2)&0x1f,
528
+ ((d64->bytes[7]&0x3)<<6)| (d64->bytes[6]>>2));
529
+ }
530
+ else { // big-endian
531
+ for (i=0; i<DECIMAL64_Bytes; i++, j+=2) {
532
+ sprintf(&buf[j], "%02x", d64->bytes[i]);
533
+ }
534
+ printf(" D64> %s [S:%d Cb:%02x Ec:%02x] BigEndian\n", buf,
535
+ decimal64Sign(d64), decimal64Comb(d64), decimal64ExpCon(d64));
536
+ }
537
+ } // decimal64Show
538
+ #endif
539
+
540
+ /* ================================================================== */
541
+ /* Shared utility routines and tables */
542
+ /* ================================================================== */
543
+ // define and include the conversion tables to use for shared code
544
+ #if DECDPUN==3
545
+ #define DEC_DPD2BIN 1
546
+ #else
547
+ #define DEC_DPD2BCD 1
548
+ #endif
549
+ #include "decDPD.h" // lookup tables
550
+
551
+ // The maximum number of decNumberUnits needed for a working copy of
552
+ // the units array is the ceiling of digits/DECDPUN, where digits is
553
+ // the maximum number of digits in any of the formats for which this
554
+ // is used. decimal128.h must not be included in this module, so, as
555
+ // a very special case, that number is defined as a literal here.
556
+ #define DECMAX754 34
557
+ #define DECMAXUNITS ((DECMAX754+DECDPUN-1)/DECDPUN)
558
+
559
+ /* ------------------------------------------------------------------ */
560
+ /* Combination field lookup tables (uInts to save measurable work) */
561
+ /* */
562
+ /* COMBEXP - 2-bit most-significant-bits of exponent */
563
+ /* [11 if an Infinity or NaN] */
564
+ /* COMBMSD - 4-bit most-significant-digit */
565
+ /* [0=Infinity, 1=NaN if COMBEXP=11] */
566
+ /* */
567
+ /* Both are indexed by the 5-bit combination field (0-31) */
568
+ /* ------------------------------------------------------------------ */
569
+ const uInt COMBEXP[32]={0, 0, 0, 0, 0, 0, 0, 0,
570
+ 1, 1, 1, 1, 1, 1, 1, 1,
571
+ 2, 2, 2, 2, 2, 2, 2, 2,
572
+ 0, 0, 1, 1, 2, 2, 3, 3};
573
+ const uInt COMBMSD[32]={0, 1, 2, 3, 4, 5, 6, 7,
574
+ 0, 1, 2, 3, 4, 5, 6, 7,
575
+ 0, 1, 2, 3, 4, 5, 6, 7,
576
+ 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
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*DECPOWERS[cut];
643
+ next+=quot;
644
+ #else
645
+ uInt rem=*source%DECPOWERS[cut];
646
+ next+=*source/DECPOWERS[cut];
647
+ #endif
648
+ if (target<=first) *target=(Unit)next; // write to target iff valid
649
+ next=rem*DECPOWERS[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
+ /* ------------------------------------------------------------------ */
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; // [if using this code for wider, check this]
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*DECPOWERS[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*DECPOWERS[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*DECPOWERS[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=&DECPOWERS[4]; *last>=*pow; pow++) dn->digits++;
834
+ #endif
835
+ #endif
836
+ #endif
837
+ #endif
838
+ return;
839
+ } //decDigitsFromDPD