{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE NoImplicitPrelude #-}
module Numeric.Floating.IEEE.Internal.Augmented where
import Control.Exception (assert)
import MyPrelude
import Numeric.Floating.IEEE.Internal.FMA (isMantissaEven,
twoProduct_nonscaling,
twoSum)
import Numeric.Floating.IEEE.Internal.NextFloat (nextDown,
nextTowardZero,
nextUp)
default ()
augmentedAddition :: RealFloat a => a -> a -> (a, a)
augmentedAddition :: a -> a -> (a, a)
augmentedAddition !a
x !a
y
| a -> Bool
forall a. RealFloat a => a -> Bool
isNaN a
x Bool -> Bool -> Bool
|| a -> Bool
forall a. RealFloat a => a -> Bool
isInfinite a
x Bool -> Bool -> Bool
|| a -> Bool
forall a. RealFloat a => a -> Bool
isNaN a
y Bool -> Bool -> Bool
|| a -> Bool
forall a. RealFloat a => a -> Bool
isInfinite a
y = let !result :: a
result = a
x a -> a -> a
forall a. Num a => a -> a -> a
+ a
y in (a
result, a
result)
| Bool
otherwise = let (a
u1, a
u2) = a -> a -> (a, a)
forall a. RealFloat a => a -> a -> (a, a)
twoSum a
x a
y
ulpTowardZero :: a
ulpTowardZero = a
u1 a -> a -> a
forall a. Num a => a -> a -> a
- a -> a
forall a. RealFloat a => a -> a
nextTowardZero a
u1
in if a -> Bool
forall a. RealFloat a => a -> Bool
isNaN a
u2 then
(a, a)
handleUndueOverflow
else
if a
u2 a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
0 then
(a
u1, a
0 a -> a -> a
forall a. Num a => a -> a -> a
* a
u1)
else
if (-a
2) a -> a -> a
forall a. Num a => a -> a -> a
* a
u2 a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
ulpTowardZero then
(a
u1 a -> a -> a
forall a. Num a => a -> a -> a
- a
ulpTowardZero, a
ulpTowardZero a -> a -> a
forall a. Num a => a -> a -> a
+ a
u2)
else
(a
u1, a
u2)
where
handleUndueOverflow :: (a, a)
handleUndueOverflow =
let e :: Int
e = Int -> Int -> Int
forall a. Ord a => a -> a -> a
max (a -> Int
forall a. RealFloat a => a -> Int
exponent a
x) (a -> Int
forall a. RealFloat a => a -> Int
exponent a
y)
x' :: a
x' = Int -> a -> a
forall a. RealFloat a => Int -> a -> a
scaleFloat (- Int
e) a
x
y' :: a
y' = Int -> a -> a
forall a. RealFloat a => Int -> a -> a
scaleFloat (- Int
e) a
y
(a
u1, a
u2) = a -> a -> (a, a)
forall a. RealFloat a => a -> a -> (a, a)
twoSum a
x' a
y'
ulpTowardZero :: a
ulpTowardZero = a
u1 a -> a -> a
forall a. Num a => a -> a -> a
- a -> a
forall a. RealFloat a => a -> a
nextTowardZero a
u1
(a
v1, a
v2) | (-a
2) a -> a -> a
forall a. Num a => a -> a -> a
* a
u2 a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
ulpTowardZero = (a
u1 a -> a -> a
forall a. Num a => a -> a -> a
- a
ulpTowardZero, a
ulpTowardZero a -> a -> a
forall a. Num a => a -> a -> a
+ a
u2)
| Bool
otherwise = (a
u1, a
u2)
r1 :: a
r1 = Int -> a -> a
forall a. RealFloat a => Int -> a -> a
scaleFloat Int
e a
v1
r2 :: a
r2 = Int -> a -> a
forall a. RealFloat a => Int -> a -> a
scaleFloat Int
e a
v2
in if a -> Bool
forall a. RealFloat a => a -> Bool
isInfinite a
r1 then
(a
r1, a
r1)
else
Bool -> (a, a) -> (a, a)
forall a. (?callStack::CallStack) => Bool -> a -> a
assert (a
r2 a -> a -> Bool
forall a. Eq a => a -> a -> Bool
/= a
0) (a
r1, a
r2)
{-# SPECIALIZE augmentedAddition :: Float -> Float -> (Float, Float), Double -> Double -> (Double, Double) #-}
augmentedSubtraction :: RealFloat a => a -> a -> (a, a)
augmentedSubtraction :: a -> a -> (a, a)
augmentedSubtraction a
x a
y = a -> a -> (a, a)
forall a. RealFloat a => a -> a -> (a, a)
augmentedAddition a
x (a -> a
forall a. Num a => a -> a
negate a
y)
augmentedMultiplication :: RealFloat a => a -> a -> (a, a)
augmentedMultiplication :: a -> a -> (a, a)
augmentedMultiplication !a
x !a
y
| a -> Bool
forall a. RealFloat a => a -> Bool
isNaN a
x Bool -> Bool -> Bool
|| a -> Bool
forall a. RealFloat a => a -> Bool
isInfinite a
x Bool -> Bool -> Bool
|| a -> Bool
forall a. RealFloat a => a -> Bool
isNaN a
y Bool -> Bool -> Bool
|| a -> Bool
forall a. RealFloat a => a -> Bool
isInfinite a
y Bool -> Bool -> Bool
|| a
x a -> a -> a
forall a. Num a => a -> a -> a
* a
y a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
0 = let !result :: a
result = a
x a -> a -> a
forall a. Num a => a -> a -> a
* a
y in (a
result, a
result)
| Bool
otherwise = let exy :: Int
exy = a -> Int
forall a. RealFloat a => a -> Int
exponent a
x Int -> Int -> Int
forall a. Num a => a -> a -> a
+ a -> Int
forall a. RealFloat a => a -> Int
exponent a
y
x' :: a
x' = a -> a
forall a. RealFloat a => a -> a
significand a
x
y' :: a
y' = a -> a
forall a. RealFloat a => a -> a
significand a
y
(a
u1, a
u2) = a -> a -> (a, a)
forall a. RealFloat a => a -> a -> (a, a)
twoProduct_nonscaling a
x' a
y'
!()
_ = Bool -> () -> ()
forall a. (?callStack::CallStack) => Bool -> a -> a
assert (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 -> Bool
forall a. Eq a => a -> a -> Bool
== a -> Rational
forall a. Real a => a -> Rational
toRational a
u1 Rational -> Rational -> Rational
forall a. Num a => a -> a -> a
+ a -> Rational
forall a. Real a => a -> Rational
toRational a
u2) ()
in if Int
exy Int -> Int -> Int
forall a. Num a => a -> a -> a
+ a -> Int
forall a. RealFloat a => a -> Int
exponent a
u1 Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
expMin then
let ulpTowardZero :: a
ulpTowardZero = a
u1 a -> a -> a
forall a. Num a => a -> a -> a
- a -> a
forall a. RealFloat a => a -> a
nextTowardZero a
u1
!()
_ = Bool -> () -> ()
forall a. (?callStack::CallStack) => Bool -> a -> a
assert (a
2 a -> a -> a
forall a. Num a => a -> a -> a
* a -> a
forall a. Num a => a -> a
abs a
u2 a -> a -> Bool
forall a. Ord a => a -> a -> Bool
<= a -> a
forall a. Num a => a -> a
abs a
ulpTowardZero) ()
(a
v1, a
v2) = if (-a
2) a -> a -> a
forall a. Num a => a -> a -> a
* a
u2 a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
ulpTowardZero then
(a
u1 a -> a -> a
forall a. Num a => a -> a -> a
- a
ulpTowardZero, a
ulpTowardZero a -> a -> a
forall a. Num a => a -> a -> a
+ a
u2)
else
(a
u1, a
u2)
!()
_ = Bool -> () -> ()
forall a. (?callStack::CallStack) => Bool -> a -> a
assert (a
v1 a -> a -> a
forall a. Num a => a -> a -> a
+ a
v2 a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
u1 a -> a -> a
forall a. Num a => a -> a -> a
+ a
u2) ()
r1 :: a
r1 = Int -> a -> a
forall a. RealFloat a => Int -> a -> a
scaleFloat Int
exy a
v1
in if a -> Bool
forall a. RealFloat a => a -> Bool
isInfinite a
r1 then
(a
r1, a
r1)
else
if a
v2 a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
0 then
(a
r1, a
0 a -> a -> a
forall a. Num a => a -> a -> a
* a
r1)
else
if Int
exy Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
expMin Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
d then
let r2 :: a
r2 = Int -> a -> a
forall a. RealFloat a => Int -> a -> a
scaleFloat Int
exy a
v2
in (a
r1, a
r2)
else
let !r2 :: a
r2 = Int -> a -> a
forall a. RealFloat a => Int -> a -> a
scaleFloatIntoSubnormalTiesTowardZero Int
exy a
v2
in (a
r1, a
r2)
else
if a
u2 a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
0 then
let !()
_ = Bool -> () -> ()
forall a. (?callStack::CallStack) => Bool -> a -> a
assert (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 -> Bool
forall a. Eq a => a -> a -> Bool
== a -> Rational
forall a. Real a => a -> Rational
toRational a
u1) ()
r1 :: a
r1 = Int -> a -> a
forall a. RealFloat a => Int -> a -> a
scaleFloatIntoSubnormalTiesTowardZero Int
exy a
u1
r1' :: a
r1' = Int -> a -> a
forall a. RealFloat a => Int -> a -> a
scaleFloat (-Int
exy) a
r1
in if a
u1 a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
r1' then
(a
r1, a
0 a -> a -> a
forall a. Num a => a -> a -> a
* a
r1)
else
(a
r1, a
0 a -> a -> a
forall a. Num a => a -> a -> a
* (a
u1 a -> a -> a
forall a. Num a => a -> a -> a
- a
r1'))
else
let u1' :: a
u1' = Int -> a -> a
forall a. RealFloat a => Int -> a -> a
scaleFloat Int
exy a
u1
v1' :: a
v1' = Int -> a -> a
forall a. RealFloat a => Int -> a -> a
scaleFloat Int
exy (if a
u2 a -> a -> Bool
forall a. Ord a => a -> a -> Bool
> a
0 then a -> a
forall a. RealFloat a => a -> a
nextUp a
u1 else a -> a
forall a. RealFloat a => a -> a
nextDown a
u1)
r1 :: a
r1 = if a
u1' a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
v1' Bool -> Bool -> Bool
|| Bool -> Bool
not (a -> Bool
forall a. RealFloat a => a -> Bool
isMantissaEven a
u1') then
a
u1'
else
a
v1'
r1' :: a
r1' = Int -> a -> a
forall a. RealFloat a => Int -> a -> a
scaleFloat (-Int
exy) a
r1
in (a
r1, a
0 a -> a -> a
forall a. Num a => a -> a -> a
* (a
u1 a -> a -> a
forall a. Num a => a -> a -> a
- a
r1' a -> a -> a
forall a. Num a => a -> a -> a
+ a
u2))
where
d :: Int
d = a -> Int
forall a. RealFloat a => a -> Int
floatDigits a
x
(Int
expMin,Int
_expMax) = a -> (Int, Int)
forall a. RealFloat a => a -> (Int, Int)
floatRange a
x
scaleFloatIntoSubnormalTiesTowardZero :: Int -> p -> p
scaleFloatIntoSubnormalTiesTowardZero Int
e p
z =
let z' :: p
z' = Int -> p -> p
forall a. RealFloat a => Int -> a -> a
scaleFloat Int
e p
z
w' :: p
w' = Int -> p -> p
forall a. RealFloat a => Int -> a -> a
scaleFloat Int
e (p -> p
forall a. RealFloat a => a -> a
nextTowardZero p
z)
in if p
z' p -> p -> Bool
forall a. Eq a => a -> a -> Bool
== p
w' Bool -> Bool -> Bool
|| Bool -> Bool
not (p -> Bool
forall a. RealFloat a => a -> Bool
isMantissaEven p
z') then
p
z'
else
p
w'
{-# SPECIALIZE augmentedMultiplication :: Float -> Float -> (Float, Float), Double -> Double -> (Double, Double) #-}