Skip to content

Commit

Permalink
Fix Issue 13391 - Allow division of BigInt by long/ulong
Browse files Browse the repository at this point in the history
  • Loading branch information
fb-pja committed Aug 31, 2014
1 parent 5fb71bb commit 5862d71
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 2 deletions.
41 changes: 39 additions & 2 deletions std/bigint.d
Expand Up @@ -163,8 +163,14 @@ public:
else static if (op=="/")
{
assert(y!=0, "Division by zero");
static assert(!is(T == long) && !is(T == ulong));
data = BigUint.divInt(data, cast(uint)u);
static if (T.sizeof <= uint.sizeof)
{
data = BigUint.divInt(data, cast(uint)u);
}
else
{
data = BigUint.divInt(data, u);
}
sign = data.isZero() ? false : sign ^ (y < 0);
}
else static if (op=="%")
Expand Down Expand Up @@ -994,3 +1000,34 @@ unittest // 11583
BigInt x = 0;
assert((x > 0) == false);
}

unittest // 13391
{
BigInt x1 = "123456789";
BigInt x2 = "123456789123456789";
BigInt x3 = "123456789123456789123456789";

import std.typetuple : TypeTuple;
foreach (T; TypeTuple!(byte, ubyte, short, ushort, int, uint, long, ulong))
{
assert((x1 * T.max) / T.max == x1);
assert((x2 * T.max) / T.max == x2);
assert((x3 * T.max) / T.max == x3);
}

assert(x1 / -123456789 == -1);
assert(x1 / 123456789U == 1);
assert(x1 / -123456789L == -1);
assert(x1 / 123456789UL == 1);
assert(x2 / -123456789123456789L == -1);
assert(x2 / 123456789123456789UL == 1);

assert(x1 / uint.max == 0);
assert(x1 / ulong.max == 0);
assert(x2 / ulong.max == 0);

x1 /= 123456789UL;
assert(x1 == 1);
x2 /= 123456789123456789UL;
assert(x2 == 1);
}
15 changes: 15 additions & 0 deletions std/internal/math/biguintcore.d
Expand Up @@ -597,6 +597,21 @@ public:
return BigUint(removeLeadingZeros(assumeUnique(result)));
}

static BigUint divInt(T)(BigUint x, T y) pure nothrow
if ( is(Unqual!T == ulong) )
{
if (y <= uint.max)
return divInt!uint(x, cast(uint)y);
if (x.data.length < 2)
return BigUint(ZERO);
uint hi = cast(uint)(y >>> 32);
uint lo = cast(uint)(y & 0xFFFF_FFFF);
immutable uint[2] z = [lo, hi];
BigDigit[] result = new BigDigit[x.data.length - z.length + 1];
divModInternal(result, null, x.data, z[]);
return BigUint(removeLeadingZeros(assumeUnique(result)));
}

// return x % y
static uint modInt(T)(BigUint x, T y_) pure if ( is(Unqual!T == uint) )
{
Expand Down

0 comments on commit 5862d71

Please sign in to comment.