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>
29 #ifndef DISABLE_DECIMAL
31 /* needed for building microsoft dll */
33 #define DECINLINE __inline
38 #define LIT_GUINT32(x) x
39 #define LIT_GUINT64(x) x##LL
42 /* we need a UInt64 type => guint64 */
48 * Deal with anon union support.
51 #define signscale u.signscale
56 #define PRECONDITION(flag) assert(flag)
57 #define POSTCONDITION(flag) assert(flag)
58 #define TEST(flag) assert(flag)
59 #define INVARIANT_TEST(p) assert(p->signscale.scale >= 0 && p->signscale.scale <= DECIMAL_MAX_SCALE \
60 && p->signscale.reserved1 == 0 && p->signscale.reserved2 == 0);
62 #define PRECONDITION(flag)
63 #define POSTCONDITION(flag)
65 #define INVARIANT_TEST(p)
66 #endif /*#ifdef _DEBUG*/
68 #define DECIMAL_MAX_SCALE 28
69 #define DECIMAL_MAX_INTFACTORS 9
71 #define DECIMAL_SUCCESS 0
72 #define DECIMAL_FINISHED 1
73 #define DECIMAL_OVERFLOW 2
74 #define DECIMAL_INVALID_CHARACTER 2
75 #define DECIMAL_INTERNAL_ERROR 3
76 #define DECIMAL_INVALID_BITS 4
77 #define DECIMAL_DIVIDE_BY_ZERO 5
78 #define DECIMAL_BUFFER_OVERFLOW 6
81 #define DECINIT(src) memset(src, 0, sizeof(decimal_repr))
83 #define DECCOPY(dest, src) memcpy(dest, src, sizeof(decimal_repr))
85 #define DECSWAP(p1, p2, h) \
86 h = (p1)->ss32; (p1)->ss32 = (p2)->ss32; (p2)->ss32 = h; \
87 h = (p1)->hi32; (p1)->hi32 = (p2)->hi32; (p2)->hi32 = h; \
88 h = (p1)->mid32; (p1)->mid32 = (p2)->mid32; (p2)->mid32 = h; \
89 h = (p1)->lo32; (p1)->lo32 = (p2)->lo32; (p2)->lo32 = h;
91 #define DECNEGATE(p1) (p1)->signscale.sign = 1 - (p1)->signscale.sign
93 #define LIT_DEC128(hi, mid, lo) { (((guint64)mid)<<32 | lo), hi }
95 #define DECTO128(pd, lo, hi) \
96 lo = (((guint64)(pd)->mid32) << 32) | (pd)->lo32; \
100 #define LIT_GUINT32_HIGHBIT LIT_GUINT32(0x80000000)
101 #define LIT_GUINT64_HIGHBIT LIT_GUINT64(0x8000000000000000)
103 #define DECIMAL_LOG_NEGINF -1000
105 static const guint32 constantsDecadeInt32Factors
[DECIMAL_MAX_INTFACTORS
+1] = {
106 LIT_GUINT32(1), LIT_GUINT32(10), LIT_GUINT32(100), LIT_GUINT32(1000),
107 LIT_GUINT32(10000), LIT_GUINT32(100000), LIT_GUINT32(1000000),
108 LIT_GUINT32(10000000), LIT_GUINT32(100000000), LIT_GUINT32(1000000000)
116 static const dec128_repr dec128decadeFactors
[DECIMAL_MAX_SCALE
+1] = {
117 LIT_DEC128( 0, 0, 1u), /* == 1 */
118 LIT_DEC128( 0, 0, 10u), /* == 10 */
119 LIT_DEC128( 0, 0, 100u), /* == 100 */
120 LIT_DEC128( 0, 0, 1000u), /* == 1e3m */
121 LIT_DEC128( 0, 0, 10000u), /* == 1e4m */
122 LIT_DEC128( 0, 0, 100000u), /* == 1e5m */
123 LIT_DEC128( 0, 0, 1000000u), /* == 1e6m */
124 LIT_DEC128( 0, 0, 10000000u), /* == 1e7m */
125 LIT_DEC128( 0, 0, 100000000u), /* == 1e8m */
126 LIT_DEC128( 0, 0, 1000000000u), /* == 1e9m */
127 LIT_DEC128( 0, 2u, 1410065408u), /* == 1e10m */
128 LIT_DEC128( 0, 23u, 1215752192u), /* == 1e11m */
129 LIT_DEC128( 0, 232u, 3567587328u), /* == 1e12m */
130 LIT_DEC128( 0, 2328u, 1316134912u), /* == 1e13m */
131 LIT_DEC128( 0, 23283u, 276447232u), /* == 1e14m */
132 LIT_DEC128( 0, 232830u, 2764472320u), /* == 1e15m */
133 LIT_DEC128( 0, 2328306u, 1874919424u), /* == 1e16m */
134 LIT_DEC128( 0, 23283064u, 1569325056u), /* == 1e17m */
135 LIT_DEC128( 0, 232830643u, 2808348672u), /* == 1e18m */
136 LIT_DEC128( 0, 2328306436u, 2313682944u), /* == 1e19m */
137 LIT_DEC128( 5u, 1808227885u, 1661992960u), /* == 1e20m */
138 LIT_DEC128( 54u, 902409669u, 3735027712u), /* == 1e21m */
139 LIT_DEC128( 542u, 434162106u, 2990538752u), /* == 1e22m */
140 LIT_DEC128( 5421u, 46653770u, 4135583744u), /* == 1e23m */
141 LIT_DEC128( 54210u, 466537709u, 2701131776u), /* == 1e24m */
142 LIT_DEC128( 542101u, 370409800u, 1241513984u), /* == 1e25m */
143 LIT_DEC128( 5421010u, 3704098002u, 3825205248u), /* == 1e26m */
144 LIT_DEC128( 54210108u, 2681241660u, 3892314112u), /* == 1e27m */
145 LIT_DEC128( 542101086u, 1042612833u, 268435456u), /* == 1e28m */
148 /* 192 bit addition: c = a + b
149 addition is modulo 2**128, any carry is lost */
150 DECINLINE
static void add128(guint64 alo
, guint64 ahi
,
151 guint64 blo
, guint64 bhi
,
152 guint64
* pclo
, guint64
* pchi
)
155 if (alo
< blo
) ahi
++; /* carry */
162 /* 128 bit subtraction: c = a - b
163 subtraction is modulo 2**128, any carry is lost */
164 DECINLINE
static void sub128(guint64 alo
, guint64 ahi
,
165 guint64 blo
, guint64 bhi
,
166 guint64
* pclo
, guint64
* pchi
)
172 if (alo
< blo
) chi
--; /* borrow */
178 /* 192 bit addition: c = a + b
179 addition is modulo 2**192, any carry is lost */
180 DECINLINE
static void add192(guint64 alo
, guint64 ami
, guint64 ahi
,
181 guint64 blo
, guint64 bmi
, guint64 bhi
,
182 guint64
* pclo
, guint64
* pcmi
, guint64
* pchi
)
185 if (alo
< blo
) { /* carry low */
187 if (ami
== 0) ahi
++; /* carry mid */
190 if (ami
< bmi
) ahi
++; /* carry mid */
197 /* 192 bit subtraction: c = a - b
198 subtraction is modulo 2**192, any carry is lost */
199 DECINLINE
static void sub192(guint64 alo
, guint64 ami
, guint64 ahi
,
200 guint64 blo
, guint64 bmi
, guint64 bhi
,
201 guint64
* pclo
, guint64
* pcmi
, guint64
* pchi
)
203 guint64 clo
, cmi
, chi
;
209 if (cmi
== 0) chi
--; /* borrow mid */
210 cmi
--; /* borrow low */
212 if (ami
< bmi
) chi
--; /* borrow mid */
218 /* multiplication c(192bit) = a(96bit) * b(96bit) */
219 DECINLINE
static void mult96by96to192(guint32 alo
, guint32 ami
, guint32 ahi
,
220 guint32 blo
, guint32 bmi
, guint32 bhi
,
221 guint64
* pclo
, guint64
* pcmi
, guint64
* pchi
)
224 guint32 h0
, h1
, h2
, h3
, h4
, h5
;
227 a
= ((guint64
)alo
) * blo
;
230 a
>>= 32; carry0
= 0;
231 b
= ((guint64
)alo
) * bmi
;
232 c
= ((guint64
)ami
) * blo
;
233 a
+= b
; if (a
< b
) carry0
++;
234 a
+= c
; if (a
< c
) carry0
++;
237 a
>>= 32; carry1
= 0;
238 b
= ((guint64
)alo
) * bhi
;
239 c
= ((guint64
)ami
) * bmi
;
240 d
= ((guint64
)ahi
) * blo
;
241 a
+= b
; if (a
< b
) carry1
++;
242 a
+= c
; if (a
< c
) carry1
++;
243 a
+= d
; if (a
< d
) carry1
++;
246 a
>>= 32; a
+= carry0
; carry0
= 0;
247 b
= ((guint64
)ami
) * bhi
;
248 c
= ((guint64
)ahi
) * bmi
;
249 a
+= b
; if (a
< b
) carry0
++;
250 a
+= c
; if (a
< c
) carry0
++;
253 a
>>= 32; a
+= carry1
;
254 b
= ((guint64
)ahi
) * bhi
;
258 a
>>= 32; a
+= carry0
;
261 *pclo
= ((guint64
)h1
) << 32 | h0
;
262 *pcmi
= ((guint64
)h3
) << 32 | h2
;
263 *pchi
= ((guint64
)h5
) << 32 | h4
;
266 /* multiplication c(128bit) = a(96bit) * b(32bit) */
267 DECINLINE
static void mult96by32to128(guint32 alo
, guint32 ami
, guint32 ahi
,
269 guint64
* pclo
, guint64
* pchi
)
274 a
= ((guint64
)alo
) * factor
;
278 a
+= ((guint64
)ami
) * factor
;
282 a
+= ((guint64
)ahi
) * factor
;
284 *pclo
= ((guint64
)h1
) << 32 | h0
;
288 /* multiplication c(128bit) *= b(32bit) */
289 DECINLINE
static int mult128by32(guint64
* pclo
, guint64
* pchi
, guint32 factor
, int roundBit
)
294 a
= ((guint64
)(guint32
)(*pclo
)) * factor
;
295 if (roundBit
) a
+= factor
/ 2;
299 a
+= (*pclo
>> 32) * factor
;
302 *pclo
= ((guint64
)h1
) << 32 | h0
;
305 a
+= ((guint64
)(guint32
)(*pchi
)) * factor
;
309 a
+= (*pchi
>> 32) * factor
;
312 *pchi
= ((guint64
)h1
) << 32 | h0
;
314 return ((a
>> 32) == 0) ? DECIMAL_SUCCESS
: DECIMAL_OVERFLOW
;
317 DECINLINE
static int mult128DecadeFactor(guint64
* pclo
, guint64
* pchi
, int powerOfTen
)
321 while (powerOfTen
> 0) {
322 idx
= (powerOfTen
>= DECIMAL_MAX_INTFACTORS
) ? DECIMAL_MAX_INTFACTORS
: powerOfTen
;
324 rc
= mult128by32(pclo
, pchi
, constantsDecadeInt32Factors
[idx
], 0);
325 if (rc
!= DECIMAL_SUCCESS
) return rc
;
327 return DECIMAL_SUCCESS
;
330 /* division: x(128bit) /= factor(32bit)
332 DECINLINE
static int div128by32(guint64
* plo
, guint64
* phi
, guint32 factor
, guint32
* pRest
)
337 a
= (guint32
)(h
>> 32);
345 *phi
= b
<< 32 | (guint32
)c
;
348 a
|= (guint32
)(h
>> 32);
355 *plo
= b
<< 32 | (guint32
)c
;
357 if (pRest
) *pRest
= (guint32
) a
;
360 return (a
>= factor
|| (a
== factor
&& (c
& 1) == 1)) ? 1 : 0;
363 /* division: x(192bit) /= factor(32bit)
364 no rest and no rounding*/
365 DECINLINE
static void div192by32(guint64
* plo
, guint64
* pmi
, guint64
* phi
,
371 a
= (guint32
)(h
>> 32);
379 *phi
= b
<< 32 | (guint32
)c
;
382 a
|= (guint32
)(h
>> 32);
390 *pmi
= b
<< 32 | (guint32
)c
;
393 a
|= (guint32
)(h
>> 32);
401 *plo
= b
<< 32 | (guint32
)c
;
404 /* returns upper 32bit for a(192bit) /= b(32bit)
405 a will contain remainder */
406 DECINLINE
static guint32
div192by96to32withRest(guint64
* palo
, guint64
* pami
, guint64
* pahi
,
407 guint32 blo
, guint32 bmi
, guint32 bhi
)
409 guint64 rlo
, rmi
, rhi
; /* remainder */
410 guint64 tlo
, thi
; /* term */
413 rlo
= *palo
; rmi
= *pami
; rhi
= *pahi
;
414 if (rhi
>= (((guint64
)bhi
) << 32)) {
415 c
= LIT_GUINT32(0xFFFFFFFF);
417 c
= (guint32
) (rhi
/ bhi
);
419 mult96by32to128(blo
, bmi
, bhi
, c
, &tlo
, &thi
);
420 sub192(rlo
, rmi
, rhi
, 0, tlo
, thi
, &rlo
, &rmi
, &rhi
);
421 while (((gint64
)rhi
) < 0) {
423 add192(rlo
, rmi
, rhi
, 0, (((guint64
)bmi
)<<32) | blo
, bhi
, &rlo
, &rmi
, &rhi
);
425 *palo
= rlo
; *pami
= rmi
; *pahi
= rhi
;
427 POSTCONDITION(rhi
>> 32 == 0);
432 /* c(128bit) = a(192bit) / b(96bit)
434 DECINLINE
static void div192by96to128(guint64 alo
, guint64 ami
, guint64 ahi
,
435 guint32 blo
, guint32 bmi
, guint32 bhi
,
436 guint64
* pclo
, guint64
* pchi
)
438 guint64 rlo
, rmi
, rhi
; /* remainder */
441 PRECONDITION(ahi
< (((guint64
)bhi
) << 32 | bmi
)
442 || (ahi
== (((guint64
)bhi
) << 32 | bmi
) && (ami
>> 32) > blo
));
445 rlo
= alo
; rmi
= ami
; rhi
= ahi
;
446 h
= div192by96to32withRest(&rlo
, &rmi
, &rhi
, blo
, bmi
, bhi
);
449 rhi
= (rhi
<< 32) | (rmi
>> 32); rmi
= (rmi
<< 32) | (rlo
>> 32); rlo
<<= 32;
450 *pchi
= (((guint64
)h
) << 32) | div192by96to32withRest(&rlo
, &rmi
, &rhi
, blo
, bmi
, bhi
);
453 rhi
= (rhi
<< 32) | (rmi
>> 32); rmi
= (rmi
<< 32) | (rlo
>> 32); rlo
<<= 32;
454 h
= div192by96to32withRest(&rlo
, &rmi
, &rhi
, blo
, bmi
, bhi
);
456 /* estimate lowest 32 bit (two last bits may be wrong) */
458 c
= LIT_GUINT32(0xFFFFFFFF);
461 c
= (guint32
) (rhi
/ bhi
);
463 *pclo
= (((guint64
)h
) << 32) | c
;
466 DECINLINE
static void roundUp128(guint64
* pclo
, guint64
* pchi
) {
467 if (++(*pclo
) == 0) ++(*pchi
);
470 DECINLINE
static int normalize128(guint64
* pclo
, guint64
* pchi
, int* pScale
,
471 int roundFlag
, int roundBit
)
473 guint32 overhang
= (guint32
)(*pchi
>> 32);
477 while (overhang
!= 0) {
478 for (deltaScale
= 1; deltaScale
< DECIMAL_MAX_INTFACTORS
; deltaScale
++)
480 if (overhang
< constantsDecadeInt32Factors
[deltaScale
]) break;
484 if (scale
< 0) return DECIMAL_OVERFLOW
;
486 roundBit
= div128by32(pclo
, pchi
, constantsDecadeInt32Factors
[deltaScale
], 0);
488 overhang
= (guint32
)(*pchi
>> 32);
489 if (roundFlag
&& roundBit
&& *pclo
== (guint64
)-1 && (gint32
)*pchi
== (gint32
)-1) {
496 if (roundFlag
&& roundBit
) {
497 roundUp128(pclo
, pchi
);
498 TEST((*pchi
>> 32) == 0);
501 return DECIMAL_SUCCESS
;
504 DECINLINE
static int maxLeftShift(/*[In, Out]*/decimal_repr
* pA
)
506 guint64 lo64
= (((guint64
)(pA
->mid32
)) << 32) | pA
->lo32
;
507 guint32 hi32
= pA
->hi32
;
510 for (shift
= 0; ((gint32
)hi32
) >= 0 && shift
< 96; shift
++) {
512 if (((gint64
)lo64
) < 0) hi32
++;
516 pA
->lo32
= (guint32
) lo64
;
517 pA
->mid32
= (guint32
)(lo64
>>32);
523 DECINLINE
static void rshift128(guint64
* pclo
, guint64
* pchi
)
526 *pclo
|= (*pchi
& 1) << 63;
530 DECINLINE
static void lshift96(guint32
* pclo
, guint32
* pcmid
, guint32
* pchi
)
533 *pchi
|= (*pcmid
& LIT_GUINT32_HIGHBIT
) >> 31;
535 *pcmid
|= (*pclo
& LIT_GUINT32_HIGHBIT
) >> 31;
539 DECINLINE
static void lshift128(guint64
* pclo
, guint64
* pchi
)
542 *pchi
|= (*pclo
& LIT_GUINT64_HIGHBIT
) >> 63;
546 DECINLINE
static void rshift192(guint64
* pclo
, guint64
* pcmi
, guint64
* pchi
)
549 *pclo
|= (*pcmi
& 1) << 63;
551 *pcmi
|= (*pchi
& 1) << 63;
556 my_g_bit_nth_msf (gsize mask
)
558 /* Mask is expected to be != 0 */
559 #if defined(__i386__) && defined(__GNUC__)
562 __asm__("bsrl %1,%0\n\t"
563 : "=r" (r
) : "rm" (mask
));
565 #elif defined(__x86_64) && defined(__GNUC__)
568 __asm__("bsrq %1,%0\n\t"
569 : "=r" (r
) : "rm" (mask
));
571 #elif defined(__i386__) && defined(_MSC_VER)
572 unsigned long bIndex
= 0;
573 if (_BitScanReverse (&bIndex
, mask
))
576 #elif defined(__x86_64__) && defined(_MSC_VER)
577 unsigned long bIndex
= 0;
578 if (_BitScanReverse64 (&bIndex
, mask
))
584 i
= sizeof (gsize
) * 8;
587 if (mask
& (1UL << i
))
594 /* returns log2(a) or DECIMAL_LOG_NEGINF for a = 0 */
595 DECINLINE
static int log2_32(guint32 a
)
597 if (a
== 0) return DECIMAL_LOG_NEGINF
;
599 return my_g_bit_nth_msf (a
) + 1;
602 /* returns log2(a) or DECIMAL_LOG_NEGINF for a = 0 */
603 DECINLINE
static int log2_64(guint64 a
)
605 if (a
== 0) return DECIMAL_LOG_NEGINF
;
607 #if SIZEOF_VOID_P == 8
608 return my_g_bit_nth_msf (a
) + 1;
611 return my_g_bit_nth_msf ((guint32
)a
) + 1;
613 return my_g_bit_nth_msf ((guint32
)(a
>> 32)) + 1 + 32;
617 /* returns log2(a) or DECIMAL_LOG_NEGINF for a = 0 */
618 DECINLINE
static int log2_128(guint64 alo
, guint64 ahi
)
620 if (ahi
== 0) return log2_64(alo
);
621 else return log2_64(ahi
) + 64;
624 /* returns a upper limit for log2(a) considering scale */
625 DECINLINE
static int log2withScale_128(guint64 alo
, guint64 ahi
, int scale
)
627 int tlog2
= log2_128(alo
, ahi
);
628 if (tlog2
< 0) tlog2
= 0;
629 return tlog2
- (scale
* 33219) / 10000;
632 DECINLINE
static int pack128toDecimal(/*[Out]*/decimal_repr
* pA
, guint64 alo
, guint64 ahi
,
635 PRECONDITION((ahi
>> 32) == 0);
636 PRECONDITION(sign
== 0 || sign
== 1);
637 PRECONDITION(scale
>= 0 && scale
<= DECIMAL_MAX_SCALE
);
639 if (scale
< 0 || scale
> DECIMAL_MAX_SCALE
|| (ahi
>> 32) != 0) {
640 return DECIMAL_OVERFLOW
;
643 pA
->lo32
= (guint32
) alo
;
644 pA
->mid32
= (guint32
) (alo
>> 32);
645 pA
->hi32
= (guint32
) ahi
;
646 pA
->signscale
.sign
= sign
;
647 pA
->signscale
.scale
= scale
;
649 return DECIMAL_SUCCESS
;
652 DECINLINE
static int adjustScale128(guint64
* palo
, guint64
* pahi
, int deltaScale
)
656 if (deltaScale
< 0) {
658 if (deltaScale
> DECIMAL_MAX_SCALE
) return DECIMAL_INTERNAL_ERROR
;
659 while (deltaScale
> 0) {
660 idx
= (deltaScale
> DECIMAL_MAX_INTFACTORS
) ? DECIMAL_MAX_INTFACTORS
: deltaScale
;
662 div128by32(palo
, pahi
, constantsDecadeInt32Factors
[idx
], 0);
664 } else if (deltaScale
> 0) {
665 if (deltaScale
> DECIMAL_MAX_SCALE
) return DECIMAL_INTERNAL_ERROR
;
666 while (deltaScale
> 0) {
667 idx
= (deltaScale
> DECIMAL_MAX_INTFACTORS
) ? DECIMAL_MAX_INTFACTORS
: deltaScale
;
669 rc
= mult128by32(palo
, pahi
, constantsDecadeInt32Factors
[idx
], 0);
670 if (rc
!= DECIMAL_SUCCESS
) return rc
;
674 return DECIMAL_SUCCESS
;
677 /* input: c * 10^-(*pScale) * 2^-exp
678 output: c * 10^-(*pScale) with
679 minScale <= *pScale <= maxScale and (chi >> 32) == 0 */
680 DECINLINE
static int rescale128(guint64
* pclo
, guint64
* pchi
, int* pScale
, int texp
,
681 int minScale
, int maxScale
, int roundFlag
)
683 guint32 factor
, overhang
;
684 int scale
, i
, rc
, roundBit
= 0;
686 PRECONDITION(texp
>= 0);
692 while (texp
> 0 && scale
<= maxScale
) {
693 overhang
= (guint32
)(*pchi
>> 32);
695 /* The original loop was this: */
697 while (texp > 0 && (overhang > (2<<DECIMAL_MAX_INTFACTORS) || (*pclo & 1) == 0)) {
699 roundBit = (int)(*pclo & 1);
700 rshift128(pclo, pchi);
701 overhang = (guint32)(*pchi >> 32);
705 int msf
= my_g_bit_nth_msf (overhang
);
706 int shift
= msf
- (DECIMAL_MAX_INTFACTORS
+ 2);
713 *pclo
= (*pclo
>> shift
) | ((*pchi
& ((1 << shift
) - 1)) << (64 - shift
));
718 g_assert (overhang
> (2 << DECIMAL_MAX_INTFACTORS
));
721 while (texp
> 0 && (overhang
> (2<<DECIMAL_MAX_INTFACTORS
) || (*pclo
& 1) == 0)) {
722 if (--texp
== 0) roundBit
= (int)(*pclo
& 1);
723 rshift128(pclo
, pchi
);
727 if (texp
> DECIMAL_MAX_INTFACTORS
) i
= DECIMAL_MAX_INTFACTORS
;
729 if (scale
+ i
> maxScale
) i
= maxScale
- scale
;
733 factor
= constantsDecadeInt32Factors
[i
] >> i
; /* 10^i/2^i=5^i */
734 mult128by32(pclo
, pchi
, factor
, 0);
735 /*printf("3: %.17e\n", (((double)chi) * pow(2,64) + clo) * pow(10, -scale) * pow(2, -texp));*/
739 if (--texp
== 0) roundBit
= (int)(*pclo
& 1);
740 rshift128(pclo
, pchi
);
746 while (scale
> maxScale
) {
747 i
= scale
- maxScale
;
748 if (i
> DECIMAL_MAX_INTFACTORS
) i
= DECIMAL_MAX_INTFACTORS
;
750 roundBit
= div128by32(pclo
, pchi
, constantsDecadeInt32Factors
[i
], 0);
753 while (scale
< minScale
) {
754 if (!roundFlag
) roundBit
= 0;
755 i
= minScale
- scale
;
756 if (i
> DECIMAL_MAX_INTFACTORS
) i
= DECIMAL_MAX_INTFACTORS
;
758 rc
= mult128by32(pclo
, pchi
, constantsDecadeInt32Factors
[i
], roundBit
);
759 if (rc
!= DECIMAL_SUCCESS
) return rc
;
763 TEST(scale
>= 0 && scale
<= DECIMAL_MAX_SCALE
);
767 return normalize128(pclo
, pchi
, pScale
, roundFlag
, roundBit
);
770 /* performs a += b */
771 gint32
mono_decimalIncr(/*[In, Out]*/decimal_repr
* pA
, /*[In]*/decimal_repr
* pB
)
773 guint64 alo
, ahi
, blo
, bhi
;
774 int log2A
, log2B
, log2Result
, log10Result
, rc
;
775 int subFlag
, sign
, scaleA
, scaleB
;
779 DECTO128(pA
, alo
, ahi
);
780 DECTO128(pB
, blo
, bhi
);
782 sign
= pA
->signscale
.sign
;
783 subFlag
= sign
- (int)pB
->signscale
.sign
;
784 scaleA
= pA
->signscale
.scale
;
785 scaleB
= pB
->signscale
.scale
;
786 if (scaleA
== scaleB
) {
787 /* same scale, that's easy */
789 sub128(alo
, ahi
, blo
, bhi
, &alo
, &ahi
);
790 if (ahi
& LIT_GUINT64_HIGHBIT
) {
798 add128(alo
, ahi
, blo
, bhi
, &alo
, &ahi
);
800 rc
= normalize128(&alo
, &ahi
, &scaleA
, 1, 0);
802 /* scales must be adjusted */
803 /* Estimate log10 and scale of result for adjusting scales */
804 log2A
= log2withScale_128(alo
, ahi
, scaleA
);
805 log2B
= log2withScale_128(blo
, bhi
, scaleB
);
806 log2Result
= MAX (log2A
, log2B
);
807 if (!subFlag
) log2Result
++; /* result can have one bit more */
808 log10Result
= (log2Result
* 1000) / 3322 + 1;
809 /* we will calculate in 128bit, so we may need to adjust scale */
810 if (scaleB
> scaleA
) scaleA
= scaleB
;
811 if (scaleA
+ log10Result
> DECIMAL_MAX_SCALE
+ 7) {
812 /* this may not fit in 128bit, so limit it */
813 scaleA
= DECIMAL_MAX_SCALE
+ 7 - log10Result
;
816 rc
= adjustScale128(&alo
, &ahi
, scaleA
- (int)pA
->signscale
.scale
);
817 if (rc
!= DECIMAL_SUCCESS
) return rc
;
818 rc
= adjustScale128(&blo
, &bhi
, scaleA
- scaleB
);
819 if (rc
!= DECIMAL_SUCCESS
) return rc
;
822 sub128(alo
, ahi
, blo
, bhi
, &alo
, &ahi
);
823 if (ahi
& LIT_GUINT64_HIGHBIT
) {
831 add128(alo
, ahi
, blo
, bhi
, &alo
, &ahi
);
834 rc
= rescale128(&alo
, &ahi
,&scaleA
, 0, 0, DECIMAL_MAX_SCALE
, 1);
837 if (rc
!= DECIMAL_SUCCESS
) return rc
;
839 return pack128toDecimal(pA
, alo
, ahi
, scaleA
, sign
);
842 /* performs a += factor * constants[idx] */
843 static int incMultConstant128(guint64
* palo
, guint64
* pahi
, int idx
, int factor
)
847 PRECONDITION(idx
>= 0 && idx
<= DECIMAL_MAX_SCALE
);
848 PRECONDITION(factor
> 0 && factor
<= 9);
850 blo
= dec128decadeFactors
[idx
].lo
;
851 h
= bhi
= dec128decadeFactors
[idx
].hi
;
853 mult128by32(&blo
, &bhi
, factor
, 0);
854 if (h
> bhi
) return DECIMAL_OVERFLOW
;
857 add128(*palo
, *pahi
, blo
, bhi
, palo
, pahi
);
858 if (h
> *pahi
) return DECIMAL_OVERFLOW
;
859 return DECIMAL_SUCCESS
;
862 DECINLINE
static void div128DecadeFactor(guint64
* palo
, guint64
* pahi
, int powerOfTen
)
864 int idx
, roundBit
= 0;
866 while (powerOfTen
> 0) {
867 idx
= (powerOfTen
> DECIMAL_MAX_INTFACTORS
) ? DECIMAL_MAX_INTFACTORS
: powerOfTen
;
869 roundBit
= div128by32(palo
, pahi
, constantsDecadeInt32Factors
[idx
], 0);
872 if (roundBit
) roundUp128(palo
, pahi
);
875 /* calc significant digits of mantisse */
876 DECINLINE
static int calcDigits(guint64 alo
, guint64 ahi
)
883 return 0; /* zero has no signficant digits */
885 tlog2
= log2_64(alo
);
888 tlog2
= 64 + log2_64(ahi
);
891 tlog10
= (tlog2
* 1000) / 3322;
892 /* we need an exact floor value of log10(a) */
893 if (dec128decadeFactors
[tlog10
].hi
> ahi
894 || (dec128decadeFactors
[tlog10
].hi
== ahi
895 && dec128decadeFactors
[tlog10
].lo
> alo
)) {
901 gint32
mono_double2decimal(/*[Out]*/decimal_repr
* pA
, double val
, gint32 digits
)
904 guint64
* p
= (guint64
*)(&val
);
905 int sigDigits
, sign
, texp
, rc
, scale
;
908 PRECONDITION(digits
<= 15);
910 sign
= ((*p
& LIT_GUINT64_HIGHBIT
) != 0) ? 1 : 0;
911 k
= ((guint16
)((*p
) >> 52)) & 0x7FF;
912 alo
= (*p
& LIT_GUINT64(0xFFFFFFFFFFFFF)) | LIT_GUINT64(0x10000000000000);
915 texp
= (k
& 0x7FF) - 0x3FF;
916 if (k
== 0x7FF || texp
>= 96) return DECIMAL_OVERFLOW
; /* NaNs, SNaNs, Infinities or >= 2^96 */
917 if (k
== 0 || texp
<= -94) { /* Subnormals, Zeros or < 2^-94 */
918 DECINIT(pA
); /* return zero */
919 return DECIMAL_SUCCESS
;
924 for (; texp
> 0; texp
--) {
925 lshift128(&alo
, &ahi
);
930 rc
= rescale128(&alo
, &ahi
, &scale
, -texp
, 0, DECIMAL_MAX_SCALE
, 0);
931 if (rc
!= DECIMAL_SUCCESS
) return rc
;
933 sigDigits
= calcDigits(alo
, ahi
);
934 /* too much digits, then round */
935 if (sigDigits
> digits
) {
936 div128DecadeFactor(&alo
, &ahi
, sigDigits
- digits
);
937 scale
-= sigDigits
- digits
;
938 /* check value, may be 10^(digits+1) caused by rounding */
939 if (ahi
== dec128decadeFactors
[digits
].hi
940 && alo
== dec128decadeFactors
[digits
].lo
) {
941 div128by32(&alo
, &ahi
, 10, 0);
945 rc
= mult128DecadeFactor(&alo
, &ahi
, -scale
);
946 if (rc
!= DECIMAL_SUCCESS
) return rc
;
951 return pack128toDecimal(pA
, alo
, ahi
, scale
, sign
);
955 * mono_string2decimal:
961 * converts a digit string to decimal
962 * The significant digits must be passed as an integer in buf !
965 * if you want to convert the number 123.456789012345678901234 to decimal
966 * buf := "123456789012345678901234"
971 * you want to convert -79228162514264337593543950335 to decimal
972 * buf := "79228162514264337593543950335"
977 * you want to convert -7922816251426433759354395033.250000000000001 to decimal
978 * buf := "7922816251426433759354395033250000000000001"
981 * returns (decimal)-7922816251426433759354395033.3
984 * you want to convert -7922816251426433759354395033.250000000000000 to decimal
985 * buf := "7922816251426433759354395033250000000000000"
988 * returns (decimal)-7922816251426433759354395033.2
991 * you want to convert -7922816251426433759354395033.150000000000000 to decimal
992 * buf := "7922816251426433759354395033150000000000000"
995 * returns (decimal)-7922816251426433759354395033.2
997 * Uses banker's rule for rounding if there are more digits than can be
998 * represented by the significant
1000 gint32
mono_string2decimal(/*[Out]*/decimal_repr
* pA
, MonoString
* str
, gint32 decrDecimal
, gint32 sign
)
1002 gushort
*buf
= mono_string_chars(str
);
1005 int n
, rc
, i
, len
, sigLen
= -1, firstNonZero
;
1006 int scale
, roundBit
= 0;
1011 for (p
= buf
, len
= 0; *p
!= 0; len
++, p
++) { }
1013 for (p
= buf
, i
= 0; *p
!= 0; i
++, p
++) {
1015 if (n
< 0 || n
> 9) {
1016 return DECIMAL_INVALID_CHARACTER
;
1021 sigLen
= (len
- firstNonZero
> DECIMAL_MAX_SCALE
+1)
1022 ? DECIMAL_MAX_SCALE
+1+firstNonZero
: len
;
1023 if (decrDecimal
> sigLen
+1) return DECIMAL_OVERFLOW
;
1025 if (i
>= sigLen
) break;
1026 rc
= incMultConstant128(&alo
, &ahi
, sigLen
- 1 - i
, n
);
1027 if (rc
!= DECIMAL_SUCCESS
) {
1033 scale
= sigLen
- decrDecimal
;
1035 if (i
< len
) { /* too much digits, we must round */
1037 if (n
< 0 || n
> 9) {
1038 return DECIMAL_INVALID_CHARACTER
;
1040 if (n
> 5) roundBit
= 1;
1041 else if (n
== 5) { /* we must take a nearer look */
1043 for (++i
; i
< len
; ++i
) {
1044 if (buf
[i
] != '0') break; /* we are greater than .5 */
1046 if (i
< len
/* greater than exactly .5 */
1047 || n
% 2 == 1) { /* exactly .5, use banker's rule for rounding */
1054 rc
= normalize128(&alo
, &ahi
, &scale
, 1, roundBit
);
1055 if (rc
!= DECIMAL_SUCCESS
) return rc
;
1058 if (alo
== 0 && ahi
== 0) {
1060 return DECIMAL_SUCCESS
;
1062 return pack128toDecimal(pA
, alo
, ahi
, sigLen
- decrDecimal
, sign
);
1067 * mono_decimal2string:
1069 * returns minimal number of digit string to represent decimal
1070 * No leading or trailing zeros !
1072 * *pA == 0 => buf = "", *pDecPos = 1, *pSign = 0
1073 * *pA == 12.34 => buf = "1234", *pDecPos = 2, *pSign = 0
1074 * *pA == -1000.0000 => buf = "1", *pDecPos = 4, *pSign = 1
1075 * *pA == -0.00000076 => buf = "76", *pDecPos = -6, *pSign = 0
1078 * pA decimal instance to convert
1079 * digits < 0: use decimals instead
1080 * = 0: gets mantisse as integer
1081 * > 0: gets at most <digits> digits, rounded according to banker's rule if necessary
1082 * decimals only used if digits < 0
1083 * >= 0: number of decimal places
1084 * buf pointer to result buffer
1085 * bufSize size of buffer
1086 * pDecPos receives insert position of decimal point relative to start of buffer
1087 * pSign receives sign
1089 gint32
mono_decimal2string(/*[In]*/decimal_repr
* pA
, gint32 digits
, gint32 decimals
,
1090 MonoArray
* pArray
, gint32 bufSize
, gint32
* pDecPos
, gint32
* pSign
)
1093 guint16
*buf
= (guint16
*) mono_array_addr(pArray
, guint16
, 0);
1094 guint16
*q
, *p
= tmp
;
1098 gint32 sigDigits
, d
;
1101 MONO_ARCH_SAVE_REGS
;
1103 scale
= pA
->signscale
.scale
;
1104 DECTO128(pA
, alo
, ahi
);
1105 sigDigits
= calcDigits(alo
, ahi
); /* significant digits */
1107 /* calc needed digits (without leading or trailing zeros) */
1108 d
= (digits
== 0) ? sigDigits
: digits
;
1109 if (d
< 0) { /* use decimals ? */
1110 if (0 <= decimals
&& decimals
< scale
) {
1111 d
= sigDigits
- scale
+ decimals
;
1113 d
= sigDigits
; /* use all you can get */
1117 if (sigDigits
> d
) { /* we need to round decimal number */
1119 aa
.signscale
.scale
= DECIMAL_MAX_SCALE
;
1120 mono_decimalRound(&aa
, DECIMAL_MAX_SCALE
- sigDigits
+ d
);
1121 DECTO128(&aa
, alo
, ahi
);
1122 sigDigits
+= calcDigits(alo
, ahi
) - d
;
1127 /* get digits starting from the tail */
1128 for (; (alo
!= 0 || ahi
!= 0) && len
< 40; len
++) {
1129 div128by32(&alo
, &ahi
, 10, &rest
);
1130 *p
++ = '0' + (char) rest
;
1135 if (len
>= bufSize
) return DECIMAL_BUFFER_OVERFLOW
;
1137 /* now we have the minimal count of digits,
1138 extend to wished count of digits or decimals */
1140 if (digits
>= 0) { /* count digits */
1141 if (digits
>= bufSize
) return DECIMAL_BUFFER_OVERFLOW
;
1143 /* zero or rounded to zero */
1146 /* copy significant digits */
1147 for (i
= 0; i
< len
; i
++) {
1150 *pDecPos
= sigDigits
- scale
;
1152 /* add trailing zeros */
1153 for (i
= len
; i
< digits
; i
++) {
1156 } else { /* count decimals */
1157 if (scale
>= sigDigits
) { /* add leading zeros */
1158 if (decimals
+2 >= bufSize
) return DECIMAL_BUFFER_OVERFLOW
;
1160 for (i
= 0; i
<= scale
- sigDigits
; i
++) {
1164 if (sigDigits
- scale
+ decimals
+1 >= bufSize
) return DECIMAL_BUFFER_OVERFLOW
;
1165 *pDecPos
= sigDigits
- scale
;
1167 /* copy significant digits */
1168 for (i
= 0; i
< len
; i
++) {
1171 /* add trailing zeros */
1172 for (i
= scale
; i
< decimals
; i
++) {
1178 *pSign
= (sigDigits
> 0) ? pA
->signscale
.sign
: 0; /* zero has positive sign */
1180 return DECIMAL_SUCCESS
;
1184 * mono_decimal2UInt64:
1187 * converts a decimal to an UInt64 without rounding
1189 gint32
mono_decimal2UInt64(/*[In]*/decimal_repr
* pA
, guint64
* pResult
)
1194 MONO_ARCH_SAVE_REGS
;
1196 DECTO128(pA
, alo
, ahi
);
1197 scale
= pA
->signscale
.scale
;
1199 div128DecadeFactor(&alo
, &ahi
, scale
);
1202 /* overflow if integer too large or < 0 */
1203 if (ahi
!= 0 || (alo
!= 0 && pA
->signscale
.sign
)) return DECIMAL_OVERFLOW
;
1206 return DECIMAL_SUCCESS
;
1210 * mono_decimal2Int64:
1213 * converts a decimal to an Int64 without rounding
1215 gint32
mono_decimal2Int64(/*[In]*/decimal_repr
* pA
, gint64
* pResult
)
1220 MONO_ARCH_SAVE_REGS
;
1222 DECTO128(pA
, alo
, ahi
);
1223 scale
= pA
->signscale
.scale
;
1225 div128DecadeFactor(&alo
, &ahi
, scale
);
1228 if (ahi
!= 0) return DECIMAL_OVERFLOW
;
1230 sign
= pA
->signscale
.sign
;
1231 if (sign
&& alo
!= 0) {
1232 if (alo
> LIT_GUINT64_HIGHBIT
) return DECIMAL_OVERFLOW
;
1233 *pResult
= (gint64
) ~(alo
-1);
1235 if (alo
& LIT_GUINT64_HIGHBIT
) return DECIMAL_OVERFLOW
;
1236 *pResult
= (gint64
) alo
;
1239 return DECIMAL_SUCCESS
;
1242 void mono_decimalFloorAndTrunc(/*[In, Out]*/decimal_repr
* pA
, gint32 floorFlag
)
1245 guint32 factor
, rest
;
1246 int scale
, sign
, idx
;
1249 MONO_ARCH_SAVE_REGS
;
1251 scale
= pA
->signscale
.scale
;
1252 if (scale
== 0) return; /* nothing to do */
1254 DECTO128(pA
, alo
, ahi
);
1255 sign
= pA
->signscale
.sign
;
1258 idx
= (scale
> DECIMAL_MAX_INTFACTORS
) ? DECIMAL_MAX_INTFACTORS
: scale
;
1259 factor
= constantsDecadeInt32Factors
[idx
];
1261 div128by32(&alo
, &ahi
, factor
, &rest
);
1262 hasRest
= hasRest
|| (rest
!= 0);
1265 if (floorFlag
&& hasRest
&& sign
) { /* floor: if negative, we must round up */
1266 roundUp128(&alo
, &ahi
);
1269 pack128toDecimal(pA
, alo
, ahi
, 0, sign
);
1272 void mono_decimalRound(/*[In, Out]*/decimal_repr
* pA
, gint32 decimals
)
1277 MONO_ARCH_SAVE_REGS
;
1279 DECTO128(pA
, alo
, ahi
);
1280 scale
= pA
->signscale
.scale
;
1281 sign
= pA
->signscale
.sign
;
1282 if (scale
> decimals
) {
1283 div128DecadeFactor(&alo
, &ahi
, scale
- decimals
);
1287 pack128toDecimal(pA
, alo
, ahi
, scale
, sign
);
1290 gint32
mono_decimalMult(/*[In, Out]*/decimal_repr
* pA
, /*[In]*/decimal_repr
* pB
)
1292 guint64 low
, mid
, high
;
1294 int scale
, sign
, rc
;
1296 MONO_ARCH_SAVE_REGS
;
1298 mult96by96to192(pA
->lo32
, pA
->mid32
, pA
->hi32
, pB
->lo32
, pB
->mid32
, pB
->hi32
,
1301 /* adjust scale and sign */
1302 scale
= (int)pA
->signscale
.scale
+ (int)pB
->signscale
.scale
;
1303 sign
= pA
->signscale
.sign
^ pB
->signscale
.sign
;
1305 /* first scaling step */
1306 factor
= constantsDecadeInt32Factors
[DECIMAL_MAX_INTFACTORS
];
1307 while (high
!= 0 || (mid
>>32) >= factor
) {
1309 factor
/= 1000; /* we need some digits for final rounding */
1310 scale
-= DECIMAL_MAX_INTFACTORS
- 3;
1312 scale
-= DECIMAL_MAX_INTFACTORS
;
1315 div192by32(&low
, &mid
, &high
, factor
);
1318 /* second and final scaling */
1319 rc
= rescale128(&low
, &mid
, &scale
, 0, 0, DECIMAL_MAX_SCALE
, 1);
1320 if (rc
!= DECIMAL_SUCCESS
) return rc
;
1322 return pack128toDecimal(pA
, low
, mid
, scale
, sign
);
1325 static DECINLINE
int decimalDivSub(/*[In]*/decimal_repr
* pA
, /*[In]*/decimal_repr
* pB
,
1326 guint64
* pclo
, guint64
* pchi
, int* pExp
)
1328 guint64 alo
, ami
, ahi
;
1329 guint64 tlo
, tmi
, thi
;
1330 guint32 blo
, bmi
, bhi
;
1331 int ashift
, bshift
, extraBit
, texp
;
1333 ahi
= (((guint64
)(pA
->hi32
)) << 32) | pA
->mid32
;
1334 ami
= ((guint64
)(pA
->lo32
)) << 32;
1340 if (blo
== 0 && bmi
== 0 && bhi
== 0) {
1341 return DECIMAL_DIVIDE_BY_ZERO
;
1344 if (ami
== 0 && ahi
== 0) {
1346 return DECIMAL_FINISHED
;
1349 /* enlarge dividend to get maximal precision */
1353 for (ashift
= 64; (ahi
& LIT_GUINT64_HIGHBIT
) == 0; ++ashift
) {
1357 for (ashift
= 0; (ahi
& LIT_GUINT64_HIGHBIT
) == 0; ++ashift
) {
1358 lshift128(&ami
, &ahi
);
1362 /* ensure that divisor is at least 2^95 */
1371 //g_assert (g_bit_nth_msf (bhi, 32) == my_g_bit_nth_msf (bhi));
1373 hi_shift
= 31 - my_g_bit_nth_msf (bhi
);
1375 bshift
= 64 + hi_shift
;
1381 for (bshift
= 32; (bhi
& LIT_GUINT32_HIGHBIT
) == 0; ++bshift
) {
1383 bhi
|= (bmi
& LIT_GUINT32_HIGHBIT
) >> 31;
1388 for (bshift
= 0; (bhi
& LIT_GUINT32_HIGHBIT
) == 0; ++bshift
) {
1390 bhi
|= (bmi
& LIT_GUINT32_HIGHBIT
) >> 31;
1392 bmi
|= (blo
& LIT_GUINT32_HIGHBIT
) >> 31;
1397 thi
= ((guint64
)bhi
)<<32 | bmi
;
1398 tmi
= ((guint64
)blo
)<<32;
1400 if (ahi
> thi
|| (ahi
== thi
&& ami
>= tmi
)) {
1401 sub192(alo
, ami
, ahi
, tlo
, tmi
, thi
, &alo
, &ami
, &ahi
);
1407 div192by96to128(alo
, ami
, ahi
, blo
, bmi
, bhi
, pclo
, pchi
);
1408 texp
= 128 + ashift
- bshift
;
1411 rshift128(pclo
, pchi
);
1412 *pchi
+= LIT_GUINT64_HIGHBIT
;
1416 /* try loss free right shift */
1417 while (texp
> 0 && (*pclo
& 1) == 0) {
1419 rshift128(pclo
, pchi
);
1425 return DECIMAL_SUCCESS
;
1428 gint32
mono_decimalDiv(/*[Out]*/decimal_repr
* pC
, /*[In]*/decimal_repr
* pA
, /*[In]*/decimal_repr
* pB
)
1430 guint64 clo
, chi
; /* result */
1431 int scale
, texp
, rc
;
1433 MONO_ARCH_SAVE_REGS
;
1435 /* Check for common cases */
1436 if (mono_decimalCompare (pA
, pB
) == 0)
1438 return pack128toDecimal (pC
, 1, 0, 0, 0);
1439 pA
->signscale
.sign
= pA
->signscale
.sign
? 0 : 1;
1440 if (mono_decimalCompare (pA
, pB
) == 0)
1442 return pack128toDecimal (pC
, 1, 0, 0, 1);
1443 pA
->signscale
.sign
= pA
->signscale
.sign
? 0 : 1;
1445 rc
= decimalDivSub(pA
, pB
, &clo
, &chi
, &texp
);
1446 if (rc
!= DECIMAL_SUCCESS
) {
1447 if (rc
== DECIMAL_FINISHED
) rc
= DECIMAL_SUCCESS
;
1451 /* adjust scale and sign */
1452 scale
= (int)pA
->signscale
.scale
- (int)pB
->signscale
.scale
;
1454 /*test: printf("0: %.17e\n", (((double)chi) * pow(2,64) + clo) * pow(10, -scale) * pow(2, -exp));*/
1455 rc
= rescale128(&clo
, &chi
, &scale
, texp
, 0, DECIMAL_MAX_SCALE
, 1);
1456 if (rc
!= DECIMAL_SUCCESS
) return rc
;
1458 return pack128toDecimal(pC
, clo
, chi
, scale
, pA
->signscale
.sign
^ pB
->signscale
.sign
);
1461 gint32
mono_decimalIntDiv(/*[Out]*/decimal_repr
* pC
, /*[In]*/decimal_repr
* pA
, /*[In]*/decimal_repr
* pB
)
1463 guint64 clo
, chi
; /* result */
1464 int scale
, texp
, rc
;
1466 MONO_ARCH_SAVE_REGS
;
1468 rc
= decimalDivSub(pA
, pB
, &clo
, &chi
, &texp
);
1469 if (rc
!= DECIMAL_SUCCESS
) {
1470 if (rc
== DECIMAL_FINISHED
) rc
= DECIMAL_SUCCESS
;
1475 scale
= (int)pA
->signscale
.scale
- (int)pB
->signscale
.scale
;
1477 /* truncate result to integer */
1478 rc
= rescale128(&clo
, &chi
, &scale
, texp
, 0, 0, 0);
1479 if (rc
!= DECIMAL_SUCCESS
) return rc
;
1481 return pack128toDecimal(pC
, clo
, chi
, scale
, pA
->signscale
.sign
);
1484 /* approximation for log2 of a
1485 If q is the exact value for log2(a), then q <= decimalLog2(a) <= q+1 */
1486 DECINLINE
static int decimalLog2(/*[In]*/decimal_repr
* pA
)
1489 int scale
= pA
->signscale
.scale
;
1491 if (pA
->hi32
!= 0) tlog2
= 64 + log2_32(pA
->hi32
);
1492 else if (pA
->mid32
!= 0) tlog2
= 32 + log2_32(pA
->mid32
);
1493 else tlog2
= log2_32(pA
->lo32
);
1495 if (tlog2
!= DECIMAL_LOG_NEGINF
) {
1496 tlog2
-= (scale
* 33219) / 10000;
1502 DECINLINE
static int decimalIsZero(/*[In]*/decimal_repr
* pA
)
1504 return (pA
->lo32
== 0 && pA
->mid32
== 0 && pA
->hi32
== 0);
1507 gint32
mono_decimalCompare(/*[In]*/decimal_repr
* pA
, /*[In]*/decimal_repr
* pB
)
1509 int log2a
, log2b
, delta
, sign
;
1512 MONO_ARCH_SAVE_REGS
;
1514 sign
= (pA
->signscale
.sign
) ? -1 : 1;
1516 if (pA
->signscale
.sign
^ pB
->signscale
.sign
) {
1517 return (decimalIsZero(pA
) && decimalIsZero(pB
)) ? 0 : sign
;
1520 /* try fast comparison via log2 */
1521 log2a
= decimalLog2(pA
);
1522 log2b
= decimalLog2(pB
);
1523 delta
= log2a
- log2b
;
1524 /* decimalLog2 is not exact, so we can say nothing
1525 if abs(delta) <= 1 */
1526 if (delta
< -1) return -sign
;
1527 if (delta
> 1) return sign
;
1531 mono_decimalIncr(&aa
, pB
);
1533 if (decimalIsZero(&aa
)) return 0;
1535 return (aa
.signscale
.sign
) ? 1 : -1;
1538 /* d=(-1)^sign * n * 2^(k-52) with sign (1bit), k(11bit), n-2^52(52bit) */
1539 DECINLINE
static void buildIEEE754Double(double* pd
, int sign
, int texp
, guint64 mantisse
)
1541 guint64
* p
= (guint64
*) pd
;
1543 PRECONDITION(sign
== 0 || sign
== 1);
1544 *p
= (((guint64
)sign
) << 63) | (((guint64
)((1023+texp
)&0x7ff)) << 52) | mantisse
;
1546 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1549 guint32
*t
= (guint32
*)p
;
1558 double mono_decimal2double(/*[In]*/decimal_repr
* pA
)
1561 guint64 alo
, ahi
, mantisse
;
1562 guint32 overhang
, factor
, roundBits
;
1563 int scale
, texp
, log5
, i
;
1565 MONO_ARCH_SAVE_REGS
;
1567 ahi
= (((guint64
)(pA
->hi32
)) << 32) | pA
->mid32
;
1568 alo
= ((guint64
)(pA
->lo32
)) << 32;
1570 /* special case zero */
1571 if (ahi
== 0 && alo
== 0) return 0.0;
1574 scale
= pA
->signscale
.scale
;
1576 /* transform n * 10^-scale and exp = 0 => m * 2^-exp and scale = 0 */
1578 while ((ahi
& LIT_GUINT64_HIGHBIT
) == 0) {
1579 lshift128(&alo
, &ahi
);
1583 overhang
= (guint32
) (ahi
>> 32);
1584 if (overhang
>= 5) {
1586 log5
= (log2_32(overhang
) * 1000) / 2322; /* ln(5)/ln(2) = 2.3219... */
1587 if (log5
< DECIMAL_MAX_INTFACTORS
) {
1588 /* get maximal factor=5^i, so that overhang / factor >= 1 */
1589 factor
= constantsDecadeInt32Factors
[log5
] >> log5
; /* 5^n = 10^n/2^n */
1590 i
= log5
+ overhang
/ factor
;
1592 i
= DECIMAL_MAX_INTFACTORS
; /* we have only constants up to 10^DECIMAL_MAX_INTFACTORS */
1594 if (i
> scale
) i
= scale
;
1595 factor
= constantsDecadeInt32Factors
[i
] >> i
; /* 5^n = 10^n/2^n */
1596 /* n * 10^-scale * 2^-exp => m * 10^-(scale-i) * 2^-(exp+i) with m = n * 5^-i */
1597 div128by32(&alo
, &ahi
, factor
, 0);
1603 /* normalize significand (highest bit should be 1) */
1604 while ((ahi
& LIT_GUINT64_HIGHBIT
) == 0) {
1605 lshift128(&alo
, &ahi
);
1609 /* round to nearest even */
1610 roundBits
= (guint32
)ahi
& 0x7ff;
1612 if ((ahi
& LIT_GUINT64_HIGHBIT
) == 0) { /* overflow ? */
1615 } else if ((roundBits
& 0x400) == 0) ahi
&= ~1;
1617 /* 96 bit => 1 implizit bit and 52 explicit bits */
1618 mantisse
= (ahi
& ~LIT_GUINT64_HIGHBIT
) >> 11;
1620 buildIEEE754Double(&d
, pA
->signscale
.sign
, -texp
+95, mantisse
);
1626 gint32
mono_decimalSetExponent(/*[In, Out]*/decimal_repr
* pA
, gint32 texp
)
1630 int scale
= pA
->signscale
.scale
;
1632 MONO_ARCH_SAVE_REGS
;
1636 if (scale
< 0 || scale
> DECIMAL_MAX_SCALE
) {
1637 DECTO128(pA
, alo
, ahi
);
1638 rc
= rescale128(&alo
, &ahi
, &scale
, 0, 0, DECIMAL_MAX_SCALE
, 1);
1639 if (rc
!= DECIMAL_SUCCESS
) return rc
;
1640 return pack128toDecimal(pA
, alo
, ahi
, scale
, pA
->signscale
.sign
);
1642 pA
->signscale
.scale
= scale
;
1643 return DECIMAL_SUCCESS
;
1647 #endif /* DISABLE_DECIMAL */