4 conversions and numerical operations for the c# type System.Decimal
6 Author: Martin Weindel (martin.weindel@t-online.de)
8 (C) 2001 by Martin Weindel
12 * machine dependent configuration for
13 * CSharp value type System.Decimal
22 /* needed for building microsoft dll */
23 #define DECINLINE __inline
25 #define LIT_GUINT32(x) x
26 #define LIT_GUINT64(x) x##L
31 /* we need a UInt64 type => guint64 */
35 #else /* #ifndef _MSC_VER */
37 /* Microsoft Compiler for testing */
39 typedef short gint16; /* that's normally defined in glib */
40 typedef unsigned short guint16; /* that's normally defined in glib */
41 typedef int gint32; /* that's normally defined in glib */
42 typedef unsigned int guint32; /* that's normally defined in glib */
43 typedef __int64 gint64; /* that's normally defined in glib */
44 typedef unsigned __int64 guint64; /* that's normally defined in glib */
47 #error this platform is not supported
55 * Deal with anon union support.
58 #define signscale u.signscale
63 #define PRECONDITION(flag) assert(flag)
64 #define POSTCONDITION(flag) assert(flag)
65 #define TEST(flag) assert(flag)
66 #define INVARIANT_TEST(p) assert(p->signscale.scale >= 0 && p->signscale.scale <= DECIMAL_MAX_SCALE \
67 && p->signscale.reserved1 == 0 && p->signscale.reserved2 == 0);
69 #define PRECONDITION(flag)
70 #define POSTCONDITION(flag)
72 #define INVARIANT_TEST(p)
73 #endif //#ifdef _DEBUG
76 void DECSIGNATURE printdec(decimal_repr* pA)
78 printf("sign=%d scale=%d %u %u %u\n", (int)pA->signscale.sign, (int) pA->signscale.scale,
79 pA->hi32, pA->mid32, pA->lo32);
83 #define DECIMAL_REPR_CONSTANT(ss, hi, mid, lo) {{ss}, hi, lo, mid}
85 #define DECIMAL_MAX_SCALE 28
86 #define DECIMAL_MAX_INTFACTORS 9
88 #define DECIMAL_SUCCESS 0
89 #define DECIMAL_FINISHED 1
90 #define DECIMAL_OVERFLOW 2
91 #define DECIMAL_INVALID_CHARACTER 2
92 #define DECIMAL_INTERNAL_ERROR 3
93 #define DECIMAL_INVALID_BITS 4
94 #define DECIMAL_DIVIDE_BY_ZERO 5
97 #define DECINIT(src) memset(src, 0, sizeof(decimal_repr))
99 #define DECCOPY(dest, src) memcpy(dest, src, sizeof(decimal_repr))
101 #define DECSWAP(p1, p2, h) \
102 h = (p1)->ss32; (p1)->ss32 = (p2)->ss32; (p2)->ss32 = h; \
103 h = (p1)->hi32; (p1)->hi32 = (p2)->hi32; (p2)->hi32 = h; \
104 h = (p1)->mid32; (p1)->mid32 = (p2)->mid32; (p2)->mid32 = h; \
105 h = (p1)->lo32; (p1)->lo32 = (p2)->lo32; (p2)->lo32 = h;
107 #define DECNEGATE(p1) (p1)->signscale.sign = 1 - (p1)->signscale.sign
109 #define DECTO128(pd, lo, hi) \
110 lo = (((guint64)(pd)->mid32) << 32) | (pd)->lo32; \
114 #define LIT_GUINT32_HIGHBIT LIT_GUINT32(0x80000000)
115 #define LIT_GUINT64_HIGHBIT LIT_GUINT64(0x8000000000000000)
117 #define DECIMAL_LOG_NEGINF -1000
119 static guint32 constantsIntFactors[DECIMAL_MAX_INTFACTORS+1] = {
120 LIT_GUINT32(1), LIT_GUINT32(10), LIT_GUINT32(100), LIT_GUINT32(1000),
121 LIT_GUINT32(10000), LIT_GUINT32(100000), LIT_GUINT32(1000000),
122 LIT_GUINT32(10000000), LIT_GUINT32(100000000), LIT_GUINT32(1000000000)
125 static decimal_repr constantsFactors[DECIMAL_MAX_SCALE+1] = {
126 DECIMAL_REPR_CONSTANT(0, 0, 0, 1), /* == 1 */
127 DECIMAL_REPR_CONSTANT(0, 0, 0, 10), /* == 10 */
128 DECIMAL_REPR_CONSTANT(0, 0, 0, 100), /* == 100 */
129 DECIMAL_REPR_CONSTANT(0, 0, 0, 1000), /* == 1e3m */
130 DECIMAL_REPR_CONSTANT(0, 0, 0, 10000), /* == 1e4m */
131 DECIMAL_REPR_CONSTANT(0, 0, 0, 100000), /* == 1e5m */
132 DECIMAL_REPR_CONSTANT(0, 0, 0, 1000000), /* == 1e6m */
133 DECIMAL_REPR_CONSTANT(0, 0, 0, 10000000), /* == 1e7m */
134 DECIMAL_REPR_CONSTANT(0, 0, 0, 100000000), /* == 1e8m */
135 DECIMAL_REPR_CONSTANT(0, 0, 0, 1000000000), /* == 1e9m */
136 DECIMAL_REPR_CONSTANT(0, 0, 2, 1410065408), /* == 1e10m */
137 DECIMAL_REPR_CONSTANT(0, 0, 23, 1215752192), /* == 1e11m */
138 DECIMAL_REPR_CONSTANT(0, 0, 232, 3567587328U), /* == 1e12m */
139 DECIMAL_REPR_CONSTANT(0, 0, 2328, 1316134912), /* == 1e13m */
140 DECIMAL_REPR_CONSTANT(0, 0, 23283, 276447232), /* == 1e14m */
141 DECIMAL_REPR_CONSTANT(0, 0, 232830, 2764472320U), /* == 1e15m */
142 DECIMAL_REPR_CONSTANT(0, 0, 2328306, 1874919424), /* == 1e16m */
143 DECIMAL_REPR_CONSTANT(0, 0, 23283064, 1569325056), /* == 1e17m */
144 DECIMAL_REPR_CONSTANT(0, 0, 232830643, 2808348672U), /* == 1e18m */
145 DECIMAL_REPR_CONSTANT(0, 0, 2328306436U, 2313682944U), /* == 1e19m */
146 DECIMAL_REPR_CONSTANT(0, 5, 1808227885, 1661992960), /* == 1e20m */
147 DECIMAL_REPR_CONSTANT(0, 54, 902409669, 3735027712U), /* == 1e21m */
148 DECIMAL_REPR_CONSTANT(0, 542, 434162106, 2990538752U), /* == 1e22m */
149 DECIMAL_REPR_CONSTANT(0, 5421, 46653770, 4135583744U), /* == 1e23m */
150 DECIMAL_REPR_CONSTANT(0, 54210, 466537709, 2701131776U), /* == 1e24m */
151 DECIMAL_REPR_CONSTANT(0, 542101, 370409800, 1241513984), /* == 1e25m */
152 DECIMAL_REPR_CONSTANT(0, 5421010, 3704098002U, 3825205248U), /* == 1e26m */
153 DECIMAL_REPR_CONSTANT(0, 54210108, 2681241660U, 3892314112U), /* == 1e27m */
154 DECIMAL_REPR_CONSTANT(0, 542101086, 1042612833, 268435456), /* == 1e28m */
157 /* 192 bit addition: c = a + b
158 addition is modulo 2**128, any carry is lost */
159 static DECINLINE void add128(guint64 alo, guint64 ahi,
160 guint64 blo, guint64 bhi,
161 guint64* pclo, guint64* pchi)
164 if (alo < blo) ahi++; /* carry */
171 /* 128 bit subtraction: c = a - b
172 subtraction is modulo 2**128, any carry is lost */
173 static DECINLINE void sub128(guint64 alo, guint64 ahi,
174 guint64 blo, guint64 bhi,
175 guint64* pclo, guint64* pchi)
181 if (alo < blo) chi--; /* borrow */
187 /* 192 bit addition: c = a + b
188 addition is modulo 2**192, any carry is lost */
189 static DECINLINE void add192(guint64 alo, guint64 ami, guint64 ahi,
190 guint64 blo, guint64 bmi, guint64 bhi,
191 guint64* pclo, guint64* pcmi, guint64* pchi)
194 if (alo < blo) { /* carry low */
196 if (ami == 0) ahi++; /* carry mid */
199 if (ami < bmi) ahi++; /* carry mid */
206 /* 192 bit subtraction: c = a - b
207 subtraction is modulo 2**192, any carry is lost */
208 static DECINLINE void sub192(guint64 alo, guint64 ami, guint64 ahi,
209 guint64 blo, guint64 bmi, guint64 bhi,
210 guint64* pclo, guint64* pcmi, guint64* pchi)
212 guint64 clo, cmi, chi;
218 if (cmi == 0) chi--; /* borrow mid */
219 cmi--; /* borrow low */
221 if (ami < bmi) chi--; /* borrow mid */
227 /* multiplication c(192bit) = a(96bit) * b(96bit) */
228 static DECINLINE void mult96by96to192(guint32 alo, guint32 ami, guint32 ahi,
229 guint32 blo, guint32 bmi, guint32 bhi,
230 guint64* pclo, guint64* pcmi, guint64* pchi)
233 guint32 h0, h1, h2, h3, h4, h5;
236 a = ((guint64)alo) * blo;
239 a >>= 32; carry0 = 0;
240 b = ((guint64)alo) * bmi;
241 c = ((guint64)ami) * blo;
242 a += b; if (a < b) carry0++;
243 a += c; if (a < c) carry0++;
246 a >>= 32; carry1 = 0;
247 b = ((guint64)alo) * bhi;
248 c = ((guint64)ami) * bmi;
249 d = ((guint64)ahi) * blo;
250 a += b; if (a < b) carry1++;
251 a += c; if (a < c) carry1++;
252 a += d; if (a < d) carry1++;
255 a >>= 32; a += carry0; carry0 = 0;
256 b = ((guint64)ami) * bhi;
257 c = ((guint64)ahi) * bmi;
258 a += b; if (a < b) carry0++;
259 a += c; if (a < c) carry0++;
262 a >>= 32; a += carry1;
263 b = ((guint64)ahi) * bhi;
267 a >>= 32; a += carry0;
270 *pclo = ((guint64)h1) << 32 | h0;
271 *pcmi = ((guint64)h3) << 32 | h2;
272 *pchi = ((guint64)h5) << 32 | h4;
275 /* multiplication c(128bit) = a(96bit) * b(32bit) */
276 static DECINLINE void mult96by32to128(guint32 alo, guint32 ami, guint32 ahi,
278 guint64* pclo, guint64* pchi)
283 a = ((guint64)alo) * factor;
287 a += ((guint64)ami) * factor;
291 a += ((guint64)ahi) * factor;
293 *pclo = ((guint64)h1) << 32 | h0;
297 /* multiplication c(128bit) *= b(32bit) */
298 static DECINLINE int mult128by32(guint64* pclo, guint64* pchi, guint32 factor, int roundBit)
303 a = ((guint64)(guint32)(*pclo)) * factor;
304 if (roundBit) a += factor / 2;
308 a += (*pclo >> 32) * factor;
311 *pclo = ((guint64)h1) << 32 | h0;
314 a += ((guint64)(guint32)(*pchi)) * factor;
318 a += (*pchi >> 32) * factor;
321 *pchi = ((guint64)h1) << 32 | h0;
323 return ((a >> 32) == 0) ? DECIMAL_SUCCESS : DECIMAL_OVERFLOW;
326 /* division: x(128bit) /= factor(32bit)
328 static DECINLINE int div128by32(guint64* plo, guint64* phi, guint32 factor, guint32* pRest)
333 a = (guint32)(h >> 32);
341 *phi = b << 32 | (guint32)c;
344 a |= (guint32)(h >> 32);
351 *plo = b << 32 | (guint32)c;
353 if (pRest) *pRest = (guint32) a;
356 return (a > factor || (a == factor && (c & 1) == 1)) ? 1 : 0;
359 /* division: x(192bit) /= factor(32bit)
360 no rest and no rounding*/
361 static DECINLINE void div192by32(guint64* plo, guint64* pmi, guint64* phi,
367 a = (guint32)(h >> 32);
375 *phi = b << 32 | (guint32)c;
378 a |= (guint32)(h >> 32);
386 *pmi = b << 32 | (guint32)c;
389 a |= (guint32)(h >> 32);
397 *plo = b << 32 | (guint32)c;
400 /* returns upper 32bit for a(192bit) /= b(32bit)
401 a will contain remainder */
402 static DECINLINE guint32 div192by96to32withRest(guint64* palo, guint64* pami, guint64* pahi,
403 guint32 blo, guint32 bmi, guint32 bhi)
405 guint64 rlo, rmi, rhi; /* remainder */
406 guint64 tlo, thi; /* term */
409 rlo = *palo; rmi = *pami; rhi = *pahi;
410 if (rhi >= (((guint64)bhi) << 32)) {
411 c = LIT_GUINT32(0xFFFFFFFF);
413 c = (guint32) (rhi / bhi);
415 mult96by32to128(blo, bmi, bhi, c, &tlo, &thi);
416 sub192(rlo, rmi, rhi, 0, tlo, thi, &rlo, &rmi, &rhi);
417 while (((gint64)rhi) < 0) {
419 add192(rlo, rmi, rhi, 0, (((guint64)bmi)<<32) | blo, bhi, &rlo, &rmi, &rhi);
421 *palo = rlo ; *pami = rmi ; *pahi = rhi;
423 POSTCONDITION(rhi >> 32 == 0);
428 /* c(128bit) = a(192bit) / b(96bit)
430 static DECINLINE void div192by96to128(guint64 alo, guint64 ami, guint64 ahi,
431 guint32 blo, guint32 bmi, guint32 bhi,
432 guint64* pclo, guint64* pchi)
434 guint64 rlo, rmi, rhi; /* remainder */
437 PRECONDITION(ahi < (((guint64)bhi) << 32 | bmi)
438 || (ahi == (((guint64)bhi) << 32 | bmi) && (ami >> 32) > blo));
441 rlo = alo; rmi = ami; rhi = ahi;
442 h = div192by96to32withRest(&rlo, &rmi, &rhi, blo, bmi, bhi);
445 rhi = (rhi << 32) | (rmi >> 32); rmi = (rmi << 32) | (rlo >> 32); rlo <<= 32;
446 *pchi = (((guint64)h) << 32) | div192by96to32withRest(&rlo, &rmi, &rhi, blo, bmi, bhi);
449 rhi = (rhi << 32) | (rmi >> 32); rmi = (rmi << 32) | (rlo >> 32); rlo <<= 32;
450 h = div192by96to32withRest(&rlo, &rmi, &rhi, blo, bmi, bhi);
452 /* estimate lowest 32 bit (two last bits may be wrong) */
454 c = LIT_GUINT32(0xFFFFFFFF);
457 c = (guint32) (rhi / bhi);
459 *pclo = (((guint64)h) << 32) | c;
462 static DECINLINE void roundUp128(guint64* pclo, guint64* pchi) {
463 if (++(*pclo) == 0) ++(*pchi);
466 static int normalize128(guint64* pclo, guint64* pchi, int* pScale,
467 int roundFlag, int roundBit)
469 guint32 overhang = (guint32)(*pchi >> 32);
473 while (overhang != 0) {
474 for (deltaScale = 1; deltaScale < DECIMAL_MAX_INTFACTORS; deltaScale++)
476 if (overhang < constantsIntFactors[deltaScale]) break;
480 if (scale < 0) return DECIMAL_OVERFLOW;
482 roundBit = div128by32(pclo, pchi, constantsIntFactors[deltaScale], 0);
484 overhang = (guint32)(*pchi >> 32);
485 if (roundFlag && roundBit && *pclo == (guint64)-1 && (gint32)*pchi == (gint32)-1) {
492 if (roundFlag && roundBit) {
493 roundUp128(pclo, pchi);
494 TEST((*pchi >> 32) == 0);
497 return DECIMAL_SUCCESS;
500 static DECINLINE int maxLeftShift(/*[In, Out]*/decimal_repr* pA)
502 guint64 lo64 = (((guint64)(pA->mid32)) << 32) | pA->lo32;
503 guint32 hi32 = pA->hi32;
506 for (shift = 0; ((gint32)hi32) >= 0 && shift < 96; shift++) {
508 if (((gint64)lo64) < 0) hi32++;
512 pA->lo32 = (guint32) lo64;
513 pA->mid32 = (guint32)(lo64>>32);
519 static DECINLINE void rshift128(guint64* pclo, guint64* pchi)
522 if (*pchi & 1) *pclo |= LIT_GUINT64_HIGHBIT;
526 static DECINLINE void lshift96(guint32* pclo, guint32* pcmid, guint32* pchi)
529 if (*pcmid & LIT_GUINT32_HIGHBIT) (*pchi)++;
531 if (*pclo & LIT_GUINT32_HIGHBIT) (*pcmid)++;
535 static DECINLINE void lshift128(guint64* pclo, guint64* pchi)
538 if (*pclo & LIT_GUINT64_HIGHBIT) (*pchi)++;
542 static DECINLINE void rshift192(guint64* pclo, guint64* pcmi, guint64* pchi)
545 if (*pcmi & 1) *pclo |= LIT_GUINT64_HIGHBIT;
547 if (*pchi & 1) *pcmi |= LIT_GUINT64_HIGHBIT;
551 /* returns log2(a) or DECIMAL_LOG_NEGINF for a = 0 */
552 static int DECINLINE log2_32(guint32 a)
556 if (a == 0) return DECIMAL_LOG_NEGINF;
558 if ((a >> 16) != 0) {
583 /* returns log2(a) or DECIMAL_LOG_NEGINF for a = 0 */
584 static int DECINLINE log2_64(guint64 a)
588 if (a == 0) return DECIMAL_LOG_NEGINF;
590 if ((a >> 32) != 0) {
594 if ((a >> 16) != 0) {
619 /* returns log2(a) or DECIMAL_LOG_NEGINF for a = 0 */
620 static int DECINLINE log2_128(guint64 alo, guint64 ahi)
622 if (ahi == 0) return log2_64(alo);
623 else return log2_64(ahi) + 64;
626 /* returns a upper limit for log2(a) considering scale */
627 static int DECINLINE log2withScale_128(guint64 alo, guint64 ahi, int scale)
629 int log2 = log2_128(alo, ahi);
630 if (log2 < 0) log2 = 0;
631 return log2 - (scale * 33219) / 10000;
634 static DECINLINE int pack128toDecimal(/*[Out]*/decimal_repr* pA, guint64 alo, guint64 ahi,
637 PRECONDITION((ahi >> 32) == 0);
638 PRECONDITION(sign == 0 || sign == 1);
639 PRECONDITION(scale >= 0 && scale <= DECIMAL_MAX_SCALE);
641 if (scale < 0 || scale > DECIMAL_MAX_SCALE || (ahi >> 32) != 0) {
642 return DECIMAL_OVERFLOW;
645 pA->lo32 = (guint32) alo;
646 pA->mid32 = (guint32) (alo >> 32);
647 pA->hi32 = (guint32) ahi;
648 pA->signscale.sign = sign;
649 pA->signscale.scale = scale;
651 return DECIMAL_SUCCESS;
654 static DECINLINE int adjustScale128(guint64* palo, guint64* pahi, int deltaScale)
658 if (deltaScale < 0) {
660 if (deltaScale > DECIMAL_MAX_SCALE) return DECIMAL_INTERNAL_ERROR;
661 while (deltaScale > 0) {
662 index = (deltaScale > DECIMAL_MAX_INTFACTORS) ? DECIMAL_MAX_INTFACTORS : deltaScale;
664 div128by32(palo, pahi, constantsIntFactors[index], 0);
666 } else if (deltaScale > 0) {
667 if (deltaScale > DECIMAL_MAX_SCALE) return DECIMAL_INTERNAL_ERROR;
668 while (deltaScale > 0) {
669 index = (deltaScale > DECIMAL_MAX_INTFACTORS) ? DECIMAL_MAX_INTFACTORS : deltaScale;
671 rc = mult128by32(palo, pahi, constantsIntFactors[index], 0);
672 if (rc != DECIMAL_SUCCESS) return rc;
676 return DECIMAL_SUCCESS;
679 /* input: c * 10^-(*pScale) * 2^-exp
680 output: c * 10^-(*pScale) with
681 minScale <= *pScale <= maxScale and (chi >> 32) == 0 */
682 static int DECINLINE rescale128(guint64* pclo, guint64* pchi, int* pScale, int exp,
683 int minScale, int maxScale, int roundFlag)
685 guint32 factor, overhang;
686 int scale, i, rc, roundBit = 0;
688 PRECONDITION(exp >= 0);
694 while (exp > 0 && scale <= maxScale) {
695 overhang = (guint32)(*pchi >> 32);
696 while (exp > 0 && ((*pclo & 1) == 0 || overhang > (2<<DECIMAL_MAX_INTFACTORS))) {
697 if (--exp == 0) roundBit = (int)(*pclo & 1);
698 rshift128(pclo, pchi);
699 overhang = (guint32)(*pchi >> 32);
702 if (exp > DECIMAL_MAX_INTFACTORS) i = DECIMAL_MAX_INTFACTORS;
704 if (scale + i > maxScale) i = maxScale - scale;
708 factor = constantsIntFactors[i] >> i; /* 10^i/2^i=5^i */
709 mult128by32(pclo, pchi, factor, 0);
710 //printf("3: %.17e\n", (((double)chi) * pow(2,64) + clo) * pow(10, -scale) * pow(2, -exp));
714 if (--exp == 0) roundBit = (int)(*pclo & 1);
715 rshift128(pclo, pchi);
721 while (scale > maxScale) {
722 i = scale - maxScale;
723 if (i > DECIMAL_MAX_INTFACTORS) i = DECIMAL_MAX_INTFACTORS;
725 roundBit = div128by32(pclo, pchi, constantsIntFactors[i], 0);
728 while (scale < minScale) {
729 if (!roundFlag) roundBit = 0;
730 i = minScale - scale;
731 if (i > DECIMAL_MAX_INTFACTORS) i = DECIMAL_MAX_INTFACTORS;
733 rc = mult128by32(pclo, pchi, constantsIntFactors[i], roundBit);
734 if (rc != DECIMAL_SUCCESS) return rc;
738 TEST(scale >= 0 && scale <= DECIMAL_MAX_SCALE);
742 return normalize128(pclo, pchi, pScale, roundFlag, roundBit);
745 /* performs a += b */
746 gint32 mono_decimalIncr(/*[In, Out]*/decimal_repr* pA, /*[In]*/decimal_repr* pB)
748 guint64 alo, ahi, blo, bhi;
749 int log2A, log2B, log2Result, log10Result, rc;
750 int subFlag, sign, scaleA, scaleB;
752 DECTO128(pA, alo, ahi);
753 DECTO128(pB, blo, bhi);
755 sign = pA->signscale.sign;
756 subFlag = sign - (int)pB->signscale.sign;
757 scaleA = pA->signscale.scale;
758 scaleB = pB->signscale.scale;
759 if (scaleA == scaleB) {
760 /* same scale, that's easy */
762 sub128(alo, ahi, blo, bhi, &alo, &ahi);
763 if (ahi & LIT_GUINT64_HIGHBIT) {
771 add128(alo, ahi, blo, bhi, &alo, &ahi);
773 rc = normalize128(&alo, &ahi, &scaleA, 1, 0);
775 /* scales must be adjusted */
776 /* Estimate log10 and scale of result for adjusting scales */
777 log2A = log2withScale_128(alo, ahi, scaleA);
778 log2B = log2withScale_128(blo, bhi, scaleB);
779 log2Result = (log2A >= log2B) ? log2A : log2B;
780 if (!subFlag) log2Result++; /* result can have one bit more */
781 log10Result = (log2Result * 1000) / 3322 + 1;
782 /* we will calculate in 128bit, so we may need to adjust scale */
783 if (scaleB > scaleA) scaleA = scaleB;
784 if (scaleA + log10Result > DECIMAL_MAX_SCALE + 7) {
785 /* this may not fit in 128bit, so limit it */
786 scaleA = DECIMAL_MAX_SCALE + 7 - log10Result;
789 rc = adjustScale128(&alo, &ahi, scaleA - (int)pA->signscale.scale);
790 if (rc != DECIMAL_SUCCESS) return rc;
791 rc = adjustScale128(&blo, &bhi, scaleA - scaleB);
792 if (rc != DECIMAL_SUCCESS) return rc;
795 sub128(alo, ahi, blo, bhi, &alo, &ahi);
796 if (ahi & LIT_GUINT64_HIGHBIT) {
804 add128(alo, ahi, blo, bhi, &alo, &ahi);
807 if (rc != DECIMAL_SUCCESS) return rc;
809 rc = rescale128(&alo, &ahi,&scaleA, 0, 0, DECIMAL_MAX_SCALE, 1);
812 if (rc != DECIMAL_SUCCESS) return rc;
814 return pack128toDecimal(pA, alo, ahi, scaleA, sign);
817 /* performs a += factor * constants[index] */
818 static int incMultConstant128(guint64* palo, guint64* pahi, int index, int factor)
822 PRECONDITION(index >= 0 && index <= DECIMAL_MAX_SCALE);
823 PRECONDITION(factor > 0 && factor <= 9);
825 DECTO128(constantsFactors + index, blo, bhi);
828 mult128by32(&blo, &bhi, factor, 0);
829 if (h > bhi) return DECIMAL_OVERFLOW;
832 add128(*palo, *pahi, blo, bhi, palo, pahi);
833 if (h > *pahi) return DECIMAL_OVERFLOW;
834 return DECIMAL_SUCCESS;
837 gint32 mono_double2decimal(/*[Out]*/decimal_repr* pA, double val, gint32 digits, gint32 sign)
839 int i, dec, decrDecimal, dummySign, roundPos, roundFlag, rc;
840 char ecvtcopy[40]; /* we should need maximal room for 16 digits */
841 char buf[40]; /* we should need maximal room for 29 digits */
844 decimal_repr roundAdd;
849 /* floating point number must be convert to the decimal system for rounding anyway
850 so we use conversion to character representation as starting point.
851 We ask for more than the significant digits, as we must round
852 according to banker's rule finally */
853 /* FIXME: the following 2 lines must be made thread safe (access to global buffer of ecvt) */
854 p = ecvt(val, digits+4, &dec, &dummySign);
858 /*test printf("%s %d digits:%d\n", ps, dec, digits);*/
859 /* determine round position */
860 roundPos = dec + DECIMAL_MAX_SCALE;
861 if (roundPos > digits) roundPos = digits; /* maximal sigificant digits */
863 /* build decimal string */
865 /* leading zeros for numbers < 1 */
866 for (i = dec; i < 0; i++)
869 /* significant digits */
870 for (i = 0; i < roundPos; i++)
873 /* trailing zeros for numbers > 1 */
874 for (i = roundPos; i < dec; i++)
880 /* position of decimal point */
884 decrDecimal = 0; /* as we have added leading zero digits */
887 /* convert string to decimal */
888 mstring = mono_string_new (buf);
889 rc = mono_string2decimal(pA, mstring, decrDecimal, sign);
890 /* FIXME: we currently leak the string: mono_string_free (mstring); */
891 if (rc != DECIMAL_SUCCESS) return rc;
893 /* do we need to upround according to banker's rule ? */
896 } else if (*ps >= '6') {
898 } else { /* banker's rule for case '5' */
899 roundFlag = ((*(ps-1) - '0') % 2 == 1);
902 /*test printf("round!!! dec=%d decrDecimal=%d roundPos=%d scale=%d\n", dec, decrDecimal, roundPos, pA->signscale.scale); printdec(pA); printdec(&roundAdd);*/
903 DECCOPY(&roundAdd, constantsFactors + dec + pA->signscale.scale - roundPos);
904 roundAdd.ss32 = pA->ss32;
905 /* perform rounding */
906 mono_decimalIncr(pA, &roundAdd);
909 return DECIMAL_SUCCESS;
912 /* converts string to decimal */
913 gint32 mono_string2decimal(/*[Out]*/decimal_repr* pA, MonoString* str, gint32 decrDecimal, gint32 sign)
922 buf = mono_string_chars (str);
924 if (len > DECIMAL_MAX_SCALE+1) {
925 return DECIMAL_OVERFLOW;
928 for (i = 0; i < len; i++) {
930 if (n < 0 || n > 9) {
931 return DECIMAL_INVALID_CHARACTER;
934 rc = incMultConstant128(&alo, &ahi, len - 1 - i, n);
935 if (rc != DECIMAL_SUCCESS) {
941 if (alo == 0 && ahi == 0) {
943 return DECIMAL_SUCCESS;
945 return pack128toDecimal(pA, alo, ahi, len - decrDecimal, sign);
949 /* calc significant digits of mantisse */
950 static int DECINLINE calcDigits(/*[In]*/decimal_repr* pA)
955 decimal_repr* pConst;
962 if (a == 0) return 0; /* zero has no signficant digits */
970 log2 += log2_32(a); /* get floor value of log2(a) */
972 log10 = (log2 * 1000) / 3322;
973 /* we need an exact floor value of log10(a) */
974 pConst = constantsFactors + log10;
975 if (pConst->hi32 > pA->hi32
976 || (pConst->hi32 == pA->hi32 && (pConst->mid32 > pA->mid32
977 || (pConst->mid32 == pA->mid32 && pConst->lo32 > pA->lo32)))) {
984 pA decimal instance to convert
985 digits < 0: use decimals instead
986 = 0: gets mantisse as integer
987 > 0: gets at most <digits> digits, rounded according to banker's rule if necessary
988 decimals only used if digits < 0
990 buf pointer to result buffer
991 bufSize size of buffer
992 pDecPos receives insert position of decimal point relative to start of buffer
993 pSign receives sign */
994 void mono_decimal2string(/*[In]*/decimal_repr* pA, int digits, int decimals,
995 MonoArray* buf, gint32 bufSize, gint32* pDecPos, gint32* pSign)
1000 int i, scale, sigDigits;
1001 gushort* p = (gushort*) mono_array_addr (buf, gushort, 0);
1004 scale = pA->signscale.scale;
1005 sigDigits = calcDigits(pA);
1007 if (digits < 0) { /* use decimals ? */
1008 if (0 <= decimals && decimals < scale) {
1009 digits = sigDigits - scale + decimals;
1010 if (digits == 0) digits = -1; /* no digits */
1012 digits = 0; /* use all you can get */
1016 if (digits > 0 && digits <= DECIMAL_MAX_SCALE) { /* significant digits */
1017 if (sigDigits > digits) { /* we need to round decimal number */
1019 aa.signscale.scale = DECIMAL_MAX_SCALE;
1020 mono_decimalRound(&aa, DECIMAL_MAX_SCALE - sigDigits + digits);
1021 sigDigits += calcDigits(&aa) - digits;
1022 DECTO128(&aa, alo, ahi);
1024 DECTO128(pA, alo, ahi);
1027 DECTO128(pA, alo, ahi);
1031 /* get digits starting from the tail */
1032 for (i = 0; (alo != 0 || ahi != 0) && i < bufSize-1; i++) {
1033 div128by32(&alo, &ahi, 10, &rest);
1034 *p++ = '0' + (char) rest;
1040 /* reverse string */
1041 p = (gushort*) mono_array_addr (buf, gushort, 0);
1049 if (digits > 0 && digits < bufSize)
1050 mono_array_set (buf, gushort, digits, 0);
1052 *pDecPos = sigDigits - scale;
1053 *pSign = pA->signscale.sign;
1056 static DECINLINE void div128DecimalFactor(guint64* palo, guint64* pahi, int powerOfTen)
1058 int index, roundBit = 0;
1060 while (powerOfTen > 0) {
1061 index = (powerOfTen > DECIMAL_MAX_INTFACTORS) ? DECIMAL_MAX_INTFACTORS : powerOfTen;
1062 powerOfTen -= index;
1063 roundBit = div128by32(palo, pahi, constantsIntFactors[index], 0);
1066 if (roundBit) roundUp128(palo, pahi);
1069 gint32 mono_decimal2UInt64(/*[In]*/decimal_repr* pA, guint64* pResult)
1074 DECTO128(pA, alo, ahi);
1075 scale = pA->signscale.scale;
1077 div128DecimalFactor(&alo, &ahi, scale);
1080 /* overflow if integer too large or < 0 */
1081 if (ahi != 0 || (alo != 0 && pA->signscale.sign)) return DECIMAL_OVERFLOW;
1084 return DECIMAL_SUCCESS;
1087 gint32 mono_decimal2Int64(/*[In]*/decimal_repr* pA, gint64* pResult)
1092 DECTO128(pA, alo, ahi);
1093 scale = pA->signscale.scale;
1095 div128DecimalFactor(&alo, &ahi, scale);
1098 if (ahi != 0) return DECIMAL_OVERFLOW;
1100 sign = pA->signscale.sign;
1101 if (sign && alo != 0) {
1102 if (alo > LIT_GUINT64_HIGHBIT) return DECIMAL_OVERFLOW;
1103 *pResult = (gint64) ~(alo-1);
1105 if (alo & LIT_GUINT64_HIGHBIT) return DECIMAL_OVERFLOW;
1106 *pResult = (gint64) alo;
1109 return DECIMAL_SUCCESS;
1112 void mono_decimalFloorAndTrunc(/*[In, Out]*/decimal_repr* pA, gint32 floorFlag)
1115 guint32 factor, rest;
1116 int scale, sign, index;
1119 scale = pA->signscale.scale;
1120 if (scale == 0) return; /* nothing to do */
1122 DECTO128(pA, alo, ahi);
1123 sign = pA->signscale.sign;
1126 index = (scale > DECIMAL_MAX_INTFACTORS) ? DECIMAL_MAX_INTFACTORS : scale;
1127 factor = constantsIntFactors[index];
1129 div128by32(&alo, &ahi, factor, &rest);
1130 hasRest = hasRest || (rest != 0);
1133 if (floorFlag && hasRest && sign) { /* floor: if negative, we must round up */
1134 roundUp128(&alo, &ahi);
1137 pack128toDecimal(pA, alo, ahi, 0, sign);
1140 void mono_decimalRound(/*[In, Out]*/decimal_repr* pA, gint32 decimals)
1145 DECTO128(pA, alo, ahi);
1146 scale = pA->signscale.scale;
1147 sign = pA->signscale.sign;
1148 if (scale > decimals) {
1149 div128DecimalFactor(&alo, &ahi, scale - decimals);
1153 pack128toDecimal(pA, alo, ahi, scale, sign);
1156 gint32 mono_decimalMult(/*[In, Out]*/decimal_repr* pA, /*[In]*/decimal_repr* pB)
1158 guint64 low, mid, high;
1160 int scale, sign, rc;
1162 mult96by96to192(pA->lo32, pA->mid32, pA->hi32, pB->lo32, pB->mid32, pB->hi32,
1165 /* adjust scale and sign */
1166 scale = (int)pA->signscale.scale + (int)pB->signscale.scale;
1167 sign = pA->signscale.sign ^ pB->signscale.sign;
1169 /* first scaling step */
1170 factor = constantsIntFactors[DECIMAL_MAX_INTFACTORS];
1171 while (high != 0 || (mid>>32) >= factor) {
1173 factor /= 1000; /* we need some digits for final rounding */
1174 scale -= DECIMAL_MAX_INTFACTORS - 3;
1176 scale -= DECIMAL_MAX_INTFACTORS;
1179 div192by32(&low, &mid, &high, factor);
1182 /* second and final scaling */
1183 rc = rescale128(&low, &mid, &scale, 0, 0, DECIMAL_MAX_SCALE, 1);
1184 if (rc != DECIMAL_SUCCESS) return rc;
1186 return pack128toDecimal(pA, low, mid, scale, sign);
1189 static int DECINLINE decimalDivSub(/*[In]*/decimal_repr* pA, /*[In]*/decimal_repr* pB,
1190 guint64* pclo, guint64* pchi, int* pExp)
1192 guint64 alo, ami, ahi;
1193 guint64 tlo, tmi, thi;
1194 guint32 blo, bmi, bhi;
1195 int ashift, bshift, extraBit, exp;
1197 ahi = (((guint64)(pA->hi32)) << 32) | pA->mid32;
1198 ami = ((guint64)(pA->lo32)) << 32;
1204 if (blo == 0 && bmi == 0 && bhi == 0) {
1205 return DECIMAL_DIVIDE_BY_ZERO;
1208 if (ami == 0 && ahi == 0) {
1210 return DECIMAL_FINISHED;
1213 /* enlarge dividend to get maximal precision */
1214 for (ashift = 0; (ahi & LIT_GUINT64_HIGHBIT) == 0; ++ashift) {
1215 lshift128(&ami, &ahi);
1218 /* ensure that divisor is at least 2^95 */
1219 for (bshift = 0; (bhi & LIT_GUINT32_HIGHBIT) == 0; ++bshift) {
1220 lshift96(&blo, &bmi, &bhi);
1223 thi = ((guint64)bhi)<<32 | bmi;
1224 tmi = ((guint64)blo)<<32;
1226 if (ahi > thi || (ahi == thi && ami >= tmi)) {
1227 sub192(alo, ami, ahi, tlo, tmi, thi, &alo, &ami, &ahi);
1233 div192by96to128(alo, ami, ahi, blo, bmi, bhi, pclo, pchi);
1234 exp = 128 + ashift - bshift;
1237 rshift128(pclo, pchi);
1238 *pchi += LIT_GUINT64_HIGHBIT;
1242 /* try loss free right shift */
1243 while (exp > 0 && (*pclo & 1) == 0) {
1245 rshift128(pclo, pchi);
1251 return DECIMAL_SUCCESS;
1254 gint32 mono_decimalDiv(/*[Out]*/decimal_repr* pC, /*[In]*/decimal_repr* pA, /*[In]*/decimal_repr* pB)
1256 guint64 clo, chi; /* result */
1259 rc = decimalDivSub(pA, pB, &clo, &chi, &exp);
1260 if (rc != DECIMAL_SUCCESS) {
1261 if (rc == DECIMAL_FINISHED) rc = DECIMAL_SUCCESS;
1265 /* adjust scale and sign */
1266 scale = (int)pA->signscale.scale - (int)pB->signscale.scale;
1268 //test: printf("0: %.17e\n", (((double)chi) * pow(2,64) + clo) * pow(10, -scale) * pow(2, -exp));
1269 rc = rescale128(&clo, &chi, &scale, exp, 0, DECIMAL_MAX_SCALE, 1);
1270 if (rc != DECIMAL_SUCCESS) return rc;
1272 return pack128toDecimal(pC, clo, chi, scale, pA->signscale.sign ^ pB->signscale.sign);
1275 gint32 mono_decimalIntDiv(/*[Out]*/decimal_repr* pC, /*[In]*/decimal_repr* pA, /*[In]*/decimal_repr* pB)
1277 guint64 clo, chi; /* result */
1280 rc = decimalDivSub(pA, pB, &clo, &chi, &exp);
1281 if (rc != DECIMAL_SUCCESS) {
1282 if (rc == DECIMAL_FINISHED) rc = DECIMAL_SUCCESS;
1287 scale = (int)pA->signscale.scale - (int)pB->signscale.scale;
1289 /* truncate result to integer */
1290 rc = rescale128(&clo, &chi, &scale, exp, 0, 0, 0);
1291 if (rc != DECIMAL_SUCCESS) return rc;
1293 return pack128toDecimal(pC, clo, chi, scale, pA->signscale.sign);
1296 /* approximation for log2 of a
1297 If q is the exact value for log2(a), then q <= decimalLog2(a) <= q+1 */
1298 static int DECINLINE decimalLog2(/*[In]*/decimal_repr* pA)
1301 int scale = pA->signscale.scale;
1303 if (pA->hi32 != 0) log2 = 64 + log2_32(pA->hi32);
1304 else if (pA->mid32 != 0) log2 = 32 + log2_32(pA->mid32);
1305 else log2 = log2_32(pA->lo32);
1307 if (log2 != DECIMAL_LOG_NEGINF) {
1308 log2 -= (scale * 33219) / 10000;
1314 static DECINLINE int decimalIsZero(/*[In]*/decimal_repr* pA)
1316 return (pA->lo32 == 0 && pA->mid32 == 0 && pA->hi32 == 0);
1319 gint32 mono_decimalCompare(/*[In]*/decimal_repr* pA, /*[In]*/decimal_repr* pB)
1321 int log2a, log2b, delta, sign;
1324 sign = (pA->signscale.sign) ? -1 : 1;
1326 if (pA->signscale.sign ^ pB->signscale.sign) {
1327 return (decimalIsZero(pA) && decimalIsZero(pB)) ? 0 : sign;
1330 /* try fast comparison via log2 */
1331 log2a = decimalLog2(pA);
1332 log2b = decimalLog2(pB);
1333 delta = log2a - log2b;
1334 /* decimalLog2 is not exact, so we can say nothing
1335 if abs(delta) <= 1 */
1336 if (delta < -1) return -sign;
1337 if (delta > 1) return sign;
1341 mono_decimalIncr(&aa, pB);
1343 if (decimalIsZero(&aa)) return 0;
1345 return (aa.signscale.sign) ? 1 : -1;
1348 /* d=(-1)^sign * n * 2^(k-52) with sign (1bit), k(11bit), n-2^52(52bit) */
1349 static DECINLINE void buildIEEE754Double(double* pd, int sign, int exp, guint64 mantisse)
1351 guint64* p = (guint64*) pd;
1353 PRECONDITION(sign == 0 || sign == 1);
1354 *p = (((guint64)sign) << 63) | (((guint64)((1023+exp)&0x7ff)) << 52) | mantisse;
1357 double mono_decimal2double(/*[In]*/decimal_repr* pA)
1360 guint64 alo, ahi, mantisse;
1361 guint32 overhang, factor, roundBits;
1362 int scale, exp, log5, i;
1364 ahi = (((guint64)(pA->hi32)) << 32) | pA->mid32;
1365 alo = ((guint64)(pA->lo32)) << 32;
1367 /* special case zero */
1368 if (ahi == 0 && alo == 0) return 0.0;
1371 scale = pA->signscale.scale;
1373 /* transform n * 10^-scale and exp = 0 => m * 2^-exp and scale = 0 */
1375 while ((ahi & LIT_GUINT64_HIGHBIT) == 0) {
1376 lshift128(&alo, &ahi);
1380 overhang = (guint32) (ahi >> 32);
1381 if (overhang >= 5) {
1383 log5 = (log2_32(overhang) * 1000) / 2322; /* ln(5)/ln(2) = 2.3219... */
1384 if (log5 < DECIMAL_MAX_INTFACTORS) {
1385 /* get maximal factor=5^i, so that overhang / factor >= 1 */
1386 factor = constantsIntFactors[log5] >> log5; /* 5^n = 10^n/2^n */
1387 i = log5 + overhang / factor;
1389 i = DECIMAL_MAX_INTFACTORS; /* we have only constants up to 10^DECIMAL_MAX_INTFACTORS */
1391 if (i > scale) i = scale;
1392 factor = constantsIntFactors[i] >> i; /* 5^n = 10^n/2^n */
1393 /* n * 10^-scale * 2^-exp => m * 10^-(scale-i) * 2^-(exp+i) with m = n * 5^-i */
1394 div128by32(&alo, &ahi, factor, 0);
1400 /* normalize significand (highest bit should be 1) */
1401 while ((ahi & LIT_GUINT64_HIGHBIT) == 0) {
1402 lshift128(&alo, &ahi);
1406 /* round to nearest even */
1407 roundBits = (guint32)ahi & 0x7ff;
1409 if ((ahi & LIT_GUINT64_HIGHBIT) == 0) { /* overflow ? */
1412 } else if ((roundBits & 0x400) == 0) ahi &= ~1;
1414 /* 96 bit => 1 implizit bit and 52 explicit bits */
1415 mantisse = (ahi & ~LIT_GUINT64_HIGHBIT) >> 11;
1417 buildIEEE754Double(&d, pA->signscale.sign, -exp+95, mantisse);
1423 gint32 mono_decimalSetExponent(/*[In, Out]*/decimal_repr* pA, gint32 exp)
1427 int scale = pA->signscale.scale;
1431 if (scale < 0 || scale > DECIMAL_MAX_SCALE) {
1432 DECTO128(pA, alo, ahi);
1433 rc = rescale128(&alo, &ahi, &scale, 0, 0, DECIMAL_MAX_SCALE, 1);
1434 if (rc != DECIMAL_SUCCESS) return rc;
1435 return pack128toDecimal(pA, alo, ahi, scale, pA->signscale.sign);
1437 pA->signscale.scale = scale;
1438 return DECIMAL_SUCCESS;