std/math — Fixed-point math¶
import std/math
A mathematics library that works entirely in Q8.8 fixed-point (the r16
type — see Type system). There is no floating-point hardware on the
AVR, so every “real” value here is a 16-bit fixed-point number: 8 integer bits
and 8 fractional bits, i.e. the true value scaled by 256.
Because of that representation, results are approximations with limited range
(roughly ±128) and precision (steps of 1/256). The transcendental functions
use series expansions and identities chosen to stay within 16-bit arithmetic;
treat them as good engineering approximations, not IEEE-exact.
Angles for the trigonometric functions are given in whole degrees as u16
(not radians), which keeps the common case exact and avoids a fixed-point
conversion at every call.
Constants¶
- @pi() -> r16¶
π, Archimedes’ constant (≈ 3.14 in Q8.8).
- @e() -> r16¶
e, Euler’s number (≈ 2.718).
- @tau() -> r16¶
τ = 2π (≈ 6.283).
Rounding and sign¶
- @abs($x: r16) -> r16¶
Absolute value of a signed fixed-point
$x.
- @ceil($x: r16) -> r16¶
Round
$xup to the nearest integer value (toward +∞).
- @floor($x: r16) -> r16¶
Round
$xdown to the nearest integer value (toward −∞).
- @trunc($x: r16) -> r16¶
Round
$xtoward zero, discarding the fractional part.
- @copysign($x: r16, $y: r16) -> r16¶
Return a value with the magnitude of
$xand the sign of$y.
- @fmod($x: r16, $y: r16) -> r16¶
Floating-style remainder of
$xdivided by$y.
Comparison and ranges¶
- @min($a: r16, $b: r16) -> r16¶
The smaller of two signed fixed-point values.
- @max($a: r16, $b: r16) -> r16¶
The larger of two signed fixed-point values.
- @clamp($val: r16, $min_val: r16, $max_val: r16) -> r16¶
Constrain
$valto the inclusive range[$min_val, $max_val].
- @map($val: r16, $in_min: r16, $in_max: r16, $out_min: r16, $out_max: r16) -> r16¶
Linearly remap
$valfrom the input range to the output range.
- @isclose($a: r16, $b: r16, $rel_tol: r16) -> r16¶
Test whether
$aand$bare within tolerance$rel_tolof each other.
Floating-status predicates¶
These exist for API completeness. A Q8.8 value is always finite, so the answers
are constant — they let code that expects an isnan/isinf interface
compile and behave sensibly.
- @isnan($x: r16) -> r16¶
Whether
$xis NaN. Fixed-point has no NaN, so this is always false.
- @isinf($x: r16) -> r16¶
Whether
$xis ±infinity. Fixed-point has no infinities.
- @isfinite($x: r16) -> r16¶
Whether
$xis finite (always true for a fixed-point value).
Powers, roots, exponentials, logs¶
- @pow($base: r16, $exp: u16) -> r16¶
$baseraised to the integer power$exp, by binary exponentiation (square-and-multiply).
- @sqrt($x: r16) -> r16¶
Square root of
$x, by digit-by-digit (binary) extraction.
- @exp($x: r16) -> r16¶
e raised to the power
$x, via a 5th-degree Maclaurin series. The input is capped at 5.0 to avoid 16-bit overflow.
- @log($x: r16) -> r16¶
Natural logarithm
ln($x), via range-reduction against e and a Taylor series.
Trigonometry¶
Angles are in degrees (u16) unless noted.
- @sin($deg: u16) -> r16¶
Sine of
$degdegrees, using quadrant symmetry.
- @cos($deg: u16) -> r16¶
Cosine of
$degdegrees (a 90° phase shift of sine).
- @tan($deg: u16) -> r16¶
Tangent of
$degdegrees, as sine over cosine (guards the zero-cosine case).
- @radians($deg: u16) -> r16¶
Convert
$degdegrees to radians (returned as Q8.8).
- @degrees($rad: r16) -> u16¶
Convert
$radradians (Q8.8) to whole degrees.
- @hypot($x: r16, $y: r16) -> r16¶
sqrt($x² + $y²), computed to avoid intermediate overflow.
- @dist($x1: r16, $y1: r16, $x2: r16, $y2: r16) -> r16¶
Euclidean distance between the points (
$x1,``$y1``) and ($x2,``$y2``).
Hyperbolic¶
- @sinh($x: r16) -> r16¶
Hyperbolic sine.
- @cosh($x: r16) -> r16¶
Hyperbolic cosine.
- @tanh($x: r16) -> r16¶
Hyperbolic tangent, as
sinh/cosh.
- @asinh($x: r16) -> r16¶
Inverse hyperbolic sine.
- @acosh($x: r16) -> r16¶
Inverse hyperbolic cosine.
- @atanh($x: r16) -> r16¶
Inverse hyperbolic tangent.
Integer number theory¶
These take and return plain integers, not fixed-point.
- @gcd($a: u16, $b: u16) -> u16¶
Greatest common divisor, by the Euclidean algorithm.
- @lcm($a: u16, $b: u16) -> u16¶
Least common multiple of
$aand$b.
- @factorial($n: u8) -> u16¶
$n!computed iteratively. Overflows au16for$nabove 8.
- @fibonacci($n: u8) -> u16¶
The
$n-th Fibonacci number, computed iteratively.
- @perm($n: u8, $k: u8) -> u16¶
The number of permutations of
$nitems taken$kat a time.
- @gamma($x: u8) -> u16¶
The Gamma function for integer input, i.e.
($x − 1)!.
Example¶
import std/math
@main {
ram imut $s: r16 = @sin(30) # angle in degrees -> ~0.5 (Q8.8)
ram imut $rt: r16 = @sqrt(2.0) # 2.0 is a fixed-point literal -> ~1.414
ram imut $hi: r16 = @clamp(9.0, 0.0, 5.0) # 9 is above the max -> clamped to 5.0
ram imut $g: u16 = @gcd(48, 36) # plain integers in/out -> 12
loop * { }
}
Note
The functions with names beginning with an underscore — @_q88_mul,
@_q88_div, @_sin_180 — are the internal fixed-point primitives the
public functions are built on. You normally do not call them directly.