{-# LANGUAGE FlexibleContexts #-}
{-# OPTIONS_GHC -Wall -Werror #-}
module Data.SBV.Utils.Numeric (
fpMaxH, fpMinH, fp2fp, fpRemH, fpRoundToIntegralH, fpIsEqualObjectH, fpCompareObjectH, fpIsNormalizedH
, floatToWord, wordToFloat, doubleToWord, wordToDouble
) where
import Data.Word
import Data.Array.ST (newArray, readArray, MArray, STUArray)
import Data.Array.Unsafe (castSTUArray)
import GHC.ST (runST, ST)
fpMaxH :: RealFloat a => a -> a -> a
fpMaxH :: forall a. RealFloat a => a -> a -> a
fpMaxH a
x a
y
| forall a. RealFloat a => a -> Bool
isNaN a
x = a
y
| forall a. RealFloat a => a -> Bool
isNaN a
y = a
x
| (a -> Bool
isN0 a
x Bool -> Bool -> Bool
&& a -> Bool
isP0 a
y) Bool -> Bool -> Bool
|| (a -> Bool
isN0 a
y Bool -> Bool -> Bool
&& a -> Bool
isP0 a
x) = forall a. HasCallStack => [Char] -> a
error [Char]
"fpMaxH: Called with alternating-sign 0's. Not supported"
| a
x forall a. Ord a => a -> a -> Bool
> a
y = a
x
| Bool
True = a
y
where isN0 :: a -> Bool
isN0 = forall a. RealFloat a => a -> Bool
isNegativeZero
isP0 :: a -> Bool
isP0 a
a = a
a forall a. Eq a => a -> a -> Bool
== a
0 Bool -> Bool -> Bool
&& Bool -> Bool
not (a -> Bool
isN0 a
a)
fpMinH :: RealFloat a => a -> a -> a
fpMinH :: forall a. RealFloat a => a -> a -> a
fpMinH a
x a
y
| forall a. RealFloat a => a -> Bool
isNaN a
x = a
y
| forall a. RealFloat a => a -> Bool
isNaN a
y = a
x
| (a -> Bool
isN0 a
x Bool -> Bool -> Bool
&& a -> Bool
isP0 a
y) Bool -> Bool -> Bool
|| (a -> Bool
isN0 a
y Bool -> Bool -> Bool
&& a -> Bool
isP0 a
x) = forall a. HasCallStack => [Char] -> a
error [Char]
"fpMinH: Called with alternating-sign 0's. Not supported"
| a
x forall a. Ord a => a -> a -> Bool
< a
y = a
x
| Bool
True = a
y
where isN0 :: a -> Bool
isN0 = forall a. RealFloat a => a -> Bool
isNegativeZero
isP0 :: a -> Bool
isP0 a
a = a
a forall a. Eq a => a -> a -> Bool
== a
0 Bool -> Bool -> Bool
&& Bool -> Bool
not (a -> Bool
isN0 a
a)
fp2fp :: (RealFloat a, RealFloat b) => a -> b
fp2fp :: forall a b. (RealFloat a, RealFloat b) => a -> b
fp2fp a
x
| forall a. RealFloat a => a -> Bool
isNaN a
x = b
0 forall a. Fractional a => a -> a -> a
/ b
0
| forall a. RealFloat a => a -> Bool
isInfinite a
x Bool -> Bool -> Bool
&& a
x forall a. Ord a => a -> a -> Bool
< a
0 = -b
1 forall a. Fractional a => a -> a -> a
/ b
0
| forall a. RealFloat a => a -> Bool
isInfinite a
x = b
1 forall a. Fractional a => a -> a -> a
/ b
0
| forall a. RealFloat a => a -> Bool
isNegativeZero a
x = forall a. Num a => a -> a
negate b
0
| Bool
True = forall a. Fractional a => Rational -> a
fromRational (forall a. Real a => a -> Rational
toRational a
x)
fpRemH :: RealFloat a => a -> a -> a
fpRemH :: forall a. RealFloat a => a -> a -> a
fpRemH a
x a
y
| forall a. RealFloat a => a -> Bool
isInfinite a
x Bool -> Bool -> Bool
|| forall a. RealFloat a => a -> Bool
isNaN a
x = a
0 forall a. Fractional a => a -> a -> a
/ a
0
| a
y forall a. Eq a => a -> a -> Bool
== a
0 Bool -> Bool -> Bool
|| forall a. RealFloat a => a -> Bool
isNaN a
y = a
0 forall a. Fractional a => a -> a -> a
/ a
0
| forall a. RealFloat a => a -> Bool
isInfinite a
y = a
x
| Bool
True = forall {a}. (Eq a, Fractional a) => a -> a
pSign (a
x forall a. Num a => a -> a -> a
- forall a. Fractional a => Rational -> a
fromRational (forall a. Num a => Integer -> a
fromInteger Integer
d forall a. Num a => a -> a -> a
* Rational
ry))
where rx, ry, rd :: Rational
rx :: Rational
rx = forall a. Real a => a -> Rational
toRational a
x
ry :: Rational
ry = forall a. Real a => a -> Rational
toRational a
y
rd :: Rational
rd = Rational
rx forall a. Fractional a => a -> a -> a
/ Rational
ry
d :: Integer
d :: Integer
d = forall a b. (RealFrac a, Integral b) => a -> b
round Rational
rd
pSign :: a -> a
pSign a
r
| a
r forall a. Eq a => a -> a -> Bool
== a
0 = if a
x forall a. Ord a => a -> a -> Bool
< a
0 Bool -> Bool -> Bool
|| forall a. RealFloat a => a -> Bool
isNegativeZero a
x then -a
0.0 else a
0.0
| Bool
True = a
r
fpRoundToIntegralH :: RealFloat a => a -> a
fpRoundToIntegralH :: forall a. RealFloat a => a -> a
fpRoundToIntegralH a
x
| forall a. RealFloat a => a -> Bool
isNaN a
x = a
x
| a
x forall a. Eq a => a -> a -> Bool
== a
0 = a
x
| forall a. RealFloat a => a -> Bool
isInfinite a
x = a
x
| Integer
i forall a. Eq a => a -> a -> Bool
== Integer
0 = if a
x forall a. Ord a => a -> a -> Bool
< a
0 Bool -> Bool -> Bool
|| forall a. RealFloat a => a -> Bool
isNegativeZero a
x then -a
0.0 else a
0.0
| Bool
True = forall a. Num a => Integer -> a
fromInteger Integer
i
where i :: Integer
i :: Integer
i = forall a b. (RealFrac a, Integral b) => a -> b
round a
x
fpIsEqualObjectH :: RealFloat a => a -> a -> Bool
fpIsEqualObjectH :: forall a. RealFloat a => a -> a -> Bool
fpIsEqualObjectH a
a a
b
| forall a. RealFloat a => a -> Bool
isNaN a
a = forall a. RealFloat a => a -> Bool
isNaN a
b
| forall a. RealFloat a => a -> Bool
isNegativeZero a
a = forall a. RealFloat a => a -> Bool
isNegativeZero a
b
| forall a. RealFloat a => a -> Bool
isNegativeZero a
b = forall a. RealFloat a => a -> Bool
isNegativeZero a
a
| Bool
True = a
a forall a. Eq a => a -> a -> Bool
== a
b
fpCompareObjectH :: RealFloat a => a -> a -> Ordering
fpCompareObjectH :: forall a. RealFloat a => a -> a -> Ordering
fpCompareObjectH a
a a
b
| a
a forall a. RealFloat a => a -> a -> Bool
`fpIsEqualObjectH` a
b = Ordering
EQ
| forall a. RealFloat a => a -> Bool
isNaN a
a = Ordering
LT
| forall a. RealFloat a => a -> Bool
isNaN a
b = Ordering
GT
| forall a. RealFloat a => a -> Bool
isNegativeZero a
a, a
b forall a. Eq a => a -> a -> Bool
== a
0 = Ordering
LT
| forall a. RealFloat a => a -> Bool
isNegativeZero a
b, a
a forall a. Eq a => a -> a -> Bool
== a
0 = Ordering
GT
| Bool
True = a
a forall a. Ord a => a -> a -> Ordering
`compare` a
b
fpIsNormalizedH :: RealFloat a => a -> Bool
fpIsNormalizedH :: forall a. RealFloat a => a -> Bool
fpIsNormalizedH a
x = Bool -> Bool
not (forall a. RealFloat a => a -> Bool
isDenormalized a
x Bool -> Bool -> Bool
|| forall a. RealFloat a => a -> Bool
isInfinite a
x Bool -> Bool -> Bool
|| forall a. RealFloat a => a -> Bool
isNaN a
x Bool -> Bool -> Bool
|| a
x forall a. Eq a => a -> a -> Bool
== a
0)
floatToWord :: Float -> Word32
floatToWord :: Float -> Word32
floatToWord Float
x = forall a. (forall s. ST s a) -> a
runST (forall s a b.
(MArray (STUArray s) a (ST s), MArray (STUArray s) b (ST s)) =>
a -> ST s b
cast Float
x)
{-# INLINEABLE floatToWord #-}
wordToFloat :: Word32 -> Float
wordToFloat :: Word32 -> Float
wordToFloat Word32
x = forall a. (forall s. ST s a) -> a
runST (forall s a b.
(MArray (STUArray s) a (ST s), MArray (STUArray s) b (ST s)) =>
a -> ST s b
cast Word32
x)
{-# INLINEABLE wordToFloat #-}
doubleToWord :: Double -> Word64
doubleToWord :: Double -> Word64
doubleToWord Double
x = forall a. (forall s. ST s a) -> a
runST (forall s a b.
(MArray (STUArray s) a (ST s), MArray (STUArray s) b (ST s)) =>
a -> ST s b
cast Double
x)
{-# INLINEABLE doubleToWord #-}
wordToDouble :: Word64 -> Double
wordToDouble :: Word64 -> Double
wordToDouble Word64
x = forall a. (forall s. ST s a) -> a
runST (forall s a b.
(MArray (STUArray s) a (ST s), MArray (STUArray s) b (ST s)) =>
a -> ST s b
cast Word64
x)
{-# INLINEABLE wordToDouble #-}
{-# INLINE cast #-}
cast :: (MArray (STUArray s) a (ST s), MArray (STUArray s) b (ST s)) => a -> ST s b
cast :: forall s a b.
(MArray (STUArray s) a (ST s), MArray (STUArray s) b (ST s)) =>
a -> ST s b
cast a
x = forall (a :: * -> * -> *) e (m :: * -> *) i.
(MArray a e m, Ix i) =>
(i, i) -> e -> m (a i e)
newArray (Int
0 :: Int, Int
0) a
x forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= forall s ix a b. STUArray s ix a -> ST s (STUArray s ix b)
castSTUArray forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= forall a b c. (a -> b -> c) -> b -> a -> c
flip forall (a :: * -> * -> *) e (m :: * -> *) i.
(MArray a e m, Ix i) =>
a i e -> i -> m e
readArray Int
0