module Feldspar.FixedPoint
( Fix(..), Fixable(..)
, freezeFix, freezeFix', unfreezeFix, unfreezeFix'
, (?!), fixFold
)
where
import qualified Prelude
import Feldspar hiding (sugar,desugar)
import Feldspar.Vector
import Language.Syntactic hiding (fold)
data Fix a =
Fix
{ exponent :: Data IntN
, mantissa :: Data a
}
deriving (Prelude.Eq,Prelude.Show)
instance
( Integral a
, Bits a
) => Num (Fix a)
where
fromInteger n = Fix 0 (Prelude.fromInteger n)
(+) = fixAddition
(*) = fixMultiplication
negate = fixNegate
abs = fixAbsolute
signum = fixSignum
instance
( Integral a
, Bits a
, Prelude.Floating a
) => Fractional (Fix a)
where
(/) = fixDiv'
recip = fixRecip'
fromRational = fixfromRational
fixAddition :: (Integral a, Bits a) => Fix a -> Fix a -> Fix a
fixAddition f1@(Fix e1 _) f2@(Fix e2 _) = Fix e m
where
e = max e1 e2
m = mantissa (fix e f1) + mantissa (fix e f2)
fixMultiplication :: (Integral a) => Fix a -> Fix a -> Fix a
fixMultiplication (Fix e1 m1) (Fix e2 m2) = Fix e m
where
e = e1 + e2
m = m1 * m2
fixNegate :: (Integral a) => Fix a -> Fix a
fixNegate (Fix e1 m1) = Fix e1 m
where
m = negate m1
fixAbsolute :: (Integral a) => Fix a -> Fix a
fixAbsolute (Fix e1 m1) = Fix e1 m
where
m = abs m1
fixSignum :: (Integral a) => Fix a -> Fix a
fixSignum (Fix _ m1) = Fix 0 m
where
m = signum m1
fixDiv' :: (Integral a, Bits a, Prelude.Real a)
=> Fix a -> Fix a -> Fix a
fixDiv' (Fix e1 m1) (Fix e2 m2) = Fix e m
where
e = e1 e2
m = div m1 m2
fixRecip' :: forall a . (Integral a, Bits a, Prelude.Floating a)
=> Fix a -> Fix a
fixRecip' (Fix e m) = Fix (e + value (wordLength (T :: T a) 1)) (div sh m)
where
sh :: Data a
sh = (1::Data a) .<<. value (fromInteger $ toInteger $ wordLength (T :: T a) 1)
fixfromRational :: forall a . (Integral a, Bits a, Prelude.Floating a) =>
Prelude.Rational -> Fix a
fixfromRational inp = Fix e m
where
inpAsFloat :: Float
inpAsFloat = fromRational inp
intPart :: Float
intPart = Prelude.fromIntegral (Prelude.floor inpAsFloat :: Integer)
intPartWidth :: IntN
intPartWidth = Prelude.ceiling $ Prelude.logBase 2 intPart
fracPartWith :: IntN
fracPartWith = wordLength (T :: T a) intPartWidth 2
m = value $ Prelude.floor $ inpAsFloat * 2.0 Prelude.** fromRational (toRational fracPartWith)
e = negate $ value fracPartWith
instance (Type a) => Syntactic (Fix a) where
type Domain (Fix a) = FeldDomain
type Internal (Fix a) = (IntN, a)
desugar = desugar . freezeFix
sugar = unfreezeFix . sugar
freezeFix :: (Type a) => Fix a -> (Data IntN,Data a)
freezeFix (Fix e m) = (e,m)
freezeFix' :: (Bits a) => IntN -> Fix a -> Data a
freezeFix' e f = mantissa $ fix (value e) f
unfreezeFix :: (Type a) => (Data IntN, Data a) -> Fix a
unfreezeFix = uncurry Fix
unfreezeFix' :: IntN -> Data a -> Fix a
unfreezeFix' e = Fix (value e)
wordLength :: forall a. (Bits a) => T a -> IntN
wordLength _ = Prelude.fromIntegral $ finiteBitSize (undefined :: a)
class (Splittable t) => Fixable t where
fix :: Data IntN -> t -> t
getExp :: t -> Data IntN
instance (Bits a) => Fixable (Fix a) where
fix e' (Fix e m) = Fix e' $ e' > e ? (m .>>. i2n (e' e)) $ (m .<<. i2n (e e'))
getExp = Feldspar.FixedPoint.exponent
instance Fixable (Data Float) where
fix = const id
getExp = const $ fromInteger $ toInteger $ Prelude.exponent (0.0 :: Float)
data T a = T
class (Syntax (Dynamic t)) => Splittable t where
type Static t
type Dynamic t
store :: t -> (Static t, Dynamic t)
retrieve :: (Static t, Dynamic t) -> t
patch :: Static t -> t -> t
common :: t -> t -> Static t
instance (Type a) => Splittable (Data a) where
type Static (Data a) = ()
type Dynamic (Data a) = Data a
store x = ((),x)
retrieve = snd
patch = const id
common _ _ = ()
instance (Bits a) => Splittable (Fix a) where
type Static (Fix a) = Data IntN
type Dynamic (Fix a) = Data a
store f = (Feldspar.FixedPoint.exponent f, mantissa f)
retrieve = uncurry Fix
patch = fix
common f g = max (Feldspar.FixedPoint.exponent f) (Feldspar.FixedPoint.exponent g)
fixFold :: forall a b . (Splittable a) => (a -> b -> a) -> a -> Vector b -> a
fixFold fun ini vec = retrieve (static, fold fun' ini' vec)
where
static = fst $ store ini
ini' = snd $ store ini
fun' st el = snd $ store $ patch static $ retrieve (static,st) `fun` el
infix 1 ?!
(?!) :: forall a . (Syntax a, Splittable a) => Data Bool -> (a,a) -> a
cond ?! (x,y) = retrieve (comm, cond ? x' $ y')
where
comm = common x y
x' = snd $ store $ patch comm x
y' = snd $ store $ patch comm y