2009-03-11 Zoltan Varga <vargaz@gmail.com>
[mono-debugger.git] / mono / metadata / decimal.c
blob6524443eab3d57168325a710d2ac93e05d74671a
1 /*
2 * decimal.c
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
9 */
12 * machine dependent configuration for
13 * CSharp value type System.Decimal
16 #include "config.h"
17 #include <mono/metadata/exception.h>
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <string.h>
21 #include <math.h>
22 #ifdef HAVE_MEMORY_H
23 #include <memory.h>
24 #endif
25 #ifdef _MSC_VER
26 #include <intrin.h>
27 #endif
29 #ifndef DISABLE_DECIMAL
31 /* needed for building microsoft dll */
32 #ifdef __GNUC__
33 #define DECINLINE __inline
34 #else
35 #define DECINLINE
36 #endif
38 #define LIT_GUINT32(x) x
39 #define LIT_GUINT64(x) x##LL
42 /* we need a UInt64 type => guint64 */
43 #include <glib.h>
45 #include "decimal.h"
48 * Deal with anon union support.
50 #define ss32 u.ss32
51 #define signscale u.signscale
53 /* debugging stuff */
54 #ifdef _DEBUG
55 #include <assert.h>
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);
61 #else
62 #define PRECONDITION(flag)
63 #define POSTCONDITION(flag)
64 #define TEST(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
80 /* some MACROS */
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; \
97 hi = (pd)->hi32;
99 /* some constants */
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)
111 typedef struct {
112 guint64 lo;
113 guint64 hi;
114 } dec128_repr;
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)
154 alo += blo;
155 if (alo < blo) ahi++; /* carry */
156 ahi += bhi;
158 *pclo = alo;
159 *pchi = ahi;
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)
168 guint64 clo, chi;
170 clo = alo - blo;
171 chi = ahi - bhi;
172 if (alo < blo) chi--; /* borrow */
174 *pclo = clo;
175 *pchi = chi;
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)
184 alo += blo;
185 if (alo < blo) { /* carry low */
186 ami++;
187 if (ami == 0) ahi++; /* carry mid */
189 ami += bmi;
190 if (ami < bmi) ahi++; /* carry mid */
191 ahi += bhi;
192 *pclo = alo;
193 *pcmi = ami;
194 *pchi = ahi;
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;
205 clo = alo - blo;
206 cmi = ami - bmi;
207 chi = ahi - bhi;
208 if (alo < blo) {
209 if (cmi == 0) chi--; /* borrow mid */
210 cmi--; /* borrow low */
212 if (ami < bmi) chi--; /* borrow mid */
213 *pclo = clo;
214 *pcmi = cmi;
215 *pchi = chi;
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)
223 guint64 a, b, c, d;
224 guint32 h0, h1, h2, h3, h4, h5;
225 int carry0, carry1;
227 a = ((guint64)alo) * blo;
228 h0 = (guint32) a;
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++;
235 h1 = (guint32) a;
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++;
244 h2 = (guint32) a;
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++;
251 h3 = (guint32) a;
253 a >>= 32; a += carry1;
254 b = ((guint64)ahi) * bhi;
255 a += b;
256 h4 = (guint32) a;
258 a >>= 32; a += carry0;
259 h5 = (guint32) a;
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,
268 guint32 factor,
269 guint64* pclo, guint64* pchi)
271 guint64 a;
272 guint32 h0, h1;
274 a = ((guint64)alo) * factor;
275 h0 = (guint32) a;
277 a >>= 32;
278 a += ((guint64)ami) * factor;
279 h1 = (guint32) a;
281 a >>= 32;
282 a += ((guint64)ahi) * factor;
284 *pclo = ((guint64)h1) << 32 | h0;
285 *pchi = a;
288 /* multiplication c(128bit) *= b(32bit) */
289 DECINLINE static int mult128by32(guint64* pclo, guint64* pchi, guint32 factor, int roundBit)
291 guint64 a;
292 guint32 h0, h1;
294 a = ((guint64)(guint32)(*pclo)) * factor;
295 if (roundBit) a += factor / 2;
296 h0 = (guint32) a;
298 a >>= 32;
299 a += (*pclo >> 32) * factor;
300 h1 = (guint32) a;
302 *pclo = ((guint64)h1) << 32 | h0;
304 a >>= 32;
305 a += ((guint64)(guint32)(*pchi)) * factor;
306 h0 = (guint32) a;
308 a >>= 32;
309 a += (*pchi >> 32) * factor;
310 h1 = (guint32) a;
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)
319 int idx, rc;
321 while (powerOfTen > 0) {
322 idx = (powerOfTen >= DECIMAL_MAX_INTFACTORS) ? DECIMAL_MAX_INTFACTORS : powerOfTen;
323 powerOfTen -= idx;
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)
331 returns roundBit */
332 DECINLINE static int div128by32(guint64* plo, guint64* phi, guint32 factor, guint32* pRest)
334 guint64 a, b, c, h;
336 h = *phi;
337 a = (guint32)(h >> 32);
338 b = a / factor;
339 a -= b * factor;
340 a <<= 32;
341 a |= (guint32) h;
342 c = a / factor;
343 a -= c * factor;
344 a <<= 32;
345 *phi = b << 32 | (guint32)c;
347 h = *plo;
348 a |= (guint32)(h >> 32);
349 b = a / factor;
350 a -= b * factor;
351 a <<= 32;
352 a |= (guint32) h;
353 c = a / factor;
354 a -= c * factor;
355 *plo = b << 32 | (guint32)c;
357 if (pRest) *pRest = (guint32) a;
359 a <<= 1;
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,
366 guint32 factor)
368 guint64 a, b, c, h;
370 h = *phi;
371 a = (guint32)(h >> 32);
372 b = a / factor;
373 a -= b * factor;
374 a <<= 32;
375 a |= (guint32) h;
376 c = a / factor;
377 a -= c * factor;
378 a <<= 32;
379 *phi = b << 32 | (guint32)c;
381 h = *pmi;
382 a |= (guint32)(h >> 32);
383 b = a / factor;
384 a -= b * factor;
385 a <<= 32;
386 a |= (guint32) h;
387 c = a / factor;
388 a -= c * factor;
389 a <<= 32;
390 *pmi = b << 32 | (guint32)c;
392 h = *plo;
393 a |= (guint32)(h >> 32);
394 b = a / factor;
395 a -= b * factor;
396 a <<= 32;
397 a |= (guint32) h;
398 c = a / factor;
399 a -= c * factor;
400 a <<= 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 */
411 guint32 c;
413 rlo = *palo; rmi = *pami; rhi = *pahi;
414 if (rhi >= (((guint64)bhi) << 32)) {
415 c = LIT_GUINT32(0xFFFFFFFF);
416 } else {
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) {
422 c--;
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);
429 return c;
432 /* c(128bit) = a(192bit) / b(96bit)
433 b must be >= 2^95 */
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 */
439 guint32 h, c;
441 PRECONDITION(ahi < (((guint64)bhi) << 32 | bmi)
442 || (ahi == (((guint64)bhi) << 32 | bmi) && (ami >> 32) > blo));
444 /* high 32 bit*/
445 rlo = alo; rmi = ami; rhi = ahi;
446 h = div192by96to32withRest(&rlo, &rmi, &rhi, blo, bmi, bhi);
448 /* mid 32 bit*/
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);
452 /* low 32 bit */
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) */
457 if (rhi >= bhi) {
458 c = LIT_GUINT32(0xFFFFFFFF);
459 } else {
460 rhi <<= 32;
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);
474 int scale = *pScale;
475 int deltaScale;
477 while (overhang != 0) {
478 for (deltaScale = 1; deltaScale < DECIMAL_MAX_INTFACTORS; deltaScale++)
480 if (overhang < constantsDecadeInt32Factors[deltaScale]) break;
483 scale -= deltaScale;
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) {
490 overhang = 1;
494 *pScale = scale;
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;
508 int shift;
510 for (shift = 0; ((gint32)hi32) >= 0 && shift < 96; shift++) {
511 hi32 <<= 1;
512 if (((gint64)lo64) < 0) hi32++;
513 lo64 <<= 1;
516 pA->lo32 = (guint32) lo64;
517 pA->mid32 = (guint32)(lo64>>32);
518 pA->hi32 = hi32;
520 return shift;
523 DECINLINE static void rshift128(guint64* pclo, guint64* pchi)
525 *pclo >>= 1;
526 *pclo |= (*pchi & 1) << 63;
527 *pchi >>= 1;
530 DECINLINE static void lshift96(guint32* pclo, guint32* pcmid, guint32* pchi)
532 *pchi <<= 1;
533 *pchi |= (*pcmid & LIT_GUINT32_HIGHBIT) >> 31;
534 *pcmid <<= 1;
535 *pcmid |= (*pclo & LIT_GUINT32_HIGHBIT) >> 31;
536 *pclo <<= 1;
539 DECINLINE static void lshift128(guint64* pclo, guint64* pchi)
541 *pchi <<= 1;
542 *pchi |= (*pclo & LIT_GUINT64_HIGHBIT) >> 63;
543 *pclo <<= 1;
546 DECINLINE static void rshift192(guint64* pclo, guint64* pcmi, guint64* pchi)
548 *pclo >>= 1;
549 *pclo |= (*pcmi & 1) << 63;
550 *pcmi >>= 1;
551 *pcmi |= (*pchi & 1) << 63;
552 *pchi >>= 1;
555 static inline gint
556 my_g_bit_nth_msf (gsize mask)
558 /* Mask is expected to be != 0 */
559 #if defined(__i386__) && defined(__GNUC__)
560 int r;
562 __asm__("bsrl %1,%0\n\t"
563 : "=r" (r) : "rm" (mask));
564 return r;
565 #elif defined(__x86_64) && defined(__GNUC__)
566 guint64 r;
568 __asm__("bsrq %1,%0\n\t"
569 : "=r" (r) : "rm" (mask));
570 return r;
571 #elif defined(__i386__) && defined(_MSC_VER)
572 unsigned long bIndex = 0;
573 if (_BitScanReverse (&bIndex, mask))
574 return bIndex;
575 return -1;
576 #elif defined(__x86_64__) && defined(_MSC_VER)
577 unsigned long bIndex = 0;
578 if (_BitScanReverse64 (&bIndex, mask))
579 return bIndex;
580 return -1;
581 #else
582 int i;
584 i = sizeof (gsize) * 8;
585 while (i > 0) {
586 i --;
587 if (mask & (1UL << i))
588 return i;
590 return -1;
591 #endif
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;
609 #else
610 if ((a >> 32) == 0)
611 return my_g_bit_nth_msf ((guint32)a) + 1;
612 else
613 return my_g_bit_nth_msf ((guint32)(a >> 32)) + 1 + 32;
614 #endif
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,
633 int scale, int sign)
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)
654 int idx, rc;
656 if (deltaScale < 0) {
657 deltaScale *= -1;
658 if (deltaScale > DECIMAL_MAX_SCALE) return DECIMAL_INTERNAL_ERROR;
659 while (deltaScale > 0) {
660 idx = (deltaScale > DECIMAL_MAX_INTFACTORS) ? DECIMAL_MAX_INTFACTORS : deltaScale;
661 deltaScale -= idx;
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;
668 deltaScale -= idx;
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);
688 scale = *pScale;
690 if (texp > 0) {
691 /* reduce exp */
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)) {
698 if (--texp == 0)
699 roundBit = (int)(*pclo & 1);
700 rshift128(pclo, pchi);
701 overhang = (guint32)(*pchi >> 32);
704 if (overhang > 0) {
705 int msf = my_g_bit_nth_msf (overhang);
706 int shift = msf - (DECIMAL_MAX_INTFACTORS + 2);
708 if (shift >= texp)
709 shift = texp - 1;
711 if (shift > 0) {
712 texp -= shift;
713 *pclo = (*pclo >> shift) | ((*pchi & ((1 << shift) - 1)) << (64 - shift));
714 *pchi >>= shift;
715 overhang >>= shift;
717 g_assert (texp > 0);
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);
724 overhang >>= 1;
727 if (texp > DECIMAL_MAX_INTFACTORS) i = DECIMAL_MAX_INTFACTORS;
728 else i = texp;
729 if (scale + i > maxScale) i = maxScale - scale;
730 if (i == 0) break;
731 texp -= i;
732 scale += i;
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));*/
738 while (texp > 0) {
739 if (--texp == 0) roundBit = (int)(*pclo & 1);
740 rshift128(pclo, pchi);
744 TEST(texp == 0);
746 while (scale > maxScale) {
747 i = scale - maxScale;
748 if (i > DECIMAL_MAX_INTFACTORS) i = DECIMAL_MAX_INTFACTORS;
749 scale -= i;
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;
757 scale += i;
758 rc = mult128by32(pclo, pchi, constantsDecadeInt32Factors[i], roundBit);
759 if (rc != DECIMAL_SUCCESS) return rc;
760 roundBit = 0;
763 TEST(scale >= 0 && scale <= DECIMAL_MAX_SCALE);
765 *pScale = 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;
777 MONO_ARCH_SAVE_REGS;
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 */
788 if (subFlag) {
789 sub128(alo, ahi, blo, bhi, &alo, &ahi);
790 if (ahi & LIT_GUINT64_HIGHBIT) {
791 alo--;
792 alo = ~alo;
793 if (alo == 0) ahi--;
794 ahi = ~ahi;
795 sign = !sign;
797 } else {
798 add128(alo, ahi, blo, bhi, &alo, &ahi);
800 rc = normalize128(&alo, &ahi, &scaleA, 1, 0);
801 } else {
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;
821 if (subFlag) {
822 sub128(alo, ahi, blo, bhi, &alo, &ahi);
823 if (ahi & LIT_GUINT64_HIGHBIT) {
824 alo--;
825 alo = ~alo;
826 if (alo == 0) ahi--;
827 ahi = ~ahi;
828 sign = !sign;
830 } else {
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)
845 guint64 blo, bhi, h;
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;
852 if (factor != 1) {
853 mult128by32(&blo, &bhi, factor, 0);
854 if (h > bhi) return DECIMAL_OVERFLOW;
856 h = *pahi;
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;
868 powerOfTen -= idx;
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)
878 int tlog2 = 0;
879 int tlog10;
881 if (ahi == 0) {
882 if (alo == 0) {
883 return 0; /* zero has no signficant digits */
884 } else {
885 tlog2 = log2_64(alo);
887 } else {
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)) {
896 --tlog10;
898 return tlog10+1;
901 gint32 mono_double2decimal(/*[Out]*/decimal_repr* pA, double val, gint32 digits)
903 guint64 alo, ahi;
904 guint64* p = (guint64*)(&val);
905 int sigDigits, sign, texp, rc, scale;
906 guint16 k;
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);
913 ahi = 0;
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;
922 texp -= 52;
923 if (texp > 0) {
924 for (; texp > 0; texp--) {
925 lshift128(&alo, &ahi);
929 scale = 0;
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);
942 scale--;
944 if (scale < 0) {
945 rc = mult128DecadeFactor(&alo, &ahi, -scale);
946 if (rc != DECIMAL_SUCCESS) return rc;
947 scale = 0;
951 return pack128toDecimal(pA, alo, ahi, scale, sign);
955 * mono_string2decimal:
956 * @decimal_repr:
957 * @str:
958 * @decrDecimal:
959 * @sign:
961 * converts a digit string to decimal
962 * The significant digits must be passed as an integer in buf !
964 * 1. Example:
965 * if you want to convert the number 123.456789012345678901234 to decimal
966 * buf := "123456789012345678901234"
967 * decrDecimal := 3
968 * sign := 0
970 * 2. Example:
971 * you want to convert -79228162514264337593543950335 to decimal
972 * buf := "79228162514264337593543950335"
973 * decrDecimal := 29
974 * sign := 1
976 * 3. Example:
977 * you want to convert -7922816251426433759354395033.250000000000001 to decimal
978 * buf := "7922816251426433759354395033250000000000001"
979 * decrDecimal := 29
980 * sign := 1
981 * returns (decimal)-7922816251426433759354395033.3
983 * 4. Example:
984 * you want to convert -7922816251426433759354395033.250000000000000 to decimal
985 * buf := "7922816251426433759354395033250000000000000"
986 * decrDecimal := 29
987 * sign := 1
988 * returns (decimal)-7922816251426433759354395033.2
990 * 5. Example:
991 * you want to convert -7922816251426433759354395033.150000000000000 to decimal
992 * buf := "7922816251426433759354395033150000000000000"
993 * decrDecimal := 29
994 * sign := 1
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);
1003 gushort *p;
1004 guint64 alo, ahi;
1005 int n, rc, i, len, sigLen = -1, firstNonZero;
1006 int scale, roundBit = 0;
1008 alo = ahi = 0;
1009 DECINIT(pA);
1011 for (p = buf, len = 0; *p != 0; len++, p++) { }
1013 for (p = buf, i = 0; *p != 0; i++, p++) {
1014 n = *p - '0';
1015 if (n < 0 || n > 9) {
1016 return DECIMAL_INVALID_CHARACTER;
1018 if (n) {
1019 if (sigLen < 0) {
1020 firstNonZero = i;
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) {
1028 return rc;
1033 scale = sigLen - decrDecimal;
1035 if (i < len) { /* too much digits, we must round */
1036 n = buf[i] - '0';
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 */
1042 n = buf[i-1] - '0';
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 */
1048 roundBit = 1;
1053 if (ahi != 0) {
1054 rc = normalize128(&alo, &ahi, &scale, 1, roundBit);
1055 if (rc != DECIMAL_SUCCESS) return rc;
1058 if (alo == 0 && ahi == 0) {
1059 DECINIT(pA);
1060 return DECIMAL_SUCCESS;
1061 } else {
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 !
1071 * Examples:
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
1077 * Parameters:
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)
1092 guint16 tmp[41];
1093 guint16 *buf = (guint16*) mono_array_addr(pArray, guint16, 0);
1094 guint16 *q, *p = tmp;
1095 decimal_repr aa;
1096 guint64 alo, ahi;
1097 guint32 rest;
1098 gint32 sigDigits, d;
1099 int i, scale, len;
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;
1112 } else {
1113 d = sigDigits; /* use all you can get */
1117 if (sigDigits > d) { /* we need to round decimal number */
1118 DECCOPY(&aa, pA);
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;
1125 len = 0;
1126 if (d > 0) {
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;
1133 *p = 0;
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 */
1139 q = buf;
1140 if (digits >= 0) { /* count digits */
1141 if (digits >= bufSize) return DECIMAL_BUFFER_OVERFLOW;
1142 if (len == 0) {
1143 /* zero or rounded to zero */
1144 *pDecPos = 1;
1145 } else {
1146 /* copy significant digits */
1147 for (i = 0; i < len; i++) {
1148 *q++ = *(--p);
1150 *pDecPos = sigDigits - scale;
1152 /* add trailing zeros */
1153 for (i = len; i < digits; i++) {
1154 *q++ = '0';
1156 } else { /* count decimals */
1157 if (scale >= sigDigits) { /* add leading zeros */
1158 if (decimals+2 >= bufSize) return DECIMAL_BUFFER_OVERFLOW;
1159 *pDecPos = 1;
1160 for (i = 0; i <= scale - sigDigits; i++) {
1161 *q++ = '0';
1163 } else {
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++) {
1169 *q++ = *(--p);
1171 /* add trailing zeros */
1172 for (i = scale; i < decimals; i++) {
1173 *q++ = '0';
1176 *q = 0;
1178 *pSign = (sigDigits > 0) ? pA->signscale.sign : 0; /* zero has positive sign */
1180 return DECIMAL_SUCCESS;
1184 * mono_decimal2UInt64:
1185 * @pA
1186 * @pResult
1187 * converts a decimal to an UInt64 without rounding
1189 gint32 mono_decimal2UInt64(/*[In]*/decimal_repr* pA, guint64* pResult)
1191 guint64 alo, ahi;
1192 int scale;
1194 MONO_ARCH_SAVE_REGS;
1196 DECTO128(pA, alo, ahi);
1197 scale = pA->signscale.scale;
1198 if (scale > 0) {
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;
1205 *pResult = alo;
1206 return DECIMAL_SUCCESS;
1210 * mono_decimal2Int64:
1211 * @pA:
1212 * pResult:
1213 * converts a decimal to an Int64 without rounding
1215 gint32 mono_decimal2Int64(/*[In]*/decimal_repr* pA, gint64* pResult)
1217 guint64 alo, ahi;
1218 int sign, scale;
1220 MONO_ARCH_SAVE_REGS;
1222 DECTO128(pA, alo, ahi);
1223 scale = pA->signscale.scale;
1224 if (scale > 0) {
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);
1234 } else {
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)
1244 guint64 alo, ahi;
1245 guint32 factor, rest;
1246 int scale, sign, idx;
1247 int hasRest = 0;
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;
1257 while (scale > 0) {
1258 idx = (scale > DECIMAL_MAX_INTFACTORS) ? DECIMAL_MAX_INTFACTORS : scale;
1259 factor = constantsDecadeInt32Factors[idx];
1260 scale -= 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)
1274 guint64 alo, ahi;
1275 int scale, sign;
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);
1284 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;
1293 guint32 factor;
1294 int scale, sign, rc;
1296 MONO_ARCH_SAVE_REGS;
1298 mult96by96to192(pA->lo32, pA->mid32, pA->hi32, pB->lo32, pB->mid32, pB->hi32,
1299 &low, &mid, &high);
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) {
1308 if (high < 100) {
1309 factor /= 1000; /* we need some digits for final rounding */
1310 scale -= DECIMAL_MAX_INTFACTORS - 3;
1311 } else {
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;
1335 alo = 0;
1336 blo = pB->lo32;
1337 bmi = pB->mid32;
1338 bhi = pB->hi32;
1340 if (blo == 0 && bmi == 0 && bhi == 0) {
1341 return DECIMAL_DIVIDE_BY_ZERO;
1344 if (ami == 0 && ahi == 0) {
1345 *pclo = *pchi = 0;
1346 return DECIMAL_FINISHED;
1349 /* enlarge dividend to get maximal precision */
1350 if (ahi == 0) {
1351 ahi = ami;
1352 ami = 0;
1353 for (ashift = 64; (ahi & LIT_GUINT64_HIGHBIT) == 0; ++ashift) {
1354 ahi <<= 1;
1356 } else {
1357 for (ashift = 0; (ahi & LIT_GUINT64_HIGHBIT) == 0; ++ashift) {
1358 lshift128(&ami, &ahi);
1362 /* ensure that divisor is at least 2^95 */
1363 if (bhi == 0) {
1365 if (bmi == 0) {
1366 guint32 hi_shift;
1367 bhi = blo;
1368 bmi = 0;
1369 blo = 0;
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);
1374 bhi <<= hi_shift;
1375 bshift = 64 + hi_shift;
1376 } else {
1377 bhi = bmi;
1378 bmi = blo;
1379 blo = 0;
1381 for (bshift = 32; (bhi & LIT_GUINT32_HIGHBIT) == 0; ++bshift) {
1382 bhi <<= 1;
1383 bhi |= (bmi & LIT_GUINT32_HIGHBIT) >> 31;
1384 bmi <<= 1;
1387 } else {
1388 for (bshift = 0; (bhi & LIT_GUINT32_HIGHBIT) == 0; ++bshift) {
1389 bhi <<= 1;
1390 bhi |= (bmi & LIT_GUINT32_HIGHBIT) >> 31;
1391 bmi <<= 1;
1392 bmi |= (blo & LIT_GUINT32_HIGHBIT) >> 31;
1393 blo <<= 1;
1397 thi = ((guint64)bhi)<<32 | bmi;
1398 tmi = ((guint64)blo)<<32;
1399 tlo = 0;
1400 if (ahi > thi || (ahi == thi && ami >= tmi)) {
1401 sub192(alo, ami, ahi, tlo, tmi, thi, &alo, &ami, &ahi);
1402 extraBit = 1;
1403 } else {
1404 extraBit = 0;
1407 div192by96to128(alo, ami, ahi, blo, bmi, bhi, pclo, pchi);
1408 texp = 128 + ashift - bshift;
1410 if (extraBit) {
1411 rshift128(pclo, pchi);
1412 *pchi += LIT_GUINT64_HIGHBIT;
1413 texp--;
1416 /* try loss free right shift */
1417 while (texp > 0 && (*pclo & 1) == 0) {
1418 /* right shift */
1419 rshift128(pclo, pchi);
1420 texp--;
1423 *pExp = texp;
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)
1437 /* One */
1438 return pack128toDecimal (pC, 1, 0, 0, 0);
1439 pA->signscale.sign = pA->signscale.sign ? 0 : 1;
1440 if (mono_decimalCompare (pA, pB) == 0)
1441 /* Minus one */
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;
1448 return rc;
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;
1471 return rc;
1474 /* calc scale */
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)
1488 int tlog2;
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;
1499 return tlog2;
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;
1510 decimal_repr aa;
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;
1529 DECCOPY(&aa, pA);
1530 DECNEGATE(&aa);
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;
1545 #ifdef ARM_FPU_FPA
1546 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1548 guint32 temp;
1549 guint32 *t = (guint32*)p;
1550 temp = t [0];
1551 t [0] = t [1];
1552 t [1] = temp;
1554 #endif
1555 #endif
1558 double mono_decimal2double(/*[In]*/decimal_repr* pA)
1560 double d;
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;
1573 texp = 0;
1574 scale = pA->signscale.scale;
1576 /* transform n * 10^-scale and exp = 0 => m * 2^-exp and scale = 0 */
1577 while (scale > 0) {
1578 while ((ahi & LIT_GUINT64_HIGHBIT) == 0) {
1579 lshift128(&alo, &ahi);
1580 texp++;
1583 overhang = (guint32) (ahi >> 32);
1584 if (overhang >= 5) {
1585 /* estimate log5 */
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;
1591 } else {
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);
1598 scale -= i;
1599 texp += i;
1603 /* normalize significand (highest bit should be 1) */
1604 while ((ahi & LIT_GUINT64_HIGHBIT) == 0) {
1605 lshift128(&alo, &ahi);
1606 texp++;
1609 /* round to nearest even */
1610 roundBits = (guint32)ahi & 0x7ff;
1611 ahi += 0x400;
1612 if ((ahi & LIT_GUINT64_HIGHBIT) == 0) { /* overflow ? */
1613 ahi >>= 1;
1614 texp--;
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);
1622 return d;
1625 /* a *= 10^exp */
1626 gint32 mono_decimalSetExponent(/*[In, Out]*/decimal_repr* pA, gint32 texp)
1628 guint64 alo, ahi;
1629 int rc;
1630 int scale = pA->signscale.scale;
1632 MONO_ARCH_SAVE_REGS;
1634 scale -= texp;
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);
1641 } else {
1642 pA->signscale.scale = scale;
1643 return DECIMAL_SUCCESS;
1647 #endif /* DISABLE_DECIMAL */