- We need to invalidate the selection area when we replace the
[mono-project.git] / mono / metadata / decimal.c
blob626a8d91e3d27f00d2223d3df711b4b663b458ef
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 <memory.h>
20 #include <stdlib.h>
21 #include <string.h>
22 #include <math.h>
24 #ifndef DISABLE_DECIMAL
26 /* needed for building microsoft dll */
27 #ifdef __GNUC__
28 #define DECINLINE __inline
29 #else
30 #define DECINLINE
31 #endif
33 #define LIT_GUINT32(x) x
34 #define LIT_GUINT64(x) x##LL
37 /* we need a UInt64 type => guint64 */
38 #include <glib.h>
40 #include "decimal.h"
43 * Deal with anon union support.
45 #define ss32 u.ss32
46 #define signscale u.signscale
48 /* debugging stuff */
49 #ifdef _DEBUG
50 #include <assert.h>
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);
56 #else
57 #define PRECONDITION(flag)
58 #define POSTCONDITION(flag)
59 #define TEST(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
75 /* some MACROS */
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; \
92 hi = (pd)->hi32;
94 /* some constants */
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)
106 typedef struct {
107 guint64 lo;
108 guint64 hi;
109 } dec128_repr;
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)
149 alo += blo;
150 if (alo < blo) ahi++; /* carry */
151 ahi += bhi;
153 *pclo = alo;
154 *pchi = ahi;
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)
163 guint64 clo, chi;
165 clo = alo - blo;
166 chi = ahi - bhi;
167 if (alo < blo) chi--; /* borrow */
169 *pclo = clo;
170 *pchi = chi;
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)
179 alo += blo;
180 if (alo < blo) { /* carry low */
181 ami++;
182 if (ami == 0) ahi++; /* carry mid */
184 ami += bmi;
185 if (ami < bmi) ahi++; /* carry mid */
186 ahi += bhi;
187 *pclo = alo;
188 *pcmi = ami;
189 *pchi = ahi;
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;
200 clo = alo - blo;
201 cmi = ami - bmi;
202 chi = ahi - bhi;
203 if (alo < blo) {
204 if (cmi == 0) chi--; /* borrow mid */
205 cmi--; /* borrow low */
207 if (ami < bmi) chi--; /* borrow mid */
208 *pclo = clo;
209 *pcmi = cmi;
210 *pchi = chi;
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)
218 guint64 a, b, c, d;
219 guint32 h0, h1, h2, h3, h4, h5;
220 int carry0, carry1;
222 a = ((guint64)alo) * blo;
223 h0 = (guint32) a;
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++;
230 h1 = (guint32) a;
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++;
239 h2 = (guint32) a;
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++;
246 h3 = (guint32) a;
248 a >>= 32; a += carry1;
249 b = ((guint64)ahi) * bhi;
250 a += b;
251 h4 = (guint32) a;
253 a >>= 32; a += carry0;
254 h5 = (guint32) a;
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,
263 guint32 factor,
264 guint64* pclo, guint64* pchi)
266 guint64 a;
267 guint32 h0, h1;
269 a = ((guint64)alo) * factor;
270 h0 = (guint32) a;
272 a >>= 32;
273 a += ((guint64)ami) * factor;
274 h1 = (guint32) a;
276 a >>= 32;
277 a += ((guint64)ahi) * factor;
279 *pclo = ((guint64)h1) << 32 | h0;
280 *pchi = a;
283 /* multiplication c(128bit) *= b(32bit) */
284 DECINLINE static int mult128by32(guint64* pclo, guint64* pchi, guint32 factor, int roundBit)
286 guint64 a;
287 guint32 h0, h1;
289 a = ((guint64)(guint32)(*pclo)) * factor;
290 if (roundBit) a += factor / 2;
291 h0 = (guint32) a;
293 a >>= 32;
294 a += (*pclo >> 32) * factor;
295 h1 = (guint32) a;
297 *pclo = ((guint64)h1) << 32 | h0;
299 a >>= 32;
300 a += ((guint64)(guint32)(*pchi)) * factor;
301 h0 = (guint32) a;
303 a >>= 32;
304 a += (*pchi >> 32) * factor;
305 h1 = (guint32) a;
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)
314 int idx, rc;
316 while (powerOfTen > 0) {
317 idx = (powerOfTen >= DECIMAL_MAX_INTFACTORS) ? DECIMAL_MAX_INTFACTORS : powerOfTen;
318 powerOfTen -= idx;
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)
326 returns roundBit */
327 DECINLINE static int div128by32(guint64* plo, guint64* phi, guint32 factor, guint32* pRest)
329 guint64 a, b, c, h;
331 h = *phi;
332 a = (guint32)(h >> 32);
333 b = a / factor;
334 a -= b * factor;
335 a <<= 32;
336 a |= (guint32) h;
337 c = a / factor;
338 a -= c * factor;
339 a <<= 32;
340 *phi = b << 32 | (guint32)c;
342 h = *plo;
343 a |= (guint32)(h >> 32);
344 b = a / factor;
345 a -= b * factor;
346 a <<= 32;
347 a |= (guint32) h;
348 c = a / factor;
349 a -= c * factor;
350 *plo = b << 32 | (guint32)c;
352 if (pRest) *pRest = (guint32) a;
354 a <<= 1;
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,
361 guint32 factor)
363 guint64 a, b, c, h;
365 h = *phi;
366 a = (guint32)(h >> 32);
367 b = a / factor;
368 a -= b * factor;
369 a <<= 32;
370 a |= (guint32) h;
371 c = a / factor;
372 a -= c * factor;
373 a <<= 32;
374 *phi = b << 32 | (guint32)c;
376 h = *pmi;
377 a |= (guint32)(h >> 32);
378 b = a / factor;
379 a -= b * factor;
380 a <<= 32;
381 a |= (guint32) h;
382 c = a / factor;
383 a -= c * factor;
384 a <<= 32;
385 *pmi = b << 32 | (guint32)c;
387 h = *plo;
388 a |= (guint32)(h >> 32);
389 b = a / factor;
390 a -= b * factor;
391 a <<= 32;
392 a |= (guint32) h;
393 c = a / factor;
394 a -= c * factor;
395 a <<= 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 */
406 guint32 c;
408 rlo = *palo; rmi = *pami; rhi = *pahi;
409 if (rhi >= (((guint64)bhi) << 32)) {
410 c = LIT_GUINT32(0xFFFFFFFF);
411 } else {
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) {
417 c--;
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);
424 return c;
427 /* c(128bit) = a(192bit) / b(96bit)
428 b must be >= 2^95 */
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 */
434 guint32 h, c;
436 PRECONDITION(ahi < (((guint64)bhi) << 32 | bmi)
437 || (ahi == (((guint64)bhi) << 32 | bmi) && (ami >> 32) > blo));
439 /* high 32 bit*/
440 rlo = alo; rmi = ami; rhi = ahi;
441 h = div192by96to32withRest(&rlo, &rmi, &rhi, blo, bmi, bhi);
443 /* mid 32 bit*/
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);
447 /* low 32 bit */
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) */
452 if (rhi >= bhi) {
453 c = LIT_GUINT32(0xFFFFFFFF);
454 } else {
455 rhi <<= 32;
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);
469 int scale = *pScale;
470 int deltaScale;
472 while (overhang != 0) {
473 for (deltaScale = 1; deltaScale < DECIMAL_MAX_INTFACTORS; deltaScale++)
475 if (overhang < constantsDecadeInt32Factors[deltaScale]) break;
478 scale -= deltaScale;
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) {
485 overhang = 1;
489 *pScale = scale;
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;
503 int shift;
505 for (shift = 0; ((gint32)hi32) >= 0 && shift < 96; shift++) {
506 hi32 <<= 1;
507 if (((gint64)lo64) < 0) hi32++;
508 lo64 <<= 1;
511 pA->lo32 = (guint32) lo64;
512 pA->mid32 = (guint32)(lo64>>32);
513 pA->hi32 = hi32;
515 return shift;
518 DECINLINE static void rshift128(guint64* pclo, guint64* pchi)
520 *pclo >>= 1;
521 if (*pchi & 1) *pclo |= LIT_GUINT64_HIGHBIT;
522 *pchi >>= 1;
525 DECINLINE static void lshift96(guint32* pclo, guint32* pcmid, guint32* pchi)
527 *pchi <<= 1;
528 if (*pcmid & LIT_GUINT32_HIGHBIT) (*pchi)++;
529 *pcmid <<= 1;
530 if (*pclo & LIT_GUINT32_HIGHBIT) (*pcmid)++;
531 *pclo <<= 1;
534 DECINLINE static void lshift128(guint64* pclo, guint64* pchi)
536 *pchi <<= 1;
537 if (*pclo & LIT_GUINT64_HIGHBIT) (*pchi)++;
538 *pclo <<= 1;
541 DECINLINE static void rshift192(guint64* pclo, guint64* pcmi, guint64* pchi)
543 *pclo >>= 1;
544 if (*pcmi & 1) *pclo |= LIT_GUINT64_HIGHBIT;
545 *pcmi >>= 1;
546 if (*pchi & 1) *pcmi |= LIT_GUINT64_HIGHBIT;
547 *pchi >>= 1;
550 /* returns log2(a) or DECIMAL_LOG_NEGINF for a = 0 */
551 DECINLINE static int log2_32(guint32 a)
553 int tlog2 = 0;
555 if (a == 0) return DECIMAL_LOG_NEGINF;
557 if ((a >> 16) != 0) {
558 a >>= 16;
559 tlog2 += 16;
561 if ((a >> 8) != 0) {
562 a >>= 8;
563 tlog2 += 8;
565 if ((a >> 4) != 0) {
566 a >>= 4;
567 tlog2 += 4;
569 if ((a >> 2) != 0) {
570 a >>= 2;
571 tlog2 += 2;
573 if ((a >> 1) != 0) {
574 a >>= 1;
575 tlog2 += 1;
577 tlog2 += (int) a;
579 return tlog2;
582 /* returns log2(a) or DECIMAL_LOG_NEGINF for a = 0 */
583 DECINLINE static int log2_64(guint64 a)
585 int tlog2 = 0;
587 if (a == 0) return DECIMAL_LOG_NEGINF;
589 if ((a >> 32) != 0) {
590 a >>= 32;
591 tlog2 += 32;
593 if ((a >> 16) != 0) {
594 a >>= 16;
595 tlog2 += 16;
597 if ((a >> 8) != 0) {
598 a >>= 8;
599 tlog2 += 8;
601 if ((a >> 4) != 0) {
602 a >>= 4;
603 tlog2 += 4;
605 if ((a >> 2) != 0) {
606 a >>= 2;
607 tlog2 += 2;
609 if ((a >> 1) != 0) {
610 a >>= 1;
611 tlog2 += 1;
613 tlog2 += (int) a;
615 return tlog2;
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,
634 int scale, int sign)
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)
655 int idx, rc;
657 if (deltaScale < 0) {
658 deltaScale *= -1;
659 if (deltaScale > DECIMAL_MAX_SCALE) return DECIMAL_INTERNAL_ERROR;
660 while (deltaScale > 0) {
661 idx = (deltaScale > DECIMAL_MAX_INTFACTORS) ? DECIMAL_MAX_INTFACTORS : deltaScale;
662 deltaScale -= idx;
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;
669 deltaScale -= idx;
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);
689 scale = *pScale;
691 if (texp > 0) {
692 /* reduce exp */
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;
702 else i = texp;
703 if (scale + i > maxScale) i = maxScale - scale;
704 if (i == 0) break;
705 texp -= i;
706 scale += i;
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));*/
712 while (texp > 0) {
713 if (--texp == 0) roundBit = (int)(*pclo & 1);
714 rshift128(pclo, pchi);
718 TEST(texp == 0);
720 while (scale > maxScale) {
721 i = scale - maxScale;
722 if (i > DECIMAL_MAX_INTFACTORS) i = DECIMAL_MAX_INTFACTORS;
723 scale -= i;
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;
731 scale += i;
732 rc = mult128by32(pclo, pchi, constantsDecadeInt32Factors[i], roundBit);
733 if (rc != DECIMAL_SUCCESS) return rc;
734 roundBit = 0;
737 TEST(scale >= 0 && scale <= DECIMAL_MAX_SCALE);
739 *pScale = 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;
751 MONO_ARCH_SAVE_REGS;
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 */
762 if (subFlag) {
763 sub128(alo, ahi, blo, bhi, &alo, &ahi);
764 if (ahi & LIT_GUINT64_HIGHBIT) {
765 alo--;
766 alo = ~alo;
767 if (alo == 0) ahi--;
768 ahi = ~ahi;
769 sign = !sign;
771 } else {
772 add128(alo, ahi, blo, bhi, &alo, &ahi);
774 rc = normalize128(&alo, &ahi, &scaleA, 1, 0);
775 } else {
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;
795 if (subFlag) {
796 sub128(alo, ahi, blo, bhi, &alo, &ahi);
797 if (ahi & LIT_GUINT64_HIGHBIT) {
798 alo--;
799 alo = ~alo;
800 if (alo == 0) ahi--;
801 ahi = ~ahi;
802 sign = !sign;
804 } else {
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)
819 guint64 blo, bhi, h;
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;
826 if (factor != 1) {
827 mult128by32(&blo, &bhi, factor, 0);
828 if (h > bhi) return DECIMAL_OVERFLOW;
830 h = *pahi;
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;
842 powerOfTen -= idx;
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)
852 int tlog2 = 0;
853 int tlog10;
855 if (ahi == 0) {
856 if (alo == 0) {
857 return 0; /* zero has no signficant digits */
858 } else {
859 tlog2 = log2_64(alo);
861 } else {
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)) {
870 --tlog10;
872 return tlog10+1;
875 gint32 mono_double2decimal(/*[Out]*/decimal_repr* pA, double val, gint32 digits)
877 guint64 alo, ahi;
878 guint64* p = (guint64*)(&val);
879 int sigDigits, sign, texp, rc, scale;
880 guint16 k;
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);
887 ahi = 0;
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;
896 texp -= 52;
897 if (texp > 0) {
898 for (; texp > 0; texp--) {
899 lshift128(&alo, &ahi);
903 scale = 0;
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);
916 scale--;
918 if (scale < 0) {
919 rc = mult128DecadeFactor(&alo, &ahi, -scale);
920 if (rc != DECIMAL_SUCCESS) return rc;
921 scale = 0;
925 return pack128toDecimal(pA, alo, ahi, scale, sign);
929 * mono_string2decimal:
930 * @decimal_repr:
931 * @str:
932 * @decrDecimal:
933 * @sign:
935 * converts a digit string to decimal
936 * The significant digits must be passed as an integer in buf !
938 * 1. Example:
939 * if you want to convert the number 123.456789012345678901234 to decimal
940 * buf := "123456789012345678901234"
941 * decrDecimal := 3
942 * sign := 0
944 * 2. Example:
945 * you want to convert -79228162514264337593543950335 to decimal
946 * buf := "79228162514264337593543950335"
947 * decrDecimal := 29
948 * sign := 1
950 * 3. Example:
951 * you want to convert -7922816251426433759354395033.250000000000001 to decimal
952 * buf := "7922816251426433759354395033250000000000001"
953 * decrDecimal := 29
954 * sign := 1
955 * returns (decimal)-7922816251426433759354395033.3
957 * 4. Example:
958 * you want to convert -7922816251426433759354395033.250000000000000 to decimal
959 * buf := "7922816251426433759354395033250000000000000"
960 * decrDecimal := 29
961 * sign := 1
962 * returns (decimal)-7922816251426433759354395033.2
964 * 5. Example:
965 * you want to convert -7922816251426433759354395033.150000000000000 to decimal
966 * buf := "7922816251426433759354395033150000000000000"
967 * decrDecimal := 29
968 * sign := 1
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);
977 gushort *p;
978 guint64 alo, ahi;
979 int n, rc, i, len, sigLen = -1, firstNonZero;
980 int scale, roundBit = 0;
982 alo = ahi = 0;
983 DECINIT(pA);
985 for (p = buf, len = 0; *p != 0; len++, p++) { }
987 for (p = buf, i = 0; *p != 0; i++, p++) {
988 n = *p - '0';
989 if (n < 0 || n > 9) {
990 return DECIMAL_INVALID_CHARACTER;
992 if (n) {
993 if (sigLen < 0) {
994 firstNonZero = i;
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) {
1002 return rc;
1007 scale = sigLen - decrDecimal;
1009 if (i < len) { /* too much digits, we must round */
1010 n = buf[i] - '0';
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 */
1016 n = buf[i-1] - '0';
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 */
1022 roundBit = 1;
1027 if (ahi != 0) {
1028 rc = normalize128(&alo, &ahi, &scale, 1, roundBit);
1029 if (rc != DECIMAL_SUCCESS) return rc;
1032 if (alo == 0 && ahi == 0) {
1033 DECINIT(pA);
1034 return DECIMAL_SUCCESS;
1035 } else {
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 !
1045 * Examples:
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
1051 * Parameters:
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)
1066 guint16 tmp[41];
1067 guint16 *buf = (guint16*) mono_array_addr(pArray, guint16, 0);
1068 guint16 *q, *p = tmp;
1069 decimal_repr aa;
1070 guint64 alo, ahi;
1071 guint32 rest;
1072 gint32 sigDigits, d;
1073 int i, scale, len;
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;
1086 } else {
1087 d = sigDigits; /* use all you can get */
1091 if (sigDigits > d) { /* we need to round decimal number */
1092 DECCOPY(&aa, pA);
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;
1099 len = 0;
1100 if (d > 0) {
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;
1107 *p = 0;
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 */
1113 q = buf;
1114 if (digits >= 0) { /* count digits */
1115 if (digits >= bufSize) return DECIMAL_BUFFER_OVERFLOW;
1116 if (len == 0) {
1117 /* zero or rounded to zero */
1118 *pDecPos = 1;
1119 } else {
1120 /* copy significant digits */
1121 for (i = 0; i < len; i++) {
1122 *q++ = *(--p);
1124 *pDecPos = sigDigits - scale;
1126 /* add trailing zeros */
1127 for (i = len; i < digits; i++) {
1128 *q++ = '0';
1130 } else { /* count decimals */
1131 if (scale >= sigDigits) { /* add leading zeros */
1132 if (decimals+2 >= bufSize) return DECIMAL_BUFFER_OVERFLOW;
1133 *pDecPos = 1;
1134 for (i = 0; i <= scale - sigDigits; i++) {
1135 *q++ = '0';
1137 } else {
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++) {
1143 *q++ = *(--p);
1145 /* add trailing zeros */
1146 for (i = scale; i < decimals; i++) {
1147 *q++ = '0';
1150 *q = 0;
1152 *pSign = (sigDigits > 0) ? pA->signscale.sign : 0; /* zero has positive sign */
1154 return DECIMAL_SUCCESS;
1158 * mono_decimal2UInt64:
1159 * @pA
1160 * @pResult
1161 * converts a decimal to an UInt64 without rounding
1163 gint32 mono_decimal2UInt64(/*[In]*/decimal_repr* pA, guint64* pResult)
1165 guint64 alo, ahi;
1166 int scale;
1168 MONO_ARCH_SAVE_REGS;
1170 DECTO128(pA, alo, ahi);
1171 scale = pA->signscale.scale;
1172 if (scale > 0) {
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;
1179 *pResult = alo;
1180 return DECIMAL_SUCCESS;
1184 * mono_decimal2Int64:
1185 * @pA:
1186 * pResult:
1187 * converts a decimal to an Int64 without rounding
1189 gint32 mono_decimal2Int64(/*[In]*/decimal_repr* pA, gint64* pResult)
1191 guint64 alo, ahi;
1192 int sign, 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 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);
1208 } else {
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)
1218 guint64 alo, ahi;
1219 guint32 factor, rest;
1220 int scale, sign, idx;
1221 int hasRest = 0;
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;
1231 while (scale > 0) {
1232 idx = (scale > DECIMAL_MAX_INTFACTORS) ? DECIMAL_MAX_INTFACTORS : scale;
1233 factor = constantsDecadeInt32Factors[idx];
1234 scale -= 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)
1248 guint64 alo, ahi;
1249 int scale, sign;
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);
1258 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;
1267 guint32 factor;
1268 int scale, sign, rc;
1270 MONO_ARCH_SAVE_REGS;
1272 mult96by96to192(pA->lo32, pA->mid32, pA->hi32, pB->lo32, pB->mid32, pB->hi32,
1273 &low, &mid, &high);
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) {
1282 if (high < 100) {
1283 factor /= 1000; /* we need some digits for final rounding */
1284 scale -= DECIMAL_MAX_INTFACTORS - 3;
1285 } else {
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;
1309 alo = 0;
1310 blo = pB->lo32;
1311 bmi = pB->mid32;
1312 bhi = pB->hi32;
1314 if (blo == 0 && bmi == 0 && bhi == 0) {
1315 return DECIMAL_DIVIDE_BY_ZERO;
1318 if (ami == 0 && ahi == 0) {
1319 *pclo = *pchi = 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;
1335 tlo = 0;
1336 if (ahi > thi || (ahi == thi && ami >= tmi)) {
1337 sub192(alo, ami, ahi, tlo, tmi, thi, &alo, &ami, &ahi);
1338 extraBit = 1;
1339 } else {
1340 extraBit = 0;
1343 div192by96to128(alo, ami, ahi, blo, bmi, bhi, pclo, pchi);
1344 texp = 128 + ashift - bshift;
1346 if (extraBit) {
1347 rshift128(pclo, pchi);
1348 *pchi += LIT_GUINT64_HIGHBIT;
1349 texp--;
1352 /* try loss free right shift */
1353 while (texp > 0 && (*pclo & 1) == 0) {
1354 /* right shift */
1355 rshift128(pclo, pchi);
1356 texp--;
1359 *pExp = texp;
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;
1374 return rc;
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;
1397 return rc;
1400 /* calc scale */
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)
1414 int tlog2;
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;
1425 return tlog2;
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;
1436 decimal_repr aa;
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;
1455 DECCOPY(&aa, pA);
1456 DECNEGATE(&aa);
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;
1471 #ifdef ARM_FPU_FPA
1472 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1474 guint32 temp;
1475 guint32 *t = (guint32*)p;
1476 temp = t [0];
1477 t [0] = t [1];
1478 t [1] = temp;
1480 #endif
1481 #endif
1484 double mono_decimal2double(/*[In]*/decimal_repr* pA)
1486 double d;
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;
1499 texp = 0;
1500 scale = pA->signscale.scale;
1502 /* transform n * 10^-scale and exp = 0 => m * 2^-exp and scale = 0 */
1503 while (scale > 0) {
1504 while ((ahi & LIT_GUINT64_HIGHBIT) == 0) {
1505 lshift128(&alo, &ahi);
1506 texp++;
1509 overhang = (guint32) (ahi >> 32);
1510 if (overhang >= 5) {
1511 /* estimate log5 */
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;
1517 } else {
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);
1524 scale -= i;
1525 texp += i;
1529 /* normalize significand (highest bit should be 1) */
1530 while ((ahi & LIT_GUINT64_HIGHBIT) == 0) {
1531 lshift128(&alo, &ahi);
1532 texp++;
1535 /* round to nearest even */
1536 roundBits = (guint32)ahi & 0x7ff;
1537 ahi += 0x400;
1538 if ((ahi & LIT_GUINT64_HIGHBIT) == 0) { /* overflow ? */
1539 ahi >>= 1;
1540 texp--;
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);
1548 return d;
1551 /* a *= 10^exp */
1552 gint32 mono_decimalSetExponent(/*[In, Out]*/decimal_repr* pA, gint32 texp)
1554 guint64 alo, ahi;
1555 int rc;
1556 int scale = pA->signscale.scale;
1558 MONO_ARCH_SAVE_REGS;
1560 scale -= texp;
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);
1567 } else {
1568 pA->signscale.scale = scale;
1569 return DECIMAL_SUCCESS;
1573 #endif /* DISABLE_DECIMAL */