Skip to content

Commit 3e4a72b

Browse files
committed
Fixed point numbers wip
1 parent 0601fde commit 3e4a72b

File tree

2 files changed

+71
-1
lines changed

2 files changed

+71
-1
lines changed

pub/functora/src/prelude/Functora/Prelude.hs

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,12 @@ module Functora.Prelude
119119
dropAround,
120120
dropWhileEnd,
121121
AscOrDesc (..),
122+
123+
-- * FixedPoint
124+
-- $fixedPoint
125+
Fix (..),
126+
FixNonNeg,
127+
mkFixNonNeg,
122128
E30,
123129

124130
-- * DerivingVia
@@ -1152,11 +1158,70 @@ data AscOrDesc
11521158
Bounded
11531159
)
11541160

1161+
-- $fixedPoint
1162+
-- Fixed point numbers.
1163+
11551164
data E30
11561165

11571166
instance HasResolution E30 where
11581167
resolution = const 1_0000000000_0000000000_0000000000
11591168

1169+
newtype Fix = Fix
1170+
{ unFix :: Fixed E30
1171+
}
1172+
deriving stock
1173+
( Eq,
1174+
Ord,
1175+
Show,
1176+
Data,
1177+
Generic
1178+
)
1179+
deriving newtype
1180+
( Num,
1181+
Real,
1182+
Fractional,
1183+
RealFrac
1184+
)
1185+
1186+
newtype FixNonNeg = FixNonNeg
1187+
{ unFixNonNeg :: Fixed E30
1188+
}
1189+
deriving stock
1190+
( Eq,
1191+
Ord,
1192+
Show,
1193+
Data,
1194+
Generic
1195+
)
1196+
1197+
mkFixNonNeg :: Fixed E30 -> FixNonNeg
1198+
mkFixNonNeg x =
1199+
if x >= 0
1200+
then FixNonNeg x
1201+
else error $ "Underflow " <> inspect x
1202+
1203+
instance Num FixNonNeg where
1204+
lhs + rhs = mkFixNonNeg $ unFixNonNeg lhs + unFixNonNeg rhs
1205+
lhs - rhs = mkFixNonNeg $ unFixNonNeg lhs - unFixNonNeg rhs
1206+
lhs * rhs = mkFixNonNeg $ unFixNonNeg lhs * unFixNonNeg rhs
1207+
negate = mkFixNonNeg . negate . unFixNonNeg
1208+
abs = mkFixNonNeg . abs . unFixNonNeg
1209+
signum = mkFixNonNeg . signum . unFixNonNeg
1210+
fromInteger = mkFixNonNeg . Prelude.fromInteger @(Fixed E30)
1211+
1212+
instance Real FixNonNeg where
1213+
toRational = toRational . unFixNonNeg
1214+
1215+
instance Fractional FixNonNeg where
1216+
fromRational = mkFixNonNeg . fromRational
1217+
lhs / rhs = mkFixNonNeg $ unFixNonNeg lhs / unFixNonNeg rhs
1218+
1219+
instance RealFrac FixNonNeg where
1220+
properFraction x =
1221+
(lhs, mkFixNonNeg rhs)
1222+
where
1223+
(lhs, rhs) = properFraction $ unFixNonNeg x
1224+
11601225
-- $derivingVia
11611226
-- Newtypes to simplify deriving via.
11621227
-- We have to expose default constructors/accessors

pub/functora/src/test/Functora/RoundSpec.hs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
module Functora.RoundSpec (spec) where
22

33
import Data.Fixed (E12, Fixed)
4-
import Functora.Prelude (throw, throwString, try)
4+
--
5+
-- NOTE : Round functions will fail for FixNonNeg because of impl details.
6+
--
7+
import Functora.Prelude (Fix, throw, throwString, try)
58
import Functora.Round (dpRound, sdRound)
69
import Numeric.Natural (Natural)
710
import System.Exit (ExitCode (..))
@@ -29,10 +32,12 @@ spec = do
2932
mkRoundSpec @(Fixed E12) "dpRound/Fixed" dpRound dpRoundTestData
3033
mkRoundSpec @Rational "dpRound/Rational" dpRound dpRoundTestData
3134
mkRoundSpec @Double "dpRound/Double" dpRound dpRoundTestData
35+
mkRoundSpec @Fix "dpRound/Fix" dpRound dpRoundTestData
3236

3337
mkRoundSpec @(Fixed E12) "sdRound/Fixed" sdRound sdRoundTestData
3438
mkRoundSpec @Rational "sdRound/Rational" sdRound sdRoundTestData
3539
mkRoundSpec @Double "sdRound/Double" sdRound sdRoundTestData
40+
mkRoundSpec @Fix "sdRound/Fix" sdRound sdRoundTestData
3641

3742
--
3843
-- Tasty

0 commit comments

Comments
 (0)