aboutsummaryrefslogtreecommitdiff
path: root/stdlib/source/test/lux/math/modular.lux
diff options
context:
space:
mode:
authorEduardo Julian2019-02-05 19:09:31 -0400
committerEduardo Julian2019-02-05 19:09:31 -0400
commit47b97c128bde837fa803a605f3e011a3e9ddd71c (patch)
tree5e8a84d1b1812ec4a157d4049c778ec2e4e434c4 /stdlib/source/test/lux/math/modular.lux
parentbe5710d104e6ee085dcb9d871be0b80305e48f8b (diff)
Integrated tests into normal source code.
Diffstat (limited to 'stdlib/source/test/lux/math/modular.lux')
-rw-r--r--stdlib/source/test/lux/math/modular.lux150
1 files changed, 150 insertions, 0 deletions
diff --git a/stdlib/source/test/lux/math/modular.lux b/stdlib/source/test/lux/math/modular.lux
new file mode 100644
index 000000000..b5ff0e40b
--- /dev/null
+++ b/stdlib/source/test/lux/math/modular.lux
@@ -0,0 +1,150 @@
+(.module:
+ [lux #*
+ [control
+ [monad (#+ do)]]
+ [data
+ ["." product]
+ [bit ("bit/." equivalence)]
+ ["." error]
+ [text
+ format]]
+ [math
+ ["r" random]
+ ["/" modular]]
+ [type ("type/." equivalence)]]
+ lux/test)
+
+(def: %3 (/.modulus +3))
+(`` (type: Mod3 (~~ (:of %3))))
+
+(def: modulusR
+ (r.Random Int)
+ (|> r.int
+ (:: r.monad map (i/% +1000))
+ (r.filter (|>> (i/= +0) not))))
+
+(def: valueR
+ (r.Random Int)
+ (|> r.int (:: r.monad map (i/% +1000))))
+
+(def: (modR modulus)
+ (All [m] (-> (/.Modulus m) (r.Random [Int (/.Mod m)])))
+ (do r.monad
+ [raw valueR]
+ (wrap [raw (/.mod modulus raw)])))
+
+(def: value
+ (All [m] (-> (/.Mod m) Int))
+ (|>> /.un-mod product.left))
+
+(def: (comparison m/? i/?)
+ (All [m]
+ (-> (-> (/.Mod m) (/.Mod m) Bit)
+ (-> Int Int Bit)
+ (-> (/.Mod m) (/.Mod m) Bit)))
+ (function (_ param subject)
+ (bit/= (m/? param subject)
+ (i/? (value param)
+ (value subject)))))
+
+(def: (arithmetic modulus m/! i/!)
+ (All [m]
+ (-> (/.Modulus m)
+ (-> (/.Mod m) (/.Mod m) (/.Mod m))
+ (-> Int Int Int)
+ (-> (/.Mod m) (/.Mod m) Bit)))
+ (function (_ param subject)
+ (|> (i/! (value param)
+ (value subject))
+ (/.mod modulus)
+ (/.m/= (m/! param subject)))))
+
+(context: "Modular arithmetic."
+ (<| (times 100)
+ (do @
+ [_normalM modulusR
+ _alternativeM (|> modulusR (r.filter (|>> (i/= _normalM) not)))
+ #let [normalM (|> _normalM /.from-int error.assume)
+ alternativeM (|> _alternativeM /.from-int error.assume)]
+ [_param param] (modR normalM)
+ [_subject subject] (modR normalM)
+ #let [copyM (|> normalM /.to-int /.from-int error.assume)]]
+ ($_ seq
+ (test "Every modulus has a unique type, even if the numeric value is the same as another."
+ (and (type/= (:of normalM)
+ (:of normalM))
+ (not (type/= (:of normalM)
+ (:of alternativeM)))
+ (not (type/= (:of normalM)
+ (:of copyM)))))
+
+ (test "Can extract the original integer from the modulus."
+ (i/= _normalM
+ (/.to-int normalM)))
+
+ (test "Can compare mod'ed values."
+ (and (/.m/= subject subject)
+ ((comparison /.m/= i/=) param subject)
+ ((comparison /.m/< i/<) param subject)
+ ((comparison /.m/<= i/<=) param subject)
+ ((comparison /.m/> i/>) param subject)
+ ((comparison /.m/>= i/>=) param subject)))
+
+ (test "Mod'ed values are ordered."
+ (and (bit/= (/.m/< param subject)
+ (not (/.m/>= param subject)))
+ (bit/= (/.m/> param subject)
+ (not (/.m/<= param subject)))
+ (bit/= (/.m/= param subject)
+ (not (or (/.m/< param subject)
+ (/.m/> param subject))))))
+
+ (test "Can do arithmetic."
+ (and ((arithmetic normalM /.m/+ i/+) param subject)
+ ((arithmetic normalM /.m/- i/-) param subject)
+ ((arithmetic normalM /.m/* i/*) param subject)))
+
+ (test "Can sometimes find multiplicative inverse."
+ (case (/.inverse subject)
+ (#.Some subject^-1)
+ (|> subject
+ (/.m/* subject^-1)
+ (/.m/= (/.mod normalM +1)))
+
+ #.None
+ #1))
+
+ (test "Can encode/decode to text."
+ (let [(^open "mod/.") (/.codec normalM)]
+ (case (|> subject mod/encode mod/decode)
+ (#error.Success output)
+ (/.m/= subject output)
+
+ (#error.Failure error)
+ #0)))
+
+ (test "Can equalize 2 moduli if they are equal."
+ (case (/.equalize (/.mod normalM _subject)
+ (/.mod copyM _param))
+ (#error.Success paramC)
+ (/.m/= param paramC)
+
+ (#error.Failure error)
+ #0))
+
+ (test "Cannot equalize 2 moduli if they are the different."
+ (case (/.equalize (/.mod normalM _subject)
+ (/.mod alternativeM _param))
+ (#error.Success paramA)
+ #0
+
+ (#error.Failure error)
+ #1))
+
+ (test "All numbers are congruent to themselves."
+ (/.congruent? normalM _subject _subject))
+
+ (test "If 2 numbers are congruent under a modulus, then they must also be equal under the same modulus."
+ (bit/= (/.congruent? normalM _param _subject)
+ (/.m/= param subject)))
+ ))))