* CSharp value type System.Decimal
*/
+#include "config.h"
+#include <mono/metadata/exception.h>
#include <stdio.h>
#include <memory.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
+#ifndef DISABLE_DECIMAL
+
/* needed for building microsoft dll */
+#ifdef __GNUC__
#define DECINLINE __inline
+#else
+#define DECINLINE
+#endif
#define LIT_GUINT32(x) x
-#define LIT_GUINT64(x) x##L
+#define LIT_GUINT64(x) x##LL
/* we need a UInt64 type => guint64 */
#define POSTCONDITION(flag)
#define TEST(flag)
#define INVARIANT_TEST(p)
-#endif //#ifdef _DEBUG
+#endif /*#ifdef _DEBUG*/
#define DECIMAL_MAX_SCALE 28
#define DECIMAL_MAX_INTFACTORS 9
#define DECIMAL_LOG_NEGINF -1000
-static guint32 constantsDecadeInt32Factors[DECIMAL_MAX_INTFACTORS+1] = {
+static const guint32 constantsDecadeInt32Factors[DECIMAL_MAX_INTFACTORS+1] = {
LIT_GUINT32(1), LIT_GUINT32(10), LIT_GUINT32(100), LIT_GUINT32(1000),
LIT_GUINT32(10000), LIT_GUINT32(100000), LIT_GUINT32(1000000),
LIT_GUINT32(10000000), LIT_GUINT32(100000000), LIT_GUINT32(1000000000)
guint64 hi;
} dec128_repr;
-static dec128_repr dec128decadeFactors[DECIMAL_MAX_SCALE+1] = {
+static const dec128_repr dec128decadeFactors[DECIMAL_MAX_SCALE+1] = {
LIT_DEC128( 0, 0, 1u), /* == 1 */
LIT_DEC128( 0, 0, 10u), /* == 10 */
LIT_DEC128( 0, 0, 100u), /* == 100 */
if (pRest) *pRest = (guint32) a;
a <<= 1;
- return (a > factor || (a == factor && (c & 1) == 1)) ? 1 : 0;
+ return (a >= factor || (a == factor && (c & 1) == 1)) ? 1 : 0;
}
/* division: x(192bit) /= factor(32bit)
scale += i;
factor = constantsDecadeInt32Factors[i] >> i; /* 10^i/2^i=5^i */
mult128by32(pclo, pchi, factor, 0);
- //printf("3: %.17e\n", (((double)chi) * pow(2,64) + clo) * pow(10, -scale) * pow(2, -texp));
+ /*printf("3: %.17e\n", (((double)chi) * pow(2,64) + clo) * pow(10, -scale) * pow(2, -texp));*/
}
while (texp > 0) {
int log2A, log2B, log2Result, log10Result, rc;
int subFlag, sign, scaleA, scaleB;
+ MONO_ARCH_SAVE_REGS;
+
DECTO128(pA, alo, ahi);
DECTO128(pB, blo, bhi);
return pack128toDecimal(pA, alo, ahi, scale, sign);
}
-/**
+/**
+ * mono_string2decimal:
+ * @decimal_repr:
+ * @str:
+ * @decrDecimal:
+ * @sign:
+ *
* converts a digit string to decimal
* The significant digits must be passed as an integer in buf !
*
}
/**
+ * mono_decimal2string:
+ * @
* returns minimal number of digit string to represent decimal
* No leading or trailing zeros !
* Examples:
- * *pA == 0 => buf = "", *pDecPos = 0, *pSign = 0
+ * *pA == 0 => buf = "", *pDecPos = 1, *pSign = 0
* *pA == 12.34 => buf = "1234", *pDecPos = 2, *pSign = 0
* *pA == -1000.0000 => buf = "1", *pDecPos = 4, *pSign = 1
* *pA == -0.00000076 => buf = "76", *pDecPos = -6, *pSign = 0
* pDecPos receives insert position of decimal point relative to start of buffer
* pSign receives sign
*/
-
gint32 mono_decimal2string(/*[In]*/decimal_repr* pA, gint32 digits, gint32 decimals,
MonoArray* pArray, gint32 bufSize, gint32* pDecPos, gint32* pSign)
{
gint32 sigDigits, d;
int i, scale, len;
+ MONO_ARCH_SAVE_REGS;
+
scale = pA->signscale.scale;
DECTO128(pA, alo, ahi);
sigDigits = calcDigits(alo, ahi); /* significant digits */
}
/**
+ * mono_decimal2UInt64:
+ * @pA
+ * @pResult
* converts a decimal to an UInt64 without rounding
*/
gint32 mono_decimal2UInt64(/*[In]*/decimal_repr* pA, guint64* pResult)
guint64 alo, ahi;
int scale;
+ MONO_ARCH_SAVE_REGS;
+
DECTO128(pA, alo, ahi);
scale = pA->signscale.scale;
if (scale > 0) {
}
/**
+ * mono_decimal2Int64:
+ * @pA:
+ * pResult:
* converts a decimal to an Int64 without rounding
*/
gint32 mono_decimal2Int64(/*[In]*/decimal_repr* pA, gint64* pResult)
guint64 alo, ahi;
int sign, scale;
+ MONO_ARCH_SAVE_REGS;
+
DECTO128(pA, alo, ahi);
scale = pA->signscale.scale;
if (scale > 0) {
int scale, sign, idx;
int hasRest = 0;
+ MONO_ARCH_SAVE_REGS;
+
scale = pA->signscale.scale;
if (scale == 0) return; /* nothing to do */
guint64 alo, ahi;
int scale, sign;
+ MONO_ARCH_SAVE_REGS;
+
DECTO128(pA, alo, ahi);
scale = pA->signscale.scale;
sign = pA->signscale.sign;
guint32 factor;
int scale, sign, rc;
+ MONO_ARCH_SAVE_REGS;
+
mult96by96to192(pA->lo32, pA->mid32, pA->hi32, pB->lo32, pB->mid32, pB->hi32,
&low, &mid, &high);
guint64 clo, chi; /* result */
int scale, texp, rc;
+ MONO_ARCH_SAVE_REGS;
+
rc = decimalDivSub(pA, pB, &clo, &chi, &texp);
if (rc != DECIMAL_SUCCESS) {
if (rc == DECIMAL_FINISHED) rc = DECIMAL_SUCCESS;
/* adjust scale and sign */
scale = (int)pA->signscale.scale - (int)pB->signscale.scale;
- //test: printf("0: %.17e\n", (((double)chi) * pow(2,64) + clo) * pow(10, -scale) * pow(2, -exp));
+ /*test: printf("0: %.17e\n", (((double)chi) * pow(2,64) + clo) * pow(10, -scale) * pow(2, -exp));*/
rc = rescale128(&clo, &chi, &scale, texp, 0, DECIMAL_MAX_SCALE, 1);
if (rc != DECIMAL_SUCCESS) return rc;
guint64 clo, chi; /* result */
int scale, texp, rc;
+ MONO_ARCH_SAVE_REGS;
+
rc = decimalDivSub(pA, pB, &clo, &chi, &texp);
if (rc != DECIMAL_SUCCESS) {
if (rc == DECIMAL_FINISHED) rc = DECIMAL_SUCCESS;
int log2a, log2b, delta, sign;
decimal_repr aa;
+ MONO_ARCH_SAVE_REGS;
+
sign = (pA->signscale.sign) ? -1 : 1;
if (pA->signscale.sign ^ pB->signscale.sign) {
PRECONDITION(sign == 0 || sign == 1);
*p = (((guint64)sign) << 63) | (((guint64)((1023+texp)&0x7ff)) << 52) | mantisse;
+#ifdef ARM_FPU_FPA
+#if G_BYTE_ORDER == G_LITTLE_ENDIAN
+ {
+ guint32 temp;
+ guint32 *t = (guint32*)p;
+ temp = t [0];
+ t [0] = t [1];
+ t [1] = temp;
+ }
+#endif
+#endif
}
double mono_decimal2double(/*[In]*/decimal_repr* pA)
guint32 overhang, factor, roundBits;
int scale, texp, log5, i;
+ MONO_ARCH_SAVE_REGS;
+
ahi = (((guint64)(pA->hi32)) << 32) | pA->mid32;
alo = ((guint64)(pA->lo32)) << 32;
ahi += 0x400;
if ((ahi & LIT_GUINT64_HIGHBIT) == 0) { /* overflow ? */
ahi >>= 1;
- texp++;
+ texp--;
} else if ((roundBits & 0x400) == 0) ahi &= ~1;
/* 96 bit => 1 implizit bit and 52 explicit bits */
int rc;
int scale = pA->signscale.scale;
+ MONO_ARCH_SAVE_REGS;
+
scale -= texp;
if (scale < 0 || scale > DECIMAL_MAX_SCALE) {
return DECIMAL_SUCCESS;
}
}
+
+#endif /* DISABLE_DECIMAL */
+