aboutsummaryrefslogtreecommitdiff
path: root/stdlib/source/library/lux/meta/type/unit/scale.lux
blob: 9f4f7e1f9355430fda1fc7c93abc1fa4917ec64c (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
(.require
 [library
  [lux (.except type)
   [math
    [number
     ["i" int]
     ["[0]" ratio (.only Ratio)]]]
   [meta
    ["[0]" code
     ["<[1]>" \\parser]]
    ["[0]" macro (.only)
     [syntax (.only syntax)]]]]]
 ["[0]" // (.only)
  ["/[1]" //]])

(.type .public (Scale s)
  (Interface
   (is (All (_ u) (-> (//.Measure Any u) (//.Measure s u)))
       up)
   (is (All (_ u) (-> (//.Measure s u) (//.Measure Any u)))
       down)
   (is Ratio
       ratio)))

(def .public (scale ratio)
  (Ex (_ s) (-> Ratio (Scale s)))
  (let [(open "/[0]") ratio]
    (implementation
     (def up
       (|>> //.number
            (i.* (.int /#numerator))
            (i./ (.int /#denominator))
            //.measure))
     (def down
       (|>> //.number
            (i.* (.int /#denominator))
            (i./ (.int /#numerator))
            //.measure))
     (def ratio
       ratio))))

(def .public (re_scaled from to measure)
  (All (_ si so u) (-> (Scale si) (Scale so) (//.Measure si u) (//.Measure so u)))
  (let [(open "/[0]") (ratio./ (at from ratio)
                               (at to ratio))]
    (|> measure
        //.number
        (i.* (.int /#numerator))
        (i./ (.int /#denominator))
        //.measure)))

(def .public type
  (syntax (_ [it <code>.any])
    (macro.with_symbols [g!a]
      (in (list (` (///.by_example [(, g!a)]
                     (is (..Scale (, g!a))
                         (, it))
                     (, g!a))))))))

(with_template [<order_of_magnitude> <up> <up_type> <down> <down_type>]
  [(def .public <up>
     (scale [ratio.#numerator <order_of_magnitude>
             ratio.#denominator 1]))
   
   (def .public <up_type>
     (let [[module _] (symbol .._)
           [_ short] (symbol <up_type>)]
       {.#Named [module short]
                (..type <up>)}))
   
   (def .public <down>
     (scale [ratio.#numerator 1
             ratio.#denominator <order_of_magnitude>]))
   
   (def .public <down_type>
     (let [[module _] (symbol .._)
           [_ short] (symbol <down_type>)]
       {.#Named [module short]
                (..type <down>)}))]

  [        1,000 kilo Kilo milli Milli]
  [    1,000,000 mega Mega micro Micro]
  [1,000,000,000 giga Giga nano  Nano ]
  )