{-# 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 :: a -> a -> a
fpMaxH a
x a
y
| a -> Bool
forall a. RealFloat a => a -> Bool
isNaN a
x = a
y
| a -> Bool
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) = [Char] -> a
forall a. HasCallStack => [Char] -> a
error [Char]
"fpMaxH: Called with alternating-sign 0's. Not supported"
| a
x a -> a -> Bool
forall a. Ord a => a -> a -> Bool
> a
y = a
x
| Bool
True = a
y
where isN0 :: a -> Bool
isN0 = a -> Bool
forall a. RealFloat a => a -> Bool
isNegativeZero
isP0 :: a -> Bool
isP0 a
a = a
a a -> a -> Bool
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 :: a -> a -> a
fpMinH a
x a
y
| a -> Bool
forall a. RealFloat a => a -> Bool
isNaN a
x = a
y
| a -> Bool
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) = [Char] -> a
forall a. HasCallStack => [Char] -> a
error [Char]
"fpMinH: Called with alternating-sign 0's. Not supported"
| a
x a -> a -> Bool
forall a. Ord a => a -> a -> Bool
< a
y = a
x
| Bool
True = a
y
where isN0 :: a -> Bool
isN0 = a -> Bool
forall a. RealFloat a => a -> Bool
isNegativeZero
isP0 :: a -> Bool
isP0 a
a = a
a a -> a -> Bool
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 :: a -> b
fp2fp a
x
| a -> Bool
forall a. RealFloat a => a -> Bool
isNaN a
x = b
0 b -> b -> b
forall a. Fractional a => a -> a -> a
/ b
0
| a -> Bool
forall a. RealFloat a => a -> Bool
isInfinite a
x Bool -> Bool -> Bool
&& a
x a -> a -> Bool
forall a. Ord a => a -> a -> Bool
< a
0 = -b
1 b -> b -> b
forall a. Fractional a => a -> a -> a
/ b
0
| a -> Bool
forall a. RealFloat a => a -> Bool
isInfinite a
x = b
1 b -> b -> b
forall a. Fractional a => a -> a -> a
/ b
0
| a -> Bool
forall a. RealFloat a => a -> Bool
isNegativeZero a
x = b -> b
forall a. Num a => a -> a
negate b
0
| Bool
True = Rational -> b
forall a. Fractional a => Rational -> a
fromRational (a -> Rational
forall a. Real a => a -> Rational
toRational a
x)
fpRemH :: RealFloat a => a -> a -> a
fpRemH :: a -> a -> a
fpRemH a
x a
y
| a -> Bool
forall a. RealFloat a => a -> Bool
isInfinite a
x Bool -> Bool -> Bool
|| a -> Bool
forall a. RealFloat a => a -> Bool
isNaN a
x = a
0 a -> a -> a
forall a. Fractional a => a -> a -> a
/ a
0
| a
y a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
0 Bool -> Bool -> Bool
|| a -> Bool
forall a. RealFloat a => a -> Bool
isNaN a
y = a
0 a -> a -> a
forall a. Fractional a => a -> a -> a
/ a
0
| a -> Bool
forall a. RealFloat a => a -> Bool
isInfinite a
y = a
x
| Bool
True = a -> a
forall p. (Eq p, Fractional p) => p -> p
pSign (a
x a -> a -> a
forall a. Num a => a -> a -> a
- Rational -> a
forall a. Fractional a => Rational -> a
fromRational (Integer -> Rational
forall a. Num a => Integer -> a
fromInteger Integer
d Rational -> Rational -> Rational
forall a. Num a => a -> a -> a
* Rational
ry))
where rx, ry, rd :: Rational
rx :: Rational
rx = a -> Rational
forall a. Real a => a -> Rational
toRational a
x
ry :: Rational
ry = a -> Rational
forall a. Real a => a -> Rational
toRational a
y
rd :: Rational
rd = Rational
rx Rational -> Rational -> Rational
forall a. Fractional a => a -> a -> a
/ Rational
ry
d :: Integer
d :: Integer
d = Rational -> Integer
forall a b. (RealFrac a, Integral b) => a -> b
round Rational
rd
pSign :: p -> p
pSign p
r
| p
r p -> p -> Bool
forall a. Eq a => a -> a -> Bool
== p
0 = if a
x a -> a -> Bool
forall a. Ord a => a -> a -> Bool
< a
0 Bool -> Bool -> Bool
|| a -> Bool
forall a. RealFloat a => a -> Bool
isNegativeZero a
x then -p
0.0 else p
0.0
| Bool
True = p
r
fpRoundToIntegralH :: RealFloat a => a -> a
fpRoundToIntegralH :: a -> a
fpRoundToIntegralH a
x
| a -> Bool
forall a. RealFloat a => a -> Bool
isNaN a
x = a
x
| a
x a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
0 = a
x
| a -> Bool
forall a. RealFloat a => a -> Bool
isInfinite a
x = a
x
| Integer
i Integer -> Integer -> Bool
forall a. Eq a => a -> a -> Bool
== Integer
0 = if a
x a -> a -> Bool
forall a. Ord a => a -> a -> Bool
< a
0 Bool -> Bool -> Bool
|| a -> Bool
forall a. RealFloat a => a -> Bool
isNegativeZero a
x then -a
0.0 else a
0.0
| Bool
True = Integer -> a
forall a. Num a => Integer -> a
fromInteger Integer
i
where i :: Integer
i :: Integer
i = a -> Integer
forall a b. (RealFrac a, Integral b) => a -> b
round a
x
fpIsEqualObjectH :: RealFloat a => a -> a -> Bool
fpIsEqualObjectH :: a -> a -> Bool
fpIsEqualObjectH a
a a
b
| a -> Bool
forall a. RealFloat a => a -> Bool
isNaN a
a = a -> Bool
forall a. RealFloat a => a -> Bool
isNaN a
b
| a -> Bool
forall a. RealFloat a => a -> Bool
isNegativeZero a
a = a -> Bool
forall a. RealFloat a => a -> Bool
isNegativeZero a
b
| a -> Bool
forall a. RealFloat a => a -> Bool
isNegativeZero a
b = a -> Bool
forall a. RealFloat a => a -> Bool
isNegativeZero a
a
| Bool
True = a
a a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
b
fpCompareObjectH :: RealFloat a => a -> a -> Ordering
fpCompareObjectH :: a -> a -> Ordering
fpCompareObjectH a
a a
b
| a
a a -> a -> Bool
forall a. RealFloat a => a -> a -> Bool
`fpIsEqualObjectH` a
b = Ordering
EQ
| a -> Bool
forall a. RealFloat a => a -> Bool
isNaN a
a = Ordering
LT
| a -> Bool
forall a. RealFloat a => a -> Bool
isNaN a
b = Ordering
GT
| a -> Bool
forall a. RealFloat a => a -> Bool
isNegativeZero a
a, a
b a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
0 = Ordering
LT
| a -> Bool
forall a. RealFloat a => a -> Bool
isNegativeZero a
b, a
a a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
0 = Ordering
GT
| Bool
True = a
a a -> a -> Ordering
forall a. Ord a => a -> a -> Ordering
`compare` a
b
fpIsNormalizedH :: RealFloat a => a -> Bool
fpIsNormalizedH :: a -> Bool
fpIsNormalizedH a
x = Bool -> Bool
not (a -> Bool
forall a. RealFloat a => a -> Bool
isDenormalized a
x Bool -> Bool -> Bool
|| a -> Bool
forall a. RealFloat a => a -> Bool
isInfinite a
x Bool -> Bool -> Bool
|| a -> Bool
forall a. RealFloat a => a -> Bool
isNaN a
x Bool -> Bool -> Bool
|| a
x a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
0)
floatToWord :: Float -> Word32
floatToWord :: Float -> Word32
floatToWord Float
x = (forall s. ST s Word32) -> Word32
forall a. (forall s. ST s a) -> a
runST (Float -> ST s Word32
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 s. ST s Float) -> Float
forall a. (forall s. ST s a) -> a
runST (Word32 -> ST s Float
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 s. ST s Word64) -> Word64
forall a. (forall s. ST s a) -> a
runST (Double -> ST s Word64
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 s. ST s Double) -> Double
forall a. (forall s. ST s a) -> a
runST (Word64 -> ST s Double
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 :: a -> ST s b
cast a
x = (Int, Int) -> a -> ST s (STUArray s Int a)
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 ST s (STUArray s Int a)
-> (STUArray s Int a -> ST s (STUArray s Int b))
-> ST s (STUArray s Int b)
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= STUArray s Int a -> ST s (STUArray s Int b)
forall s ix a b. STUArray s ix a -> ST s (STUArray s ix b)
castSTUArray ST s (STUArray s Int b) -> (STUArray s Int b -> ST s b) -> ST s b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= (STUArray s Int b -> Int -> ST s b)
-> Int -> STUArray s Int b -> ST s b
forall a b c. (a -> b -> c) -> b -> a -> c
flip STUArray s Int b -> Int -> ST s b
forall (a :: * -> * -> *) e (m :: * -> *) i.
(MArray a e m, Ix i) =>
a i e -> i -> m e
readArray Int
0