Current section
Files
Jump to
Current section
Files
src/bigi.gleam
import gleam/order
/// A big integer.
pub type BigInt
/// Create a big integer representing zero.
@external(erlang, "bigi_ffi", "zero")
@external(javascript, "./bigi_ffi.mjs", "zero")
pub fn zero() -> BigInt
/// Create a big integer from a regular integer.
@external(erlang, "bigi_ffi", "from")
@external(javascript, "./bigi_ffi.mjs", "from")
pub fn from_int(int: Int) -> BigInt
/// Convert the big integer to a regular integer.
///
/// In Erlang, this cannot fail, as all Erlang integers are big integers. In the
/// JavaScript target, this will fail if the integer is bigger than the
/// [maximum safe integer](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/MAX_SAFE_INTEGER)
/// or smaller than the
/// [minimum safe integer](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/MIN_SAFE_INTEGER).
@external(erlang, "bigi_ffi", "to")
@external(javascript, "./bigi_ffi.mjs", "to")
pub fn to_int(bigint: BigInt) -> Result(Int, Nil)
/// Convert the big integer into a simple string - a sequence of digits.
@external(erlang, "erlang", "integer_to_binary")
@external(javascript, "./bigi_ffi.mjs", "to_string")
pub fn to_string(bigint: BigInt) -> String
/// Compare two big integers, returning an order that denotes if `b` is lower,
/// bigger than, or equal to `a`.
@external(erlang, "bigi_ffi", "compare")
@external(javascript, "./bigi_ffi.mjs", "compare")
pub fn compare(a: BigInt, with b: BigInt) -> order.Order
/// Get the absolute value of a big integer.
@external(erlang, "erlang", "abs")
@external(javascript, "./bigi_ffi.mjs", "absolute")
pub fn absolute(bigint: BigInt) -> BigInt
/// Add two big integers together.
@external(erlang, "bigi_ffi", "add")
@external(javascript, "./bigi_ffi.mjs", "add")
pub fn add(a: BigInt, b: BigInt) -> BigInt
/// Subtract the subtrahend from the minuend.
@external(erlang, "bigi_ffi", "subtract")
@external(javascript, "./bigi_ffi.mjs", "subtract")
pub fn subtract(minuend a: BigInt, subtrahend b: BigInt) -> BigInt
/// Multiply two big integers together.
@external(erlang, "bigi_ffi", "multiply")
@external(javascript, "./bigi_ffi.mjs", "multiply")
pub fn multiply(a: BigInt, b: BigInt) -> BigInt
/// Divide the dividend with the divisor using integer division.
///
/// Follows the standard Gleam divide-by-zero rule of 0 when the divisor is 0.
@external(erlang, "bigi_ffi", "divide")
@external(javascript, "./bigi_ffi.mjs", "divide")
pub fn divide(dividend a: BigInt, divisor b: BigInt) -> BigInt
/// Divide the dividend with the divisor using integer division.
///
/// Returns an error if the divisor is 0.
@external(erlang, "bigi_ffi", "divide_no_zero")
@external(javascript, "./bigi_ffi.mjs", "divide_no_zero")
pub fn divide_no_zero(
dividend a: BigInt,
divisor b: BigInt,
) -> Result(BigInt, Nil)
/// Divide the dividend with the divisor using integer division and return the
/// remainder.
///
/// Follows the standard Gleam divide-by-zero rule of 0 when the divisor is 0.
@external(erlang, "bigi_ffi", "remainder")
@external(javascript, "./bigi_ffi.mjs", "remainder")
pub fn remainder(dividend a: BigInt, divisor b: BigInt) -> BigInt
/// Divide the dividend with the divisor using integer division and return the
/// remainder.
///
/// Returns an error if the divisor is 0.
@external(erlang, "bigi_ffi", "remainder_no_zero")
@external(javascript, "./bigi_ffi.mjs", "remainder_no_zero")
pub fn remainder_no_zero(
dividend a: BigInt,
divisor b: BigInt,
) -> Result(BigInt, Nil)
/// Calculate a mathematical modulo operation.
///
/// Follows the standard Gleam divide-by-zero rule of 0 when the divisor is 0.
@external(erlang, "bigi_ffi", "modulo")
@external(javascript, "./bigi_ffi.mjs", "modulo")
pub fn modulo(dividend a: BigInt, divisor b: BigInt) -> BigInt
/// Calculate a mathematical modulo operation.
///
/// Returns an error if the divisor is 0.
@external(erlang, "bigi_ffi", "modulo_no_zero")
@external(javascript, "./bigi_ffi.mjs", "modulo_no_zero")
pub fn modulo_no_zero(
dividend a: BigInt,
divisor b: BigInt,
) -> Result(BigInt, Nil)
/// Raise the base to the exponent.
@external(erlang, "bigi_ffi", "power")
@external(javascript, "./bigi_ffi.mjs", "power")
pub fn power(base a: BigInt, exponent b: BigInt) -> BigInt
/// Get the digits in a given bigint as a list of integers.
///
/// The list is ordered starting from the most significant digit.
pub fn digits(bigint: BigInt) {
let divisor = from_int(10)
get_digit(bigint, [], divisor)
}
fn get_digit(bigint: BigInt, digits: List(Int), divisor: BigInt) {
case compare(bigint, divisor) {
order.Gt -> {
let assert Ok(digit) = to_int(bigint)
[digit, ..digits]
}
_ -> {
let assert Ok(digit) =
remainder(bigint, divisor)
|> to_int()
let digits = [digit, ..digits]
get_digit(divide(bigint, divisor), digits, divisor)
}
}
}