{-# LANGUAGE CPP #-}
{-# LANGUAGE NoImplicitPrelude #-}
module Numeric.Floating.IEEE.Internal.RoundToIntegral
( round'
, roundAway'
, truncate'
, ceiling'
, floor'
, round
, roundAway
, truncate
, ceiling
, floor
) where
import MyPrelude
#if defined(USE_FFI) && defined(SOME_LIBC_FUNCTIONS_MIGHT_BE_BUGGY)
import Numeric.Floating.IEEE.Internal.Conversion
#endif
default ()
round' :: RealFloat a => a -> a
round' :: forall a. RealFloat a => a -> a
round' a
x | a -> Bool
forall a. RealFloat a => a -> Bool
isInfinite a
x Bool -> Bool -> Bool
|| a -> Bool
forall a. RealFloat a => a -> Bool
isNaN a
x Bool -> Bool -> Bool
|| a -> Bool
forall a. RealFloat a => a -> Bool
isNegativeZero a
x = a
x a -> a -> a
forall a. Num a => a -> a -> a
+ a
x
round' a
x = case a -> Integer
forall b. Integral b => a -> b
forall a b. (RealFrac a, Integral b) => a -> b
round a
x of
Integer
0 | a
x a -> a -> Bool
forall a. Ord a => a -> a -> Bool
< a
0 -> -a
0
| Bool
otherwise -> a
0
Integer
n -> Integer -> a
forall a. Num a => Integer -> a
fromInteger Integer
n
{-# NOINLINE [1] round' #-}
roundAway' :: RealFloat a => a -> a
roundAway' :: forall a. RealFloat a => a -> a
roundAway' a
x | a -> Bool
forall a. RealFloat a => a -> Bool
isInfinite a
x Bool -> Bool -> Bool
|| a -> Bool
forall a. RealFloat a => a -> Bool
isNaN a
x Bool -> Bool -> Bool
|| a -> Bool
forall a. RealFloat a => a -> Bool
isNegativeZero a
x = a
x a -> a -> a
forall a. Num a => a -> a -> a
+ a
x
roundAway' a
x = case a -> (Integer, a)
forall b. Integral b => a -> (b, a)
forall a b. (RealFrac a, Integral b) => a -> (b, a)
properFraction a
x of
(Integer
n,a
r) -> if a -> a
forall a. Num a => a -> a
abs a
r a -> a -> Bool
forall a. Ord a => a -> a -> Bool
< a
0.5 then
if Integer
n Integer -> Integer -> Bool
forall a. Eq a => a -> a -> Bool
== Integer
0 then
a
0.0 a -> a -> a
forall a. Num a => a -> a -> a
* a
r
else
Integer -> a
forall a. Num a => Integer -> a
fromInteger Integer
n
else
if a
r a -> a -> Bool
forall a. Ord a => a -> a -> Bool
< a
0 then
Integer -> a
forall a. Num a => Integer -> a
fromInteger (Integer
n Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
- Integer
1)
else
Integer -> a
forall a. Num a => Integer -> a
fromInteger (Integer
n Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
+ Integer
1)
{-# NOINLINE [1] roundAway' #-}
truncate' :: RealFloat a => a -> a
truncate' :: forall a. RealFloat a => a -> a
truncate' a
x | a -> Bool
forall a. RealFloat a => a -> Bool
isInfinite a
x Bool -> Bool -> Bool
|| a -> Bool
forall a. RealFloat a => a -> Bool
isNaN a
x Bool -> Bool -> Bool
|| a -> Bool
forall a. RealFloat a => a -> Bool
isNegativeZero a
x = a
x a -> a -> a
forall a. Num a => a -> a -> a
+ a
x
truncate' a
x = case a -> Integer
forall b. Integral b => a -> b
forall a b. (RealFrac a, Integral b) => a -> b
truncate a
x of
Integer
0 | a
x a -> a -> Bool
forall a. Ord a => a -> a -> Bool
< a
0 -> -a
0
| Bool
otherwise -> a
0
Integer
n -> Integer -> a
forall a. Num a => Integer -> a
fromInteger Integer
n
{-# NOINLINE [1] truncate' #-}
ceiling' :: RealFloat a => a -> a
ceiling' :: forall a. RealFloat a => a -> a
ceiling' a
x | a -> Bool
forall a. RealFloat a => a -> Bool
isInfinite a
x Bool -> Bool -> Bool
|| a -> Bool
forall a. RealFloat a => a -> Bool
isNaN a
x Bool -> Bool -> Bool
|| a -> Bool
forall a. RealFloat a => a -> Bool
isNegativeZero a
x = a
x a -> a -> a
forall a. Num a => a -> a -> a
+ a
x
ceiling' a
x = case a -> Integer
forall b. Integral b => a -> b
forall a b. (RealFrac a, Integral b) => a -> b
ceiling a
x of
Integer
0 | a
x a -> a -> Bool
forall a. Ord a => a -> a -> Bool
< a
0 -> -a
0
| Bool
otherwise -> a
0
Integer
n -> Integer -> a
forall a. Num a => Integer -> a
fromInteger Integer
n
{-# NOINLINE [1] ceiling' #-}
floor' :: RealFloat a => a -> a
floor' :: forall a. RealFloat a => a -> a
floor' a
x | a -> Bool
forall a. RealFloat a => a -> Bool
isInfinite a
x Bool -> Bool -> Bool
|| a -> Bool
forall a. RealFloat a => a -> Bool
isNaN a
x Bool -> Bool -> Bool
|| a -> Bool
forall a. RealFloat a => a -> Bool
isNegativeZero a
x = a
x a -> a -> a
forall a. Num a => a -> a -> a
+ a
x
| Bool
otherwise = Integer -> a
forall a. Num a => Integer -> a
fromInteger (a -> Integer
forall b. Integral b => a -> b
forall a b. (RealFrac a, Integral b) => a -> b
floor a
x)
{-# NOINLINE [1] floor' #-}
roundAway :: (RealFrac a, Integral b) => a -> b
roundAway :: forall a b. (RealFrac a, Integral b) => a -> b
roundAway a
x = case a -> (b, a)
forall b. Integral b => a -> (b, a)
forall a b. (RealFrac a, Integral b) => a -> (b, a)
properFraction a
x of
(b
n,a
r) -> if a -> a
forall a. Num a => a -> a
abs a
r a -> a -> Bool
forall a. Ord a => a -> a -> Bool
< a
0.5 then
b
n
else
if a
r a -> a -> Bool
forall a. Ord a => a -> a -> Bool
< a
0 then
b
n b -> b -> b
forall a. Num a => a -> a -> a
- b
1
else
b
n b -> b -> b
forall a. Num a => a -> a -> a
+ b
1
{-# INLINE roundAway #-}
#ifdef USE_FFI
foreign import ccall unsafe "ceilf"
c_ceilFloat :: Float -> Float
foreign import ccall unsafe "ceil"
c_ceilDouble :: Double -> Double
foreign import ccall unsafe "floorf"
c_floorFloat :: Float -> Float
foreign import ccall unsafe "floor"
c_floorDouble :: Double -> Double
foreign import ccall unsafe "roundf"
c_roundFloat :: Float -> Float
foreign import ccall unsafe "round"
c_roundDouble :: Double -> Double
foreign import ccall unsafe "truncf"
c_truncFloat :: Float -> Float
foreign import ccall unsafe "trunc"
c_truncDouble :: Double -> Double
#if defined(SOME_LIBC_FUNCTIONS_MIGHT_BE_BUGGY)
{-# RULES
"roundAway'/Float"
roundAway' = c_roundFloat . canonicalizeFloat
"roundAway'/Double"
roundAway' = c_roundDouble . canonicalizeDouble
"truncate'/Float"
truncate' = c_truncFloat
"truncate'/Double"
truncate' = c_truncDouble
"ceiling'/Float"
ceiling' = c_ceilFloat
"ceiling'/Double"
ceiling' = c_ceilDouble
"floor'/Float"
floor' = c_floorFloat
"floor'/Double"
floor' = c_floorDouble
#-}
#else
{-# RULES
"roundAway'/Float"
roundAway' = c_roundFloat
"roundAway'/Double"
roundAway' = c_roundDouble
"truncate'/Float"
truncate' = c_truncFloat
"truncate'/Double"
truncate' = c_truncDouble
"ceiling'/Float"
ceiling' = c_ceilFloat
"ceiling'/Double"
ceiling' = c_ceilDouble
"floor'/Float"
floor' = c_floorFloat
"floor'/Double"
floor' = c_floorDouble
#-}
#endif
#if defined(HAS_FAST_ROUNDEVEN)
foreign import ccall unsafe "hs_roundevenFloat"
c_roundevenFloat :: Float -> Float
foreign import ccall unsafe "hs_roundevenDouble"
c_roundevenDouble :: Double -> Double
{-# RULES
"round'/Float"
round' = c_roundevenFloat
"round'/Double"
round' = c_roundevenDouble
#-}
#endif
#endif