From 5e1aec0f78069399d2f7c59e4eca90fd9e6000d3 Mon Sep 17 00:00:00 2001 From: DualFroz Date: Fri, 28 Aug 2026 09:00:00 +0200 Subject: [PATCH] test(numeric): add bigint arithmetic tests --- Tests/KiteCoreTests/BigIntTests.swift | 106 ++++++++++++++++++++++++++ 1 file changed, 106 insertions(+) create mode 100644 Tests/KiteCoreTests/BigIntTests.swift diff --git a/Tests/KiteCoreTests/BigIntTests.swift b/Tests/KiteCoreTests/BigIntTests.swift new file mode 100644 index 0000000..4e21f3d --- /dev/null +++ b/Tests/KiteCoreTests/BigIntTests.swift @@ -0,0 +1,106 @@ +import XCTest +@testable import KiteCore + +final class BigIntTests: XCTestCase { + func testRoundTripInt() { + for value in [0, 1, -1, 42, -42, Int.max, Int.min, 1234567890, -1234567890] { + let big = BigInt(value) + XCTAssertTrue(big.fitsInt, "\(value) should fit") + XCTAssertEqual(big.toInt(), value) + } + } + + func testAddSubAgainstInt() { + let pairs = [(12, 34), (-5, 9), (1000, -1000), (999999, 1), (-7, -8)] + for (a, b) in pairs { + XCTAssertEqual((BigInt(a) + BigInt(b)).toInt(), a + b) + XCTAssertEqual((BigInt(a) - BigInt(b)).toInt(), a - b) + XCTAssertEqual((BigInt(a) * BigInt(b)).toInt(), a * b) + } + } + + func testFactorialKnownValue() { + var acc = BigInt.one + for k in 1...100 { acc = acc * BigInt(k) } + let expected = "93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000" + XCTAssertEqual(acc.description, expected) + } + + func testDivModAgainstInt() { + let pairs = [(17, 5), (-17, 5), (17, -5), (-17, -5), (100, 7), (5, 17), (0, 3)] + for (a, b) in pairs { + let (q, r) = BigInt.divMod(BigInt(a), BigInt(b)) + XCTAssertEqual(q.toInt(), a / b, "quotient \(a)/\(b)") + XCTAssertEqual(r.toInt(), a % b, "remainder \(a)%\(b)") + XCTAssertEqual((q * BigInt(b) + r).toInt(), a, "identity \(a)/\(b)") + } + } + + func testBigDivMod() { + var big = BigInt.one + for k in 1...50 { big = big * BigInt(k) } + let divisor = BigInt(string: "1000000000000000000", radix: 10)! + let (q, r) = BigInt.divMod(big, divisor) + XCTAssertEqual((q * divisor + r), big) + XCTAssertTrue(r < divisor) + XCTAssertFalse(r.isNegative) + } + + func testModulo() { + XCTAssertEqual(BigInt(-7).modulo(BigInt(3)).toInt(), 2) + XCTAssertEqual(BigInt(7).modulo(BigInt(3)).toInt(), 1) + XCTAssertEqual(BigInt(7).modulo(BigInt(-3)).toInt(), -2) + XCTAssertEqual(BigInt(-7).modulo(BigInt(-3)).toInt(), -1) + } + + func testGcd() { + XCTAssertEqual(BigInt.gcd(BigInt(12), BigInt(18)).toInt(), 6) + XCTAssertEqual(BigInt.gcd(BigInt(0), BigInt(5)).toInt(), 5) + var a = BigInt.one + for k in 1...30 { a = a * BigInt(k) } + var b = BigInt.one + for k in 1...20 { b = b * BigInt(k) } + XCTAssertEqual(BigInt.gcd(a, b), b) + } + + func testPower() { + XCTAssertEqual(BigInt(2).power(10).toInt(), 1024) + XCTAssertEqual(BigInt(2).power(64).description, "18446744073709551616") + XCTAssertEqual(BigInt(10).power(30).description, "1000000000000000000000000000000") + } + + func testStringRoundTrip() { + let samples = [ + "0", "1", "-1", "255", "4294967296", "18446744073709551616", + "-93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000", + ] + for s in samples { + XCTAssertEqual(BigInt(string: s, radix: 10)?.description, s) + } + } + + func testRadixConversion() { + XCTAssertEqual(BigInt(255).toString(radix: 16), "ff") + XCTAssertEqual(BigInt(255).toString(radix: 2), "11111111") + XCTAssertEqual(BigInt(string: "ff", radix: 16)?.toInt(), 255) + XCTAssertEqual(BigInt(string: "-101", radix: 2)?.toInt(), -5) + XCTAssertEqual(BigInt(1000000).toString(radix: 16), "f4240") + } + + func testIsqrt() { + XCTAssertEqual(BigInt(0).isqrt().toInt(), 0) + XCTAssertEqual(BigInt(1).isqrt().toInt(), 1) + XCTAssertEqual(BigInt(15).isqrt().toInt(), 3) + XCTAssertEqual(BigInt(16).isqrt().toInt(), 4) + XCTAssertEqual(BigInt(17).isqrt().toInt(), 4) + let big = BigInt(string: "100000000000000000000", radix: 10)! + XCTAssertEqual(big.isqrt().toInt(), 10000000000) + } + + func testComparison() { + XCTAssertTrue(BigInt(-5) < BigInt(3)) + XCTAssertTrue(BigInt(3) < BigInt(5)) + XCTAssertTrue(BigInt(string: "100000000000000000000", radix: 10)! > BigInt(Int.max)) + XCTAssertTrue(BigInt(Int.min) < BigInt(0)) + } +}