/*
- decimal.c
-
- conversions and numerical operations for the c# type System.Decimal
-
- Author: Martin Weindel (martin.weindel@t-online.de)
-
- (C) 2001 by Martin Weindel
-*/
+ * decimal.c
+ *
+ * conversions and numerical operations for the c# type System.Decimal
+ *
+ * Author: Martin Weindel (martin.weindel@t-online.de)
+ *
+ * (C) 2001 by Martin Weindel
+ */
/*
* machine dependent configuration for
#ifdef HAVE_MEMORY_H
#include <memory.h>
#endif
+#ifdef _MSC_VER
+#include <intrin.h>
+#endif
#ifndef DISABLE_DECIMAL
__asm__("bsrq %1,%0\n\t"
: "=r" (r) : "rm" (mask));
return r;
+#elif defined(__i386__) && defined(_MSC_VER)
+ unsigned long bIndex = 0;
+ if (_BitScanReverse (&bIndex, mask))
+ return bIndex;
+ return -1;
+#elif defined(__x86_64__) && defined(_MSC_VER)
+ unsigned long bIndex = 0;
+ if (_BitScanReverse64 (&bIndex, mask))
+ return bIndex;
+ return -1;
#else
- return g_bit_nth_msf (mask, sizeof (gsize) * 8);
+ int i;
+
+ i = sizeof (gsize) * 8;
+ while (i > 0) {
+ i --;
+ if (mask & (1UL << i))
+ return i;
+ }
+ return -1;
#endif
}
DECINLINE static int rescale128(guint64* pclo, guint64* pchi, int* pScale, int texp,
int minScale, int maxScale, int roundFlag)
{
- guint32 factor, overhang, prev_lo;
+ guint32 factor, overhang;
int scale, i, rc, roundBit = 0;
PRECONDITION(texp >= 0);
/* reduce exp */
while (texp > 0 && scale <= maxScale) {
overhang = (guint32)(*pchi >> 32);
- prev_lo = *pclo;
+
+ /* The original loop was this: */
+ /*
+ while (texp > 0 && (overhang > (2<<DECIMAL_MAX_INTFACTORS) || (*pclo & 1) == 0)) {
+ if (--texp == 0)
+ roundBit = (int)(*pclo & 1);
+ rshift128(pclo, pchi);
+ overhang = (guint32)(*pchi >> 32);
+ }
+ */
+ if (overhang > 0) {
+ int msf = my_g_bit_nth_msf (overhang);
+ int shift = msf - (DECIMAL_MAX_INTFACTORS + 2);
+
+ if (shift >= texp)
+ shift = texp - 1;
+
+ if (shift > 0) {
+ texp -= shift;
+ *pclo = (*pclo >> shift) | ((*pchi & ((1 << shift) - 1)) << (64 - shift));
+ *pchi >>= shift;
+ overhang >>= shift;
+
+ g_assert (texp > 0);
+ g_assert (overhang > (2 << DECIMAL_MAX_INTFACTORS));
+ }
+ }
while (texp > 0 && (overhang > (2<<DECIMAL_MAX_INTFACTORS) || (*pclo & 1) == 0)) {
- --texp;
- prev_lo = *pclo;
+ if (--texp == 0) roundBit = (int)(*pclo & 1);
rshift128(pclo, pchi);
overhang >>= 1;
}
- if (texp == 0)
- roundBit = (int)(prev_lo & 1);
if (texp > DECIMAL_MAX_INTFACTORS) i = DECIMAL_MAX_INTFACTORS;
else i = texp;
MONO_ARCH_SAVE_REGS;
+ /* Check for common cases */
+ if (mono_decimalCompare (pA, pB) == 0)
+ /* One */
+ return pack128toDecimal (pC, 1, 0, 0, 0);
+ pA->signscale.sign = pA->signscale.sign ? 0 : 1;
+ if (mono_decimalCompare (pA, pB) == 0)
+ /* Minus one */
+ return pack128toDecimal (pC, 1, 0, 0, 1);
+ pA->signscale.sign = pA->signscale.sign ? 0 : 1;
+
rc = decimalDivSub(pA, pB, &clo, &chi, &texp);
if (rc != DECIMAL_SUCCESS) {
if (rc == DECIMAL_FINISHED) rc = DECIMAL_SUCCESS;