aboutsummaryrefslogtreecommitdiff
path: root/stdlib/source/library/lux/math/modulus.lux
blob: 05a0ef26db0b194f7dea034497c81cfbea7d1997 (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
(.module:
  [library
   [lux #*
    ["." meta]
    [abstract
     [monad (#+ do)]]
    [control
     ["." try (#+ Try)]
     ["." exception (#+ exception:)]
     [parser
      ["<.>" code]]]
    [macro
     [syntax (#+ syntax:)]
     ["." code]]
    [math
     [number
      ["i" int]]]
    [type
     abstract]]])

(exception: #export zero_cannot_be_a_modulus)

(abstract: #export (Modulus %)
  Int

  {#.doc (doc "A number used as a modulus in modular arithmetic."
              "It cannot be 0.")}

  (def: #export (modulus value)
    (Ex [%] (-> Int (Try (Modulus %))))
    (if (i.= +0 value)
      (exception.except ..zero_cannot_be_a_modulus [])
      (#try.Success (:abstraction value))))

  (def: #export divisor
    (All [%] (-> (Modulus %) Int))
    (|>> :representation))

  (def: #export (= reference subject)
    (All [%r %s] (-> (Modulus %r) (Modulus %s) Bit))
    (i.= (:representation reference)
         (:representation subject)))

  (def: #export (congruent? modulus reference subject)
    (All [%] (-> (Modulus %) Int Int Bit))
    (|> subject
        (i.- reference)
        (i.% (:representation modulus))
        (i.= +0)))
  )

(syntax: #export (literal {divisor <code>.int})
  {#.doc (doc "Success!"
              (literal 123)

              "Failure!"
              (literal 0))}
  (meta.lift
   (do try.monad
     [_ (..modulus divisor)]
     (in (list (` ((~! try.assumed) (..modulus (~ (code.int divisor))))))))))