0 | module Data.Fixed
  1 |
  2 | import Data.String
  3 |
  4 | %hide Data.List.replicate
  5 |
  6 | --------------------------------------------------------------------------------
  7 | --          Fixed
  8 | --------------------------------------------------------------------------------
  9 |
 10 | ||| The type of fixed-point fractional numbers.
 11 | |||
 12 | public export
 13 | data Fixed : (res : Integer) -> Type where
 14 |   MkFixed :  Integer
 15 |           -> Fixed res
 16 |
 17 | --------------------------------------------------------------------------------
 18 | --          Show Utility
 19 | --------------------------------------------------------------------------------
 20 |
 21 | ||| Render a fixed-point value to a string, with optional trailing zero chopping.
 22 | |||
 23 | ||| @chop  whether to drop trailing zeros from the fractional part
 24 | ||| @fa    the fixed-point value, whose type index encodes resolution
 25 | |||
 26 | export
 27 | showFixed :  {res : Integer}
 28 |           -> (chop : Bool)
 29 |           -> (fa : Fixed res)
 30 |           -> String
 31 | showFixed chop fa@(MkFixed a) =
 32 |   case a < 0 of
 33 |     True =>
 34 |       let fixed = assert_total $
 35 |                   showFixed {res}
 36 |                             chop
 37 |                             (MkFixed (negate a))
 38 |         in "-" ++ fixed
 39 |     False =>
 40 |       let (i, d)  = divMod a res
 41 |           digits  = cast {to=Int} (length (show res)) - 1
 42 |           maxnum  = pow 10 (cast {to=Double} digits)
 43 |           fracnum = divCeil (d * cast {to=Integer} maxnum) res
 44 |           dot     = withDot (showIntegerZeros chop (cast digits) fracnum)
 45 |        in show i ++ dot
 46 |   where
 47 |     sigNum :  Integer
 48 |            -> Integer
 49 |     sigNum n =
 50 |       case n < 0 of
 51 |         True  =>
 52 |           -1
 53 |         False =>
 54 |           case n == 0 of
 55 |             True  =>
 56 |               0
 57 |             False =>
 58 |               1
 59 |     divMod :  Integer
 60 |            -> Integer
 61 |            -> (Integer, Integer)
 62 |     divMod n d =
 63 |       let q = div n d
 64 |           r = mod n d
 65 |         in case sigNum r == negate (sigNum d) of
 66 |              True  =>
 67 |                (q - 1, r + d)
 68 |              False =>
 69 |                (q, r)
 70 |     chopZeros :  Integer
 71 |               -> String
 72 |     chopZeros 0 =
 73 |       ""
 74 |     chopZeros x =
 75 |       case mod x 10 == 0 of
 76 |         True  =>
 77 |           chopZeros (assert_smaller x (div x 10))
 78 |         False =>
 79 |           show x
 80 |     showIntegerZeros :  Bool
 81 |                      -> Nat
 82 |                      -> Integer
 83 |                      -> String
 84 |     showIntegerZeros True _      0 =
 85 |       ""
 86 |     showIntegerZeros chop digits n =
 87 |       let s       = show n
 88 |           s'      = case chop of
 89 |                       True  =>
 90 |                         chopZeros n
 91 |                       False =>
 92 |                         s
 93 |           padding = replicate (digits `minus` length s) '0'
 94 |         in padding ++ s'
 95 |     withDot :  String
 96 |             -> String
 97 |     withDot "" =
 98 |       ""
 99 |     withDot s  =
100 |       "." ++ s
101 |     divCeil :  Integer
102 |             -> Integer
103 |             -> Integer
104 |     divCeil x y =
105 |       (x + y - 1) `div` y
106 |
107 | --------------------------------------------------------------------------------
108 | --          Interfaces
109 | --------------------------------------------------------------------------------
110 |
111 | public export
112 | {n : Integer} -> Num (Fixed n) where
113 |   (MkFixed a) + (MkFixed b) = MkFixed (a + b)
114 |   (MkFixed a) * (MkFixed b) = MkFixed (div (a * b) n)
115 |   fromInteger i             = MkFixed (i * n)
116 |
117 | public export
118 | {n : Integer} -> Neg (Fixed n) where
119 |   negate (MkFixed a)          = MkFixed (negate a)
120 |   (-) (MkFixed a) (MkFixed b) = MkFixed (a - b)
121 |
122 | public export
123 | {n : Integer} -> Fractional (Fixed n) where
124 |   (MkFixed a) / (MkFixed b) = MkFixed (div (a * n) b)
125 |   recip (MkFixed a)         = MkFixed (div (n * n) a)
126 |
127 | public export
128 | {n : Integer} -> Eq (Fixed n) where
129 |   (MkFixed a) == (MkFixed b) = a == b
130 |
131 | public export
132 | {n : Integer} -> Ord (Fixed n) where
133 |   compare (MkFixed a) (MkFixed b) = compare a b
134 |
135 | public export
136 | {n : Integer} -> Show (Fixed n) where
137 |   showPrec p fixed@(MkFixed a) =
138 |     showParens (p >= App && a < 0) $
139 |       showFixed False fixed
140 |
141 | --------------------------------------------------------------------------------
142 | --          E0/Uni
143 | --------------------------------------------------------------------------------
144 |
145 | ||| +------------+---------------------+------+------------+
146 | ||| | Resolution | Scaling Factor      | Type | show 12345 |
147 | ||| +============+=====================+======+============+
148 | ||| | E0         | 1\1                 | Uni  | 12345.0    |
149 | ||| +------------+---------------------+------+------------+
150 | |||
151 | public export
152 | Uni : Type
153 | Uni = Fixed 1
154 |
155 | --------------------------------------------------------------------------------
156 | --          E1/Deci
157 | --------------------------------------------------------------------------------
158 |
159 | ||| +------------+---------------------+------+------------+
160 | ||| | Resolution | Scaling Factor      | Type | show 12345 |
161 | ||| +============+=====================+======+============+
162 | ||| | E1         | 1\10                | Deci | 1234.5     |
163 | ||| +------------+---------------------+------+------------+
164 | |||
165 | public export
166 | Deci : Type
167 | Deci = Fixed 10
168 |
169 | --------------------------------------------------------------------------------
170 | --          E2/Centi
171 | --------------------------------------------------------------------------------
172 |
173 | ||| +------------+---------------------+-------+------------+
174 | ||| | Resolution | Scaling Factor      | Type  | show 12345 |
175 | ||| +============+=====================+=======+============+
176 | ||| | E2         | 1\100               | Centi | 123.45     |
177 | ||| +------------+---------------------+-------+------------+
178 | |||
179 | public export
180 | Centi : Type
181 | Centi = Fixed 100
182 |
183 | --------------------------------------------------------------------------------
184 | --          E3/Milli
185 | --------------------------------------------------------------------------------
186 |
187 | ||| +------------+--------------------+-------+------------+
188 | ||| | Resolution | Scaling Factor     | Type  | show 12345 |
189 | ||| +============+====================+=======+============+
190 | ||| | E3         | 1\1000             | Milli | 12.345     |
191 | ||| +------------+--------------------+-------+------------+
192 | |||
193 | public export
194 | Milli : Type
195 | Milli = Fixed 1000
196 |
197 | --------------------------------------------------------------------------------
198 | --          E4/TenthMilli
199 | --------------------------------------------------------------------------------
200 |
201 | ||| +------------+--------------------+------------+------------+
202 | ||| | Resolution | Scaling Factor     | Type       | show 12345 |
203 | ||| +============+====================+=======+=================+
204 | ||| | E4         | 1\10000            | TenthMilli | 1.2345     |
205 | ||| +------------+--------------------+------------+------------+
206 | |||
207 | public export
208 | TenthMilli : Type
209 | TenthMilli = Fixed 10000
210 |
211 | --------------------------------------------------------------------------------
212 | --          E5/HundredthMilli
213 | --------------------------------------------------------------------------------
214 |
215 | ||| +------------+--------------------+------------------------+------------+
216 | ||| | Resolution | Scaling Factor     | Type                   | show 12345 |
217 | ||| +============+====================+========================+============+
218 | ||| | E5         | 1\100000           | HundredthMilli         | 0.12345    |
219 | ||| +------------+--------------------+------------------------+------------+
220 | |||
221 | public export
222 | HundredthMilli : Type
223 | HundredthMilli = Fixed 100000
224 |
225 | --------------------------------------------------------------------------------
226 | --          E6/Micro
227 | --------------------------------------------------------------------------------
228 |
229 | ||| +------------+-------------------+-------+------------+
230 | ||| | Resolution | Scaling Factor    | Type  | show 12345 |
231 | ||| +============+===================+=======+============+
232 | ||| | E6         | 1\1000000         | Micro | 0.012345   |
233 | ||| +------------+-------------------+-------+------------+
234 | |||
235 | public export
236 | Micro : Type
237 | Micro = Fixed 1000000
238 |
239 | --------------------------------------------------------------------------------
240 | --          E7/DeciMicro
241 | --------------------------------------------------------------------------------
242 |
243 | ||| +------------+-------------------+-----------+------------+
244 | ||| | Resolution | Scaling Factor    | Type      | show 12345 |
245 | ||| +============+===================+===========+============+
246 | ||| | E7         | 1\10000000        | DeciMicro | 0.0012345  |
247 | ||| +------------+-------------------+-----------+------------+
248 | |||
249 | public export
250 | DeciMicro : Type
251 | DeciMicro = Fixed 10000000
252 |
253 | --------------------------------------------------------------------------------
254 | --          E8/CentiMicro
255 | --------------------------------------------------------------------------------
256 |
257 | ||| +------------+--------------------+------------+------------+
258 | ||| | Resolution | Scaling Factor     | Type       | show 12345 |
259 | ||| +============+====================+============+============+
260 | ||| | E8         | 1\100000000        | CentiMicro | 0.00012345 |
261 | ||| +------------+--------------------+------------+------------+
262 | |||
263 | public export
264 | CentiMicro : Type
265 | CentiMicro = Fixed 100000000
266 |
267 | --------------------------------------------------------------------------------
268 | --          E9/Nano
269 | --------------------------------------------------------------------------------
270 |
271 | ||| +------------+------------------+------+-------------+
272 | ||| | Resolution | Scaling Factor   | Type | show 12345  |
273 | ||| +============+==================+======+=============+
274 | ||| | E9         | 1\1000000000     | Nano | 0.000012345 |
275 | ||| +------------+------------------+------+-------------+
276 | |||
277 | public export
278 | Nano : Type
279 | Nano = Fixed 1000000000
280 |
281 | --------------------------------------------------------------------------------
282 | --          E10/DeciNano
283 | --------------------------------------------------------------------------------
284 |
285 | ||| +------------+-----------------+----------+--------------+
286 | ||| | Resolution | Scaling Factor  | Type     | show 12345   |
287 | ||| +============+=================+==========+==============+
288 | ||| | E10        | 1\10000000000   | DeciNano | 0.0000012345 |
289 | ||| +------------+-----------------+----------+--------------+
290 | |||
291 | public export
292 | DeciNano : Type
293 | DeciNano = Fixed 10000000000
294 |
295 | --------------------------------------------------------------------------------
296 | --          E11/CentiNano
297 | --------------------------------------------------------------------------------
298 |
299 | ||| +------------+-----------------+-----------+---------------+
300 | ||| | Resolution | Scaling Factor  | Type      | show 12345    |
301 | ||| +============+=================+===========+===============+
302 | ||| | E11        | 1\100000000000  | CentiNano | 0.00000012345 |
303 | ||| +------------+-----------------+-----------+---------------+
304 | |||
305 | public export
306 | CentiNano : Type
307 | CentiNano = Fixed 100000000000
308 |
309 | --------------------------------------------------------------------------------
310 | --          E12/Pico
311 | --------------------------------------------------------------------------------
312 |
313 | ||| +------------+-----------------+------+----------------+
314 | ||| | Resolution | Scaling Factor  | Type | show 12345     |
315 | ||| +============+=================+======+================+
316 | ||| | E12        | 1\1000000000000 | Pico | 0.000000012345 |
317 | ||| +------------+-----------------+------+----------------+
318 | |||
319 | public export
320 | Pico : Type
321 | Pico = Fixed 1000000000000
322 |
323 | --------------------------------------------------------------------------------
324 | --          withResolution
325 | --------------------------------------------------------------------------------
326 |
327 | ||| Run a computation with the resolution available as an `Integer`.
328 | |||
329 | export
330 | withResolution :  {res : Integer}
331 |                -> (f : Integer -> b)
332 |                -> b
333 | withResolution f =
334 |   f res
335 |