#BigInt Package Documentation

    This package provides arbitrary-precision integer arithmetic through the BigInt type. BigInt allows you to work with integers of unlimited size, making it perfect for cryptographic operations, mathematical computations, and any scenario where standard integer types are insufficient.

    #Creating BigInt Values

    There are several ways to create BigInt values:

    ///|
    test "creating bigint values" {
    // From integer literals with 'N' suffix
    let big1 = 12345678901234567890N
    inspect(big1, content="12345678901234567890")

    // From regular integers
    let big2 = @bigint.BigInt::from_int(42)
    inspect(big2, content="42")

    // From Int64 values
    let big3 = @bigint.BigInt::from_int64(9223372036854775807L)
    inspect(big3, content="9223372036854775807")

    // From strings
    let big4 = @bigint.BigInt::from_string("123456789012345678901234567890")
    inspect(big4, content="123456789012345678901234567890")

    // From hexadecimal strings
    let big5 = @bigint.BigInt::from_string("1a2b3c4d5e6f", radix=16)
    inspect(big5, content="28772997619311")
    }

    #Basic Arithmetic Operations

    BigInt supports all standard arithmetic operations:

    ///|
    test "arithmetic operations" {
    let a = 123456789012345678901234567890N
    let b = 987654321098765432109876543210N

    // Addition
    let sum = a + b
    inspect(sum, content="1111111110111111111011111111100")

    // Subtraction
    let diff = b - a
    inspect(diff, content="864197532086419753208641975320")

    // Multiplication
    let product = @bigint.BigInt::from_int(123) * @bigint.BigInt::from_int(456)
    inspect(product, content="56088")

    // Division
    let quotient = @bigint.BigInt::from_int(1000) / @bigint.BigInt::from_int(7)
    inspect(quotient, content="142")

    // Modulo
    let remainder = @bigint.BigInt::from_int(1000) % @bigint.BigInt::from_int(7)
    inspect(remainder, content="6")

    // Negation
    let neg = -a
    inspect(neg, content="-123456789012345678901234567890")
    }

    #Comparison Operations

    Compare BigInt values with each other and with regular integers:

    ///|
    test "comparisons" {
    let big = 12345N
    let small = 123N

    // BigInt to BigInt comparison
    inspect(big > small, content="true")
    inspect(big == small, content="false")
    inspect(small < big, content="true")

    // BigInt to Int comparison
    inspect(big.equal_int(12345), content="true")
    inspect(big.compare_int(12345), content="0")
    inspect(big.compare_int(1000), content="1") // greater than
    inspect(small.compare_int(200), content="-1") // less than

    // BigInt to Int64 comparison
    let big64 = @bigint.BigInt::from_int64(9223372036854775807L)
    inspect(big64.equal_int64(9223372036854775807L), content="true")
    }

    #Bitwise Operations

    BigInt supports bitwise operations for bit manipulation:

    ///|
    test "bitwise operations" {
    let a = 0b11110000N // 240 in decimal
    let b = 0b10101010N // 170 in decimal

    // Bitwise AND
    let and_result = a & b
    inspect(and_result, content="160") // 0b10100000

    // Bitwise OR
    let or_result = a | b
    inspect(or_result, content="250") // 0b11111010

    // Bitwise XOR
    let xor_result = a ^ b
    inspect(xor_result, content="90") // 0b01011010

    // Bit length
    let big_num = 255N
    inspect(big_num.bit_length(), content="8")

    // Count trailing zeros
    let with_zeros = 1000N // Has trailing zeros in binary
    let ctz = with_zeros.ctz()
    inspect(ctz >= 0, content="true")
    }

    #Power and Modular Arithmetic

    BigInt provides efficient power and modular exponentiation:

    ///|
    test "power operations" {
    // Basic power
    let base = 2N
    let exponent = 10N
    let power = base.pow(exponent)
    inspect(power, content="1024")

    // Modular exponentiation (useful for cryptography)
    let base2 = 3N
    let exp2 = 5N
    let modulus = 7N
    let mod_power = base2.pow(exp2, modulus~)
    inspect(mod_power, content="5") // (3^5) % 7 = 243 % 7 = 5

    // Large modular exponentiation (optimized for speed)
    let large_base = 123N
    let large_exp = 20N
    let large_mod = 1000007N
    let result = large_base.pow(large_exp, modulus=large_mod)
    inspect(result, content="378446") // (123^20) % 1000007
    }

    #String and Hexadecimal Conversion

    Convert BigInt to and from various string representations:

    ///|
    test "string conversions" {
    let big = 255N

    // Decimal string
    let decimal = big.to_string()
    inspect(decimal, content="255")

    // Hexadecimal (lowercase)
    let hex = big.to_string(radix=16)
    inspect(hex, content="ff")

    // Parse from hex (radix=16)
    let from_radix16 = @bigint.BigInt::from_string("deadbeef", radix=16)
    inspect(from_radix16, content="3735928559")

    // Round-trip conversion
    let original = 98765432109876543210N
    let as_string = original.to_string()
    let parsed_back = @bigint.BigInt::from_string(as_string)
    inspect(original == parsed_back, content="true")
    }

    #Byte Array Conversion

    Convert BigInt to and from byte arrays:

    ///|
    test "byte conversions" {
    let big = 0x123456789abcdefN

    // Convert to bytes
    let bytes = big.to_octets()
    inspect(bytes.length() > 0, content="true")

    // Convert from bytes (positive number)
    let from_bytes = @bigint.BigInt::from_octets(bytes)
    inspect(from_bytes == big, content="true")

    // Convert with specific length
    let fixed_length = @bigint.BigInt::from_int(255).to_octets(length=4)
    inspect(fixed_length.length(), content="4")

    // Negative numbers
    // let negative = -big
    // let neg_bytes = negative.to_octets()
    // to_octets does not accept negative numbers
    // let neg_from_bytes = @bigint.BigInt::from_octets(neg_bytes, signum=-1)
    // inspect(neg_from_bytes == negative, content="true")
    }

    #Type Conversions

    Convert BigInt to standard integer types:

    ///|
    test "type conversions" {
    let big = 12345N

    // To Int (truncates if too large)
    let as_int = big.to_int()
    inspect(as_int, content="12345")

    // To Int64
    let as_int64 = big.to_int64()
    inspect(as_int64, content="12345")

    // To UInt
    let as_uint = big.to_uint()
    inspect(as_uint, content="12345")

    // To smaller types
    let small = 255N
    let as_int16 = small.to_int16()
    inspect(as_int16, content="255")
    let as_uint16 = small.to_uint16()
    inspect(as_uint16, content="255")
    }

    #JSON Serialization

    BigInt values can be serialized to and from JSON:

    ///|
    test "json serialization" {
    let big = 12345678901234567890N

    // Convert to JSON (as string to preserve precision)
    let json = big.to_json()
    @debug.debug_inspect(json, content="String(\"12345678901234567890\")")

    // Large numbers that exceed JavaScript's safe integer range
    let very_big = @bigint.BigInt::from_string("123456789012345678901234567890")
    let big_json = very_big.to_json()
    @debug.debug_inspect(
    big_json,
    content="String(\"123456789012345678901234567890\")",
    )
    }

    #Utility Functions

    Check properties of BigInt values:

    ///|
    test "utility functions" {
    let zero = 0N
    let positive = 42N
    let negative = -42N

    // Check if zero
    inspect(zero.is_zero(), content="true")
    inspect(positive.is_zero(), content="false")

    // Sign testing through comparison
    inspect(positive > zero, content="true")
    inspect(negative < zero, content="true")
    inspect(zero == zero, content="true")
    }

    #Use Cases and Applications

    BigInt is particularly useful for:

    1. Cryptography: RSA encryption, digital signatures, and key generation
    2. Mathematical computations: Factorial calculations, Fibonacci sequences, prime number testing
    3. Financial calculations: High-precision monetary computations
    4. Scientific computing: Large integer calculations in physics and chemistry
    5. Data processing: Handling large numeric IDs and checksums

    #Performance Considerations

    • BigInt operations are slower than regular integer operations due to arbitrary precision
    • Addition and subtraction are generally fast
    • Multiplication and division become slower with larger numbers
    • Modular exponentiation is optimized for cryptographic use cases
    • String conversions can be expensive for very large numbers

    #Best Practices

    1. Use regular integers when possible: Only use BigInt when you need arbitrary precision
    2. Cache string representations: If you need to display the same BigInt multiple times
    3. Use modular arithmetic: For cryptographic applications, always use modular exponentiation
    4. Be careful with conversions: Converting very large BigInt to regular integers will truncate
    5. Consider memory usage: Very large BigInt values consume more memory

    BigInt

    type BigInt

    impl Add for BigInt
    impl BitAnd for BigInt
    impl BitOr for BigInt
    impl BitXOr for BigInt
    impl Compare for BigInt
    impl Default for BigInt
    impl Div for BigInt
    impl Eq for BigInt
    impl Hash for BigInt
    impl Mod for BigInt
    impl Mul for BigInt
    impl Neg for BigInt
    impl Shl for BigInt
    impl Show for BigInt
    impl Shr for BigInt
    impl Sub for BigInt
    impl ToJson for BigInt

    BigInt::add

    fn BigInt::add(self : BigInt, other : BigInt) -> BigInt

    BigInt::bit_length

    fn BigInt::bit_length(self : BigInt) -> Int

    Returns the number of bits in the minimal representation excluding its sign bit.

    BigInt::compare

    fn BigInt::compare(self : BigInt, other : BigInt) -> Int

    BigInt::compare_int

    fn BigInt::compare_int(self : BigInt, other : Int) -> Int

    Compares a BigInt with an Int and returns their relative order.

    Parameters:

    • self : The BigInt value to compare.
    • other : The Int value to compare against.

    Returns an integer indicating the relative order:

    • A negative value if self is less than other
    • Zero if self equals other
    • A positive value if self is greater than other

    Example:

    test {
    let big = 42N
    inspect(big.compare_int(24), content="1") // 42 > 24
    inspect(big.compare_int(42), content="0") // 42 = 42
    inspect(big.compare_int(100), content="-1") // 42 < 100
    }

    BigInt::compare_int64

    fn BigInt::compare_int64(self : BigInt, other : Int64) -> Int

    Compares a BigInt with an Int64 and returns their relative order.

    Parameters:

    • self : The BigInt value to compare.
    • other : The Int64 value to compare against.

    Returns an integer indicating the relative order:

    • A negative value if self is less than other
    • Zero if self equals other
    • A positive value if self is greater than other

    Example:

    test {
    let big = 42N
    inspect(big.compare_int64(24L), content="1") // 42 > 24
    inspect(big.compare_int64(42L), content="0") // 42 = 42
    inspect(big.compare_int64(100L), content="-1") // 42 < 100
    }

    BigInt::compare_uint

    fn BigInt::compare_uint(self : BigInt, other : UInt) -> Int

    Compares a BigInt with a UInt and returns their relative order.

    BigInt::compare_uint64

    fn BigInt::compare_uint64(self : BigInt, other : UInt64) -> Int

    Compares a BigInt with a UInt64 and returns their relative order.

    BigInt::ctz

    fn BigInt::ctz(self : BigInt) -> Int

    Returns the number of trailing zero bits in the magnitude.

    BigInt::div

    fn BigInt::div(self : BigInt, other : BigInt) -> BigInt

    BigInt::equal

    fn BigInt::equal(self : BigInt, other : BigInt) -> Bool

    BigInt::equal_int

    fn BigInt::equal_int(self : BigInt, other : Int) -> Bool

    Tests equality between a BigInt and an Int value.

    This function performs a safe comparison by first checking if the BigInt can be converted to an Int without overflow, then comparing the converted value with the Int parameter. If the BigInt is too large or too small to fit in an Int, the function returns false.

    Parameters:

    • self : The BigInt value to compare.
    • other : The Int value to compare against.

    Returns true if the BigInt and Int represent the same numerical value, false otherwise.

    Example:

    test {
    let big = 42N
    inspect(big.equal_int(42), content="true")
    inspect(big.equal_int(41), content="false")
    let large = 9223372036854775808N // Beyond Int64 range
    inspect(large.equal_int(42), content="false")
    }

    BigInt::equal_int64

    fn BigInt::equal_int64(self : BigInt, other : Int64) -> Bool

    Tests whether a BigInt value is equal to an Int64 value.

    This function performs an efficient equality check by first verifying if the BigInt can be represented as an Int64 without overflow. If it can be converted, it then compares the converted value with the given Int64.

    Parameters:

    • self : The BigInt value to compare.
    • other : The Int64 value to compare against.

    Returns true if the BigInt and Int64 represent the same numerical value, false otherwise.

    Example:

    test {
    let big = @bigint.BigInt::from_int64(9223372036854775807L) // Int64 max value
    inspect(big.equal_int64(9223372036854775807L), content="true")
    inspect(big.equal_int64(42L), content="false")
    let overflow = @bigint.BigInt::from_string("9223372036854775808") // Beyond Int64 range
    inspect(overflow.equal_int64(9223372036854775807L), content="false")
    }

    BigInt::equal_uint

    fn BigInt::equal_uint(self : BigInt, other : UInt) -> Bool

    Tests whether a BigInt value is equal to a UInt value.

    This is a convenience helper mirroring equal_int/equal_int64 and avoids forcing callers to construct a temporary BigInt manually.

    BigInt::equal_uint64

    fn BigInt::equal_uint64(self : BigInt, other : UInt64) -> Bool

    Tests whether a BigInt value is equal to a UInt64 value.

    This is a convenience helper mirroring equal_int/equal_int64 and avoids forcing callers to construct a temporary BigInt manually.

    BigInt::from_int

    fn BigInt::from_int(n : Int) -> BigInt

    Creates a BigInt from a signed 32-bit integer.

    BigInt::from_int64

    fn BigInt::from_int64(n : Int64) -> BigInt

    Creates a BigInt from a signed 64-bit integer.

    BigInt::from_octets

    fn BigInt::from_octets(input : BytesView, signum? : Int) -> BigInt

    Creates a magnitude from unsigned big-endian bytes.

    BigInt::from_string

    fn BigInt::from_string(input : String, radix? : Int) -> BigInt

    Converts a string representation in the specified radix to a BigInt.

    Panics if the input is malformed. Use @string.parse_bigint to handle errors.

    BigInt::from_uint

    fn BigInt::from_uint(n : UInt) -> BigInt

    Creates a non-negative BigInt from an unsigned 32-bit integer.

    BigInt::from_uint64

    fn BigInt::from_uint64(n : UInt64) -> BigInt

    Creates a non-negative BigInt from an unsigned 64-bit integer.

    BigInt::hash

    fn BigInt::hash(self : BigInt) -> Int

    BigInt::is_zero

    fn BigInt::is_zero(self : BigInt) -> Bool

    Returns whether this integer is zero.

    BigInt::land

    fn BigInt::land(self : BigInt, other : BigInt) -> BigInt

    BigInt::lor

    fn BigInt::lor(self : BigInt, other : BigInt) -> BigInt

    BigInt::lxor

    fn BigInt::lxor(self : BigInt, other : BigInt) -> BigInt

    BigInt::mod

    fn BigInt::mod(self : BigInt, other : BigInt) -> BigInt

    BigInt::mul

    fn BigInt::mul(self : BigInt, other : BigInt) -> BigInt

    BigInt::neg

    fn BigInt::neg(self : BigInt) -> BigInt

    BigInt::pow

    fn BigInt::pow(self : BigInt, exp : BigInt, modulus? : BigInt) -> BigInt

    self ^ exp by square-and-multiply.

    BigInt::shl

    fn BigInt::shl(self : BigInt, n : Int) -> BigInt

    BigInt::shr

    fn BigInt::shr(self : BigInt, n : Int) -> BigInt

    BigInt::sub

    fn BigInt::sub(self : BigInt, other : BigInt) -> BigInt

    BigInt::to_int

    fn BigInt::to_int(self : BigInt) -> Int

    Returns the low 32 bits reinterpreted as a signed integer.

    BigInt::to_int16

    fn BigInt::to_int16(self : BigInt) -> Int16

    Converts a BigInt value to a signed 16-bit integer (Int16).

    Parameters:

    • self : The BigInt value to be converted.

    Returns a 16-bit signed integer representing the lower 16 bits of the input BigInt.

    Example:

    test {
    let n = 42N
    inspect(n.to_int16(), content="42")
    let neg = -1N
    inspect(neg.to_int16(), content="-1")
    let big = 32768N // 2^15
    inspect(big.to_int16(), content="-32768") // Overflow to Int16.min_value
    }

    BigInt::to_int64

    fn BigInt::to_int64(self : BigInt) -> Int64

    Returns the low 64 bits reinterpreted as a signed integer.

    BigInt::to_json

    fn BigInt::to_json(self : BigInt) -> Json

    BigInt::to_octets

    fn BigInt::to_octets(self : BigInt, length? : Int) -> Bytes

    Converts a non-negative integer to unsigned big-endian bytes.

    BigInt::to_string

    fn BigInt::to_string(self : BigInt, radix? : Int) -> String

    Converts this integer to a string in a radix between 2 and 36.

    BigInt::to_uint

    fn BigInt::to_uint(self : BigInt) -> UInt

    Returns the low 32 bits as an unsigned integer.

    BigInt::to_uint16

    fn BigInt::to_uint16(self : BigInt) -> UInt16

    Converts a BigInt value to an unsigned 16-bit integer (UInt16).

    Parameters:

    • self : The BigInt value to be converted.

    Returns a UInt16 value representing the lower 16 bits of the input BigInt.

    Example:

    test {
    let n = 42N
    inspect(n.to_uint16(), content="42")
    let neg = -1N
    inspect(neg.to_uint16(), content="65535") // 2^16 - 1
    }

    BigInt::to_uint64

    fn BigInt::to_uint64(self : BigInt) -> UInt64

    Returns the low 64 bits as an unsigned integer.