#include <math.h>
/* 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 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)
/* performs a += b */
gint32 mono_decimalIncr(/*[In, Out]*/decimal_repr* pA, /*[In]*/decimal_repr* pB)
{
- MONO_ARCH_SAVE_REGS;
-
guint64 alo, ahi, blo, bhi;
int log2A, log2B, log2Result, log10Result, rc;
int subFlag, sign, scaleA, scaleB;
+ MONO_ARCH_SAVE_REGS;
+
DECTO128(pA, alo, ahi);
DECTO128(pB, blo, bhi);
gint32 mono_decimal2string(/*[In]*/decimal_repr* pA, gint32 digits, gint32 decimals,
MonoArray* pArray, gint32 bufSize, gint32* pDecPos, gint32* pSign)
{
- MONO_ARCH_SAVE_REGS;
-
guint16 tmp[41];
guint16 *buf = (guint16*) mono_array_addr(pArray, guint16, 0);
guint16 *q, *p = tmp;
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 */
*/
gint32 mono_decimal2UInt64(/*[In]*/decimal_repr* pA, guint64* pResult)
{
- MONO_ARCH_SAVE_REGS;
-
guint64 alo, ahi;
int scale;
+ MONO_ARCH_SAVE_REGS;
+
DECTO128(pA, alo, ahi);
scale = pA->signscale.scale;
if (scale > 0) {
*/
gint32 mono_decimal2Int64(/*[In]*/decimal_repr* pA, gint64* pResult)
{
- MONO_ARCH_SAVE_REGS;
-
guint64 alo, ahi;
int sign, scale;
+ MONO_ARCH_SAVE_REGS;
+
DECTO128(pA, alo, ahi);
scale = pA->signscale.scale;
if (scale > 0) {
void mono_decimalFloorAndTrunc(/*[In, Out]*/decimal_repr* pA, gint32 floorFlag)
{
- MONO_ARCH_SAVE_REGS;
-
guint64 alo, ahi;
guint32 factor, rest;
int scale, sign, idx;
int hasRest = 0;
+ MONO_ARCH_SAVE_REGS;
+
scale = pA->signscale.scale;
if (scale == 0) return; /* nothing to do */
void mono_decimalRound(/*[In, Out]*/decimal_repr* pA, gint32 decimals)
{
- MONO_ARCH_SAVE_REGS;
-
guint64 alo, ahi;
int scale, sign;
+ MONO_ARCH_SAVE_REGS;
+
DECTO128(pA, alo, ahi);
scale = pA->signscale.scale;
sign = pA->signscale.sign;
gint32 mono_decimalMult(/*[In, Out]*/decimal_repr* pA, /*[In]*/decimal_repr* pB)
{
- MONO_ARCH_SAVE_REGS;
-
guint64 low, mid, high;
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);
gint32 mono_decimalDiv(/*[Out]*/decimal_repr* pC, /*[In]*/decimal_repr* pA, /*[In]*/decimal_repr* pB)
{
- MONO_ARCH_SAVE_REGS;
-
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;
gint32 mono_decimalIntDiv(/*[Out]*/decimal_repr* pC, /*[In]*/decimal_repr* pA, /*[In]*/decimal_repr* pB)
{
- MONO_ARCH_SAVE_REGS;
-
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;
gint32 mono_decimalCompare(/*[In]*/decimal_repr* pA, /*[In]*/decimal_repr* pB)
{
- MONO_ARCH_SAVE_REGS;
-
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) {
double mono_decimal2double(/*[In]*/decimal_repr* pA)
{
- MONO_ARCH_SAVE_REGS;
-
double d;
guint64 alo, ahi, mantisse;
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 */
/* a *= 10^exp */
gint32 mono_decimalSetExponent(/*[In, Out]*/decimal_repr* pA, gint32 texp)
{
- MONO_ARCH_SAVE_REGS;
-
guint64 alo, ahi;
int rc;
int scale = pA->signscale.scale;
+ MONO_ARCH_SAVE_REGS;
+
scale -= texp;
if (scale < 0 || scale > DECIMAL_MAX_SCALE) {