{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE DeriveFunctor #-}
{-# LANGUAGE NoImplicitPrelude #-}
module Numeric.Floating.IEEE.Internal.Rounding.Common where
import Control.Exception (assert)
import Data.Bits
import Data.Functor.Product
import Data.Int
import GHC.Float (expt)
import Math.NumberTheory.Logarithms (integerLog2')
import MyPrelude
import Numeric.Floating.IEEE.Internal.IntegerInternals
default ()
class Functor f => RoundingStrategy f where
exact :: a -> f a
inexact :: Ordering
-> Bool
-> Int
-> a
-> a
-> f a
doRound :: Bool
-> Ordering
-> Bool
-> Int
-> a
-> a
-> f a
exact a
x = forall (f :: * -> *) a.
RoundingStrategy f =>
Bool -> Ordering -> Bool -> Int -> a -> a -> f a
doRound Bool
True Ordering
LT Bool
False Int
0 a
x a
x
inexact Ordering
o Bool
neg Int
parity a
zero a
away = forall (f :: * -> *) a.
RoundingStrategy f =>
Bool -> Ordering -> Bool -> Int -> a -> a -> f a
doRound Bool
False Ordering
o Bool
neg Int
parity a
zero a
away
newtype RoundTiesToEven a = RoundTiesToEven { forall a. RoundTiesToEven a -> a
roundTiesToEven :: a }
deriving (forall a b. a -> RoundTiesToEven b -> RoundTiesToEven a
forall a b. (a -> b) -> RoundTiesToEven a -> RoundTiesToEven b
forall (f :: * -> *).
(forall a b. (a -> b) -> f a -> f b)
-> (forall a b. a -> f b -> f a) -> Functor f
<$ :: forall a b. a -> RoundTiesToEven b -> RoundTiesToEven a
$c<$ :: forall a b. a -> RoundTiesToEven b -> RoundTiesToEven a
fmap :: forall a b. (a -> b) -> RoundTiesToEven a -> RoundTiesToEven b
$cfmap :: forall a b. (a -> b) -> RoundTiesToEven a -> RoundTiesToEven b
Functor)
instance RoundingStrategy RoundTiesToEven where
exact :: forall a. a -> RoundTiesToEven a
exact = forall a. a -> RoundTiesToEven a
RoundTiesToEven
inexact :: forall a. Ordering -> Bool -> Int -> a -> a -> RoundTiesToEven a
inexact Ordering
o Bool
_neg Int
parity a
zero a
away = forall a. a -> RoundTiesToEven a
RoundTiesToEven forall a b. (a -> b) -> a -> b
$ case Ordering
o of
Ordering
LT -> a
zero
Ordering
EQ | forall a. Integral a => a -> Bool
even Int
parity -> a
zero
| Bool
otherwise -> a
away
Ordering
GT -> a
away
doRound :: forall a.
Bool -> Ordering -> Bool -> Int -> a -> a -> RoundTiesToEven a
doRound Bool
_ex Ordering
o Bool
_neg Int
parity a
zero a
away = forall a. a -> RoundTiesToEven a
RoundTiesToEven forall a b. (a -> b) -> a -> b
$ case Ordering
o of
Ordering
LT -> a
zero
Ordering
EQ | forall a. Integral a => a -> Bool
even Int
parity -> a
zero
| Bool
otherwise -> a
away
Ordering
GT -> a
away
{-# INLINE exact #-}
{-# INLINE inexact #-}
{-# INLINE doRound #-}
newtype RoundTiesToAway a = RoundTiesToAway { forall a. RoundTiesToAway a -> a
roundTiesToAway :: a }
deriving (forall a b. a -> RoundTiesToAway b -> RoundTiesToAway a
forall a b. (a -> b) -> RoundTiesToAway a -> RoundTiesToAway b
forall (f :: * -> *).
(forall a b. (a -> b) -> f a -> f b)
-> (forall a b. a -> f b -> f a) -> Functor f
<$ :: forall a b. a -> RoundTiesToAway b -> RoundTiesToAway a
$c<$ :: forall a b. a -> RoundTiesToAway b -> RoundTiesToAway a
fmap :: forall a b. (a -> b) -> RoundTiesToAway a -> RoundTiesToAway b
$cfmap :: forall a b. (a -> b) -> RoundTiesToAway a -> RoundTiesToAway b
Functor)
instance RoundingStrategy RoundTiesToAway where
exact :: forall a. a -> RoundTiesToAway a
exact = forall a. a -> RoundTiesToAway a
RoundTiesToAway
inexact :: forall a. Ordering -> Bool -> Int -> a -> a -> RoundTiesToAway a
inexact Ordering
o Bool
_neg Int
_parity a
zero a
away = forall a. a -> RoundTiesToAway a
RoundTiesToAway forall a b. (a -> b) -> a -> b
$ case Ordering
o of
Ordering
LT -> a
zero
Ordering
EQ -> a
away
Ordering
GT -> a
away
doRound :: forall a.
Bool -> Ordering -> Bool -> Int -> a -> a -> RoundTiesToAway a
doRound Bool
_ex Ordering
o Bool
_neg Int
_parity a
zero a
away = forall a. a -> RoundTiesToAway a
RoundTiesToAway forall a b. (a -> b) -> a -> b
$ case Ordering
o of
Ordering
LT -> a
zero
Ordering
EQ -> a
away
Ordering
GT -> a
away
{-# INLINE exact #-}
{-# INLINE inexact #-}
{-# INLINE doRound #-}
newtype RoundTowardPositive a = RoundTowardPositive { forall a. RoundTowardPositive a -> a
roundTowardPositive :: a }
deriving (forall a b. a -> RoundTowardPositive b -> RoundTowardPositive a
forall a b.
(a -> b) -> RoundTowardPositive a -> RoundTowardPositive b
forall (f :: * -> *).
(forall a b. (a -> b) -> f a -> f b)
-> (forall a b. a -> f b -> f a) -> Functor f
<$ :: forall a b. a -> RoundTowardPositive b -> RoundTowardPositive a
$c<$ :: forall a b. a -> RoundTowardPositive b -> RoundTowardPositive a
fmap :: forall a b.
(a -> b) -> RoundTowardPositive a -> RoundTowardPositive b
$cfmap :: forall a b.
(a -> b) -> RoundTowardPositive a -> RoundTowardPositive b
Functor)
instance RoundingStrategy RoundTowardPositive where
exact :: forall a. a -> RoundTowardPositive a
exact = forall a. a -> RoundTowardPositive a
RoundTowardPositive
inexact :: forall a.
Ordering -> Bool -> Int -> a -> a -> RoundTowardPositive a
inexact Ordering
_o Bool
neg Int
_parity a
zero a
away | Bool
neg = forall a. a -> RoundTowardPositive a
RoundTowardPositive a
zero
| Bool
otherwise = forall a. a -> RoundTowardPositive a
RoundTowardPositive a
away
doRound :: forall a.
Bool -> Ordering -> Bool -> Int -> a -> a -> RoundTowardPositive a
doRound Bool
ex Ordering
_o Bool
neg Int
_parity a
zero a
away | Bool
ex Bool -> Bool -> Bool
|| Bool
neg = forall a. a -> RoundTowardPositive a
RoundTowardPositive a
zero
| Bool
otherwise = forall a. a -> RoundTowardPositive a
RoundTowardPositive a
away
{-# INLINE exact #-}
{-# INLINE inexact #-}
{-# INLINE doRound #-}
newtype RoundTowardNegative a = RoundTowardNegative { forall a. RoundTowardNegative a -> a
roundTowardNegative :: a }
deriving (forall a b. a -> RoundTowardNegative b -> RoundTowardNegative a
forall a b.
(a -> b) -> RoundTowardNegative a -> RoundTowardNegative b
forall (f :: * -> *).
(forall a b. (a -> b) -> f a -> f b)
-> (forall a b. a -> f b -> f a) -> Functor f
<$ :: forall a b. a -> RoundTowardNegative b -> RoundTowardNegative a
$c<$ :: forall a b. a -> RoundTowardNegative b -> RoundTowardNegative a
fmap :: forall a b.
(a -> b) -> RoundTowardNegative a -> RoundTowardNegative b
$cfmap :: forall a b.
(a -> b) -> RoundTowardNegative a -> RoundTowardNegative b
Functor)
instance RoundingStrategy RoundTowardNegative where
exact :: forall a. a -> RoundTowardNegative a
exact = forall a. a -> RoundTowardNegative a
RoundTowardNegative
inexact :: forall a.
Ordering -> Bool -> Int -> a -> a -> RoundTowardNegative a
inexact Ordering
_o Bool
neg Int
_parity a
zero a
away | Bool
neg = forall a. a -> RoundTowardNegative a
RoundTowardNegative a
away
| Bool
otherwise = forall a. a -> RoundTowardNegative a
RoundTowardNegative a
zero
doRound :: forall a.
Bool -> Ordering -> Bool -> Int -> a -> a -> RoundTowardNegative a
doRound Bool
ex Ordering
_o Bool
neg Int
_parity a
zero a
away | Bool -> Bool
not Bool
ex Bool -> Bool -> Bool
&& Bool
neg = forall a. a -> RoundTowardNegative a
RoundTowardNegative a
away
| Bool
otherwise = forall a. a -> RoundTowardNegative a
RoundTowardNegative a
zero
{-# INLINE exact #-}
{-# INLINE inexact #-}
{-# INLINE doRound #-}
newtype RoundTowardZero a = RoundTowardZero { forall a. RoundTowardZero a -> a
roundTowardZero :: a }
deriving (forall a b. a -> RoundTowardZero b -> RoundTowardZero a
forall a b. (a -> b) -> RoundTowardZero a -> RoundTowardZero b
forall (f :: * -> *).
(forall a b. (a -> b) -> f a -> f b)
-> (forall a b. a -> f b -> f a) -> Functor f
<$ :: forall a b. a -> RoundTowardZero b -> RoundTowardZero a
$c<$ :: forall a b. a -> RoundTowardZero b -> RoundTowardZero a
fmap :: forall a b. (a -> b) -> RoundTowardZero a -> RoundTowardZero b
$cfmap :: forall a b. (a -> b) -> RoundTowardZero a -> RoundTowardZero b
Functor)
instance RoundingStrategy RoundTowardZero where
exact :: forall a. a -> RoundTowardZero a
exact = forall a. a -> RoundTowardZero a
RoundTowardZero
inexact :: forall a. Ordering -> Bool -> Int -> a -> a -> RoundTowardZero a
inexact Ordering
_o Bool
_neg Int
_parity a
zero a
_away = forall a. a -> RoundTowardZero a
RoundTowardZero a
zero
doRound :: forall a.
Bool -> Ordering -> Bool -> Int -> a -> a -> RoundTowardZero a
doRound Bool
_ex Ordering
_o Bool
_neg Int
_parity a
zero a
_away = forall a. a -> RoundTowardZero a
RoundTowardZero a
zero
{-# INLINE exact #-}
{-# INLINE inexact #-}
{-# INLINE doRound #-}
instance (RoundingStrategy f, RoundingStrategy g) => RoundingStrategy (Product f g) where
exact :: forall a. a -> Product f g a
exact a
x = forall {k} (f :: k -> *) (g :: k -> *) (a :: k).
f a -> g a -> Product f g a
Pair (forall (f :: * -> *) a. RoundingStrategy f => a -> f a
exact a
x) (forall (f :: * -> *) a. RoundingStrategy f => a -> f a
exact a
x)
inexact :: forall a. Ordering -> Bool -> Int -> a -> a -> Product f g a
inexact Ordering
o Bool
neg Int
parity a
zero a
away = forall {k} (f :: k -> *) (g :: k -> *) (a :: k).
f a -> g a -> Product f g a
Pair (forall (f :: * -> *) a.
RoundingStrategy f =>
Ordering -> Bool -> Int -> a -> a -> f a
inexact Ordering
o Bool
neg Int
parity a
zero a
away) (forall (f :: * -> *) a.
RoundingStrategy f =>
Ordering -> Bool -> Int -> a -> a -> f a
inexact Ordering
o Bool
neg Int
parity a
zero a
away)
doRound :: forall a.
Bool -> Ordering -> Bool -> Int -> a -> a -> Product f g a
doRound Bool
ex Ordering
o Bool
neg Int
parity a
zero a
away = forall {k} (f :: k -> *) (g :: k -> *) (a :: k).
f a -> g a -> Product f g a
Pair (forall (f :: * -> *) a.
RoundingStrategy f =>
Bool -> Ordering -> Bool -> Int -> a -> a -> f a
doRound Bool
ex Ordering
o Bool
neg Int
parity a
zero a
away) (forall (f :: * -> *) a.
RoundingStrategy f =>
Bool -> Ordering -> Bool -> Int -> a -> a -> f a
doRound Bool
ex Ordering
o Bool
neg Int
parity a
zero a
away)
{-# INLINE exact #-}
{-# INLINE inexact #-}
{-# INLINE doRound #-}
quotRemByExpt :: Integer
-> Integer
-> Int
-> (Integer, Integer)
quotRemByExpt :: Integer -> Integer -> Int -> (Integer, Integer)
quotRemByExpt Integer
x Integer
2 Int
n = forall a. (?callStack::CallStack) => Bool -> a -> a
assert (Int
n forall a. Ord a => a -> a -> Bool
>= Int
0) (Integer
x Integer -> Int -> Integer
`unsafeShiftRInteger` Int
n, Integer
x forall a. Bits a => a -> a -> a
.&. (forall a. Bits a => Int -> a
bit Int
n forall a. Num a => a -> a -> a
- Integer
1))
quotRemByExpt Integer
x Integer
base Int
n = Integer
x forall a. Integral a => a -> a -> (a, a)
`quotRem` Integer -> Int -> Integer
expt Integer
base Int
n
{-# INLINE quotRemByExpt #-}
multiplyByExpt :: Integer
-> Integer
-> Int
-> Integer
multiplyByExpt :: Integer -> Integer -> Int -> Integer
multiplyByExpt Integer
x Integer
2 Int
n = forall a. (?callStack::CallStack) => Bool -> a -> a
assert (Int
n forall a. Ord a => a -> a -> Bool
>= Int
0) (Integer
x Integer -> Int -> Integer
`unsafeShiftLInteger` Int
n)
multiplyByExpt Integer
x Integer
base Int
n = Integer
x forall a. Num a => a -> a -> a
* Integer -> Int -> Integer
expt Integer
base Int
n
{-# INLINE multiplyByExpt #-}
isDivisibleByExpt :: Integer
-> Integer
-> Int
-> Integer
-> Bool
isDivisibleByExpt :: Integer -> Integer -> Int -> Integer -> Bool
isDivisibleByExpt Integer
x Integer
2 Int
e Integer
r = forall a. (?callStack::CallStack) => Bool -> a -> a
assert (Integer
r forall a. Eq a => a -> a -> Bool
== Integer
x forall a. Integral a => a -> a -> a
`rem` (Integer
2 forall a b. (Num a, Integral b) => a -> b -> a
^ Int
e)) forall a b. (a -> b) -> a -> b
$ Integer
x forall a. Eq a => a -> a -> Bool
== Integer
0 Bool -> Bool -> Bool
|| Integer -> Int
Numeric.Floating.IEEE.Internal.IntegerInternals.countTrailingZerosInteger Integer
x forall a. Ord a => a -> a -> Bool
>= Int
e
isDivisibleByExpt Integer
x Integer
base Int
e Integer
r = forall a. (?callStack::CallStack) => Bool -> a -> a
assert (Integer
r forall a. Eq a => a -> a -> Bool
== Integer
x forall a. Integral a => a -> a -> a
`rem` (Integer
base forall a b. (Num a, Integral b) => a -> b -> a
^ Int
e)) (Integer
r forall a. Eq a => a -> a -> Bool
== Integer
0)
{-# INLINE isDivisibleByExpt #-}
compareWithExpt :: Integer
-> Integer
-> Integer
-> Int
-> Ordering
compareWithExpt :: Integer -> Integer -> Integer -> Int -> Ordering
compareWithExpt Integer
2 Integer
n Integer
r Int
e = forall a. (?callStack::CallStack) => Bool -> a -> a
assert (Integer
r forall a. Eq a => a -> a -> Bool
== Integer
n forall a. Integral a => a -> a -> a
`rem` Integer -> Int -> Integer
expt Integer
2 (Int
eforall a. Num a => a -> a -> a
+Int
1)) forall a b. (a -> b) -> a -> b
$
if Integer
n forall a. Eq a => a -> a -> Bool
== Integer
0 Bool -> Bool -> Bool
|| Integer -> Int
integerLog2' Integer
n forall a. Ord a => a -> a -> Bool
< Int
e then
Ordering
LT
else
let result :: Ordering
result = Integer -> Int -> Ordering
Numeric.Floating.IEEE.Internal.IntegerInternals.roundingMode Integer
n Int
e
!()
_ = forall a. (?callStack::CallStack) => Bool -> a -> a
assert (Ordering
result forall a. Eq a => a -> a -> Bool
== forall a. Ord a => a -> a -> Ordering
compare Integer
r (Integer -> Int -> Integer
expt Integer
2 Int
e)) ()
in Ordering
result
compareWithExpt Integer
base Integer
n Integer
r Int
e = forall a. (?callStack::CallStack) => Bool -> a -> a
assert (Integer
r forall a. Eq a => a -> a -> Bool
== Integer
n forall a. Integral a => a -> a -> a
`rem` Integer -> Int -> Integer
expt Integer
base (Int
eforall a. Num a => a -> a -> a
+Int
1)) forall a b. (a -> b) -> a -> b
$ forall a. Ord a => a -> a -> Ordering
compare Integer
r (Integer -> Int -> Integer
expt Integer
base Int
e)
{-# INLINE compareWithExpt #-}