aboutsummaryrefslogtreecommitdiff
path: root/stdlib/source/test/lux/math/number/ratio.lux
blob: d9c1c1ba8ef268af7765161c733899ca7d5c684e (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
125
126
127
(.using
 [library
  [lux "*"
   ["_" test {"+" Test}]
   [abstract
    [monad {"+" do}]
    [\\specification
     ["$[0]" equivalence]
     ["$[0]" order]
     ["$[0]" monoid]
     ["$[0]" codec]]]
   [control
    ["[0]" maybe ("[1]#[0]" functor)]]
   [data
    ["[0]" bit ("[1]#[0]" equivalence)]]
   [math
    ["[0]" random {"+" Random}]]]]
 [\\library
  ["[0]" /
   [//
    ["n" nat ("[1]#[0]" equivalence)]]]])

(def: part
  (Random Nat)
  (# random.monad each
     (|>> (n.% 1,000,000) (n.max 1))
     random.nat))

(def: .public random
  (Random /.Ratio)
  (do random.monad
    [numerator ..part
     denominator (random.only (|>> (n.= 0) not)
                              ..part)]
    (in (/.ratio numerator denominator))))

(def: .public test
  Test
  (<| (_.covering /._)
      (_.for [/.Ratio])
      (`` ($_ _.and
              (_.for [/.equivalence /.=]
                     ($equivalence.spec /.equivalence ..random))
              (_.for [/.order /.<]
                     ($order.spec /.order ..random))
              (~~ (template [<composite> <monoid>]
                    [(_.for [<monoid> <composite>]
                            ($monoid.spec /.equivalence <monoid> ..random))]

                    [/.+ /.addition]
                    [/.* /.multiplication]
                    ))
              (_.for [/.codec]
                     ($codec.spec /.equivalence /.codec ..random))

              (do random.monad
                [.let [(open "#[0]") /.equivalence]
                 denom/0 ..part
                 denom/1 ..part]
                (_.cover [/.ratio]
                         (#= (/.ratio 0 denom/0)
                             (/.ratio 0 denom/1))))
              (do random.monad
                [numerator ..part
                 denominator (random.only (|>> (n#= 1) not)
                                          ..part)]
                (_.cover [/.nat]
                         (let [only_numerator!
                               (|> (/.ratio numerator)
                                   /.nat
                                   (maybe#each (n#= numerator))
                                   (maybe.else false))

                               denominator_1!
                               (|> (/.ratio numerator 1)
                                   /.nat
                                   (maybe#each (n#= numerator))
                                   (maybe.else false))

                               with_denominator!
                               (case (/.nat (/.ratio numerator denominator))
                                 {.#Some factor}
                                 (and (n.= 0 (n.% denominator numerator))
                                      (n.= numerator (n.* factor denominator)))
                                 
                                 {.#None}
                                 (not (n.= 0 (n.% denominator numerator))))]
                           (and only_numerator!
                                denominator_1!
                                with_denominator!))))
              (do random.monad
                [sample ..random]
                ($_ _.and
                    (_.cover [/.-]
                             (and (/.= (/.ratio 0) (/.- sample sample))
                                  (/.= sample (/.- (/.ratio 0) sample))))
                    (_.cover [/./]
                             (and (/.= (/.ratio 1) (/./ sample sample))
                                  (/.= sample (/./ (/.ratio 1) sample))))
                    (_.cover [/.reciprocal]
                             (/.= (/.ratio 1)
                                  (/.* sample (/.reciprocal sample))))
                    ))
              (do random.monad
                [left (random.only (|>> (/.= (/.ratio 0)) not)
                                   ..random)
                 right ..random]
                (_.cover [/.%]
                         (let [rem (/.% left right)
                               div (|> right (/.- rem) (/./ left))]
                           (and (/.= right
                                     (|> div (/.* left) (/.+ rem)))
                                (case (/.nat div)
                                  {.#Some _} true
                                  {.#None}   false)))))
              (do random.monad
                [left ..random
                 right ..random]
                ($_ _.and
                    (_.cover [/.>]
                             (bit#= (/.> left right)
                                    (/.< right left)))
                    (_.cover [/.<= /.>=]
                             (bit#= (/.<= left right)
                                    (/.>= right left)))
                    ))
              ))))