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
minNum :: (RealFloat a) => a -> a -> a
minNum x y | x <= y || isNaN y = x
           | otherwise         = y
maxNaN :: (RealFloat a) => a -> a -> a
maxNaN x y | x >= y || isNaN x = x
           | otherwise         = y
minNaN :: (RealFloat a) =>  a -> a -> a
minNaN x y | x <= y || isNaN x = x
           | otherwise         = y
instance IEEE Float where
    identicalIEEE x y = c_identicalf x y /= 0
    
    infinity = 1/0
    
    nan = (0/0)
    
    nanWithPayload n = c_mknanf (fromIntegral n)
    
    maxNaNPayload _ = 0x003FFFFF
    
    nanPayload x = fromIntegral $ c_getnanf x
    
    minDenormal = 1e-45
    
    minNormal = 1.17549435e-38
    
    maxFinite = 3.40282347e+38
    
    epsilon = 1.19209290e-07
    
    copySign = c_copysignf
    
    succIEEE = c_ieeesuccf
    
    predIEEE = c_ieeepredf
    
    bisectIEEE = c_ieeemeanf
    
    sameSignificandBits = c_feqrelf
    
instance IEEE CFloat where
    identicalIEEE x y = c_identicalf (realToFrac x) (realToFrac y) /= 0
    
    infinity = 1/0
    
    nan = (0/0)
    
    nanWithPayload n = realToFrac $ c_mknanf (fromIntegral n)
    
    maxNaNPayload _ = 0x003FFFFF
    
    nanPayload x = fromIntegral $ c_getnanf (realToFrac x)
    
    minDenormal = 1e-45
    
    minNormal = 1.17549435e-38
    
    maxFinite = 3.40282347e+38
    
    epsilon = 1.19209290e-07
    
    copySign x y = realToFrac $ c_copysignf (realToFrac x) (realToFrac y)
    
    succIEEE x = realToFrac $ c_ieeesuccf (realToFrac x)
    
    predIEEE x = realToFrac $ c_ieeepredf (realToFrac x)
    
    bisectIEEE x y = realToFrac $ c_ieeemeanf (realToFrac x) (realToFrac y)
    
    sameSignificandBits x y = c_feqrelf (realToFrac x) (realToFrac y)
    
instance IEEE Double where
    identicalIEEE x y = c_identical x y /= 0
    
    infinity = 1/0
    
    nan = (0/0)
    
    nanWithPayload n = c_mknan n
    
    maxNaNPayload _ = 0x0007FFFFFFFFFFFF
    
    nanPayload x = c_getnan x
    
    minDenormal = 5e-324
    
    minNormal = 2.2250738585072014e-308
    
    maxFinite = 1.7976931348623157e+308
    
    epsilon = 2.2204460492503131e-16
    
    copySign = c_copysign
    
    succIEEE = c_ieeesucc
    
    predIEEE = c_ieeepred
    
    bisectIEEE = c_ieeemean
    
    sameSignificandBits = c_feqrel
    
instance IEEE CDouble where
    identicalIEEE x y = c_identical (realToFrac x) (realToFrac y) /= 0
    
    infinity = 1/0
    
    nan = (0/0)
    
    nanWithPayload n = realToFrac $ c_mknan n
    
    maxNaNPayload _ = 0x0007FFFFFFFFFFFF
    
    nanPayload x = c_getnan (realToFrac x)
    
    minDenormal = 5e-324
    
    minNormal = 2.2250738585072014e-308
    
    maxFinite = 1.7976931348623157e+308
    
    epsilon = 2.2204460492503131e-16
    
    succIEEE x = realToFrac $ c_ieeesucc (realToFrac x)
    
    copySign x y = realToFrac $ c_copysign (realToFrac x) (realToFrac y)
    
    predIEEE x = realToFrac $ c_ieeepred (realToFrac x)
    
    bisectIEEE x y = realToFrac $ c_ieeemean (realToFrac x) (realToFrac y)
    
    sameSignificandBits x y = c_feqrel (realToFrac x) (realToFrac y)
    
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