aboutsummaryrefslogtreecommitdiff
path: root/stdlib/source/test/lux/math.lux
diff options
context:
space:
mode:
Diffstat (limited to 'stdlib/source/test/lux/math.lux')
-rw-r--r--stdlib/source/test/lux/math.lux125
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]))))
+ ))))