import math.big fn test_integer_from_int() { assert big.integer_from_int(0).hex() == '0' assert big.integer_from_int(1).hex() == '1' assert big.integer_from_int(255).hex() == 'ff' assert big.integer_from_int(127).hex() == '7f' assert big.integer_from_int(1024).hex() == '400' assert big.integer_from_int(2147483647).hex() == '7fffffff' } fn test_integer_from_u64() { assert big.integer_from_u64(0).hex() == '0' assert big.integer_from_u64(1).hex() == '1' assert big.integer_from_u64(255).hex() == 'ff' assert big.integer_from_u64(127).hex() == '7f' assert big.integer_from_u64(1024).hex() == '400' assert big.integer_from_u64(4294967295).hex() == 'ffffffff' assert big.integer_from_u64(4398046511104).hex() == '40000000000' max_value := big.integer_from_u64(u64(-1)) assert max_value.hex() == 'ffffffffffffffff' } fn test_integer_from_bytes() { assert big.integer_from_bytes([]).hex() == '0' assert big.integer_from_bytes([u8(0)]).hex() == '0' assert big.integer_from_bytes([u8(0x13), 0x37]).hex() == '1337' assert big.integer_from_bytes([u8(0x13), 0x37, 0xca]).hex() == '1337ca' assert big.integer_from_bytes([u8(0x13), 0x37, 0xca, 0xfe]).hex() == '1337cafe' assert big.integer_from_bytes([u8(0x13), 0x37, 0xca, 0xfe, 0xba]).hex() == '1337cafeba' assert big.integer_from_bytes([u8(0x13), 0x37, 0xca, 0xfe, 0xba, 0xbe]).hex() == '1337cafebabe' mut bytes := []u8{cap: 1024} mut expected := '' for i := 0; i < bytes.cap; i++ { bytes << u8(i) expected = expected + u8(i).hex() } assert big.integer_from_bytes(bytes).hex() == expected.trim_left('0') } fn test_bytes() { result1, sign1 := big.integer_from_u64(0x1337cafebabe).bytes() assert result1 == [u8(0x13), 0x37, 0xca, 0xfe, 0xba, 0xbe] assert sign1 == 1 mut bytes := []u8{cap: 1024} mut expected := '' for i := 0; i < bytes.cap; i++ { bytes << u8(i | 1) expected = expected + u8(i).hex() } result2, sign2 := big.integer_from_bytes(bytes).bytes() assert result2 == bytes assert sign2 == 1 } fn test_addition() { a := big.integer_from_int(2) b := big.integer_from_int(3) c := a + b assert c.hex() == '5' assert (big.integer_from_int(1024) + big.integer_from_int(1024)).hex() == '800' fib1 := big.integer_from_string('84885164052257330097714121751630835360966663883732297726369399') or { panic('Cannot read decimal') } fib2 := big.integer_from_string('137347080577163115432025771710279131845700275212767467264610201') or { panic('Cannot read decimal') } assert (fib1 + fib2).str() == '222232244629420445529739893461909967206666939096499764990979600' } fn test_subtraction() { a := big.integer_from_int(2) b := big.integer_from_int(3) assert (a - b).hex() == '-1' assert (b - a).hex() == '1' c := big.integer_from_int(1024) assert (c - c) == big.zero_int assert big.integer_from_int(-37) - big.integer_from_int(-54) == big.integer_from_int(17) } fn test_multiplication() { a := big.integer_from_int(2) b := big.integer_from_int(3) c := big.integer_from_int(6) assert a * b == c assert big.integer_from_int(-869) * big.integer_from_int(789) == big.integer_from_int(-685641) e := big.integer_from_u32(1024) e2 := e * e e4 := e2 * e2 e8 := e2 * e2 * e2 * e2 e9 := e8 + big.one_int d := ((e9 * e9) + b) * c assert e4.hex() == '10000000000' assert e8.hex() == '100000000000000000000' assert e9.hex() == '100000000000000000001' assert d.hex() == '60000000000000000000c00000000000000000018' } fn test_division() { a := big.integer_from_u64(2) b := big.integer_from_u64(3) c := b / a assert c.hex() == '1' assert (b % a).hex() == '1' e := big.integer_from_u64(1024) // dec(1024) == hex(0x400) ee := e / e assert ee.hex() == '1' assert (e / a).hex() == '200' assert (e / (a * a)).hex() == '100' assert (b / a).hex() == '1' } fn test_mod() { assert (big.integer_from_u64(13) % big.integer_from_u64(10)).int() == 3 assert (big.integer_from_u64(13) % big.integer_from_u64(9)).int() == 4 assert (big.integer_from_u64(7) % big.integer_from_u64(5)).int() == 2 } struct DivisionTest { dividend string divisor string quotient string remainder string } const divmod_test_data = [ DivisionTest{'13', '10', '1', '3'}, DivisionTest{'13', '9', '1', '4'}, DivisionTest{'7', '5', '1', '2'}, DivisionTest{'2103180314840157', '1631403814113', '1289', '300798448500'}, DivisionTest{'21408410031413414147401', '3130541314113413', '6838564', '2900204736088469'} // vfmt off DivisionTest{ '13407807929942597099574024998205846127479365820592393377723561443721764030073546976801874298166903427690031858186486050853753882811946569946433649006084096', '13407807926845237209807376456131917626043958556151178674833163543294276330515137663421134775482798690129946803802212663956180562088664022929883876655300863', '1', '3097359889766648542073928501435407264441214702890397900427487699558409313380739522684104737560085054384273386897573320723282547016549772350783233', }, DivisionTest{ '24388660549343689307666288436614463270948472382596516055139370678271628439810393042585576900667596857198513726355043536294702186342478937800831', '38733748171303628844838787580045178098452927239062690602450784467058896912531690007767956310348951731921168881868406259712', '629648864382619361826', '2724578611525334851445652767465274410979805962941953382558409365935061481311529445551691298696266856092833571769883246719', }, // vfmt on ] fn test_divmod() { for t in divmod_test_data { a := big.integer_from_string(t.dividend) or { panic('Cannot read decimal') } b := big.integer_from_string(t.divisor) or { panic('Cannot read decimal') } eq := big.integer_from_string(t.quotient) or { panic('Cannot read decimal') } er := big.integer_from_string(t.remainder) or { panic('Cannot read decimal') } q, r := a.div_mod(b) assert q == eq assert r == er } } fn test_comparison() { values := [-3, 13, 52, 6, 41] for value in values { x := big.integer_from_int(value) assert x == x assert x <= x assert x >= x } a := big.integer_from_int(-45) b := big.integer_from_int(35) assert a < b assert a <= b assert b > a assert b >= a } fn test_conversion() { ten := big.integer_from_int(10) mut n := big.integer_from_u64(u64(-1)) mut digits := []rune{} for n.signum != 0 { quot, rem := n.div_mod(ten) digits << rune(rem.int()) + `0` n = quot } assert digits.reverse().string() == '18446744073709551615' } fn test_integer_from_string() { a := big.integer_from_string('00000000') or { panic('Zero int test fails') } assert a == big.zero_int b := big.integer_from_radix('00', 4) or { panic('Zero int test fails') } assert b == big.zero_int assert a == b string_values := ['0', '1', '0012', '1349173614', '+24', '-325'] int_values := [0, 1, 12, 1349173614, 24, -325] for index in 0 .. string_values.len { x := big.integer_from_string(string_values[index]) or { panic('Could not convert decimal string') } y := big.integer_from_int(int_values[index]) assert x == y } imin := big.integer_from_string('-2147483648') or { panic('Minimum signed 32-bit int test fails.') } assert imin.int() == -2147483648 imax := big.integer_from_string('2147483647') or { panic('Maximum signed 32-bit int test fails.') } assert imax.int() == 2147483647 } fn test_integer_from_powers_of_2() { assert (big.integer_from_radix('101010', 2) or { panic('Cannot read binary') }).int() == 42 assert (big.integer_from_radix('1010', 2) or { panic('Cannot read binary') }).int() == 10 assert (big.integer_from_radix('-0000101', 2) or { panic('Cannot read binary') }).int() == -5 assert (big.integer_from_radix('CAFE', 16) or { panic('Cannot read hexadecimal') }).int() == 0xCAFE assert (big.integer_from_radix('DED', 16) or { panic('Cannot read hexadecimal') }).int() == 0xDED assert (big.integer_from_radix('-abcd', 16) or { panic('Cannot read hexadecimal') }).int() == -0xabcd } fn test_from_and_to_hex() { assert (big.integer_from_radix('123', 16) or { panic('Cannot read hexadecimal') }).hex() == '123' for i in 1 .. 33 { input := 'e'.repeat(i) output := (big.integer_from_radix(input, 16) or { panic('Cannot read hexadecimal') }).hex() assert input == output } assert (big.integer_from_string('0') or { panic('Cannot read decimal') }).str() == '0' } fn test_str() { assert big.integer_from_u64(255).str() == '255' assert big.integer_from_u64(127).str() == '127' assert big.integer_from_u64(1024).str() == '1024' assert big.integer_from_u64(4294967295).str() == '4294967295' assert big.integer_from_u64(4398046511104).str() == '4398046511104' assert big.integer_from_u64(u64(-1)).str() == '18446744073709551615' assert (big.integer_from_radix('e'.repeat(80), 16) or { panic('Cannot read hexadecimal') }).str() == '1993587900192849410235353592424915306962524220866209251950572167300738410728597846688097947807470' } fn test_exponentiation() { a := big.integer_from_int(2) assert a.pow(0).int() == 1 assert a.pow(1).int() == 2 assert a.pow(5).int() == 32 assert a.pow(10).int() == 1024 assert a.pow(30).int() == 1073741824 exp_array := [u32(5), 7, 234, 524, 291, 13051] for exp in exp_array { expected := '1' + '0'.repeat(int(exp)) actual := a.pow(exp) assert actual.binary_str() == expected } result := '66325146064916587705822805477951823674769212922003325230500180789514487101799702287247301347816140714887582527826252837635296749781071351621748491469338347097923896026211183517655658952346069454893422558286798338709431368762851475568899541999504754550056265493269010870696623999709399529395247064542825851568385196637089440522882877102429945439977107582295420418108331098961838419917230847980056560488541780255425015021238743932289115066701337398107639567748102191005710201353615093246958907555634902309636451244444952203735074916066229982498598205421944122042066749035283837586883383420374291325389757869347147357807188516650352693616763867685354382631931356465247637321960345782811272139101785279798666504361229957479336436466489780129445016691164329417001378480690804715301830926348058624' assert big.integer_from_int(324).pow(u32(315)).str() == result } fn test_mod_exponentiation() { divisor := big.integer_from_int(632) assert big.integer_from_int(324).mod_pow(u32(315), divisor) == big.integer_from_int(512) a := big.integer_from_int(65) b := big.integer_from_int(2790) div := big.integer_from_int(3233) assert a.mod_pow(17, div) == b assert b.mod_pow(413, div) == a } fn test_big_mod_exponentiation_1() { a := big.integer_from_int(23) b := big.integer_from_int(35) c := big.integer_from_int(4205) result := big.integer_from_int(552) assert a.big_mod_pow(b, c) == result } fn test_big_mod_exponentiation_2() { a := big.integer_from_string('2222589987119231759186196754430278233855361024') or { panic('Could not read big integer') } b := big.integer_from_string('3104719823194124242') or { panic('Could not read big integer') } c := big.integer_from_string('15121308410741') or { panic('Could not read big integer') } result := big.integer_from_string('487881863537') or { panic('Could not read big integer') } assert a.big_mod_pow(b, c) == result } fn test_big_mod_exponentiation_3() { a := big.integer_from_string('3192874698137469817346981364918346578619384619387463987413') or { panic('Could not read big integer') } b := big.integer_from_string('3104981983749813749137493871037') or { panic('Could not read big integer') } c := big.integer_from_string('2137476918375698711341313') or { panic('Could not read big integer') } result := big.integer_from_string('418107071760838517119254') or { panic('Could not read big integer') } assert a.big_mod_pow(b, c) == result } fn test_gcd() { assert big.integer_from_int(0).gcd(big.integer_from_int(0)) == big.zero_int assert big.integer_from_int(10).gcd(big.integer_from_int(0)) == big.integer_from_int(10) assert big.integer_from_int(0).gcd(big.integer_from_int(-18)) == big.integer_from_int(18) assert big.integer_from_int(51).gcd(big.integer_from_int(22)) == big.one_int assert big.integer_from_int(98).gcd(big.integer_from_int(56)) == big.integer_from_int(14) assert big.integer_from_int(98).gcd(big.integer_from_int(56)) == big.integer_from_int(14) a := big.integer_from_string('67116917544110') or { panic('Could not read decimal') } b := big.integer_from_string('60943431483592') or { panic('Could not read decimal') } c := big.integer_from_string('6299482') or { panic('Could not read decimal') } assert a.gcd(b) == c } fn test_factorial() { f5 := big.integer_from_u64(5).factorial() assert f5.hex() == '78' f100 := big.integer_from_u64(100).factorial() assert f100.hex() == '1b30964ec395dc24069528d54bbda40d16e966ef9a70eb21b5b2943a321cdf10391745570cca9420c6ecb3b72ed2ee8b02ea2735c61a000000000000000000000000' } fn test_inc_and_dec() { mut a := big.integer_from_int(2) mut b := big.integer_from_int(3) mut c := big.integer_from_int(4) a.inc() c.dec() assert a == b assert b == c } fn test_lshift() { assert big.integer_from_int(45).lshift(2) == big.integer_from_int(45 * 4) assert big.integer_from_int(45).lshift(3) == big.integer_from_int(45 * 8) assert big.integer_from_int(45).lshift(4) == big.integer_from_int(45 * 16) assert big.integer_from_int(45).lshift(5) == big.integer_from_int(45 * 32) assert big.integer_from_u64(0xabcedabcde).lshift(20) == big.integer_from_u64(0xabcedabcde00000) assert big.integer_from_bytes([u8(1), 1, 1]).lshift(56) == big.integer_from_bytes([ u8(1), 1, 1, 0, 0, 0, 0, 0, 0, 0, ]) } fn test_rshift() { assert big.integer_from_int(45).rshift(3) == big.integer_from_int(5) assert big.integer_from_int(0x13374956).rshift(16) == big.integer_from_int(0x1337) assert big.integer_from_bytes([ u8(1), 1, 1, 0, 0, 0, 0, 0, 0, 0, ]).rshift(56) == big.integer_from_bytes([u8(1), 1, 1]) } fn test_isqrt() { for i in 0 .. 1000 { a := big.integer_from_int(i) b := big.integer_from_int(i * i) assert b.isqrt() == a } values := [ '314', '213149', '2198614', '318014', '1000000000', '1000131039410', '2148170394871039847019843349714981', ] for value in values { a := big.integer_from_string(value) or { panic('Cannot read from decimal') } b := a * a assert b.isqrt() == a } } fn test_bitwise_ops() { a := big.integer_from_int(1).lshift(512) b := a - big.one_int assert a.bitwise_and(b) == big.zero_int assert b.bitwise_xor(b) == big.zero_int assert b.bitwise_or(b) == b assert b.bitwise_and(b) == b assert b.bitwise_not() == big.zero_int } fn test_get_bit() { x := big.integer_from_int(42) assert x.get_bit(0) == false assert x.get_bit(1) == true assert x.get_bit(2) == false assert x.get_bit(3) == true assert x.get_bit(4) == false assert x.get_bit(5) == true assert x.get_bit(10) == false values := ['1001001001001010010010100100100101011101001001010', '1111111111111111111111111111111111111111111111111', '0000000000000000000000000000000000000000010000', '1110010', '0001001'] for value in values { a := big.integer_from_radix(value, 2) or { panic('Could not read binary') } bits := []bool{len: value.len, init: value[value.len - 1 - index] == `1`} for i in 0 .. value.len { assert a.get_bit(i) == bits[i] } } } fn test_set_bit() { mut a := big.integer_from_int(32) a.set_bit(1, true) assert a.int() == 34 a.set_bit(1, false) a.set_bit(3, true) assert a.int() == 40 a.set_bit(50, true) assert a == big.one_int.lshift(50) + big.integer_from_int(40) b := a a.set_bit(100, false) assert a == b } fn test_bit_len() ? { assert big.zero_int.bit_len() == 0 assert big.one_int.bit_len() == 1 assert big.integer_from_u32(0xffffffff).bit_len() == 32 assert big.one_int.lshift(1239).bit_len() == 1240 mut num := big.integer_from_string('4338476092346017364013796407961305761039463198075691378460917856')! assert num.bit_len() == 212 for num.bit_len() > 0 { num = num.rshift(8) assert true } }