Skip to content
Topaz6.0 · Before release
Download

Search documentation

Specification 6.0 · Not released · Tested product 5.21.3

Use arrow keys to choose a result. Press Enter to open.

Type an API name, diagnostic number, rule, or project topic.

    Library

    std.bigint

    Compute exact signed integers and convert them through explicit radices.

    APIs in this module

    5 APIs

    NameModule
    BigInt.divstd.bigint
    BigInt.modstd.bigint
    BigInt.parsestd.bigint
    BigInt.toIntstd.bigint
    BigInt.toStringstd.bigint

    Module

    Link

    BigInt preserves arbitrary precision values. Text parsing, formatting, checked int conversion, division, and remainder have explicit failure outcomes.

    Why

    Link

    Exact arithmetic and checked conversions keep large values distinct from bounded machine integers.

    Availability

    Link

    Import std.bigint in language mode 5.21. The current compiler selects std/bigint.tpz for this language mode. Availability in other released editions and inclusion in each installed distribution are Pending.

    Exported types

    Link

    export type BigInt = BigInt

    Type members keep the compiler-owned type name shown in their declarations. Importing a module does not create a new type identity.

    Public API

    Link

    BigInt.div

    BigInt.mod

    BigInt.parse

    BigInt.toInt

    BigInt.toString

    Pending contracts

    Link

    Read and write integers in an explicit radix

    Link
    Ruletopaz.stdlib.contract.bigint-text.rule

    Read and write integers in an explicit radix

    BigInt represents signed integers without a fixed bit width. Its text operations preserve the exact integer value and do not use a locale.

    BigInt.parse takes a radix from 2 through 36. Text consists of an optional minus sign followed by at least one ASCII digit or lowercase ASCII letter. Letters a through z have digit values 10 through 35. Every digit must be smaller than the radix.

    Leading zero digits are accepted. Negative zero produces the same zero value as 0. Parsing does not trim whitespace, accept a plus sign, accept uppercase letters, accept separators, or interpret a radix prefix. Characters are interpreted as ordinary digits of the supplied radix.

    Valid text returns Some containing the exact integer. Empty text, a sign without digits, an invalid digit, any extra character, or a radix outside the allowed range returns None(). These input failures do not raise a runtime fault.

    BigInt.toString takes a radix from 2 through 36 and returns lowercase ASCII digits in that radix. A negative nonzero value starts with a minus sign. The output has no radix prefix or leading zero digits. Zero is written as 0.

    An invalid BigInt.toString radix raises TPZ5001 during execution. It does not select a default radix or return empty text.

    Formatting a value and parsing the result with the same radix recovers that value. Parsing and formatting accepted text produces its canonical spelling in the selected radix.

    The receiver and positional arguments are evaluated once in source order before the operation validates their values. An earlier fault prevents later evaluation. The operations do not change their inputs or perform external effects.

    Why

    An explicit radix gives each digit one value. Strict input spelling makes accidental whitespace and alternate signs visible to the caller. Canonical output gives stored integer text a predictable form without a locale dependency.

    Source evidence

    Parse and format exact integers in explicit radices

    Link
    main.tpzParse and format exact integers in explicit radicesOpen in Playground
    1. import std.bigint { BigInt }
    2. import std.test
    3. import std.io
    4. let number = test.assertSome(BigInt.parse("ff", 16))
    5. io.writeLine(number.toString(2))
    6. io.writeLine(number.toString(10))
    7. io.writeLine(number.toString(16))
    8. io.writeLine(test.assertSome(BigInt.parse("z", 36)).toString(10))
    9. io.writeLine(test.assertSome(BigInt.parse("-00015", 10)).toString(16))
    10. io.writeLine(test.assertSome(BigInt.parse("-000", 10)).toString(36))
    11. io.writeLine(test.assertSome(BigInt.parse("123456789012345678901234567890", 10)).toString(10))
    Expected outputexit 0
    11111111
    255
    ff
    35
    -f
    0
    123456789012345678901234567890
    
    $ topaz run main.tpz · target product 5.21.3
    Expected result

    Expected result

    Execution completes. Exit code 0.

    Expected stdout
    1. 11111111
    2. 255
    3. ff
    4. 35
    5. -f
    6. 0
    7. 123456789012345678901234567890
    Source evidence

    Return None for malformed or out of radix digits

    Link
    main.tpzReturn None for malformed or out of radix digitsOpen in Playground
    1. import std.bigint { BigInt }
    2. import std.io
    3. for text in (["", "-", "1_0", "0x10", "g", "12", "1\n2"]) {
    4. match (BigInt.parse(text, 16)) {
    5. case None() => io.writeLine("rejected")
    6. case Some(_) => io.writeLine("accepted")
    7. }
    8. }
    9. match (BigInt.parse("2", 2)) {
    10. case None() => io.writeLine("digit rejected")
    11. case Some(_) => io.writeLine("accepted")
    12. }
    Expected outputexit 0
    rejected
    rejected
    rejected
    rejected
    rejected
    rejected
    rejected
    digit rejected
    
    $ topaz run main.tpz · target product 5.21.3
    Expected result

    Expected result

    Execution completes. Exit code 0.

    Expected stdout
    1. rejected
    2. rejected
    3. rejected
    4. rejected
    5. rejected
    6. rejected
    7. rejected
    8. digit rejected
    Source evidence

    Reject parse radices outside two through thirty six

    Link
    main.tpzReject parse radices outside two through thirty sixOpen in Playground
    1. import std.bigint { BigInt }
    2. import std.io
    3. for radix in ([-1, 0, 1, 37, 9223372036854775807]) {
    4. match (BigInt.parse("10", radix)) {
    5. case None() => io.writeLine("radix rejected")
    6. case Some(_) => io.writeLine("accepted")
    7. }
    8. }
    Expected outputexit 0
    radix rejected
    radix rejected
    radix rejected
    radix rejected
    radix rejected
    
    $ topaz run main.tpz · target product 5.21.3
    Expected result

    Expected result

    Execution completes. Exit code 0.

    Expected stdout
    1. radix rejected
    2. radix rejected
    3. radix rejected
    4. radix rejected
    5. radix rejected
    Source evidence

    Reject surrounding whitespace in integer text

    Link
    main.tpzReject surrounding whitespace in integer textOpen in Playground
    1. import std.bigint { BigInt }
    2. import std.io
    3. match (BigInt.parse(" 10 ", 10)) {
    4. case None() => io.writeLine("whitespace rejected")
    5. case Some(_) => io.writeLine("accepted")
    6. }
    Expected outputexit 0
    whitespace rejected
    
    $ topaz run main.tpz · target product 5.21.3
    Expected result

    Expected result

    Execution completes. Exit code 0.

    Expected stdout
    1. whitespace rejected
    Source evidence

    Reject a leading plus sign in integer text

    Link
    main.tpzReject a leading plus sign in integer textOpen in Playground
    1. import std.bigint { BigInt }
    2. import std.io
    3. match (BigInt.parse("+10", 10)) {
    4. case None() => io.writeLine("plus rejected")
    5. case Some(_) => io.writeLine("accepted")
    6. }
    Expected outputexit 0
    plus rejected
    
    $ topaz run main.tpz · target product 5.21.3
    Expected result

    Expected result

    Execution completes. Exit code 0.

    Expected stdout
    1. plus rejected
    Source evidence

    Reject uppercase letters in integer text

    Link
    main.tpzReject uppercase letters in integer textOpen in Playground
    1. import std.bigint { BigInt }
    2. import std.io
    3. match (BigInt.parse("FF", 16)) {
    4. case None() => io.writeLine("uppercase rejected")
    5. case Some(_) => io.writeLine("accepted")
    6. }
    Expected outputexit 0
    uppercase rejected
    
    $ topaz run main.tpz · target product 5.21.3
    Expected result

    Expected result

    Execution completes. Exit code 0.

    Expected stdout
    1. uppercase rejected
    Source evidence

    Evaluate parse arguments before validating their values

    Link
    main.tpzEvaluate parse arguments before validating their valuesOpen in Playground
    1. import std.bigint { BigInt }
    2. import std.io
    3. function text() -> string {
    4. io.writeLine("text")
    5. return "bad"
    6. }
    7. function radix() -> int {
    8. io.writeLine("radix")
    9. return 10
    10. }
    11. match (BigInt.parse(text(), radix())) {
    12. case None() => io.writeLine("rejected")
    13. case Some(_) => io.writeLine("accepted")
    14. }
    Expected outputexit 0
    text
    radix
    rejected
    
    $ topaz run main.tpz · target product 5.21.3
    Expected result

    Expected result

    Execution completes. Exit code 0.

    Expected stdout
    1. text
    2. radix
    3. rejected
    Source evidence

    Reject a formatting radix outside the valid range

    Link
    main.tpzReject a formatting radix outside the valid rangeOpen in Playground
    1. import std.bigint { BigInt }
    2. import std.test
    3. import std.io
    4. let number: BigInt = test.assertSome(BigInt.parse("1", 10))
    5. number.toString(1)
    6. io.writeLine("after")
    Expected outputNonzero exit
    No stdout.
    $ topaz run main.tpz · target product 5.21.3
    Expected result

    Expected result

    Rejection during run. Nonzero exit.

    • TPZ5001 stdlib-bigint-radix at main.tpz:5:1
    Source evidence

    Reject a formatting radix outside the valid range

    Link
    main.tpzReject a formatting radix outside the valid rangeOpen in Playground
    1. import std.bigint { BigInt }
    2. import std.test
    3. import std.io
    4. let number: BigInt = test.assertSome(BigInt.parse("1", 10))
    5. number.toString(37)
    6. io.writeLine("after")
    Expected outputNonzero exit
    No stdout.
    $ topaz run main.tpz · target product 5.21.3
    Expected result

    Expected result

    Rejection during run. Nonzero exit.

    • TPZ5001 stdlib-bigint-radix at main.tpz:5:1
    Source evidence

    Diagnostics

    Link

    Runtime value guard

    Convert exact integers within the int range

    Link
    Ruletopaz.stdlib.contract.bigint-to-int.rule

    Convert exact integers within the int range

    BigInt.toInt returns Some containing the same integer when the value is at least -9223372036854775808 and at most 9223372036854775807. Both endpoints are included.

    Every value outside that signed 64 bit range returns None(). Conversion does not wrap, truncate, round, or saturate.

    The operation evaluates its receiver once and leaves it unchanged. A failed conversion is an Option value and does not raise an arithmetic overflow fault.

    BigInt.parse can represent integers beyond the int range. BigInt.toString still formats those values exactly when BigInt.toInt returns None().

    Why

    A checked conversion preserves the distinction between an exact arbitrary precision value and a bounded machine integer. Option makes failure explicit without inventing a replacement integer.

    Source evidence

    Include both int endpoints and reject their neighbors

    Link
    main.tpzInclude both int endpoints and reject their neighborsOpen in Playground
    1. import std.bigint { BigInt }
    2. import std.test
    3. import std.io
    4. function show(text: string) -> () {
    5. let value = test.assertSome(BigInt.parse(text, 10))
    6. match (value.toInt()) {
    7. case Some(integer) => io.writeLine("{integer}")
    8. case None() => io.writeLine("outside int")
    9. }
    10. }
    11. show("-9223372036854775808")
    12. show("9223372036854775807")
    13. show("-9223372036854775809")
    14. show("9223372036854775808")
    15. show("0")
    Expected outputexit 0
    -9223372036854775808
    9223372036854775807
    outside int
    outside int
    0
    
    $ topaz run main.tpz · target product 5.21.3
    Expected result

    Expected result

    Execution completes. Exit code 0.

    Expected stdout
    1. -9223372036854775808
    2. 9223372036854775807
    3. outside int
    4. outside int
    5. 0
    Source evidence

    Keep a large value after conversion fails

    Link
    main.tpzKeep a large value after conversion failsOpen in Playground
    1. import std.bigint { BigInt }
    2. import std.test
    3. import std.io
    4. let value = test.assertSome(BigInt.parse("1000000000000000000000000000000", 10))
    5. match (value.toInt()) {
    6. case None() => io.writeLine("outside int")
    7. case Some(_) => io.writeLine("converted")
    8. }
    9. io.writeLine(value.toString(10))
    Expected outputexit 0
    outside int
    1000000000000000000000000000000
    
    $ topaz run main.tpz · target product 5.21.3
    Expected result

    Expected result

    Execution completes. Exit code 0.

    Expected stdout
    1. outside int
    2. 1000000000000000000000000000000
    Source evidence

    Divide exact integers toward zero

    Link
    Ruletopaz.stdlib.contract.bigint-division.rule

    Divide exact integers toward zero

    For a nonzero divisor, BigInt.div returns Ok containing the exact integer quotient truncated toward zero.

    BigInt.mod returns Ok containing the remainder left by that quotient. For dividend a and divisor b, the values satisfy a = quotient * b + remainder. A nonzero remainder has the sign of the dividend and a magnitude smaller than the divisor magnitude.

    A zero dividend and nonzero divisor produce a zero quotient and zero remainder. A negative divisor changes the quotient sign and does not choose the remainder sign.

    A zero divisor makes either operation return Err containing a descriptive nonempty string. The string has no stable machine readable format. The operation does not raise a division fault for this input.

    Quotients and remainders are BigInt values. Division has no signed 64 bit overflow boundary and does not convert an operand to int.

    The receiver is evaluated before the divisor and each is evaluated once. An earlier fault prevents later evaluation. The operations leave both values unchanged and have no external effects.

    Use div and mod for BigInt division and remainder. The language arithmetic operators on BigInt provide addition, subtraction, and multiplication.

    Why

    Truncating the quotient toward zero keeps signed division aligned with int arithmetic. Returning Err for a zero divisor gives exact integer calculations a recoverable failure value.

    Source evidence

    Keep quotient and remainder signs explicit

    Link
    main.tpzKeep quotient and remainder signs explicitOpen in Playground
    1. import std.bigint { BigInt }
    2. import std.test
    3. import std.io
    4. function divide(left: string, right: string) -> () {
    5. let a = test.assertSome(BigInt.parse(left, 10))
    6. let b = test.assertSome(BigInt.parse(right, 10))
    7. let quotient = test.assertOk(a.div(b))
    8. let remainder = test.assertOk(a.mod(b))
    9. io.writeLine(quotient.toString(10) + " " + remainder.toString(10))
    10. }
    11. divide("7", "3")
    12. divide("-7", "3")
    13. divide("7", "-3")
    14. divide("-7", "-3")
    15. divide("2", "7")
    16. divide("0", "-3")
    17. divide("-9223372036854775808", "-1")
    Expected outputexit 0
    2 1
    -2 -1
    -2 1
    2 -1
    0 2
    0 0
    9223372036854775808 0
    
    $ topaz run main.tpz · target product 5.21.3
    Expected result

    Expected result

    Execution completes. Exit code 0.

    Expected stdout
    1. 2 1
    2. -2 -1
    3. -2 1
    4. 2 -1
    5. 0 2
    6. 0 0
    7. 9223372036854775808 0
    Source evidence

    Handle a zero divisor as a Result error

    Link
    main.tpzHandle a zero divisor as a Result errorOpen in Playground
    1. import std.bigint { BigInt }
    2. import std.test
    3. import std.io
    4. let value = test.assertSome(BigInt.parse("7", 10))
    5. let zero = test.assertSome(BigInt.parse("0", 10))
    6. match (value.div(zero)) {
    7. case Err(_) => io.writeLine("division rejected")
    8. case Ok(_) => io.writeLine("accepted")
    9. }
    10. match (value.mod(zero)) {
    11. case Err(_) => io.writeLine("remainder rejected")
    12. case Ok(_) => io.writeLine("accepted")
    13. }
    14. io.writeLine(value.toString(10))
    15. io.writeLine(zero.toString(10))
    Expected outputexit 0
    division rejected
    remainder rejected
    7
    0
    
    $ topaz run main.tpz · target product 5.21.3
    Expected result

    Expected result

    Execution completes. Exit code 0.

    Expected stdout
    1. division rejected
    2. remainder rejected
    3. 7
    4. 0
    Source evidence

    Evaluate the receiver before the divisor

    Link
    main.tpzEvaluate the receiver before the divisorOpen in Playground
    1. import std.bigint { BigInt }
    2. import std.test
    3. import std.io
    4. function receiver() -> BigInt {
    5. io.writeLine("receiver")
    6. return test.assertSome(BigInt.parse("7", 10))
    7. }
    8. function divisor() -> BigInt {
    9. io.writeLine("divisor")
    10. return test.assertSome(BigInt.parse("3", 10))
    11. }
    12. let quotient = test.assertOk(receiver().div(divisor()))
    13. io.writeLine(quotient.toString(10))
    Expected outputexit 0
    receiver
    divisor
    2
    
    $ topaz run main.tpz · target product 5.21.3
    Expected result

    Expected result

    Execution completes. Exit code 0.

    Expected stdout
    1. receiver
    2. divisor
    3. 2
    Source evidence

    Menu

    Download