{-# LANGUAGE CPP #-}
{-# LANGUAGE NoImplicitPrelude #-}
module Numeric.Floating.IEEE.Internal.MinMax where
import           MyPrelude

default ()

-- |
-- IEEE 754 @minimum@ operation.
-- @-0@ is smaller than @+0@.
-- Propagates NaNs.
minimum' :: RealFloat a => a -> a -> a
minimum' :: forall a. RealFloat a => a -> a -> a
minimum' a
x a
y | forall a. RealFloat a => a -> Bool
isNaN a
x = a
x forall a. Num a => a -> a -> a
+ a
x
             | forall a. RealFloat a => a -> Bool
isNaN a
y = a
y forall a. Num a => a -> a -> a
+ a
y
             | a
x forall a. Ord a => a -> a -> Bool
< a
y Bool -> Bool -> Bool
|| (a
x forall a. Eq a => a -> a -> Bool
== a
y Bool -> Bool -> Bool
&& forall a. RealFloat a => a -> Bool
isNegativeZero a
x) = a
x
             | Bool
otherwise = a
y
{-# NOINLINE [1] minimum' #-}

-- |
-- IEEE 754 @minimumNumber@ operation.
-- @-0@ is smaller than @+0@.
-- Treats NaNs as missing data.
minimumNumber :: RealFloat a => a -> a -> a
minimumNumber :: forall a. RealFloat a => a -> a -> a
minimumNumber a
x a
y | forall a. RealFloat a => a -> Bool
isNaN a
x Bool -> Bool -> Bool
&& forall a. RealFloat a => a -> Bool
isNaN a
y = a
x forall a. Num a => a -> a -> a
+ a
x
                  | a
x forall a. Ord a => a -> a -> Bool
< a
y Bool -> Bool -> Bool
|| forall a. RealFloat a => a -> Bool
isNaN a
y Bool -> Bool -> Bool
|| (a
x forall a. Eq a => a -> a -> Bool
== a
y Bool -> Bool -> Bool
&& forall a. RealFloat a => a -> Bool
isNegativeZero a
x) = a
x
                  | Bool
otherwise = a
y
{-# NOINLINE [1] minimumNumber #-}

-- |
-- IEEE 754 @maximum@ operation.
-- @-0@ is smaller than @+0@.
-- Propagates NaNs.
maximum' :: RealFloat a => a -> a -> a
maximum' :: forall a. RealFloat a => a -> a -> a
maximum' a
x a
y | forall a. RealFloat a => a -> Bool
isNaN a
x = a
x forall a. Num a => a -> a -> a
+ a
x
             | forall a. RealFloat a => a -> Bool
isNaN a
y = a
y forall a. Num a => a -> a -> a
+ a
y
             | a
x forall a. Ord a => a -> a -> Bool
< a
y Bool -> Bool -> Bool
|| (a
x forall a. Eq a => a -> a -> Bool
== a
y Bool -> Bool -> Bool
&& forall a. RealFloat a => a -> Bool
isNegativeZero a
x) = a
y
             | Bool
otherwise = a
x
{-# NOINLINE [1] maximum' #-}

-- |
-- IEEE 754 @maximumNumber@ operation.
-- @-0@ is smaller than @+0@.
-- Treats NaNs as missing data.
maximumNumber :: RealFloat a => a -> a -> a
maximumNumber :: forall a. RealFloat a => a -> a -> a
maximumNumber a
x a
y | forall a. RealFloat a => a -> Bool
isNaN a
x Bool -> Bool -> Bool
&& forall a. RealFloat a => a -> Bool
isNaN a
y = a
x forall a. Num a => a -> a -> a
+ a
x
                  | a
x forall a. Ord a => a -> a -> Bool
< a
y 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
y Bool -> Bool -> Bool
&& forall a. RealFloat a => a -> Bool
isNegativeZero a
x) = a
y
                  | Bool
otherwise = a
x
{-# NOINLINE [1] maximumNumber #-}

-- |
-- IEEE 754 @minimumMagnitude@ operation.
minimumMagnitude :: RealFloat a => a -> a -> a
minimumMagnitude :: forall a. RealFloat a => a -> a -> a
minimumMagnitude a
x a
y | forall a. Num a => a -> a
abs a
x forall a. Ord a => a -> a -> Bool
< forall a. Num a => a -> a
abs a
y = a
x
                     | forall a. Num a => a -> a
abs a
y forall a. Ord a => a -> a -> Bool
< forall a. Num a => a -> a
abs a
x = a
y
                     | Bool
otherwise = forall a. RealFloat a => a -> a -> a
minimum' a
x a
y

-- |
-- IEEE 754 @minimumMagnitudeNumber@ operation.
minimumMagnitudeNumber :: RealFloat a => a -> a -> a
minimumMagnitudeNumber :: forall a. RealFloat a => a -> a -> a
minimumMagnitudeNumber a
x a
y | forall a. Num a => a -> a
abs a
x forall a. Ord a => a -> a -> Bool
< forall a. Num a => a -> a
abs a
y = a
x
                           | forall a. Num a => a -> a
abs a
y forall a. Ord a => a -> a -> Bool
< forall a. Num a => a -> a
abs a
x = a
y
                           | Bool
otherwise = forall a. RealFloat a => a -> a -> a
minimumNumber a
x a
y

-- |
-- IEEE 754 @maximumMagnitude@ operation.
maximumMagnitude :: RealFloat a => a -> a -> a
maximumMagnitude :: forall a. RealFloat a => a -> a -> a
maximumMagnitude a
x a
y | forall a. Num a => a -> a
abs a
x forall a. Ord a => a -> a -> Bool
> forall a. Num a => a -> a
abs a
y = a
x
                     | forall a. Num a => a -> a
abs a
y forall a. Ord a => a -> a -> Bool
> forall a. Num a => a -> a
abs a
x = a
y
                     | Bool
otherwise = forall a. RealFloat a => a -> a -> a
maximum' a
x a
y

-- |
-- IEEE 754 @maximumMagnitudeNumber@ operation.
maximumMagnitudeNumber :: RealFloat a => a -> a -> a
maximumMagnitudeNumber :: forall a. RealFloat a => a -> a -> a
maximumMagnitudeNumber a
x a
y | forall a. Num a => a -> a
abs a
x forall a. Ord a => a -> a -> Bool
> forall a. Num a => a -> a
abs a
y = a
x
                           | forall a. Num a => a -> a
abs a
y forall a. Ord a => a -> a -> Bool
> forall a. Num a => a -> a
abs a
x = a
y
                           | Bool
otherwise = forall a. RealFloat a => a -> a -> a
maximumNumber a
x a
y

#if defined(HAS_FAST_MINMAX)

foreign import ccall unsafe "hs_minimumFloat"
  minimumFloat :: Float -> Float -> Float
foreign import ccall unsafe "hs_maximumFloat"
  maximumFloat :: Float -> Float -> Float
foreign import ccall unsafe "hs_minimumNumberFloat"
  minimumNumberFloat :: Float -> Float -> Float
foreign import ccall unsafe "hs_maximumNumberFloat"
  maximumNumberFloat :: Float -> Float -> Float
foreign import ccall unsafe "hs_minimumDouble"
  minimumDouble :: Double -> Double -> Double
foreign import ccall unsafe "hs_maximumDouble"
  maximumDouble :: Double -> Double -> Double
foreign import ccall unsafe "hs_minimumNumberDouble"
  minimumNumberDouble :: Double -> Double -> Double
foreign import ccall unsafe "hs_maximumNumberDouble"
  maximumNumberDouble :: Double -> Double -> Double

{-# RULES
"minimum'/Float" minimum' = minimumFloat
"maximum'/Float" maximum' = maximumFloat
"minimumNumber/Float" minimumNumber = minimumNumberFloat
"maximumNumber/Float" maximumNumber = maximumNumberFloat
"minimum'/Double" minimum' = minimumDouble
"maximum'/Double" maximum' = maximumDouble
"minimumNumber/Double" minimumNumber = minimumNumberDouble
"maximumNumber/Double" maximumNumber = maximumNumberDouble
  #-}

#else

minimumFloat :: Float -> Float -> Float
maximumFloat :: Float -> Float -> Float
minimumNumberFloat :: Float -> Float -> Float
maximumNumberFloat :: Float -> Float -> Float
minimumDouble :: Double -> Double -> Double
maximumDouble :: Double -> Double -> Double
minimumNumberDouble :: Double -> Double -> Double
maximumNumberDouble :: Double -> Double -> Double

minimumFloat :: Float -> Float -> Float
minimumFloat = forall a. RealFloat a => a -> a -> a
minimum'
minimumDouble :: Double -> Double -> Double
minimumDouble = forall a. RealFloat a => a -> a -> a
minimum'
minimumNumberFloat :: Float -> Float -> Float
minimumNumberFloat = forall a. RealFloat a => a -> a -> a
minimumNumber
minimumNumberDouble :: Double -> Double -> Double
minimumNumberDouble = forall a. RealFloat a => a -> a -> a
minimumNumber
maximumFloat :: Float -> Float -> Float
maximumFloat = forall a. RealFloat a => a -> a -> a
maximum'
maximumDouble :: Double -> Double -> Double
maximumDouble = forall a. RealFloat a => a -> a -> a
maximum'
maximumNumberFloat :: Float -> Float -> Float
maximumNumberFloat = forall a. RealFloat a => a -> a -> a
maximumNumber
maximumNumberDouble :: Double -> Double -> Double
maximumNumberDouble = forall a. RealFloat a => a -> a -> a
maximumNumber

#endif