aboutsummaryrefslogtreecommitdiff
path: root/stdlib/source/test/lux/math/number/ratio.lux
blob: 9865db7ed378054e6907a2ab32aa5b675a6a6bd4 (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
(.require
 [library
  [lux (.except)
   ["_" test (.only Test)]
   [abstract
    [monad (.only do)]
    [\\specification
     ["$[0]" equivalence]
     ["$[0]" order]
     ["$[0]" monoid]
     ["$[0]" codec]]]
   [control
    ["[0]" maybe (.use "[1]#[0]" functor)]]
   [data
    ["[0]" bit (.use "[1]#[0]" equivalence)]]
   [math
    ["[0]" random (.only Random)]]]]
 [\\library
  ["[0]" / (.only)
   [//
    ["n" nat (.use "[1]#[0]" equivalence)]]]])

(def part
  (Random Nat)
  (at 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])
      (`` (all _.and
               (_.for [/.equivalence /.=]
                      ($equivalence.spec /.equivalence ..random))
               (_.for [/.order /.<]
                      ($order.spec /.order ..random))
               (~~ (with_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]
                 (_.coverage [/.ratio]
                   (#= (/.ratio 0 denom/0)
                       (/.ratio 0 denom/1))))
               (do random.monad
                 [numerator ..part
                  denominator (random.only (|>> (n#= 1) not)
                                           ..part)]
                 (_.coverage [/.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]
                 (all _.and
                      (_.coverage [/.-]
                        (and (/.= (/.ratio 0) (/.- sample sample))
                             (/.= sample (/.- (/.ratio 0) sample))))
                      (_.coverage [/./]
                        (and (/.= (/.ratio 1) (/./ sample sample))
                             (/.= sample (/./ (/.ratio 1) sample))))
                      (_.coverage [/.reciprocal]
                        (/.= (/.ratio 1)
                             (/.* sample (/.reciprocal sample))))
                      ))
               (do random.monad
                 [left (random.only (|>> (/.= (/.ratio 0)) not)
                                    ..random)
                  right ..random]
                 (_.coverage [/.%]
                   (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]
                 (all _.and
                      (_.coverage [/.>]
                        (bit#= (/.> left right)
                               (/.< right left)))
                      (_.coverage [/.<= /.>=]
                        (bit#= (/.<= left right)
                               (/.>= right left)))
                      ))
               ))))