{-# LANGUAGE CPP #-}
{-# LANGUAGE NoImplicitPrelude #-}
module Numeric.Floating.IEEE.Internal.Remainder
  ( remainder
  ) where
import           MyPrelude
import           Numeric.Floating.IEEE.Internal.Classify

default ()

-- |
-- @'remainder' x y@ returns \(r=x-yn\), where \(n\) is the integer nearest the exact number \(x/y\); i.e. \(n=\mathrm{round}(x/y)\).
--
-- IEEE 754 @remainder@ operation.
remainder :: RealFloat a => a -> a -> a
remainder :: forall a. RealFloat a => a -> a -> a
remainder a
x a
y | a -> Bool
forall a. RealFloat a => a -> Bool
isFinite a
x Bool -> Bool -> Bool
&& a -> Bool
forall a. RealFloat a => a -> Bool
isInfinite a
y = a
x
              | 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
isInfinite a
y Bool -> Bool -> Bool
|| a -> Bool
forall a. RealFloat a => a -> Bool
isNaN a
y Bool -> Bool -> Bool
|| Bool -> Bool
not (a -> Bool
forall a. RealFloat a => a -> Bool
isFinite a
x) = (a
x a -> a -> a
forall a. Num a => a -> a -> a
- a
x) a -> a -> a
forall a. Fractional a => a -> a -> a
/ a
y a -> a -> a
forall a. Num a => a -> a -> a
* a
y -- return a NaN
              | Bool
otherwise = let n :: Integer
n = Rational -> Integer
forall b. Integral b => Rational -> b
forall a b. (RealFrac a, Integral b) => a -> b
round (a -> Rational
forall a. Real a => a -> Rational
toRational a
x Rational -> Rational -> Rational
forall a. Fractional a => a -> a -> a
/ a -> Rational
forall a. Real a => a -> Rational
toRational a
y)
                                r :: a
r = Rational -> a
forall a. Fractional a => Rational -> a
fromRational (a -> Rational
forall a. Real a => a -> Rational
toRational a
x Rational -> Rational -> Rational
forall a. Num a => a -> a -> a
- a -> Rational
forall a. Real a => a -> Rational
toRational a
y Rational -> Rational -> Rational
forall a. Num a => a -> a -> a
* Integer -> Rational
forall a. Num a => Integer -> a
fromInteger Integer
n)
                            in a
r -- if r == 0, the sign of r is the same as x
{-# NOINLINE [1] remainder #-}

#if defined(USE_FFI)

foreign import ccall unsafe "remainderf"
  c_remainderFloat :: Float -> Float -> Float
foreign import ccall unsafe "remainder"
  c_remainderDouble :: Double -> Double -> Double

{-# RULES
"remainder/Float" remainder = c_remainderFloat
"remainder/Double" remainder = c_remainderDouble
  #-}

#endif