{-# LANGUAGE ForeignFunctionInterface #-}
module Numeric.IEEE (
IEEE(..),
minNum,
maxNum,
minNaN,
maxNaN,
) where
import Data.Word
import Foreign.C.Types( CFloat, CDouble )
class (RealFloat a) => IEEE a where
infinity :: a
minDenormal :: a
minNormal :: a
maxFinite :: a
epsilon :: a
copySign :: a -> a -> a
identicalIEEE :: a -> a -> Bool
succIEEE :: a -> a
predIEEE :: a -> a
bisectIEEE :: a -> a -> a
sameSignificandBits :: a -> a -> Int
nan :: a
nanWithPayload :: Word64 -> a
maxNaNPayload :: a -> Word64
nanPayload :: a -> Word64
maxNum :: (RealFloat a) => a -> a -> a
maxNum x y | x >= y || isNaN y = x
| otherwise = y
{-# INLINE maxNum #-}
minNum :: (RealFloat a) => a -> a -> a
minNum x y | x <= y || isNaN y = x
| otherwise = y
{-# INLINE minNum #-}
maxNaN :: (RealFloat a) => a -> a -> a
maxNaN x y | x >= y || isNaN x = x
| otherwise = y
{-# INLINE maxNaN #-}
minNaN :: (RealFloat a) => a -> a -> a
minNaN x y | x <= y || isNaN x = x
| otherwise = y
{-# INLINE minNaN #-}
instance IEEE Float where
identicalIEEE x y = c_identicalf x y /= 0
{-# INLINE identicalIEEE #-}
infinity = 1/0
{-# INLINE infinity #-}
nan = (0/0)
{-# INLINE nan #-}
nanWithPayload n = c_mknanf (fromIntegral n)
{-# INLINE nanWithPayload #-}
maxNaNPayload _ = 0x003FFFFF
{-# INLINE maxNaNPayload #-}
nanPayload x = fromIntegral $ c_getnanf x
{-# INLINE nanPayload #-}
minDenormal = 1e-45
{-# INLINE minDenormal #-}
minNormal = 1.17549435e-38
{-# INLINE minNormal #-}
maxFinite = 3.40282347e+38
{-# INLINE maxFinite #-}
epsilon = 1.19209290e-07
{-# INLINE epsilon #-}
copySign = c_copysignf
{-# INLINE copySign #-}
succIEEE = c_ieeesuccf
{-# INLINE succIEEE #-}
predIEEE = c_ieeepredf
{-# INLINE predIEEE #-}
bisectIEEE = c_ieeemeanf
{-# INLINE bisectIEEE #-}
sameSignificandBits = c_feqrelf
{-# INLINE sameSignificandBits #-}
instance IEEE CFloat where
identicalIEEE x y = c_identicalf (realToFrac x) (realToFrac y) /= 0
{-# INLINE identicalIEEE #-}
infinity = 1/0
{-# INLINE infinity #-}
nan = (0/0)
{-# INLINE nan #-}
nanWithPayload n = realToFrac $ c_mknanf (fromIntegral n)
{-# INLINE nanWithPayload #-}
maxNaNPayload _ = 0x003FFFFF
{-# INLINE maxNaNPayload #-}
nanPayload x = fromIntegral $ c_getnanf (realToFrac x)
{-# INLINE nanPayload #-}
minDenormal = 1e-45
{-# INLINE minDenormal #-}
minNormal = 1.17549435e-38
{-# INLINE minNormal #-}
maxFinite = 3.40282347e+38
{-# INLINE maxFinite #-}
epsilon = 1.19209290e-07
{-# INLINE epsilon #-}
copySign x y = realToFrac $ c_copysignf (realToFrac x) (realToFrac y)
{-# INLINE copySign #-}
succIEEE x = realToFrac $ c_ieeesuccf (realToFrac x)
{-# INLINE succIEEE #-}
predIEEE x = realToFrac $ c_ieeepredf (realToFrac x)
{-# INLINE predIEEE #-}
bisectIEEE x y = realToFrac $ c_ieeemeanf (realToFrac x) (realToFrac y)
{-# INLINE bisectIEEE #-}
sameSignificandBits x y = c_feqrelf (realToFrac x) (realToFrac y)
{-# INLINE sameSignificandBits #-}
instance IEEE Double where
identicalIEEE x y = c_identical x y /= 0
{-# INLINE identicalIEEE #-}
infinity = 1/0
{-# INLINE infinity #-}
nan = (0/0)
{-# INLINE nan #-}
nanWithPayload n = c_mknan n
{-# INLINE nanWithPayload #-}
maxNaNPayload _ = 0x0007FFFFFFFFFFFF
{-# INLINE maxNaNPayload #-}
nanPayload x = c_getnan x
{-# INLINE nanPayload #-}
minDenormal = 5e-324
{-# INLINE minDenormal #-}
minNormal = 2.2250738585072014e-308
{-# INLINE minNormal #-}
maxFinite = 1.7976931348623157e+308
{-# INLINE maxFinite #-}
epsilon = 2.2204460492503131e-16
{-# INLINE epsilon #-}
copySign = c_copysign
{-# INLINE copySign #-}
succIEEE = c_ieeesucc
{-# INLINE succIEEE #-}
predIEEE = c_ieeepred
{-# INLINE predIEEE #-}
bisectIEEE = c_ieeemean
{-# INLINE bisectIEEE #-}
sameSignificandBits = c_feqrel
{-# INLINE sameSignificandBits #-}
instance IEEE CDouble where
identicalIEEE x y = c_identical (realToFrac x) (realToFrac y) /= 0
{-# INLINE identicalIEEE #-}
infinity = 1/0
{-# INLINE infinity #-}
nan = (0/0)
{-# INLINE nan #-}
nanWithPayload n = realToFrac $ c_mknan n
{-# INLINE nanWithPayload #-}
maxNaNPayload _ = 0x0007FFFFFFFFFFFF
{-# INLINE maxNaNPayload #-}
nanPayload x = c_getnan (realToFrac x)
{-# INLINE nanPayload #-}
minDenormal = 5e-324
{-# INLINE minDenormal #-}
minNormal = 2.2250738585072014e-308
{-# INLINE minNormal #-}
maxFinite = 1.7976931348623157e+308
{-# INLINE maxFinite #-}
epsilon = 2.2204460492503131e-16
{-# INLINE epsilon #-}
succIEEE x = realToFrac $ c_ieeesucc (realToFrac x)
{-# INLINE succIEEE #-}
copySign x y = realToFrac $ c_copysign (realToFrac x) (realToFrac y)
{-# INLINE copySign #-}
predIEEE x = realToFrac $ c_ieeepred (realToFrac x)
{-# INLINE predIEEE #-}
bisectIEEE x y = realToFrac $ c_ieeemean (realToFrac x) (realToFrac y)
{-# INLINE bisectIEEE #-}
sameSignificandBits x y = c_feqrel (realToFrac x) (realToFrac y)
{-# INLINE sameSignificandBits #-}
foreign import ccall unsafe "identical"
c_identical :: Double -> Double -> Int
foreign import ccall unsafe "identicalf"
c_identicalf :: Float -> Float -> Int
foreign import ccall unsafe "feqrel"
c_feqrel :: Double -> Double -> Int
foreign import ccall unsafe "feqrelf"
c_feqrelf :: Float -> Float -> Int
foreign import ccall unsafe "ieeesucc"
c_ieeesucc :: Double -> Double
foreign import ccall unsafe "ieeesuccf"
c_ieeesuccf :: Float -> Float
foreign import ccall unsafe "ieeepred"
c_ieeepred :: Double -> Double
foreign import ccall unsafe "ieeepredf"
c_ieeepredf :: Float -> Float
foreign import ccall unsafe "ieeemean"
c_ieeemean :: Double -> Double -> Double
foreign import ccall unsafe "ieeemeanf"
c_ieeemeanf :: Float -> Float -> Float
foreign import ccall unsafe "copysign"
c_copysign :: Double -> Double -> Double
foreign import ccall unsafe "copysignf"
c_copysignf :: Float -> Float -> Float
foreign import ccall unsafe "mknan"
c_mknan :: Word64 -> Double
foreign import ccall unsafe "getnan"
c_getnan :: Double -> Word64
foreign import ccall unsafe "mknanf"
c_mknanf :: Word32 -> Float
foreign import ccall unsafe "getnanf"
c_getnanf :: Float -> Word32