aboutsummaryrefslogtreecommitdiff
path: root/stdlib/source/test/lux/math/modular.lux
blob: 0137ba9ae70d8b57b1ed51f73f1e707ca0f48e5a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
(.using
 [library
  [lux (.except)
   ["_" test (.only Test)]
   ["[0]" type (.open: "[1]#[0]" equivalence)]
   [abstract
    [monad (.only do)]
    ["[0]" predicate]
    [\\specification
     ["$[0]" equivalence]
     ["$[0]" order]
     ["$[0]" monoid]
     ["$[0]" codec]]]
   [control
    ["[0]" try]
    ["[0]" exception]]
   [data
    ["[0]" product]
    ["[0]" bit (.open: "[1]#[0]" equivalence)]]
   [math
    ["[0]" random (.only Random)]
    [number
     ["i" int]]]]]
 ["$[0]" //
  ["[1]" modulus]]
 [\\library
  ["[0]" / (.only)
   ["/[1]" //
    ["[1]" modulus]]]])

(def: .public (random modulus)
  (All (_ %) (-> (//.Modulus %) (Random (/.Mod %))))
  (# random.monad each
     (/.modular modulus)
     random.int))

(def: .public test
  Test
  (<| (_.covering /._)
      (_.for [/.Mod])
      (do random.monad
        [param##% ($//.random +1,000,000)
         param (..random param##%)

         subject##% (random.only (predicate.and (|>> //.divisor (i.> +2))
                                                (|>> (//.= param##%) not))
                                 ($//.random +1,000,000))
         subject (..random subject##%)
         another (..random subject##%)]
        (`` (all _.and
                 (_.for [/.equivalence /.=]
                        ($equivalence.spec /.equivalence (..random subject##%)))
                 (_.for [/.order /.<]
                        ($order.spec /.order (..random subject##%)))
                 (~~ (template [<composite> <monoid>]
                       [(_.for [<monoid> <composite>]
                               ($monoid.spec /.equivalence (<monoid> subject##%) (..random subject##%)))]
                       
                       [/.+ /.addition]
                       [/.* /.multiplication]
                       ))
                 (_.for [/.codec]
                        ($codec.spec /.equivalence (/.codec subject##%) (..random subject##%)))

                 (_.coverage [/.incorrect_modulus]
                   (case (|> param
                             (# (/.codec param##%) encoded)
                             (# (/.codec subject##%) decoded))
                     {try.#Failure error}
                     (exception.match? /.incorrect_modulus error)
                     
                     {try.#Success _}
                     false))
                 (_.coverage [/.modulus]
                   (and (type#= (type_of (/.modulus subject))
                                (type_of (/.modulus subject)))
                        (not (type#= (type_of (/.modulus subject))
                                     (type_of (/.modulus param))))))
                 (_.coverage [/.modular /.value]
                   (/.= subject
                        (/.modular (/.modulus subject) (/.value subject))))
                 (_.coverage [/.>]
                   (bit#= (/.> another subject)
                          (/.< subject another)))
                 (_.coverage [/.<= /.>=]
                   (bit#= (/.<= another subject)
                          (/.>= subject another)))
                 (_.coverage [/.-]
                   (let [zero (/.modular (/.modulus subject) +0)]
                     (and (/.= zero
                               (/.- subject subject))
                          (/.= subject
                               (/.- zero subject)))))
                 (_.coverage [/.inverse]
                   (let [one (/.modular (/.modulus subject) +1)
                         co_prime? (i.co_prime? (//.divisor (/.modulus subject))
                                                (/.value subject))]
                     (case (/.inverse subject)
                       {.#Some subject^-1}
                       (and co_prime?
                            (|> subject
                                (/.* subject^-1)
                                (/.= one)))
                       
                       {.#None}
                       (not co_prime?))))
                 (_.coverage [/.adapter]
                   (<| (try.else false)
                       (do try.monad
                         [copy##% (//.modulus (//.divisor subject##%))
                          adapt (/.adapter subject##% copy##%)]
                         (in (|> subject
                                 /.value
                                 (/.modular copy##%)
                                 adapt
                                 (/.= subject))))))
                 (_.coverage [/.moduli_are_not_equal]
                   (case (/.adapter subject##% param##%)
                     {try.#Failure error}
                     (exception.match? /.moduli_are_not_equal error)
                     
                     {try.#Success _}
                     false))
                 )))))