diff options
author | Eduardo Julian | 2019-02-05 19:09:31 -0400 |
---|---|---|
committer | Eduardo Julian | 2019-02-05 19:09:31 -0400 |
commit | 47b97c128bde837fa803a605f3e011a3e9ddd71c (patch) | |
tree | 5e8a84d1b1812ec4a157d4049c778ec2e4e434c4 /stdlib/source/test/lux/math/modular.lux | |
parent | be5710d104e6ee085dcb9d871be0b80305e48f8b (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.lux | 150 |
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))) + )))) |