5import Data.Fixed (class KnownPrecision, Fixed, PProxy, fromNumber, toNumber, fromString, reifyPrecision, reflectPrecision, toString, P100, rescale, fromBigInt, floor, ceil, numerator)
6import Data.BigInt as BigInt
7import Data.Maybe (Maybe(..), fromJust, isJust)
9import Effect.Console (log)
10import Data.Number as Math
11import Partial.Unsafe (unsafePartial)
12import Test.QuickCheck (arbitrary, quickCheck', (<?>), (===))
13import Test.QuickCheck.Gen (Gen, chooseInt, uniform, suchThat)
15-- Just here to package up the safe use of `unsafePartial`.
16trying :: forall a b. Gen a -> (a -> Maybe b) -> Gen b
17trying gen f = map (unsafePartial fromJust) (map f gen `suchThat` isJust)
19genFixedP :: forall p. KnownPrecision p => PProxy p -> Gen (Fixed p)
20genFixedP _ = map (fromNumber <<< stretch) uniform `trying` identity
22 -- maps [0,1] to [-10,10]
23 stretch = (_ * 20.0) >>> (_ - 10.0)
27 . KnownPrecision precision
30 -> Maybe (Fixed precision)
31fromNumberWith _ = fromNumber
39withPrecisionOf _ x = x
43 . KnownPrecision precision
47truncateToPrecision p =
49 <<< (\x -> if x > zero then floor x else ceil x)
53 fromBigInt (BigInt.pow (BigInt.fromInt 10) (BigInt.fromInt p))
57 log "Commutative monoid under addition:"
60 log "Associativity: (a + b) + c = a + (b + c)"
62 precision <- chooseInt 0 10
63 unsafePartial fromJust $ reifyPrecision precision \p -> do
67 pure $ (a + b) + c == a + (b + c) <?> show { precision, a, b, c }
69 log "Identity: zero + a = a + zero = a"
72 precision <- chooseInt 0 10
73 unsafePartial fromJust $ reifyPrecision precision \p -> do
75 pure $ zero + a == a <?> show { precision, a }
77 precision <- chooseInt 0 10
78 unsafePartial fromJust $ reifyPrecision precision \p -> do
80 pure $ a + zero == a <?> show { precision, a }
82 log "Commutative: a + b = b + a"
84 precision <- chooseInt 0 10
85 unsafePartial fromJust $ reifyPrecision precision \p -> do
88 pure $ a + b == b + a <?> show { precision, a, b }
90 log "Multiplicative unit: one * a = a * one = a"
93 precision <- chooseInt 0 10
94 unsafePartial fromJust $ reifyPrecision precision \p -> do
96 pure $ one * a == a <?> show { precision, a }
98 precision <- chooseInt 0 10
99 unsafePartial fromJust $ reifyPrecision precision \p -> do
101 pure $ a * one == a <?> show { precision, a }
103 log "Multiplicative zero: zero * a = a * zero = zero"
105 precision <- chooseInt 0 10
106 unsafePartial fromJust $ reifyPrecision precision \p -> do
108 pure $ zero * a == zero <?> show { precision, a }
110 precision <- chooseInt 0 10
111 unsafePartial fromJust $ reifyPrecision precision \p -> do
113 pure $ a * zero == zero <?> show { precision, a }
116 log "Parsing/printing"
119 log "An empty string parses Nothing"
121 let x = fromString "" :: Maybe (Fixed P100)
124 log "Roundtrip: fromString <<< toString == Just"
126 precision <- chooseInt 0 100
127 unsafePartial fromJust $ reifyPrecision precision \p -> do
129 let b = fromString (toString a)
130 pure $ b == Just a <?> show { precision, a, b, numeratorA: numerator a, numeratorB: map numerator b }
133 log "Conversions to/from Number"
136 log "Roundtrip inaccuracy should be bounded by precision"
137 quickCheck' 1000 \x -> do
138 -- This is limited by the precision of Number
139 precision <- chooseInt 0 10
140 pure $ unsafePartial fromJust $ reifyPrecision precision \p -> do
141 -- Note: we use 0.5 here because these numbers should differ by no more
142 -- than half of the distance between two consecutive representable values
143 -- of the type `Fixed precision`.
144 let epsilon = 0.5 / BigInt.toNumber (reflectPrecision p)
145 case toNumber <$> fromNumberWith p x of
147 (Math.abs (x' - x) <= epsilon)
148 <?> show { precision, epsilon, x, x' }
151 <?> ("failed to roundtrip via Number: " <> show { precision, x })
157 log "rescaling up then down should be no-op"
160 hi <- chooseInt 10 20
161 unsafePartial fromJust $ join $
162 reifyPrecision lo \lo_ ->
163 reifyPrecision hi \hi_ -> do
165 let y = withPrecisionOf hi_ $ rescale x
167 pure $ x == xx <?> show { x, xx, y }
169 log "rescaling down then up should be the same as truncating"
172 lo <- chooseInt 10 20
173 unsafePartial fromJust $ join $
174 reifyPrecision lo \lo_ ->
175 reifyPrecision hi \hi_ -> do
177 let y = withPrecisionOf lo_ $ rescale x
178 let xx = truncateToPrecision lo x
179 pure $ xx == rescale y <?> show { x, xx, y }
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list