mirror of
https://github.com/ziglang/zig.git
synced 2025-12-06 06:13:07 +00:00
We already have a LICENSE file that covers the Zig Standard Library. We no longer need to remind everyone that the license is MIT in every single file. Previously this was introduced to clarify the situation for a fork of Zig that made Zig's LICENSE file harder to find, and replaced it with their own license that required annual payments to their company. However that fork now appears to be dead. So there is no need to reinforce the copyright notice in every single file.
1599 lines
50 KiB
Zig
1599 lines
50 KiB
Zig
const std = @import("../../std.zig");
|
|
const mem = std.mem;
|
|
const testing = std.testing;
|
|
const Managed = std.math.big.int.Managed;
|
|
const Mutable = std.math.big.int.Mutable;
|
|
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 / @typeInfo(Limb).Int.bits;
|
|
|
|
comptime var i: usize = 0;
|
|
inline while (i < s_limb_count) : (i += 1) {
|
|
const result = @as(Limb, s & maxInt(Limb));
|
|
s >>= @typeInfo(Limb).Int.bits / 2;
|
|
s >>= @typeInfo(Limb).Int.bits / 2;
|
|
try testing.expect(a.limbs[i] == result);
|
|
}
|
|
}
|
|
|
|
test "big.int comptime_int set negative" {
|
|
var a = try Managed.initSet(testing.allocator, -10);
|
|
defer a.deinit();
|
|
|
|
try testing.expect(a.limbs[0] == 10);
|
|
try 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();
|
|
|
|
try testing.expect(a.limbs[0] == 45);
|
|
try testing.expect(a.isPositive() == true);
|
|
}
|
|
|
|
test "big.int comptime_int to" {
|
|
var a = try Managed.initSet(testing.allocator, 0xefffffff00000001eeeeeeefaaaaaaab);
|
|
defer a.deinit();
|
|
|
|
try testing.expect((try a.to(u128)) == 0xefffffff00000001eeeeeeefaaaaaaab);
|
|
}
|
|
|
|
test "big.int sub-limb to" {
|
|
var a = try Managed.initSet(testing.allocator, 10);
|
|
defer a.deinit();
|
|
|
|
try 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();
|
|
|
|
try 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);
|
|
try testing.expect(a.len() == 3);
|
|
|
|
a.limbs[0] = 1;
|
|
a.limbs[1] = 2;
|
|
a.limbs[2] = 3;
|
|
a.normalize(3);
|
|
try testing.expect(a.len() == 3);
|
|
|
|
a.limbs[0] = 0;
|
|
a.limbs[1] = 0;
|
|
a.normalize(2);
|
|
try testing.expect(a.len() == 1);
|
|
|
|
a.limbs[0] = 0;
|
|
a.normalize(1);
|
|
try 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);
|
|
try testing.expect(a.len() == 2);
|
|
|
|
a.limbs[0] = 1;
|
|
a.limbs[1] = 2;
|
|
a.limbs[2] = 3;
|
|
a.normalize(3);
|
|
try testing.expect(a.len() == 3);
|
|
|
|
a.limbs[0] = 0;
|
|
a.limbs[1] = 0;
|
|
a.limbs[2] = 0;
|
|
a.limbs[3] = 0;
|
|
a.normalize(4);
|
|
try testing.expect(a.len() == 1);
|
|
|
|
a.limbs[0] = 0;
|
|
a.normalize(1);
|
|
try testing.expect(a.len() == 1);
|
|
}
|
|
|
|
test "big.int parity" {
|
|
var a = try Managed.init(testing.allocator);
|
|
defer a.deinit();
|
|
|
|
try a.set(0);
|
|
try testing.expect(a.isEven());
|
|
try testing.expect(!a.isOdd());
|
|
|
|
try a.set(7);
|
|
try testing.expect(!a.isEven());
|
|
try testing.expect(a.isOdd());
|
|
}
|
|
|
|
test "big.int bitcount + sizeInBaseUpperBound" {
|
|
var a = try Managed.init(testing.allocator);
|
|
defer a.deinit();
|
|
|
|
try a.set(0b100);
|
|
try testing.expect(a.bitCountAbs() == 3);
|
|
try testing.expect(a.sizeInBaseUpperBound(2) >= 3);
|
|
try testing.expect(a.sizeInBaseUpperBound(10) >= 1);
|
|
|
|
a.negate();
|
|
try testing.expect(a.bitCountAbs() == 3);
|
|
try testing.expect(a.sizeInBaseUpperBound(2) >= 4);
|
|
try testing.expect(a.sizeInBaseUpperBound(10) >= 2);
|
|
|
|
try a.set(0xffffffff);
|
|
try testing.expect(a.bitCountAbs() == 32);
|
|
try testing.expect(a.sizeInBaseUpperBound(2) >= 32);
|
|
try testing.expect(a.sizeInBaseUpperBound(10) >= 10);
|
|
|
|
try a.shiftLeft(a, 5000);
|
|
try testing.expect(a.bitCountAbs() == 5032);
|
|
try testing.expect(a.sizeInBaseUpperBound(2) >= 5032);
|
|
a.setSign(false);
|
|
|
|
try testing.expect(a.bitCountAbs() == 5032);
|
|
try 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);
|
|
try testing.expect(a.bitCountTwosComp() == 0);
|
|
|
|
try testing.expect((try a.to(u0)) == 0);
|
|
try testing.expect((try a.to(i0)) == 0);
|
|
|
|
try a.set(-1);
|
|
try testing.expect(a.bitCountTwosComp() == 1);
|
|
try testing.expect((try a.to(i1)) == -1);
|
|
|
|
try a.set(-8);
|
|
try testing.expect(a.bitCountTwosComp() == 4);
|
|
try testing.expect((try a.to(i4)) == -8);
|
|
|
|
try a.set(127);
|
|
try testing.expect(a.bitCountTwosComp() == 7);
|
|
try testing.expect((try a.to(u7)) == 127);
|
|
|
|
try a.set(-128);
|
|
try testing.expect(a.bitCountTwosComp() == 8);
|
|
try testing.expect((try a.to(i8)) == -128);
|
|
|
|
try a.set(-129);
|
|
try testing.expect(a.bitCountTwosComp() == 9);
|
|
try 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);
|
|
try testing.expect(a.fits(u0));
|
|
try testing.expect(a.fits(i0));
|
|
|
|
try a.set(255);
|
|
try testing.expect(!a.fits(u0));
|
|
try testing.expect(!a.fits(u1));
|
|
try testing.expect(!a.fits(i8));
|
|
try testing.expect(a.fits(u8));
|
|
try testing.expect(a.fits(u9));
|
|
try testing.expect(a.fits(i9));
|
|
|
|
try a.set(-128);
|
|
try testing.expect(!a.fits(i7));
|
|
try testing.expect(a.fits(i8));
|
|
try testing.expect(a.fits(i9));
|
|
try testing.expect(!a.fits(u9));
|
|
|
|
try a.set(0x1ffffffffeeeeeeee);
|
|
try testing.expect(!a.fits(u32));
|
|
try testing.expect(!a.fits(u64));
|
|
try 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");
|
|
try 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");
|
|
try 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___");
|
|
try 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");
|
|
try 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();
|
|
try 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();
|
|
try 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, .lower);
|
|
defer testing.allocator.free(as);
|
|
const es = "120317241209124781241290847124";
|
|
|
|
try 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();
|
|
|
|
try testing.expectError(error.InvalidBase, a.toString(testing.allocator, 45, .lower));
|
|
}
|
|
|
|
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, .lower);
|
|
defer testing.allocator.free(as);
|
|
const es = "-1011";
|
|
|
|
try 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, .lower);
|
|
defer testing.allocator.free(as);
|
|
const es = "efffffff00000001eeeeeeefaaaaaaab";
|
|
|
|
try 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, .lower);
|
|
defer testing.allocator.free(as);
|
|
const es = "-123907434";
|
|
|
|
try 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, .lower);
|
|
defer testing.allocator.free(as);
|
|
const es = "0";
|
|
|
|
try 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();
|
|
|
|
try testing.expect((try a.to(u32)) == 1234);
|
|
try testing.expect((try b.to(u32)) == 1234);
|
|
|
|
try a.set(77);
|
|
try testing.expect((try a.to(u32)) == 77);
|
|
try 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();
|
|
|
|
try testing.expect((try a.to(u32)) == 1234);
|
|
try testing.expect((try b.to(u32)) == 5678);
|
|
|
|
a.swap(&b);
|
|
|
|
try testing.expect((try a.to(u32)) == 5678);
|
|
try testing.expect((try b.to(u32)) == 1234);
|
|
}
|
|
|
|
test "big.int to negative" {
|
|
var a = try Managed.initSet(testing.allocator, -10);
|
|
defer a.deinit();
|
|
|
|
try 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();
|
|
|
|
try testing.expect(a.orderAbs(b) == .gt);
|
|
try 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();
|
|
|
|
try testing.expect(a.orderAbs(b) == .lt);
|
|
try 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();
|
|
|
|
try testing.expect(a.orderAbs(b) == .gt);
|
|
try 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();
|
|
|
|
try testing.expect(a.orderAbs(b) == .gt);
|
|
try 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();
|
|
|
|
try testing.expect(a.eqAbs(b));
|
|
try testing.expect(!a.eq(b));
|
|
}
|
|
|
|
test "big.int abs" {
|
|
var a = try Managed.initSet(testing.allocator, -5);
|
|
defer a.deinit();
|
|
|
|
a.abs();
|
|
try testing.expect((try a.to(u32)) == 5);
|
|
|
|
a.abs();
|
|
try testing.expect((try a.to(u32)) == 5);
|
|
}
|
|
|
|
test "big.int negate" {
|
|
var a = try Managed.initSet(testing.allocator, 5);
|
|
defer a.deinit();
|
|
|
|
a.negate();
|
|
try testing.expect((try a.to(i32)) == -5);
|
|
|
|
a.negate();
|
|
try 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());
|
|
|
|
try 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());
|
|
try testing.expect((try c.to(DoubleLimb)) == maxInt(Limb) + 2);
|
|
|
|
try c.add(b.toConst(), a.toConst());
|
|
try 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());
|
|
|
|
try 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());
|
|
|
|
try 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());
|
|
|
|
try 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());
|
|
try testing.expect((try a.to(i32)) == 3);
|
|
|
|
try a.add(neg_one.toConst(), two.toConst());
|
|
try testing.expect((try a.to(i32)) == 1);
|
|
|
|
try a.add(one.toConst(), neg_two.toConst());
|
|
try testing.expect((try a.to(i32)) == -1);
|
|
|
|
try a.add(neg_one.toConst(), neg_two.toConst());
|
|
try testing.expect((try a.to(i32)) == -3);
|
|
}
|
|
|
|
test "big.int add scalar" {
|
|
var a = try Managed.initSet(testing.allocator, 50);
|
|
defer a.deinit();
|
|
|
|
var b = try Managed.init(testing.allocator);
|
|
defer b.deinit();
|
|
try b.addScalar(a.toConst(), 5);
|
|
|
|
try testing.expect((try b.to(u32)) == 55);
|
|
}
|
|
|
|
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());
|
|
|
|
try 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());
|
|
|
|
try 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());
|
|
|
|
try 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());
|
|
|
|
try 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());
|
|
try testing.expect((try a.to(i32)) == -1);
|
|
|
|
try a.sub(neg_one.toConst(), two.toConst());
|
|
try testing.expect((try a.to(i32)) == -3);
|
|
|
|
try a.sub(one.toConst(), neg_two.toConst());
|
|
try testing.expect((try a.to(i32)) == 3);
|
|
|
|
try a.sub(neg_one.toConst(), neg_two.toConst());
|
|
try testing.expect((try a.to(i32)) == 1);
|
|
|
|
try a.sub(neg_two.toConst(), neg_one.toConst());
|
|
try 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());
|
|
|
|
try 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());
|
|
|
|
try 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());
|
|
|
|
try 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());
|
|
|
|
try 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());
|
|
|
|
try 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());
|
|
|
|
try 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());
|
|
|
|
try 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());
|
|
|
|
try testing.expect((try c.to(u32)) == 0);
|
|
}
|
|
|
|
test "big.int mul large" {
|
|
var a = try Managed.initCapacity(testing.allocator, 50);
|
|
defer a.deinit();
|
|
var b = try Managed.initCapacity(testing.allocator, 100);
|
|
defer b.deinit();
|
|
var c = try Managed.initCapacity(testing.allocator, 100);
|
|
defer c.deinit();
|
|
|
|
// Generate a number that's large enough to cross the thresholds for the use
|
|
// of subquadratic algorithms
|
|
for (a.limbs) |*p| {
|
|
p.* = std.math.maxInt(Limb);
|
|
}
|
|
a.setMetadata(true, 50);
|
|
|
|
try b.mul(a.toConst(), a.toConst());
|
|
try c.sqr(a.toConst());
|
|
|
|
try testing.expect(b.eq(c));
|
|
}
|
|
|
|
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());
|
|
|
|
try testing.expect((try q.to(u32)) == 10);
|
|
try 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());
|
|
|
|
try testing.expect((try q.to(u32)) == 9);
|
|
try 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());
|
|
|
|
try testing.expect((try q.to(u64)) == op1 / op2);
|
|
try 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());
|
|
|
|
try testing.expect((try q.to(u64)) == op1 / op2);
|
|
try 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());
|
|
|
|
try testing.expect((try q.to(u128)) == op1 / op2);
|
|
try 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());
|
|
|
|
try testing.expect((try q.to(u64)) == 0);
|
|
try 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());
|
|
|
|
try testing.expect((try q.to(u64)) == 1);
|
|
try 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());
|
|
|
|
try testing.expect((try a.to(u64)) == 0);
|
|
try 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());
|
|
|
|
try testing.expect((try q.to(u128)) == 0);
|
|
try 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);
|
|
|
|
try testing.expect((try q.to(i32)) == eq);
|
|
try 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;
|
|
|
|
try testing.expect((try q.to(i32)) == eq);
|
|
try 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;
|
|
|
|
try testing.expect((try q.to(i32)) == eq);
|
|
try 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;
|
|
|
|
try testing.expect((try q.to(i32)) == eq);
|
|
try 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;
|
|
|
|
try testing.expect((try q.to(i32)) == eq);
|
|
try 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;
|
|
|
|
try testing.expect((try q.to(i32)) == eq);
|
|
try 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;
|
|
|
|
try testing.expect((try q.to(i32)) == eq);
|
|
try 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;
|
|
|
|
try testing.expect((try q.to(i32)) == eq);
|
|
try 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());
|
|
|
|
try testing.expect((try q.to(u128)) == 0xe38f38e39161aaabd03f0f1b);
|
|
try 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());
|
|
|
|
try testing.expect((try q.to(u128)) == 0xe38f38e39161aaabd03f0f1b);
|
|
try 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());
|
|
|
|
try testing.expect((try q.to(u128)) == 0x10000000000000000);
|
|
try 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());
|
|
|
|
try testing.expect((try q.to(u128)) == 0xfffffffffffffffffff);
|
|
try 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();
|
|
try testing.expect(q.eq(expected));
|
|
try 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());
|
|
|
|
try testing.expect((try q.to(u128)) == 0x10000000000000000);
|
|
|
|
const rs = try r.toString(testing.allocator, 16, .lower);
|
|
defer testing.allocator.free(rs);
|
|
try 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());
|
|
|
|
try testing.expect((try q.to(u128)) == 0x1);
|
|
|
|
const rs = try r.toString(testing.allocator, 16, .lower);
|
|
defer testing.allocator.free(rs);
|
|
try 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, .lower);
|
|
defer testing.allocator.free(qs);
|
|
try testing.expect(std.mem.eql(u8, qs, "10000000000000000820820803105186f"));
|
|
|
|
const rs = try r.toString(testing.allocator, 16, .lower);
|
|
defer testing.allocator.free(rs);
|
|
try 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, .lower);
|
|
defer testing.allocator.free(qs);
|
|
try testing.expect(std.mem.eql(u8, qs, "3ffffffffffffffffffffffffffff0000000000000000000000000000000000001ffffffffffffffffffffffffffff7fffffffe000000000000000000000000000180000000000000000000003fffffbfffffffdfffffffffffffeffff800000100101000000100000000020003fffffdfbfffffe3ffffffffffffeffff7fffc00800a100000017ffe000002000400007efbfff7fe9f00000037ffff3fff7fffa004006100000009ffe00000190038200bf7d2ff7fefe80400060000f7d7f8fbf9401fe38e0403ffc0bdffffa51102c300d7be5ef9df4e5060007b0127ad3fa69f97d0f820b6605ff617ddf7f32ad7a05c0d03f2e7bc78a6000e087a8bbcdc59e07a5a079128a7861f553ddebed7e8e56701756f9ead39b48cd1b0831889ea6ec1fddf643d0565b075ff07e6caea4e2854ec9227fd635ed60a2f5eef2893052ffd54718fa08604acbf6a15e78a467c4a3c53c0278af06c4416573f925491b195e8fd79302cb1aaf7caf4ecfc9aec1254cc969786363ac729f914c6ddcc26738d6b0facd54eba026580aba2eb6482a088b0d224a8852420b91ec1"));
|
|
|
|
const rs = try r.toString(testing.allocator, 16, .lower);
|
|
defer testing.allocator.free(rs);
|
|
try 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, .lower);
|
|
defer testing.allocator.free(qs);
|
|
try testing.expect(std.mem.eql(u8, qs, "40100400fe3f8fe3f8fe3f8fe3f8fe3f8fe4f93e4f93e4f93e4f93e4f93e4f93e4f93e4f93e4f93e4f93e4f93e4f91e4791e4791e4791e4791e4791e4791e4791e4791e4791e4791e4791e4791e4992649926499264991e4791e4791e4791e4791e4791e4791e4791e4791e4791e4791e4791e4791e4791e4791e4791e4791e4791e4791e4791e4791e4791e4791e4791e4792e4b92e4b92e4b92e4b92a4a92a4a92a4"));
|
|
|
|
const rs = try r.toString(testing.allocator, 16, .lower);
|
|
defer testing.allocator.free(rs);
|
|
try 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);
|
|
|
|
try 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);
|
|
|
|
try testing.expect((try a.to(u64)) == 0x1fffe0001dddc222);
|
|
|
|
try a.set(0xffff0000eeee1111dddd2222cccc3333);
|
|
try a.shiftRight(a, 63);
|
|
try a.shiftRight(a, 63);
|
|
try a.shiftRight(a, 2);
|
|
try testing.expect(a.eqZero());
|
|
}
|
|
|
|
test "big.int shift-left single" {
|
|
var a = try Managed.initSet(testing.allocator, 0xffff);
|
|
defer a.deinit();
|
|
try a.shiftLeft(a, 16);
|
|
|
|
try 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);
|
|
|
|
try 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);
|
|
try testing.expect((try a.to(i32)) == -20 >> 2);
|
|
|
|
var arg2 = try Managed.initSet(testing.allocator, -5);
|
|
defer arg2.deinit();
|
|
try a.shiftRight(arg2, 10);
|
|
try 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);
|
|
try 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);
|
|
|
|
try 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);
|
|
|
|
try 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);
|
|
|
|
try 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);
|
|
|
|
try 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);
|
|
|
|
try 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.
|
|
try 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());
|
|
try testing.expect((try a.to(u64)) == 11);
|
|
|
|
var c = try Managed.initSet(testing.allocator, 11);
|
|
defer c.deinit();
|
|
try testing.expect(a.order(c) == .eq);
|
|
|
|
var d = try Managed.initSet(testing.allocator, 14);
|
|
defer d.deinit();
|
|
try 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);
|
|
|
|
try 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);
|
|
|
|
try 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);
|
|
|
|
try 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));
|
|
try 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);
|
|
|
|
try testing.expect((try r.to(u64)) == 1);
|
|
}
|
|
|
|
test "big.int mutable to managed" {
|
|
const allocator = testing.allocator;
|
|
var limbs_buf = try allocator.alloc(Limb, 8);
|
|
defer allocator.free(limbs_buf);
|
|
|
|
var a = Mutable.init(limbs_buf, 0xdeadbeef);
|
|
var a_managed = a.toManaged(allocator);
|
|
|
|
try testing.expect(a.toConst().eq(a_managed.toConst()));
|
|
}
|
|
|
|
test "big.int const to managed" {
|
|
var a = try Managed.initSet(testing.allocator, 123423453456);
|
|
defer a.deinit();
|
|
|
|
var b = try a.toConst().toManaged(testing.allocator);
|
|
defer b.deinit();
|
|
|
|
try testing.expect(a.toConst().eq(b.toConst()));
|
|
}
|
|
|
|
test "big.int pow" {
|
|
{
|
|
var a = try Managed.initSet(testing.allocator, -3);
|
|
defer a.deinit();
|
|
|
|
try a.pow(a.toConst(), 3);
|
|
try testing.expectEqual(@as(i32, -27), try a.to(i32));
|
|
|
|
try a.pow(a.toConst(), 4);
|
|
try testing.expectEqual(@as(i32, 531441), try a.to(i32));
|
|
}
|
|
{
|
|
var a = try Managed.initSet(testing.allocator, 10);
|
|
defer a.deinit();
|
|
|
|
var y = try Managed.init(testing.allocator);
|
|
defer y.deinit();
|
|
|
|
// y and a are not aliased
|
|
try y.pow(a.toConst(), 123);
|
|
// y and a are aliased
|
|
try a.pow(a.toConst(), 123);
|
|
|
|
try testing.expect(a.eq(y));
|
|
|
|
const ys = try y.toString(testing.allocator, 16, .lower);
|
|
defer testing.allocator.free(ys);
|
|
try testing.expectEqualSlices(
|
|
u8,
|
|
"183425a5f872f126e00a5ad62c839075cd6846c6fb0230887c7ad7a9dc530fcb" ++
|
|
"4933f60e8000000000000000000000000000000",
|
|
ys,
|
|
);
|
|
}
|
|
// Special cases
|
|
{
|
|
var a = try Managed.initSet(testing.allocator, 0);
|
|
defer a.deinit();
|
|
|
|
try a.pow(a.toConst(), 100);
|
|
try testing.expectEqual(@as(i32, 0), try a.to(i32));
|
|
|
|
try a.set(1);
|
|
try a.pow(a.toConst(), 0);
|
|
try testing.expectEqual(@as(i32, 1), try a.to(i32));
|
|
try a.pow(a.toConst(), 100);
|
|
try testing.expectEqual(@as(i32, 1), try a.to(i32));
|
|
try a.set(-1);
|
|
try a.pow(a.toConst(), 15);
|
|
try testing.expectEqual(@as(i32, -1), try a.to(i32));
|
|
try a.pow(a.toConst(), 16);
|
|
try testing.expectEqual(@as(i32, 1), try a.to(i32));
|
|
}
|
|
}
|
|
|
|
test "big.int regression test for 1 limb overflow with alias" {
|
|
// Note these happen to be two consecutive Fibonacci sequence numbers, the
|
|
// first two whose sum exceeds 2**64.
|
|
var a = try Managed.initSet(testing.allocator, 7540113804746346429);
|
|
defer a.deinit();
|
|
var b = try Managed.initSet(testing.allocator, 12200160415121876738);
|
|
defer b.deinit();
|
|
|
|
try a.ensureAddCapacity(a.toConst(), b.toConst());
|
|
try a.add(a.toConst(), b.toConst());
|
|
|
|
try testing.expect(a.toConst().orderAgainstScalar(19740274219868223167) == .eq);
|
|
}
|
|
|
|
test "big.int regression test for realloc with alias" {
|
|
// Note these happen to be two consecutive Fibonacci sequence numbers, the
|
|
// second of which is the first such number to exceed 2**192.
|
|
var a = try Managed.initSet(testing.allocator, 5611500259351924431073312796924978741056961814867751431689);
|
|
defer a.deinit();
|
|
var b = try Managed.initSet(testing.allocator, 9079598147510263717870894449029933369491131786514446266146);
|
|
defer b.deinit();
|
|
|
|
try a.ensureAddCapacity(a.toConst(), b.toConst());
|
|
try a.add(a.toConst(), b.toConst());
|
|
|
|
try testing.expect(a.toConst().orderAgainstScalar(14691098406862188148944207245954912110548093601382197697835) == .eq);
|
|
}
|