blob: 627d15c04698d555b9f7d683461dfcf48c333caf [file] [log] [blame]
pure @safe unittest
{
import std.bigint;
ubyte[] magnitude = [1, 2, 3, 4, 5, 6];
auto b1 = BigInt(false, magnitude);
assert(cast(long) b1 == 0x01_02_03_04_05_06L);
auto b2 = BigInt(true, magnitude);
assert(cast(long) b2 == -0x01_02_03_04_05_06L);
}
@safe unittest
{
import std.bigint;
ulong data = 1_000_000_000_000;
auto bigData = BigInt(data);
assert(bigData == BigInt("1_000_000_000_000"));
}
@safe unittest
{
import std.bigint;
const(BigInt) b1 = BigInt("1_234_567_890");
BigInt b2 = BigInt(b1);
assert(b2 == BigInt("1_234_567_890"));
}
@safe unittest
{
import std.bigint;
auto b = BigInt("123");
b = 456;
assert(b == BigInt("456"));
}
@safe unittest
{
import std.bigint;
auto b1 = BigInt("123");
auto b2 = BigInt("456");
b2 = b1;
assert(b2 == BigInt("123"));
}
@safe unittest
{
import std.bigint;
auto b = BigInt("1_000_000_000");
b += 12345;
assert(b == BigInt("1_000_012_345"));
b /= 5;
assert(b == BigInt("200_002_469"));
}
@safe unittest
{
import std.bigint;
auto x = BigInt("123");
auto y = BigInt("321");
x += y;
assert(x == BigInt("444"));
}
@safe unittest
{
import std.bigint;
auto x = BigInt("123");
auto y = BigInt("456");
BigInt z = x * y;
assert(z == BigInt("56088"));
}
@safe unittest
{
import std.bigint;
auto x = BigInt("123");
x *= 300;
assert(x == BigInt("36900"));
}
@safe unittest
{
import std.bigint;
auto x = BigInt("1_000_000_500");
long l = 1_000_000L;
ulong ul = 2_000_000UL;
int i = 500_000;
short s = 30_000;
assert(is(typeof(x % l) == long) && x % l == 500L);
assert(is(typeof(x % ul) == BigInt) && x % ul == BigInt(500));
assert(is(typeof(x % i) == int) && x % i == 500);
assert(is(typeof(x % s) == int) && x % s == 10500);
}
@safe unittest
{
import std.bigint;
auto x = BigInt("100");
BigInt y = 123 + x;
assert(y == BigInt("223"));
BigInt z = 123 - x;
assert(z == BigInt("23"));
// Dividing a built-in integer type by BigInt always results in
// something that fits in a built-in type, so the built-in type is
// returned, not BigInt.
assert(is(typeof(1000 / x) == int));
assert(1000 / x == 10);
}
@safe unittest
{
import std.bigint;
auto x = BigInt("1234");
assert(-x == BigInt("-1234"));
++x;
assert(x == BigInt("1235"));
}
@safe unittest
{
import std.bigint;
// Note that when comparing a BigInt to a float or double the
// full precision of the BigInt is always considered, unlike
// when comparing an int to a float or a long to a double.
assert(BigInt(123456789) != cast(float) 123456789);
}
@safe unittest
{
import std.bigint;
// Non-zero values are regarded as true
auto x = BigInt("1");
auto y = BigInt("10");
assert(x);
assert(y);
// Zero value is regarded as false
auto z = BigInt("0");
assert(!z);
}
@safe unittest
{
import std.bigint;
import std.conv : to, ConvOverflowException;
import std.exception : assertThrown;
assert(BigInt("0").to!int == 0);
assert(BigInt("0").to!ubyte == 0);
assert(BigInt("255").to!ubyte == 255);
assertThrown!ConvOverflowException(BigInt("256").to!ubyte);
assertThrown!ConvOverflowException(BigInt("-1").to!ubyte);
}
@system unittest
{
import std.bigint;
assert(cast(float) BigInt("35540592535949172786332045140593475584")
== 35540592535949172786332045140593475584.0f);
assert(cast(double) BigInt("35540601499647381470685035515422441472")
== 35540601499647381470685035515422441472.0);
assert(cast(real) BigInt("35540601499647381470685035515422441472")
== 35540601499647381470685035515422441472.0L);
assert(cast(float) BigInt("-0x1345_6780_0000_0000_0000_0000_0000") == -0x1.3456_78p+108f );
assert(cast(double) BigInt("-0x1345_678a_bcde_f000_0000_0000_0000") == -0x1.3456_78ab_cdefp+108 );
assert(cast(real) BigInt("-0x1345_678a_bcde_f000_0000_0000_0000") == -0x1.3456_78ab_cdefp+108L);
}
@system unittest
{
import std.bigint;
// BigInts whose values cannot be exactly represented as float/double/real
// are rounded when cast to float/double/real. When cast to float or
// double or 64-bit real the rounding is strictly defined. When cast
// to extended-precision real the rounding rules vary by environment.
// BigInts that fall somewhere between two non-infinite floats/doubles
// are rounded to the closer value when cast to float/double.
assert(cast(float) BigInt(0x1aaa_aae7) == 0x1.aaa_aaep+28f);
assert(cast(float) BigInt(0x1aaa_aaff) == 0x1.aaa_ab0p+28f);
assert(cast(float) BigInt(-0x1aaa_aae7) == -0x1.aaaaaep+28f);
assert(cast(float) BigInt(-0x1aaa_aaff) == -0x1.aaaab0p+28f);
assert(cast(double) BigInt(0x1aaa_aaaa_aaaa_aa77) == 0x1.aaa_aaaa_aaaa_aa00p+60);
assert(cast(double) BigInt(0x1aaa_aaaa_aaaa_aaff) == 0x1.aaa_aaaa_aaaa_ab00p+60);
assert(cast(double) BigInt(-0x1aaa_aaaa_aaaa_aa77) == -0x1.aaa_aaaa_aaaa_aa00p+60);
assert(cast(double) BigInt(-0x1aaa_aaaa_aaaa_aaff) == -0x1.aaa_aaaa_aaaa_ab00p+60);
// BigInts that fall exactly between two non-infinite floats/doubles
// are rounded away from zero when cast to float/double. (Note that
// in most environments this is NOT the same rounding rule rule used
// when casting int/long to float/double.)
assert(cast(float) BigInt(0x1aaa_aaf0) == 0x1.aaa_ab0p+28f);
assert(cast(float) BigInt(-0x1aaa_aaf0) == -0x1.aaaab0p+28f);
assert(cast(double) BigInt(0x1aaa_aaaa_aaaa_aa80) == 0x1.aaa_aaaa_aaaa_ab00p+60);
assert(cast(double) BigInt(-0x1aaa_aaaa_aaaa_aa80) == -0x1.aaa_aaaa_aaaa_ab00p+60);
// BigInts that are bounded on one side by the largest positive or
// most negative finite float/double and on the other side by infinity
// or -infinity are rounded as if in place of infinity was the value
// `2^^(T.max_exp)` when cast to float/double.
assert(cast(float) BigInt("999_999_999_999_999_999_999_999_999_999_999_999_999") == float.infinity);
assert(cast(float) BigInt("-999_999_999_999_999_999_999_999_999_999_999_999_999") == -float.infinity);
assert(cast(double) BigInt("999_999_999_999_999_999_999_999_999_999_999_999_999") < double.infinity);
assert(cast(real) BigInt("999_999_999_999_999_999_999_999_999_999_999_999_999") < real.infinity);
}
@safe unittest
{
import std.bigint;
const(BigInt) x = BigInt("123");
BigInt y = cast() x; // cast away const
assert(y == x);
}
@safe unittest
{
import std.bigint;
auto x = BigInt("100");
auto y = BigInt("10");
int z = 50;
const int w = 200;
assert(y < x);
assert(x > z);
assert(z > y);
assert(x < w);
}
@safe unittest
{
import std.bigint;
auto x = BigInt("0x1abc_de80_0000_0000_0000_0000_0000_0000");
BigInt y = x - 1;
BigInt z = x + 1;
double d = 0x1.abcde8p124;
assert(y < d);
assert(z > d);
assert(x >= d && x <= d);
// Note that when comparing a BigInt to a float or double the
// full precision of the BigInt is always considered, unlike
// when comparing an int to a float or a long to a double.
assert(BigInt(123456789) < cast(float) 123456789);
}
@safe unittest
{
import std.bigint;
auto b = BigInt("12345");
long l = b.toLong();
assert(l == 12345);
}
@safe unittest
{
import std.bigint;
auto big = BigInt("5_000_000");
auto i = big.toInt();
assert(i == 5_000_000);
// Numbers that are too big to fit into an int will be clamped to int.max.
auto tooBig = BigInt("5_000_000_000");
i = tooBig.toInt();
assert(i == int.max);
}
@safe unittest
{
import std.bigint;
import std.format : format;
auto x = BigInt("1_000_000");
x *= 12345;
assert(format("%d", x) == "12345000000");
assert(format("%x", x) == "2_dfd1c040");
assert(format("%X", x) == "2_DFD1C040");
assert(format("%o", x) == "133764340100");
}
@safe pure unittest
{
import std.bigint;
string[BigInt] aa;
aa[BigInt(123)] = "abc";
aa[BigInt(456)] = "def";
assert(aa[BigInt(123)] == "abc");
assert(aa[BigInt(456)] == "def");
}
@safe pure unittest
{
import std.bigint;
auto a = BigInt("1000");
assert(a.ulongLength() == 1);
assert(a.getDigit(0) == 1000);
assert(a.uintLength() == 1);
assert(a.getDigit!uint(0) == 1000);
auto b = BigInt("2_000_000_000_000_000_000_000_000_000");
assert(b.ulongLength() == 2);
assert(b.getDigit(0) == 4584946418820579328);
assert(b.getDigit(1) == 108420217);
assert(b.uintLength() == 3);
assert(b.getDigit!uint(0) == 3489660928);
assert(b.getDigit!uint(1) == 1067516025);
assert(b.getDigit!uint(2) == 108420217);
}
@safe unittest
{
import std.bigint;
BigInt a = "9588669891916142";
BigInt b = "7452469135154800";
auto c = a * b;
assert(c == BigInt("71459266416693160362545788781600"));
auto d = b * a;
assert(d == BigInt("71459266416693160362545788781600"));
assert(d == c);
d = c * BigInt("794628672112");
assert(d == BigInt("56783581982794522489042432639320434378739200"));
auto e = c + d;
assert(e == BigInt("56783581982865981755459125799682980167520800"));
auto f = d + c;
assert(f == e);
auto g = f - c;
assert(g == d);
g = f - d;
assert(g == c);
e = 12345678;
g = c + e;
auto h = g / b;
auto i = g % b;
assert(h == a);
assert(i == e);
BigInt j = "-0x9A56_57f4_7B83_AB78";
BigInt k = j;
j ^^= 11;
assert(k ^^ 11 == j);
}
@safe pure unittest
{
import std.bigint;
auto x = BigInt("123");
x *= 1000;
x += 456;
auto xstr = x.toDecimalString();
assert(xstr == "123456");
}
@safe unittest
{
import std.bigint;
auto x = BigInt("123");
x *= 1000;
x += 456;
auto xstr = x.toHex();
assert(xstr == "1E240");
}
nothrow pure @safe unittest
{
import std.bigint;
assert((-1).absUnsign == 1);
assert(1.absUnsign == 1);
}
@safe pure nothrow unittest
{
import std.bigint;
auto a = BigInt(123);
auto b = BigInt(25);
BigInt q, r;
divMod(a, b, q, r);
assert(q == 4);
assert(r == 23);
assert(q * b + r == a);
}
@safe unittest
{
import std.bigint;
BigInt base = BigInt("123456789012345678901234567890");
BigInt exponent = BigInt("1234567890123456789012345678901234567");
BigInt modulus = BigInt("1234567");
BigInt result = powmod(base, exponent, modulus);
assert(result == 359079);
}