moonmath the arithmetic of space

Every public name

One entry per type, field, variant, method and value, in the words the source wrote for it. Grouped by what the thing is for; the page is generated from the interfaces and the doc comments, so it cannot drift from the code without the build saying so.

Values

18

Scalars, angles and the easing functions, which belong to no type.

approxfunction

pub fn approx(Float, Float, eps? : Float) -> Bool

Whether two numbers are the same to within eps.

Without an epsilon the comparison uses default_epsilon, scaled up for values whose magnitude would swamp an absolute tolerance. Equality itself is exact — == on two numbers that took different paths to the same place rarely holds — so this is the test callers want for results of arithmetic.

mbt check
test {
let a : Float = 0.1 + 0.2
assert_true(@moonmath.approx(a, 0.3))
assert_false(@moonmath.approx(a, 0.31))
assert_true(@moonmath.approx(a, 0.31, eps=0.02))
}

approx_anglefunction

pub fn approx_angle(Float, Float, eps? : Float) -> Bool

Whether two angles — in radians, wrapping at tau — point the same way.

0 and tau are the same direction, and so are -pi and pi; comparing them as plain numbers says otherwise.

clamp01function

pub fn clamp01(Float) -> Float

value pinned to 0..1.

default_epsilonvalue

pub let default_epsilon : Float

The absolute tolerance approx falls back on when the caller gives none.

It is a compromise: large enough to cover the rounding of a handful of operations at this precision, small enough that values a user would call different do not compare equal.

half_pivalue

pub let half_pi : Float

Half a turn in radians: pi / 2. A quarter of tau.

hsv_to_rgbfunction

pub fn hsv_to_rgb(Color3) -> Color3

The colour a hue, saturation and value describe, read the way rgb_to_hsv writes them.

inverse_lerpfunction

pub fn inverse_lerp(Float, Float, Float) -> Float

Where value sits between start and end, as a fraction: the inverse of lerp.

Returns zero when the two ends are equal — there is no fraction between them, and zero is the answer that keeps lerp from producing a NaN.

lerpfunction

pub fn lerp(Float, Float, Float) -> Float

The point t of the way from a to b: a at zero, b at one.

t outside 0..1 extrapolates, which is what callers building animation curves usually want; clamp the result if it is not.

pivalue

pub let pi : Float

The ratio of a circle's circumference to its diameter.

quarter_pivalue

pub let quarter_pi : Float

A quarter turn in radians: pi / 4, the angle whose tangent is one.

remapfunction

pub fn remap(Float, Float, Float, Float, Float) -> Float

value taken from the range from_start..from_end and placed in to_start..to_end.

It is lerp(to_start, to_end, inverse_lerp(from_start, from_end, value)): the value keeps its position within the range, and values outside the source range land outside the destination range by the same proportion.

rgb_to_hsvfunction

pub fn rgb_to_hsv(Color3) -> Color3

The hue, saturation and value of a colour, packed into a Color3 as r the hue, g the saturation and b the value.

The hue is a fraction of a turn in 0..1 — a turn rather than degrees or radians, so it lines up with the rest of a graphics pipeline — and the other two are in 0..1. A grey has no hue and comes back as zero.

smoothstepfunction

pub fn smoothstep(Float, Float, Float) -> Float

A smooth step from zero at start to one at end, zero slope at both ends.

The curve is 3t² - 2t³ over the normalised position, which is the cheapest easing whose first derivative vanishes at both ends — no visible corner where the animation starts or stops.

A zero-width range has no slope to smooth: it steps at start.

tauvalue

pub let tau : Float

A full turn in radians: 2 * pi. The period of every angle here.

to_degreesfunction

pub fn to_degrees(Float) -> Float

radians converted to degrees.

to_radiansfunction

pub fn to_radians(Float) -> Float

degrees converted to radians.

wrapfunction

pub fn wrap(Float, Float) -> Float

value folded into 0..span.

Angles and texture coordinates repeat, and a value that has run past the end of its range has to come back to the start rather than stop there. A span of zero or less has nothing to fold into and gives zero.

mbt check
test {
assert_eq(@moonmath.wrap(7.5, 5.0), 2.5)
assert_eq(@moonmath.wrap(-1.0, 5.0), 4.0)
}

wrap_rangefunction

pub fn wrap_range(Float, Float, Float) -> Float

value folded into start..end.

wrap(value - start, end - start) + start, with the same half-open result.

Half precision

1

A 16-bit float, the storage format a texture or a packed vertex uses.

Halfstruct

pub struct Half

A 16-bit IEEE 754 binary16 value: the half precision a texture, a packed vertex or a GPU buffer carries when thirty-two bits are more than the data needs and sixteen are enough.

The value is the sixteen bits themselves, so a half read from a buffer is from_bits and one written back is to_bits. Arithmetic runs at Float, the precision the rest of this library works in: a half is a storage format, not a second arithmetic. Conversion rounds to nearest with ties to even, as the standard and the graphics formats do, and the special values — signed zeros, the two infinities, a quiet NaN and the subnormals — survive the round trip.

Fixed at sixteen bits, this type has no double-precision counterpart; it lives only in the single-precision package.

Fields
bits : UInt16

The sixteen bits, sign, exponent and fraction, in that order.

CarriesDebug, Show

approx

pub fn Half::approx(Self, Self, eps? : Float) -> Bool

Whether the two halves hold the same value to within eps, compared at Float precision.

denorm_min

pub fn Half::denorm_min() -> Self

The smallest positive subnormal, 2^-24.

epsilon

pub fn Half::epsilon() -> Self

The smallest number that, added to one, gives a half different from one: 2^-10.

from_bits

pub fn Half::from_bits(UInt16) -> Self

The half made of the sixteen raw bits, as a buffer holds it.

from_float

pub fn Half::from_float(Float) -> Self

The 16-bit encoding of value, rounded to the nearest representable half, ties to even.

Values beyond the largest finite half become an infinity of the same sign; values below the smallest subnormal become a signed zero; a NaN stays a NaN.

is_denormal

pub fn Half::is_denormal(Self) -> Bool

Whether the half is a subnormal: non-zero, smaller than the smallest normal.

is_finite

pub fn Half::is_finite(Self) -> Bool

Whether the half is neither an infinity nor a NaN.

is_inf

pub fn Half::is_inf(Self) -> Bool

Whether the half is an infinity, of either sign.

is_nan

pub fn Half::is_nan(Self) -> Bool

Whether the half is a NaN.

is_normal

pub fn Half::is_normal(Self) -> Bool

Whether the half is a normal number: not zero, not subnormal, not infinite.

lowest

pub fn Half::lowest() -> Self

The most negative finite half, -65504.

max

pub fn Half::max() -> Self

The largest finite half, 65504.

min

pub fn Half::min() -> Self

The smallest positive normal, 2^-14.

nan

pub fn Half::nan() -> Self

A quiet NaN.

neg_infinity

pub fn Half::neg_infinity() -> Self

Negative infinity.

one

pub fn Half::one() -> Self

One.

pos_infinity

pub fn Half::pos_infinity() -> Self

Positive infinity.

to_bits

pub fn Half::to_bits(Self) -> UInt16

The sixteen raw bits, in the order a buffer expects.

to_float

pub fn Half::to_float(Self) -> Float

The Float the half stands for.

Exact: every half is a Float, though not every Float is a half.

zero

pub fn Half::zero() -> Self

Positive zero.

Vectors

3

Points and directions, and the arithmetic between them.

Vec2struct

pub(all) struct Vec2

A point or a direction in the plane.

Two scalars side by side, in the order the plane's axes are named: x runs east, y runs north. Nothing here knows whether +y points up the screen or down it — that is a convention of the canvas, not of the arithmetic.

Values are immutable; every operation returns a new one.

The operators take two vectors of the same type. There is no Vec2 * Float, because a value can only carry one Mul implementation here: scalar scaling is scale, its inverse divide.

Fields
x : Float

The x component: east.

y : Float

The y component: north.

CarriesAdd, Debug, Div, Mul, Neg, Show, Sub

abs

pub fn Vec2::abs(Self) -> Self

The vector with every component replaced by its absolute value.

angle_between

pub fn Vec2::angle_between(Self, Self) -> Float

The angle from self to other, in radians, positive counter-clockwise.

Signed, because in the plane there are only two ways to turn and the sign says which. The result is in -pi..pi, and is zero when either vector has no direction.

mbt check
test {
let x : @moonmath.Vec2 = @moonmath.Vec2::unit_x()
let y = @moonmath.Vec2::unit_y()
assert_true(@moonmath.approx(x.angle_between(y), @moonmath.half_pi))
}

approx

pub fn Vec2::approx(Self, Self, eps? : Float) -> Bool

Whether the two vectors agree to within eps component by component.

Without an epsilon this uses default_epsilon.

ceil

pub fn Vec2::ceil(Self) -> Self

The vector with every component rounded up to a whole number.

clamp

pub fn Vec2::clamp(Self, Self, Self) -> Self

The vector with every component pinned between low and high.

cross

pub fn Vec2::cross(Self, Self) -> Float

The 2D cross product: the signed area of the parallelogram the two span.

Positive when other lies counter-clockwise of self, which is the sign a winding test reads.

distance

pub fn Vec2::distance(Self, Self) -> Float

The distance between the two points.

distance_squared

pub fn Vec2::distance_squared(Self, Self) -> Float

The square of the distance between the two points.

divide

pub fn Vec2::divide(Self, Float) -> Self

The vector divided by divisor, component by component.

Dividing by zero gives an infinity or a NaN, as the scalar division does; no check is made here.

dot

pub fn Vec2::dot(Self, Self) -> Float

The dot product: length * other.length * cos(angle) between them.

Positive when they point the same way, negative when they oppose, zero when they are perpendicular. It is also what a shader's dot computes, so the two agree bit for bit when the operands do.

floor

pub fn Vec2::floor(Self) -> Self

The vector with every component rounded down to a whole number.

fract

pub fn Vec2::fract(Self) -> Self

The vector with every component replaced by its fractional part, x - floor(x).

is_finite

pub fn Vec2::is_finite(Self) -> Bool

Whether both components are finite — neither an infinity nor a NaN.

length

pub fn Vec2::length(Self) -> Float

The length of the vector: its distance from the origin.

length_squared

pub fn Vec2::length_squared(Self) -> Float

The square of the length.

Comparing squared lengths orders vectors the same way length does without the square root, which is why range checks in hot loops use it.

lerp

pub fn Vec2::lerp(Self, Self, Float) -> Self

The point a fraction of the way from self to other.

max

pub fn Vec2::max(Self, Self) -> Self

The component-wise larger of the two.

min

pub fn Vec2::min(Self, Self) -> Self

The component-wise smaller of the two.

new

pub fn Vec2::new(Float, Float) -> Self

The vector from x and y.

normalize

pub fn Vec2::normalize(Self) -> Self

The vector scaled to length one, pointing the way it did.

The zero vector has no direction, and this returns zero rather than a NaN or a division by zero: Vec2::zero() is the named answer for "no direction". Callers that need to tell the case apart use try_normalize.

normalize_or

pub fn Vec2::normalize_or(Self, Self) -> Self

The vector scaled to length one, or fallback if it has no direction.

one

pub fn Vec2::one() -> Self

The vector with one in both components.

perp

pub fn Vec2::perp(Self) -> Self

The vector turned a quarter turn counter-clockwise: (-y, x).

project

pub fn Vec2::project(Self, Self) -> Self

The component of self along onto: the shadow it casts on that direction.

onto need not be a unit vector; the result lies along it either way. A zero onto has no direction to project onto and gives zero.

reflect

pub fn Vec2::reflect(Self, Self) -> Self

The direction self takes after bouncing off a surface with normal normal.

self is the incoming direction, and normal points out of the surface against it — the result leaves at the mirror angle with the same length. A zero normal returns self unchanged.

refract

pub fn Vec2::refract(Self, Self, Float) -> Self?

The direction self takes after entering a medium with normal normal and index ratio eta, or None when it does not enter at all.

self and normal are taken to be unit length, normal pointing against the incoming direction, and eta the ratio of the indices of refraction on the two sides. Past the critical angle the ray is reflected instead of refracted, and there is no refracted direction to return — that is the None, and it is the caller's job to reflect.

reject

pub fn Vec2::reject(Self, Self) -> Self

The component of self perpendicular to onto: what is left after the projection is taken away.

round

pub fn Vec2::round(Self) -> Self

The vector with every component rounded to the nearest whole number, a half going up: 2.5 becomes 3 and -1.5 becomes -1. This is the rounding Float::round does, in both units and sign.

scale

pub fn Vec2::scale(Self, Float) -> Self

The vector multiplied by factor.

This is the scalar product the * operator cannot express, since * on two vectors is the component-wise one.

splat

pub fn Vec2::splat(Float) -> Self

The same value in both components.

to_array

pub fn Vec2::to_array(Self) -> FixedArray[Float]

The components in order, [x, y], for handing to a buffer.

to_vec3

pub fn Vec2::to_vec3(Self, Float) -> Vec3

The same vector with z appended, for a point being lifted into 3D.

to_vec4

pub fn Vec2::to_vec4(Self, Float, Float) -> Vec4

The same vector with z and w appended.

try_normalize

pub fn Vec2::try_normalize(Self) -> Self?

The vector scaled to length one, or None if it has no direction.

unit_x

pub fn Vec2::unit_x() -> Self

The unit vector along +x.

unit_y

pub fn Vec2::unit_y() -> Self

The unit vector along +y.

yx

pub fn Vec2::yx(Self) -> Self

The components the other way round: (y, x).

zero

pub fn Vec2::zero() -> Self

The zero vector: the origin, and the one vector with no direction.

Vec3struct

pub(all) struct Vec3

A point or a direction in space.

Right-handed: x and y as in the plane, z towards the viewer in the usual camera setup, so that cross(x, y) == z.

Values are immutable; every operation returns a new one.

The operators take two vectors of the same type. Scalar scaling is scale and divide, not * and /, which belong to the component-wise product.

Fields
x : Float

The x component: east.

y : Float

The y component: north.

z : Float

The z component: towards the viewer.

CarriesAdd, Debug, Div, Mul, Neg, Show, Sub

abs

pub fn Vec3::abs(Self) -> Self

The vector with every component replaced by its absolute value.

angle_between

pub fn Vec3::angle_between(Self, Self) -> Float

The angle between the two directions, in radians, in 0..pi.

Unsigned: in space there is no counter-clockwise, so the answer is just how far apart they point. Computed from the normalized dot product, clamped so that rounding cannot push it out of the arc cosine's domain. Zero when either vector has no direction.

mbt check
test {
let x : @moonmath.Vec3 = @moonmath.Vec3::unit_x()
let y = @moonmath.Vec3::unit_y()
assert_true(@moonmath.approx(x.angle_between(y), @moonmath.half_pi))
assert_true(@moonmath.approx(x.angle_between(-x), @moonmath.pi))
}

approx

pub fn Vec3::approx(Self, Self, eps? : Float) -> Bool

Whether the two vectors agree to within eps component by component.

ceil

pub fn Vec3::ceil(Self) -> Self

The vector with every component rounded up to a whole number.

clamp

pub fn Vec3::clamp(Self, Self, Self) -> Self

The vector with every component pinned between low and high.

cross

pub fn Vec3::cross(Self, Self) -> Self

The cross product: the vector perpendicular to both, right-handed.

Its length is the area of the parallelogram they span, so the two are parallel exactly when it is zero. cross(x, y) is z.

distance

pub fn Vec3::distance(Self, Self) -> Float

The distance between the two points.

distance_squared

pub fn Vec3::distance_squared(Self, Self) -> Float

The square of the distance between the two points.

divide

pub fn Vec3::divide(Self, Float) -> Self

The vector divided by divisor, component by component.

Dividing by zero gives an infinity or a NaN, as the scalar division does.

dot

pub fn Vec3::dot(Self, Self) -> Float

The dot product: length * other.length * cos(angle) between them.

floor

pub fn Vec3::floor(Self) -> Self

The vector with every component rounded down to a whole number.

fract

pub fn Vec3::fract(Self) -> Self

The vector with every component replaced by its fractional part.

is_finite

pub fn Vec3::is_finite(Self) -> Bool

Whether every component is finite.

length

pub fn Vec3::length(Self) -> Float

The length of the vector: its distance from the origin.

length_squared

pub fn Vec3::length_squared(Self) -> Float

The square of the length, without the square root.

lerp

pub fn Vec3::lerp(Self, Self, Float) -> Self

The point a fraction of the way from self to other.

max

pub fn Vec3::max(Self, Self) -> Self

The component-wise larger of the two.

min

pub fn Vec3::min(Self, Self) -> Self

The component-wise smaller of the two.

new

pub fn Vec3::new(Float, Float, Float) -> Self

The vector from its three components.

normalize

pub fn Vec3::normalize(Self) -> Self

The vector scaled to length one, pointing the way it did.

The zero vector has no direction, and this returns Vec3::zero() rather than a NaN: the named answer is "no direction", not "undefined". Use try_normalize where the case needs telling apart.

normalize_or

pub fn Vec3::normalize_or(Self, Self) -> Self

The vector scaled to length one, or fallback if it has no direction.

one

pub fn Vec3::one() -> Self

The vector with one in every component.

project

pub fn Vec3::project(Self, Self) -> Self

The component of self along onto.

onto need not be a unit vector. A zero onto gives zero.

random_in_ball

pub fn Vec3::random_in_ball(Float, Float, Float) -> Self

A point uniformly distributed through the unit ball.

u1, u2 and u3 are independent uniform samples in [0, 1). The radius is the cube root of u3, not u3 itself: the volume grows as the cube of the radius, so a linear radius would pile the points near the centre.

random_on_sphere

pub fn Vec3::random_on_sphere(Float, Float) -> Self

A point uniformly distributed over the surface of the unit sphere.

u1 and u2 are independent uniform samples in [0, 1). The height is sampled uniformly rather than the polar angle, which is what keeps the distribution even: sampling the angle uniformly would crowd the poles.

reflect

pub fn Vec3::reflect(Self, Self) -> Self

The direction self takes after bouncing off a surface with normal normal.

self is the incoming direction and normal points out of the surface against it. Both are taken to be unit length, as they are in a shader; the result has the same length as self.

refract

pub fn Vec3::refract(Self, Self, Float) -> Self?

The direction self takes after entering a medium with normal normal and index ratio eta, or None past the critical angle.

self and normal are taken to be unit length, normal pointing against the incoming direction, and eta the ratio of the indices of refraction on the two sides. Past the critical angle the ray is reflected whole and there is no refracted direction: None says so, and reflecting is the caller's business.

mbt check
test {
let down : @moonmath.Vec3 = @moonmath.Vec3::new(0.0, -1.0, 0.0)
let up = @moonmath.Vec3::new(0.0, 1.0, 0.0)
// Straight down onto a surface and straight on through.
let through = down.refract(up, 0.5).unwrap()
assert_true(through.approx(down))
}

reject

pub fn Vec3::reject(Self, Self) -> Self

The component of self perpendicular to onto.

round

pub fn Vec3::round(Self) -> Self

The vector with every component rounded to the nearest whole number, a half going up.

scale

pub fn Vec3::scale(Self, Float) -> Self

The vector multiplied by factor.

splat

pub fn Vec3::splat(Float) -> Self

The same value in all three components.

to_array

pub fn Vec3::to_array(Self) -> FixedArray[Float]

The components in order, [x, y, z], for handing to a buffer.

to_vec4

pub fn Vec3::to_vec4(Self, Float) -> Vec4

The same vector with w appended, for a point being lifted into 4D.

try_normalize

pub fn Vec3::try_normalize(Self) -> Self?

The vector scaled to length one, or None if it has no direction.

unit_x

pub fn Vec3::unit_x() -> Self

The unit vector along +x.

unit_y

pub fn Vec3::unit_y() -> Self

The unit vector along +y.

unit_z

pub fn Vec3::unit_z() -> Self

The unit vector along +z.

xy

pub fn Vec3::xy(Self) -> Vec2

The first two components: the vector projected onto the xy plane.

xz

pub fn Vec3::xz(Self) -> Vec2

The first and third components: the projection onto the xz plane.

xzy

pub fn Vec3::xzy(Self) -> Self

The components in the order (x, z, y), swapping the last two.

yxz

pub fn Vec3::yxz(Self) -> Self

The components in the order (y, x, z), swapping the first two.

yz

pub fn Vec3::yz(Self) -> Vec2

The last two components: the projection onto the yz plane.

yzx

pub fn Vec3::yzx(Self) -> Self

The components in the order (y, z, x), a third of a turn of the axes.

zero

pub fn Vec3::zero() -> Self

The zero vector: the origin, and the one vector with no direction.

zxy

pub fn Vec3::zxy(Self) -> Self

The components in the order (z, x, y), the other third of a turn.

zyx

pub fn Vec3::zyx(Self) -> Self

The components backwards: (z, y, x), which turns a lookup into its mirror.

Vec4struct

pub(all) struct Vec4

Four components: a point in homogeneous coordinates, a colour with alpha, or four numbers that travel together.

A Vec4 is what a Mat4 multiplies, and what a shader writes into a vertex buffer: to_array gives the four in the order the buffer wants them.

Values are immutable; every operation returns a new one.

Fields
x : Float

The x component: east.

y : Float

The y component: north.

z : Float

The z component: towards the viewer.

w : Float

The fourth component: one for a point, zero for a direction.

CarriesAdd, Debug, Div, Mul, Neg, Show, Sub

abs

pub fn Vec4::abs(Self) -> Self

The vector with every component replaced by its absolute value.

approx

pub fn Vec4::approx(Self, Self, eps? : Float) -> Bool

Whether the two vectors agree to within eps component by component.

ceil

pub fn Vec4::ceil(Self) -> Self

The vector with every component rounded up to a whole number.

clamp

pub fn Vec4::clamp(Self, Self, Self) -> Self

The vector with every component pinned between low and high.

distance

pub fn Vec4::distance(Self, Self) -> Float

The distance between the two points, in four dimensions.

distance_squared

pub fn Vec4::distance_squared(Self, Self) -> Float

The square of the distance between the two points.

divide

pub fn Vec4::divide(Self, Float) -> Self

The vector divided by divisor, component by component.

dot

pub fn Vec4::dot(Self, Self) -> Float

The dot product, over all four components.

In homogeneous coordinates this is what a plane's dot does with a point, and what the w component of a transformed vector carries.

floor

pub fn Vec4::floor(Self) -> Self

The vector with every component rounded down to a whole number.

fract

pub fn Vec4::fract(Self) -> Self

The vector with every component replaced by its fractional part.

is_finite

pub fn Vec4::is_finite(Self) -> Bool

Whether every component is finite.

length

pub fn Vec4::length(Self) -> Float

The length of the vector, in four dimensions.

length_squared

pub fn Vec4::length_squared(Self) -> Float

The square of the length, without the square root.

lerp

pub fn Vec4::lerp(Self, Self, Float) -> Self

The point a fraction of the way from self to other, all four components.

max

pub fn Vec4::max(Self, Self) -> Self

The component-wise larger of the two.

min

pub fn Vec4::min(Self, Self) -> Self

The component-wise smaller of the two.

new

pub fn Vec4::new(Float, Float, Float, Float) -> Self

The vector from its four components.

normalize

pub fn Vec4::normalize(Self) -> Self

The vector scaled to length one, or Vec4::zero() if it has no direction.

normalize_or

pub fn Vec4::normalize_or(Self, Self) -> Self

The vector scaled to length one, or fallback if it has no direction.

one

pub fn Vec4::one() -> Self

The vector with one in every component.

round

pub fn Vec4::round(Self) -> Self

The vector with every component rounded to the nearest whole number, a half going up.

scale

pub fn Vec4::scale(Self, Float) -> Self

The vector multiplied by factor.

This is how a homogeneous position is taken out of projective space: divide by w with divide, or scale by its reciprocal.

splat

pub fn Vec4::splat(Float) -> Self

The same value in all four components.

to_array

pub fn Vec4::to_array(Self) -> FixedArray[Float]

The components in order, [x, y, z, w], for handing to a buffer.

try_normalize

pub fn Vec4::try_normalize(Self) -> Self?

The vector scaled to length one, or None if it has no direction.

unit_w

pub fn Vec4::unit_w() -> Self

The unit vector along +w.

unit_x

pub fn Vec4::unit_x() -> Self

The unit vector along +x.

unit_y

pub fn Vec4::unit_y() -> Self

The unit vector along +y.

unit_z

pub fn Vec4::unit_z() -> Self

The unit vector along +z.

wzyx

pub fn Vec4::wzyx(Self) -> Self

All four components backwards: (w, z, y, x).

xy

pub fn Vec4::xy(Self) -> Vec2

The first two components.

xyz

pub fn Vec4::xyz(Self) -> Vec3

The first three components: the position a homogeneous point names, before the division by w.

zero

pub fn Vec4::zero() -> Self

The zero vector.

Integer vectors

6

For grid cells, pixels and indices, where a half is not a position.

IVec2struct

pub(all) struct IVec2

Two whole numbers: a grid cell or a pixel coordinate.

Division is integer division and truncates towards zero, and dividing by zero aborts, as it does for Int itself.

Fields
x : Int32

The x component.

y : Int32

The y component.

CarriesAdd, Debug, Div, Mul, Neg, Show, Sub

abs

pub fn IVec2::abs(Self) -> Self

The pair with every component replaced by its absolute value.

as_vec2

pub fn IVec2::as_vec2(Self) -> Vec2

The same cell as a floating-point vector, exactly.

clamp

pub fn IVec2::clamp(Self, Self, Self) -> Self

The pair with every component pinned between low and high, inclusive.

dot

pub fn IVec2::dot(Self, Self) -> Int32

The dot product, in whole numbers.

from_vec2

pub fn IVec2::from_vec2(Vec2) -> Self

The cell a floating-point position falls in, truncated towards zero.

Truncation rather than rounding, because a pixel coordinate of -0.5 is in cell 0 when the cell is counted from the point, and the caller that wants the floor asks for floor first.

max

pub fn IVec2::max(Self, Self) -> Self

The component-wise larger of the two.

min

pub fn IVec2::min(Self, Self) -> Self

The component-wise smaller of the two.

new

pub fn IVec2::new(Int32, Int32) -> Self

The pair (x, y).

one

pub fn IVec2::one() -> Self

One in both components: the step between neighbouring cells.

splat

pub fn IVec2::splat(Int32) -> Self

The same value in both components.

to_array

pub fn IVec2::to_array(Self) -> FixedArray[Int32]

The components in order, [x, y].

zero

pub fn IVec2::zero() -> Self

The origin of the grid.

IVec3struct

pub(all) struct IVec3

Three whole numbers: a cell in a voxel grid.

Fields
x : Int32

The x component.

y : Int32

The y component.

z : Int32

The z component.

CarriesAdd, Debug, Div, Mul, Neg, Show, Sub

abs

pub fn IVec3::abs(Self) -> Self

The triple with every component replaced by its absolute value.

as_vec3

pub fn IVec3::as_vec3(Self) -> Vec3

The same cell as a floating-point vector, exactly.

clamp

pub fn IVec3::clamp(Self, Self, Self) -> Self

The triple with every component pinned between low and high, inclusive.

dot

pub fn IVec3::dot(Self, Self) -> Int32

The dot product, in whole numbers.

from_vec3

pub fn IVec3::from_vec3(Vec3) -> Self

The cell a floating-point position falls in, truncated towards zero.

max

pub fn IVec3::max(Self, Self) -> Self

The component-wise larger of the two.

min

pub fn IVec3::min(Self, Self) -> Self

The component-wise smaller of the two.

new

pub fn IVec3::new(Int32, Int32, Int32) -> Self

The triple (x, y, z).

one

pub fn IVec3::one() -> Self

One in every component.

splat

pub fn IVec3::splat(Int32) -> Self

The same value in all three components.

to_array

pub fn IVec3::to_array(Self) -> FixedArray[Int32]

The components in order, [x, y, z].

zero

pub fn IVec3::zero() -> Self

The origin of the grid.

IVec4struct

pub(all) struct IVec4

Four whole numbers.

Fields
x : Int32

The x component.

y : Int32

The y component.

z : Int32

The z component.

w : Int32

The fourth component.

CarriesAdd, Debug, Div, Mul, Neg, Show, Sub

abs

pub fn IVec4::abs(Self) -> Self

The quadruple with every component replaced by its absolute value.

as_vec4

pub fn IVec4::as_vec4(Self) -> Vec4

The same values as a floating-point vector, exactly.

clamp

pub fn IVec4::clamp(Self, Self, Self) -> Self

The quadruple with every component pinned between low and high.

dot

pub fn IVec4::dot(Self, Self) -> Int32

The dot product, in whole numbers.

from_vec4

pub fn IVec4::from_vec4(Vec4) -> Self

The values a floating-point vector carries, truncated towards zero.

max

pub fn IVec4::max(Self, Self) -> Self

The component-wise larger of the two.

min

pub fn IVec4::min(Self, Self) -> Self

The component-wise smaller of the two.

new

pub fn IVec4::new(Int32, Int32, Int32, Int32) -> Self

The quadruple (x, y, z, w).

one

pub fn IVec4::one() -> Self

One in every component.

splat

pub fn IVec4::splat(Int32) -> Self

The same value in all four components.

to_array

pub fn IVec4::to_array(Self) -> FixedArray[Int32]

The components in order, [x, y, z, w].

zero

pub fn IVec4::zero() -> Self

The zero vector.

UVec2struct

pub(all) struct UVec2

Two unsigned whole numbers: a size, a count, a pixel coordinate that cannot be negative.

There is no Neg here for the obvious reason: a negative size is not a size. Subtraction is present and wraps, as UInt subtraction does.

Fields
x : UInt32

The x component.

y : UInt32

The y component.

CarriesAdd, Debug, Div, Mul, Show, Sub

as_vec2

pub fn UVec2::as_vec2(Self) -> Vec2

The same size as a floating-point vector, exactly.

clamp

pub fn UVec2::clamp(Self, Self, Self) -> Self

The pair with every component pinned between low and high, inclusive.

dot

pub fn UVec2::dot(Self, Self) -> UInt32

The dot product.

max

pub fn UVec2::max(Self, Self) -> Self

The component-wise larger of the two.

min

pub fn UVec2::min(Self, Self) -> Self

The component-wise smaller of the two.

new

pub fn UVec2::new(UInt32, UInt32) -> Self

The pair (x, y).

one

pub fn UVec2::one() -> Self

One in both components.

splat

pub fn UVec2::splat(UInt32) -> Self

The same value in both components.

to_array

pub fn UVec2::to_array(Self) -> FixedArray[UInt32]

The components in order, [x, y].

zero

pub fn UVec2::zero() -> Self

Zero in both components: an empty size.

UVec3struct

pub(all) struct UVec3

Three unsigned whole numbers.

Fields
x : UInt32

The x component.

y : UInt32

The y component.

z : UInt32

The z component.

CarriesAdd, Debug, Div, Mul, Show, Sub

as_vec3

pub fn UVec3::as_vec3(Self) -> Vec3

The same values as a floating-point vector, exactly.

clamp

pub fn UVec3::clamp(Self, Self, Self) -> Self

The triple with every component pinned between low and high, inclusive.

dot

pub fn UVec3::dot(Self, Self) -> UInt32

The dot product.

max

pub fn UVec3::max(Self, Self) -> Self

The component-wise larger of the two.

min

pub fn UVec3::min(Self, Self) -> Self

The component-wise smaller of the two.

new

pub fn UVec3::new(UInt32, UInt32, UInt32) -> Self

The triple (x, y, z).

one

pub fn UVec3::one() -> Self

One in every component.

splat

pub fn UVec3::splat(UInt32) -> Self

The same value in all three components.

to_array

pub fn UVec3::to_array(Self) -> FixedArray[UInt32]

The components in order, [x, y, z].

zero

pub fn UVec3::zero() -> Self

Zero in every component.

UVec4struct

pub(all) struct UVec4

Four unsigned whole numbers.

Fields
x : UInt32

The x component.

y : UInt32

The y component.

z : UInt32

The z component.

w : UInt32

The fourth component.

CarriesAdd, Debug, Div, Mul, Show, Sub

as_vec4

pub fn UVec4::as_vec4(Self) -> Vec4

The same values as a floating-point vector, exactly.

clamp

pub fn UVec4::clamp(Self, Self, Self) -> Self

The quadruple with every component pinned between low and high.

dot

pub fn UVec4::dot(Self, Self) -> UInt32

The dot product.

max

pub fn UVec4::max(Self, Self) -> Self

The component-wise larger of the two.

min

pub fn UVec4::min(Self, Self) -> Self

The component-wise smaller of the two.

new

pub fn UVec4::new(UInt32, UInt32, UInt32, UInt32) -> Self

The quadruple (x, y, z, w).

one

pub fn UVec4::one() -> Self

One in every component.

splat

pub fn UVec4::splat(UInt32) -> Self

The same value in all four components.

to_array

pub fn UVec4::to_array(Self) -> FixedArray[UInt32]

The components in order, [x, y, z, w].

zero

pub fn UVec4::zero() -> Self

Zero in every component.

Matrices

4

Linear maps, and the four cameras: look_at, perspective, orthographic, frustum.

Mat2struct

pub(all) struct Mat2

A 2×2 matrix, stored as two column vectors.

Column-major, like every matrix here: c0 is the first column, so the matrix that maps x to (a, c) and y to (b, d) is c0 = (a, c), c1 = (b, d), and its x and y are the first and second rows. WGSL writes a mat2x2<f32> in the same order, so to_array goes straight into a buffer.

Values are immutable.

Fields
c0 : Vec2

The first column.

c1 : Vec2

The second column.

CarriesAdd, Debug, Div, Mul, Neg, Show, Sub

approx

pub fn Mat2::approx(Self, Self, eps? : Float) -> Bool

Whether the two matrices agree to within eps element by element.

col

pub fn Mat2::col(Self, Int32) -> Vec2

Column index, counted from zero.

determinant

pub fn Mat2::determinant(Self) -> Float

The signed area the matrix scales by: zero exactly when it is singular.

from_angle

pub fn Mat2::from_angle(Float) -> Self

The matrix that rotates counter-clockwise by radians.

from_array

pub fn Mat2::from_array(FixedArray[Float]) -> Self

The matrix from four values in column-major order: [c0.x, c0.y, c1.x, c1.y].

This is the order a mat2x2<f32> sits in a GPU buffer in, so a matrix read back out of one goes in here unchanged. Aborts if the array does not hold four values.

from_cols

pub fn Mat2::from_cols(Vec2, Vec2) -> Self

The matrix with c0 and c1 as its columns.

from_rows

pub fn Mat2::from_rows(Vec2, Vec2) -> Self

The matrix with r0 and r1 as its rows.

from_scale

pub fn Mat2::from_scale(Vec2) -> Self

The matrix that scales x by s.x and y by s.y.

get

pub fn Mat2::get(Self, Int32, Int32) -> Float

The element at row and column, both counted from zero.

identity

pub fn Mat2::identity() -> Self

The identity: the matrix that changes nothing.

inverse

pub fn Mat2::inverse(Self) -> Self?

The matrix that undoes this one, or None when there is none.

A singular matrix — one with a zero determinant — flattens the plane onto a line or a point, and nothing undoes that. None is the honest answer; the caller decides whether that is an error or a case to handle.

is_finite

pub fn Mat2::is_finite(Self) -> Bool

Whether every element is finite.

mul_vec2

pub fn Mat2::mul_vec2(Self, Vec2) -> Vec2

The vector the matrix takes v to.

Written as one expression per component rather than as the sum of two scaled columns: a Vec2 is a heap value in the native backend, so every intermediate column is an allocation, and there are two of them here for each result.

row

pub fn Mat2::row(Self, Int32) -> Vec2

Row index, counted from zero.

to_angle

pub fn Mat2::to_angle(Self) -> Float

The angle, in radians, the matrix rotates x by.

Only meaningful for a rotation matrix — one built by from_angle, or a linear part that happens to be one; on anything else it reads the direction of the first column.

to_array

pub fn Mat2::to_array(Self) -> FixedArray[Float]

The elements in column-major order, [c0.x, c0.y, c1.x, c1.y], ready for a buffer.

transpose

pub fn Mat2::transpose(Self) -> Self

The matrix with rows and columns exchanged.

zero

pub fn Mat2::zero() -> Self

The zero matrix: the one that sends everything to the origin.

Mat3struct

pub(all) struct Mat3

A 3×3 matrix: a linear map of space, or the upper-left block of a 4×4 one.

Column-major, as mat3x3<f32> is in a buffer: c0 is the first column, and the rows are read across the columns. Rotations, scalings and shears are linear maps, so they need no translation column and live here rather than in Affine3.

Values are immutable.

Fields
c0 : Vec3

The first column.

c1 : Vec3

The second column.

c2 : Vec3

The third column.

CarriesAdd, Debug, Div, Mul, Neg, Show, Sub

approx

pub fn Mat3::approx(Self, Self, eps? : Float) -> Bool

Whether the two matrices agree to within eps element by element.

col

pub fn Mat3::col(Self, Int32) -> Vec3

Column index, counted from zero.

determinant

pub fn Mat3::determinant(Self) -> Float

The signed volume the matrix scales by: zero exactly when it is singular.

from_array

pub fn Mat3::from_array(FixedArray[Float]) -> Self

The matrix from nine values in column-major order.

Aborts if the array does not hold nine values.

from_axis_angle

pub fn Mat3::from_axis_angle(Vec3, Float) -> Self

The rotation of radians about axis, by the right-hand rule.

axis is normalized first; a zero axis has no direction to turn about and gives the identity.

from_cols

pub fn Mat3::from_cols(Vec3, Vec3, Vec3) -> Self

The matrix with the three vecs as its columns.

from_euler

pub fn Mat3::from_euler(EulerOrder, Vec3) -> Self

The rotation the three angles describe, taken in order, read by axis.

The components are the turns about x, y and z, in radians, wherever in the order those axes turn up; see Quat::from_euler, which also says which orders this reading cannot express. from_euler_turns takes the turns in the order the order names them and covers all twelve.

from_euler_turns

pub fn Mat3::from_euler_turns(EulerOrder, Turns) -> Self

The rotation the three turns describe, in the order the order names them.

from_mat4

pub fn Mat3::from_mat4(Mat4) -> Self

The upper-left 3×3 block of a 4×4 matrix: the linear part, without the translation.

from_quat

pub fn Mat3::from_quat(Quat) -> Self

The rotation the quaternion holds.

from_rows

pub fn Mat3::from_rows(Vec3, Vec3, Vec3) -> Self

The matrix with the three vecs as its rows.

from_scale

pub fn Mat3::from_scale(Vec3) -> Self

The matrix that scales each axis by the matching component of s.

get

pub fn Mat3::get(Self, Int32, Int32) -> Float

The element at row and column, both counted from zero.

identity

pub fn Mat3::identity() -> Self

The identity: the matrix that changes nothing.

inverse

pub fn Mat3::inverse(Self) -> Self?

The matrix that undoes this one, or None when there is none.

is_finite

pub fn Mat3::is_finite(Self) -> Bool

Whether every element is finite.

mul_vec3

pub fn Mat3::mul_vec3(Self, Vec3) -> Vec3

The vector the matrix takes v to.

One expression per component, for the reason given at Mat2::mul_vec2: the three scaled columns a sum would build are three allocations on the native backend.

row

pub fn Mat3::row(Self, Int32) -> Vec3

Row index, counted from zero.

to_array

pub fn Mat3::to_array(Self) -> FixedArray[Float]

The elements in column-major order, ready for a buffer.

transpose

pub fn Mat3::transpose(Self) -> Self

The matrix with rows and columns exchanged.

This is also the inverse of a rotation matrix, which is the cheapest way to undo one.

zero

pub fn Mat3::zero() -> Self

The zero matrix: the one that sends everything to the origin.

Mat4struct

pub(all) struct Mat4

A 4×4 matrix: everything a 3×3 matrix does, plus the translation a transformation of space needs.

Column-major, so c3 is the translation column and to_array is exactly the sixteen floats a mat4x4<f32> occupies in a storage or uniform buffer. A point is a Vec4 with w = 1, a direction one with w = 0, and the fourth row of a projection matrix puts the perspective divide into w.

Values are immutable.

Fields
c0 : Vec4

The first column.

c1 : Vec4

The second column.

c2 : Vec4

The third column.

c3 : Vec4

The fourth column: the translation, for an affine matrix.

CarriesAdd, Debug, Div, Mul, Neg, Show, Sub

approx

pub fn Mat4::approx(Self, Self, eps? : Float) -> Bool

Whether the two matrices agree to within eps element by element.

col

pub fn Mat4::col(Self, Int32) -> Vec4

Column index, counted from zero.

determinant

pub fn Mat4::determinant(Self) -> Float

The signed hypervolume the matrix scales by: zero exactly when it is singular.

from_array

pub fn Mat4::from_array(FixedArray[Float]) -> Self

The matrix from sixteen values in column-major order — the order a mat4x4<f32> sits in a buffer in.

Aborts if the array does not hold sixteen values.

from_axis_angle

pub fn Mat4::from_axis_angle(Vec3, Float) -> Self

The rotation of radians about axis, by the right-hand rule.

from_cols

pub fn Mat4::from_cols(Vec4, Vec4, Vec4, Vec4) -> Self

The matrix with the four vecs as its columns.

from_euler

pub fn Mat4::from_euler(EulerOrder, Vec3) -> Self

The rotation the three angles describe, taken in order, in radians, read by axis. See Quat::from_euler for how the components are read and which orders that reading cannot express.

from_euler_turns

pub fn Mat4::from_euler_turns(EulerOrder, Turns) -> Self

The rotation the three turns describe, in the order the order names them.

from_mat3

pub fn Mat4::from_mat3(Mat3) -> Self

The matrix that does what the 3×3 matrix does to x, y and z, and leaves w alone.

from_quat

pub fn Mat4::from_quat(Quat) -> Self

The rotation the quaternion holds.

from_rows

pub fn Mat4::from_rows(Vec4, Vec4, Vec4, Vec4) -> Self

The matrix with the four vecs as its rows.

from_scale

pub fn Mat4::from_scale(Vec3) -> Self

The matrix that scales each axis by the matching component of s.

from_translation

pub fn Mat4::from_translation(Vec3) -> Self

The matrix that moves every point by t.

from_trs

pub fn Mat4::from_trs(Trs) -> Self

The matrix that scales by scale, then rotates by rotation, then moves by translation.

mbt check
test {
let scale : @moonmath.Vec3 = @moonmath.Vec3::splat(2.0)
let offset = @moonmath.Vec3::new(1.0, 0.0, 0.0)
let m = @moonmath.Mat4::from_trs(
@moonmath.Trs::new(offset, @moonmath.Quat::identity(), scale),
)
// One, scaled by two, then moved one along x.
assert_true(
m
.transform_point(@moonmath.Vec3::one())
.approx(@moonmath.Vec3::new(3.0, 2.0, 2.0)),
)
}

frustum

pub fn Mat4::frustum(Float, Float, Float, Float, Float, Float) -> Self

A perspective projection from an explicit frustum with the depth range 0..1.

The rectangle on the near plane becomes the full clip volume, so the six numbers are all a camera needs: left and bottom are negative, right and top positive for a centred view, and offsetting them is what a lens shift does.

frustum_gl

pub fn Mat4::frustum_gl(Float, Float, Float, Float, Float, Float) -> Self

A perspective projection from an explicit frustum with the depth range -1..1.

get

pub fn Mat4::get(Self, Int32, Int32) -> Float

The element at row and column, both counted from zero.

identity

pub fn Mat4::identity() -> Self

The identity: the matrix that changes nothing.

inverse

pub fn Mat4::inverse(Self) -> Self?

The matrix that undoes this one, or None when there is none.

The usual use is the inverse of a camera's view-projection matrix, and the usual singular case is a projection built with far equal to near.

is_finite

pub fn Mat4::is_finite(Self) -> Bool

Whether every element is finite.

look_at

pub fn Mat4::look_at(Vec3, Vec3, Vec3) -> Self

The view matrix of a camera at eye looking at target, with up telling it which way is up.

Right-handed: the camera looks down its own -z, so the third column of the result is eye - target, normalized. up need not be perpendicular to the view direction, only not parallel to it; when it is parallel there is no answer and the identity comes back rather than a matrix full of NaNs.

mul_vec4

pub fn Mat4::mul_vec4(Self, Vec4) -> Vec4

The vector the matrix takes v to, without any division by w.

This is what a shader's matrix * vector does: the projection divide happens after clipping, not here. One expression per component, for the reason given at Mat2::mul_vec2.

orthographic

pub fn Mat4::orthographic(Float, Float, Float, Float, Float, Float) -> Self

An orthographic projection with the depth range 0..1: the box the six planes bound becomes the unit cube in clip space.

Right-handed, so the camera looks down -z and near and far are distances in front of it, both positive. A box with left == right, bottom == top or near == far has no volume to map and gives the identity.

orthographic_gl

pub fn Mat4::orthographic_gl(Float, Float, Float, Float, Float, Float) -> Self

An orthographic projection with the depth range -1..1.

perspective

pub fn Mat4::perspective(Float, Float, Float, Float) -> Self

A perspective projection with the depth range 0..1: the near plane maps to zero and the far plane to one, which is what WebGPU clips against.

fov_y is the vertical field of view in radians and aspect the width divided by the height. Right-handed: the camera looks down -z, so near and far are distances in front of it, both positive.

mbt check
test {
let m = @moonmath.Mat4::perspective(@moonmath.half_pi, 1.0, 0.1, 100.0)
// The near plane lands on depth 0 and the far plane on depth 1.
let near = m.mul_vec4(@moonmath.Vec4::new(0.0, 0.0, -0.1, 1.0))
assert_true(@moonmath.approx(near.z / near.w, 0.0))
let far = m.mul_vec4(@moonmath.Vec4::new(0.0, 0.0, -100.0, 1.0))
assert_true(@moonmath.approx(far.z / far.w, 1.0))
}

perspective_gl

pub fn Mat4::perspective_gl(Float, Float, Float, Float) -> Self

A perspective projection with the depth range -1..1, for a pipeline that clips like OpenGL.

The same as perspective in every other respect; only the third row differs.

perspective_infinite

pub fn Mat4::perspective_infinite(Float, Float, Float) -> Self

A perspective projection with the depth range 0..1 and no far plane.

Precision is better spent near the eye: with no far plane to reach, the depth values crowd into the region where a depth buffer can still tell them apart, instead of being spread over a range whose far end nothing occupies.

perspective_infinite_gl

pub fn Mat4::perspective_infinite_gl(Float, Float, Float) -> Self

A perspective projection with the depth range -1..1 and no far plane.

row

pub fn Mat4::row(Self, Int32) -> Vec4

Row index, counted from zero.

to_array

pub fn Mat4::to_array(Self) -> FixedArray[Float]

The elements in column-major order, the sixteen a buffer holds.

to_trs

pub fn Mat4::to_trs(Self) -> Trs?

The translation, rotation and scale the matrix was built from, or None when it cannot be read that way.

A matrix with shear in it — the common case being a non-uniform scale applied after a rotation — is not a Trs and has no decomposition here; neither has one whose linear part is singular, whose rotation would be unrecoverable. When the determinant is negative the first component of scale carries the sign, because a mirrored basis is a rotation with one flipped axis.

transform_point

pub fn Mat4::transform_point(Self, Vec3) -> Vec3

The point the matrix takes p to, dividing by w when there is one.

A projection matrix leaves the result in homogeneous coordinates; the point only exists after that division, so it happens here. A w of zero — a point on the horizon of a perspective projection — leaves the numerator as it is.

transform_vector

pub fn Mat4::transform_vector(Self, Vec3) -> Vec3

The direction the matrix takes v to, ignoring the translation column.

Directions have no position, so the fourth row must not touch them: a translation leaves a direction alone, as it should.

transpose

pub fn Mat4::transpose(Self) -> Self

The matrix with rows and columns exchanged.

zero

pub fn Mat4::zero() -> Self

The zero matrix: the one that sends everything to the origin and loses w.

Shearstruct

pub(all) struct Shear

A shear: the three off-diagonal terms that slide one axis into another while leaving the origin and the axes themselves where they are.

A shear is a linear map, so it is applied through to_mat3 or to_mat4. xy slides y into x, xz slides z into x, and yz slides z into y, matching the (row, column) terms of the upper triangle. The three together are the general upper-triangular linear map, which is what a skew, a slanted view of a page, or a shear deformation of a mesh is.

Values are immutable.

Fields
xy : Float

How much x gains from y: the (0, 1) term.

xz : Float

How much x gains from z: the (0, 2) term.

yz : Float

How much y gains from z: the (1, 2) term.

CarriesDebug, Show

approx

pub fn Shear::approx(Self, Self, eps? : Float) -> Bool

Whether the three terms agree with other to within eps.

is_finite

pub fn Shear::is_finite(Self) -> Bool

Whether the three terms are finite.

new

pub fn Shear::new(Float, Float, Float) -> Self

The shear from its three terms.

to_mat3

pub fn Shear::to_mat3(Self) -> Mat3

The shear as a linear map, ready to compose with a rotation or a scale.

to_mat4

pub fn Shear::to_mat4(Self) -> Mat4

The shear as a 4×4 matrix whose translation is zero.

zero

pub fn Shear::zero() -> Self

No shear: the identity map.

Rotation

3

A rotation as four numbers, and the twelve ways of writing one as three angles.

Quatstruct

pub(all) struct Quat

A rotation, as a unit quaternion.

(x, y, z) is the axis of the rotation scaled by the sine of half its angle, and w the cosine of half the angle. Half angles, because a rotation acts on a vector from both sides: q v q⁻¹.

A quaternion is four numbers where a matrix is nine, composes in fewer operations, and interpolates smoothly — which is why animation and physics carry rotations this way and convert to a matrix only when handing one to a shader.

The rotations are the unit quaternions; the ones here do not enforce that on construction, because building one by summing or lerping intermediate values is legitimate and only the end result has to be normal. Anything that composes an arbitrary number of them — rotate, to_mat3, slerp — says when it assumes unit length.

Fields
x : Float

The x part of the axis, scaled by the sine of half the angle.

y : Float

The y part of the axis, scaled by the sine of half the angle.

z : Float

The z part of the axis, scaled by the sine of half the angle.

w : Float

The cosine of half the angle.

CarriesDebug, Div, Mul, Neg, Show

approx

pub fn Quat::approx(Self, Self, eps? : Float) -> Bool

Whether the two rotations are the same to within eps.

q and -q are the same rotation, so the sign between them is not a difference; the comparison uses the absolute dot product.

conjugate

pub fn Quat::conjugate(Self) -> Self

The conjugate: the quaternion with its axis part negated.

The inverse rotation for a unit quaternion, and cheaper than inverse because it divides by nothing.

dot

pub fn Quat::dot(Self, Self) -> Float

The dot product of the two, as four-component vectors.

Its sign says whether the two rotations take the short way round: negative means the interpolations in this module would travel the long way, and interpolating with the negated quaternion instead gives the short one.

from_axis_angle

pub fn Quat::from_axis_angle(Vec3, Float) -> Self

The rotation of radians about axis, by the right-hand rule.

axis is normalized first; a zero axis has no direction to turn about and gives the identity.

mbt check
test {
let quarter = @moonmath.Quat::from_axis_angle(
@moonmath.Vec3::unit_z(),
@moonmath.half_pi,
)
assert_true(
quarter.rotate(@moonmath.Vec3::unit_x()).approx(@moonmath.Vec3::unit_y()),
)
}

from_euler

pub fn Quat::from_euler(EulerOrder, Vec3) -> Self

The rotation the three angles describe, taken in order, in radians.

The components of angles are the turns about x, y and z, wherever in the order those axes turn up: for Zyx, which turns about z first, the third component is the first turn. That is the reading a caller expects from a vector named after axes, and it is exact for the six orders that name three different axes.

The other six turn about one axis twice — Xyx is the family — and two turns about one axis cannot both be given by its single component. Passing one of those orders to this function aborts; from_euler_turns takes the three turns in order and covers all twelve.

mbt check
test {
// Zyx turns about z first, so the third component is the first turn.
let turn = @moonmath.Quat::from_euler(
@moonmath.EulerOrder::Zyx,
@moonmath.Vec3::new(0.0, 0.0, @moonmath.half_pi),
)
assert_true(
turn.rotate(@moonmath.Vec3::unit_y()).approx(-@moonmath.Vec3::unit_x()),
)
}

from_euler_turns

pub fn Quat::from_euler_turns(EulerOrder, Turns) -> Self

The rotation the three turns describe, in the order the order names them.

The general form: it takes the first turn, the second and the third however many axes they use, so it covers all twelve orders. For the six that name three different axes it is the same rotation from_euler builds from a vector, with the turns already in order.

from_mat3

pub fn Quat::from_mat3(Mat3) -> Self

The rotation the matrix holds, for a matrix that is a rotation.

A matrix with a scale in it gives the rotation underneath only when the scale is uniform; one that is not a rotation at all gives the nearest unit quaternion to its columns, which is still a usable answer for a matrix that drifted.

from_mat4

pub fn Quat::from_mat4(Mat4) -> Self

The rotation the 4×4 matrix holds, read from its upper-left block.

from_rotation_arc

pub fn Quat::from_rotation_arc(Vec3, Vec3) -> Self

The shortest rotation that turns from towards to, for two directions.

The pair need not be normalized and need not be perpendicular to anything: the rotation takes the direction of from to the direction of to and leaves the plane they span alone. Opposed directions have no single shortest rotation — every half turn about a perpendicular axis works — and one is picked. A zero vector has no direction to turn and gives the identity.

mbt check
test {
let turn = @moonmath.Quat::from_rotation_arc(
@moonmath.Vec3::unit_x(),
@moonmath.Vec3::unit_y(),
)
assert_true(
turn.rotate(@moonmath.Vec3::unit_x()).approx(@moonmath.Vec3::unit_y()),
)
}

identity

pub fn Quat::identity() -> Self

The rotation that changes nothing.

inverse

pub fn Quat::inverse(Self) -> Self?

The rotation run backwards: the quaternion that undoes this one.

For a unit quaternion this is the conjugate; for any other it is the conjugate divided by the squared length, so that q * q.inverse() is the identity. None for the zero quaternion, which represents no rotation and has no inverse.

is_finite

pub fn Quat::is_finite(Self) -> Bool

Whether every component is finite.

length

pub fn Quat::length(Self) -> Float

The length of the quaternion as a four-component vector: one for a rotation.

length_squared

pub fn Quat::length_squared(Self) -> Float

The square of the length.

new

pub fn Quat::new(Float, Float, Float, Float) -> Self

The quaternion from its four components, in the order (x, y, z, w).

nlerp

pub fn Quat::nlerp(Self, Self, Float) -> Self

The rotation a fraction of the way from self to other along the straight line, normalized back onto the sphere.

Cheaper than slerp and close to it for small angles; the rate is not quite constant, which a long animation would show.

normalize

pub fn Quat::normalize(Self) -> Self

The quaternion scaled to length one, or the identity if it is zero.

A rotation is always a unit quaternion; one built by summing or lerping others has to be brought back before it can rotate anything, and the zero quaternion — which summing can produce — falls back to the identity rather than to a division by zero.

random

pub fn Quat::random(Float, Float, Float) -> Self

A uniformly distributed random rotation.

u1, u2 and u3 are independent uniform samples in [0, 1). The result is a unit quaternion spread evenly over the rotation group — the construction that makes it even is not obvious, and a quaternion built from three evenly sampled angles would not be.

rotate

pub fn Quat::rotate(Self, Vec3) -> Vec3

The vector turned by the rotation.

Assumes unit length. Two cross products rather than q v q⁻¹, which is the same result with fewer multiplications.

slerp

pub fn Quat::slerp(Self, Self, Float) -> Self

The rotation a fraction of the way from self to other, at constant angular speed.

Spherical interpolation: the intermediate rotations turn at a steady rate, which is what an animation between two orientations wants. The two are compared first, and the negated one is used when they point away from each other — q and -q are the same rotation, and the negation is the one that takes the short way.

to_array

pub fn Quat::to_array(Self) -> FixedArray[Float]

The four components in order, [x, y, z, w], for handing to a buffer.

to_axis_angle

pub fn Quat::to_axis_angle(Self) -> (Vec3, Float)

The angle and axis of the rotation, as (axis, radians) with the axis a unit vector and the angle in 0..pi.

A rotation of zero has no axis to name; it comes back as (x, 0) — the first axis, with a zero angle, which rotates nothing either way.

to_euler

pub fn Quat::to_euler(Self, EulerOrder) -> Vec3

The turn about each axis that produces this rotation in order, in radians.

The inverse of from_euler, and read the same way: the component of an axis is the turn about it, wherever in the order it comes. Aborts for the six orders that turn about one axis twice, whose two turns cannot both be written into one component; to_euler_turns returns them in order instead.

mbt check
test {
let turn = @moonmath.Quat::from_axis_angle(
@moonmath.Vec3::unit_x(),
@moonmath.quarter_pi,
)
let angles = turn.to_euler(@moonmath.EulerOrder::Yxz)
assert_true(@moonmath.approx(angles.x, @moonmath.quarter_pi))
}

to_euler_turns

pub fn Quat::to_euler_turns(Self, EulerOrder) -> Turns

The three turns that produce this rotation in order, in radians, in the order the order names them.

The inverse of from_euler_turns, for every one of the twelve orders. Feeding the result back gives the rotation again, except at the two angles where the first and third turns collapse into one — the gimbal lock every three-angle convention has. There the first turn comes back as zero and the whole of it is carried by the third.

to_mat3

pub fn Quat::to_mat3(Self) -> Mat3

The rotation as a 3×3 matrix.

Assumes unit length; a quaternion that drifted scales the matrix by the square of its norm.

to_mat4

pub fn Quat::to_mat4(Self) -> Mat4

The rotation as a 4×4 matrix whose translation is zero.

EulerOrderenum

pub(all) enum EulerOrder

The order the three Euler angles are applied in.

The name says which axis each angle turns about, read left to right: Xyz turns about x, then about the new y, then about the new z. That is the intrinsic reading, the one an aircraft's roll, pitch and yaw use, and it is the same as applying the three turns about the fixed axes in the opposite order.

Six orders turn about three different axes and six about two — the last group repeats the first axis and is what a turntable and a gyroscope do. Between them they cover every way to name a rotation by three angles; the choice is a convention of the file format or the editor that produced the angles, not of the arithmetic.

Variants
Xyz

Turns about x, then y, then z: the family that locks at a quarter turn of y.

Xzy

Turns about x, then z, then y.

Yxz

Turns about y, then x, then z.

Yzx

Turns about y, then z, then x.

Zxy

Turns about z, then x, then y.

Zyx

Turns about z, then y, then x: yaw, pitch and roll, in that order.

Xyx

Turns about x, then y, then x again: the first and third share an axis.

Xzx

Turns about x, then z, then x again.

Yxy

Turns about y, then x, then y again.

Yzy

Turns about y, then z, then y again.

Zxz

Turns about z, then x, then z again.

Zyz

Turns about z, then y, then z again.

Turnsstruct

pub(all) struct Turns

The three turns of a rotation, in the order the order names them.

first is the turn about the first axis of the order, second about the second and third about the third — which for six of the twelve orders is the first axis again. A record rather than a vector because a vector's components are named after axes, and for those six orders the third turn is not about the third axis; naming the slots after their place in the order says exactly what they are.

Fields
first : Float

The turn about the first axis the order names.

second : Float

The turn about the second axis the order names.

third : Float

The turn about the third axis the order names.

CarriesDebug, Show

approx

pub fn Turns::approx(Self, Self, eps? : Float) -> Bool

Whether the two triples agree to within eps.

new

pub fn Turns::new(Float, Float, Float) -> Self

The three turns, in the order the order names them.

Placement

3

The transforms a scene graph stores: a rotation, a scale and a translation.

Trsstruct

pub(all) struct Trs

A translation, a rotation and a scale, in that order of composition: a point is scaled, then turned, then moved.

This is what Mat4::to_trs recovers from a matrix that was built the same way, and what a scene graph stores per node — the three pieces are what an animation edits, and a decomposition keeps them editable.

Fields
translation : Vec3

Where the frame sits.

rotation : Quat

How it is turned.

scale : Vec3

How far it is stretched, per axis.

CarriesDebug, Show

new

pub fn Trs::new(Vec3, Quat, Vec3) -> Self

The three parts of a transformation.

Affine2struct

pub(all) struct Affine2

A 2D affine transform: a linear map and a translation, without the row of a matrix that does nothing but hold (0, 0, 1).

Composition, inversion and applying are all cheaper than the 3×3 matrix that would carry the same thing, and there is no way to build one of these that is not affine — which is what UI layout, sprite placement and 2D physics want.

Values are immutable.

Fields
linear : Mat2

The part that turns and scales: a 2×2 matrix.

translation : Vec2

The part that moves.

CarriesDebug, Div, Mul, Show

approx

pub fn Affine2::approx(Self, Self, eps? : Float) -> Bool

Whether the two transforms agree to within eps element by element.

from_angle

pub fn Affine2::from_angle(Float) -> Self

The transform that turns counter-clockwise by radians about the origin.

from_angle_translation

pub fn Affine2::from_angle_translation(Float, Vec2) -> Self

The transform that turns by radians and then moves by offset.

from_mat3

pub fn Affine2::from_mat3(Mat3) -> Self?

The affine transform a 3×3 matrix holds, or None when the matrix is not affine.

A matrix whose last row is not (0, 0, 1) — a projection, say — carries a perspective that this type cannot hold, and there is no transform to return.

from_scale

pub fn Affine2::from_scale(Vec2) -> Self

The transform that scales each axis by the matching component of scale.

from_translation

pub fn Affine2::from_translation(Vec2) -> Self

The transform that moves every point by offset.

identity

pub fn Affine2::identity() -> Self

The transform that changes nothing.

inverse

pub fn Affine2::inverse(Self) -> Self?

The transform that undoes this one, or None when the linear part is singular.

A singular linear part flattens the plane onto a line or a point, and no transform brings that back.

is_finite

pub fn Affine2::is_finite(Self) -> Bool

Whether every element is finite.

new

pub fn Affine2::new(Mat2, Vec2) -> Self

The transform that maps v to linear * v + translation.

to_mat3

pub fn Affine2::to_mat3(Self) -> Mat3

The same transform as a 3×3 matrix, with (0, 0, 1) as its last row.

transform_point

pub fn Affine2::transform_point(Self, Vec2) -> Vec2

The point the transform takes p to.

transform_vector

pub fn Affine2::transform_vector(Self, Vec2) -> Vec2

The direction the transform takes v to, without the translation.

A direction has no position, so moving the origin must leave it alone.

Affine3struct

pub(all) struct Affine3

A 3D affine transform: a linear map and a translation, without the fourth row of a matrix that does nothing but hold (0, 0, 0, 1).

This is the transform a scene node carries — position, rotation and scale applied to its geometry — and it is cheaper than the 4×4 matrix that would also happen to work, since the wasted row would be multiplied four times per vector.

Values are immutable.

Fields
linear : Mat3

The part that turns and scales: a 3×3 matrix.

translation : Vec3

The part that moves.

CarriesDebug, Div, Mul, Show

approx

pub fn Affine3::approx(Self, Self, eps? : Float) -> Bool

Whether the two transforms agree to within eps element by element.

from_axis_angle

pub fn Affine3::from_axis_angle(Vec3, Float) -> Self

The transform that turns by radians about axis, by the right-hand rule.

from_mat4

pub fn Affine3::from_mat4(Mat4) -> Self?

The affine transform a 4×4 matrix holds, or None when the matrix is not affine.

from_rotation

pub fn Affine3::from_rotation(Quat) -> Self

The transform that applies the rotation, about the origin.

from_scale

pub fn Affine3::from_scale(Vec3) -> Self

The transform that scales each axis by the matching component of scale.

from_translation

pub fn Affine3::from_translation(Vec3) -> Self

The transform that moves every point by offset.

from_trs

pub fn Affine3::from_trs(Trs) -> Self

The transform that scales, then rotates, then moves: the three parts of a Trs.

identity

pub fn Affine3::identity() -> Self

The transform that changes nothing.

inverse

pub fn Affine3::inverse(Self) -> Self?

The transform that undoes this one, or None when the linear part is singular.

is_finite

pub fn Affine3::is_finite(Self) -> Bool

Whether every element is finite.

new

pub fn Affine3::new(Mat3, Vec3) -> Self

The transform that maps v to linear * v + translation.

to_mat4

pub fn Affine3::to_mat4(Self) -> Mat4

The same transform as a 4×4 matrix, with (0, 0, 0, 1) as its last row.

to_trs

pub fn Affine3::to_trs(Self) -> Trs?

The three parts the transform was built from, or None when its linear part is singular or has shear in it. See Mat4::to_trs.

transform_point

pub fn Affine3::transform_point(Self, Vec3) -> Vec3

The point the transform takes p to.

transform_vector

pub fn Affine3::transform_vector(Self, Vec3) -> Vec3

The direction the transform takes v to, without the translation.

Geometry

11

Shapes, and whether two of them meet.

Rectstruct

pub(all) struct Rect

A rectangle given by its corner and its size: the shape a layout hands out.

A layout thinks in "here, this big", not in two opposite corners, which is why this is not Aabb2 — the two describe the same set of points and answer different questions. origin is the corner with the smaller coordinates and size the extent from it, so a size with a negative component describes the same points as the equivalent positive one, with the corners swapped.

Values are immutable.

Fields
origin : Vec2

The corner with the smallest coordinate on each axis.

size : Vec2

How far it extends along each axis; never negative.

CarriesDebug, Show

approx

pub fn Rect::approx(Self, Self, eps? : Float) -> Bool

Whether the two rectangles cover the same points to within eps.

area

pub fn Rect::area(Self) -> Float

The area the rectangle covers.

center

pub fn Rect::center(Self) -> Vec2

The point in the middle.

contains

pub fn Rect::contains(Self, Vec2) -> Bool

Whether the point is inside or on the edge.

corners

pub fn Rect::corners(Self) -> FixedArray[Vec2]

The four corners, starting at origin and going counter-clockwise.

from_edges

pub fn Rect::from_edges(Float, Float, Float, Float) -> Self

The rectangle spanning two opposite corners, in either order.

from_xywh

pub fn Rect::from_xywh(Float, Float, Float, Float) -> Self

The rectangle with its top-left corner at x, y and the given extent.

The usual spelling for a layout node; which way is "top" is the caller's convention, as everywhere else here.

height

pub fn Rect::height(Self) -> Float

The extent along y, always non-negative.

inset

pub fn Rect::inset(Self, Float) -> Self

The same rectangle with every edge moved in by amount.

A positive amount shrinks it, a negative one grows it; shrinking past the middle leaves an empty rectangle at the centre rather than a negative one.

intersection

pub fn Rect::intersection(Self, Self) -> Self?

The area the two share, or None when they share none.

intersects

pub fn Rect::intersects(Self, Self) -> Bool

Whether the two rectangles share any area.

Touching edges share no area and do not count; an empty rectangle intersects nothing.

is_empty

pub fn Rect::is_empty(Self) -> Bool

Whether the rectangle covers no area at all.

A zero width or height is empty: it is a line or a point, and nothing inside it can be drawn or hit.

max

pub fn Rect::max(Self) -> Vec2

The corner with the larger coordinates.

min

pub fn Rect::min(Self) -> Vec2

The corner with the smaller coordinates.

new

pub fn Rect::new(Vec2, Vec2) -> Self

The rectangle at origin extending size.

to_aabb

pub fn Rect::to_aabb(Self) -> Aabb2

The same points as an axis-aligned box.

translate

pub fn Rect::translate(Self, Vec2) -> Self

The same rectangle moved by offset.

union

pub fn Rect::union(Self, Self) -> Self

The smallest rectangle containing both.

width

pub fn Rect::width(Self) -> Float

The extent along x, always non-negative.

Aabb2struct

pub(all) struct Aabb2

An axis-aligned box in the plane, given by two opposite corners.

Broad-phase collision and culling ask "is this thing anywhere near that thing", and a box around each answers it without touching the contents. The corners are min and max rather than a corner and a size because that is the form the tests read, and because merging two boxes is then two component comparisons.

Values are immutable.

Fields
min : Vec2

The corner with the smallest coordinate on each axis.

max : Vec2

The corner with the largest coordinate on each axis.

CarriesDebug, Show

approx

pub fn Aabb2::approx(Self, Self, eps? : Float) -> Bool

Whether the two boxes agree to within eps.

area

pub fn Aabb2::area(Self) -> Float

The area the box covers, zero when it is empty.

center

pub fn Aabb2::center(Self) -> Vec2

The point in the middle.

contains

pub fn Aabb2::contains(Self, Self) -> Bool

Whether other lies entirely inside this box.

contains_point

pub fn Aabb2::contains_point(Self, Vec2) -> Bool

Whether the point is inside or on the boundary.

corners

pub fn Aabb2::corners(Self) -> FixedArray[Vec2]

The four corners, starting at min and going counter-clockwise.

empty

pub fn Aabb2::empty() -> Self

A box with nothing in it: the identity for union.

Its corners are the wrong way round on purpose, so that merging anything into it gives that thing back unchanged.

expand

pub fn Aabb2::expand(Self, Float) -> Self

The same box grown by amount in every direction.

extents

pub fn Aabb2::extents(Self) -> Vec2

The half extent along each axis: the distance from the middle to a face.

from_center_half_extents

pub fn Aabb2::from_center_half_extents(Vec2, Vec2) -> Self

The box with the given centre and half-extents.

from_points

pub fn Aabb2::from_points(FixedArray[Vec2]) -> Self?

The smallest box around the points, or None when there are none.

intersection

pub fn Aabb2::intersection(Self, Self) -> Self?

The overlapping box, or None when they do not overlap.

intersects

pub fn Aabb2::intersects(Self, Self) -> Bool

Whether the two boxes overlap in positive area.

is_empty

pub fn Aabb2::is_empty(Self) -> Bool

Whether the box holds nothing.

new

pub fn Aabb2::new(Vec2, Vec2) -> Self

The box with the two given corners.

size

pub fn Aabb2::size(Self) -> Vec2

The full extent along each axis.

to_rect

pub fn Aabb2::to_rect(Self) -> Rect

The same points as a rectangle.

union

pub fn Aabb2::union(Self, Self) -> Self

The smallest box containing both.

Aabb3struct

pub(all) struct Aabb3

An axis-aligned box in space, given by two opposite corners.

The same broad-phase role as Aabb2, with a third axis: a frustum is tested against one of these per object per frame, so the tests here are written to read the extremes of a plane's distance rather than to visit eight corners.

Values are immutable.

Fields
min : Vec3

The corner with the smallest coordinate on each axis.

max : Vec3

The corner with the largest coordinate on each axis.

CarriesDebug, Show

approx

pub fn Aabb3::approx(Self, Self, eps? : Float) -> Bool

Whether the two boxes agree to within eps.

center

pub fn Aabb3::center(Self) -> Vec3

The point in the middle.

contains

pub fn Aabb3::contains(Self, Self) -> Bool

Whether other lies entirely inside this box.

contains_point

pub fn Aabb3::contains_point(Self, Vec3) -> Bool

Whether the point is inside or on the boundary.

corners

pub fn Aabb3::corners(Self) -> FixedArray[Vec3]

The eight corners.

empty

pub fn Aabb3::empty() -> Self

A box with nothing in it: the identity for union.

expand

pub fn Aabb3::expand(Self, Float) -> Self

The same box grown by amount in every direction.

extents

pub fn Aabb3::extents(Self) -> Vec3

The half extent along each axis.

from_center_half_extents

pub fn Aabb3::from_center_half_extents(Vec3, Vec3) -> Self

The box with the given centre and half-extents.

from_points

pub fn Aabb3::from_points(FixedArray[Vec3]) -> Self?

The smallest box around the points, or None when there are none.

intersection

pub fn Aabb3::intersection(Self, Self) -> Self?

The overlapping box, or None when they do not overlap.

intersects

pub fn Aabb3::intersects(Self, Self) -> Bool

Whether the two boxes overlap in positive volume.

is_empty

pub fn Aabb3::is_empty(Self) -> Bool

Whether the box holds nothing.

new

pub fn Aabb3::new(Vec3, Vec3) -> Self

The box with the two given corners.

random_point

pub fn Aabb3::random_point(Self, Float, Float, Float) -> Vec3

A point uniformly distributed through the box.

u1, u2 and u3 are independent uniform samples in [0, 1), one per axis.

size

pub fn Aabb3::size(Self) -> Vec3

The full extent along each axis.

surface_area

pub fn Aabb3::surface_area(Self) -> Float

The total area of the six faces, zero when it is empty.

transform

pub fn Aabb3::transform(Self, Mat4) -> Self

The box around the transformed box.

A box turned by a rotation is no longer axis-aligned, so the result is the smallest axis-aligned box around the turned one: correct, and looser than it was before the turn.

union

pub fn Aabb3::union(Self, Self) -> Self

The smallest box containing both.

volume

pub fn Aabb3::volume(Self) -> Float

The volume the box encloses, zero when it is empty.

Ray2struct

pub(all) struct Ray2

A half-line in the plane: a start and a direction.

origin + direction * t for t >= 0. The direction is not normalized here — a ray whose direction carries the speed of something travelling along it is as useful as a unit one, and t then reads as time.

Values are immutable.

Fields
origin : Vec2

Where the ray starts.

direction : Vec2

Which way it goes. The intersections report t in units of this vector, so a unit direction makes t a distance.

CarriesDebug, Show

approx

pub fn Ray2::approx(Self, Self, eps? : Float) -> Bool

Whether the two rays start at the same point and head the same way.

at

pub fn Ray2::at(Self, Float) -> Vec2

The point t along the ray.

intersect_aabb

pub fn Ray2::intersect_aabb(Self, Aabb2) -> Float?

Where the ray first meets the box, as a t, or None when it misses.

A ray that starts inside the box meets its surface on the way out, and that crossing is the one reported — the nearest one at t >= 0, rather than "the one in front of the origin in the direction of travel".

intersect_aabb_interval

pub fn Ray2::intersect_aabb_interval(Self, Aabb2) -> (Float, Float)?

The stretch of the ray that lies inside the box, as a pair of t values.

A ray that starts inside the box is already inside at t = 0, and the entry is then negative — the point was inside before the ray started, and the interval says from where. None when the ray misses the box.

intersect_circle

pub fn Ray2::intersect_circle(Self, Vec2, Float) -> Float?

Where the ray first meets the circle, as a t, or None when it misses.

A ray that starts inside the circle meets it on the way out.

intersect_rect

pub fn Ray2::intersect_rect(Self, Rect) -> Float?

Where the ray first meets the rectangle, as a t, or None when it misses.

new

pub fn Ray2::new(Vec2, Vec2) -> Self

The ray starting at origin and heading along direction.

Ray3struct

pub(all) struct Ray3

A half-line in space: a start and a direction.

What a picking click, a mouse cursor in a 3D scene and a photon all are. The tests here return the parameter t of the first surface crossing rather than the point, because the caller usually needs the distance and the point is one multiplication away.

Values are immutable.

Fields
origin : Vec3

Where the ray starts.

direction : Vec3

Which way it goes. The intersections report t in units of this vector, so a unit direction makes t a distance.

CarriesDebug, Show

approx

pub fn Ray3::approx(Self, Self, eps? : Float) -> Bool

Whether the two rays start at the same point and head the same way.

at

pub fn Ray3::at(Self, Float) -> Vec3

The point t along the ray.

intersect_aabb

pub fn Ray3::intersect_aabb(Self, Aabb3) -> Float?

Where the ray first meets the box, as a t, or None when it misses.

A ray that starts inside the box reports its exit.

intersect_aabb_interval

pub fn Ray3::intersect_aabb_interval(Self, Aabb3) -> (Float, Float)?

The stretch of the ray that lies inside the box, as a pair of t values.

A ray that starts inside has an entry before its origin. This is the slab test: for each axis the ray is inside the box over an interval, and the intersection of the three intervals is the stretch wanted. A ray parallel to a face never leaves that axis' slab, or never enters it.

intersect_plane

pub fn Ray3::intersect_plane(Self, Plane) -> Float?

Where the ray meets the plane, as a t, or None when it runs parallel.

A ray lying inside the plane meets it everywhere and nowhere in particular; that comes back as None too.

intersect_sphere

pub fn Ray3::intersect_sphere(Self, Sphere) -> Float?

Where the ray first meets the sphere, as a t, or None when it misses.

A ray that starts inside the sphere reports its exit.

intersect_triangle

pub fn Ray3::intersect_triangle(Self, Triangle) -> Float?

Where the ray meets the triangle, as a t, or None when it misses.

Möller–Trumbore: the ray is solved against the triangle's barycentric coordinates directly, without building the plane first, and a hit behind the origin or outside the triangle gives None.

new

pub fn Ray3::new(Vec3, Vec3) -> Self

The ray starting at origin and heading along direction.

Planestruct

pub(all) struct Plane

An infinite plane in space: the set of points p with dot(normal, p) == distance, where the normal is a unit vector.

The offset form rather than point-and-normal, because the signed distance of a point is then a dot product and no subtraction, which is what a frustum does six times per box.

Values are immutable.

Fields
normal : Vec3

The unit normal: which side is out.

distance : Float

How far the plane is from the origin, measured along the normal.

CarriesDebug, Show

approx

pub fn Plane::approx(Self, Self, eps? : Float) -> Bool

Whether the two planes are the same to within eps.

flip

pub fn Plane::flip(Self) -> Self

The same plane with the other side facing out.

from_point_normal

pub fn Plane::from_point_normal(Vec3, Vec3) -> Self?

The plane through point with the given normal.

from_points

pub fn Plane::from_points(Vec3, Vec3, Vec3) -> Self?

The plane through the three points, or None when they are collinear.

The normal faces the way the points wind, by the right-hand rule, so the winding order decides which side is positive.

intersect_ray

pub fn Plane::intersect_ray(Self, Ray3) -> Float?

Where the ray meets the plane, as a t, or None when it runs parallel or the crossing is behind the origin.

is_finite

pub fn Plane::is_finite(Self) -> Bool

Whether the normal and the distance are finite.

new

pub fn Plane::new(Vec3, Float) -> Self

The plane whose normal is normal and whose signed distance from the origin is distance.

normal is normalized, and distance scaled with it, so that signed_distance counts the same units as the coordinates. A zero normal names no plane and aborts: there is no answer to give back.

project

pub fn Plane::project(Self, Vec3) -> Vec3

The point of the plane closest to point: the point projected onto it.

signed_distance

pub fn Plane::signed_distance(Self, Vec3) -> Float

The distance from the plane to the point, positive on the side the normal points to.

Spherestruct

pub(all) struct Sphere

A sphere: a centre and a radius.

Values are immutable.

Fields
center : Vec3

The centre.

radius : Float

The radius.

CarriesDebug, Show

approx

pub fn Sphere::approx(Self, Self, eps? : Float) -> Bool

Whether the two spheres agree to within eps.

contains_point

pub fn Sphere::contains_point(Self, Vec3) -> Bool

Whether the point is inside or on the surface.

intersects_aabb

pub fn Sphere::intersects_aabb(Self, Aabb3) -> Bool

Whether the sphere and the box overlap or touch.

The point of the box closest to the centre is the one that decides it: if that point is within the radius, the two meet. Testing the centre against the box alone would call a sphere near a corner a miss.

intersects_sphere

pub fn Sphere::intersects_sphere(Self, Self) -> Bool

Whether the two spheres overlap or touch.

new

pub fn Sphere::new(Vec3, Float) -> Self

The sphere with the given centre and radius.

random_inside

pub fn Sphere::random_inside(Self, Float, Float, Float) -> Vec3

A point uniformly distributed through the sphere.

u1, u2 and u3 are independent uniform samples in [0, 1), as for Vec3::random_in_ball.

random_on_surface

pub fn Sphere::random_on_surface(Self, Float, Float) -> Vec3

A point uniformly distributed over the surface of the sphere.

u1 and u2 are independent uniform samples in [0, 1), as for Vec3::random_on_sphere.

surface_area

pub fn Sphere::surface_area(Self) -> Float

The area of the surface.

volume

pub fn Sphere::volume(Self) -> Float

The volume it encloses.

Line3struct

pub(all) struct Line3

An infinite line in space: a point and a direction.

A ray has a start and runs one way; a line has neither end, which is what a construction axis, a normal or the intersection of two planes is. The direction need not be a unit vector — the results are the same whatever its length — but a zero direction names no line, and every operation treats it as the single point point.

Values are immutable.

Fields
point : Vec3

A point on the line.

direction : Vec3

The direction it runs in; its length does not matter.

CarriesDebug, Show

approx

pub fn Line3::approx(Self, Self, eps? : Float) -> Bool

Whether the two lines have the same point and direction to within eps.

at

pub fn Line3::at(Self, Float) -> Vec3

The point t of the direction from point; t may be any number.

closest_point_to

pub fn Line3::closest_point_to(Self, Vec3) -> Vec3

The point of the line closest to other.

The perpendicular foot: the vector from it to other is perpendicular to the direction. A zero direction leaves the line a point, and the answer is that point.

closest_point_to_line

pub fn Line3::closest_point_to_line(Self, Self) -> Vec3

The point of this line closest to the other line.

For two lines that meet or are skew, the closest points are the pair joined by the common perpendicular; this is the one on this line. Parallel lines have a whole family of closest pairs and the foot from the other line's point is returned. A degenerate line — a zero direction — gives its point.

distance_to_line

pub fn Line3::distance_to_line(Self, Self) -> Float

The distance between the two lines: zero when they meet.

distance_to_point

pub fn Line3::distance_to_point(Self, Vec3) -> Float

The distance from the line to the point.

intersect_plane

pub fn Line3::intersect_plane(Self, Plane) -> Vec3?

Where the line cuts the plane, or None when it runs parallel to it.

A line has no ends, so any crossing counts, on either side of point.

is_finite

pub fn Line3::is_finite(Self) -> Bool

Whether the point and the direction are finite.

new

pub fn Line3::new(Vec3, Vec3) -> Self

The line through point in direction.

Intervalstruct

pub(all) struct Interval

A one-dimensional range between two numbers, min at or below max.

It is the one-dimensional case of an axis-aligned box, and what a timeline, an exposure or a depth range is. An empty interval — no numbers at all — is the one with min above max, which is how the union of nothing starts and how empty builds it; every operation here treats it as the identity the set operations expect.

Values are immutable.

Fields
min : Float

The low end, inclusive.

max : Float

The high end, inclusive.

CarriesDebug, Show

approx

pub fn Interval::approx(Self, Self, eps? : Float) -> Bool

Whether the two intervals agree end for end to within eps.

center

pub fn Interval::center(Self) -> Float

The midpoint of the interval.

contains

pub fn Interval::contains(Self, Float) -> Bool

Whether value lies in the interval, ends included.

empty

pub fn Interval::empty() -> Self

The interval with no numbers in it, which every union starts from.

expand

pub fn Interval::expand(Self, Float) -> Self

The interval grown by amount at both ends; a negative amount shrinks it.

extend_by

pub fn Interval::extend_by(Self, Float) -> Self

The interval grown to include value; the empty interval becomes [value, value].

intersection

pub fn Interval::intersection(Self, Self) -> Self?

The overlap of the two, or None when they do not meet.

intersects

pub fn Interval::intersects(Self, Self) -> Bool

Whether the two intervals share at least one point.

is_empty

pub fn Interval::is_empty(Self) -> Bool

Whether the interval holds no numbers: min above max.

is_finite

pub fn Interval::is_finite(Self) -> Bool

Whether both ends are finite.

new

pub fn Interval::new(Float, Float) -> Self

The interval from min to max; the two are not reordered, so passing them the other way round gives the empty interval.

size

pub fn Interval::size(Self) -> Float

The distance from min to max, or zero for the empty interval.

union

pub fn Interval::union(Self, Self) -> Self

The smallest interval holding both; the empty interval is the identity.

Trianglestruct

pub(all) struct Triangle

A triangle in space: three corners in winding order.

The winding decides which side the normal faces, by the right-hand rule.

Values are immutable.

Fields
a : Vec3

The first corner.

b : Vec3

The second corner.

c : Vec3

The third corner.

CarriesDebug, Show

approx

pub fn Triangle::approx(Self, Self, eps? : Float) -> Bool

Whether the two triangles have the same corners to within eps.

area

pub fn Triangle::area(Self) -> Float

The area.

barycentric

pub fn Triangle::barycentric(Self, Vec3) -> Vec3?

The barycentric coordinates of a point with respect to the triangle.

The three weights sum to one, and a point inside has all three in 0..1. The point is projected onto the triangle's plane first, so a point off the plane still has coordinates — they are those of the closest point on the plane. None when the triangle has no area to weight against.

intersect_ray

pub fn Triangle::intersect_ray(Self, Ray3) -> Float?

Where the ray meets the triangle, as a t, or None when it misses.

The same test as Ray3::intersect_triangle, written from this side for code that already has the triangle.

new

pub fn Triangle::new(Vec3, Vec3, Vec3) -> Self

The triangle with the three given corners.

normal

pub fn Triangle::normal(Self) -> Vec3

The unit normal, facing the way the corners wind.

A triangle with no area — three collinear points — has no normal, and comes back as the zero vector rather than a NaN.

Frustumstruct

pub struct Frustum

The six planes bounding what a camera can see, each facing inwards.

A view-projection matrix describes the visible volume as a set of inequalities in clip space; each of the six becomes one plane in world space, and culling is then a signed distance per plane per object. That is the cheapest test that still rejects most of a scene, which is why it is the one every renderer starts with.

The planes are built for a matrix whose depth range is 0..1. For an OpenGL-style matrix, whose near plane sits at -1, use from_matrix_gl.

Fields
planes : FixedArray[Plane]

The six planes, in the order left, right, bottom, top, near, far.

CarriesDebug, Eq, Show

approx

pub fn Frustum::approx(Self, Self, eps? : Float) -> Bool

Whether two frusta have the same six planes to within eps.

contains_aabb

pub fn Frustum::contains_aabb(Self, Aabb3) -> Bool

Whether the box lies entirely inside the frustum.

The corner furthest from each plane — the one the normal points away from — decides: if even that corner is inside, all eight are.

contains_point

pub fn Frustum::contains_point(Self, Vec3) -> Bool

Whether the point is inside all six planes, boundary included.

contains_sphere

pub fn Frustum::contains_sphere(Self, Sphere) -> Bool

Whether the sphere lies entirely inside the frustum.

from_matrix

pub fn Frustum::from_matrix(Mat4) -> Self?

The frustum of a view-projection matrix whose depth range is 0..1, or None when the matrix does not describe one.

The six planes are the six clip-space inequalities pulled back into world space: the left plane is the row w + x of the matrix, and so on. A matrix that is singular or degenerate — a projection with no near plane, say — gives a plane with no normal, and there is no frustum to return.

mbt check
test {
let projection = @moonmath.Mat4::perspective(
@moonmath.half_pi, 1.0, 0.1, 100.0,
)
let frustum = @moonmath.Frustum::from_matrix(projection).unwrap()
// A point just in front of the camera is inside, one behind it is not.
assert_true(frustum.contains_point(@moonmath.Vec3::new(0.0, 0.0, -1.0)))
assert_false(frustum.contains_point(@moonmath.Vec3::new(0.0, 0.0, 1.0)))
}

from_matrix_gl

pub fn Frustum::from_matrix_gl(Mat4) -> Self?

The frustum of a view-projection matrix whose depth range is -1..1.

intersects_aabb

pub fn Frustum::intersects_aabb(Self, Aabb3) -> Bool

Whether the frustum overlaps any part of the box.

The opposite corner from contains_aabb, for the opposite question: a box is out only when it lies wholly behind one plane.

intersects_line

pub fn Frustum::intersects_line(Self, Line3) -> Bool

Whether the infinite line meets the frustum at all.

Each of the six planes is a linear inequality in the line's parameter, so the part of the line inside the frustum is the intersection of six half-lines: one interval. The line meets the frustum exactly when that interval is not empty, which is the honest test an infinite line needs — unlike a ray, it has no start that could already be outside one plane while inside another.

intersects_sphere

pub fn Frustum::intersects_sphere(Self, Sphere) -> Bool

Whether the frustum overlaps any part of the sphere.

plane

pub fn Frustum::plane(Self, Int32) -> Plane

The plane at index, counted from zero in the order left, right, bottom, top, near, far.

planes

pub fn Frustum::planes(Self) -> FixedArray[Plane]

The planes of the frustum, in the order left, right, bottom, top, near, far.

A copy: the array the frustum holds cannot be reached from outside, so a caller cannot break the six-plane invariant by writing into it.

Colour

2

Red, green, blue and alpha, and the hue-saturation-value form of the same.

Color3struct

pub(all) struct Color3

A colour with three components, red, green and blue, and no alpha.

The components are plain numbers: this library does the arithmetic — adding a light, blending two values, lerping a gradient — and leaves the encoding to the caller, who knows whether the numbers are linear or sRGB and whether they are in 0..1 or 0..255. The HSV conversion is rgb_to_hsv, with the hue in turns and the other two in 0..1.

Values are immutable, and the operators work component by component.

Fields
r : Float

The red component.

g : Float

The green component.

b : Float

The blue component.

CarriesAdd, Debug, Div, Mul, Neg, Show, Sub

approx

pub fn Color3::approx(Self, Self, eps? : Float) -> Bool

Whether the two colours agree to within eps component by component.

clamp

pub fn Color3::clamp(Self, Self, Self) -> Self

The colour with every component pinned between low and high.

is_finite

pub fn Color3::is_finite(Self) -> Bool

Whether every component is finite.

lerp

pub fn Color3::lerp(Self, Self, Float) -> Self

The colour a fraction of the way from self to other.

max

pub fn Color3::max(Self, Self) -> Self

The component-wise larger of the two.

min

pub fn Color3::min(Self, Self) -> Self

The component-wise smaller of the two.

new

pub fn Color3::new(Float, Float, Float) -> Self

The colour from its three components.

one

pub fn Color3::one() -> Self

White: the most of every component.

splat

pub fn Color3::splat(Float) -> Self

The colour with the same value in all three components: a grey.

to_array

pub fn Color3::to_array(Self) -> FixedArray[Float]

The three components in order, [r, g, b], for a buffer.

zero

pub fn Color3::zero() -> Self

Black: no light at all.

Color4struct

pub(all) struct Color4

A colour with alpha: the three components of Color3 and an opacity.

The arithmetic is the same as Color3, with the fourth component carried along, so an alpha-premultiplied or straight-alpha pipeline can blend with the operators and decide the policy itself.

Values are immutable.

Fields
r : Float

The red component.

g : Float

The green component.

b : Float

The blue component.

a : Float

The opacity: one is opaque, zero is invisible.

CarriesAdd, Debug, Div, Mul, Neg, Show, Sub

approx

pub fn Color4::approx(Self, Self, eps? : Float) -> Bool

Whether the two colours agree to within eps component by component.

from_color3

pub fn Color4::from_color3(Color3, Float) -> Self

The colour of rgb at the opacity a.

is_finite

pub fn Color4::is_finite(Self) -> Bool

Whether every component is finite.

lerp

pub fn Color4::lerp(Self, Self, Float) -> Self

The colour a fraction of the way from self to other.

max

pub fn Color4::max(Self, Self) -> Self

The component-wise larger of the two.

min

pub fn Color4::min(Self, Self) -> Self

The component-wise smaller of the two.

new

pub fn Color4::new(Float, Float, Float, Float) -> Self

The colour from its four components.

splat

pub fn Color4::splat(Float) -> Self

The colour with the same value in every component.

to_array

pub fn Color4::to_array(Self) -> FixedArray[Float]

The four components in order, [r, g, b, a], for a buffer.

to_color3

pub fn Color4::to_color3(Self) -> Color3

The three colour components, dropping the alpha.

moonmath/f64

the same, at Double

The same shapes as the parent package, in double precision. Every type, method and value above appears here under the same name and with the same meaning, with Float replaced by Double; the two packages are expanded from one template. The integer vectors are absent, because they count pixels. What follows is the index of names, not a second copy of the sentences.

Values

approxapprox_angleclamp01default_epsilonhalf_pihsv_to_rgbinverse_lerplerppiquarter_piremaprgb_to_hsvsmoothsteptauto_degreesto_radianswrapwrap_range

Vectors

Vec2struct

absangle_betweenapproxceilclampcrossdistancedistance_squareddividedotfloorfractis_finitelengthlength_squaredlerpmaxminnewnormalizenormalize_oroneperpprojectreflectrefractrejectroundscalesplatto_arrayto_vec3to_vec4try_normalizeunit_xunit_yyxzero

Vec3struct

absangle_betweenapproxceilclampcrossdistancedistance_squareddividedotfloorfractis_finitelengthlength_squaredlerpmaxminnewnormalizenormalize_oroneprojectrandom_in_ballrandom_on_spherereflectrefractrejectroundscalesplatto_arrayto_vec4try_normalizeunit_xunit_yunit_zxyxzxzyyxzyzyzxzerozxyzyx

Vec4struct

absapproxceilclampdistancedistance_squareddividedotfloorfractis_finitelengthlength_squaredlerpmaxminnewnormalizenormalize_oroneroundscalesplatto_arraytry_normalizeunit_wunit_xunit_yunit_zwzyxxyxyzzero

Matrices

Mat2struct

approxcoldeterminantfrom_anglefrom_arrayfrom_colsfrom_rowsfrom_scalegetidentityinverseis_finitemul_vec2rowto_angleto_arraytransposezero

Mat3struct

approxcoldeterminantfrom_arrayfrom_axis_anglefrom_colsfrom_eulerfrom_euler_turnsfrom_mat4from_quatfrom_rowsfrom_scalegetidentityinverseis_finitemul_vec3rowto_arraytransposezero

Mat4struct

approxcoldeterminantfrom_arrayfrom_axis_anglefrom_colsfrom_eulerfrom_euler_turnsfrom_mat3from_quatfrom_rowsfrom_scalefrom_translationfrom_trsfrustumfrustum_glgetidentityinverseis_finitelook_atmul_vec4orthographicorthographic_glperspectiveperspective_glperspective_infiniteperspective_infinite_glrowto_arrayto_trstransform_pointtransform_vectortransposezero

Shearstruct

approxis_finitenewto_mat3to_mat4zero

Rotation

Quatstruct

approxconjugatedotfrom_axis_anglefrom_eulerfrom_euler_turnsfrom_mat3from_mat4from_rotation_arcidentityinverseis_finitelengthlength_squarednewnlerpnormalizerandomrotateslerpto_arrayto_axis_angleto_eulerto_euler_turnsto_mat3to_mat4

EulerOrderenum

Turnsstruct

approxnew

Placement

Trsstruct

new

Affine2struct

approxfrom_anglefrom_angle_translationfrom_mat3from_scalefrom_translationidentityinverseis_finitenewto_mat3transform_pointtransform_vector

Affine3struct

approxfrom_axis_anglefrom_mat4from_rotationfrom_scalefrom_translationfrom_trsidentityinverseis_finitenewto_mat4to_trstransform_pointtransform_vector

Geometry

Rectstruct

approxareacentercontainscornersfrom_edgesfrom_xywhheightinsetintersectionintersectsis_emptymaxminnewto_aabbtranslateunionwidth

Aabb2struct

approxareacentercontainscontains_pointcornersemptyexpandextentsfrom_center_half_extentsfrom_pointsintersectionintersectsis_emptynewsizeto_rectunion

Aabb3struct

approxcentercontainscontains_pointcornersemptyexpandextentsfrom_center_half_extentsfrom_pointsintersectionintersectsis_emptynewrandom_pointsizesurface_areatransformunionvolume

Ray2struct

approxatintersect_aabbintersect_aabb_intervalintersect_circleintersect_rectnew

Ray3struct

approxatintersect_aabbintersect_aabb_intervalintersect_planeintersect_sphereintersect_trianglenew

Planestruct

approxflipfrom_point_normalfrom_pointsintersect_rayis_finitenewprojectsigned_distance

Spherestruct

approxcontains_pointintersects_aabbintersects_spherenewrandom_insiderandom_on_surfacesurface_areavolume

Line3struct

approxatclosest_point_toclosest_point_to_linedistance_to_linedistance_to_pointintersect_planeis_finitenew

Intervalstruct

approxcentercontainsemptyexpandextend_byintersectionintersectsis_emptyis_finitenewsizeunion

Trianglestruct

approxareabarycentricintersect_raynewnormal

Frustumstruct

approxcontains_aabbcontains_pointcontains_spherefrom_matrixfrom_matrix_glintersects_aabbintersects_lineintersects_sphereplaneplanes

Colour

Color3struct

approxclampis_finitelerpmaxminnewonesplatto_arrayzero

Color4struct

approxfrom_color3is_finitelerpmaxminnewsplatto_arrayto_color3

Special functions

33

Special functions at double precision: the gamma and error families, the Bessel functions, the elliptic integrals, the hypergeometric functions and the Riemann zeta.

bessel_ifunction

pub fn bessel_i(Double, Double) -> Double

The modified Bessel function of the first kind I_v(x), for x > 0.

It grows like e^x, so a large argument runs past the largest finite double.

bessel_jfunction

pub fn bessel_j(Double, Double) -> Double

The Bessel function of the first kind J_v(x), for x > 0 and real v.

bessel_kfunction

pub fn bessel_k(Double, Double) -> Double

The modified Bessel function of the second kind K_v(x), for x > 0.

It decays like e^-x: bessel_k(0, 40) is about 8.4e-19, and the tail keeps falling from there.

bessel_yfunction

pub fn bessel_y(Double, Double) -> Double

The Bessel function of the second kind Y_v(x), for x > 0 and real v.

betafunction

pub fn beta(Double, Double) -> Double

The Euler beta function B(a, b) = Γ(a) Γ(b) / Γ(a + b), for positive arguments.

It is the normalising constant of the beta distribution and the value of the integral ∫ t^(a-1) (1-t)^(b-1) dt over 0..1.

digammafunction

pub fn digamma(Double) -> Double

The digamma ψ(x) = d/dx ln Γ(x), the logarithmic derivative of the gamma function.

ellipefunction

pub fn ellipe(Double) -> Double

The complete elliptic integral of the second kind E(m).

ellipeincfunction

pub fn ellipeinc(Double, Double) -> Double

The incomplete elliptic integral of the second kind E(phi, m) = ∫_0^phi sqrt(1 - m sin²θ) dθ.

ellipkfunction

pub fn ellipk(Double) -> Double

The complete elliptic integral of the first kind K(m), with m the parameter.

ellipkincfunction

pub fn ellipkinc(Double, Double) -> Double

The incomplete elliptic integral of the first kind F(phi, m) = ∫_0^phi dθ / sqrt(1 - m sin²θ).

ellipkm1function

pub fn ellipkm1(Double) -> Double

The complete elliptic integral of the first kind from the complementary parameter, K(1 - m).

elliprcfunction

pub fn elliprc(Double, Double) -> Double

The Carlson symmetric integral of the third kind, degenerate form R_C(x, y) = R_F(x, y, y).

elliprdfunction

pub fn elliprd(Double, Double, Double) -> Double

The Carlson symmetric integral of the second kind R_D(x, y, z).

elliprffunction

pub fn elliprf(Double, Double, Double) -> Double

The Carlson symmetric integral of the first kind R_F(x, y, z).

elliprgfunction

pub fn elliprg(Double, Double, Double) -> Double

The Carlson symmetric integral of the second kind, completely symmetric form R_G(x, y, z).

elliprjfunction

pub fn elliprj(Double, Double, Double, Double) -> Double

The Carlson symmetric integral of the third kind R_J(x, y, z, p).

It is the form the incomplete elliptic integral of the third kind is written in: a caller with a potential 1/(t + p) under the same square root.

erffunction

pub fn erf(Double) -> Double

The error function erf(x) = (2/sqrt π) ∫_0^x e^(-t²) dt.

erfcfunction

pub fn erfc(Double) -> Double

The complementary error function erfc(x) = 1 - erf(x).

It is the one to call in the tail, where 1 - erf(x) would lose every digit the result has.

erfcinvfunction

pub fn erfcinv(Double) -> Double

The inverse of the complementary error function: the y with erfc(y) = x, for x in 0 .. 2.

erfcxfunction

pub fn erfcx(Double) -> Double

The scaled complementary error function erfcx(x) = e^(x²) erfc(x), which stays representable where erfc itself has long underflowed.

erfifunction

pub fn erfi(Double) -> Double

The imaginary error function erfi(x) = -i erf(i x).

erfinvfunction

pub fn erfinv(Double) -> Double

The inverse of the error function: the y with erf(y) = x, for x in -1 .. 1.

gammafunction

pub fn gamma(Double) -> Double

The gamma function Γ(x), the continuous extension of the factorial.

Γ(n) = (n - 1)! for a positive integer, and the function is the integral ∫ t^(x-1) e^(-t) dt for x > 0. The whole real line is covered by the Stirling expansion plus the reflection Γ(x) Γ(1 - x) = π / sin(π x). A pole at a non-positive integer comes back as an infinity, as it should.

gammaincfunction

pub fn gammainc(Double, Double) -> Double

The regularised lower incomplete gamma P(a, x) = γ(a, x) / Γ(a), the cumulative distribution of the gamma distribution with unit rate.

gammainccfunction

pub fn gammaincc(Double, Double) -> Double

The regularised upper incomplete gamma Q(a, x) = Γ(a, x) / Γ(a) = 1 - P(a, x).

hyper0f1function

pub fn hyper0f1(Double, Double) -> Double

The confluent limit 0F1(; b; x) = Σ x^k / ((b)_k k!).

Its terms are all positive for b > 0 and x > 0, so it does not cancel and is summed directly.

hyper1f1function

pub fn hyper1f1(Double, Double, Double) -> Double

Kummer's confluent hypergeometric 1F1(a; b; x) = Σ (a)_k / ((b)_k k!) x^k.

The series is summed directly, with Kummer's transformation e^x 1F1(b - a; b; -x) past x = -4. Where the terms run a millionfold past the result the sum is redone at forty-five digits and rounded once, which is what carries the large-parameter region: 1F1(-19; 24.8; 32.5) is -2.2e-8, formed from terms around 1e4.

hyper2f1function

pub fn hyper2f1(Double, Double, Double, Double) -> Double

The Gauss hypergeometric 2F1(a, b; c; x), for |x| < 1.

Past a half the series converges too slowly to be worth summing, so the argument is moved to 1 - x by the linear transformation, and a negative argument takes Pfaff's.

This one has no escalation, and the reason is worth stating: with parameters of order a hundred and the argument near one, the two halves of the transformation sit around 10^450 either side of a result of order one. A fixed point of forty-five digits carries neither, so the wider type is not a rescue here — it is a different algorithm that is needed, and the doc comment on the body says what it is. A caller in that region should not read a double from this function and believe it.

incbetafunction

pub fn incbeta(Double, Double, Double) -> Double

The regularised incomplete beta I_x(a, b), the cumulative distribution of the beta distribution.

lbetafunction

pub fn lbeta(Double, Double) -> Double

The natural logarithm of the beta function.

The log form stays finite where beta itself would overflow or underflow.

lgammafunction

pub fn lgamma(Double) -> Double

The natural logarithm of the absolute value of the gamma function.

The log form is what a caller wants when Γ(x) itself would overflow a double: lgamma(1000) is about 5905, while gamma(1000) is past the largest finite double.

polygammafunction

pub fn polygamma(Int32, Double) -> Double

The polygamma ψ^(n)(x), the n-th derivative of the digamma.

n = 0 is the digamma itself; n = 1 the trigamma and n = 2 the tetragamma, the names a caller meets when a sum over 1/(k + x)^(n+1) has to be closed.

zetafunction

pub fn zeta(Double) -> Double

The Riemann zeta function ζ(s).

ζ(s) = Σ n^(-s) for s > 1, by Euler-Maclaurin. Below one the analytic continuation fills in through the functional equation, so a negative argument answers as well; the trivial zeros at the negative even integers come back as exactly zero. The simple pole at s = 1 is a positive infinity.