Math utilities for numberscope

Generally speaking, you should obtain all of your functions for doing math in frontscope code from this incorporated shared/math module. It is based primarily on the mathjs package.

Note in particular that you should only use the random number generators from mathjs supplied by this module, namely math.random(), math.randomInt(), and/or math.pickRandom(). The testing framework used for frontscope will fail if the built-in JavaScript Math.random() is used.

Other than that, only the Numberscope extensions to mathjs are documented below; refer to the mathjs documentation to see all of the other facilities available. We also have some additional tips for working with bigint numbers in Numberscope.

Note that currently all of the numerical extension functions described below accept either number or bigint inputs for all arguments and convert them to bigints as needed.

In addition, math formulas may create and manipulate colors using Chroma objects and functions. The formulas extend the hue argument to of the rainbow function to any value that can be converted into a bigint or number, and to complex numbers by taking their so-called argument angle as the hue angle.

Example usage

import {math} from '@/shared/math'

// Example of a standard mathjs function: random integer
// from 1, 2, 3, 4, 5, 6 (note right endpoint is exclusive).
const myDie: number = math.randomInt(1, 7)

// Remaining examples are Numberscope extensions
try {
  const myNumber = math.safeNumber(9007199254740992n)
} catch (err: unknown) {
  console.log('This will always be logged')
}
try {
  const myNumber = math.safeNumber(9007n)
} catch (err: unknown) {
  console.log('This will never be logged and myNumber will be 9007')
}

// ExtendedBigint is the type of bigints completed with ±infinity
const inf: ExtendedBigint = math.posInfinity
const neginf: ExtendedBigint = math.negInfinity

// Like Math.floor, but with BigInt result type:
const negTwo: bigint = math.bigInt(-1.5)

const fifteen: number = math.triangular(5)
const four: bigint = math.invTriangular(14n)

const five: bigint = math.floorSqrt(30n)
const negativeTwo: bigint = math.floorSqrt(-2n)

const three: bigint = math.modulo(-7n, 5)
const two: bigint = math.modulo(7, 5n)

const isFactor: boolean = math.divides(6, 24n) // true
const isntFactor: boolean = math.divides(7n, 12) // false

const six: bigint = math.powmod(6, 2401n, 7n)
// n to the p is congruent to n mod a prime p,
// so a to any power of p is as well.

const fortysixish: number = math.natlog(100000000000000000000n)

const seven: bigint = math.bigabs(-7n)

const twelve: ExtendedBigint = math.bigmax(5n, 12, -3)
const negthree: ExtendedBigint = math.bigmin(5n, 12, -3)
const anotherNegInf = math.bigmin(5n, math.negInfinity, -3)

const orangey = math.evaluate('rainbow(1+i)')
// depends just on arg of a complex number input

Detailed function reference

triangular(n: number | bigint): typeof n

Returns the n-th triangular number, preserving the type of the input.

invTriangular(t: number | bigint): typeof t

Returns the index of the largest triangular number less than or equal to t, again preserving the type of the input.

safeNumber(n: MathType): number

Returns the number mathematically equal to n if there is one, or throws an error otherwise.

floorSqrt(n: number | bigint): bigint

Returns the largest bigint r such that the square of r is less than or equal to n, if there is one; otherwise returns the bigint mathematically equal to n. (Thus, it leaves negative bigints unchanged.)

modulo(n: number | bigint, modulus: number | bigint): bigint

Returns the smallest nonnegative bigint congruent to n modulo modulus; this is also the remainder upon dividing n by modulus. Note that this is the "mathematician's modulus" that never returns a negative value, unlike the built-in JavaScript % operator.

Throws a RangeError if modulus is nonpositive.

divides(a: number| bigint, b: number | bigint): boolean

Returns true if and only if the integer a divides (evenly into) the integer b.

powmod(n, exponent, modulus): bigint

All parameters have type number | bigint. If modulus is nonpositive, throws a RangeError.

Otherwise, if exponent is positive, returns the smallest nonnegative bigint congruent to n raised to the exponent power modulo modulus (but far more efficiently than computing modulo(n**exponent, modulus)).

If exponent is negative, first computes i = powmod(n, -exponent, modulus). If i has a multiplicative inverse modulo modulus, returns that inverse, otherwise throws a RangeError.

natlog(n: number | bigint): number

Returns the natural log of the input.

bigInt(n: number | bigint): bigint

Returns the floor of n as a bigint

bigabs(n: number | bigint): bigint

returns the absolute value of a bigint or an integer number

bigmax(...args: number | bigint): ExtendedBigint

returns the largest its arguments, which may be bigints and/or integer numbers. Note the result has to be an extended bigint because one of the numbers might be Infinity.

bigmin(...args: number | bigint): ExtendedBigint

returns the smallest of its arguments, with the same conditions as bigmax.