Skip to Content

Math

Introduction

import 'math';

The math module has the arithmetic most programs eventually need: square roots and powers, trigonometry, logarithms, rounding, abs, min, max and clamp, and conversions between whole numbers and floats.

import 'math'; float side = math.sqrt(3.0 * 3.0 + 4.0 * 4.0); print(side); // 5 print(math.round(2.5), math.floor(-2.5)); // 3 -3 print(math.clamp(15, 0, 10)); // 10 print(math.toInt(side) + 1); // 6

Notes

  • Impossible results do not stop the program. math.sqrt(-1.0) gives NaN (“not a number”), math.log(0.0) gives -inf, and math.pow(10.0, 400.0) gives inf. This is what the float operators already do (1.0 / 0.0 is inf), and what C, Go, Rust and JavaScript do, so a formula copied from any of them gives the same answers. print writes these values as nan, inf and -inf.
  • NaN is not equal to anything, not even itself, so use math.isNaN and math.isInfinite to test for them.
  • The float functions take a float. math.sqrt(4) is a compile error, because 4 is a whole number; write math.sqrt(4.0). A float32 works anywhere a float does.
  • abs, min, max and clamp take any number type. The arguments follow the same rules as +: they must be from the same family (signed, unsigned, or float), and the result has the type + would give. A plain number written next to a value takes that value’s type, so math.max(u, 0) works when u is a uint.
  • toInt and toFloat convert between whole numbers and floats, which as does not do (see the as expression). A conversion like that has to decide how to round, and toInt always cuts toward zero. To round another way, call floor, ceil or round first.

math.PI and math.E

float math.PI // 3.141592653589793 float math.E // 2.718281828459045

The two constants, as float values.

import 'math'; float radius = 2.0; print(math.PI * radius * radius); // 12.566370614359172

math.sqrt()

float math.sqrt(float x)

Returns the square root of x. A negative x gives NaN.

import 'math'; print(math.sqrt(16.0)); // 4

math.pow()

float math.pow(float x, float y)

Returns x raised to the power y.

import 'math'; print(math.pow(2.0, 10.0)); // 1024 print(math.pow(9.0, 0.5)); // 3

math.sin(), math.cos() and math.tan()

float math.sin(float x) float math.cos(float x) float math.tan(float x)

The sine, cosine and tangent of an angle. The angle is in radians, so a full turn is 2.0 * math.PI.

import 'math'; print(math.sin(0.0)); // 0 print(math.cos(math.PI)); // -1

math.asin(), math.acos() and math.atan()

float math.asin(float x) float math.acos(float x) float math.atan(float x)

The inverse functions: they take a ratio and return an angle in radians.

import 'math'; print(math.acos(-1.0) == math.PI); // true

math.atan2()

float math.atan2(float y, float x)

Returns the angle, in radians, from the positive x axis to the point (x, y). Unlike atan(y / x), it knows which quarter of the plane the point is in, and it works when x is zero. Note that y comes first.

import 'math'; print(math.atan2(1.0, 1.0) == math.PI / 4.0); // true

math.log(), math.log2() and math.log10()

float math.log(float x) float math.log2(float x) float math.log10(float x)

The logarithm of x in base e, base 2, and base 10. log(0.0) is -inf, and a negative x gives NaN.

import 'math'; print(math.log2(1024.0)); // 10 print(math.log10(1000.0)); // 3

math.exp()

float math.exp(float x)

Returns e raised to the power x. It is the inverse of math.log.

import 'math'; print(math.exp(0.0)); // 1 print(math.exp(1.0) == math.E); // true

math.floor(), math.ceil() and math.round()

float math.floor(float x) float math.ceil(float x) float math.round(float x)

Round x to a whole number, but keep it a float: floor rounds down, ceil rounds up, and round goes to the nearest whole number, with a half rounding away from zero.

import 'math'; print(math.floor(2.7), math.ceil(2.1)); // 2 3 print(math.round(2.5), math.round(-2.5)); // 3 -3

math.isNaN() and math.isInfinite()

bool math.isNaN(float x) bool math.isInfinite(float x)

Report whether x is NaN, or whether it is inf or -inf. You need these because NaN is never equal to anything, so x == x is false when x is NaN.

import 'math'; float bad = math.sqrt(-1.0); print(math.isNaN(bad)); // true print(math.isInfinite(1.0 / 0.0)); // true

math.toInt()

int math.toInt(float x)

Converts a float to an int by dropping the fractional part, so it always rounds toward zero. Round first with floor, ceil or round if you want something else.

Warning

toInt is the one function in this module that can stop the program: it is a runtime error when x is NaN, infinite, or too large to fit in an int.

import 'math'; print(math.toInt(2.9), math.toInt(-2.9)); // 2 -2 print(math.toInt(math.round(2.9))); // 3

math.toFloat()

float math.toFloat(integer n)

Converts a whole number of any integer type, signed or unsigned, to the nearest float. It never fails.

import 'math'; print(math.toFloat(7) / 2.0); // 3.5 uint count = 3; print(math.toFloat(count)); // 3

math.abs()

T math.abs(T x)

Returns the size of x without its sign. It works on every number type.

import 'math'; int n = -3; float f = -2.5; print(math.abs(n), math.abs(f)); // 3 2.5

math.min() and math.max()

T math.min(T a, T b) T math.max(T a, T b)

Return the smaller, and the larger, of two numbers. When one of two floats is NaN, the other one is returned.

import 'math'; int n = -3; print(math.min(n, 2), math.max(n, 2)); // -3 2

math.clamp()

T math.clamp(T x, T lo, T hi)

Keeps x between lo and hi: it returns lo when x is below it, hi when x is above it, and x otherwise.

import 'math'; print(math.clamp(-3, 0, 10)); // 0 print(math.clamp(-2.5, -1.0, 1.0)); // -1