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 rc
= rescale128(&alo
, &ahi
,&scaleA
, 0, 0, DECIMAL_MAX_SCALE
, 1);
811 if (rc
!= DECIMAL_SUCCESS
) return rc
;
813 return pack128toDecimal(pA
, alo
, ahi
, scaleA
, sign
);
816 /* performs a += factor * constants[idx] */
817 static int incMultConstant128(guint64
* palo
, guint64
* pahi
, int idx
, int factor
)
821 PRECONDITION(idx
>= 0 && idx
<= DECIMAL_MAX_SCALE
);
822 PRECONDITION(factor
> 0 && factor
<= 9);
824 blo
= dec128decadeFactors
[idx
].lo
;
825 h
= bhi
= dec128decadeFactors
[idx
].hi
;
827 mult128by32(&blo
, &bhi
, factor
, 0);
828 if (h
> bhi
) return DECIMAL_OVERFLOW
;
831 add128(*palo
, *pahi
, blo
, bhi
, palo
, pahi
);
832 if (h
> *pahi
) return DECIMAL_OVERFLOW
;
833 return DECIMAL_SUCCESS
;
836 DECINLINE
static void div128DecadeFactor(guint64
* palo
, guint64
* pahi
, int powerOfTen
)
838 int idx
, roundBit
= 0;
840 while (powerOfTen
> 0) {
841 idx
= (powerOfTen
> DECIMAL_MAX_INTFACTORS
) ? DECIMAL_MAX_INTFACTORS
: powerOfTen
;
843 roundBit
= div128by32(palo
, pahi
, constantsDecadeInt32Factors
[idx
], 0);
846 if (roundBit
) roundUp128(palo
, pahi
);
849 /* calc significant digits of mantisse */
850 DECINLINE
static int calcDigits(guint64 alo
, guint64 ahi
)
857 return 0; /* zero has no signficant digits */
859 tlog2
= log2_64(alo
);
862 tlog2
= 64 + log2_64(ahi
);
865 tlog10
= (tlog2
* 1000) / 3322;
866 /* we need an exact floor value of log10(a) */
867 if (dec128decadeFactors
[tlog10
].hi
> ahi
868 || (dec128decadeFactors
[tlog10
].hi
== ahi
869 && dec128decadeFactors
[tlog10
].lo
> alo
)) {
875 gint32
mono_double2decimal(/*[Out]*/decimal_repr
* pA
, double val
, gint32 digits
)
878 guint64
* p
= (guint64
*)(&val
);
879 int sigDigits
, sign
, texp
, rc
, scale
;
882 PRECONDITION(digits
<= 15);
884 sign
= ((*p
& LIT_GUINT64_HIGHBIT
) != 0) ? 1 : 0;
885 k
= ((guint16
)((*p
) >> 52)) & 0x7FF;
886 alo
= (*p
& LIT_GUINT64(0xFFFFFFFFFFFFF)) | LIT_GUINT64(0x10000000000000);
889 texp
= (k
& 0x7FF) - 0x3FF;
890 if (k
== 0x7FF || texp
>= 96) return DECIMAL_OVERFLOW
; /* NaNs, SNaNs, Infinities or >= 2^96 */
891 if (k
== 0 || texp
<= -94) { /* Subnormals, Zeros or < 2^-94 */
892 DECINIT(pA
); /* return zero */
893 return DECIMAL_SUCCESS
;
898 for (; texp
> 0; texp
--) {
899 lshift128(&alo
, &ahi
);
904 rc
= rescale128(&alo
, &ahi
, &scale
, -texp
, 0, DECIMAL_MAX_SCALE
, 0);
905 if (rc
!= DECIMAL_SUCCESS
) return rc
;
907 sigDigits
= calcDigits(alo
, ahi
);
908 /* too much digits, then round */
909 if (sigDigits
> digits
) {
910 div128DecadeFactor(&alo
, &ahi
, sigDigits
- digits
);
911 scale
-= sigDigits
- digits
;
912 /* check value, may be 10^(digits+1) caused by rounding */
913 if (ahi
== dec128decadeFactors
[digits
].hi
914 && alo
== dec128decadeFactors
[digits
].lo
) {
915 div128by32(&alo
, &ahi
, 10, 0);
919 rc
= mult128DecadeFactor(&alo
, &ahi
, -scale
);
920 if (rc
!= DECIMAL_SUCCESS
) return rc
;
925 return pack128toDecimal(pA
, alo
, ahi
, scale
, sign
);
929 * mono_string2decimal:
935 * converts a digit string to decimal
936 * The significant digits must be passed as an integer in buf !
939 * if you want to convert the number 123.456789012345678901234 to decimal
940 * buf := "123456789012345678901234"
945 * you want to convert -79228162514264337593543950335 to decimal
946 * buf := "79228162514264337593543950335"
951 * you want to convert -7922816251426433759354395033.250000000000001 to decimal
952 * buf := "7922816251426433759354395033250000000000001"
955 * returns (decimal)-7922816251426433759354395033.3
958 * you want to convert -7922816251426433759354395033.250000000000000 to decimal
959 * buf := "7922816251426433759354395033250000000000000"
962 * returns (decimal)-7922816251426433759354395033.2
965 * you want to convert -7922816251426433759354395033.150000000000000 to decimal
966 * buf := "7922816251426433759354395033150000000000000"
969 * returns (decimal)-7922816251426433759354395033.2
971 * Uses banker's rule for rounding if there are more digits than can be
972 * represented by the significant
974 gint32
mono_string2decimal(/*[Out]*/decimal_repr
* pA
, MonoString
* str
, gint32 decrDecimal
, gint32 sign
)
976 gushort
*buf
= mono_string_chars(str
);
979 int n
, rc
, i
, len
, sigLen
= -1, firstNonZero
;
980 int scale
, roundBit
= 0;
985 for (p
= buf
, len
= 0; *p
!= 0; len
++, p
++) { }
987 for (p
= buf
, i
= 0; *p
!= 0; i
++, p
++) {
989 if (n
< 0 || n
> 9) {
990 return DECIMAL_INVALID_CHARACTER
;
995 sigLen
= (len
- firstNonZero
> DECIMAL_MAX_SCALE
+1)
996 ? DECIMAL_MAX_SCALE
+1+firstNonZero
: len
;
997 if (decrDecimal
> sigLen
+1) return DECIMAL_OVERFLOW
;
999 if (i
>= sigLen
) break;
1000 rc
= incMultConstant128(&alo
, &ahi
, sigLen
- 1 - i
, n
);
1001 if (rc
!= DECIMAL_SUCCESS
) {
1007 scale
= sigLen
- decrDecimal
;
1009 if (i
< len
) { /* too much digits, we must round */
1011 if (n
< 0 || n
> 9) {
1012 return DECIMAL_INVALID_CHARACTER
;
1014 if (n
> 5) roundBit
= 1;
1015 else if (n
== 5) { /* we must take a nearer look */
1017 for (++i
; i
< len
; ++i
) {
1018 if (buf
[i
] != '0') break; /* we are greater than .5 */
1020 if (i
< len
/* greater than exactly .5 */
1021 || n
% 2 == 1) { /* exactly .5, use banker's rule for rounding */
1028 rc
= normalize128(&alo
, &ahi
, &scale
, 1, roundBit
);
1029 if (rc
!= DECIMAL_SUCCESS
) return rc
;
1032 if (alo
== 0 && ahi
== 0) {
1034 return DECIMAL_SUCCESS
;
1036 return pack128toDecimal(pA
, alo
, ahi
, sigLen
- decrDecimal
, sign
);
1041 * mono_decimal2string:
1043 * returns minimal number of digit string to represent decimal
1044 * No leading or trailing zeros !
1046 * *pA == 0 => buf = "", *pDecPos = 1, *pSign = 0
1047 * *pA == 12.34 => buf = "1234", *pDecPos = 2, *pSign = 0
1048 * *pA == -1000.0000 => buf = "1", *pDecPos = 4, *pSign = 1
1049 * *pA == -0.00000076 => buf = "76", *pDecPos = -6, *pSign = 0
1052 * pA decimal instance to convert
1053 * digits < 0: use decimals instead
1054 * = 0: gets mantisse as integer
1055 * > 0: gets at most <digits> digits, rounded according to banker's rule if necessary
1056 * decimals only used if digits < 0
1057 * >= 0: number of decimal places
1058 * buf pointer to result buffer
1059 * bufSize size of buffer
1060 * pDecPos receives insert position of decimal point relative to start of buffer
1061 * pSign receives sign
1063 gint32
mono_decimal2string(/*[In]*/decimal_repr
* pA
, gint32 digits
, gint32 decimals
,
1064 MonoArray
* pArray
, gint32 bufSize
, gint32
* pDecPos
, gint32
* pSign
)
1067 guint16
*buf
= (guint16
*) mono_array_addr(pArray
, guint16
, 0);
1068 guint16
*q
, *p
= tmp
;
1072 gint32 sigDigits
, d
;
1075 MONO_ARCH_SAVE_REGS
;
1077 scale
= pA
->signscale
.scale
;
1078 DECTO128(pA
, alo
, ahi
);
1079 sigDigits
= calcDigits(alo
, ahi
); /* significant digits */
1081 /* calc needed digits (without leading or trailing zeros) */
1082 d
= (digits
== 0) ? sigDigits
: digits
;
1083 if (d
< 0) { /* use decimals ? */
1084 if (0 <= decimals
&& decimals
< scale
) {
1085 d
= sigDigits
- scale
+ decimals
;
1087 d
= sigDigits
; /* use all you can get */
1091 if (sigDigits
> d
) { /* we need to round decimal number */
1093 aa
.signscale
.scale
= DECIMAL_MAX_SCALE
;
1094 mono_decimalRound(&aa
, DECIMAL_MAX_SCALE
- sigDigits
+ d
);
1095 DECTO128(&aa
, alo
, ahi
);
1096 sigDigits
+= calcDigits(alo
, ahi
) - d
;
1101 /* get digits starting from the tail */
1102 for (; (alo
!= 0 || ahi
!= 0) && len
< 40; len
++) {
1103 div128by32(&alo
, &ahi
, 10, &rest
);
1104 *p
++ = '0' + (char) rest
;
1109 if (len
>= bufSize
) return DECIMAL_BUFFER_OVERFLOW
;
1111 /* now we have the minimal count of digits,
1112 extend to wished count of digits or decimals */
1114 if (digits
>= 0) { /* count digits */
1115 if (digits
>= bufSize
) return DECIMAL_BUFFER_OVERFLOW
;
1117 /* zero or rounded to zero */
1120 /* copy significant digits */
1121 for (i
= 0; i
< len
; i
++) {
1124 *pDecPos
= sigDigits
- scale
;
1126 /* add trailing zeros */
1127 for (i
= len
; i
< digits
; i
++) {
1130 } else { /* count decimals */
1131 if (scale
>= sigDigits
) { /* add leading zeros */
1132 if (decimals
+2 >= bufSize
) return DECIMAL_BUFFER_OVERFLOW
;
1134 for (i
= 0; i
<= scale
- sigDigits
; i
++) {
1138 if (sigDigits
- scale
+ decimals
+1 >= bufSize
) return DECIMAL_BUFFER_OVERFLOW
;
1139 *pDecPos
= sigDigits
- scale
;
1141 /* copy significant digits */
1142 for (i
= 0; i
< len
; i
++) {
1145 /* add trailing zeros */
1146 for (i
= scale
; i
< decimals
; i
++) {
1152 *pSign
= (sigDigits
> 0) ? pA
->signscale
.sign
: 0; /* zero has positive sign */
1154 return DECIMAL_SUCCESS
;
1158 * mono_decimal2UInt64:
1161 * converts a decimal to an UInt64 without rounding
1163 gint32
mono_decimal2UInt64(/*[In]*/decimal_repr
* pA
, guint64
* pResult
)
1168 MONO_ARCH_SAVE_REGS
;
1170 DECTO128(pA
, alo
, ahi
);
1171 scale
= pA
->signscale
.scale
;
1173 div128DecadeFactor(&alo
, &ahi
, scale
);
1176 /* overflow if integer too large or < 0 */
1177 if (ahi
!= 0 || (alo
!= 0 && pA
->signscale
.sign
)) return DECIMAL_OVERFLOW
;
1180 return DECIMAL_SUCCESS
;
1184 * mono_decimal2Int64:
1187 * converts a decimal to an Int64 without rounding
1189 gint32
mono_decimal2Int64(/*[In]*/decimal_repr
* pA
, gint64
* pResult
)
1194 MONO_ARCH_SAVE_REGS
;
1196 DECTO128(pA
, alo
, ahi
);
1197 scale
= pA
->signscale
.scale
;
1199 div128DecadeFactor(&alo
, &ahi
, scale
);
1202 if (ahi
!= 0) return DECIMAL_OVERFLOW
;
1204 sign
= pA
->signscale
.sign
;
1205 if (sign
&& alo
!= 0) {
1206 if (alo
> LIT_GUINT64_HIGHBIT
) return DECIMAL_OVERFLOW
;
1207 *pResult
= (gint64
) ~(alo
-1);
1209 if (alo
& LIT_GUINT64_HIGHBIT
) return DECIMAL_OVERFLOW
;
1210 *pResult
= (gint64
) alo
;
1213 return DECIMAL_SUCCESS
;
1216 void mono_decimalFloorAndTrunc(/*[In, Out]*/decimal_repr
* pA
, gint32 floorFlag
)
1219 guint32 factor
, rest
;
1220 int scale
, sign
, idx
;
1223 MONO_ARCH_SAVE_REGS
;
1225 scale
= pA
->signscale
.scale
;
1226 if (scale
== 0) return; /* nothing to do */
1228 DECTO128(pA
, alo
, ahi
);
1229 sign
= pA
->signscale
.sign
;
1232 idx
= (scale
> DECIMAL_MAX_INTFACTORS
) ? DECIMAL_MAX_INTFACTORS
: scale
;
1233 factor
= constantsDecadeInt32Factors
[idx
];
1235 div128by32(&alo
, &ahi
, factor
, &rest
);
1236 hasRest
= hasRest
|| (rest
!= 0);
1239 if (floorFlag
&& hasRest
&& sign
) { /* floor: if negative, we must round up */
1240 roundUp128(&alo
, &ahi
);
1243 pack128toDecimal(pA
, alo
, ahi
, 0, sign
);
1246 void mono_decimalRound(/*[In, Out]*/decimal_repr
* pA
, gint32 decimals
)
1251 MONO_ARCH_SAVE_REGS
;
1253 DECTO128(pA
, alo
, ahi
);
1254 scale
= pA
->signscale
.scale
;
1255 sign
= pA
->signscale
.sign
;
1256 if (scale
> decimals
) {
1257 div128DecadeFactor(&alo
, &ahi
, scale
- decimals
);
1261 pack128toDecimal(pA
, alo
, ahi
, scale
, sign
);
1264 gint32
mono_decimalMult(/*[In, Out]*/decimal_repr
* pA
, /*[In]*/decimal_repr
* pB
)
1266 guint64 low
, mid
, high
;
1268 int scale
, sign
, rc
;
1270 MONO_ARCH_SAVE_REGS
;
1272 mult96by96to192(pA
->lo32
, pA
->mid32
, pA
->hi32
, pB
->lo32
, pB
->mid32
, pB
->hi32
,
1275 /* adjust scale and sign */
1276 scale
= (int)pA
->signscale
.scale
+ (int)pB
->signscale
.scale
;
1277 sign
= pA
->signscale
.sign
^ pB
->signscale
.sign
;
1279 /* first scaling step */
1280 factor
= constantsDecadeInt32Factors
[DECIMAL_MAX_INTFACTORS
];
1281 while (high
!= 0 || (mid
>>32) >= factor
) {
1283 factor
/= 1000; /* we need some digits for final rounding */
1284 scale
-= DECIMAL_MAX_INTFACTORS
- 3;
1286 scale
-= DECIMAL_MAX_INTFACTORS
;
1289 div192by32(&low
, &mid
, &high
, factor
);
1292 /* second and final scaling */
1293 rc
= rescale128(&low
, &mid
, &scale
, 0, 0, DECIMAL_MAX_SCALE
, 1);
1294 if (rc
!= DECIMAL_SUCCESS
) return rc
;
1296 return pack128toDecimal(pA
, low
, mid
, scale
, sign
);
1299 static int decimalDivSub(/*[In]*/decimal_repr
* pA
, /*[In]*/decimal_repr
* pB
,
1300 guint64
* pclo
, guint64
* pchi
, int* pExp
)
1302 guint64 alo
, ami
, ahi
;
1303 guint64 tlo
, tmi
, thi
;
1304 guint32 blo
, bmi
, bhi
;
1305 int ashift
, bshift
, extraBit
, texp
;
1307 ahi
= (((guint64
)(pA
->hi32
)) << 32) | pA
->mid32
;
1308 ami
= ((guint64
)(pA
->lo32
)) << 32;
1314 if (blo
== 0 && bmi
== 0 && bhi
== 0) {
1315 return DECIMAL_DIVIDE_BY_ZERO
;
1318 if (ami
== 0 && ahi
== 0) {
1320 return DECIMAL_FINISHED
;
1323 /* enlarge dividend to get maximal precision */
1324 for (ashift
= 0; (ahi
& LIT_GUINT64_HIGHBIT
) == 0; ++ashift
) {
1325 lshift128(&ami
, &ahi
);
1328 /* ensure that divisor is at least 2^95 */
1329 for (bshift
= 0; (bhi
& LIT_GUINT32_HIGHBIT
) == 0; ++bshift
) {
1330 lshift96(&blo
, &bmi
, &bhi
);
1333 thi
= ((guint64
)bhi
)<<32 | bmi
;
1334 tmi
= ((guint64
)blo
)<<32;
1336 if (ahi
> thi
|| (ahi
== thi
&& ami
>= tmi
)) {
1337 sub192(alo
, ami
, ahi
, tlo
, tmi
, thi
, &alo
, &ami
, &ahi
);
1343 div192by96to128(alo
, ami
, ahi
, blo
, bmi
, bhi
, pclo
, pchi
);
1344 texp
= 128 + ashift
- bshift
;
1347 rshift128(pclo
, pchi
);
1348 *pchi
+= LIT_GUINT64_HIGHBIT
;
1352 /* try loss free right shift */
1353 while (texp
> 0 && (*pclo
& 1) == 0) {
1355 rshift128(pclo
, pchi
);
1361 return DECIMAL_SUCCESS
;
1364 gint32
mono_decimalDiv(/*[Out]*/decimal_repr
* pC
, /*[In]*/decimal_repr
* pA
, /*[In]*/decimal_repr
* pB
)
1366 guint64 clo
, chi
; /* result */
1367 int scale
, texp
, rc
;
1369 MONO_ARCH_SAVE_REGS
;
1371 rc
= decimalDivSub(pA
, pB
, &clo
, &chi
, &texp
);
1372 if (rc
!= DECIMAL_SUCCESS
) {
1373 if (rc
== DECIMAL_FINISHED
) rc
= DECIMAL_SUCCESS
;
1377 /* adjust scale and sign */
1378 scale
= (int)pA
->signscale
.scale
- (int)pB
->signscale
.scale
;
1380 /*test: printf("0: %.17e\n", (((double)chi) * pow(2,64) + clo) * pow(10, -scale) * pow(2, -exp));*/
1381 rc
= rescale128(&clo
, &chi
, &scale
, texp
, 0, DECIMAL_MAX_SCALE
, 1);
1382 if (rc
!= DECIMAL_SUCCESS
) return rc
;
1384 return pack128toDecimal(pC
, clo
, chi
, scale
, pA
->signscale
.sign
^ pB
->signscale
.sign
);
1387 gint32
mono_decimalIntDiv(/*[Out]*/decimal_repr
* pC
, /*[In]*/decimal_repr
* pA
, /*[In]*/decimal_repr
* pB
)
1389 guint64 clo
, chi
; /* result */
1390 int scale
, texp
, rc
;
1392 MONO_ARCH_SAVE_REGS
;
1394 rc
= decimalDivSub(pA
, pB
, &clo
, &chi
, &texp
);
1395 if (rc
!= DECIMAL_SUCCESS
) {
1396 if (rc
== DECIMAL_FINISHED
) rc
= DECIMAL_SUCCESS
;
1401 scale
= (int)pA
->signscale
.scale
- (int)pB
->signscale
.scale
;
1403 /* truncate result to integer */
1404 rc
= rescale128(&clo
, &chi
, &scale
, texp
, 0, 0, 0);
1405 if (rc
!= DECIMAL_SUCCESS
) return rc
;
1407 return pack128toDecimal(pC
, clo
, chi
, scale
, pA
->signscale
.sign
);
1410 /* approximation for log2 of a
1411 If q is the exact value for log2(a), then q <= decimalLog2(a) <= q+1 */
1412 DECINLINE
static int decimalLog2(/*[In]*/decimal_repr
* pA
)
1415 int scale
= pA
->signscale
.scale
;
1417 if (pA
->hi32
!= 0) tlog2
= 64 + log2_32(pA
->hi32
);
1418 else if (pA
->mid32
!= 0) tlog2
= 32 + log2_32(pA
->mid32
);
1419 else tlog2
= log2_32(pA
->lo32
);
1421 if (tlog2
!= DECIMAL_LOG_NEGINF
) {
1422 tlog2
-= (scale
* 33219) / 10000;
1428 DECINLINE
static int decimalIsZero(/*[In]*/decimal_repr
* pA
)
1430 return (pA
->lo32
== 0 && pA
->mid32
== 0 && pA
->hi32
== 0);
1433 gint32
mono_decimalCompare(/*[In]*/decimal_repr
* pA
, /*[In]*/decimal_repr
* pB
)
1435 int log2a
, log2b
, delta
, sign
;
1438 MONO_ARCH_SAVE_REGS
;
1440 sign
= (pA
->signscale
.sign
) ? -1 : 1;
1442 if (pA
->signscale
.sign
^ pB
->signscale
.sign
) {
1443 return (decimalIsZero(pA
) && decimalIsZero(pB
)) ? 0 : sign
;
1446 /* try fast comparison via log2 */
1447 log2a
= decimalLog2(pA
);
1448 log2b
= decimalLog2(pB
);
1449 delta
= log2a
- log2b
;
1450 /* decimalLog2 is not exact, so we can say nothing
1451 if abs(delta) <= 1 */
1452 if (delta
< -1) return -sign
;
1453 if (delta
> 1) return sign
;
1457 mono_decimalIncr(&aa
, pB
);
1459 if (decimalIsZero(&aa
)) return 0;
1461 return (aa
.signscale
.sign
) ? 1 : -1;
1464 /* d=(-1)^sign * n * 2^(k-52) with sign (1bit), k(11bit), n-2^52(52bit) */
1465 DECINLINE
static void buildIEEE754Double(double* pd
, int sign
, int texp
, guint64 mantisse
)
1467 guint64
* p
= (guint64
*) pd
;
1469 PRECONDITION(sign
== 0 || sign
== 1);
1470 *p
= (((guint64
)sign
) << 63) | (((guint64
)((1023+texp
)&0x7ff)) << 52) | mantisse
;
1472 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1475 guint32
*t
= (guint32
*)p
;
1484 double mono_decimal2double(/*[In]*/decimal_repr
* pA
)
1487 guint64 alo
, ahi
, mantisse
;
1488 guint32 overhang
, factor
, roundBits
;
1489 int scale
, texp
, log5
, i
;
1491 MONO_ARCH_SAVE_REGS
;
1493 ahi
= (((guint64
)(pA
->hi32
)) << 32) | pA
->mid32
;
1494 alo
= ((guint64
)(pA
->lo32
)) << 32;
1496 /* special case zero */
1497 if (ahi
== 0 && alo
== 0) return 0.0;
1500 scale
= pA
->signscale
.scale
;
1502 /* transform n * 10^-scale and exp = 0 => m * 2^-exp and scale = 0 */
1504 while ((ahi
& LIT_GUINT64_HIGHBIT
) == 0) {
1505 lshift128(&alo
, &ahi
);
1509 overhang
= (guint32
) (ahi
>> 32);
1510 if (overhang
>= 5) {
1512 log5
= (log2_32(overhang
) * 1000) / 2322; /* ln(5)/ln(2) = 2.3219... */
1513 if (log5
< DECIMAL_MAX_INTFACTORS
) {
1514 /* get maximal factor=5^i, so that overhang / factor >= 1 */
1515 factor
= constantsDecadeInt32Factors
[log5
] >> log5
; /* 5^n = 10^n/2^n */
1516 i
= log5
+ overhang
/ factor
;
1518 i
= DECIMAL_MAX_INTFACTORS
; /* we have only constants up to 10^DECIMAL_MAX_INTFACTORS */
1520 if (i
> scale
) i
= scale
;
1521 factor
= constantsDecadeInt32Factors
[i
] >> i
; /* 5^n = 10^n/2^n */
1522 /* n * 10^-scale * 2^-exp => m * 10^-(scale-i) * 2^-(exp+i) with m = n * 5^-i */
1523 div128by32(&alo
, &ahi
, factor
, 0);
1529 /* normalize significand (highest bit should be 1) */
1530 while ((ahi
& LIT_GUINT64_HIGHBIT
) == 0) {
1531 lshift128(&alo
, &ahi
);
1535 /* round to nearest even */
1536 roundBits
= (guint32
)ahi
& 0x7ff;
1538 if ((ahi
& LIT_GUINT64_HIGHBIT
) == 0) { /* overflow ? */
1541 } else if ((roundBits
& 0x400) == 0) ahi
&= ~1;
1543 /* 96 bit => 1 implizit bit and 52 explicit bits */
1544 mantisse
= (ahi
& ~LIT_GUINT64_HIGHBIT
) >> 11;
1546 buildIEEE754Double(&d
, pA
->signscale
.sign
, -texp
+95, mantisse
);
1552 gint32
mono_decimalSetExponent(/*[In, Out]*/decimal_repr
* pA
, gint32 texp
)
1556 int scale
= pA
->signscale
.scale
;
1558 MONO_ARCH_SAVE_REGS
;
1562 if (scale
< 0 || scale
> DECIMAL_MAX_SCALE
) {
1563 DECTO128(pA
, alo
, ahi
);
1564 rc
= rescale128(&alo
, &ahi
, &scale
, 0, 0, DECIMAL_MAX_SCALE
, 1);
1565 if (rc
!= DECIMAL_SUCCESS
) return rc
;
1566 return pack128toDecimal(pA
, alo
, ahi
, scale
, pA
->signscale
.sign
);
1568 pA
->signscale
.scale
= scale
;
1569 return DECIMAL_SUCCESS
;
1573 #endif /* DISABLE_DECIMAL */