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
16 #include <mono/metadata/exception.h>
23 /* needed for building microsoft dll */
24 #define DECINLINE __inline
26 #define LIT_GUINT32(x) x
27 #define LIT_GUINT64(x) x##L
30 /* we need a UInt64 type => guint64 */
36 * Deal with anon union support.
39 #define signscale u.signscale
44 #define PRECONDITION(flag) assert(flag)
45 #define POSTCONDITION(flag) assert(flag)
46 #define TEST(flag) assert(flag)
47 #define INVARIANT_TEST(p) assert(p->signscale.scale >= 0 && p->signscale.scale <= DECIMAL_MAX_SCALE \
48 && p->signscale.reserved1 == 0 && p->signscale.reserved2 == 0);
50 #define PRECONDITION(flag)
51 #define POSTCONDITION(flag)
53 #define INVARIANT_TEST(p)
54 #endif /*#ifdef _DEBUG*/
56 #define DECIMAL_MAX_SCALE 28
57 #define DECIMAL_MAX_INTFACTORS 9
59 #define DECIMAL_SUCCESS 0
60 #define DECIMAL_FINISHED 1
61 #define DECIMAL_OVERFLOW 2
62 #define DECIMAL_INVALID_CHARACTER 2
63 #define DECIMAL_INTERNAL_ERROR 3
64 #define DECIMAL_INVALID_BITS 4
65 #define DECIMAL_DIVIDE_BY_ZERO 5
66 #define DECIMAL_BUFFER_OVERFLOW 6
69 #define DECINIT(src) memset(src, 0, sizeof(decimal_repr))
71 #define DECCOPY(dest, src) memcpy(dest, src, sizeof(decimal_repr))
73 #define DECSWAP(p1, p2, h) \
74 h = (p1)->ss32; (p1)->ss32 = (p2)->ss32; (p2)->ss32 = h; \
75 h = (p1)->hi32; (p1)->hi32 = (p2)->hi32; (p2)->hi32 = h; \
76 h = (p1)->mid32; (p1)->mid32 = (p2)->mid32; (p2)->mid32 = h; \
77 h = (p1)->lo32; (p1)->lo32 = (p2)->lo32; (p2)->lo32 = h;
79 #define DECNEGATE(p1) (p1)->signscale.sign = 1 - (p1)->signscale.sign
81 #define LIT_DEC128(hi, mid, lo) { (((guint64)mid)<<32 | lo), hi }
83 #define DECTO128(pd, lo, hi) \
84 lo = (((guint64)(pd)->mid32) << 32) | (pd)->lo32; \
88 #define LIT_GUINT32_HIGHBIT LIT_GUINT32(0x80000000)
89 #define LIT_GUINT64_HIGHBIT LIT_GUINT64(0x8000000000000000)
91 #define DECIMAL_LOG_NEGINF -1000
93 static guint32 constantsDecadeInt32Factors[DECIMAL_MAX_INTFACTORS+1] = {
94 LIT_GUINT32(1), LIT_GUINT32(10), LIT_GUINT32(100), LIT_GUINT32(1000),
95 LIT_GUINT32(10000), LIT_GUINT32(100000), LIT_GUINT32(1000000),
96 LIT_GUINT32(10000000), LIT_GUINT32(100000000), LIT_GUINT32(1000000000)
104 static dec128_repr dec128decadeFactors[DECIMAL_MAX_SCALE+1] = {
105 LIT_DEC128( 0, 0, 1u), /* == 1 */
106 LIT_DEC128( 0, 0, 10u), /* == 10 */
107 LIT_DEC128( 0, 0, 100u), /* == 100 */
108 LIT_DEC128( 0, 0, 1000u), /* == 1e3m */
109 LIT_DEC128( 0, 0, 10000u), /* == 1e4m */
110 LIT_DEC128( 0, 0, 100000u), /* == 1e5m */
111 LIT_DEC128( 0, 0, 1000000u), /* == 1e6m */
112 LIT_DEC128( 0, 0, 10000000u), /* == 1e7m */
113 LIT_DEC128( 0, 0, 100000000u), /* == 1e8m */
114 LIT_DEC128( 0, 0, 1000000000u), /* == 1e9m */
115 LIT_DEC128( 0, 2u, 1410065408u), /* == 1e10m */
116 LIT_DEC128( 0, 23u, 1215752192u), /* == 1e11m */
117 LIT_DEC128( 0, 232u, 3567587328u), /* == 1e12m */
118 LIT_DEC128( 0, 2328u, 1316134912u), /* == 1e13m */
119 LIT_DEC128( 0, 23283u, 276447232u), /* == 1e14m */
120 LIT_DEC128( 0, 232830u, 2764472320u), /* == 1e15m */
121 LIT_DEC128( 0, 2328306u, 1874919424u), /* == 1e16m */
122 LIT_DEC128( 0, 23283064u, 1569325056u), /* == 1e17m */
123 LIT_DEC128( 0, 232830643u, 2808348672u), /* == 1e18m */
124 LIT_DEC128( 0, 2328306436u, 2313682944u), /* == 1e19m */
125 LIT_DEC128( 5u, 1808227885u, 1661992960u), /* == 1e20m */
126 LIT_DEC128( 54u, 902409669u, 3735027712u), /* == 1e21m */
127 LIT_DEC128( 542u, 434162106u, 2990538752u), /* == 1e22m */
128 LIT_DEC128( 5421u, 46653770u, 4135583744u), /* == 1e23m */
129 LIT_DEC128( 54210u, 466537709u, 2701131776u), /* == 1e24m */
130 LIT_DEC128( 542101u, 370409800u, 1241513984u), /* == 1e25m */
131 LIT_DEC128( 5421010u, 3704098002u, 3825205248u), /* == 1e26m */
132 LIT_DEC128( 54210108u, 2681241660u, 3892314112u), /* == 1e27m */
133 LIT_DEC128( 542101086u, 1042612833u, 268435456u), /* == 1e28m */
136 /* 192 bit addition: c = a + b
137 addition is modulo 2**128, any carry is lost */
138 DECINLINE static void add128(guint64 alo, guint64 ahi,
139 guint64 blo, guint64 bhi,
140 guint64* pclo, guint64* pchi)
143 if (alo < blo) ahi++; /* carry */
150 /* 128 bit subtraction: c = a - b
151 subtraction is modulo 2**128, any carry is lost */
152 DECINLINE static void sub128(guint64 alo, guint64 ahi,
153 guint64 blo, guint64 bhi,
154 guint64* pclo, guint64* pchi)
160 if (alo < blo) chi--; /* borrow */
166 /* 192 bit addition: c = a + b
167 addition is modulo 2**192, any carry is lost */
168 DECINLINE static void add192(guint64 alo, guint64 ami, guint64 ahi,
169 guint64 blo, guint64 bmi, guint64 bhi,
170 guint64* pclo, guint64* pcmi, guint64* pchi)
173 if (alo < blo) { /* carry low */
175 if (ami == 0) ahi++; /* carry mid */
178 if (ami < bmi) ahi++; /* carry mid */
185 /* 192 bit subtraction: c = a - b
186 subtraction is modulo 2**192, any carry is lost */
187 DECINLINE static void sub192(guint64 alo, guint64 ami, guint64 ahi,
188 guint64 blo, guint64 bmi, guint64 bhi,
189 guint64* pclo, guint64* pcmi, guint64* pchi)
191 guint64 clo, cmi, chi;
197 if (cmi == 0) chi--; /* borrow mid */
198 cmi--; /* borrow low */
200 if (ami < bmi) chi--; /* borrow mid */
206 /* multiplication c(192bit) = a(96bit) * b(96bit) */
207 DECINLINE static void mult96by96to192(guint32 alo, guint32 ami, guint32 ahi,
208 guint32 blo, guint32 bmi, guint32 bhi,
209 guint64* pclo, guint64* pcmi, guint64* pchi)
212 guint32 h0, h1, h2, h3, h4, h5;
215 a = ((guint64)alo) * blo;
218 a >>= 32; carry0 = 0;
219 b = ((guint64)alo) * bmi;
220 c = ((guint64)ami) * blo;
221 a += b; if (a < b) carry0++;
222 a += c; if (a < c) carry0++;
225 a >>= 32; carry1 = 0;
226 b = ((guint64)alo) * bhi;
227 c = ((guint64)ami) * bmi;
228 d = ((guint64)ahi) * blo;
229 a += b; if (a < b) carry1++;
230 a += c; if (a < c) carry1++;
231 a += d; if (a < d) carry1++;
234 a >>= 32; a += carry0; carry0 = 0;
235 b = ((guint64)ami) * bhi;
236 c = ((guint64)ahi) * bmi;
237 a += b; if (a < b) carry0++;
238 a += c; if (a < c) carry0++;
241 a >>= 32; a += carry1;
242 b = ((guint64)ahi) * bhi;
246 a >>= 32; a += carry0;
249 *pclo = ((guint64)h1) << 32 | h0;
250 *pcmi = ((guint64)h3) << 32 | h2;
251 *pchi = ((guint64)h5) << 32 | h4;
254 /* multiplication c(128bit) = a(96bit) * b(32bit) */
255 DECINLINE static void mult96by32to128(guint32 alo, guint32 ami, guint32 ahi,
257 guint64* pclo, guint64* pchi)
262 a = ((guint64)alo) * factor;
266 a += ((guint64)ami) * factor;
270 a += ((guint64)ahi) * factor;
272 *pclo = ((guint64)h1) << 32 | h0;
276 /* multiplication c(128bit) *= b(32bit) */
277 DECINLINE static int mult128by32(guint64* pclo, guint64* pchi, guint32 factor, int roundBit)
282 a = ((guint64)(guint32)(*pclo)) * factor;
283 if (roundBit) a += factor / 2;
287 a += (*pclo >> 32) * factor;
290 *pclo = ((guint64)h1) << 32 | h0;
293 a += ((guint64)(guint32)(*pchi)) * factor;
297 a += (*pchi >> 32) * factor;
300 *pchi = ((guint64)h1) << 32 | h0;
302 return ((a >> 32) == 0) ? DECIMAL_SUCCESS : DECIMAL_OVERFLOW;
305 DECINLINE static int mult128DecadeFactor(guint64* pclo, guint64* pchi, int powerOfTen)
309 while (powerOfTen > 0) {
310 idx = (powerOfTen >= DECIMAL_MAX_INTFACTORS) ? DECIMAL_MAX_INTFACTORS : powerOfTen;
312 rc = mult128by32(pclo, pchi, constantsDecadeInt32Factors[idx], 0);
313 if (rc != DECIMAL_SUCCESS) return rc;
315 return DECIMAL_SUCCESS;
318 /* division: x(128bit) /= factor(32bit)
320 DECINLINE static int div128by32(guint64* plo, guint64* phi, guint32 factor, guint32* pRest)
325 a = (guint32)(h >> 32);
333 *phi = b << 32 | (guint32)c;
336 a |= (guint32)(h >> 32);
343 *plo = b << 32 | (guint32)c;
345 if (pRest) *pRest = (guint32) a;
348 return (a > factor || (a == factor && (c & 1) == 1)) ? 1 : 0;
351 /* division: x(192bit) /= factor(32bit)
352 no rest and no rounding*/
353 DECINLINE static void div192by32(guint64* plo, guint64* pmi, guint64* phi,
359 a = (guint32)(h >> 32);
367 *phi = b << 32 | (guint32)c;
370 a |= (guint32)(h >> 32);
378 *pmi = b << 32 | (guint32)c;
381 a |= (guint32)(h >> 32);
389 *plo = b << 32 | (guint32)c;
392 /* returns upper 32bit for a(192bit) /= b(32bit)
393 a will contain remainder */
394 static guint32 div192by96to32withRest(guint64* palo, guint64* pami, guint64* pahi,
395 guint32 blo, guint32 bmi, guint32 bhi)
397 guint64 rlo, rmi, rhi; /* remainder */
398 guint64 tlo, thi; /* term */
401 rlo = *palo; rmi = *pami; rhi = *pahi;
402 if (rhi >= (((guint64)bhi) << 32)) {
403 c = LIT_GUINT32(0xFFFFFFFF);
405 c = (guint32) (rhi / bhi);
407 mult96by32to128(blo, bmi, bhi, c, &tlo, &thi);
408 sub192(rlo, rmi, rhi, 0, tlo, thi, &rlo, &rmi, &rhi);
409 while (((gint64)rhi) < 0) {
411 add192(rlo, rmi, rhi, 0, (((guint64)bmi)<<32) | blo, bhi, &rlo, &rmi, &rhi);
413 *palo = rlo ; *pami = rmi ; *pahi = rhi;
415 POSTCONDITION(rhi >> 32 == 0);
420 /* c(128bit) = a(192bit) / b(96bit)
422 static void div192by96to128(guint64 alo, guint64 ami, guint64 ahi,
423 guint32 blo, guint32 bmi, guint32 bhi,
424 guint64* pclo, guint64* pchi)
426 guint64 rlo, rmi, rhi; /* remainder */
429 PRECONDITION(ahi < (((guint64)bhi) << 32 | bmi)
430 || (ahi == (((guint64)bhi) << 32 | bmi) && (ami >> 32) > blo));
433 rlo = alo; rmi = ami; rhi = ahi;
434 h = div192by96to32withRest(&rlo, &rmi, &rhi, blo, bmi, bhi);
437 rhi = (rhi << 32) | (rmi >> 32); rmi = (rmi << 32) | (rlo >> 32); rlo <<= 32;
438 *pchi = (((guint64)h) << 32) | div192by96to32withRest(&rlo, &rmi, &rhi, blo, bmi, bhi);
441 rhi = (rhi << 32) | (rmi >> 32); rmi = (rmi << 32) | (rlo >> 32); rlo <<= 32;
442 h = div192by96to32withRest(&rlo, &rmi, &rhi, blo, bmi, bhi);
444 /* estimate lowest 32 bit (two last bits may be wrong) */
446 c = LIT_GUINT32(0xFFFFFFFF);
449 c = (guint32) (rhi / bhi);
451 *pclo = (((guint64)h) << 32) | c;
454 DECINLINE static void roundUp128(guint64* pclo, guint64* pchi) {
455 if (++(*pclo) == 0) ++(*pchi);
458 static int normalize128(guint64* pclo, guint64* pchi, int* pScale,
459 int roundFlag, int roundBit)
461 guint32 overhang = (guint32)(*pchi >> 32);
465 while (overhang != 0) {
466 for (deltaScale = 1; deltaScale < DECIMAL_MAX_INTFACTORS; deltaScale++)
468 if (overhang < constantsDecadeInt32Factors[deltaScale]) break;
472 if (scale < 0) return DECIMAL_OVERFLOW;
474 roundBit = div128by32(pclo, pchi, constantsDecadeInt32Factors[deltaScale], 0);
476 overhang = (guint32)(*pchi >> 32);
477 if (roundFlag && roundBit && *pclo == (guint64)-1 && (gint32)*pchi == (gint32)-1) {
484 if (roundFlag && roundBit) {
485 roundUp128(pclo, pchi);
486 TEST((*pchi >> 32) == 0);
489 return DECIMAL_SUCCESS;
492 DECINLINE static int maxLeftShift(/*[In, Out]*/decimal_repr* pA)
494 guint64 lo64 = (((guint64)(pA->mid32)) << 32) | pA->lo32;
495 guint32 hi32 = pA->hi32;
498 for (shift = 0; ((gint32)hi32) >= 0 && shift < 96; shift++) {
500 if (((gint64)lo64) < 0) hi32++;
504 pA->lo32 = (guint32) lo64;
505 pA->mid32 = (guint32)(lo64>>32);
511 DECINLINE static void rshift128(guint64* pclo, guint64* pchi)
514 if (*pchi & 1) *pclo |= LIT_GUINT64_HIGHBIT;
518 DECINLINE static void lshift96(guint32* pclo, guint32* pcmid, guint32* pchi)
521 if (*pcmid & LIT_GUINT32_HIGHBIT) (*pchi)++;
523 if (*pclo & LIT_GUINT32_HIGHBIT) (*pcmid)++;
527 DECINLINE static void lshift128(guint64* pclo, guint64* pchi)
530 if (*pclo & LIT_GUINT64_HIGHBIT) (*pchi)++;
534 DECINLINE static void rshift192(guint64* pclo, guint64* pcmi, guint64* pchi)
537 if (*pcmi & 1) *pclo |= LIT_GUINT64_HIGHBIT;
539 if (*pchi & 1) *pcmi |= LIT_GUINT64_HIGHBIT;
543 /* returns log2(a) or DECIMAL_LOG_NEGINF for a = 0 */
544 DECINLINE static int log2_32(guint32 a)
548 if (a == 0) return DECIMAL_LOG_NEGINF;
550 if ((a >> 16) != 0) {
575 /* returns log2(a) or DECIMAL_LOG_NEGINF for a = 0 */
576 DECINLINE static int log2_64(guint64 a)
580 if (a == 0) return DECIMAL_LOG_NEGINF;
582 if ((a >> 32) != 0) {
586 if ((a >> 16) != 0) {
611 /* returns log2(a) or DECIMAL_LOG_NEGINF for a = 0 */
612 DECINLINE static int log2_128(guint64 alo, guint64 ahi)
614 if (ahi == 0) return log2_64(alo);
615 else return log2_64(ahi) + 64;
618 /* returns a upper limit for log2(a) considering scale */
619 DECINLINE static int log2withScale_128(guint64 alo, guint64 ahi, int scale)
621 int tlog2 = log2_128(alo, ahi);
622 if (tlog2 < 0) tlog2 = 0;
623 return tlog2 - (scale * 33219) / 10000;
626 DECINLINE static int pack128toDecimal(/*[Out]*/decimal_repr* pA, guint64 alo, guint64 ahi,
629 PRECONDITION((ahi >> 32) == 0);
630 PRECONDITION(sign == 0 || sign == 1);
631 PRECONDITION(scale >= 0 && scale <= DECIMAL_MAX_SCALE);
633 if (scale < 0 || scale > DECIMAL_MAX_SCALE || (ahi >> 32) != 0) {
634 return DECIMAL_OVERFLOW;
637 pA->lo32 = (guint32) alo;
638 pA->mid32 = (guint32) (alo >> 32);
639 pA->hi32 = (guint32) ahi;
640 pA->signscale.sign = sign;
641 pA->signscale.scale = scale;
643 return DECIMAL_SUCCESS;
646 DECINLINE static int adjustScale128(guint64* palo, guint64* pahi, int deltaScale)
650 if (deltaScale < 0) {
652 if (deltaScale > DECIMAL_MAX_SCALE) return DECIMAL_INTERNAL_ERROR;
653 while (deltaScale > 0) {
654 idx = (deltaScale > DECIMAL_MAX_INTFACTORS) ? DECIMAL_MAX_INTFACTORS : deltaScale;
656 div128by32(palo, pahi, constantsDecadeInt32Factors[idx], 0);
658 } else if (deltaScale > 0) {
659 if (deltaScale > DECIMAL_MAX_SCALE) return DECIMAL_INTERNAL_ERROR;
660 while (deltaScale > 0) {
661 idx = (deltaScale > DECIMAL_MAX_INTFACTORS) ? DECIMAL_MAX_INTFACTORS : deltaScale;
663 rc = mult128by32(palo, pahi, constantsDecadeInt32Factors[idx], 0);
664 if (rc != DECIMAL_SUCCESS) return rc;
668 return DECIMAL_SUCCESS;
671 /* input: c * 10^-(*pScale) * 2^-exp
672 output: c * 10^-(*pScale) with
673 minScale <= *pScale <= maxScale and (chi >> 32) == 0 */
674 DECINLINE static int rescale128(guint64* pclo, guint64* pchi, int* pScale, int texp,
675 int minScale, int maxScale, int roundFlag)
677 guint32 factor, overhang;
678 int scale, i, rc, roundBit = 0;
680 PRECONDITION(texp >= 0);
686 while (texp > 0 && scale <= maxScale) {
687 overhang = (guint32)(*pchi >> 32);
688 while (texp > 0 && ((*pclo & 1) == 0 || overhang > (2<<DECIMAL_MAX_INTFACTORS))) {
689 if (--texp == 0) roundBit = (int)(*pclo & 1);
690 rshift128(pclo, pchi);
691 overhang = (guint32)(*pchi >> 32);
694 if (texp > DECIMAL_MAX_INTFACTORS) i = DECIMAL_MAX_INTFACTORS;
696 if (scale + i > maxScale) i = maxScale - scale;
700 factor = constantsDecadeInt32Factors[i] >> i; /* 10^i/2^i=5^i */
701 mult128by32(pclo, pchi, factor, 0);
702 /*printf("3: %.17e\n", (((double)chi) * pow(2,64) + clo) * pow(10, -scale) * pow(2, -texp));*/
706 if (--texp == 0) roundBit = (int)(*pclo & 1);
707 rshift128(pclo, pchi);
713 while (scale > maxScale) {
714 i = scale - maxScale;
715 if (i > DECIMAL_MAX_INTFACTORS) i = DECIMAL_MAX_INTFACTORS;
717 roundBit = div128by32(pclo, pchi, constantsDecadeInt32Factors[i], 0);
720 while (scale < minScale) {
721 if (!roundFlag) roundBit = 0;
722 i = minScale - scale;
723 if (i > DECIMAL_MAX_INTFACTORS) i = DECIMAL_MAX_INTFACTORS;
725 rc = mult128by32(pclo, pchi, constantsDecadeInt32Factors[i], roundBit);
726 if (rc != DECIMAL_SUCCESS) return rc;
730 TEST(scale >= 0 && scale <= DECIMAL_MAX_SCALE);
734 return normalize128(pclo, pchi, pScale, roundFlag, roundBit);
737 /* performs a += b */
738 gint32 mono_decimalIncr(/*[In, Out]*/decimal_repr* pA, /*[In]*/decimal_repr* pB)
742 guint64 alo, ahi, blo, bhi;
743 int log2A, log2B, log2Result, log10Result, rc;
744 int subFlag, sign, scaleA, scaleB;
746 DECTO128(pA, alo, ahi);
747 DECTO128(pB, blo, bhi);
749 sign = pA->signscale.sign;
750 subFlag = sign - (int)pB->signscale.sign;
751 scaleA = pA->signscale.scale;
752 scaleB = pB->signscale.scale;
753 if (scaleA == scaleB) {
754 /* same scale, that's easy */
756 sub128(alo, ahi, blo, bhi, &alo, &ahi);
757 if (ahi & LIT_GUINT64_HIGHBIT) {
765 add128(alo, ahi, blo, bhi, &alo, &ahi);
767 rc = normalize128(&alo, &ahi, &scaleA, 1, 0);
769 /* scales must be adjusted */
770 /* Estimate log10 and scale of result for adjusting scales */
771 log2A = log2withScale_128(alo, ahi, scaleA);
772 log2B = log2withScale_128(blo, bhi, scaleB);
773 log2Result = (log2A >= log2B) ? log2A : log2B;
774 if (!subFlag) log2Result++; /* result can have one bit more */
775 log10Result = (log2Result * 1000) / 3322 + 1;
776 /* we will calculate in 128bit, so we may need to adjust scale */
777 if (scaleB > scaleA) scaleA = scaleB;
778 if (scaleA + log10Result > DECIMAL_MAX_SCALE + 7) {
779 /* this may not fit in 128bit, so limit it */
780 scaleA = DECIMAL_MAX_SCALE + 7 - log10Result;
783 rc = adjustScale128(&alo, &ahi, scaleA - (int)pA->signscale.scale);
784 if (rc != DECIMAL_SUCCESS) return rc;
785 rc = adjustScale128(&blo, &bhi, scaleA - scaleB);
786 if (rc != DECIMAL_SUCCESS) return rc;
789 sub128(alo, ahi, blo, bhi, &alo, &ahi);
790 if (ahi & LIT_GUINT64_HIGHBIT) {
798 add128(alo, ahi, blo, bhi, &alo, &ahi);
801 if (rc != DECIMAL_SUCCESS) return rc;
803 rc = rescale128(&alo, &ahi,&scaleA, 0, 0, DECIMAL_MAX_SCALE, 1);
806 if (rc != DECIMAL_SUCCESS) return rc;
808 return pack128toDecimal(pA, alo, ahi, scaleA, sign);
811 /* performs a += factor * constants[idx] */
812 static int incMultConstant128(guint64* palo, guint64* pahi, int idx, int factor)
816 PRECONDITION(idx >= 0 && idx <= DECIMAL_MAX_SCALE);
817 PRECONDITION(factor > 0 && factor <= 9);
819 blo = dec128decadeFactors[idx].lo;
820 h = bhi = dec128decadeFactors[idx].hi;
822 mult128by32(&blo, &bhi, factor, 0);
823 if (h > bhi) return DECIMAL_OVERFLOW;
826 add128(*palo, *pahi, blo, bhi, palo, pahi);
827 if (h > *pahi) return DECIMAL_OVERFLOW;
828 return DECIMAL_SUCCESS;
831 DECINLINE static void div128DecadeFactor(guint64* palo, guint64* pahi, int powerOfTen)
833 int idx, roundBit = 0;
835 while (powerOfTen > 0) {
836 idx = (powerOfTen > DECIMAL_MAX_INTFACTORS) ? DECIMAL_MAX_INTFACTORS : powerOfTen;
838 roundBit = div128by32(palo, pahi, constantsDecadeInt32Factors[idx], 0);
841 if (roundBit) roundUp128(palo, pahi);
844 /* calc significant digits of mantisse */
845 DECINLINE static int calcDigits(guint64 alo, guint64 ahi)
852 return 0; /* zero has no signficant digits */
854 tlog2 = log2_64(alo);
857 tlog2 = 64 + log2_64(ahi);
860 tlog10 = (tlog2 * 1000) / 3322;
861 /* we need an exact floor value of log10(a) */
862 if (dec128decadeFactors[tlog10].hi > ahi
863 || (dec128decadeFactors[tlog10].hi == ahi
864 && dec128decadeFactors[tlog10].lo > alo)) {
870 gint32 mono_double2decimal(/*[Out]*/decimal_repr* pA, double val, gint32 digits)
873 guint64* p = (guint64*)(&val);
874 int sigDigits, sign, texp, rc, scale;
877 PRECONDITION(digits <= 15);
879 sign = ((*p & LIT_GUINT64_HIGHBIT) != 0) ? 1 : 0;
880 k = ((guint16)((*p) >> 52)) & 0x7FF;
881 alo = (*p & LIT_GUINT64(0xFFFFFFFFFFFFF)) | LIT_GUINT64(0x10000000000000);
884 texp = (k & 0x7FF) - 0x3FF;
885 if (k == 0x7FF || texp >= 96) return DECIMAL_OVERFLOW; /* NaNs, SNaNs, Infinities or >= 2^96 */
886 if (k == 0 || texp <= -94) { /* Subnormals, Zeros or < 2^-94 */
887 DECINIT(pA); /* return zero */
888 return DECIMAL_SUCCESS;
893 for (; texp > 0; texp--) {
894 lshift128(&alo, &ahi);
899 rc = rescale128(&alo, &ahi, &scale, -texp, 0, DECIMAL_MAX_SCALE, 0);
900 if (rc != DECIMAL_SUCCESS) return rc;
902 sigDigits = calcDigits(alo, ahi);
903 /* too much digits, then round */
904 if (sigDigits > digits) {
905 div128DecadeFactor(&alo, &ahi, sigDigits - digits);
906 scale -= sigDigits - digits;
907 /* check value, may be 10^(digits+1) caused by rounding */
908 if (ahi == dec128decadeFactors[digits].hi
909 && alo == dec128decadeFactors[digits].lo) {
910 div128by32(&alo, &ahi, 10, 0);
914 rc = mult128DecadeFactor(&alo, &ahi, -scale);
915 if (rc != DECIMAL_SUCCESS) return rc;
920 return pack128toDecimal(pA, alo, ahi, scale, sign);
924 * converts a digit string to decimal
925 * The significant digits must be passed as an integer in buf !
928 * if you want to convert the number 123.456789012345678901234 to decimal
929 * buf := "123456789012345678901234"
934 * you want to convert -79228162514264337593543950335 to decimal
935 * buf := "79228162514264337593543950335"
940 * you want to convert -7922816251426433759354395033.250000000000001 to decimal
941 * buf := "7922816251426433759354395033250000000000001"
944 * returns (decimal)-7922816251426433759354395033.3
947 * you want to convert -7922816251426433759354395033.250000000000000 to decimal
948 * buf := "7922816251426433759354395033250000000000000"
951 * returns (decimal)-7922816251426433759354395033.2
954 * you want to convert -7922816251426433759354395033.150000000000000 to decimal
955 * buf := "7922816251426433759354395033150000000000000"
958 * returns (decimal)-7922816251426433759354395033.2
960 * Uses banker's rule for rounding if there are more digits than can be
961 * represented by the significant
963 gint32 mono_string2decimal(/*[Out]*/decimal_repr* pA, MonoString* str, gint32 decrDecimal, gint32 sign)
965 gushort *buf = mono_string_chars(str);
968 int n, rc, i, len, sigLen = -1, firstNonZero;
969 int scale, roundBit = 0;
974 for (p = buf, len = 0; *p != 0; len++, p++) { }
976 for (p = buf, i = 0; *p != 0; i++, p++) {
978 if (n < 0 || n > 9) {
979 return DECIMAL_INVALID_CHARACTER;
984 sigLen = (len - firstNonZero > DECIMAL_MAX_SCALE+1)
985 ? DECIMAL_MAX_SCALE+1+firstNonZero : len;
986 if (decrDecimal > sigLen+1) return DECIMAL_OVERFLOW;
988 if (i >= sigLen) break;
989 rc = incMultConstant128(&alo, &ahi, sigLen - 1 - i, n);
990 if (rc != DECIMAL_SUCCESS) {
996 scale = sigLen - decrDecimal;
998 if (i < len) { /* too much digits, we must round */
1000 if (n < 0 || n > 9) {
1001 return DECIMAL_INVALID_CHARACTER;
1003 if (n > 5) roundBit = 1;
1004 else if (n == 5) { /* we must take a nearer look */
1006 for (++i; i < len; ++i) {
1007 if (buf[i] != '0') break; /* we are greater than .5 */
1009 if (i < len /* greater than exactly .5 */
1010 || n % 2 == 1) { /* exactly .5, use banker's rule for rounding */
1017 rc = normalize128(&alo, &ahi, &scale, 1, roundBit);
1018 if (rc != DECIMAL_SUCCESS) return rc;
1021 if (alo == 0 && ahi == 0) {
1023 return DECIMAL_SUCCESS;
1025 return pack128toDecimal(pA, alo, ahi, sigLen - decrDecimal, sign);
1030 * returns minimal number of digit string to represent decimal
1031 * No leading or trailing zeros !
1033 * *pA == 0 => buf = "", *pDecPos = 1, *pSign = 0
1034 * *pA == 12.34 => buf = "1234", *pDecPos = 2, *pSign = 0
1035 * *pA == -1000.0000 => buf = "1", *pDecPos = 4, *pSign = 1
1036 * *pA == -0.00000076 => buf = "76", *pDecPos = -6, *pSign = 0
1039 * pA decimal instance to convert
1040 * digits < 0: use decimals instead
1041 * = 0: gets mantisse as integer
1042 * > 0: gets at most <digits> digits, rounded according to banker's rule if necessary
1043 * decimals only used if digits < 0
1044 * >= 0: number of decimal places
1045 * buf pointer to result buffer
1046 * bufSize size of buffer
1047 * pDecPos receives insert position of decimal point relative to start of buffer
1048 * pSign receives sign
1051 gint32 mono_decimal2string(/*[In]*/decimal_repr* pA, gint32 digits, gint32 decimals,
1052 MonoArray* pArray, gint32 bufSize, gint32* pDecPos, gint32* pSign)
1054 MONO_ARCH_SAVE_REGS;
1057 guint16 *buf = (guint16*) mono_array_addr(pArray, guint16, 0);
1058 guint16 *q, *p = tmp;
1062 gint32 sigDigits, d;
1065 scale = pA->signscale.scale;
1066 DECTO128(pA, alo, ahi);
1067 sigDigits = calcDigits(alo, ahi); /* significant digits */
1069 /* calc needed digits (without leading or trailing zeros) */
1070 d = (digits == 0) ? sigDigits : digits;
1071 if (d < 0) { /* use decimals ? */
1072 if (0 <= decimals && decimals < scale) {
1073 d = sigDigits - scale + decimals;
1075 d = sigDigits; /* use all you can get */
1079 if (sigDigits > d) { /* we need to round decimal number */
1081 aa.signscale.scale = DECIMAL_MAX_SCALE;
1082 mono_decimalRound(&aa, DECIMAL_MAX_SCALE - sigDigits + d);
1083 DECTO128(&aa, alo, ahi);
1084 sigDigits += calcDigits(alo, ahi) - d;
1089 /* get digits starting from the tail */
1090 for (; (alo != 0 || ahi != 0) && len < 40; len++) {
1091 div128by32(&alo, &ahi, 10, &rest);
1092 *p++ = '0' + (char) rest;
1097 if (len >= bufSize) return DECIMAL_BUFFER_OVERFLOW;
1099 /* now we have the minimal count of digits,
1100 extend to wished count of digits or decimals */
1102 if (digits >= 0) { /* count digits */
1103 if (digits >= bufSize) return DECIMAL_BUFFER_OVERFLOW;
1105 /* zero or rounded to zero */
1108 /* copy significant digits */
1109 for (i = 0; i < len; i++) {
1112 *pDecPos = sigDigits - scale;
1114 /* add trailing zeros */
1115 for (i = len; i < digits; i++) {
1118 } else { /* count decimals */
1119 if (scale >= sigDigits) { /* add leading zeros */
1120 if (decimals+2 >= bufSize) return DECIMAL_BUFFER_OVERFLOW;
1122 for (i = 0; i <= scale - sigDigits; i++) {
1126 if (sigDigits - scale + decimals+1 >= bufSize) return DECIMAL_BUFFER_OVERFLOW;
1127 *pDecPos = sigDigits - scale;
1129 /* copy significant digits */
1130 for (i = 0; i < len; i++) {
1133 /* add trailing zeros */
1134 for (i = scale; i < decimals; i++) {
1140 *pSign = (sigDigits > 0) ? pA->signscale.sign : 0; /* zero has positive sign */
1142 return DECIMAL_SUCCESS;
1146 * converts a decimal to an UInt64 without rounding
1148 gint32 mono_decimal2UInt64(/*[In]*/decimal_repr* pA, guint64* pResult)
1150 MONO_ARCH_SAVE_REGS;
1155 DECTO128(pA, alo, ahi);
1156 scale = pA->signscale.scale;
1158 div128DecadeFactor(&alo, &ahi, scale);
1161 /* overflow if integer too large or < 0 */
1162 if (ahi != 0 || (alo != 0 && pA->signscale.sign)) return DECIMAL_OVERFLOW;
1165 return DECIMAL_SUCCESS;
1169 * converts a decimal to an Int64 without rounding
1171 gint32 mono_decimal2Int64(/*[In]*/decimal_repr* pA, gint64* pResult)
1173 MONO_ARCH_SAVE_REGS;
1178 DECTO128(pA, alo, ahi);
1179 scale = pA->signscale.scale;
1181 div128DecadeFactor(&alo, &ahi, scale);
1184 if (ahi != 0) return DECIMAL_OVERFLOW;
1186 sign = pA->signscale.sign;
1187 if (sign && alo != 0) {
1188 if (alo > LIT_GUINT64_HIGHBIT) return DECIMAL_OVERFLOW;
1189 *pResult = (gint64) ~(alo-1);
1191 if (alo & LIT_GUINT64_HIGHBIT) return DECIMAL_OVERFLOW;
1192 *pResult = (gint64) alo;
1195 return DECIMAL_SUCCESS;
1198 void mono_decimalFloorAndTrunc(/*[In, Out]*/decimal_repr* pA, gint32 floorFlag)
1200 MONO_ARCH_SAVE_REGS;
1203 guint32 factor, rest;
1204 int scale, sign, idx;
1207 scale = pA->signscale.scale;
1208 if (scale == 0) return; /* nothing to do */
1210 DECTO128(pA, alo, ahi);
1211 sign = pA->signscale.sign;
1214 idx = (scale > DECIMAL_MAX_INTFACTORS) ? DECIMAL_MAX_INTFACTORS : scale;
1215 factor = constantsDecadeInt32Factors[idx];
1217 div128by32(&alo, &ahi, factor, &rest);
1218 hasRest = hasRest || (rest != 0);
1221 if (floorFlag && hasRest && sign) { /* floor: if negative, we must round up */
1222 roundUp128(&alo, &ahi);
1225 pack128toDecimal(pA, alo, ahi, 0, sign);
1228 void mono_decimalRound(/*[In, Out]*/decimal_repr* pA, gint32 decimals)
1230 MONO_ARCH_SAVE_REGS;
1235 DECTO128(pA, alo, ahi);
1236 scale = pA->signscale.scale;
1237 sign = pA->signscale.sign;
1238 if (scale > decimals) {
1239 div128DecadeFactor(&alo, &ahi, scale - decimals);
1243 pack128toDecimal(pA, alo, ahi, scale, sign);
1246 gint32 mono_decimalMult(/*[In, Out]*/decimal_repr* pA, /*[In]*/decimal_repr* pB)
1248 MONO_ARCH_SAVE_REGS;
1250 guint64 low, mid, high;
1252 int scale, sign, rc;
1254 mult96by96to192(pA->lo32, pA->mid32, pA->hi32, pB->lo32, pB->mid32, pB->hi32,
1257 /* adjust scale and sign */
1258 scale = (int)pA->signscale.scale + (int)pB->signscale.scale;
1259 sign = pA->signscale.sign ^ pB->signscale.sign;
1261 /* first scaling step */
1262 factor = constantsDecadeInt32Factors[DECIMAL_MAX_INTFACTORS];
1263 while (high != 0 || (mid>>32) >= factor) {
1265 factor /= 1000; /* we need some digits for final rounding */
1266 scale -= DECIMAL_MAX_INTFACTORS - 3;
1268 scale -= DECIMAL_MAX_INTFACTORS;
1271 div192by32(&low, &mid, &high, factor);
1274 /* second and final scaling */
1275 rc = rescale128(&low, &mid, &scale, 0, 0, DECIMAL_MAX_SCALE, 1);
1276 if (rc != DECIMAL_SUCCESS) return rc;
1278 return pack128toDecimal(pA, low, mid, scale, sign);
1281 static int decimalDivSub(/*[In]*/decimal_repr* pA, /*[In]*/decimal_repr* pB,
1282 guint64* pclo, guint64* pchi, int* pExp)
1284 guint64 alo, ami, ahi;
1285 guint64 tlo, tmi, thi;
1286 guint32 blo, bmi, bhi;
1287 int ashift, bshift, extraBit, texp;
1289 ahi = (((guint64)(pA->hi32)) << 32) | pA->mid32;
1290 ami = ((guint64)(pA->lo32)) << 32;
1296 if (blo == 0 && bmi == 0 && bhi == 0) {
1297 return DECIMAL_DIVIDE_BY_ZERO;
1300 if (ami == 0 && ahi == 0) {
1302 return DECIMAL_FINISHED;
1305 /* enlarge dividend to get maximal precision */
1306 for (ashift = 0; (ahi & LIT_GUINT64_HIGHBIT) == 0; ++ashift) {
1307 lshift128(&ami, &ahi);
1310 /* ensure that divisor is at least 2^95 */
1311 for (bshift = 0; (bhi & LIT_GUINT32_HIGHBIT) == 0; ++bshift) {
1312 lshift96(&blo, &bmi, &bhi);
1315 thi = ((guint64)bhi)<<32 | bmi;
1316 tmi = ((guint64)blo)<<32;
1318 if (ahi > thi || (ahi == thi && ami >= tmi)) {
1319 sub192(alo, ami, ahi, tlo, tmi, thi, &alo, &ami, &ahi);
1325 div192by96to128(alo, ami, ahi, blo, bmi, bhi, pclo, pchi);
1326 texp = 128 + ashift - bshift;
1329 rshift128(pclo, pchi);
1330 *pchi += LIT_GUINT64_HIGHBIT;
1334 /* try loss free right shift */
1335 while (texp > 0 && (*pclo & 1) == 0) {
1337 rshift128(pclo, pchi);
1343 return DECIMAL_SUCCESS;
1346 gint32 mono_decimalDiv(/*[Out]*/decimal_repr* pC, /*[In]*/decimal_repr* pA, /*[In]*/decimal_repr* pB)
1348 MONO_ARCH_SAVE_REGS;
1350 guint64 clo, chi; /* result */
1351 int scale, texp, rc;
1353 rc = decimalDivSub(pA, pB, &clo, &chi, &texp);
1354 if (rc != DECIMAL_SUCCESS) {
1355 if (rc == DECIMAL_FINISHED) rc = DECIMAL_SUCCESS;
1359 /* adjust scale and sign */
1360 scale = (int)pA->signscale.scale - (int)pB->signscale.scale;
1362 /*test: printf("0: %.17e\n", (((double)chi) * pow(2,64) + clo) * pow(10, -scale) * pow(2, -exp));*/
1363 rc = rescale128(&clo, &chi, &scale, texp, 0, DECIMAL_MAX_SCALE, 1);
1364 if (rc != DECIMAL_SUCCESS) return rc;
1366 return pack128toDecimal(pC, clo, chi, scale, pA->signscale.sign ^ pB->signscale.sign);
1369 gint32 mono_decimalIntDiv(/*[Out]*/decimal_repr* pC, /*[In]*/decimal_repr* pA, /*[In]*/decimal_repr* pB)
1371 MONO_ARCH_SAVE_REGS;
1373 guint64 clo, chi; /* result */
1374 int scale, texp, rc;
1376 rc = decimalDivSub(pA, pB, &clo, &chi, &texp);
1377 if (rc != DECIMAL_SUCCESS) {
1378 if (rc == DECIMAL_FINISHED) rc = DECIMAL_SUCCESS;
1383 scale = (int)pA->signscale.scale - (int)pB->signscale.scale;
1385 /* truncate result to integer */
1386 rc = rescale128(&clo, &chi, &scale, texp, 0, 0, 0);
1387 if (rc != DECIMAL_SUCCESS) return rc;
1389 return pack128toDecimal(pC, clo, chi, scale, pA->signscale.sign);
1392 /* approximation for log2 of a
1393 If q is the exact value for log2(a), then q <= decimalLog2(a) <= q+1 */
1394 DECINLINE static int decimalLog2(/*[In]*/decimal_repr* pA)
1397 int scale = pA->signscale.scale;
1399 if (pA->hi32 != 0) tlog2 = 64 + log2_32(pA->hi32);
1400 else if (pA->mid32 != 0) tlog2 = 32 + log2_32(pA->mid32);
1401 else tlog2 = log2_32(pA->lo32);
1403 if (tlog2 != DECIMAL_LOG_NEGINF) {
1404 tlog2 -= (scale * 33219) / 10000;
1410 DECINLINE static int decimalIsZero(/*[In]*/decimal_repr* pA)
1412 return (pA->lo32 == 0 && pA->mid32 == 0 && pA->hi32 == 0);
1415 gint32 mono_decimalCompare(/*[In]*/decimal_repr* pA, /*[In]*/decimal_repr* pB)
1417 MONO_ARCH_SAVE_REGS;
1419 int log2a, log2b, delta, sign;
1422 sign = (pA->signscale.sign) ? -1 : 1;
1424 if (pA->signscale.sign ^ pB->signscale.sign) {
1425 return (decimalIsZero(pA) && decimalIsZero(pB)) ? 0 : sign;
1428 /* try fast comparison via log2 */
1429 log2a = decimalLog2(pA);
1430 log2b = decimalLog2(pB);
1431 delta = log2a - log2b;
1432 /* decimalLog2 is not exact, so we can say nothing
1433 if abs(delta) <= 1 */
1434 if (delta < -1) return -sign;
1435 if (delta > 1) return sign;
1439 mono_decimalIncr(&aa, pB);
1441 if (decimalIsZero(&aa)) return 0;
1443 return (aa.signscale.sign) ? 1 : -1;
1446 /* d=(-1)^sign * n * 2^(k-52) with sign (1bit), k(11bit), n-2^52(52bit) */
1447 DECINLINE static void buildIEEE754Double(double* pd, int sign, int texp, guint64 mantisse)
1449 guint64* p = (guint64*) pd;
1451 PRECONDITION(sign == 0 || sign == 1);
1452 *p = (((guint64)sign) << 63) | (((guint64)((1023+texp)&0x7ff)) << 52) | mantisse;
1455 double mono_decimal2double(/*[In]*/decimal_repr* pA)
1457 MONO_ARCH_SAVE_REGS;
1460 guint64 alo, ahi, mantisse;
1461 guint32 overhang, factor, roundBits;
1462 int scale, texp, log5, i;
1464 ahi = (((guint64)(pA->hi32)) << 32) | pA->mid32;
1465 alo = ((guint64)(pA->lo32)) << 32;
1467 /* special case zero */
1468 if (ahi == 0 && alo == 0) return 0.0;
1471 scale = pA->signscale.scale;
1473 /* transform n * 10^-scale and exp = 0 => m * 2^-exp and scale = 0 */
1475 while ((ahi & LIT_GUINT64_HIGHBIT) == 0) {
1476 lshift128(&alo, &ahi);
1480 overhang = (guint32) (ahi >> 32);
1481 if (overhang >= 5) {
1483 log5 = (log2_32(overhang) * 1000) / 2322; /* ln(5)/ln(2) = 2.3219... */
1484 if (log5 < DECIMAL_MAX_INTFACTORS) {
1485 /* get maximal factor=5^i, so that overhang / factor >= 1 */
1486 factor = constantsDecadeInt32Factors[log5] >> log5; /* 5^n = 10^n/2^n */
1487 i = log5 + overhang / factor;
1489 i = DECIMAL_MAX_INTFACTORS; /* we have only constants up to 10^DECIMAL_MAX_INTFACTORS */
1491 if (i > scale) i = scale;
1492 factor = constantsDecadeInt32Factors[i] >> i; /* 5^n = 10^n/2^n */
1493 /* n * 10^-scale * 2^-exp => m * 10^-(scale-i) * 2^-(exp+i) with m = n * 5^-i */
1494 div128by32(&alo, &ahi, factor, 0);
1500 /* normalize significand (highest bit should be 1) */
1501 while ((ahi & LIT_GUINT64_HIGHBIT) == 0) {
1502 lshift128(&alo, &ahi);
1506 /* round to nearest even */
1507 roundBits = (guint32)ahi & 0x7ff;
1509 if ((ahi & LIT_GUINT64_HIGHBIT) == 0) { /* overflow ? */
1512 } else if ((roundBits & 0x400) == 0) ahi &= ~1;
1514 /* 96 bit => 1 implizit bit and 52 explicit bits */
1515 mantisse = (ahi & ~LIT_GUINT64_HIGHBIT) >> 11;
1517 buildIEEE754Double(&d, pA->signscale.sign, -texp+95, mantisse);
1523 gint32 mono_decimalSetExponent(/*[In, Out]*/decimal_repr* pA, gint32 texp)
1525 MONO_ARCH_SAVE_REGS;
1529 int scale = pA->signscale.scale;
1533 if (scale < 0 || scale > DECIMAL_MAX_SCALE) {
1534 DECTO128(pA, alo, ahi);
1535 rc = rescale128(&alo, &ahi, &scale, 0, 0, DECIMAL_MAX_SCALE, 1);
1536 if (rc != DECIMAL_SUCCESS) return rc;
1537 return pack128toDecimal(pA, alo, ahi, scale, pA->signscale.sign);
1539 pA->signscale.scale = scale;
1540 return DECIMAL_SUCCESS;