Source
tests/purrc/math_sys_test.cpp
1
// Copyright (c) 2026 BigBrain LLC. MIT-licensed (see LICENSE).2
// Original work; see ACKNOWLEDGMENTS.md for the open-source ideas we build upon.3
// System-level test for the cheatah stdlib `math` module: ONE cohesive program4
// that exercises EVERY public function and constant declared in5
// stdlib/math/math.hpp (sqrt, cbrt, fabs, floor, ceil, trunc, round, exp, log,6
// log2, log10, sin, cos, tan, asin, acos, atan, atan2, hypot, fmod, copysign,7
// degrees, radians, isnan, isinf, isfinite, gcd, factorial, and the math-related8
// built-ins abs/min/max/pow, plus the constants pi/e/tau/inf/nan).9
//10
// Unlike the per-function compile-run tests (math_cr_test.cpp), this drives a11
// small geometry / number-theory pipeline that wires the functions together12
// (round_to uses round+pow; unit_point uses cos/sin/hypot; the combined section13
// reduces a fraction by gcd then norms it via pow/sqrt) and prints a single14
// deterministic multi-line report.15
//16
// The expected stdout below was captured by compiling and running the program17
// with the debug-build purrc + cheatah and confirming the output is identical18
// across repeated runs (md5 stable) before hardcoding it. Nothing here is19
// time/RNG dependent, so it is reproducible byte-for-byte.21
#include "e2e_harness.hpp"23
TEST(StdlibE2E, Math) {24
e2e::expect_e2e("math_sys", R"PURR(import io25
import math27
# A cohesive pipeline exercising every public function/constant in stdlib/math.28
# It builds a little geometry/number-theory "report" from a few seeds.30
# --- helpers ---------------------------------------------------------------32
# Round a double to `digits` decimal places (uses round/pow).33
fn round_to(x, digits) {34
let scale = math.pow(10, digits)35
return math.round(x * scale) / scale36
}38
# Polar -> cartesian distance check using trig + hypot.39
fn unit_point(theta) {40
# returns hypot(cos, sin) which is 1 for any theta41
return math.hypot(math.cos(theta), math.sin(theta))42
}44
# --- 1) constants ----------------------------------------------------------45
io.print("== constants ==")46
io.print("pi", round_to(math.pi, 5), "e", round_to(math.e, 5), "tau", round_to(math.tau, 5))47
io.print("inf", math.inf, "nan", math.nan)49
# --- 2) roots and powers ---------------------------------------------------50
let r = math.sqrt(2.0) # ~1.4142151
let c = math.cbrt(27.0) # 352
let p = math.pow(2, 10) # 102453
io.print("== roots/powers ==")54
io.print("sqrt2", round_to(r, 5), "cbrt27", c, "pow", p)56
# --- 3) rounding family ----------------------------------------------------57
let v = -2.758
io.print("== rounding ==")59
io.print("fabs", math.fabs(v), "floor", math.floor(v), "ceil", math.ceil(v))60
io.print("trunc", math.trunc(v), "round", math.round(v))62
# --- 4) exponentials / logs ------------------------------------------------63
let x = math.exp(1.0) # e64
io.print("== exp/log ==")65
io.print("exp1", round_to(x, 5))66
io.print("ln_e", round_to(math.log(math.e), 5), "log2_8", math.log2(8.0), "log10_1000", math.log10(1000.0))68
# --- 5) trigonometry -------------------------------------------------------69
let theta = math.pi / 4.0 # 45 degrees70
io.print("== trig ==")71
io.print("sin", round_to(math.sin(theta), 5), "cos", round_to(math.cos(theta), 5), "tan", round_to(math.tan(theta), 5))72
io.print("asin", round_to(math.asin(1.0), 5), "acos", round_to(math.acos(1.0), 5))73
io.print("atan", round_to(math.atan(1.0), 5), "atan2", round_to(math.atan2(1.0, 1.0), 5))74
io.print("unit_pt", round_to(unit_point(theta), 5))76
# --- 6) misc real ----------------------------------------------------------77
io.print("== misc ==")78
io.print("hypot", math.hypot(3.0, 4.0), "fmod", math.fmod(7.0, 3.0), "copysign", math.copysign(3.0, -1.0))79
io.print("degrees", math.degrees(math.pi), "radians", round_to(math.radians(180.0), 5))81
# --- 7) classification -----------------------------------------------------82
io.print("== classify ==")83
io.print("isnan", math.isnan(math.nan), "isinf", math.isinf(math.inf), "isfinite", math.isfinite(1.0))85
# --- 8) integer ops + builtins ---------------------------------------------86
io.print("== integer/builtins ==")87
io.print("gcd", math.gcd(48, 36), "fact", math.factorial(6))88
io.print("abs", math.abs(-7), "min", math.min(3, 9, 1, 5), "max", math.max(3, 9, 1, 5))90
# --- 9) a small combined computation ---------------------------------------91
# Reduce a fraction 48/36 by its gcd, then take pow/sqrt of the pieces.92
let g = math.gcd(48, 36)93
let num = 48 / g94
let den = 36 / g95
let combined = math.sqrt(math.pow(num, 2) + math.pow(den, 2))96
io.print("== combined ==")97
io.print("reduced", num, den, "norm", round_to(combined, 5))98
)PURR",99
"== constants ==\n"100
"pi 3.14159 e 2.71828 tau 6.28319\n"101
"inf inf nan nan\n"102
"== roots/powers ==\n"103
"sqrt2 1.41421 cbrt27 3 pow 1024\n"104
"== rounding ==\n"105
"fabs 2.7 floor -3 ceil -2\n"106
"trunc -2 round -3\n"107
"== exp/log ==\n"108
"exp1 2.71828\n"109
"ln_e 1 log2_8 3 log10_1000 3\n"110
"== trig ==\n"111
"sin 0.70711 cos 0.70711 tan 1\n"112
"asin 1.5708 acos 0\n"113
"atan 0.7854 atan2 0.7854\n"114
"unit_pt 1\n"115
"== misc ==\n"116
"hypot 5 fmod 1 copysign -3\n"117
"degrees 180 radians 3.14159\n"118
"== classify ==\n"119
"isnan True isinf True isfinite True\n"120
"== integer/builtins ==\n"121
"gcd 12 fact 720\n"122
"abs 7 min 1 max 9\n"123
"== combined ==\n"124
"reduced 4 3 norm 5\n");125
}