diff options
Diffstat (limited to 'stdlib/source/test/lux/math.lux')
-rw-r--r-- | stdlib/source/test/lux/math.lux | 125 |
1 files changed, 125 insertions, 0 deletions
diff --git a/stdlib/source/test/lux/math.lux b/stdlib/source/test/lux/math.lux new file mode 100644 index 000000000..002cdaa41 --- /dev/null +++ b/stdlib/source/test/lux/math.lux @@ -0,0 +1,125 @@ +(.module: + [lux #* + [control + [monad (#+ Monad do)]] + [data + [bit ("bit/." equivalence)] + [number ("frac/." number)]] + ["&" math + infix + ["r" random]]] + lux/test) + +(def: (within? margin-of-error standard value) + (-> Frac Frac Frac Bit) + (f/< margin-of-error + (frac/abs (f/- standard value)))) + +(def: margin Frac +0.0000001) + +(def: (trigonometric-symmetry forward backward angle) + (-> (-> Frac Frac) (-> Frac Frac) Frac Bit) + (let [normal (|> angle forward backward)] + (|> normal forward backward (within? margin normal)))) + +(context: "Trigonometry" + (<| (times 100) + (do @ + [angle (|> r.frac (:: @ map (f/* &.tau)))] + ($_ seq + (test "Sine and arc-sine are inverse functions." + (trigonometric-symmetry &.sin &.asin angle)) + + (test "Cosine and arc-cosine are inverse functions." + (trigonometric-symmetry &.cos &.acos angle)) + + (test "Tangent and arc-tangent are inverse functions." + (trigonometric-symmetry &.tan &.atan angle)) + )))) + +(context: "Rounding" + (<| (times 100) + (do @ + [sample (|> r.frac (:: @ map (f/* +1000.0)))] + ($_ seq + (test "The ceiling will be an integer value, and will be >= the original." + (let [ceil'd (&.ceil sample)] + (and (|> ceil'd frac-to-int int-to-frac (f/= ceil'd)) + (f/>= sample ceil'd) + (f/<= +1.0 (f/- sample ceil'd))))) + + (test "The floor will be an integer value, and will be <= the original." + (let [floor'd (&.floor sample)] + (and (|> floor'd frac-to-int int-to-frac (f/= floor'd)) + (f/<= sample floor'd) + (f/<= +1.0 (f/- floor'd sample))))) + + (test "The round will be an integer value, and will be < or > or = the original." + (let [round'd (&.round sample)] + (and (|> round'd frac-to-int int-to-frac (f/= round'd)) + (f/<= +1.0 (frac/abs (f/- sample round'd)))))) + )))) + +(context: "Exponentials and logarithms" + (<| (times 100) + (do @ + [sample (|> r.frac (:: @ map (f/* +10.0)))] + (test "Logarithm is the inverse of exponential." + (|> sample &.exp &.log (within? +1.0e-15 sample)))))) + +(context: "Greatest-Common-Divisor and Least-Common-Multiple" + (<| (times 100) + (do @ + [#let [gen-nat (|> r.nat (:: @ map (|>> (n/% 1000) (n/max 1))))] + x gen-nat + y gen-nat] + ($_ seq + (test "GCD" + (let [gcd (&.n/gcd x y)] + (and (n/= 0 (n/% gcd x)) + (n/= 0 (n/% gcd y)) + (n/>= 1 gcd)))) + + (test "LCM" + (let [lcm (&.n/lcm x y)] + (and (n/= 0 (n/% x lcm)) + (n/= 0 (n/% y lcm)) + (n/<= (n/* x y) lcm)))) + )))) + +(context: "Infix syntax" + (<| (times 100) + (do @ + [x r.nat + y r.nat + z r.nat + theta r.frac + #let [top (|> x (n/max y) (n/max z)) + bottom (|> x (n/min y) (n/min z))]] + ($_ seq + (test "Constant values don't change." + (n/= x + (infix x))) + + (test "Can call binary functions." + (n/= (&.n/gcd y x) + (infix [x &.n/gcd y]))) + + (test "Can call unary functions." + (f/= (&.sin theta) + (infix [&.sin theta]))) + + (test "Can use regular syntax in the middle of infix code." + (n/= (&.n/gcd 450 (n/* 3 9)) + (infix [(n/* 3 9) &.n/gcd 450]))) + + (test "Can use non-numerical functions/macros as operators." + (bit/= (and (n/< y x) (n/< z y)) + (infix [[x n/< y] and [y n/< z]]))) + + (test "Can combine bit operations in special ways via special keywords." + (and (bit/= (and (n/< y x) (n/< z y)) + (infix [#and x n/< y n/< z])) + (bit/= (and (n/< y x) (n/> z y)) + (infix [#and x n/< y n/> z])))) + )))) |