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
17 #include <mono/metadata/exception.h>
24 #ifndef DISABLE_DECIMAL
26 /* needed for building microsoft dll */
28 #define DECINLINE __inline
33 #define LIT_GUINT32(x) x
34 #define LIT_GUINT64(x) x##LL
37 /* we need a UInt64 type => guint64 */
43 * Deal with anon union support.
46 #define signscale u.signscale
51 #define PRECONDITION(flag) assert(flag)
52 #define POSTCONDITION(flag) assert(flag)
53 #define TEST(flag) assert(flag)
54 #define INVARIANT_TEST(p) assert(p->signscale.scale >= 0 && p->signscale.scale <= DECIMAL_MAX_SCALE \
55 && p->signscale.reserved1 == 0 && p->signscale.reserved2 == 0);
57 #define PRECONDITION(flag)
58 #define POSTCONDITION(flag)
60 #define INVARIANT_TEST(p)
61 #endif /*#ifdef _DEBUG*/
63 #define DECIMAL_MAX_SCALE 28
64 #define DECIMAL_MAX_INTFACTORS 9
66 #define DECIMAL_SUCCESS 0
67 #define DECIMAL_FINISHED 1
68 #define DECIMAL_OVERFLOW 2
69 #define DECIMAL_INVALID_CHARACTER 2
70 #define DECIMAL_INTERNAL_ERROR 3
71 #define DECIMAL_INVALID_BITS 4
72 #define DECIMAL_DIVIDE_BY_ZERO 5
73 #define DECIMAL_BUFFER_OVERFLOW 6
76 #define DECINIT(src) memset(src, 0, sizeof(decimal_repr))
78 #define DECCOPY(dest, src) memcpy(dest, src, sizeof(decimal_repr))
80 #define DECSWAP(p1, p2, h) \
81 h = (p1)->ss32; (p1)->ss32 = (p2)->ss32; (p2)->ss32 = h; \
82 h = (p1)->hi32; (p1)->hi32 = (p2)->hi32; (p2)->hi32 = h; \
83 h = (p1)->mid32; (p1)->mid32 = (p2)->mid32; (p2)->mid32 = h; \
84 h = (p1)->lo32; (p1)->lo32 = (p2)->lo32; (p2)->lo32 = h;
86 #define DECNEGATE(p1) (p1)->signscale.sign = 1 - (p1)->signscale.sign
88 #define LIT_DEC128(hi, mid, lo) { (((guint64)mid)<<32 | lo), hi }
90 #define DECTO128(pd, lo, hi) \
91 lo = (((guint64)(pd)->mid32) << 32) | (pd)->lo32; \
95 #define LIT_GUINT32_HIGHBIT LIT_GUINT32(0x80000000)
96 #define LIT_GUINT64_HIGHBIT LIT_GUINT64(0x8000000000000000)
98 #define DECIMAL_LOG_NEGINF -1000
100 static const guint32 constantsDecadeInt32Factors
[DECIMAL_MAX_INTFACTORS
+1] = {
101 LIT_GUINT32(1), LIT_GUINT32(10), LIT_GUINT32(100), LIT_GUINT32(1000),
102 LIT_GUINT32(10000), LIT_GUINT32(100000), LIT_GUINT32(1000000),
103 LIT_GUINT32(10000000), LIT_GUINT32(100000000), LIT_GUINT32(1000000000)
111 static const dec128_repr dec128decadeFactors
[DECIMAL_MAX_SCALE
+1] = {
112 LIT_DEC128( 0, 0, 1u), /* == 1 */
113 LIT_DEC128( 0, 0, 10u), /* == 10 */
114 LIT_DEC128( 0, 0, 100u), /* == 100 */
115 LIT_DEC128( 0, 0, 1000u), /* == 1e3m */
116 LIT_DEC128( 0, 0, 10000u), /* == 1e4m */
117 LIT_DEC128( 0, 0, 100000u), /* == 1e5m */
118 LIT_DEC128( 0, 0, 1000000u), /* == 1e6m */
119 LIT_DEC128( 0, 0, 10000000u), /* == 1e7m */
120 LIT_DEC128( 0, 0, 100000000u), /* == 1e8m */
121 LIT_DEC128( 0, 0, 1000000000u), /* == 1e9m */
122 LIT_DEC128( 0, 2u, 1410065408u), /* == 1e10m */
123 LIT_DEC128( 0, 23u, 1215752192u), /* == 1e11m */
124 LIT_DEC128( 0, 232u, 3567587328u), /* == 1e12m */
125 LIT_DEC128( 0, 2328u, 1316134912u), /* == 1e13m */
126 LIT_DEC128( 0, 23283u, 276447232u), /* == 1e14m */
127 LIT_DEC128( 0, 232830u, 2764472320u), /* == 1e15m */
128 LIT_DEC128( 0, 2328306u, 1874919424u), /* == 1e16m */
129 LIT_DEC128( 0, 23283064u, 1569325056u), /* == 1e17m */
130 LIT_DEC128( 0, 232830643u, 2808348672u), /* == 1e18m */
131 LIT_DEC128( 0, 2328306436u, 2313682944u), /* == 1e19m */
132 LIT_DEC128( 5u, 1808227885u, 1661992960u), /* == 1e20m */
133 LIT_DEC128( 54u, 902409669u, 3735027712u), /* == 1e21m */
134 LIT_DEC128( 542u, 434162106u, 2990538752u), /* == 1e22m */
135 LIT_DEC128( 5421u, 46653770u, 4135583744u), /* == 1e23m */
136 LIT_DEC128( 54210u, 466537709u, 2701131776u), /* == 1e24m */
137 LIT_DEC128( 542101u, 370409800u, 1241513984u), /* == 1e25m */
138 LIT_DEC128( 5421010u, 3704098002u, 3825205248u), /* == 1e26m */
139 LIT_DEC128( 54210108u, 2681241660u, 3892314112u), /* == 1e27m */
140 LIT_DEC128( 542101086u, 1042612833u, 268435456u), /* == 1e28m */
143 /* 192 bit addition: c = a + b
144 addition is modulo 2**128, any carry is lost */
145 DECINLINE
static void add128(guint64 alo
, guint64 ahi
,
146 guint64 blo
, guint64 bhi
,
147 guint64
* pclo
, guint64
* pchi
)
150 if (alo
< blo
) ahi
++; /* carry */
157 /* 128 bit subtraction: c = a - b
158 subtraction is modulo 2**128, any carry is lost */
159 DECINLINE
static void sub128(guint64 alo
, guint64 ahi
,
160 guint64 blo
, guint64 bhi
,
161 guint64
* pclo
, guint64
* pchi
)
167 if (alo
< blo
) chi
--; /* borrow */
173 /* 192 bit addition: c = a + b
174 addition is modulo 2**192, any carry is lost */
175 DECINLINE
static void add192(guint64 alo
, guint64 ami
, guint64 ahi
,
176 guint64 blo
, guint64 bmi
, guint64 bhi
,
177 guint64
* pclo
, guint64
* pcmi
, guint64
* pchi
)
180 if (alo
< blo
) { /* carry low */
182 if (ami
== 0) ahi
++; /* carry mid */
185 if (ami
< bmi
) ahi
++; /* carry mid */
192 /* 192 bit subtraction: c = a - b
193 subtraction is modulo 2**192, any carry is lost */
194 DECINLINE
static void sub192(guint64 alo
, guint64 ami
, guint64 ahi
,
195 guint64 blo
, guint64 bmi
, guint64 bhi
,
196 guint64
* pclo
, guint64
* pcmi
, guint64
* pchi
)
198 guint64 clo
, cmi
, chi
;
204 if (cmi
== 0) chi
--; /* borrow mid */
205 cmi
--; /* borrow low */
207 if (ami
< bmi
) chi
--; /* borrow mid */
213 /* multiplication c(192bit) = a(96bit) * b(96bit) */
214 DECINLINE
static void mult96by96to192(guint32 alo
, guint32 ami
, guint32 ahi
,
215 guint32 blo
, guint32 bmi
, guint32 bhi
,
216 guint64
* pclo
, guint64
* pcmi
, guint64
* pchi
)
219 guint32 h0
, h1
, h2
, h3
, h4
, h5
;
222 a
= ((guint64
)alo
) * blo
;
225 a
>>= 32; carry0
= 0;
226 b
= ((guint64
)alo
) * bmi
;
227 c
= ((guint64
)ami
) * blo
;
228 a
+= b
; if (a
< b
) carry0
++;
229 a
+= c
; if (a
< c
) carry0
++;
232 a
>>= 32; carry1
= 0;
233 b
= ((guint64
)alo
) * bhi
;
234 c
= ((guint64
)ami
) * bmi
;
235 d
= ((guint64
)ahi
) * blo
;
236 a
+= b
; if (a
< b
) carry1
++;
237 a
+= c
; if (a
< c
) carry1
++;
238 a
+= d
; if (a
< d
) carry1
++;
241 a
>>= 32; a
+= carry0
; carry0
= 0;
242 b
= ((guint64
)ami
) * bhi
;
243 c
= ((guint64
)ahi
) * bmi
;
244 a
+= b
; if (a
< b
) carry0
++;
245 a
+= c
; if (a
< c
) carry0
++;
248 a
>>= 32; a
+= carry1
;
249 b
= ((guint64
)ahi
) * bhi
;
253 a
>>= 32; a
+= carry0
;
256 *pclo
= ((guint64
)h1
) << 32 | h0
;
257 *pcmi
= ((guint64
)h3
) << 32 | h2
;
258 *pchi
= ((guint64
)h5
) << 32 | h4
;
261 /* multiplication c(128bit) = a(96bit) * b(32bit) */
262 DECINLINE
static void mult96by32to128(guint32 alo
, guint32 ami
, guint32 ahi
,
264 guint64
* pclo
, guint64
* pchi
)
269 a
= ((guint64
)alo
) * factor
;
273 a
+= ((guint64
)ami
) * factor
;
277 a
+= ((guint64
)ahi
) * factor
;
279 *pclo
= ((guint64
)h1
) << 32 | h0
;
283 /* multiplication c(128bit) *= b(32bit) */
284 DECINLINE
static int mult128by32(guint64
* pclo
, guint64
* pchi
, guint32 factor
, int roundBit
)
289 a
= ((guint64
)(guint32
)(*pclo
)) * factor
;
290 if (roundBit
) a
+= factor
/ 2;
294 a
+= (*pclo
>> 32) * factor
;
297 *pclo
= ((guint64
)h1
) << 32 | h0
;
300 a
+= ((guint64
)(guint32
)(*pchi
)) * factor
;
304 a
+= (*pchi
>> 32) * factor
;
307 *pchi
= ((guint64
)h1
) << 32 | h0
;
309 return ((a
>> 32) == 0) ? DECIMAL_SUCCESS
: DECIMAL_OVERFLOW
;
312 DECINLINE
static int mult128DecadeFactor(guint64
* pclo
, guint64
* pchi
, int powerOfTen
)
316 while (powerOfTen
> 0) {
317 idx
= (powerOfTen
>= DECIMAL_MAX_INTFACTORS
) ? DECIMAL_MAX_INTFACTORS
: powerOfTen
;
319 rc
= mult128by32(pclo
, pchi
, constantsDecadeInt32Factors
[idx
], 0);
320 if (rc
!= DECIMAL_SUCCESS
) return rc
;
322 return DECIMAL_SUCCESS
;
325 /* division: x(128bit) /= factor(32bit)
327 DECINLINE
static int div128by32(guint64
* plo
, guint64
* phi
, guint32 factor
, guint32
* pRest
)
332 a
= (guint32
)(h
>> 32);
340 *phi
= b
<< 32 | (guint32
)c
;
343 a
|= (guint32
)(h
>> 32);
350 *plo
= b
<< 32 | (guint32
)c
;
352 if (pRest
) *pRest
= (guint32
) a
;
355 return (a
>= factor
|| (a
== factor
&& (c
& 1) == 1)) ? 1 : 0;
358 /* division: x(192bit) /= factor(32bit)
359 no rest and no rounding*/
360 DECINLINE
static void div192by32(guint64
* plo
, guint64
* pmi
, guint64
* phi
,
366 a
= (guint32
)(h
>> 32);
374 *phi
= b
<< 32 | (guint32
)c
;
377 a
|= (guint32
)(h
>> 32);
385 *pmi
= b
<< 32 | (guint32
)c
;
388 a
|= (guint32
)(h
>> 32);
396 *plo
= b
<< 32 | (guint32
)c
;
399 /* returns upper 32bit for a(192bit) /= b(32bit)
400 a will contain remainder */
401 static guint32
div192by96to32withRest(guint64
* palo
, guint64
* pami
, guint64
* pahi
,
402 guint32 blo
, guint32 bmi
, guint32 bhi
)
404 guint64 rlo
, rmi
, rhi
; /* remainder */
405 guint64 tlo
, thi
; /* term */
408 rlo
= *palo
; rmi
= *pami
; rhi
= *pahi
;
409 if (rhi
>= (((guint64
)bhi
) << 32)) {
410 c
= LIT_GUINT32(0xFFFFFFFF);
412 c
= (guint32
) (rhi
/ bhi
);
414 mult96by32to128(blo
, bmi
, bhi
, c
, &tlo
, &thi
);
415 sub192(rlo
, rmi
, rhi
, 0, tlo
, thi
, &rlo
, &rmi
, &rhi
);
416 while (((gint64
)rhi
) < 0) {
418 add192(rlo
, rmi
, rhi
, 0, (((guint64
)bmi
)<<32) | blo
, bhi
, &rlo
, &rmi
, &rhi
);
420 *palo
= rlo
; *pami
= rmi
; *pahi
= rhi
;
422 POSTCONDITION(rhi
>> 32 == 0);
427 /* c(128bit) = a(192bit) / b(96bit)
429 static void div192by96to128(guint64 alo
, guint64 ami
, guint64 ahi
,
430 guint32 blo
, guint32 bmi
, guint32 bhi
,
431 guint64
* pclo
, guint64
* pchi
)
433 guint64 rlo
, rmi
, rhi
; /* remainder */
436 PRECONDITION(ahi
< (((guint64
)bhi
) << 32 | bmi
)
437 || (ahi
== (((guint64
)bhi
) << 32 | bmi
) && (ami
>> 32) > blo
));
440 rlo
= alo
; rmi
= ami
; rhi
= ahi
;
441 h
= div192by96to32withRest(&rlo
, &rmi
, &rhi
, blo
, bmi
, bhi
);
444 rhi
= (rhi
<< 32) | (rmi
>> 32); rmi
= (rmi
<< 32) | (rlo
>> 32); rlo
<<= 32;
445 *pchi
= (((guint64
)h
) << 32) | div192by96to32withRest(&rlo
, &rmi
, &rhi
, blo
, bmi
, bhi
);
448 rhi
= (rhi
<< 32) | (rmi
>> 32); rmi
= (rmi
<< 32) | (rlo
>> 32); rlo
<<= 32;
449 h
= div192by96to32withRest(&rlo
, &rmi
, &rhi
, blo
, bmi
, bhi
);
451 /* estimate lowest 32 bit (two last bits may be wrong) */
453 c
= LIT_GUINT32(0xFFFFFFFF);
456 c
= (guint32
) (rhi
/ bhi
);
458 *pclo
= (((guint64
)h
) << 32) | c
;
461 DECINLINE
static void roundUp128(guint64
* pclo
, guint64
* pchi
) {
462 if (++(*pclo
) == 0) ++(*pchi
);
465 static int normalize128(guint64
* pclo
, guint64
* pchi
, int* pScale
,
466 int roundFlag
, int roundBit
)
468 guint32 overhang
= (guint32
)(*pchi
>> 32);
472 while (overhang
!= 0) {
473 for (deltaScale
= 1; deltaScale
< DECIMAL_MAX_INTFACTORS
; deltaScale
++)
475 if (overhang
< constantsDecadeInt32Factors
[deltaScale
]) break;
479 if (scale
< 0) return DECIMAL_OVERFLOW
;
481 roundBit
= div128by32(pclo
, pchi
, constantsDecadeInt32Factors
[deltaScale
], 0);
483 overhang
= (guint32
)(*pchi
>> 32);
484 if (roundFlag
&& roundBit
&& *pclo
== (guint64
)-1 && (gint32
)*pchi
== (gint32
)-1) {
491 if (roundFlag
&& roundBit
) {
492 roundUp128(pclo
, pchi
);
493 TEST((*pchi
>> 32) == 0);
496 return DECIMAL_SUCCESS
;
499 DECINLINE
static int maxLeftShift(/*[In, Out]*/decimal_repr
* pA
)
501 guint64 lo64
= (((guint64
)(pA
->mid32
)) << 32) | pA
->lo32
;
502 guint32 hi32
= pA
->hi32
;
505 for (shift
= 0; ((gint32
)hi32
) >= 0 && shift
< 96; shift
++) {
507 if (((gint64
)lo64
) < 0) hi32
++;
511 pA
->lo32
= (guint32
) lo64
;
512 pA
->mid32
= (guint32
)(lo64
>>32);
518 DECINLINE
static void rshift128(guint64
* pclo
, guint64
* pchi
)
521 if (*pchi
& 1) *pclo
|= LIT_GUINT64_HIGHBIT
;
525 DECINLINE
static void lshift96(guint32
* pclo
, guint32
* pcmid
, guint32
* pchi
)
528 if (*pcmid
& LIT_GUINT32_HIGHBIT
) (*pchi
)++;
530 if (*pclo
& LIT_GUINT32_HIGHBIT
) (*pcmid
)++;
534 DECINLINE
static void lshift128(guint64
* pclo
, guint64
* pchi
)
537 if (*pclo
& LIT_GUINT64_HIGHBIT
) (*pchi
)++;
541 DECINLINE
static void rshift192(guint64
* pclo
, guint64
* pcmi
, guint64
* pchi
)
544 if (*pcmi
& 1) *pclo
|= LIT_GUINT64_HIGHBIT
;
546 if (*pchi
& 1) *pcmi
|= LIT_GUINT64_HIGHBIT
;
550 /* returns log2(a) or DECIMAL_LOG_NEGINF for a = 0 */
551 DECINLINE
static int log2_32(guint32 a
)
555 if (a
== 0) return DECIMAL_LOG_NEGINF
;
557 if ((a
>> 16) != 0) {
582 /* returns log2(a) or DECIMAL_LOG_NEGINF for a = 0 */
583 DECINLINE
static int log2_64(guint64 a
)
587 if (a
== 0) return DECIMAL_LOG_NEGINF
;
589 if ((a
>> 32) != 0) {
593 if ((a
>> 16) != 0) {
618 /* returns log2(a) or DECIMAL_LOG_NEGINF for a = 0 */
619 DECINLINE
static int log2_128(guint64 alo
, guint64 ahi
)
621 if (ahi
== 0) return log2_64(alo
);
622 else return log2_64(ahi
) + 64;
625 /* returns a upper limit for log2(a) considering scale */
626 DECINLINE
static int log2withScale_128(guint64 alo
, guint64 ahi
, int scale
)
628 int tlog2
= log2_128(alo
, ahi
);
629 if (tlog2
< 0) tlog2
= 0;
630 return tlog2
- (scale
* 33219) / 10000;
633 DECINLINE
static int pack128toDecimal(/*[Out]*/decimal_repr
* pA
, guint64 alo
, guint64 ahi
,
636 PRECONDITION((ahi
>> 32) == 0);
637 PRECONDITION(sign
== 0 || sign
== 1);
638 PRECONDITION(scale
>= 0 && scale
<= DECIMAL_MAX_SCALE
);
640 if (scale
< 0 || scale
> DECIMAL_MAX_SCALE
|| (ahi
>> 32) != 0) {
641 return DECIMAL_OVERFLOW
;
644 pA
->lo32
= (guint32
) alo
;
645 pA
->mid32
= (guint32
) (alo
>> 32);
646 pA
->hi32
= (guint32
) ahi
;
647 pA
->signscale
.sign
= sign
;
648 pA
->signscale
.scale
= scale
;
650 return DECIMAL_SUCCESS
;
653 DECINLINE
static int adjustScale128(guint64
* palo
, guint64
* pahi
, int deltaScale
)
657 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 div128by32(palo
, pahi
, constantsDecadeInt32Factors
[idx
], 0);
665 } else if (deltaScale
> 0) {
666 if (deltaScale
> DECIMAL_MAX_SCALE
) return DECIMAL_INTERNAL_ERROR
;
667 while (deltaScale
> 0) {
668 idx
= (deltaScale
> DECIMAL_MAX_INTFACTORS
) ? DECIMAL_MAX_INTFACTORS
: deltaScale
;
670 rc
= mult128by32(palo
, pahi
, constantsDecadeInt32Factors
[idx
], 0);
671 if (rc
!= DECIMAL_SUCCESS
) return rc
;
675 return DECIMAL_SUCCESS
;
678 /* input: c * 10^-(*pScale) * 2^-exp
679 output: c * 10^-(*pScale) with
680 minScale <= *pScale <= maxScale and (chi >> 32) == 0 */
681 DECINLINE
static int rescale128(guint64
* pclo
, guint64
* pchi
, int* pScale
, int texp
,
682 int minScale
, int maxScale
, int roundFlag
)
684 guint32 factor
, overhang
;
685 int scale
, i
, rc
, roundBit
= 0;
687 PRECONDITION(texp
>= 0);
693 while (texp
> 0 && scale
<= maxScale
) {
694 overhang
= (guint32
)(*pchi
>> 32);
695 while (texp
> 0 && ((*pclo
& 1) == 0 || overhang
> (2<<DECIMAL_MAX_INTFACTORS
))) {
696 if (--texp
== 0) roundBit
= (int)(*pclo
& 1);
697 rshift128(pclo
, pchi
);
698 overhang
= (guint32
)(*pchi
>> 32);
701 if (texp
> DECIMAL_MAX_INTFACTORS
) i
= DECIMAL_MAX_INTFACTORS
;
703 if (scale
+ i
> maxScale
) i
= maxScale
- scale
;
707 factor
= constantsDecadeInt32Factors
[i
] >> i
; /* 10^i/2^i=5^i */
708 mult128by32(pclo
, pchi
, factor
, 0);
709 /*printf("3: %.17e\n", (((double)chi) * pow(2,64) + clo) * pow(10, -scale) * pow(2, -texp));*/
713 if (--texp
== 0) roundBit
= (int)(*pclo
& 1);
714 rshift128(pclo
, pchi
);
720 while (scale
> maxScale
) {
721 i
= scale
- maxScale
;
722 if (i
> DECIMAL_MAX_INTFACTORS
) i
= DECIMAL_MAX_INTFACTORS
;
724 roundBit
= div128by32(pclo
, pchi
, constantsDecadeInt32Factors
[i
], 0);
727 while (scale
< minScale
) {
728 if (!roundFlag
) roundBit
= 0;
729 i
= minScale
- scale
;
730 if (i
> DECIMAL_MAX_INTFACTORS
) i
= DECIMAL_MAX_INTFACTORS
;
732 rc
= mult128by32(pclo
, pchi
, constantsDecadeInt32Factors
[i
], roundBit
);
733 if (rc
!= DECIMAL_SUCCESS
) return rc
;
737 TEST(scale
>= 0 && scale
<= DECIMAL_MAX_SCALE
);
741 return normalize128(pclo
, pchi
, pScale
, roundFlag
, roundBit
);
744 /* performs a += b */
745 gint32
mono_decimalIncr(/*[In, Out]*/decimal_repr
* pA
, /*[In]*/decimal_repr
* pB
)
747 guint64 alo
, ahi
, blo
, bhi
;
748 int log2A
, log2B
, log2Result
, log10Result
, rc
;
749 int subFlag
, sign
, scaleA
, scaleB
;
753 DECTO128(pA
, alo
, ahi
);
754 DECTO128(pB
, blo
, bhi
);
756 sign
= pA
->signscale
.sign
;
757 subFlag
= sign
- (int)pB
->signscale
.sign
;
758 scaleA
= pA
->signscale
.scale
;
759 scaleB
= pB
->signscale
.scale
;
760 if (scaleA
== scaleB
) {
761 /* same scale, that's easy */
763 sub128(alo
, ahi
, blo
, bhi
, &alo
, &ahi
);
764 if (ahi
& LIT_GUINT64_HIGHBIT
) {
772 add128(alo
, ahi
, blo
, bhi
, &alo
, &ahi
);
774 rc
= normalize128(&alo
, &ahi
, &scaleA
, 1, 0);
776 /* scales must be adjusted */
777 /* Estimate log10 and scale of result for adjusting scales */
778 log2A
= log2withScale_128(alo
, ahi
, scaleA
);
779 log2B
= log2withScale_128(blo
, bhi
, scaleB
);
780 log2Result
= (log2A
>= log2B
) ? log2A
: log2B
;
781 if (!subFlag
) log2Result
++; /* result can have one bit more */
782 log10Result
= (log2Result
* 1000) / 3322 + 1;
783 /* we will calculate in 128bit, so we may need to adjust scale */
784 if (scaleB
> scaleA
) scaleA
= scaleB
;
785 if (scaleA
+ log10Result
> DECIMAL_MAX_SCALE
+ 7) {
786 /* this may not fit in 128bit, so limit it */
787 scaleA
= DECIMAL_MAX_SCALE
+ 7 - log10Result
;
790 rc
= adjustScale128(&alo
, &ahi
, scaleA
- (int)pA
->signscale
.scale
);
791 if (rc
!= DECIMAL_SUCCESS
) return rc
;
792 rc
= adjustScale128(&blo
, &bhi
, scaleA
- scaleB
);
793 if (rc
!= DECIMAL_SUCCESS
) return rc
;
796 sub128(alo
, ahi
, blo
, bhi
, &alo
, &ahi
);
797 if (ahi
& LIT_GUINT64_HIGHBIT
) {
805 add128(alo
, ahi
, blo
, bhi
, &alo
, &ahi
);
808 if (rc
!= DECIMAL_SUCCESS
) return rc
;
810 rc
= rescale128(&alo
, &ahi
,&scaleA
, 0, 0, DECIMAL_MAX_SCALE
, 1);
813 if (rc
!= DECIMAL_SUCCESS
) return rc
;
815 return pack128toDecimal(pA
, alo
, ahi
, scaleA
, sign
);
818 /* performs a += factor * constants[idx] */
819 static int incMultConstant128(guint64
* palo
, guint64
* pahi
, int idx
, int factor
)
823 PRECONDITION(idx
>= 0 && idx
<= DECIMAL_MAX_SCALE
);
824 PRECONDITION(factor
> 0 && factor
<= 9);
826 blo
= dec128decadeFactors
[idx
].lo
;
827 h
= bhi
= dec128decadeFactors
[idx
].hi
;
829 mult128by32(&blo
, &bhi
, factor
, 0);
830 if (h
> bhi
) return DECIMAL_OVERFLOW
;
833 add128(*palo
, *pahi
, blo
, bhi
, palo
, pahi
);
834 if (h
> *pahi
) return DECIMAL_OVERFLOW
;
835 return DECIMAL_SUCCESS
;
838 DECINLINE
static void div128DecadeFactor(guint64
* palo
, guint64
* pahi
, int powerOfTen
)
840 int idx
, roundBit
= 0;
842 while (powerOfTen
> 0) {
843 idx
= (powerOfTen
> DECIMAL_MAX_INTFACTORS
) ? DECIMAL_MAX_INTFACTORS
: powerOfTen
;
845 roundBit
= div128by32(palo
, pahi
, constantsDecadeInt32Factors
[idx
], 0);
848 if (roundBit
) roundUp128(palo
, pahi
);
851 /* calc significant digits of mantisse */
852 DECINLINE
static int calcDigits(guint64 alo
, guint64 ahi
)
859 return 0; /* zero has no signficant digits */
861 tlog2
= log2_64(alo
);
864 tlog2
= 64 + log2_64(ahi
);
867 tlog10
= (tlog2
* 1000) / 3322;
868 /* we need an exact floor value of log10(a) */
869 if (dec128decadeFactors
[tlog10
].hi
> ahi
870 || (dec128decadeFactors
[tlog10
].hi
== ahi
871 && dec128decadeFactors
[tlog10
].lo
> alo
)) {
877 gint32
mono_double2decimal(/*[Out]*/decimal_repr
* pA
, double val
, gint32 digits
)
880 guint64
* p
= (guint64
*)(&val
);
881 int sigDigits
, sign
, texp
, rc
, scale
;
884 PRECONDITION(digits
<= 15);
886 sign
= ((*p
& LIT_GUINT64_HIGHBIT
) != 0) ? 1 : 0;
887 k
= ((guint16
)((*p
) >> 52)) & 0x7FF;
888 alo
= (*p
& LIT_GUINT64(0xFFFFFFFFFFFFF)) | LIT_GUINT64(0x10000000000000);
891 texp
= (k
& 0x7FF) - 0x3FF;
892 if (k
== 0x7FF || texp
>= 96) return DECIMAL_OVERFLOW
; /* NaNs, SNaNs, Infinities or >= 2^96 */
893 if (k
== 0 || texp
<= -94) { /* Subnormals, Zeros or < 2^-94 */
894 DECINIT(pA
); /* return zero */
895 return DECIMAL_SUCCESS
;
900 for (; texp
> 0; texp
--) {
901 lshift128(&alo
, &ahi
);
906 rc
= rescale128(&alo
, &ahi
, &scale
, -texp
, 0, DECIMAL_MAX_SCALE
, 0);
907 if (rc
!= DECIMAL_SUCCESS
) return rc
;
909 sigDigits
= calcDigits(alo
, ahi
);
910 /* too much digits, then round */
911 if (sigDigits
> digits
) {
912 div128DecadeFactor(&alo
, &ahi
, sigDigits
- digits
);
913 scale
-= sigDigits
- digits
;
914 /* check value, may be 10^(digits+1) caused by rounding */
915 if (ahi
== dec128decadeFactors
[digits
].hi
916 && alo
== dec128decadeFactors
[digits
].lo
) {
917 div128by32(&alo
, &ahi
, 10, 0);
921 rc
= mult128DecadeFactor(&alo
, &ahi
, -scale
);
922 if (rc
!= DECIMAL_SUCCESS
) return rc
;
927 return pack128toDecimal(pA
, alo
, ahi
, scale
, sign
);
931 * mono_string2decimal:
937 * converts a digit string to decimal
938 * The significant digits must be passed as an integer in buf !
941 * if you want to convert the number 123.456789012345678901234 to decimal
942 * buf := "123456789012345678901234"
947 * you want to convert -79228162514264337593543950335 to decimal
948 * buf := "79228162514264337593543950335"
953 * you want to convert -7922816251426433759354395033.250000000000001 to decimal
954 * buf := "7922816251426433759354395033250000000000001"
957 * returns (decimal)-7922816251426433759354395033.3
960 * you want to convert -7922816251426433759354395033.250000000000000 to decimal
961 * buf := "7922816251426433759354395033250000000000000"
964 * returns (decimal)-7922816251426433759354395033.2
967 * you want to convert -7922816251426433759354395033.150000000000000 to decimal
968 * buf := "7922816251426433759354395033150000000000000"
971 * returns (decimal)-7922816251426433759354395033.2
973 * Uses banker's rule for rounding if there are more digits than can be
974 * represented by the significant
976 gint32
mono_string2decimal(/*[Out]*/decimal_repr
* pA
, MonoString
* str
, gint32 decrDecimal
, gint32 sign
)
978 gushort
*buf
= mono_string_chars(str
);
981 int n
, rc
, i
, len
, sigLen
= -1, firstNonZero
;
982 int scale
, roundBit
= 0;
987 for (p
= buf
, len
= 0; *p
!= 0; len
++, p
++) { }
989 for (p
= buf
, i
= 0; *p
!= 0; i
++, p
++) {
991 if (n
< 0 || n
> 9) {
992 return DECIMAL_INVALID_CHARACTER
;
997 sigLen
= (len
- firstNonZero
> DECIMAL_MAX_SCALE
+1)
998 ? DECIMAL_MAX_SCALE
+1+firstNonZero
: len
;
999 if (decrDecimal
> sigLen
+1) return DECIMAL_OVERFLOW
;
1001 if (i
>= sigLen
) break;
1002 rc
= incMultConstant128(&alo
, &ahi
, sigLen
- 1 - i
, n
);
1003 if (rc
!= DECIMAL_SUCCESS
) {
1009 scale
= sigLen
- decrDecimal
;
1011 if (i
< len
) { /* too much digits, we must round */
1013 if (n
< 0 || n
> 9) {
1014 return DECIMAL_INVALID_CHARACTER
;
1016 if (n
> 5) roundBit
= 1;
1017 else if (n
== 5) { /* we must take a nearer look */
1019 for (++i
; i
< len
; ++i
) {
1020 if (buf
[i
] != '0') break; /* we are greater than .5 */
1022 if (i
< len
/* greater than exactly .5 */
1023 || n
% 2 == 1) { /* exactly .5, use banker's rule for rounding */
1030 rc
= normalize128(&alo
, &ahi
, &scale
, 1, roundBit
);
1031 if (rc
!= DECIMAL_SUCCESS
) return rc
;
1034 if (alo
== 0 && ahi
== 0) {
1036 return DECIMAL_SUCCESS
;
1038 return pack128toDecimal(pA
, alo
, ahi
, sigLen
- decrDecimal
, sign
);
1043 * mono_decimal2string:
1045 * returns minimal number of digit string to represent decimal
1046 * No leading or trailing zeros !
1048 * *pA == 0 => buf = "", *pDecPos = 1, *pSign = 0
1049 * *pA == 12.34 => buf = "1234", *pDecPos = 2, *pSign = 0
1050 * *pA == -1000.0000 => buf = "1", *pDecPos = 4, *pSign = 1
1051 * *pA == -0.00000076 => buf = "76", *pDecPos = -6, *pSign = 0
1054 * pA decimal instance to convert
1055 * digits < 0: use decimals instead
1056 * = 0: gets mantisse as integer
1057 * > 0: gets at most <digits> digits, rounded according to banker's rule if necessary
1058 * decimals only used if digits < 0
1059 * >= 0: number of decimal places
1060 * buf pointer to result buffer
1061 * bufSize size of buffer
1062 * pDecPos receives insert position of decimal point relative to start of buffer
1063 * pSign receives sign
1065 gint32
mono_decimal2string(/*[In]*/decimal_repr
* pA
, gint32 digits
, gint32 decimals
,
1066 MonoArray
* pArray
, gint32 bufSize
, gint32
* pDecPos
, gint32
* pSign
)
1069 guint16
*buf
= (guint16
*) mono_array_addr(pArray
, guint16
, 0);
1070 guint16
*q
, *p
= tmp
;
1074 gint32 sigDigits
, d
;
1077 MONO_ARCH_SAVE_REGS
;
1079 scale
= pA
->signscale
.scale
;
1080 DECTO128(pA
, alo
, ahi
);
1081 sigDigits
= calcDigits(alo
, ahi
); /* significant digits */
1083 /* calc needed digits (without leading or trailing zeros) */
1084 d
= (digits
== 0) ? sigDigits
: digits
;
1085 if (d
< 0) { /* use decimals ? */
1086 if (0 <= decimals
&& decimals
< scale
) {
1087 d
= sigDigits
- scale
+ decimals
;
1089 d
= sigDigits
; /* use all you can get */
1093 if (sigDigits
> d
) { /* we need to round decimal number */
1095 aa
.signscale
.scale
= DECIMAL_MAX_SCALE
;
1096 mono_decimalRound(&aa
, DECIMAL_MAX_SCALE
- sigDigits
+ d
);
1097 DECTO128(&aa
, alo
, ahi
);
1098 sigDigits
+= calcDigits(alo
, ahi
) - d
;
1103 /* get digits starting from the tail */
1104 for (; (alo
!= 0 || ahi
!= 0) && len
< 40; len
++) {
1105 div128by32(&alo
, &ahi
, 10, &rest
);
1106 *p
++ = '0' + (char) rest
;
1111 if (len
>= bufSize
) return DECIMAL_BUFFER_OVERFLOW
;
1113 /* now we have the minimal count of digits,
1114 extend to wished count of digits or decimals */
1116 if (digits
>= 0) { /* count digits */
1117 if (digits
>= bufSize
) return DECIMAL_BUFFER_OVERFLOW
;
1119 /* zero or rounded to zero */
1122 /* copy significant digits */
1123 for (i
= 0; i
< len
; i
++) {
1126 *pDecPos
= sigDigits
- scale
;
1128 /* add trailing zeros */
1129 for (i
= len
; i
< digits
; i
++) {
1132 } else { /* count decimals */
1133 if (scale
>= sigDigits
) { /* add leading zeros */
1134 if (decimals
+2 >= bufSize
) return DECIMAL_BUFFER_OVERFLOW
;
1136 for (i
= 0; i
<= scale
- sigDigits
; i
++) {
1140 if (sigDigits
- scale
+ decimals
+1 >= bufSize
) return DECIMAL_BUFFER_OVERFLOW
;
1141 *pDecPos
= sigDigits
- scale
;
1143 /* copy significant digits */
1144 for (i
= 0; i
< len
; i
++) {
1147 /* add trailing zeros */
1148 for (i
= scale
; i
< decimals
; i
++) {
1154 *pSign
= (sigDigits
> 0) ? pA
->signscale
.sign
: 0; /* zero has positive sign */
1156 return DECIMAL_SUCCESS
;
1160 * mono_decimal2UInt64:
1163 * converts a decimal to an UInt64 without rounding
1165 gint32
mono_decimal2UInt64(/*[In]*/decimal_repr
* pA
, guint64
* pResult
)
1170 MONO_ARCH_SAVE_REGS
;
1172 DECTO128(pA
, alo
, ahi
);
1173 scale
= pA
->signscale
.scale
;
1175 div128DecadeFactor(&alo
, &ahi
, scale
);
1178 /* overflow if integer too large or < 0 */
1179 if (ahi
!= 0 || (alo
!= 0 && pA
->signscale
.sign
)) return DECIMAL_OVERFLOW
;
1182 return DECIMAL_SUCCESS
;
1186 * mono_decimal2Int64:
1189 * converts a decimal to an Int64 without rounding
1191 gint32
mono_decimal2Int64(/*[In]*/decimal_repr
* pA
, gint64
* pResult
)
1196 MONO_ARCH_SAVE_REGS
;
1198 DECTO128(pA
, alo
, ahi
);
1199 scale
= pA
->signscale
.scale
;
1201 div128DecadeFactor(&alo
, &ahi
, scale
);
1204 if (ahi
!= 0) return DECIMAL_OVERFLOW
;
1206 sign
= pA
->signscale
.sign
;
1207 if (sign
&& alo
!= 0) {
1208 if (alo
> LIT_GUINT64_HIGHBIT
) return DECIMAL_OVERFLOW
;
1209 *pResult
= (gint64
) ~(alo
-1);
1211 if (alo
& LIT_GUINT64_HIGHBIT
) return DECIMAL_OVERFLOW
;
1212 *pResult
= (gint64
) alo
;
1215 return DECIMAL_SUCCESS
;
1218 void mono_decimalFloorAndTrunc(/*[In, Out]*/decimal_repr
* pA
, gint32 floorFlag
)
1221 guint32 factor
, rest
;
1222 int scale
, sign
, idx
;
1225 MONO_ARCH_SAVE_REGS
;
1227 scale
= pA
->signscale
.scale
;
1228 if (scale
== 0) return; /* nothing to do */
1230 DECTO128(pA
, alo
, ahi
);
1231 sign
= pA
->signscale
.sign
;
1234 idx
= (scale
> DECIMAL_MAX_INTFACTORS
) ? DECIMAL_MAX_INTFACTORS
: scale
;
1235 factor
= constantsDecadeInt32Factors
[idx
];
1237 div128by32(&alo
, &ahi
, factor
, &rest
);
1238 hasRest
= hasRest
|| (rest
!= 0);
1241 if (floorFlag
&& hasRest
&& sign
) { /* floor: if negative, we must round up */
1242 roundUp128(&alo
, &ahi
);
1245 pack128toDecimal(pA
, alo
, ahi
, 0, sign
);
1248 void mono_decimalRound(/*[In, Out]*/decimal_repr
* pA
, gint32 decimals
)
1253 MONO_ARCH_SAVE_REGS
;
1255 DECTO128(pA
, alo
, ahi
);
1256 scale
= pA
->signscale
.scale
;
1257 sign
= pA
->signscale
.sign
;
1258 if (scale
> decimals
) {
1259 div128DecadeFactor(&alo
, &ahi
, scale
- decimals
);
1263 pack128toDecimal(pA
, alo
, ahi
, scale
, sign
);
1266 gint32
mono_decimalMult(/*[In, Out]*/decimal_repr
* pA
, /*[In]*/decimal_repr
* pB
)
1268 guint64 low
, mid
, high
;
1270 int scale
, sign
, rc
;
1272 MONO_ARCH_SAVE_REGS
;
1274 mult96by96to192(pA
->lo32
, pA
->mid32
, pA
->hi32
, pB
->lo32
, pB
->mid32
, pB
->hi32
,
1277 /* adjust scale and sign */
1278 scale
= (int)pA
->signscale
.scale
+ (int)pB
->signscale
.scale
;
1279 sign
= pA
->signscale
.sign
^ pB
->signscale
.sign
;
1281 /* first scaling step */
1282 factor
= constantsDecadeInt32Factors
[DECIMAL_MAX_INTFACTORS
];
1283 while (high
!= 0 || (mid
>>32) >= factor
) {
1285 factor
/= 1000; /* we need some digits for final rounding */
1286 scale
-= DECIMAL_MAX_INTFACTORS
- 3;
1288 scale
-= DECIMAL_MAX_INTFACTORS
;
1291 div192by32(&low
, &mid
, &high
, factor
);
1294 /* second and final scaling */
1295 rc
= rescale128(&low
, &mid
, &scale
, 0, 0, DECIMAL_MAX_SCALE
, 1);
1296 if (rc
!= DECIMAL_SUCCESS
) return rc
;
1298 return pack128toDecimal(pA
, low
, mid
, scale
, sign
);
1301 static int decimalDivSub(/*[In]*/decimal_repr
* pA
, /*[In]*/decimal_repr
* pB
,
1302 guint64
* pclo
, guint64
* pchi
, int* pExp
)
1304 guint64 alo
, ami
, ahi
;
1305 guint64 tlo
, tmi
, thi
;
1306 guint32 blo
, bmi
, bhi
;
1307 int ashift
, bshift
, extraBit
, texp
;
1309 ahi
= (((guint64
)(pA
->hi32
)) << 32) | pA
->mid32
;
1310 ami
= ((guint64
)(pA
->lo32
)) << 32;
1316 if (blo
== 0 && bmi
== 0 && bhi
== 0) {
1317 return DECIMAL_DIVIDE_BY_ZERO
;
1320 if (ami
== 0 && ahi
== 0) {
1322 return DECIMAL_FINISHED
;
1325 /* enlarge dividend to get maximal precision */
1326 for (ashift
= 0; (ahi
& LIT_GUINT64_HIGHBIT
) == 0; ++ashift
) {
1327 lshift128(&ami
, &ahi
);
1330 /* ensure that divisor is at least 2^95 */
1331 for (bshift
= 0; (bhi
& LIT_GUINT32_HIGHBIT
) == 0; ++bshift
) {
1332 lshift96(&blo
, &bmi
, &bhi
);
1335 thi
= ((guint64
)bhi
)<<32 | bmi
;
1336 tmi
= ((guint64
)blo
)<<32;
1338 if (ahi
> thi
|| (ahi
== thi
&& ami
>= tmi
)) {
1339 sub192(alo
, ami
, ahi
, tlo
, tmi
, thi
, &alo
, &ami
, &ahi
);
1345 div192by96to128(alo
, ami
, ahi
, blo
, bmi
, bhi
, pclo
, pchi
);
1346 texp
= 128 + ashift
- bshift
;
1349 rshift128(pclo
, pchi
);
1350 *pchi
+= LIT_GUINT64_HIGHBIT
;
1354 /* try loss free right shift */
1355 while (texp
> 0 && (*pclo
& 1) == 0) {
1357 rshift128(pclo
, pchi
);
1363 return DECIMAL_SUCCESS
;
1366 gint32
mono_decimalDiv(/*[Out]*/decimal_repr
* pC
, /*[In]*/decimal_repr
* pA
, /*[In]*/decimal_repr
* pB
)
1368 guint64 clo
, chi
; /* result */
1369 int scale
, texp
, rc
;
1371 MONO_ARCH_SAVE_REGS
;
1373 rc
= decimalDivSub(pA
, pB
, &clo
, &chi
, &texp
);
1374 if (rc
!= DECIMAL_SUCCESS
) {
1375 if (rc
== DECIMAL_FINISHED
) rc
= DECIMAL_SUCCESS
;
1379 /* adjust scale and sign */
1380 scale
= (int)pA
->signscale
.scale
- (int)pB
->signscale
.scale
;
1382 /*test: printf("0: %.17e\n", (((double)chi) * pow(2,64) + clo) * pow(10, -scale) * pow(2, -exp));*/
1383 rc
= rescale128(&clo
, &chi
, &scale
, texp
, 0, DECIMAL_MAX_SCALE
, 1);
1384 if (rc
!= DECIMAL_SUCCESS
) return rc
;
1386 return pack128toDecimal(pC
, clo
, chi
, scale
, pA
->signscale
.sign
^ pB
->signscale
.sign
);
1389 gint32
mono_decimalIntDiv(/*[Out]*/decimal_repr
* pC
, /*[In]*/decimal_repr
* pA
, /*[In]*/decimal_repr
* pB
)
1391 guint64 clo
, chi
; /* result */
1392 int scale
, texp
, rc
;
1394 MONO_ARCH_SAVE_REGS
;
1396 rc
= decimalDivSub(pA
, pB
, &clo
, &chi
, &texp
);
1397 if (rc
!= DECIMAL_SUCCESS
) {
1398 if (rc
== DECIMAL_FINISHED
) rc
= DECIMAL_SUCCESS
;
1403 scale
= (int)pA
->signscale
.scale
- (int)pB
->signscale
.scale
;
1405 /* truncate result to integer */
1406 rc
= rescale128(&clo
, &chi
, &scale
, texp
, 0, 0, 0);
1407 if (rc
!= DECIMAL_SUCCESS
) return rc
;
1409 return pack128toDecimal(pC
, clo
, chi
, scale
, pA
->signscale
.sign
);
1412 /* approximation for log2 of a
1413 If q is the exact value for log2(a), then q <= decimalLog2(a) <= q+1 */
1414 DECINLINE
static int decimalLog2(/*[In]*/decimal_repr
* pA
)
1417 int scale
= pA
->signscale
.scale
;
1419 if (pA
->hi32
!= 0) tlog2
= 64 + log2_32(pA
->hi32
);
1420 else if (pA
->mid32
!= 0) tlog2
= 32 + log2_32(pA
->mid32
);
1421 else tlog2
= log2_32(pA
->lo32
);
1423 if (tlog2
!= DECIMAL_LOG_NEGINF
) {
1424 tlog2
-= (scale
* 33219) / 10000;
1430 DECINLINE
static int decimalIsZero(/*[In]*/decimal_repr
* pA
)
1432 return (pA
->lo32
== 0 && pA
->mid32
== 0 && pA
->hi32
== 0);
1435 gint32
mono_decimalCompare(/*[In]*/decimal_repr
* pA
, /*[In]*/decimal_repr
* pB
)
1437 int log2a
, log2b
, delta
, sign
;
1440 MONO_ARCH_SAVE_REGS
;
1442 sign
= (pA
->signscale
.sign
) ? -1 : 1;
1444 if (pA
->signscale
.sign
^ pB
->signscale
.sign
) {
1445 return (decimalIsZero(pA
) && decimalIsZero(pB
)) ? 0 : sign
;
1448 /* try fast comparison via log2 */
1449 log2a
= decimalLog2(pA
);
1450 log2b
= decimalLog2(pB
);
1451 delta
= log2a
- log2b
;
1452 /* decimalLog2 is not exact, so we can say nothing
1453 if abs(delta) <= 1 */
1454 if (delta
< -1) return -sign
;
1455 if (delta
> 1) return sign
;
1459 mono_decimalIncr(&aa
, pB
);
1461 if (decimalIsZero(&aa
)) return 0;
1463 return (aa
.signscale
.sign
) ? 1 : -1;
1466 /* d=(-1)^sign * n * 2^(k-52) with sign (1bit), k(11bit), n-2^52(52bit) */
1467 DECINLINE
static void buildIEEE754Double(double* pd
, int sign
, int texp
, guint64 mantisse
)
1469 guint64
* p
= (guint64
*) pd
;
1471 PRECONDITION(sign
== 0 || sign
== 1);
1472 *p
= (((guint64
)sign
) << 63) | (((guint64
)((1023+texp
)&0x7ff)) << 52) | mantisse
;
1475 double mono_decimal2double(/*[In]*/decimal_repr
* pA
)
1478 guint64 alo
, ahi
, mantisse
;
1479 guint32 overhang
, factor
, roundBits
;
1480 int scale
, texp
, log5
, i
;
1482 MONO_ARCH_SAVE_REGS
;
1484 ahi
= (((guint64
)(pA
->hi32
)) << 32) | pA
->mid32
;
1485 alo
= ((guint64
)(pA
->lo32
)) << 32;
1487 /* special case zero */
1488 if (ahi
== 0 && alo
== 0) return 0.0;
1491 scale
= pA
->signscale
.scale
;
1493 /* transform n * 10^-scale and exp = 0 => m * 2^-exp and scale = 0 */
1495 while ((ahi
& LIT_GUINT64_HIGHBIT
) == 0) {
1496 lshift128(&alo
, &ahi
);
1500 overhang
= (guint32
) (ahi
>> 32);
1501 if (overhang
>= 5) {
1503 log5
= (log2_32(overhang
) * 1000) / 2322; /* ln(5)/ln(2) = 2.3219... */
1504 if (log5
< DECIMAL_MAX_INTFACTORS
) {
1505 /* get maximal factor=5^i, so that overhang / factor >= 1 */
1506 factor
= constantsDecadeInt32Factors
[log5
] >> log5
; /* 5^n = 10^n/2^n */
1507 i
= log5
+ overhang
/ factor
;
1509 i
= DECIMAL_MAX_INTFACTORS
; /* we have only constants up to 10^DECIMAL_MAX_INTFACTORS */
1511 if (i
> scale
) i
= scale
;
1512 factor
= constantsDecadeInt32Factors
[i
] >> i
; /* 5^n = 10^n/2^n */
1513 /* n * 10^-scale * 2^-exp => m * 10^-(scale-i) * 2^-(exp+i) with m = n * 5^-i */
1514 div128by32(&alo
, &ahi
, factor
, 0);
1520 /* normalize significand (highest bit should be 1) */
1521 while ((ahi
& LIT_GUINT64_HIGHBIT
) == 0) {
1522 lshift128(&alo
, &ahi
);
1526 /* round to nearest even */
1527 roundBits
= (guint32
)ahi
& 0x7ff;
1529 if ((ahi
& LIT_GUINT64_HIGHBIT
) == 0) { /* overflow ? */
1532 } else if ((roundBits
& 0x400) == 0) ahi
&= ~1;
1534 /* 96 bit => 1 implizit bit and 52 explicit bits */
1535 mantisse
= (ahi
& ~LIT_GUINT64_HIGHBIT
) >> 11;
1537 buildIEEE754Double(&d
, pA
->signscale
.sign
, -texp
+95, mantisse
);
1543 gint32
mono_decimalSetExponent(/*[In, Out]*/decimal_repr
* pA
, gint32 texp
)
1547 int scale
= pA
->signscale
.scale
;
1549 MONO_ARCH_SAVE_REGS
;
1553 if (scale
< 0 || scale
> DECIMAL_MAX_SCALE
) {
1554 DECTO128(pA
, alo
, ahi
);
1555 rc
= rescale128(&alo
, &ahi
, &scale
, 0, 0, DECIMAL_MAX_SCALE
, 1);
1556 if (rc
!= DECIMAL_SUCCESS
) return rc
;
1557 return pack128toDecimal(pA
, alo
, ahi
, scale
, pA
->signscale
.sign
);
1559 pA
->signscale
.scale
= scale
;
1560 return DECIMAL_SUCCESS
;
1564 #endif /* DISABLE_DECIMAL */