module Numeric.ExpExtended.Internal
( Cache(..)
, cacheDefault
, minExponent
, maxExponent
) where
import Data.Bits (bit, shiftL, shiftR)
data Cache a = Cache
{ cRadix :: !Integer
, cDigits :: !Int
, cRangeMin :: !Int
, cRangeMax :: !Int
, cSupExponent :: !Int
, cInfExponent :: !Int
, cUpShift :: Integer -> Int -> Integer
, cDownShift :: Integer -> Int -> Integer
, cRadixPower :: Int -> Integer
, cExpMin :: !Int
, cExpMax :: !Int
, cExpInf :: !Int
, cExpSup :: !Int
, cLogRadix :: !a
, cRadix' :: !a
}
cacheDefault :: RealFloat a => Cache a
cacheDefault = self
where
x = unProxy self
self = Cache
{ cRadix = floatRadix x
, cDigits = floatDigits x
, cRangeMin = fst (floatRange x)
, cRangeMax = snd (floatRange x)
, cSupExponent = supExponentDefault x
, cInfExponent = infExponentDefault x
, cUpShift = case floatRadix x of
2 -> shiftL
d -> \n e -> n * (d ^ e)
, cDownShift = case floatRadix x of
2 -> shiftR
d -> \n e -> n `div` (d ^ e)
, cRadixPower = case floatRadix x of
2 -> bit
d -> \e -> d ^ e
, cExpMin = expMinDefault x
, cExpMax = expMaxDefault x
, cExpInf = expInfDefault x
, cExpSup = expSupDefault x
, cLogRadix = log (fromIntegral (floatRadix x))
, cRadix' = fromIntegral (floatRadix x)
}
unProxy :: proxy a -> a
unProxy _ = undefined
margin :: Int
margin = 2
maxExponent :: Int
maxExponent = div maxBound 2 margin
minExponent :: Int
minExponent = div minBound 2 + margin
expSupDefault :: RealFloat a => a -> Int
expSupDefault m = floor $ logBase b (fromIntegral maxExponent * log b)
where
b :: Double
b = fromIntegral (floatRadix m)
expInfDefault :: RealFloat a => a -> Int
expInfDefault m = negate (floatDigits m)
expMaxDefault :: RealFloat a => a -> Int
expMaxDefault m = floor $ logBase b (log (scaleFloat (snd (floatRange m)) (recip b)))
where b = fromIntegral (floatRadix m) `asTypeOf` m
expMinDefault :: RealFloat a => a -> Int
expMinDefault m = negate (floatDigits m)
supExponentDefault :: RealFloat a => a -> Int
supExponentDefault x
= maxExponent
fst (floatRange x)
+ floatDigits x
infExponentDefault :: RealFloat a => a -> Int
infExponentDefault x
= minExponent
snd (floatRange x)
floatDigits x