Refactor string to/from double conversion, fix bugs, use bigger ints
Finally, fixed bugs in bigint implementation as well as switched to 32/64 bit integer implementation (gained 2x speed up in some cases). Additionally, I decided to split Float.c into Float.c and BInt.h for better readability.
This commit is contained in:
499
src/String/BInt.h
Normal file
499
src/String/BInt.h
Normal file
@@ -0,0 +1,499 @@
|
|||||||
|
/* Platform dependant definition */
|
||||||
|
#ifndef BH_TWEAK_SHORT_BINT
|
||||||
|
#define BINT_SIZE 40
|
||||||
|
#define BINT_TYPE uint32_t
|
||||||
|
#define BINT_TTYPE uint64_t
|
||||||
|
#define BINT_BITS 32
|
||||||
|
#define BINT_MASK 0xFFFFFFFFul
|
||||||
|
#else
|
||||||
|
#define BINT_SIZE 80
|
||||||
|
#define BINT_TYPE uint16_t
|
||||||
|
#define BINT_TTYPE uint32_t
|
||||||
|
#define BINT_BITS 16
|
||||||
|
#define BINT_MASK 0xFFFFu
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct BInt {
|
||||||
|
int size;
|
||||||
|
BINT_TYPE data[BINT_SIZE];
|
||||||
|
} BInt;
|
||||||
|
|
||||||
|
|
||||||
|
static const uint8_t clzLookup[256] =
|
||||||
|
{
|
||||||
|
8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4,
|
||||||
|
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
|
||||||
|
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
|
||||||
|
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef BH_TWEAK_SHORT_BINT
|
||||||
|
static const BInt BInt1 = {1, {0x00000001ul}};
|
||||||
|
static const BInt BInt53 = {2, {0x00000000ul, 0x00200000ul}};
|
||||||
|
|
||||||
|
|
||||||
|
static const BInt powLookup[] =
|
||||||
|
{
|
||||||
|
{1, {0x0000000Aul}},
|
||||||
|
{1, {0x00000064ul}},
|
||||||
|
{1, {0x00002710ul}},
|
||||||
|
{1, {0x05F5E100ul}},
|
||||||
|
{2, {0x6FC10000ul, 0x002386F2ul}},
|
||||||
|
{4, {0x00000000ul, 0x85ACEF81ul, 0x2D6D415Bul, 0x000004EEul}},
|
||||||
|
{7, {0x00000000ul, 0x00000000ul, 0xBF6A1F01ul, 0x6E38ED64ul, 0xDAA797EDul,
|
||||||
|
0xE93FF9F4ul, 0x00184F03ul}},
|
||||||
|
{14, {0x00000000ul, 0x00000000ul, 0x00000000ul, 0x00000000ul, 0x2E953E01ul,
|
||||||
|
0x03DF9909ul, 0x0F1538FDul, 0x2374E42Ful, 0xD3CFF5ECul, 0xC404DC08ul,
|
||||||
|
0xBCCDB0DAul, 0xA6337F19ul, 0xE91F2603ul, 0x0000024Eul}},
|
||||||
|
{27, {0x00000000ul, 0x00000000ul, 0x00000000ul, 0x00000000ul, 0x00000000ul,
|
||||||
|
0x00000000ul, 0x00000000ul, 0x00000000ul, 0x982E7C01ul, 0xBED3875Bul,
|
||||||
|
0xD8D99F72ul, 0x12152F87ul, 0x6BDE50C6ul, 0xCF4A6E70ul, 0xD595D80Ful,
|
||||||
|
0x26B2716Eul, 0xADC666B0ul, 0x1D153624ul, 0x3C42D35Aul, 0x63FF540Eul,
|
||||||
|
0xCC5573C0ul, 0x65F9EF17ul, 0x55BC28F2ul, 0x80DCC7F7ul, 0xF46EEDDCul,
|
||||||
|
0x5FDCEFCEul, 0x000553F7ul}}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static int BIntClz(BINT_TYPE value)
|
||||||
|
{
|
||||||
|
if (value & 0xFF000000ul)
|
||||||
|
return clzLookup[(value >> 24) & 0xFF];
|
||||||
|
else if (value & 0x00FF0000ul)
|
||||||
|
return 8 + clzLookup[(value >> 16) & 0xFF];
|
||||||
|
else if (value & 0x0000FF00ul)
|
||||||
|
return 16 + clzLookup[(value >> 8) & 0xFF];
|
||||||
|
else
|
||||||
|
return 24 + clzLookup[value & 0xFF];
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
static const BInt BInt1 = {1, {0x0001u}};
|
||||||
|
static const BInt BInt53 = {4, {0x0000u, 0x0000u, 0x0000u, 0x0020u}};
|
||||||
|
|
||||||
|
|
||||||
|
static const BInt powLookup[] =
|
||||||
|
{
|
||||||
|
{1, {0x000Au}},
|
||||||
|
{1, {0x0064u}},
|
||||||
|
{1, {0x2710u}},
|
||||||
|
{2, {0xE100u, 0x05F5u}},
|
||||||
|
{4, {0x0000u, 0x6FC1u, 0x86F2u, 0x0023u}},
|
||||||
|
{7, {0x0000u, 0x0000u, 0xEF81u, 0x85ACu, 0x415Bu, 0x2D6Du, 0x04EEu}},
|
||||||
|
{14, {0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x1F01u, 0xBF6Au, 0xED64u,
|
||||||
|
0x6E38u, 0x97EDu, 0xDAA7u, 0xF9F4u, 0xE93Fu, 0x4F03u, 0x0018u}},
|
||||||
|
{27, {0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u,
|
||||||
|
0x0000u, 0x3E01u, 0x2E95u, 0x9909u, 0x03DFu, 0x38FDu, 0x0F15u,
|
||||||
|
0xE42Fu, 0x2374u, 0xF5ECu, 0xD3CFu, 0xDC08u, 0xC404u, 0xB0DAu,
|
||||||
|
0xBCCDu, 0x7F19u, 0xA633u, 0x2603u, 0xE91Fu, 0x024Eu}},
|
||||||
|
{54, {0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u,
|
||||||
|
0x0000u,
|
||||||
|
0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u,
|
||||||
|
0x0000u, 0x7C01u, 0x982Eu, 0x875Bu, 0xBED3u, 0x9F72u, 0xD8D9u,
|
||||||
|
0x2F87u, 0x1215u, 0x50C6u, 0x6BDEu, 0x6E70u, 0xCF4Au, 0xD80Fu,
|
||||||
|
0xD595u, 0x716Eu, 0x26B2u, 0x66B0u, 0xADC6u, 0x3624u, 0x1D15u,
|
||||||
|
0xD35Au, 0x3C42u, 0x540Eu, 0x63FFu, 0x73C0u, 0xCC55u, 0xEF17u,
|
||||||
|
0x65F9u, 0x28F2u, 0x55BCu, 0xC7F7u, 0x80DCu, 0xEDDCu, 0xF46Eu,
|
||||||
|
0xEFCEu, 0x5FDCu, 0x53F7u, 0x0005u}}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static int BIntClz(BINT_TYPE value)
|
||||||
|
{
|
||||||
|
if (value & 0xFF00)
|
||||||
|
return clzLookup[(value >> 8) & 0xFF];
|
||||||
|
else
|
||||||
|
return 8 + clzLookup[value & 0xFF];
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
static int BIntLog2(const BInt *in)
|
||||||
|
{
|
||||||
|
/* Preconditions */
|
||||||
|
assert(in != NULL);
|
||||||
|
assert(in->size != 0);
|
||||||
|
assert(in->data[in->size - 1] != 0);
|
||||||
|
|
||||||
|
return (BINT_BITS - 1) - BIntClz(in->data[in->size - 1]) + BINT_BITS * (in->size - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void BIntTrim(BInt *in)
|
||||||
|
{
|
||||||
|
/* Preconditions */
|
||||||
|
assert(in != NULL);
|
||||||
|
|
||||||
|
while (in->size && !in->data[in->size - 1])
|
||||||
|
in->size--;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int BIntCompare(const BInt *a,
|
||||||
|
const BInt *b)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/* Preconditions */
|
||||||
|
assert(a != NULL && b != NULL);
|
||||||
|
|
||||||
|
/* Compare by lengths */
|
||||||
|
i = a->size - b->size;
|
||||||
|
if (a->size - b->size)
|
||||||
|
return a->size - b->size;
|
||||||
|
|
||||||
|
/* Compare by blocks */
|
||||||
|
for (i = a->size; i; i--)
|
||||||
|
{
|
||||||
|
if (a->data[i - 1] < b->data[i - 1])
|
||||||
|
return -1;
|
||||||
|
else if (a->data[i - 1] > b->data[i - 1])
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void BIntAdd(const BInt *a,
|
||||||
|
const BInt *b,
|
||||||
|
BInt *out)
|
||||||
|
{
|
||||||
|
BINT_TTYPE carry;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/* Preconditions */
|
||||||
|
assert(a != NULL && b != NULL && out != NULL);
|
||||||
|
assert(a->size + 1 <= BINT_SIZE);
|
||||||
|
assert(b->size + 1 <= BINT_SIZE);
|
||||||
|
|
||||||
|
/* Addition loop */
|
||||||
|
carry = 0;
|
||||||
|
for (i = 0; i < a->size || i < b->size; i++)
|
||||||
|
{
|
||||||
|
if (i < a->size)
|
||||||
|
carry += a->data[i];
|
||||||
|
if (i < b->size)
|
||||||
|
carry += b->data[i];
|
||||||
|
|
||||||
|
out->data[i] = carry & BINT_MASK;
|
||||||
|
carry = (carry >> BINT_BITS);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Handle new digit */
|
||||||
|
if (carry)
|
||||||
|
out->data[i++] = carry;
|
||||||
|
|
||||||
|
out->size = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void BIntSub(const BInt *a,
|
||||||
|
const BInt *b,
|
||||||
|
BInt *out)
|
||||||
|
{
|
||||||
|
BINT_TTYPE carry;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/* Preconditions */
|
||||||
|
assert(a != NULL && b != NULL && out != NULL);
|
||||||
|
assert(BIntCompare(a, b) >= 0);
|
||||||
|
|
||||||
|
/* Main subtraction loop */
|
||||||
|
carry = 0;
|
||||||
|
for (i = 0; i < a->size || i < b->size; i++)
|
||||||
|
{
|
||||||
|
if (i < a->size)
|
||||||
|
carry += a->data[i];
|
||||||
|
if (i < b->size)
|
||||||
|
carry -= b->data[i];
|
||||||
|
|
||||||
|
out->data[i] = carry & BINT_MASK;
|
||||||
|
carry = carry >> BINT_BITS;
|
||||||
|
carry |= (carry << BINT_BITS);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Trim leading zeros */
|
||||||
|
out->size = a->size;
|
||||||
|
BIntTrim(out);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void BIntMul(const BInt *a,
|
||||||
|
const BInt *b,
|
||||||
|
BInt *out)
|
||||||
|
{
|
||||||
|
BINT_TTYPE carry;
|
||||||
|
int i, j;
|
||||||
|
|
||||||
|
/* Preconditions */
|
||||||
|
assert(a != NULL && b != NULL && out != NULL);
|
||||||
|
assert(a->size + b->size <= BINT_SIZE);
|
||||||
|
|
||||||
|
/* Zero out the result */
|
||||||
|
memset(out->data, 0, sizeof(out->data));
|
||||||
|
|
||||||
|
/* Multiplication loop */
|
||||||
|
for (i = 0; i < a->size; i++)
|
||||||
|
{
|
||||||
|
carry = 0;
|
||||||
|
for (j = 0; j < b->size; j++)
|
||||||
|
{
|
||||||
|
carry += out->data[i + j];
|
||||||
|
carry += (BINT_TTYPE)a->data[i] * (BINT_TTYPE)b->data[j];
|
||||||
|
out->data[i + j] = carry & BINT_MASK;
|
||||||
|
carry = (carry >> BINT_BITS);
|
||||||
|
}
|
||||||
|
out->data[i + j] += carry;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Trim leading zeros */
|
||||||
|
out->size = a->size + b->size;
|
||||||
|
BIntTrim(out);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void BIntMulDigit(const BInt *a,
|
||||||
|
BINT_TYPE b,
|
||||||
|
BInt *out)
|
||||||
|
{
|
||||||
|
BINT_TTYPE carry;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/* Preconditions */
|
||||||
|
assert(a != NULL && out != NULL);
|
||||||
|
assert(a->size + 1 <= BINT_SIZE);
|
||||||
|
|
||||||
|
/* Multiplication loop */
|
||||||
|
carry = 0;
|
||||||
|
for (i = 0; i < a->size; i++)
|
||||||
|
{
|
||||||
|
carry += (BINT_TTYPE)a->data[i] * b;
|
||||||
|
out->data[i] = carry & BINT_MASK;
|
||||||
|
carry = (carry >> BINT_BITS);
|
||||||
|
}
|
||||||
|
out->data[i] = carry;
|
||||||
|
|
||||||
|
/* Trim leading zeros */
|
||||||
|
out->size = a->size + 1;
|
||||||
|
BIntTrim(out);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void BIntPow10(const BInt *in,
|
||||||
|
int exponent,
|
||||||
|
BInt *out,
|
||||||
|
BInt *tmp)
|
||||||
|
{
|
||||||
|
int i, current;
|
||||||
|
|
||||||
|
/* Preconditions */
|
||||||
|
assert(in != NULL && out != NULL && tmp != NULL);
|
||||||
|
assert(exponent >= 0 && exponent < 512);
|
||||||
|
|
||||||
|
tmp[0] = *in;
|
||||||
|
for (current = 0, i = 0; exponent; i++, exponent >>= 1)
|
||||||
|
{
|
||||||
|
if (!(exponent & 0x1))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
BIntMul(&tmp[current], &powLookup[i], &tmp[1 - current]);
|
||||||
|
current = 1 - current;
|
||||||
|
}
|
||||||
|
*out = tmp[current];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void BIntLsh(const BInt *in,
|
||||||
|
int amount,
|
||||||
|
BInt *out)
|
||||||
|
{
|
||||||
|
int blocks, bits, i;
|
||||||
|
BINT_TYPE low, high;
|
||||||
|
|
||||||
|
/* Preconditions */
|
||||||
|
assert(in != NULL && out != NULL);
|
||||||
|
assert(amount >= 0 && in->size + (amount + BINT_BITS - 1) / BINT_BITS <= BINT_SIZE);
|
||||||
|
|
||||||
|
blocks = amount / BINT_BITS;
|
||||||
|
bits = amount % BINT_BITS;
|
||||||
|
if (!in->size)
|
||||||
|
{
|
||||||
|
out->size = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Main shift loop */
|
||||||
|
if (bits)
|
||||||
|
{
|
||||||
|
high = 0;
|
||||||
|
for (i = in->size + blocks; i > blocks; i--)
|
||||||
|
{
|
||||||
|
low = in->data[i - blocks - 1] >> (BINT_BITS - bits);
|
||||||
|
out->data[i] = low | high;
|
||||||
|
high = in->data[i - blocks - 1] << bits;
|
||||||
|
}
|
||||||
|
out->data[i] = high;
|
||||||
|
out->size = in->size + blocks + 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (i = in->size; i; i--)
|
||||||
|
out->data[i - 1 + blocks] = in->data[i - 1];
|
||||||
|
out->size = in->size + blocks;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Trim leading zeros and zero out lower blocks */
|
||||||
|
BIntTrim(out);
|
||||||
|
for (i = blocks; i; i--)
|
||||||
|
out->data[i - 1] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void BIntRsh(const BInt *in,
|
||||||
|
int amount,
|
||||||
|
BInt *out)
|
||||||
|
{
|
||||||
|
int blocks, bits, i;
|
||||||
|
BINT_TYPE low, high;
|
||||||
|
|
||||||
|
/* Preconditions */
|
||||||
|
assert(in != NULL && out != NULL);
|
||||||
|
assert(amount >= 0);
|
||||||
|
|
||||||
|
blocks = amount / BINT_BITS;
|
||||||
|
bits = amount % BINT_BITS;
|
||||||
|
|
||||||
|
/* Zero size input or shift is bigger then input */
|
||||||
|
if (in->size == 0 || in->size <= blocks)
|
||||||
|
{
|
||||||
|
out->size = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Shift and copy parts of two blocks */
|
||||||
|
if (bits)
|
||||||
|
{
|
||||||
|
low = in->data[blocks] >> bits;
|
||||||
|
high = 0;
|
||||||
|
for (i = 0; i < in->size - blocks - 1; i++)
|
||||||
|
{
|
||||||
|
high = in->data[i + blocks + 1] << (BINT_BITS - bits);
|
||||||
|
out->data[i] = low | high;
|
||||||
|
low = in->data[i + blocks + 1] >> bits;
|
||||||
|
}
|
||||||
|
out->data[in->size - blocks - 1] = low;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (i = 0; i < in->size - blocks; i++)
|
||||||
|
out->data[i] = out->data[i + blocks];
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Trim leading zeros */
|
||||||
|
out->size = in->size - blocks;
|
||||||
|
BIntTrim(out);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static BINT_TTYPE BIntGuess(const BInt *a,
|
||||||
|
const BInt *b)
|
||||||
|
{
|
||||||
|
BINT_TTYPE tmp;
|
||||||
|
|
||||||
|
/* Preconditions */
|
||||||
|
assert(a != NULL && b != NULL);
|
||||||
|
assert(a->size > 0 && b->size > 0);
|
||||||
|
assert((a->size == b->size) || ((a->size != b->size) && a->size > 1));
|
||||||
|
|
||||||
|
if (BIntCompare(a, b) < 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
tmp = a->data[a->size - 1];
|
||||||
|
if (a->size != b->size)
|
||||||
|
tmp = (tmp << BINT_BITS) | a->data[a->size - 2];
|
||||||
|
|
||||||
|
return tmp / b->data[b->size - 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void BIntDiv(const BInt *a,
|
||||||
|
const BInt *b,
|
||||||
|
BInt *q,
|
||||||
|
BInt *r,
|
||||||
|
BInt *tmp)
|
||||||
|
{
|
||||||
|
BINT_TTYPE digit;
|
||||||
|
int shift;
|
||||||
|
|
||||||
|
/* Preconditions */
|
||||||
|
assert(a != NULL && b != NULL && q != NULL && r != NULL && tmp != NULL);
|
||||||
|
assert(b->size != 0);
|
||||||
|
|
||||||
|
/* Handle case where a is less then b */
|
||||||
|
if (BIntCompare(a, b) < 0)
|
||||||
|
{
|
||||||
|
*r = *a;
|
||||||
|
q->size = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Normilize input to reduce tries */
|
||||||
|
shift = BIntClz(b->data[b->size - 1]);
|
||||||
|
BIntLsh(a, shift, &tmp[0]);
|
||||||
|
BIntLsh(b, shift, &tmp[1]);
|
||||||
|
|
||||||
|
/* Prepare first step of the division */
|
||||||
|
q->size = 0;
|
||||||
|
r->size = 0;
|
||||||
|
while (BIntCompare(r, &tmp[1]) < 0)
|
||||||
|
{
|
||||||
|
BIntLsh(r, BINT_BITS, r);
|
||||||
|
r->data[0] = tmp[0].data[--tmp[0].size];
|
||||||
|
r->size += !r->size;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
/* Make a guess and check */
|
||||||
|
digit = BIntGuess(r, &tmp[1]);
|
||||||
|
while (digit > BINT_MASK)
|
||||||
|
digit--;
|
||||||
|
BIntMulDigit(&tmp[1], digit, &tmp[2]);
|
||||||
|
while (BIntCompare(r, &tmp[2]) < 0)
|
||||||
|
{
|
||||||
|
--digit;
|
||||||
|
BIntSub(&tmp[2], &tmp[1], &tmp[2]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Store digit in quotient */
|
||||||
|
BIntSub(r, &tmp[2], r);
|
||||||
|
BIntLsh(q, BINT_BITS, q);
|
||||||
|
q->data[0] = digit;
|
||||||
|
q->size += !q->size;
|
||||||
|
|
||||||
|
/* Fetch next digit or exit */
|
||||||
|
if (!tmp[0].size)
|
||||||
|
break;
|
||||||
|
|
||||||
|
BIntLsh(r, BINT_BITS, r);
|
||||||
|
r->data[0] = tmp[0].data[--tmp[0].size];
|
||||||
|
if (!r->size)
|
||||||
|
r->size = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Normilize remainder */
|
||||||
|
BIntRsh(r, shift, r);
|
||||||
|
}
|
||||||
@@ -8,11 +8,13 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
|
||||||
|
#include "BInt.h"
|
||||||
|
|
||||||
|
|
||||||
/* Common defines */
|
/* Common defines */
|
||||||
#define MAX(a,b) (((a)>(b))?(a):(b))
|
#define MAX(a,b) (((a)>(b))?(a):(b))
|
||||||
#define MIN(a,b) (((a)<(b))?(a):(b))
|
#define MIN(a,b) (((a)<(b))?(a):(b))
|
||||||
#define BUFSIZE 309
|
#define BUFSIZE 309
|
||||||
#define DIGITS 80
|
|
||||||
|
|
||||||
/* Modes */
|
/* Modes */
|
||||||
#define NORMAL 0
|
#define NORMAL 0
|
||||||
@@ -20,12 +22,6 @@
|
|||||||
#define RELATIVE 2
|
#define RELATIVE 2
|
||||||
|
|
||||||
|
|
||||||
typedef struct BInt {
|
|
||||||
int size;
|
|
||||||
uint16_t data[DIGITS];
|
|
||||||
} BInt;
|
|
||||||
|
|
||||||
|
|
||||||
struct DragonState
|
struct DragonState
|
||||||
{
|
{
|
||||||
BInt r;
|
BInt r;
|
||||||
@@ -38,433 +34,6 @@ struct DragonState
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
static const BInt BInt1 = {1, {1}};
|
|
||||||
static const BInt BInt53 = {4, {0x0000, 0x0000, 0x0000, 0x0020}};
|
|
||||||
|
|
||||||
|
|
||||||
static const uint8_t clzLookup[256] =
|
|
||||||
{
|
|
||||||
8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4,
|
|
||||||
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
|
|
||||||
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
|
|
||||||
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
|
|
||||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
|
||||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
|
||||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
|
||||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
static const BInt powLookup[] =
|
|
||||||
{
|
|
||||||
{1, {0x000A}},
|
|
||||||
{1, {0x0064}},
|
|
||||||
{1, {0x2710}},
|
|
||||||
{2, {0xE100, 0x05F5}},
|
|
||||||
{4, {0x0000, 0x6FC1, 0x86F2, 0x0023}},
|
|
||||||
{7, {0x0000, 0x0000, 0xEF81, 0x85AC, 0x415B, 0x2D6D, 0x04EE}},
|
|
||||||
{14, {0x0000, 0x0000, 0x0000, 0x0000, 0x1F01, 0xBF6A, 0xED64, 0x6E38,
|
|
||||||
0x97ED, 0xDAA7, 0xF9F4, 0xE93F, 0x4F03, 0x0018}},
|
|
||||||
{27, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
|
||||||
0x3E01, 0x2E95, 0x9909, 0x03DF, 0x38FD, 0x0F15, 0xE42F, 0x2374,
|
|
||||||
0xF5EC, 0xD3CF, 0xDC08, 0xC404, 0xB0DA, 0xBCCD, 0x7F19, 0xA633,
|
|
||||||
0x2603, 0xE91F, 0x024E}},
|
|
||||||
{54, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
|
||||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
|
||||||
0x7C01, 0x982E, 0x875B, 0xBED3, 0x9F72, 0xD8D9, 0x2F87, 0x1215,
|
|
||||||
0x50C6, 0x6BDE, 0x6E70, 0xCF4A, 0xD80F, 0xD595, 0x716E, 0x26B2,
|
|
||||||
0x66B0, 0xADC6, 0x3624, 0x1D15, 0xD35A, 0x3C42, 0x540E, 0x63FF,
|
|
||||||
0x73C0, 0xCC55, 0xEF17, 0x65F9, 0x28F2, 0x55BC, 0xC7F7, 0x80DC,
|
|
||||||
0xEDDC, 0xF46E, 0xEFCE, 0x5FDC, 0x53F7, 0x0005}}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
static int BIntClz(uint16_t value)
|
|
||||||
{
|
|
||||||
if (value & 0xFF00)
|
|
||||||
return clzLookup[(value >> 8) & 0xFF];
|
|
||||||
else
|
|
||||||
return 8 + clzLookup[value & 0xFF];
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static int BIntLog2(const BInt *in)
|
|
||||||
{
|
|
||||||
/* Preconditions */
|
|
||||||
assert(in != NULL);
|
|
||||||
assert(in->size != 0);
|
|
||||||
assert(in->data[in->size - 1] != 0);
|
|
||||||
|
|
||||||
return 15 - BIntClz(in->data[in->size - 1]) + 16 * (in->size - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void BIntTrim(BInt *in)
|
|
||||||
{
|
|
||||||
/* Preconditions */
|
|
||||||
assert(in != NULL);
|
|
||||||
|
|
||||||
while (in->size && !in->data[in->size - 1])
|
|
||||||
in->size--;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static int BIntCompare(const BInt *a,
|
|
||||||
const BInt *b)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
/* Preconditions */
|
|
||||||
assert(a != NULL && b != NULL);
|
|
||||||
|
|
||||||
/* Compare by lengths */
|
|
||||||
i = a->size - b->size;
|
|
||||||
if (a->size - b->size)
|
|
||||||
return a->size - b->size;
|
|
||||||
|
|
||||||
/* Compare by blocks */
|
|
||||||
for (i = a->size; i; i--)
|
|
||||||
{
|
|
||||||
if (a->data[i - 1] < b->data[i - 1])
|
|
||||||
return -1;
|
|
||||||
else if (a->data[i - 1] > b->data[i - 1])
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void BIntAdd(const BInt *a,
|
|
||||||
const BInt *b,
|
|
||||||
BInt *out)
|
|
||||||
{
|
|
||||||
uint32_t carry;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
/* Preconditions */
|
|
||||||
assert(a != NULL && b != NULL && out != NULL);
|
|
||||||
assert(a->size + 1 <= DIGITS);
|
|
||||||
assert(b->size + 1 <= DIGITS);
|
|
||||||
|
|
||||||
/* Addition loop */
|
|
||||||
carry = 0;
|
|
||||||
for (i = 0; i < a->size || i < b->size; i++)
|
|
||||||
{
|
|
||||||
if (i < a->size)
|
|
||||||
carry += a->data[i];
|
|
||||||
if (i < b->size)
|
|
||||||
carry += b->data[i];
|
|
||||||
|
|
||||||
out->data[i] = carry & 0xFFFF;
|
|
||||||
carry = (carry >> 16);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Handle new digit */
|
|
||||||
if (carry)
|
|
||||||
out->data[i++] = carry;
|
|
||||||
|
|
||||||
out->size = i;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void BIntSub(const BInt *a,
|
|
||||||
const BInt *b,
|
|
||||||
BInt *out)
|
|
||||||
{
|
|
||||||
uint32_t carry;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
/* Preconditions */
|
|
||||||
assert(a != NULL && b != NULL && out != NULL);
|
|
||||||
assert(BIntCompare(a, b) >= 0);
|
|
||||||
|
|
||||||
/* Main subtraction loop */
|
|
||||||
carry = 0;
|
|
||||||
for (i = 0; i < a->size || i < b->size; i++)
|
|
||||||
{
|
|
||||||
if (i < a->size)
|
|
||||||
carry += a->data[i];
|
|
||||||
if (i < b->size)
|
|
||||||
carry -= b->data[i];
|
|
||||||
|
|
||||||
out->data[i] = carry & 0xFFFF;
|
|
||||||
carry = (carry & 0xFFFF0000) | (carry >> 16);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Trim leading zeros */
|
|
||||||
out->size = a->size;
|
|
||||||
BIntTrim(out);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void BIntMul(const BInt *a,
|
|
||||||
const BInt *b,
|
|
||||||
BInt *out)
|
|
||||||
{
|
|
||||||
uint32_t carry;
|
|
||||||
int i, j;
|
|
||||||
|
|
||||||
/* Preconditions */
|
|
||||||
assert(a != NULL && b != NULL && out != NULL);
|
|
||||||
assert(a->size + b->size <= DIGITS);
|
|
||||||
|
|
||||||
/* Zero out the result */
|
|
||||||
memset(out->data, 0, sizeof(out->data));
|
|
||||||
for (i = 0; i < DIGITS; i++)
|
|
||||||
out->data[i] = 0;
|
|
||||||
|
|
||||||
/* Multiplication loop */
|
|
||||||
for (i = 0; i < a->size; i++)
|
|
||||||
{
|
|
||||||
carry = 0;
|
|
||||||
for (j = 0; j < b->size; j++)
|
|
||||||
{
|
|
||||||
carry += out->data[i + j];
|
|
||||||
carry += (uint32_t)a->data[i] * (uint32_t)b->data[j];
|
|
||||||
out->data[i + j] = carry & 0xFFFF;
|
|
||||||
carry = (carry >> 16);
|
|
||||||
}
|
|
||||||
out->data[i + j] += carry;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Trim leading zeros */
|
|
||||||
out->size = a->size + b->size;
|
|
||||||
BIntTrim(out);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void BIntMulDigit(const BInt *a,
|
|
||||||
uint16_t b,
|
|
||||||
BInt *out)
|
|
||||||
{
|
|
||||||
uint32_t carry;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
/* Preconditions */
|
|
||||||
assert(a != NULL && out != NULL);
|
|
||||||
assert(a->size + 1 <= DIGITS);
|
|
||||||
|
|
||||||
/* Multiplication loop */
|
|
||||||
carry = 0;
|
|
||||||
for (i = 0; i < a->size; i++)
|
|
||||||
{
|
|
||||||
carry += (uint32_t)a->data[i] * b;
|
|
||||||
out->data[i] = carry & 0xFFFF;
|
|
||||||
carry = (carry >> 16);
|
|
||||||
}
|
|
||||||
out->data[i] = carry;
|
|
||||||
|
|
||||||
/* Trim leading zeros */
|
|
||||||
out->size = a->size + 1;
|
|
||||||
BIntTrim(out);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void BIntPow10(const BInt *in,
|
|
||||||
int exponent,
|
|
||||||
BInt *out,
|
|
||||||
BInt *tmp)
|
|
||||||
{
|
|
||||||
int i, current;
|
|
||||||
|
|
||||||
/* Preconditions */
|
|
||||||
assert(in != NULL && out != NULL && tmp != NULL);
|
|
||||||
assert(exponent >= 0 && exponent < 512);
|
|
||||||
|
|
||||||
tmp[0] = *in;
|
|
||||||
for (current = 0, i = 0; exponent; i++, exponent >>= 1)
|
|
||||||
{
|
|
||||||
if (!(exponent & 0x1))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
BIntMul(&tmp[current], &powLookup[i], &tmp[1 - current]);
|
|
||||||
current = 1 - current;
|
|
||||||
}
|
|
||||||
*out = tmp[current];
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void BIntLsh(const BInt *in,
|
|
||||||
int amount,
|
|
||||||
BInt *out)
|
|
||||||
{
|
|
||||||
int blocks, bits, i;
|
|
||||||
uint16_t low, high;
|
|
||||||
|
|
||||||
/* Preconditions */
|
|
||||||
assert(in != NULL && out != NULL);
|
|
||||||
assert(amount >= 0 && in->size + (amount + 15) / 16 <= DIGITS);
|
|
||||||
|
|
||||||
blocks = amount / 16;
|
|
||||||
bits = amount % 16;
|
|
||||||
if (!in->size)
|
|
||||||
{
|
|
||||||
out->size = 0;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Main shift loop */
|
|
||||||
if (bits)
|
|
||||||
{
|
|
||||||
high = 0;
|
|
||||||
for (i = in->size + blocks; i > blocks; i--)
|
|
||||||
{
|
|
||||||
low = in->data[i - blocks - 1] >> (16 - bits);
|
|
||||||
out->data[i] = low | high;
|
|
||||||
high = in->data[i - blocks - 1] << bits;
|
|
||||||
}
|
|
||||||
out->data[i] = high;
|
|
||||||
out->size = in->size + blocks + 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
for (i = in->size; i; i--)
|
|
||||||
out->data[i - 1 + blocks] = in->data[i - 1];
|
|
||||||
out->size = in->size + blocks;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Trim leading zeros and zero out lower blocks */
|
|
||||||
BIntTrim(out);
|
|
||||||
for (i = blocks; i; i--)
|
|
||||||
out->data[i - 1] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void BIntRsh(const BInt *in,
|
|
||||||
int amount,
|
|
||||||
BInt *out)
|
|
||||||
{
|
|
||||||
int blocks, bits, i;
|
|
||||||
uint16_t low, high;
|
|
||||||
|
|
||||||
/* Preconditions */
|
|
||||||
assert(in != NULL && out != NULL);
|
|
||||||
assert(amount >= 0);
|
|
||||||
|
|
||||||
blocks = amount / 16;
|
|
||||||
bits = amount % 16;
|
|
||||||
|
|
||||||
/* Zero size input or shift is bigger then input */
|
|
||||||
if (in->size == 0 || in->size <= blocks)
|
|
||||||
{
|
|
||||||
out->size = 0;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Shift and copy parts of two blocks */
|
|
||||||
low = in->data[blocks] >> bits;
|
|
||||||
high = 0;
|
|
||||||
for (i = 0; i < in->size - blocks - 1; i++)
|
|
||||||
{
|
|
||||||
high = in->data[i + blocks + 1] << (16 - bits);
|
|
||||||
out->data[i] = low | high;
|
|
||||||
low = in->data[i + blocks + 1] >> bits;
|
|
||||||
}
|
|
||||||
out->data[in->size - blocks - 1] = low;
|
|
||||||
|
|
||||||
/* Trim leading zeros */
|
|
||||||
out->size = in->size - blocks;
|
|
||||||
BIntTrim(out);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static uint16_t BIntGuess(const BInt *a,
|
|
||||||
const BInt *b)
|
|
||||||
{
|
|
||||||
uint32_t tmp;
|
|
||||||
|
|
||||||
/* Preconditions */
|
|
||||||
assert(a != NULL && b != NULL);
|
|
||||||
assert(a->size > 0 && b->size > 0);
|
|
||||||
|
|
||||||
if (BIntCompare(a, b) < 0)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
tmp = a->data[a->size - 1];
|
|
||||||
if (a->size != b->size)
|
|
||||||
tmp = tmp << 16 | a->data[a->size - 2];
|
|
||||||
|
|
||||||
return tmp / b->data[b->size - 1];
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void BIntDiv(const BInt *a,
|
|
||||||
const BInt *b,
|
|
||||||
BInt *q,
|
|
||||||
BInt *r,
|
|
||||||
BInt *tmp)
|
|
||||||
{
|
|
||||||
uint16_t digit;
|
|
||||||
int shift;
|
|
||||||
|
|
||||||
/* Preconditions */
|
|
||||||
assert(a != NULL && b != NULL && q != NULL && r != NULL && tmp != NULL);
|
|
||||||
assert(b->size != 0);
|
|
||||||
|
|
||||||
/* Handle case where a is less then b */
|
|
||||||
if (BIntCompare(a, b) < 0)
|
|
||||||
{
|
|
||||||
*r = *a;
|
|
||||||
q->size = 0;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Normilize input to reduce tries */
|
|
||||||
shift = BIntClz(b->data[b->size - 1]);
|
|
||||||
BIntLsh(a, shift, &tmp[0]);
|
|
||||||
BIntLsh(b, shift, &tmp[1]);
|
|
||||||
|
|
||||||
/* Prepare first step of the division */
|
|
||||||
q->size = 0;
|
|
||||||
r->size = 0;
|
|
||||||
while (BIntCompare(r, &tmp[1]) < 0)
|
|
||||||
{
|
|
||||||
BIntLsh(r, 16, r);
|
|
||||||
r->data[0] = tmp[0].data[--tmp[0].size];
|
|
||||||
r->size += !r->size;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (1)
|
|
||||||
{
|
|
||||||
/* Make a guess and check */
|
|
||||||
digit = BIntGuess(r, &tmp[1]);
|
|
||||||
BIntMulDigit(&tmp[1], digit, &tmp[2]);
|
|
||||||
while (BIntCompare(r, &tmp[2]) < 0)
|
|
||||||
{
|
|
||||||
--digit;
|
|
||||||
BIntSub(&tmp[2], &tmp[1], &tmp[2]);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Store digit in quotient */
|
|
||||||
BIntSub(r, &tmp[2], r);
|
|
||||||
BIntLsh(q, 16, q);
|
|
||||||
q->data[0] = digit;
|
|
||||||
q->size += !q->size;
|
|
||||||
|
|
||||||
/* Fetch next digit or exit */
|
|
||||||
if (!tmp[0].size)
|
|
||||||
break;
|
|
||||||
|
|
||||||
BIntLsh(r, 16, r);
|
|
||||||
r->data[0] = tmp[0].data[--tmp[0].size];
|
|
||||||
if (!r->size)
|
|
||||||
r->size = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Normilize remainder */
|
|
||||||
BIntRsh(r, shift, r);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void dragonFixup(struct DragonState *state,
|
static void dragonFixup(struct DragonState *state,
|
||||||
int precision,
|
int precision,
|
||||||
int mode,
|
int mode,
|
||||||
@@ -486,10 +55,15 @@ static void dragonFixup(struct DragonState *state,
|
|||||||
state->k = 0;
|
state->k = 0;
|
||||||
|
|
||||||
/* Burger/Dybvig approach */
|
/* Burger/Dybvig approach */
|
||||||
state->k = BIntClz((f >> 48) & 0xFFFF);
|
#ifndef BH_TWEAK_SHORT_BINT
|
||||||
state->k += (state->k == 16) ? (BIntClz((f >> 32) & 0xFFFF)) : (0);
|
state->k = BIntClz((f >> 32) & BINT_MASK);
|
||||||
state->k += (state->k == 32) ? (BIntClz((f >> 16) & 0xFFFF)) : (0);
|
state->k += (state->k == 32) ? (BIntClz(f & BINT_MASK)) : (0);
|
||||||
state->k += (state->k == 48) ? (BIntClz(f & 0xFFFF)) : (0);
|
#else
|
||||||
|
state->k = BIntClz((f >> 48) & BINT_MASK);
|
||||||
|
state->k += (state->k == 16) ? (BIntClz((f >> 32) & BINT_MASK)) : (0);
|
||||||
|
state->k += (state->k == 32) ? (BIntClz((f >> 16) & BINT_MASK)) : (0);
|
||||||
|
state->k += (state->k == 48) ? (BIntClz(f & BINT_MASK)) : (0);
|
||||||
|
#endif
|
||||||
|
|
||||||
/* 77 / 256 is an approximation for Log(2) or 0.30102999 */
|
/* 77 / 256 is an approximation for Log(2) or 0.30102999 */
|
||||||
state->k = (63 - state->k + exp - 54) * 77;
|
state->k = (63 - state->k + exp - 54) * 77;
|
||||||
@@ -595,9 +169,18 @@ static void dragon(double value,
|
|||||||
|
|
||||||
/* Prepare dragon */
|
/* Prepare dragon */
|
||||||
f = frexp(value, &e) * ((uint64_t)1 << 53);
|
f = frexp(value, &e) * ((uint64_t)1 << 53);
|
||||||
state.r.data[0] = f & 0xFFFF; state.r.data[1] = (f >> 16) & 0xFFFF;
|
#ifndef BH_TWEAK_SHORT_BINT
|
||||||
state.r.data[2] = (f >> 32) & 0xFFFF; state.r.data[3] = (f >> 48) & 0xFFFF;
|
state.r.data[0] = f & BINT_MASK;
|
||||||
state.r.size = 4; BIntTrim(&state.r);
|
state.r.data[1] = (f >> 32) & BINT_MASK;
|
||||||
|
state.r.size = 2;
|
||||||
|
#else
|
||||||
|
state.r.data[0] = f & BINT_MASK;
|
||||||
|
state.r.data[1] = (f >> 16) & BINT_MASK;
|
||||||
|
state.r.data[2] = (f >> 32) & BINT_MASK;
|
||||||
|
state.r.data[3] = (f >> 48) & BINT_MASK;
|
||||||
|
state.r.size = 4;
|
||||||
|
#endif
|
||||||
|
BIntTrim(&state.r);
|
||||||
|
|
||||||
BIntLsh(&state.r, MAX(e - 53, 0), &state.r);
|
BIntLsh(&state.r, MAX(e - 53, 0), &state.r);
|
||||||
BIntLsh(&BInt1, MAX(0, -(e - 53)), &state.s);
|
BIntLsh(&BInt1, MAX(0, -(e - 53)), &state.s);
|
||||||
@@ -997,11 +580,11 @@ double BH_StringToDouble(const char *string,
|
|||||||
if (type == BH_FP_INFINITE)
|
if (type == BH_FP_INFINITE)
|
||||||
{
|
{
|
||||||
if (sign)
|
if (sign)
|
||||||
return -INFINITY;
|
return -1.0 / 0.0;
|
||||||
return INFINITY;
|
return 1.0 / 0.0;
|
||||||
}
|
}
|
||||||
else if (type == BH_FP_NAN)
|
else if (type == BH_FP_NAN)
|
||||||
return NAN;
|
return 0.0 / 0.0;
|
||||||
else if (type == BH_FP_ZERO)
|
else if (type == BH_FP_ZERO)
|
||||||
{
|
{
|
||||||
/* Hacky solution to indicate we haven't seen any digit */
|
/* Hacky solution to indicate we haven't seen any digit */
|
||||||
@@ -1030,8 +613,8 @@ double BH_StringToDouble(const char *string,
|
|||||||
if (e > 292)
|
if (e > 292)
|
||||||
{
|
{
|
||||||
if (sign)
|
if (sign)
|
||||||
return -INFINITY;
|
return -1.0 / 0.0;
|
||||||
return INFINITY;
|
return 1.0 / 0.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Convert character buffer into integers */
|
/* Convert character buffer into integers */
|
||||||
@@ -1083,10 +666,15 @@ double BH_StringToDouble(const char *string,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Create double from integer and exponent */
|
/* Create double from integer and exponent */
|
||||||
|
#ifndef BH_TWEAK_SHORT_BINT
|
||||||
|
f = (tmp[0].data[1] & 0x001FFFFFul);
|
||||||
|
f = (f << 32) | tmp[0].data[0];
|
||||||
|
#else
|
||||||
f = (tmp[0].data[3] & 0x1F);
|
f = (tmp[0].data[3] & 0x1F);
|
||||||
f = (f << 16) | tmp[0].data[2];
|
f = (f << 16) | tmp[0].data[2];
|
||||||
f = (f << 16) | tmp[0].data[1];
|
f = (f << 16) | tmp[0].data[1];
|
||||||
f = (f << 16) | tmp[0].data[0];
|
f = (f << 16) | tmp[0].data[0];
|
||||||
|
#endif
|
||||||
|
|
||||||
result = ldexp(f, shift);
|
result = ldexp(f, shift);
|
||||||
if (sign)
|
if (sign)
|
||||||
|
|||||||
Reference in New Issue
Block a user