zig/lib/std/math/big/int_test.zig
Andrew Kelley 8766821157 rework std.math.big.Int
Now there are 3 types:
 * std.math.big.int.Const
   - the memory is immutable, only stores limbs and is_positive
   - all methods operating on constant data go here
 * std.math.big.int.Mutable
   - the memory is mutable, stores capacity in addition to limbs and
     is_positive
   - methods here have some Mutable parameters and some Const
     parameters. These methods expect callers to pre-calculate the
     amount of resources required, and asserts that the resources are
     available.
 * std.math.big.int.Managed
   - the memory is mutable and additionally stores an allocator.
   - methods here perform the resource calculations for the programmer.
   - this is the high level abstraction from before

Each of these 3 types can be converted to the other ones.

You can see the use case for this in the self-hosted compiler, where we
only store limbs, and construct the big ints as needed.

This gets rid of the hack where the allocator was optional and the
notion of "fixed" versions of the struct. Such things are now modeled
with the `big.int.Const` type.
2020-05-01 06:47:56 -04:00

1456 lines
44 KiB
Zig

const std = @import("../../std.zig");
const mem = std.mem;
const testing = std.testing;
const Managed = std.math.big.int.Managed;
const Limb = std.math.big.Limb;
const DoubleLimb = std.math.big.DoubleLimb;
const maxInt = std.math.maxInt;
const minInt = std.math.minInt;
// NOTE: All the following tests assume the max machine-word will be 64-bit.
//
// They will still run on larger than this and should pass, but the multi-limb code-paths
// may be untested in some cases.
test "big.int comptime_int set" {
comptime var s = 0xefffffff00000001eeeeeeefaaaaaaab;
var a = try Managed.initSet(testing.allocator, s);
defer a.deinit();
const s_limb_count = 128 / Limb.bit_count;
comptime var i: usize = 0;
inline while (i < s_limb_count) : (i += 1) {
const result = @as(Limb, s & maxInt(Limb));
s >>= Limb.bit_count / 2;
s >>= Limb.bit_count / 2;
testing.expect(a.limbs[i] == result);
}
}
test "big.int comptime_int set negative" {
var a = try Managed.initSet(testing.allocator, -10);
defer a.deinit();
testing.expect(a.limbs[0] == 10);
testing.expect(a.isPositive() == false);
}
test "big.int int set unaligned small" {
var a = try Managed.initSet(testing.allocator, @as(u7, 45));
defer a.deinit();
testing.expect(a.limbs[0] == 45);
testing.expect(a.isPositive() == true);
}
test "big.int comptime_int to" {
var a = try Managed.initSet(testing.allocator, 0xefffffff00000001eeeeeeefaaaaaaab);
defer a.deinit();
testing.expect((try a.to(u128)) == 0xefffffff00000001eeeeeeefaaaaaaab);
}
test "big.int sub-limb to" {
var a = try Managed.initSet(testing.allocator, 10);
defer a.deinit();
testing.expect((try a.to(u8)) == 10);
}
test "big.int to target too small error" {
var a = try Managed.initSet(testing.allocator, 0xffffffff);
defer a.deinit();
testing.expectError(error.TargetTooSmall, a.to(u8));
}
test "big.int normalize" {
var a = try Managed.init(testing.allocator);
defer a.deinit();
try a.ensureCapacity(8);
a.limbs[0] = 1;
a.limbs[1] = 2;
a.limbs[2] = 3;
a.limbs[3] = 0;
a.normalize(4);
testing.expect(a.len() == 3);
a.limbs[0] = 1;
a.limbs[1] = 2;
a.limbs[2] = 3;
a.normalize(3);
testing.expect(a.len() == 3);
a.limbs[0] = 0;
a.limbs[1] = 0;
a.normalize(2);
testing.expect(a.len() == 1);
a.limbs[0] = 0;
a.normalize(1);
testing.expect(a.len() == 1);
}
test "big.int normalize multi" {
var a = try Managed.init(testing.allocator);
defer a.deinit();
try a.ensureCapacity(8);
a.limbs[0] = 1;
a.limbs[1] = 2;
a.limbs[2] = 0;
a.limbs[3] = 0;
a.normalize(4);
testing.expect(a.len() == 2);
a.limbs[0] = 1;
a.limbs[1] = 2;
a.limbs[2] = 3;
a.normalize(3);
testing.expect(a.len() == 3);
a.limbs[0] = 0;
a.limbs[1] = 0;
a.limbs[2] = 0;
a.limbs[3] = 0;
a.normalize(4);
testing.expect(a.len() == 1);
a.limbs[0] = 0;
a.normalize(1);
testing.expect(a.len() == 1);
}
test "big.int parity" {
var a = try Managed.init(testing.allocator);
defer a.deinit();
try a.set(0);
testing.expect(a.isEven());
testing.expect(!a.isOdd());
try a.set(7);
testing.expect(!a.isEven());
testing.expect(a.isOdd());
}
test "big.int bitcount + sizeInBaseUpperBound" {
var a = try Managed.init(testing.allocator);
defer a.deinit();
try a.set(0b100);
testing.expect(a.bitCountAbs() == 3);
testing.expect(a.sizeInBaseUpperBound(2) >= 3);
testing.expect(a.sizeInBaseUpperBound(10) >= 1);
a.negate();
testing.expect(a.bitCountAbs() == 3);
testing.expect(a.sizeInBaseUpperBound(2) >= 4);
testing.expect(a.sizeInBaseUpperBound(10) >= 2);
try a.set(0xffffffff);
testing.expect(a.bitCountAbs() == 32);
testing.expect(a.sizeInBaseUpperBound(2) >= 32);
testing.expect(a.sizeInBaseUpperBound(10) >= 10);
try a.shiftLeft(a, 5000);
testing.expect(a.bitCountAbs() == 5032);
testing.expect(a.sizeInBaseUpperBound(2) >= 5032);
a.setSign(false);
testing.expect(a.bitCountAbs() == 5032);
testing.expect(a.sizeInBaseUpperBound(2) >= 5033);
}
test "big.int bitcount/to" {
var a = try Managed.init(testing.allocator);
defer a.deinit();
try a.set(0);
testing.expect(a.bitCountTwosComp() == 0);
testing.expect((try a.to(u0)) == 0);
testing.expect((try a.to(i0)) == 0);
try a.set(-1);
testing.expect(a.bitCountTwosComp() == 1);
testing.expect((try a.to(i1)) == -1);
try a.set(-8);
testing.expect(a.bitCountTwosComp() == 4);
testing.expect((try a.to(i4)) == -8);
try a.set(127);
testing.expect(a.bitCountTwosComp() == 7);
testing.expect((try a.to(u7)) == 127);
try a.set(-128);
testing.expect(a.bitCountTwosComp() == 8);
testing.expect((try a.to(i8)) == -128);
try a.set(-129);
testing.expect(a.bitCountTwosComp() == 9);
testing.expect((try a.to(i9)) == -129);
}
test "big.int fits" {
var a = try Managed.init(testing.allocator);
defer a.deinit();
try a.set(0);
testing.expect(a.fits(u0));
testing.expect(a.fits(i0));
try a.set(255);
testing.expect(!a.fits(u0));
testing.expect(!a.fits(u1));
testing.expect(!a.fits(i8));
testing.expect(a.fits(u8));
testing.expect(a.fits(u9));
testing.expect(a.fits(i9));
try a.set(-128);
testing.expect(!a.fits(i7));
testing.expect(a.fits(i8));
testing.expect(a.fits(i9));
testing.expect(!a.fits(u9));
try a.set(0x1ffffffffeeeeeeee);
testing.expect(!a.fits(u32));
testing.expect(!a.fits(u64));
testing.expect(a.fits(u65));
}
test "big.int string set" {
var a = try Managed.init(testing.allocator);
defer a.deinit();
try a.setString(10, "120317241209124781241290847124");
testing.expect((try a.to(u128)) == 120317241209124781241290847124);
}
test "big.int string negative" {
var a = try Managed.init(testing.allocator);
defer a.deinit();
try a.setString(10, "-1023");
testing.expect((try a.to(i32)) == -1023);
}
test "big.int string set number with underscores" {
var a = try Managed.init(testing.allocator);
defer a.deinit();
try a.setString(10, "__1_2_0_3_1_7_2_4_1_2_0_____9_1__2__4_7_8_1_2_4_1_2_9_0_8_4_7_1_2_4___");
testing.expect((try a.to(u128)) == 120317241209124781241290847124);
}
test "big.int string set case insensitive number" {
var a = try Managed.init(testing.allocator);
defer a.deinit();
try a.setString(16, "aB_cD_eF");
testing.expect((try a.to(u32)) == 0xabcdef);
}
test "big.int string set bad char error" {
var a = try Managed.init(testing.allocator);
defer a.deinit();
testing.expectError(error.InvalidCharacter, a.setString(10, "x"));
}
test "big.int string set bad base error" {
var a = try Managed.init(testing.allocator);
defer a.deinit();
testing.expectError(error.InvalidBase, a.setString(45, "10"));
}
test "big.int string to" {
var a = try Managed.initSet(testing.allocator, 120317241209124781241290847124);
defer a.deinit();
const as = try a.toString(testing.allocator, 10, false);
defer testing.allocator.free(as);
const es = "120317241209124781241290847124";
testing.expect(mem.eql(u8, as, es));
}
test "big.int string to base base error" {
var a = try Managed.initSet(testing.allocator, 0xffffffff);
defer a.deinit();
testing.expectError(error.InvalidBase, a.toString(testing.allocator, 45, false));
}
test "big.int string to base 2" {
var a = try Managed.initSet(testing.allocator, -0b1011);
defer a.deinit();
const as = try a.toString(testing.allocator, 2, false);
defer testing.allocator.free(as);
const es = "-1011";
testing.expect(mem.eql(u8, as, es));
}
test "big.int string to base 16" {
var a = try Managed.initSet(testing.allocator, 0xefffffff00000001eeeeeeefaaaaaaab);
defer a.deinit();
const as = try a.toString(testing.allocator, 16, false);
defer testing.allocator.free(as);
const es = "efffffff00000001eeeeeeefaaaaaaab";
testing.expect(mem.eql(u8, as, es));
}
test "big.int neg string to" {
var a = try Managed.initSet(testing.allocator, -123907434);
defer a.deinit();
const as = try a.toString(testing.allocator, 10, false);
defer testing.allocator.free(as);
const es = "-123907434";
testing.expect(mem.eql(u8, as, es));
}
test "big.int zero string to" {
var a = try Managed.initSet(testing.allocator, 0);
defer a.deinit();
const as = try a.toString(testing.allocator, 10, false);
defer testing.allocator.free(as);
const es = "0";
testing.expect(mem.eql(u8, as, es));
}
test "big.int clone" {
var a = try Managed.initSet(testing.allocator, 1234);
defer a.deinit();
var b = try a.clone();
defer b.deinit();
testing.expect((try a.to(u32)) == 1234);
testing.expect((try b.to(u32)) == 1234);
try a.set(77);
testing.expect((try a.to(u32)) == 77);
testing.expect((try b.to(u32)) == 1234);
}
test "big.int swap" {
var a = try Managed.initSet(testing.allocator, 1234);
defer a.deinit();
var b = try Managed.initSet(testing.allocator, 5678);
defer b.deinit();
testing.expect((try a.to(u32)) == 1234);
testing.expect((try b.to(u32)) == 5678);
a.swap(&b);
testing.expect((try a.to(u32)) == 5678);
testing.expect((try b.to(u32)) == 1234);
}
test "big.int to negative" {
var a = try Managed.initSet(testing.allocator, -10);
defer a.deinit();
testing.expect((try a.to(i32)) == -10);
}
test "big.int compare" {
var a = try Managed.initSet(testing.allocator, -11);
defer a.deinit();
var b = try Managed.initSet(testing.allocator, 10);
defer b.deinit();
testing.expect(a.orderAbs(b) == .gt);
testing.expect(a.order(b) == .lt);
}
test "big.int compare similar" {
var a = try Managed.initSet(testing.allocator, 0xffffffffeeeeeeeeffffffffeeeeeeee);
defer a.deinit();
var b = try Managed.initSet(testing.allocator, 0xffffffffeeeeeeeeffffffffeeeeeeef);
defer b.deinit();
testing.expect(a.orderAbs(b) == .lt);
testing.expect(b.orderAbs(a) == .gt);
}
test "big.int compare different limb size" {
var a = try Managed.initSet(testing.allocator, maxInt(Limb) + 1);
defer a.deinit();
var b = try Managed.initSet(testing.allocator, 1);
defer b.deinit();
testing.expect(a.orderAbs(b) == .gt);
testing.expect(b.orderAbs(a) == .lt);
}
test "big.int compare multi-limb" {
var a = try Managed.initSet(testing.allocator, -0x7777777799999999ffffeeeeffffeeeeffffeeeef);
defer a.deinit();
var b = try Managed.initSet(testing.allocator, 0x7777777799999999ffffeeeeffffeeeeffffeeeee);
defer b.deinit();
testing.expect(a.orderAbs(b) == .gt);
testing.expect(a.order(b) == .lt);
}
test "big.int equality" {
var a = try Managed.initSet(testing.allocator, 0xffffffff1);
defer a.deinit();
var b = try Managed.initSet(testing.allocator, -0xffffffff1);
defer b.deinit();
testing.expect(a.eqAbs(b));
testing.expect(!a.eq(b));
}
test "big.int abs" {
var a = try Managed.initSet(testing.allocator, -5);
defer a.deinit();
a.abs();
testing.expect((try a.to(u32)) == 5);
a.abs();
testing.expect((try a.to(u32)) == 5);
}
test "big.int negate" {
var a = try Managed.initSet(testing.allocator, 5);
defer a.deinit();
a.negate();
testing.expect((try a.to(i32)) == -5);
a.negate();
testing.expect((try a.to(i32)) == 5);
}
test "big.int add single-single" {
var a = try Managed.initSet(testing.allocator, 50);
defer a.deinit();
var b = try Managed.initSet(testing.allocator, 5);
defer b.deinit();
var c = try Managed.init(testing.allocator);
defer c.deinit();
try c.add(a.toConst(), b.toConst());
testing.expect((try c.to(u32)) == 55);
}
test "big.int add multi-single" {
var a = try Managed.initSet(testing.allocator, maxInt(Limb) + 1);
defer a.deinit();
var b = try Managed.initSet(testing.allocator, 1);
defer b.deinit();
var c = try Managed.init(testing.allocator);
defer c.deinit();
try c.add(a.toConst(), b.toConst());
testing.expect((try c.to(DoubleLimb)) == maxInt(Limb) + 2);
try c.add(b.toConst(), a.toConst());
testing.expect((try c.to(DoubleLimb)) == maxInt(Limb) + 2);
}
test "big.int add multi-multi" {
const op1 = 0xefefefef7f7f7f7f;
const op2 = 0xfefefefe9f9f9f9f;
var a = try Managed.initSet(testing.allocator, op1);
defer a.deinit();
var b = try Managed.initSet(testing.allocator, op2);
defer b.deinit();
var c = try Managed.init(testing.allocator);
defer c.deinit();
try c.add(a.toConst(), b.toConst());
testing.expect((try c.to(u128)) == op1 + op2);
}
test "big.int add zero-zero" {
var a = try Managed.initSet(testing.allocator, 0);
defer a.deinit();
var b = try Managed.initSet(testing.allocator, 0);
defer b.deinit();
var c = try Managed.init(testing.allocator);
defer c.deinit();
try c.add(a.toConst(), b.toConst());
testing.expect((try c.to(u32)) == 0);
}
test "big.int add alias multi-limb nonzero-zero" {
const op1 = 0xffffffff777777771;
var a = try Managed.initSet(testing.allocator, op1);
defer a.deinit();
var b = try Managed.initSet(testing.allocator, 0);
defer b.deinit();
try a.add(a.toConst(), b.toConst());
testing.expect((try a.to(u128)) == op1);
}
test "big.int add sign" {
var a = try Managed.init(testing.allocator);
defer a.deinit();
var one = try Managed.initSet(testing.allocator, 1);
defer one.deinit();
var two = try Managed.initSet(testing.allocator, 2);
defer two.deinit();
var neg_one = try Managed.initSet(testing.allocator, -1);
defer neg_one.deinit();
var neg_two = try Managed.initSet(testing.allocator, -2);
defer neg_two.deinit();
try a.add(one.toConst(), two.toConst());
testing.expect((try a.to(i32)) == 3);
try a.add(neg_one.toConst(), two.toConst());
testing.expect((try a.to(i32)) == 1);
try a.add(one.toConst(), neg_two.toConst());
testing.expect((try a.to(i32)) == -1);
try a.add(neg_one.toConst(), neg_two.toConst());
testing.expect((try a.to(i32)) == -3);
}
test "big.int sub single-single" {
var a = try Managed.initSet(testing.allocator, 50);
defer a.deinit();
var b = try Managed.initSet(testing.allocator, 5);
defer b.deinit();
var c = try Managed.init(testing.allocator);
defer c.deinit();
try c.sub(a.toConst(), b.toConst());
testing.expect((try c.to(u32)) == 45);
}
test "big.int sub multi-single" {
var a = try Managed.initSet(testing.allocator, maxInt(Limb) + 1);
defer a.deinit();
var b = try Managed.initSet(testing.allocator, 1);
defer b.deinit();
var c = try Managed.init(testing.allocator);
defer c.deinit();
try c.sub(a.toConst(), b.toConst());
testing.expect((try c.to(Limb)) == maxInt(Limb));
}
test "big.int sub multi-multi" {
const op1 = 0xefefefefefefefefefefefef;
const op2 = 0xabababababababababababab;
var a = try Managed.initSet(testing.allocator, op1);
defer a.deinit();
var b = try Managed.initSet(testing.allocator, op2);
defer b.deinit();
var c = try Managed.init(testing.allocator);
defer c.deinit();
try c.sub(a.toConst(), b.toConst());
testing.expect((try c.to(u128)) == op1 - op2);
}
test "big.int sub equal" {
var a = try Managed.initSet(testing.allocator, 0x11efefefefefefefefefefefef);
defer a.deinit();
var b = try Managed.initSet(testing.allocator, 0x11efefefefefefefefefefefef);
defer b.deinit();
var c = try Managed.init(testing.allocator);
defer c.deinit();
try c.sub(a.toConst(), b.toConst());
testing.expect((try c.to(u32)) == 0);
}
test "big.int sub sign" {
var a = try Managed.init(testing.allocator);
defer a.deinit();
var one = try Managed.initSet(testing.allocator, 1);
defer one.deinit();
var two = try Managed.initSet(testing.allocator, 2);
defer two.deinit();
var neg_one = try Managed.initSet(testing.allocator, -1);
defer neg_one.deinit();
var neg_two = try Managed.initSet(testing.allocator, -2);
defer neg_two.deinit();
try a.sub(one.toConst(), two.toConst());
testing.expect((try a.to(i32)) == -1);
try a.sub(neg_one.toConst(), two.toConst());
testing.expect((try a.to(i32)) == -3);
try a.sub(one.toConst(), neg_two.toConst());
testing.expect((try a.to(i32)) == 3);
try a.sub(neg_one.toConst(), neg_two.toConst());
testing.expect((try a.to(i32)) == 1);
try a.sub(neg_two.toConst(), neg_one.toConst());
testing.expect((try a.to(i32)) == -1);
}
test "big.int mul single-single" {
var a = try Managed.initSet(testing.allocator, 50);
defer a.deinit();
var b = try Managed.initSet(testing.allocator, 5);
defer b.deinit();
var c = try Managed.init(testing.allocator);
defer c.deinit();
try c.mul(a.toConst(), b.toConst());
testing.expect((try c.to(u64)) == 250);
}
test "big.int mul multi-single" {
var a = try Managed.initSet(testing.allocator, maxInt(Limb));
defer a.deinit();
var b = try Managed.initSet(testing.allocator, 2);
defer b.deinit();
var c = try Managed.init(testing.allocator);
defer c.deinit();
try c.mul(a.toConst(), b.toConst());
testing.expect((try c.to(DoubleLimb)) == 2 * maxInt(Limb));
}
test "big.int mul multi-multi" {
const op1 = 0x998888efefefefefefefef;
const op2 = 0x333000abababababababab;
var a = try Managed.initSet(testing.allocator, op1);
defer a.deinit();
var b = try Managed.initSet(testing.allocator, op2);
defer b.deinit();
var c = try Managed.init(testing.allocator);
defer c.deinit();
try c.mul(a.toConst(), b.toConst());
testing.expect((try c.to(u256)) == op1 * op2);
}
test "big.int mul alias r with a" {
var a = try Managed.initSet(testing.allocator, maxInt(Limb));
defer a.deinit();
var b = try Managed.initSet(testing.allocator, 2);
defer b.deinit();
try a.mul(a.toConst(), b.toConst());
testing.expect((try a.to(DoubleLimb)) == 2 * maxInt(Limb));
}
test "big.int mul alias r with b" {
var a = try Managed.initSet(testing.allocator, maxInt(Limb));
defer a.deinit();
var b = try Managed.initSet(testing.allocator, 2);
defer b.deinit();
try a.mul(b.toConst(), a.toConst());
testing.expect((try a.to(DoubleLimb)) == 2 * maxInt(Limb));
}
test "big.int mul alias r with a and b" {
var a = try Managed.initSet(testing.allocator, maxInt(Limb));
defer a.deinit();
try a.mul(a.toConst(), a.toConst());
testing.expect((try a.to(DoubleLimb)) == maxInt(Limb) * maxInt(Limb));
}
test "big.int mul a*0" {
var a = try Managed.initSet(testing.allocator, 0xefefefefefefefef);
defer a.deinit();
var b = try Managed.initSet(testing.allocator, 0);
defer b.deinit();
var c = try Managed.init(testing.allocator);
defer c.deinit();
try c.mul(a.toConst(), b.toConst());
testing.expect((try c.to(u32)) == 0);
}
test "big.int mul 0*0" {
var a = try Managed.initSet(testing.allocator, 0);
defer a.deinit();
var b = try Managed.initSet(testing.allocator, 0);
defer b.deinit();
var c = try Managed.init(testing.allocator);
defer c.deinit();
try c.mul(a.toConst(), b.toConst());
testing.expect((try c.to(u32)) == 0);
}
test "big.int div single-single no rem" {
var a = try Managed.initSet(testing.allocator, 50);
defer a.deinit();
var b = try Managed.initSet(testing.allocator, 5);
defer b.deinit();
var q = try Managed.init(testing.allocator);
defer q.deinit();
var r = try Managed.init(testing.allocator);
defer r.deinit();
try Managed.divTrunc(&q, &r, a.toConst(), b.toConst());
testing.expect((try q.to(u32)) == 10);
testing.expect((try r.to(u32)) == 0);
}
test "big.int div single-single with rem" {
var a = try Managed.initSet(testing.allocator, 49);
defer a.deinit();
var b = try Managed.initSet(testing.allocator, 5);
defer b.deinit();
var q = try Managed.init(testing.allocator);
defer q.deinit();
var r = try Managed.init(testing.allocator);
defer r.deinit();
try Managed.divTrunc(&q, &r, a.toConst(), b.toConst());
testing.expect((try q.to(u32)) == 9);
testing.expect((try r.to(u32)) == 4);
}
test "big.int div multi-single no rem" {
const op1 = 0xffffeeeeddddcccc;
const op2 = 34;
var a = try Managed.initSet(testing.allocator, op1);
defer a.deinit();
var b = try Managed.initSet(testing.allocator, op2);
defer b.deinit();
var q = try Managed.init(testing.allocator);
defer q.deinit();
var r = try Managed.init(testing.allocator);
defer r.deinit();
try Managed.divTrunc(&q, &r, a.toConst(), b.toConst());
testing.expect((try q.to(u64)) == op1 / op2);
testing.expect((try r.to(u64)) == 0);
}
test "big.int div multi-single with rem" {
const op1 = 0xffffeeeeddddcccf;
const op2 = 34;
var a = try Managed.initSet(testing.allocator, op1);
defer a.deinit();
var b = try Managed.initSet(testing.allocator, op2);
defer b.deinit();
var q = try Managed.init(testing.allocator);
defer q.deinit();
var r = try Managed.init(testing.allocator);
defer r.deinit();
try Managed.divTrunc(&q, &r, a.toConst(), b.toConst());
testing.expect((try q.to(u64)) == op1 / op2);
testing.expect((try r.to(u64)) == 3);
}
test "big.int div multi>2-single" {
const op1 = 0xfefefefefefefefefefefefefefefefe;
const op2 = 0xefab8;
var a = try Managed.initSet(testing.allocator, op1);
defer a.deinit();
var b = try Managed.initSet(testing.allocator, op2);
defer b.deinit();
var q = try Managed.init(testing.allocator);
defer q.deinit();
var r = try Managed.init(testing.allocator);
defer r.deinit();
try Managed.divTrunc(&q, &r, a.toConst(), b.toConst());
testing.expect((try q.to(u128)) == op1 / op2);
testing.expect((try r.to(u32)) == 0x3e4e);
}
test "big.int div single-single q < r" {
var a = try Managed.initSet(testing.allocator, 0x0078f432);
defer a.deinit();
var b = try Managed.initSet(testing.allocator, 0x01000000);
defer b.deinit();
var q = try Managed.init(testing.allocator);
defer q.deinit();
var r = try Managed.init(testing.allocator);
defer r.deinit();
try Managed.divTrunc(&q, &r, a.toConst(), b.toConst());
testing.expect((try q.to(u64)) == 0);
testing.expect((try r.to(u64)) == 0x0078f432);
}
test "big.int div single-single q == r" {
var a = try Managed.initSet(testing.allocator, 10);
defer a.deinit();
var b = try Managed.initSet(testing.allocator, 10);
defer b.deinit();
var q = try Managed.init(testing.allocator);
defer q.deinit();
var r = try Managed.init(testing.allocator);
defer r.deinit();
try Managed.divTrunc(&q, &r, a.toConst(), b.toConst());
testing.expect((try q.to(u64)) == 1);
testing.expect((try r.to(u64)) == 0);
}
test "big.int div q=0 alias" {
var a = try Managed.initSet(testing.allocator, 3);
defer a.deinit();
var b = try Managed.initSet(testing.allocator, 10);
defer b.deinit();
try Managed.divTrunc(&a, &b, a.toConst(), b.toConst());
testing.expect((try a.to(u64)) == 0);
testing.expect((try b.to(u64)) == 3);
}
test "big.int div multi-multi q < r" {
const op1 = 0x1ffffffff0078f432;
const op2 = 0x1ffffffff01000000;
var a = try Managed.initSet(testing.allocator, op1);
defer a.deinit();
var b = try Managed.initSet(testing.allocator, op2);
defer b.deinit();
var q = try Managed.init(testing.allocator);
defer q.deinit();
var r = try Managed.init(testing.allocator);
defer r.deinit();
try Managed.divTrunc(&q, &r, a.toConst(), b.toConst());
testing.expect((try q.to(u128)) == 0);
testing.expect((try r.to(u128)) == op1);
}
test "big.int div trunc single-single +/+" {
const u: i32 = 5;
const v: i32 = 3;
var a = try Managed.initSet(testing.allocator, u);
defer a.deinit();
var b = try Managed.initSet(testing.allocator, v);
defer b.deinit();
var q = try Managed.init(testing.allocator);
defer q.deinit();
var r = try Managed.init(testing.allocator);
defer r.deinit();
try Managed.divTrunc(&q, &r, a.toConst(), b.toConst());
// n = q * d + r
// 5 = 1 * 3 + 2
const eq = @divTrunc(u, v);
const er = @mod(u, v);
testing.expect((try q.to(i32)) == eq);
testing.expect((try r.to(i32)) == er);
}
test "big.int div trunc single-single -/+" {
const u: i32 = -5;
const v: i32 = 3;
var a = try Managed.initSet(testing.allocator, u);
defer a.deinit();
var b = try Managed.initSet(testing.allocator, v);
defer b.deinit();
var q = try Managed.init(testing.allocator);
defer q.deinit();
var r = try Managed.init(testing.allocator);
defer r.deinit();
try Managed.divTrunc(&q, &r, a.toConst(), b.toConst());
// n = q * d + r
// -5 = 1 * -3 - 2
const eq = -1;
const er = -2;
testing.expect((try q.to(i32)) == eq);
testing.expect((try r.to(i32)) == er);
}
test "big.int div trunc single-single +/-" {
const u: i32 = 5;
const v: i32 = -3;
var a = try Managed.initSet(testing.allocator, u);
defer a.deinit();
var b = try Managed.initSet(testing.allocator, v);
defer b.deinit();
var q = try Managed.init(testing.allocator);
defer q.deinit();
var r = try Managed.init(testing.allocator);
defer r.deinit();
try Managed.divTrunc(&q, &r, a.toConst(), b.toConst());
// n = q * d + r
// 5 = -1 * -3 + 2
const eq = -1;
const er = 2;
testing.expect((try q.to(i32)) == eq);
testing.expect((try r.to(i32)) == er);
}
test "big.int div trunc single-single -/-" {
const u: i32 = -5;
const v: i32 = -3;
var a = try Managed.initSet(testing.allocator, u);
defer a.deinit();
var b = try Managed.initSet(testing.allocator, v);
defer b.deinit();
var q = try Managed.init(testing.allocator);
defer q.deinit();
var r = try Managed.init(testing.allocator);
defer r.deinit();
try Managed.divTrunc(&q, &r, a.toConst(), b.toConst());
// n = q * d + r
// -5 = 1 * -3 - 2
const eq = 1;
const er = -2;
testing.expect((try q.to(i32)) == eq);
testing.expect((try r.to(i32)) == er);
}
test "big.int div floor single-single +/+" {
const u: i32 = 5;
const v: i32 = 3;
var a = try Managed.initSet(testing.allocator, u);
defer a.deinit();
var b = try Managed.initSet(testing.allocator, v);
defer b.deinit();
var q = try Managed.init(testing.allocator);
defer q.deinit();
var r = try Managed.init(testing.allocator);
defer r.deinit();
try Managed.divFloor(&q, &r, a.toConst(), b.toConst());
// n = q * d + r
// 5 = 1 * 3 + 2
const eq = 1;
const er = 2;
testing.expect((try q.to(i32)) == eq);
testing.expect((try r.to(i32)) == er);
}
test "big.int div floor single-single -/+" {
const u: i32 = -5;
const v: i32 = 3;
var a = try Managed.initSet(testing.allocator, u);
defer a.deinit();
var b = try Managed.initSet(testing.allocator, v);
defer b.deinit();
var q = try Managed.init(testing.allocator);
defer q.deinit();
var r = try Managed.init(testing.allocator);
defer r.deinit();
try Managed.divFloor(&q, &r, a.toConst(), b.toConst());
// n = q * d + r
// -5 = -2 * 3 + 1
const eq = -2;
const er = 1;
testing.expect((try q.to(i32)) == eq);
testing.expect((try r.to(i32)) == er);
}
test "big.int div floor single-single +/-" {
const u: i32 = 5;
const v: i32 = -3;
var a = try Managed.initSet(testing.allocator, u);
defer a.deinit();
var b = try Managed.initSet(testing.allocator, v);
defer b.deinit();
var q = try Managed.init(testing.allocator);
defer q.deinit();
var r = try Managed.init(testing.allocator);
defer r.deinit();
try Managed.divFloor(&q, &r, a.toConst(), b.toConst());
// n = q * d + r
// 5 = -2 * -3 - 1
const eq = -2;
const er = -1;
testing.expect((try q.to(i32)) == eq);
testing.expect((try r.to(i32)) == er);
}
test "big.int div floor single-single -/-" {
const u: i32 = -5;
const v: i32 = -3;
var a = try Managed.initSet(testing.allocator, u);
defer a.deinit();
var b = try Managed.initSet(testing.allocator, v);
defer b.deinit();
var q = try Managed.init(testing.allocator);
defer q.deinit();
var r = try Managed.init(testing.allocator);
defer r.deinit();
try Managed.divFloor(&q, &r, a.toConst(), b.toConst());
// n = q * d + r
// -5 = 2 * -3 + 1
const eq = 1;
const er = -2;
testing.expect((try q.to(i32)) == eq);
testing.expect((try r.to(i32)) == er);
}
test "big.int div multi-multi with rem" {
var a = try Managed.initSet(testing.allocator, 0x8888999911110000ffffeeeeddddccccbbbbaaaa9999);
defer a.deinit();
var b = try Managed.initSet(testing.allocator, 0x99990000111122223333);
defer b.deinit();
var q = try Managed.init(testing.allocator);
defer q.deinit();
var r = try Managed.init(testing.allocator);
defer r.deinit();
try Managed.divTrunc(&q, &r, a.toConst(), b.toConst());
testing.expect((try q.to(u128)) == 0xe38f38e39161aaabd03f0f1b);
testing.expect((try r.to(u128)) == 0x28de0acacd806823638);
}
test "big.int div multi-multi no rem" {
var a = try Managed.initSet(testing.allocator, 0x8888999911110000ffffeeeedb4fec200ee3a4286361);
defer a.deinit();
var b = try Managed.initSet(testing.allocator, 0x99990000111122223333);
defer b.deinit();
var q = try Managed.init(testing.allocator);
defer q.deinit();
var r = try Managed.init(testing.allocator);
defer r.deinit();
try Managed.divTrunc(&q, &r, a.toConst(), b.toConst());
testing.expect((try q.to(u128)) == 0xe38f38e39161aaabd03f0f1b);
testing.expect((try r.to(u128)) == 0);
}
test "big.int div multi-multi (2 branch)" {
var a = try Managed.initSet(testing.allocator, 0x866666665555555588888887777777761111111111111111);
defer a.deinit();
var b = try Managed.initSet(testing.allocator, 0x86666666555555554444444433333333);
defer b.deinit();
var q = try Managed.init(testing.allocator);
defer q.deinit();
var r = try Managed.init(testing.allocator);
defer r.deinit();
try Managed.divTrunc(&q, &r, a.toConst(), b.toConst());
testing.expect((try q.to(u128)) == 0x10000000000000000);
testing.expect((try r.to(u128)) == 0x44444443444444431111111111111111);
}
test "big.int div multi-multi (3.1/3.3 branch)" {
var a = try Managed.initSet(testing.allocator, 0x11111111111111111111111111111111111111111111111111111111111111);
defer a.deinit();
var b = try Managed.initSet(testing.allocator, 0x1111111111111111111111111111111111111111171);
defer b.deinit();
var q = try Managed.init(testing.allocator);
defer q.deinit();
var r = try Managed.init(testing.allocator);
defer r.deinit();
try Managed.divTrunc(&q, &r, a.toConst(), b.toConst());
testing.expect((try q.to(u128)) == 0xfffffffffffffffffff);
testing.expect((try r.to(u256)) == 0x1111111111111111111110b12222222222222222282);
}
test "big.int div multi-single zero-limb trailing" {
var a = try Managed.initSet(testing.allocator, 0x60000000000000000000000000000000000000000000000000000000000000000);
defer a.deinit();
var b = try Managed.initSet(testing.allocator, 0x10000000000000000);
defer b.deinit();
var q = try Managed.init(testing.allocator);
defer q.deinit();
var r = try Managed.init(testing.allocator);
defer r.deinit();
try Managed.divTrunc(&q, &r, a.toConst(), b.toConst());
var expected = try Managed.initSet(testing.allocator, 0x6000000000000000000000000000000000000000000000000);
defer expected.deinit();
testing.expect(q.eq(expected));
testing.expect(r.eqZero());
}
test "big.int div multi-multi zero-limb trailing (with rem)" {
var a = try Managed.initSet(testing.allocator, 0x86666666555555558888888777777776111111111111111100000000000000000000000000000000);
defer a.deinit();
var b = try Managed.initSet(testing.allocator, 0x8666666655555555444444443333333300000000000000000000000000000000);
defer b.deinit();
var q = try Managed.init(testing.allocator);
defer q.deinit();
var r = try Managed.init(testing.allocator);
defer r.deinit();
try Managed.divTrunc(&q, &r, a.toConst(), b.toConst());
testing.expect((try q.to(u128)) == 0x10000000000000000);
const rs = try r.toString(testing.allocator, 16, false);
defer testing.allocator.free(rs);
testing.expect(std.mem.eql(u8, rs, "4444444344444443111111111111111100000000000000000000000000000000"));
}
test "big.int div multi-multi zero-limb trailing (with rem) and dividend zero-limb count > divisor zero-limb count" {
var a = try Managed.initSet(testing.allocator, 0x8666666655555555888888877777777611111111111111110000000000000000);
defer a.deinit();
var b = try Managed.initSet(testing.allocator, 0x8666666655555555444444443333333300000000000000000000000000000000);
defer b.deinit();
var q = try Managed.init(testing.allocator);
defer q.deinit();
var r = try Managed.init(testing.allocator);
defer r.deinit();
try Managed.divTrunc(&q, &r, a.toConst(), b.toConst());
testing.expect((try q.to(u128)) == 0x1);
const rs = try r.toString(testing.allocator, 16, false);
defer testing.allocator.free(rs);
testing.expect(std.mem.eql(u8, rs, "444444434444444311111111111111110000000000000000"));
}
test "big.int div multi-multi zero-limb trailing (with rem) and dividend zero-limb count < divisor zero-limb count" {
var a = try Managed.initSet(testing.allocator, 0x86666666555555558888888777777776111111111111111100000000000000000000000000000000);
defer a.deinit();
var b = try Managed.initSet(testing.allocator, 0x866666665555555544444444333333330000000000000000);
defer b.deinit();
var q = try Managed.init(testing.allocator);
defer q.deinit();
var r = try Managed.init(testing.allocator);
defer r.deinit();
try Managed.divTrunc(&q, &r, a.toConst(), b.toConst());
const qs = try q.toString(testing.allocator, 16, false);
defer testing.allocator.free(qs);
testing.expect(std.mem.eql(u8, qs, "10000000000000000820820803105186f"));
const rs = try r.toString(testing.allocator, 16, false);
defer testing.allocator.free(rs);
testing.expect(std.mem.eql(u8, rs, "4e11f2baa5896a321d463b543d0104e30000000000000000"));
}
test "big.int div multi-multi fuzz case #1" {
var a = try Managed.init(testing.allocator);
defer a.deinit();
var b = try Managed.init(testing.allocator);
defer b.deinit();
try a.setString(16, "ffffffffffffffffffffffffffffc00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000");
try b.setString(16, "3ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0000000000000000000000000000000000001ffffffffffffffffffffffffffffffffffffffffffffffffffc000000000000000000000000000000007fffffffffff");
var q = try Managed.init(testing.allocator);
defer q.deinit();
var r = try Managed.init(testing.allocator);
defer r.deinit();
try Managed.divTrunc(&q, &r, a.toConst(), b.toConst());
const qs = try q.toString(testing.allocator, 16, false);
defer testing.allocator.free(qs);
testing.expect(std.mem.eql(u8, qs, "3ffffffffffffffffffffffffffff0000000000000000000000000000000000001ffffffffffffffffffffffffffff7fffffffe000000000000000000000000000180000000000000000000003fffffbfffffffdfffffffffffffeffff800000100101000000100000000020003fffffdfbfffffe3ffffffffffffeffff7fffc00800a100000017ffe000002000400007efbfff7fe9f00000037ffff3fff7fffa004006100000009ffe00000190038200bf7d2ff7fefe80400060000f7d7f8fbf9401fe38e0403ffc0bdffffa51102c300d7be5ef9df4e5060007b0127ad3fa69f97d0f820b6605ff617ddf7f32ad7a05c0d03f2e7bc78a6000e087a8bbcdc59e07a5a079128a7861f553ddebed7e8e56701756f9ead39b48cd1b0831889ea6ec1fddf643d0565b075ff07e6caea4e2854ec9227fd635ed60a2f5eef2893052ffd54718fa08604acbf6a15e78a467c4a3c53c0278af06c4416573f925491b195e8fd79302cb1aaf7caf4ecfc9aec1254cc969786363ac729f914c6ddcc26738d6b0facd54eba026580aba2eb6482a088b0d224a8852420b91ec1"));
const rs = try r.toString(testing.allocator, 16, false);
defer testing.allocator.free(rs);
testing.expect(std.mem.eql(u8, rs, "310d1d4c414426b4836c2635bad1df3a424e50cbdd167ffccb4dfff57d36b4aae0d6ca0910698220171a0f3373c1060a046c2812f0027e321f72979daa5e7973214170d49e885de0c0ecc167837d44502430674a82522e5df6a0759548052420b91ec1"));
}
test "big.int div multi-multi fuzz case #2" {
var a = try Managed.init(testing.allocator);
defer a.deinit();
var b = try Managed.init(testing.allocator);
defer b.deinit();
try a.setString(16, "3ffffffffe00000000000000000000000000fffffffffffffffffffffffffffffffffffffffffffffffffffffffffe000000000000000000000000000000000000000000000000000000000000001fffffffffffffffff800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffc000000000000000000000000000000000000000000000000000000000000000");
try b.setString(16, "ffc0000000000000000000000000000000000000000000000000");
var q = try Managed.init(testing.allocator);
defer q.deinit();
var r = try Managed.init(testing.allocator);
defer r.deinit();
try Managed.divTrunc(&q, &r, a.toConst(), b.toConst());
const qs = try q.toString(testing.allocator, 16, false);
defer testing.allocator.free(qs);
testing.expect(std.mem.eql(u8, qs, "40100400fe3f8fe3f8fe3f8fe3f8fe3f8fe4f93e4f93e4f93e4f93e4f93e4f93e4f93e4f93e4f93e4f93e4f93e4f91e4791e4791e4791e4791e4791e4791e4791e4791e4791e4791e4791e4791e4992649926499264991e4791e4791e4791e4791e4791e4791e4791e4791e4791e4791e4791e4791e4791e4791e4791e4791e4791e4791e4791e4791e4791e4791e4791e4792e4b92e4b92e4b92e4b92a4a92a4a92a4"));
const rs = try r.toString(testing.allocator, 16, false);
defer testing.allocator.free(rs);
testing.expect(std.mem.eql(u8, rs, "a900000000000000000000000000000000000000000000000000"));
}
test "big.int shift-right single" {
var a = try Managed.initSet(testing.allocator, 0xffff0000);
defer a.deinit();
try a.shiftRight(a, 16);
testing.expect((try a.to(u32)) == 0xffff);
}
test "big.int shift-right multi" {
var a = try Managed.initSet(testing.allocator, 0xffff0000eeee1111dddd2222cccc3333);
defer a.deinit();
try a.shiftRight(a, 67);
testing.expect((try a.to(u64)) == 0x1fffe0001dddc222);
}
test "big.int shift-left single" {
var a = try Managed.initSet(testing.allocator, 0xffff);
defer a.deinit();
try a.shiftLeft(a, 16);
testing.expect((try a.to(u64)) == 0xffff0000);
}
test "big.int shift-left multi" {
var a = try Managed.initSet(testing.allocator, 0x1fffe0001dddc222);
defer a.deinit();
try a.shiftLeft(a, 67);
testing.expect((try a.to(u128)) == 0xffff0000eeee11100000000000000000);
}
test "big.int shift-right negative" {
var a = try Managed.init(testing.allocator);
defer a.deinit();
var arg = try Managed.initSet(testing.allocator, -20);
defer arg.deinit();
try a.shiftRight(arg, 2);
testing.expect((try a.to(i32)) == -20 >> 2);
var arg2 = try Managed.initSet(testing.allocator, -5);
defer arg2.deinit();
try a.shiftRight(arg2, 10);
testing.expect((try a.to(i32)) == -5 >> 10);
}
test "big.int shift-left negative" {
var a = try Managed.init(testing.allocator);
defer a.deinit();
var arg = try Managed.initSet(testing.allocator, -10);
defer arg.deinit();
try a.shiftRight(arg, 1232);
testing.expect((try a.to(i32)) == -10 >> 1232);
}
test "big.int bitwise and simple" {
var a = try Managed.initSet(testing.allocator, 0xffffffff11111111);
defer a.deinit();
var b = try Managed.initSet(testing.allocator, 0xeeeeeeee22222222);
defer b.deinit();
try a.bitAnd(a, b);
testing.expect((try a.to(u64)) == 0xeeeeeeee00000000);
}
test "big.int bitwise and multi-limb" {
var a = try Managed.initSet(testing.allocator, maxInt(Limb) + 1);
defer a.deinit();
var b = try Managed.initSet(testing.allocator, maxInt(Limb));
defer b.deinit();
try a.bitAnd(a, b);
testing.expect((try a.to(u128)) == 0);
}
test "big.int bitwise xor simple" {
var a = try Managed.initSet(testing.allocator, 0xffffffff11111111);
defer a.deinit();
var b = try Managed.initSet(testing.allocator, 0xeeeeeeee22222222);
defer b.deinit();
try a.bitXor(a, b);
testing.expect((try a.to(u64)) == 0x1111111133333333);
}
test "big.int bitwise xor multi-limb" {
var a = try Managed.initSet(testing.allocator, maxInt(Limb) + 1);
defer a.deinit();
var b = try Managed.initSet(testing.allocator, maxInt(Limb));
defer b.deinit();
try a.bitXor(a, b);
testing.expect((try a.to(DoubleLimb)) == (maxInt(Limb) + 1) ^ maxInt(Limb));
}
test "big.int bitwise or simple" {
var a = try Managed.initSet(testing.allocator, 0xffffffff11111111);
defer a.deinit();
var b = try Managed.initSet(testing.allocator, 0xeeeeeeee22222222);
defer b.deinit();
try a.bitOr(a, b);
testing.expect((try a.to(u64)) == 0xffffffff33333333);
}
test "big.int bitwise or multi-limb" {
var a = try Managed.initSet(testing.allocator, maxInt(Limb) + 1);
defer a.deinit();
var b = try Managed.initSet(testing.allocator, maxInt(Limb));
defer b.deinit();
try a.bitOr(a, b);
// TODO: big.int.cpp or is wrong on multi-limb.
testing.expect((try a.to(DoubleLimb)) == (maxInt(Limb) + 1) + maxInt(Limb));
}
test "big.int var args" {
var a = try Managed.initSet(testing.allocator, 5);
defer a.deinit();
var b = try Managed.initSet(testing.allocator, 6);
defer b.deinit();
try a.add(a.toConst(), b.toConst());
testing.expect((try a.to(u64)) == 11);
var c = try Managed.initSet(testing.allocator, 11);
defer c.deinit();
testing.expect(a.order(c) == .eq);
var d = try Managed.initSet(testing.allocator, 14);
defer d.deinit();
testing.expect(a.order(d) != .gt);
}
test "big.int gcd non-one small" {
var a = try Managed.initSet(testing.allocator, 17);
defer a.deinit();
var b = try Managed.initSet(testing.allocator, 97);
defer b.deinit();
var r = try Managed.init(testing.allocator);
defer r.deinit();
try r.gcd(a, b);
testing.expect((try r.to(u32)) == 1);
}
test "big.int gcd non-one small" {
var a = try Managed.initSet(testing.allocator, 4864);
defer a.deinit();
var b = try Managed.initSet(testing.allocator, 3458);
defer b.deinit();
var r = try Managed.init(testing.allocator);
defer r.deinit();
try r.gcd(a, b);
testing.expect((try r.to(u32)) == 38);
}
test "big.int gcd non-one large" {
var a = try Managed.initSet(testing.allocator, 0xffffffffffffffff);
defer a.deinit();
var b = try Managed.initSet(testing.allocator, 0xffffffffffffffff7777);
defer b.deinit();
var r = try Managed.init(testing.allocator);
defer r.deinit();
try r.gcd(a, b);
testing.expect((try r.to(u32)) == 4369);
}
test "big.int gcd large multi-limb result" {
var a = try Managed.initSet(testing.allocator, 0x12345678123456781234567812345678123456781234567812345678);
defer a.deinit();
var b = try Managed.initSet(testing.allocator, 0x12345671234567123456712345671234567123456712345671234567);
defer b.deinit();
var r = try Managed.init(testing.allocator);
defer r.deinit();
try r.gcd(a, b);
const answer = (try r.to(u256));
testing.expect(answer == 0xf000000ff00000fff0000ffff000fffff00ffffff1);
}
test "big.int gcd one large" {
var a = try Managed.initSet(testing.allocator, 1897056385327307);
defer a.deinit();
var b = try Managed.initSet(testing.allocator, 2251799813685248);
defer b.deinit();
var r = try Managed.init(testing.allocator);
defer r.deinit();
try r.gcd(a, b);
testing.expect((try r.to(u64)) == 1);
}