module math

module lib/math.mu

import "math"

math provides a collection of mathematical functions.

Imports

Functions

abs#

fn abs(n)

abs returns the magnitude of n, dropping its sign.

Source lib/math.mu:23
fn abs(n) {
  if n < 0 {
    return -n
  }
  return n
}

bin#

fn bin(value)

bin returns the binary literal of value with a 0b prefix.

Source lib/math.mu:186
fn bin(value) {
  return _format_with_prefix(value, 2, "0b", false)
}

ceil_div#

fn ceil_div(a, b)

ceil_div performs ceil division for integers, rounding toward positive infinity.

Source lib/math.mu:115
fn ceil_div(a, b) {
  if b == 0 {
    return error("ceil_div div by zero")
  }
  if a % b == 0 {
    return a / b
  }
  if a > 0 && b > 0 {
    return a / b + 1
  }
  if a < 0 && b < 0 {
    return a / b + 1
  }
  return a / b
}

clamp#

fn clamp(value, low, high)

clamp limits value to the inclusive [low, high] range.

Source lib/math.mu:31
fn clamp(value, low, high) {
  if low > high {
    return error("clamp range is inverted")
  }
  if value < low {
    return low
  }
  if value > high {
    return high
  }
  return value
}

cos_scaled#

fn cos_scaled(degrees, bits)

cos_scaled returns cos(degrees) * 2^bits.

Source lib/math.mu:297
fn cos_scaled(degrees, bits) {
  pair := sin_cos_scaled(degrees, bits)
  if is_error(pair) {
    return pair
  }
  return pair[1]
}

div_mod#

fn div_mod(value, divisor)

div_mod returns quotient and remainder while keeping remainder non-negative, matching the floor mod semantics the time helpers expect.

Source lib/math.mu:148
fn div_mod(value, divisor) {
  quotient := value / divisor
  remainder := value % divisor
  if remainder < 0 {
    remainder = remainder + divisor
    quotient = quotient - 1
  }
  return [quotient, remainder]
}

format_int#

fn format_int(args...)

format_int renders value in the requested base (2-36) bits using optional uppercase digits. format_int(value, base, uppercase?) -> string | ERROR The uppercase flag defaults to false when omitted.

Source lib/math.mu:161
fn format_int(args...) {
  // check if len(args) is between 2 and 3
  count := len(args)
  if count < 2 || count > 3 {
    return error("math.format_int expects 2 or 3 arguments")
  }
  value := args[0]
  base := args[1]
  if !typing.is_int(base) {
    return error("math.format_int base must be an integer")
  }
  if base < 2 || base > 36 {
    return error("math.format_int base must be between 2 and 36")
  }
  uppercaseFlag := false
  if len(args) == 3 {
    if !typing.is_bool(args[2]) {
      return error("math.format_int uppercase flag must be a boolean")
    }
    uppercaseFlag = args[2]
  }
  return _format_signed(value, base, uppercaseFlag)
}

gcd#

fn gcd(a, b)

gcd returns the greatest common divisor of a and b.

Source lib/math.mu:132
fn gcd(a, b) {
  if a < 0 {
    a = -a
  }
  if b < 0 {
    b = -b
  }
  while b != 0 {
    t := b
    b = a % b
    a = t
  }
  return a
}

hex#

fn hex(value)

hex returns the lowercase hexadecimal literal of value with a 0x prefix.

Source lib/math.mu:191
fn hex(value) {
  return _format_with_prefix(value, 16, "0x", false)
}

is_even#

fn is_even(n)

is_even reports whether n is divisible by 2.

Source lib/math.mu:56
fn is_even(n) {
  return n % 2 == 0
}

is_odd#

fn is_odd(n)

is_odd reports whether n is not divisible by 2.

Source lib/math.mu:61
fn is_odd(n) {
  return n % 2 != 0
}

max#

fn max(a, b)

max returns the larger of a and b.

Source lib/math.mu:15
fn max(a, b) {
  if a > b {
    return a
  }
  return b
}

min#

fn min(a, b)

min returns the smaller of a and b.

Source lib/math.mu:7
fn min(a, b) {
  if a < b {
    return a
  }
  return b
}

normalise_degrees#

fn normalise_degrees(degrees)

normalise_degrees folds an angle into [0, 360).

Source lib/math.mu:306
fn normalise_degrees(degrees) {
  h := degrees % 360
  if h < 0 {
    h = h + 360
  }
  return h
}

num_digits#

fn num_digits(n)

num_digits counts decimal digits of n (base 10).

Source lib/math.mu:99
fn num_digits(n) {
  if n == 0 {
    return 1
  }
  if n < 0 {
    n = -n
  }
  d := 0
  while n > 0 {
    n = n / 10
    d = d + 1
  }
  return d
}

oct#

fn oct(value)

oct returns the octal literal of value with a 0o prefix.

Source lib/math.mu:196
fn oct(value) {
  return _format_with_prefix(value, 8, "0o", false)
}

parse_bin#

fn parse_bin(text)

parse_bin returns the integer value of the binary literal, supporting optional 0b/0B prefix.

Source lib/math.mu:223
fn parse_bin(text) {
  return _parse_int_text(text, 2, "0b", "math.parse_bin")
}

parse_hex#

fn parse_hex(text)

parse_hex returns the integer value of the hexadecimal literal, supporting 0x/0X prefix.

Source lib/math.mu:228
fn parse_hex(text) {
  return _parse_int_text(text, 16, "0x", "math.parse_hex")
}

parse_int#

fn parse_int(args...)

parse_int parses text as an integer using the optional base (default 10). parse_int(text, base?) -> int | ERROR

Source lib/math.mu:202
fn parse_int(args...) {
  count := len(args)
  if count < 1 || count > 2 {
    return error("math.parse_int expects 1 or 2 arguments")
  }
  text := args[0]
  base := 10
  if count == 2 {
    baseArg := args[1]
    if !typing.is_int(baseArg) {
      return error("math.parse_int base must be an integer")
    }
    base = baseArg
  }
  if base < 2 || base > 36 {
    return error("math.parse_int base must be between 2 and 36")
  }
  return _parse_int_text(text, base, nil, "math.parse_int")
}

parse_oct#

fn parse_oct(text)

parse_oct returns the integer value of the octal literal, supporting 0o/0O prefix.

Source lib/math.mu:233
fn parse_oct(text) {
  return _parse_int_text(text, 8, "0o", "math.parse_oct")
}

pow_10#

fn pow_10(k)

pow_10 returns 10^k for non-negative k.

Source lib/math.mu:88
fn pow_10(k) {
  n := 1
  i := 0
  while i < k {
    n = n * 10
    i = i + 1
  }
  return n
}

sign#

fn sign(n)

sign returns -1 for negative, 1 for positive, and 0 for zero.

Source lib/math.mu:45
fn sign(n) {
  if n < 0 {
    return -1
  }
  if n > 0 {
    return 1
  }
  return 0
}

sin_cos_scaled#

fn sin_cos_scaled(degrees, bits)

sin_cos_scaled returns [sin, cos] of an integer number of degrees, each multiplied by 2^bits. bits may be 0..30; 30 is the precision the computation is carried out at, and anything smaller is shifted down from it.

math.sin_cos_scaled(90, 16)   ->  [65536, 0]

The four cardinal angles are answered exactly rather than approximated, so a quarter turn is precisely a quarter turn.

Source lib/math.mu:272
fn sin_cos_scaled(degrees, bits) {
  if !typing.is_int(degrees) {
    return error("math.sin_cos_scaled expects integer degrees, got " + type(degrees))
  }
  if !typing.is_int(bits) || bits < 0 || bits > _TRIG_BITS {
    return error("math.sin_cos_scaled expects bits in 0.." + str(_TRIG_BITS) + ", got " + inspect(bits))
  }
  pair := _sin_cos_q30(degrees)
  if bits == _TRIG_BITS {
    return pair
  }
  shift := _TRIG_BITS - bits
  return [pair[0] >> shift, pair[1] >> shift]
}

sin_scaled#

fn sin_scaled(degrees, bits)

sin_scaled returns sin(degrees) * 2^bits.

Source lib/math.mu:288
fn sin_scaled(degrees, bits) {
  pair := sin_cos_scaled(degrees, bits)
  if is_error(pair) {
    return pair
  }
  return pair[0]
}

sqrt#

fn sqrt(n)

sqrt returns the square root of n

Source lib/math.mu:66
fn sqrt(n) {
  if n < 0 {
    return error("Square root of a negative number is undefined.")
  }

  if n < 2 {
    return n
  }

  // Initial guess: n // 2 or closer approximation
  x := n
  y := (x + 1) / 2

  while y < x {
    x = y
    y = (x + n / x) / 2
  }

  return x
}

Internal helpers

Underscore-prefixed names are implementation detail. They are listed so the module's source reads without surprises, not as API — they may change at any time.

_CORDIC_ATANatan(2^-i) in degrees * 1,000,000.
_CORDIC_KCORDIC gain compensation in Q30: 0.607252935 * 2^30.
_TRIG_BITSThe scale the CORDIC works in: one unit is 2^-30.
_TRIG_ONE
_digit_char(digit_value, uppercase_flag)digit_char returns the character representing digit_value for the given base.
_digit_value(ch)digit_value returns the numeric value of ch or -1 when invalid.
_format_signed(value, base, uppercase_flag)format_signed renders value in base while keeping the sign.
_format_unsigned(value, base, uppercase_flag)format_unsigned renders the non-negative value in the provided base.
_format_with_prefix(value, base, prefix, uppercase_flag)format_with_prefix renders value and prepends prefix if provided.
_matches_prefix_ignore_case(text, prefix, idx)matches_prefix_ignore_case compares prefix with text starting at idx, ignoring ASCII case.
_parse_int_text(text, base, prefix, func_name)parse_int_text reads a signed integer in the specified base, allowing the optional prefix.
_sin_cos_q30(degrees)_sin_cos_q30 returns [sin, cos] scaled by 2^30.
_skip_prefix(text, idx, prefix)skip_prefix consumes prefix (if present) from text[idx:].