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

(def: part
  (Random Nat)
  (\ random.monad map
     (|>> (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 [<compose> <monoid>]
                    [(_.for [<monoid> <compose>]
                            ($monoid.spec /.equivalence <monoid> ..random))]

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

              (do random.monad
                [.let [(^open "\.") /.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\map (n\= numerator))
                                   (maybe.else false))

                               denominator_1!
                               (|> (/.ratio numerator 1)
                                   /.nat
                                   (maybe\map (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)))
                    ))
              ))))