{-
 - Copyright (C) 2009-2010 Nick Bowler.
 -
 - License BSD2:  2-clause BSD license.  See LICENSE for full terms.
 - This is free software: you are free to change and redistribute it.
 - There is NO WARRANTY, to the extent permitted by law.
 -}

-- | Top level module for alternative floating point support.
module Data.Floating (
    module Data.Floating.Classes,
    Double, Float,
    module Data.Floating,
    toFloating
) where

import Prelude hiding (RealFloat(..), RealFrac(..), Double, Float)
import Data.Floating.Classes
import Data.Floating.Instances
import Data.Floating.Types
import Data.Floating.Types.Double
import Data.Floating.Types.Float
import Data.Floating.Environment

import Control.Monad

isInfinite :: PrimFloat a => a -> Bool
isInfinite = (== FPInfinite) . classify

isNaN :: PrimFloat a => a -> Bool
isNaN = (== FPNaN) . classify

isNormal :: PrimFloat a => a -> Bool
isNormal = (== FPNormal) . classify

isSubNormal :: PrimFloat a => a -> Bool
isSubNormal = (== FPSubNormal) . classify

isFinite :: PrimFloat a => a -> Bool
isFinite = not . liftM2 (||) isInfinite isNaN

isNegativeZero :: PrimFloat a => a -> Bool
isNegativeZero = liftM2 (&&) ((== FPZero) . classify) ((== (-1)) . signum)

-- | @fquotRem x y@ computes the remainder and integral quotient upon division
-- of x by y.  The result is (x-n*y, n), where n is the value x/y rounded to
-- the nearest integer.
fquotRem :: RealFloat a => a -> a -> (a, a)
fquotRem x y = (frem x y, nearbyint (x/y))