{-# LANGUAGE Trustworthy #-}{-# LANGUAGE ScopedTypeVariables #-}{-# LANGUAGE PolyKinds #-}{-# LANGUAGE FlexibleInstances #-}------------------------------------------------------------------------------- |-- Module : Data.Fixed-- Copyright : (c) Ashley Yakeley 2005, 2006, 2009-- License : BSD-style (see the file libraries/base/LICENSE)---- Maintainer : Ashley Yakeley <ashley@semantic.org>-- Stability : experimental-- Portability : portable---- This module defines a \"Fixed\" type for fixed-precision arithmetic.-- The parameter to 'Fixed' is any type that's an instance of 'HasResolution'.-- 'HasResolution' has a single method that gives the resolution of the 'Fixed'-- type.---- This module also contains generalisations of 'div', 'mod', and 'divMod' to-- work with any 'Real' instance.-------------------------------------------------------------------------------moduleData.Fixed(div' ,mod' ,divMod' ,Fixed (..),HasResolution (..),showFixed ,E0 ,Uni ,E1 ,Deci ,E2 ,Centi ,E3 ,Milli ,E6 ,Micro ,E9 ,Nano ,E12 ,Pico )whereimportData.Data importGHC.TypeLits (KnownNat ,natVal )importGHC.Read importText.ParserCombinators.ReadPrec importText.Read.Lex default()-- avoid any defaulting shenanigans-- | Generalisation of 'div' to any instance of 'Real'div' ::(Real a ,Integral b )=>a ->a ->b div' :: a -> a -> b div' a n a d =Rational -> b forall a b. (RealFrac a, Integral b) => a -> b floor ((a -> Rational forall a. Real a => a -> Rational toRational a n )Rational -> Rational -> Rational forall a. Fractional a => a -> a -> a / (a -> Rational forall a. Real a => a -> Rational toRational a d ))-- | Generalisation of 'divMod' to any instance of 'Real'divMod' ::(Real a ,Integral b )=>a ->a ->(b ,a )divMod' :: a -> a -> (b, a) divMod' a n a d =(b f ,a n a -> a -> a forall a. Num a => a -> a -> a - (b -> a forall a b. (Integral a, Num b) => a -> b fromIntegral b f )a -> a -> a forall a. Num a => a -> a -> a * a d )wheref :: b f =a -> a -> b forall a b. (Real a, Integral b) => a -> a -> b div' a n a d -- | Generalisation of 'mod' to any instance of 'Real'mod' ::(Real a )=>a ->a ->a mod' :: a -> a -> a mod' a n a d =a n a -> a -> a forall a. Num a => a -> a -> a - (Integer -> a forall a. Num a => Integer -> a fromInteger Integer f )a -> a -> a forall a. Num a => a -> a -> a * a d wheref :: Integer f =a -> a -> Integer forall a b. (Real a, Integral b) => a -> a -> b div' a n a d -- | The type parameter should be an instance of 'HasResolution'.newtypeFixed (a ::k )=MkFixed Integerderiving(Eq-- ^ @since 2.01,Ord-- ^ @since 2.01)-- We do this because the automatically derived Data instance requires (Data a) context.-- Our manual instance has the more general (Typeable a) context.tyFixed ::DataType tyFixed :: DataType tyFixed =String -> [Constr] -> DataType mkDataType String "Data.Fixed.Fixed"[Constr conMkFixed ]conMkFixed ::Constr conMkFixed :: Constr conMkFixed =DataType -> String -> [String] -> Fixity -> Constr mkConstr DataType tyFixed String "MkFixed"[]Fixity Prefix -- | @since 4.1.0.0instance(Typeable k ,Typeable a )=>Data (Fixed (a ::k ))wheregfoldl :: (forall d b. Data d => c (d -> b) -> d -> c b) -> (forall g. g -> c g) -> Fixed a -> c (Fixed a) gfoldl forall d b. Data d => c (d -> b) -> d -> c b k forall g. g -> c g z (MkFixed Integer a )=c (Integer -> Fixed a) -> Integer -> c (Fixed a) forall d b. Data d => c (d -> b) -> d -> c b k ((Integer -> Fixed a) -> c (Integer -> Fixed a) forall g. g -> c g z Integer -> Fixed a forall k (a :: k). Integer -> Fixed a MkFixed )Integer a gunfold :: (forall b r. Data b => c (b -> r) -> c r) -> (forall r. r -> c r) -> Constr -> c (Fixed a) gunfold forall b r. Data b => c (b -> r) -> c r k forall r. r -> c r z Constr _=c (Integer -> Fixed a) -> c (Fixed a) forall b r. Data b => c (b -> r) -> c r k ((Integer -> Fixed a) -> c (Integer -> Fixed a) forall r. r -> c r z Integer -> Fixed a forall k (a :: k). Integer -> Fixed a MkFixed )dataTypeOf :: Fixed a -> DataType dataTypeOf Fixed a _=DataType tyFixed toConstr :: Fixed a -> Constr toConstr Fixed a _=Constr conMkFixed classHasResolution (a ::k )whereresolution ::p a ->Integer-- | For example, @Fixed 1000@ will give you a 'Fixed' with a resolution of 1000.instanceKnownNat n =>HasResolution n whereresolution :: p n -> Integer resolution p n _=Proxy n -> Integer forall (n :: Nat) (proxy :: Nat -> *). KnownNat n => proxy n -> Integer natVal (Proxy n forall k (t :: k). Proxy t Proxy ::Proxy n )withType ::(Proxy a ->f a )->f a withType :: (Proxy a -> f a) -> f a withType Proxy a -> f a foo =Proxy a -> f a foo Proxy a forall k (t :: k). Proxy t Proxy withResolution ::(HasResolution a )=>(Integer->f a )->f a withResolution :: (Integer -> f a) -> f a withResolution Integer -> f a foo =(Proxy a -> f a) -> f a forall k (a :: k) (f :: k -> *). (Proxy a -> f a) -> f a withType (Integer -> f a foo (Integer -> f a) -> (Proxy a -> Integer) -> Proxy a -> f a forall b c a. (b -> c) -> (a -> b) -> a -> c . Proxy a -> Integer forall k (a :: k) (p :: k -> *). HasResolution a => p a -> Integer resolution )-- | @since 2.01instanceEnum (Fixed a )wheresucc :: Fixed a -> Fixed a succ (MkFixed Integer a )=Integer -> Fixed a forall k (a :: k). Integer -> Fixed a MkFixed (Integer -> Integer forall a. Enum a => a -> a succ Integer a )pred :: Fixed a -> Fixed a pred (MkFixed Integer a )=Integer -> Fixed a forall k (a :: k). Integer -> Fixed a MkFixed (Integer -> Integer forall a. Enum a => a -> a pred Integer a )toEnum :: Int -> Fixed a toEnum =Integer -> Fixed a forall k (a :: k). Integer -> Fixed a MkFixed (Integer -> Fixed a) -> (Int -> Integer) -> Int -> Fixed a forall b c a. (b -> c) -> (a -> b) -> a -> c . Int -> Integer forall a. Enum a => Int -> a toEnum fromEnum :: Fixed a -> Int fromEnum (MkFixed Integer a )=Integer -> Int forall a. Enum a => a -> Int fromEnum Integer a enumFrom :: Fixed a -> [Fixed a] enumFrom (MkFixed Integer a )=(Integer -> Fixed a) -> [Integer] -> [Fixed a] forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b fmap Integer -> Fixed a forall k (a :: k). Integer -> Fixed a MkFixed (Integer -> [Integer] forall a. Enum a => a -> [a] enumFrom Integer a )enumFromThen :: Fixed a -> Fixed a -> [Fixed a] enumFromThen (MkFixed Integer a )(MkFixed Integer b )=(Integer -> Fixed a) -> [Integer] -> [Fixed a] forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b fmap Integer -> Fixed a forall k (a :: k). Integer -> Fixed a MkFixed (Integer -> Integer -> [Integer] forall a. Enum a => a -> a -> [a] enumFromThen Integer a Integer b )enumFromTo :: Fixed a -> Fixed a -> [Fixed a] enumFromTo (MkFixed Integer a )(MkFixed Integer b )=(Integer -> Fixed a) -> [Integer] -> [Fixed a] forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b fmap Integer -> Fixed a forall k (a :: k). Integer -> Fixed a MkFixed (Integer -> Integer -> [Integer] forall a. Enum a => a -> a -> [a] enumFromTo Integer a Integer b )enumFromThenTo :: Fixed a -> Fixed a -> Fixed a -> [Fixed a] enumFromThenTo (MkFixed Integer a )(MkFixed Integer b )(MkFixed Integer c )=(Integer -> Fixed a) -> [Integer] -> [Fixed a] forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b fmap Integer -> Fixed a forall k (a :: k). Integer -> Fixed a MkFixed (Integer -> Integer -> Integer -> [Integer] forall a. Enum a => a -> a -> a -> [a] enumFromThenTo Integer a Integer b Integer c )-- | @since 2.01instance(HasResolution a )=>Num (Fixed a )where(MkFixed Integer a )+ :: Fixed a -> Fixed a -> Fixed a + (MkFixed Integer b )=Integer -> Fixed a forall k (a :: k). Integer -> Fixed a MkFixed (Integer a Integer -> Integer -> Integer forall a. Num a => a -> a -> a + Integer b )(MkFixed Integer a )- :: Fixed a -> Fixed a -> Fixed a - (MkFixed Integer b )=Integer -> Fixed a forall k (a :: k). Integer -> Fixed a MkFixed (Integer a Integer -> Integer -> Integer forall a. Num a => a -> a -> a - Integer b )fa :: Fixed a fa @(MkFixed Integer a )* :: Fixed a -> Fixed a -> Fixed a * (MkFixed Integer b )=Integer -> Fixed a forall k (a :: k). Integer -> Fixed a MkFixed (Integer -> Integer -> Integer forall a. Integral a => a -> a -> a div (Integer a Integer -> Integer -> Integer forall a. Num a => a -> a -> a * Integer b )(Fixed a -> Integer forall k (a :: k) (p :: k -> *). HasResolution a => p a -> Integer resolution Fixed a fa ))negate :: Fixed a -> Fixed a negate (MkFixed Integer a )=Integer -> Fixed a forall k (a :: k). Integer -> Fixed a MkFixed (Integer -> Integer forall a. Num a => a -> a negate Integer a )abs :: Fixed a -> Fixed a abs (MkFixed Integer a )=Integer -> Fixed a forall k (a :: k). Integer -> Fixed a MkFixed (Integer -> Integer forall a. Num a => a -> a abs Integer a )signum :: Fixed a -> Fixed a signum (MkFixed Integer a )=Integer -> Fixed a forall a. Num a => Integer -> a fromInteger (Integer -> Integer forall a. Num a => a -> a signum Integer a )fromInteger :: Integer -> Fixed a fromInteger Integer i =(Integer -> Fixed a) -> Fixed a forall k (a :: k) (f :: k -> *). HasResolution a => (Integer -> f a) -> f a withResolution (\Integer res ->Integer -> Fixed a forall k (a :: k). Integer -> Fixed a MkFixed (Integer i Integer -> Integer -> Integer forall a. Num a => a -> a -> a * Integer res ))-- | @since 2.01instance(HasResolution a )=>Real (Fixed a )wheretoRational :: Fixed a -> Rational toRational fa :: Fixed a fa @(MkFixed Integer a )=(Integer -> Rational forall a. Real a => a -> Rational toRational Integer a )Rational -> Rational -> Rational forall a. Fractional a => a -> a -> a / (Integer -> Rational forall a. Real a => a -> Rational toRational (Fixed a -> Integer forall k (a :: k) (p :: k -> *). HasResolution a => p a -> Integer resolution Fixed a fa ))-- | @since 2.01instance(HasResolution a )=>Fractional (Fixed a )wherefa :: Fixed a fa @(MkFixed Integer a )/ :: Fixed a -> Fixed a -> Fixed a / (MkFixed Integer b )=Integer -> Fixed a forall k (a :: k). Integer -> Fixed a MkFixed (Integer -> Integer -> Integer forall a. Integral a => a -> a -> a div (Integer a Integer -> Integer -> Integer forall a. Num a => a -> a -> a * (Fixed a -> Integer forall k (a :: k) (p :: k -> *). HasResolution a => p a -> Integer resolution Fixed a fa ))Integer b )recip :: Fixed a -> Fixed a recip fa :: Fixed a fa @(MkFixed Integer a )=Integer -> Fixed a forall k (a :: k). Integer -> Fixed a MkFixed (Integer -> Integer -> Integer forall a. Integral a => a -> a -> a div (Integer res Integer -> Integer -> Integer forall a. Num a => a -> a -> a * Integer res )Integer a )whereres :: Integer res =Fixed a -> Integer forall k (a :: k) (p :: k -> *). HasResolution a => p a -> Integer resolution Fixed a fa fromRational :: Rational -> Fixed a fromRational Rational r =(Integer -> Fixed a) -> Fixed a forall k (a :: k) (f :: k -> *). HasResolution a => (Integer -> f a) -> f a withResolution (\Integer res ->Integer -> Fixed a forall k (a :: k). Integer -> Fixed a MkFixed (Rational -> Integer forall a b. (RealFrac a, Integral b) => a -> b floor (Rational r Rational -> Rational -> Rational forall a. Num a => a -> a -> a * (Integer -> Rational forall a. Real a => a -> Rational toRational Integer res ))))-- | @since 2.01instance(HasResolution a )=>RealFrac (Fixed a )whereproperFraction :: Fixed a -> (b, Fixed a) properFraction Fixed a a =(b i ,Fixed a a Fixed a -> Fixed a -> Fixed a forall a. Num a => a -> a -> a - (b -> Fixed a forall a b. (Integral a, Num b) => a -> b fromIntegral b i ))wherei :: b i =Fixed a -> b forall a b. (RealFrac a, Integral b) => a -> b truncate Fixed a a truncate :: Fixed a -> b truncate Fixed a f =Rational -> b forall a b. (RealFrac a, Integral b) => a -> b truncate (Fixed a -> Rational forall a. Real a => a -> Rational toRational Fixed a f )round :: Fixed a -> b round Fixed a f =Rational -> b forall a b. (RealFrac a, Integral b) => a -> b round (Fixed a -> Rational forall a. Real a => a -> Rational toRational Fixed a f )ceiling :: Fixed a -> b ceiling Fixed a f =Rational -> b forall a b. (RealFrac a, Integral b) => a -> b ceiling (Fixed a -> Rational forall a. Real a => a -> Rational toRational Fixed a f )floor :: Fixed a -> b floor Fixed a f =Rational -> b forall a b. (RealFrac a, Integral b) => a -> b floor (Fixed a -> Rational forall a. Real a => a -> Rational toRational Fixed a f )chopZeros ::Integer->String chopZeros :: Integer -> String chopZeros Integer 0=String ""chopZeros Integer a |Integer -> Integer -> Integer forall a. Integral a => a -> a -> a mod Integer a Integer 10Integer -> Integer -> Bool forall a. Eq a => a -> a -> Bool ==Integer 0=Integer -> String chopZeros (Integer -> Integer -> Integer forall a. Integral a => a -> a -> a div Integer a Integer 10)chopZeros Integer a =Integer -> String forall a. Show a => a -> String show Integer a -- only works for positive ashowIntegerZeros ::Bool->Int->Integer->String showIntegerZeros :: Bool -> Int -> Integer -> String showIntegerZeros Bool TrueInt _Integer 0=String ""showIntegerZeros Bool chopTrailingZeros Int digits Integer a =Int -> Char -> String forall a. Int -> a -> [a] replicate (Int digits Int -> Int -> Int forall a. Num a => a -> a -> a - String -> Int forall (t :: * -> *) a. Foldable t => t a -> Int length String s )Char '0'String -> String -> String forall a. [a] -> [a] -> [a] ++ String s' wheres :: String s =Integer -> String forall a. Show a => a -> String show Integer a s' :: String s' =ifBool chopTrailingZeros thenInteger -> String chopZeros Integer a elseString s withDot ::String ->String withDot :: String -> String withDot String ""=String ""withDot String s =Char '.'Char -> String -> String forall a. a -> [a] -> [a] :String s -- | First arg is whether to chop off trailing zerosshowFixed ::(HasResolution a )=>Bool->Fixed a ->String showFixed :: Bool -> Fixed a -> String showFixed Bool chopTrailingZeros fa :: Fixed a fa @(MkFixed Integer a )|Integer a Integer -> Integer -> Bool forall a. Ord a => a -> a -> Bool <Integer 0=String "-"String -> String -> String forall a. [a] -> [a] -> [a] ++ (Bool -> Fixed a -> String forall k (a :: k). HasResolution a => Bool -> Fixed a -> String showFixed Bool chopTrailingZeros (Fixed a -> Fixed a -> Fixed a forall a. a -> a -> a asTypeOf (Integer -> Fixed a forall k (a :: k). Integer -> Fixed a MkFixed (Integer -> Integer forall a. Num a => a -> a negate Integer a ))Fixed a fa ))showFixed Bool chopTrailingZeros fa :: Fixed a fa @(MkFixed Integer a )=(Integer -> String forall a. Show a => a -> String show Integer i )String -> String -> String forall a. [a] -> [a] -> [a] ++ (String -> String withDot (Bool -> Int -> Integer -> String showIntegerZeros Bool chopTrailingZeros Int digits Integer fracNum ))whereres :: Integer res =Fixed a -> Integer forall k (a :: k) (p :: k -> *). HasResolution a => p a -> Integer resolution Fixed a fa (Integer i ,Integer d )=Integer -> Integer -> (Integer, Integer) forall a. Integral a => a -> a -> (a, a) divMod Integer a Integer res -- enough digits to be unambiguousdigits :: Int digits =Double -> Int forall a b. (RealFrac a, Integral b) => a -> b ceiling (Double -> Double -> Double forall a. Floating a => a -> a -> a logBase Double 10(Integer -> Double forall a. Num a => Integer -> a fromInteger Integer res )::Double)maxnum :: Integer maxnum =Integer 10Integer -> Int -> Integer forall a b. (Num a, Integral b) => a -> b -> a ^ Int digits -- read floors, so show must ceil for `read . show = id` to hold. See #9240fracNum :: Integer fracNum =Integer -> Integer -> Integer forall a. Integral a => a -> a -> a divCeil (Integer d Integer -> Integer -> Integer forall a. Num a => a -> a -> a * Integer maxnum )Integer res divCeil :: a -> a -> a divCeil a x a y =(a x a -> a -> a forall a. Num a => a -> a -> a + a y a -> a -> a forall a. Num a => a -> a -> a - a 1)a -> a -> a forall a. Integral a => a -> a -> a `div` a y -- | @since 2.01instance(HasResolution a )=>Show (Fixed a )whereshowsPrec :: Int -> Fixed a -> String -> String showsPrec Int p Fixed a n =Bool -> (String -> String) -> String -> String showParen (Int p Int -> Int -> Bool forall a. Ord a => a -> a -> Bool >Int 6Bool -> Bool -> Bool &&Fixed a n Fixed a -> Fixed a -> Bool forall a. Ord a => a -> a -> Bool <Fixed a 0)((String -> String) -> String -> String) -> (String -> String) -> String -> String forall a b. (a -> b) -> a -> b $ String -> String -> String showString (String -> String -> String) -> String -> String -> String forall a b. (a -> b) -> a -> b $ Bool -> Fixed a -> String forall k (a :: k). HasResolution a => Bool -> Fixed a -> String showFixed Bool FalseFixed a n -- | @since 4.3.0.0instance(HasResolution a )=>Read (Fixed a )wherereadPrec :: ReadPrec (Fixed a) readPrec =(Lexeme -> ReadPrec (Fixed a)) -> ReadPrec (Fixed a) forall a. Num a => (Lexeme -> ReadPrec a) -> ReadPrec a readNumber Lexeme -> ReadPrec (Fixed a) forall k (a :: k). HasResolution a => Lexeme -> ReadPrec (Fixed a) convertFixed readListPrec :: ReadPrec [Fixed a] readListPrec =ReadPrec [Fixed a] forall a. Read a => ReadPrec [a] readListPrecDefault readList :: ReadS [Fixed a] readList =ReadS [Fixed a] forall a. Read a => ReadS [a] readListDefault convertFixed ::foralla .HasResolution a =>Lexeme ->ReadPrec (Fixed a )convertFixed :: Lexeme -> ReadPrec (Fixed a) convertFixed (Number Number n )|Just (Integer i ,Integer f )<-Integer -> Number -> Maybe (Integer, Integer) numberToFixed Integer e Number n =Fixed a -> ReadPrec (Fixed a) forall (m :: * -> *) a. Monad m => a -> m a return (Integer -> Fixed a forall a. Num a => Integer -> a fromInteger Integer i Fixed a -> Fixed a -> Fixed a forall a. Num a => a -> a -> a + (Integer -> Fixed a forall a. Num a => Integer -> a fromInteger Integer f Fixed a -> Fixed a -> Fixed a forall a. Fractional a => a -> a -> a / (Fixed a 10Fixed a -> Integer -> Fixed a forall a b. (Num a, Integral b) => a -> b -> a ^ Integer e )))wherer :: Integer r =Proxy a -> Integer forall k (a :: k) (p :: k -> *). HasResolution a => p a -> Integer resolution (Proxy a forall k (t :: k). Proxy t Proxy ::Proxy a )-- round 'e' up to help make the 'read . show == id' property-- possible also for cases where 'resolution' is not a-- power-of-10, such as e.g. when 'resolution = 128'e :: Integer e =Double -> Integer forall a b. (RealFrac a, Integral b) => a -> b ceiling (Double -> Double -> Double forall a. Floating a => a -> a -> a logBase Double 10(Integer -> Double forall a. Num a => Integer -> a fromInteger Integer r )::Double)convertFixed Lexeme _=ReadPrec (Fixed a) forall a. ReadPrec a pfail dataE0 -- | @since 4.1.0.0instanceHasResolution E0 whereresolution :: p E0 -> Integer resolution p E0 _=Integer 1-- | resolution of 1, this works the same as IntegertypeUni =Fixed E0 dataE1 -- | @since 4.1.0.0instanceHasResolution E1 whereresolution :: p E1 -> Integer resolution p E1 _=Integer 10-- | resolution of 10^-1 = .1typeDeci =Fixed E1 dataE2 -- | @since 4.1.0.0instanceHasResolution E2 whereresolution :: p E2 -> Integer resolution p E2 _=Integer 100-- | resolution of 10^-2 = .01, useful for many monetary currenciestypeCenti =Fixed E2 dataE3 -- | @since 4.1.0.0instanceHasResolution E3 whereresolution :: p E3 -> Integer resolution p E3 _=Integer 1000-- | resolution of 10^-3 = .001typeMilli =Fixed E3 dataE6 -- | @since 2.01instanceHasResolution E6 whereresolution :: p E6 -> Integer resolution p E6 _=Integer 1000000-- | resolution of 10^-6 = .000001typeMicro =Fixed E6 dataE9 -- | @since 4.1.0.0instanceHasResolution E9 whereresolution :: p E9 -> Integer resolution p E9 _=Integer 1000000000-- | resolution of 10^-9 = .000000001typeNano =Fixed E9 dataE12 -- | @since 2.01instanceHasResolution E12 whereresolution :: p E12 -> Integer resolution p E12 _=Integer 1000000000000-- | resolution of 10^-12 = .000000000001typePico =Fixed E12