{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE CPP #-}
{-# LANGUAGE NoImplicitPrelude #-}
#if defined(HAS_FMA_PRIM)
{-# LANGUAGE MagicHash #-}
{-# LANGUAGE UnboxedTuples #-}
#endif
module Numeric.Floating.IEEE.Internal.FMA
( isMantissaEven
, twoSum
, addToOdd
, split
, twoProductFloat_viaDouble
, twoProduct
, twoProduct_nonscaling
, twoProductFloat
, twoProductDouble
, fusedMultiplyAddFloat_viaDouble
, fusedMultiplyAdd
, fusedMultiplyAddFloat
, fusedMultiplyAddDouble
) where
import Control.Exception (assert)
import Data.Bits
import GHC.Float.Compat (castDoubleToWord64, castFloatToWord32,
double2Float, float2Double)
import MyPrelude
import Numeric.Floating.IEEE.Internal.Base (isDoubleBinary64,
isFloatBinary32, (^!))
import Numeric.Floating.IEEE.Internal.Classify (isFinite)
import Numeric.Floating.IEEE.Internal.NextFloat (nextDown, nextUp)
#if defined(HAS_FMA_PRIM)
import GHC.Exts
#endif
default ()
isMantissaEven :: RealFloat a => a -> Bool
isMantissaEven :: forall a. RealFloat a => a -> Bool
isMantissaEven a
0 = Bool
True
isMantissaEven a
x = let !()
_ = forall a. (?callStack::CallStack) => Bool -> a -> a
assert (forall a. RealFloat a => a -> Bool
isFinite a
x) ()
(Integer
m,Int
n) = forall a. RealFloat a => a -> (Integer, Int)
decodeFloat a
x
d :: Int
d = forall a. RealFloat a => a -> Int
floatDigits a
x
!()
_ = forall a. (?callStack::CallStack) => Bool -> a -> a
assert (forall a. RealFloat a => a -> Integer
floatRadix a
x forall a b. (Num a, Integral b) => a -> b -> a
^ (Int
d forall a. Num a => a -> a -> a
- Int
1) forall a. Ord a => a -> a -> Bool
<= forall a. Num a => a -> a
abs Integer
m Bool -> Bool -> Bool
&& forall a. Num a => a -> a
abs Integer
m forall a. Ord a => a -> a -> Bool
< forall a. RealFloat a => a -> Integer
floatRadix a
x forall a b. (Num a, Integral b) => a -> b -> a
^ Int
d) ()
(Int
expMin, Int
_expMax) = forall a. RealFloat a => a -> (Int, Int)
floatRange a
x
s :: Int
s = Int
expMin forall a. Num a => a -> a -> a
- (Int
n forall a. Num a => a -> a -> a
+ Int
d)
!()
_ = forall a. (?callStack::CallStack) => Bool -> a -> a
assert (forall a. RealFloat a => a -> Bool
isDenormalized a
x forall a. Eq a => a -> a -> Bool
== (Int
s forall a. Ord a => a -> a -> Bool
> Int
0)) ()
in if Int
s forall a. Ord a => a -> a -> Bool
> Int
0 then
forall a. Integral a => a -> Bool
even (Integer
m forall a. Bits a => a -> Int -> a
`shiftR` Int
s)
else
forall a. Integral a => a -> Bool
even Integer
m
{-# NOINLINE [1] isMantissaEven #-}
{-# RULES
"isMantissaEven/Double"
isMantissaEven = \x -> even (castDoubleToWord64 x)
"isMantissaEven/Float"
isMantissaEven = \x -> even (castFloatToWord32 x)
#-}
twoSum :: RealFloat a => a -> a -> (a, a)
twoSum :: forall a. RealFloat a => a -> a -> (a, a)
twoSum a
a a
b =
let x :: a
x = a
a forall a. Num a => a -> a -> a
+ a
b
t :: a
t = a
x forall a. Num a => a -> a -> a
- a
a
y :: a
y = (a
a forall a. Num a => a -> a -> a
- (a
x forall a. Num a => a -> a -> a
- a
t)) forall a. Num a => a -> a -> a
+ (a
b forall a. Num a => a -> a -> a
- a
t)
in (a
x, a
y)
{-# SPECIALIZE twoSum :: Float -> Float -> (Float, Float), Double -> Double -> (Double, Double) #-}
addToOdd :: RealFloat a => a -> a -> a
addToOdd :: forall a. RealFloat a => a -> a -> a
addToOdd a
x a
y = let (a
u, a
v) = forall a. RealFloat a => a -> a -> (a, a)
twoSum a
x a
y
result :: a
result | forall a. RealFloat a => a -> Bool
isMantissaEven a
u Bool -> Bool -> Bool
&& a
v forall a. Ord a => a -> a -> Bool
< a
0 = forall a. RealFloat a => a -> a
nextDown a
u
| forall a. RealFloat a => a -> Bool
isMantissaEven a
u Bool -> Bool -> Bool
&& a
v forall a. Ord a => a -> a -> Bool
> a
0 = forall a. RealFloat a => a -> a
nextUp a
u
| forall a. RealFloat a => a -> Bool
isMantissaEven a
u Bool -> Bool -> Bool
&& forall a. RealFloat a => a -> Bool
isNaN a
v Bool -> Bool -> Bool
&& Bool -> Bool
not (forall a. RealFloat a => a -> Bool
isInfinite a
u) =
let v' :: a
v' = if 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 then
a
y forall a. Num a => a -> a -> a
- (a
u forall a. Num a => a -> a -> a
- a
x)
else
a
x forall a. Num a => a -> a -> a
- (a
u forall a. Num a => a -> a -> a
- a
y)
in if a
v' forall a. Ord a => a -> a -> Bool
< a
0 then
forall a. RealFloat a => a -> a
nextDown a
u
else if a
v' forall a. Ord a => a -> a -> Bool
> a
0 then
forall a. RealFloat a => a -> a
nextUp a
u
else
a
u
| Bool
otherwise = a
u
!()
_ = forall a. (?callStack::CallStack) => Bool -> a -> a
assert (forall a. RealFloat a => a -> Bool
isInfinite a
u Bool -> Bool -> Bool
|| forall a. Real a => a -> Rational
toRational a
u forall a. Eq a => a -> a -> Bool
== forall a. Real a => a -> Rational
toRational a
x forall a. Num a => a -> a -> a
+ forall a. Real a => a -> Rational
toRational a
y Bool -> Bool -> Bool
|| Bool -> Bool
not (forall a. RealFloat a => a -> Bool
isMantissaEven a
result)) ()
in a
result
{-# SPECIALIZE addToOdd :: Float -> Float -> Float, Double -> Double -> Double #-}
split :: RealFloat a => a -> (a, a)
split :: forall a. RealFloat a => a -> (a, a)
split a
a =
let c :: a
c = a
factor forall a. Num a => a -> a -> a
* a
a
x :: a
x = a
c forall a. Num a => a -> a -> a
- (a
c forall a. Num a => a -> a -> a
- a
a)
y :: a
y = a
a forall a. Num a => a -> a -> a
- a
x
in (a
x, a
y)
where factor :: a
factor = forall a. Num a => Integer -> a
fromInteger forall a b. (a -> b) -> a -> b
$ Integer
1 forall a. Num a => a -> a -> a
+ forall a. RealFloat a => a -> Integer
floatRadix a
a Integer -> Int -> Integer
^! ((forall a. RealFloat a => a -> Int
floatDigits a
a forall a. Num a => a -> a -> a
+ Int
1) forall a. Integral a => a -> a -> a
`quot` Int
2)
{-# SPECIALIZE split :: Float -> (Float, Float), Double -> (Double, Double) #-}
twoProduct :: RealFloat a => a -> a -> (a, a)
twoProduct :: forall a. RealFloat a => a -> a -> (a, a)
twoProduct a
a a
b =
let eab :: Int
eab = forall a. RealFloat a => a -> Int
exponent a
a forall a. Num a => a -> a -> a
+ forall a. RealFloat a => a -> Int
exponent a
b
a' :: a
a' = forall a. RealFloat a => a -> a
significand a
a
b' :: a
b' = forall a. RealFloat a => a -> a
significand a
b
(a
ah, a
al) = forall a. RealFloat a => a -> (a, a)
split a
a'
(a
bh, a
bl) = forall a. RealFloat a => a -> (a, a)
split a
b'
x :: a
x = a
a forall a. Num a => a -> a -> a
* a
b
y' :: a
y' = a
al forall a. Num a => a -> a -> a
* a
bl forall a. Num a => a -> a -> a
- (forall a. RealFloat a => Int -> a -> a
scaleFloat (-Int
eab) a
x forall a. Num a => a -> a -> a
- a
ah forall a. Num a => a -> a -> a
* a
bh forall a. Num a => a -> a -> a
- a
al forall a. Num a => a -> a -> a
* a
bh forall a. Num a => a -> a -> a
- a
ah forall a. Num a => a -> a -> a
* a
bl)
in (a
x, forall a. RealFloat a => Int -> a -> a
scaleFloat Int
eab a
y')
{-# INLINABLE [1] twoProduct #-}
twoProductFloat_viaDouble :: Float -> Float -> (Float, Float)
twoProductFloat_viaDouble :: Float -> Float -> (Float, Float)
twoProductFloat_viaDouble Float
a Float
b =
let x, y :: Float
a', b', x' :: Double
a' :: Double
a' = Float -> Double
float2Double Float
a
b' :: Double
b' = Float -> Double
float2Double Float
b
x' :: Double
x' = Double
a' forall a. Num a => a -> a -> a
* Double
b'
x :: Float
x = Double -> Float
double2Float Double
x'
y :: Float
y = Double -> Float
double2Float (Double
x' forall a. Num a => a -> a -> a
- Float -> Double
float2Double Float
x)
in (Float
x, Float
y)
twoProduct_nonscaling :: RealFloat a => a -> a -> (a, a)
twoProduct_nonscaling :: forall a. RealFloat a => a -> a -> (a, a)
twoProduct_nonscaling a
a a
b =
let (a
ah, a
al) = forall a. RealFloat a => a -> (a, a)
split a
a
(a
bh, a
bl) = forall a. RealFloat a => a -> (a, a)
split a
b
x :: a
x = a
a forall a. Num a => a -> a -> a
* a
b
y :: a
y = a
al forall a. Num a => a -> a -> a
* a
bl forall a. Num a => a -> a -> a
- (a
x forall a. Num a => a -> a -> a
- a
ah forall a. Num a => a -> a -> a
* a
bh forall a. Num a => a -> a -> a
- a
al forall a. Num a => a -> a -> a
* a
bh forall a. Num a => a -> a -> a
- a
ah forall a. Num a => a -> a -> a
* a
bl)
in (a
x, a
y)
{-# NOINLINE [1] twoProduct_nonscaling #-}
twoProductFloat :: Float -> Float -> (Float, Float)
twoProductDouble :: Double -> Double -> (Double, Double)
#if defined(HAS_FMA_PRIM) && 0
twoProductFloat# :: Float# -> Float# -> (# Float#, Float# #)
twoProductFloat# x y = let !r = x `timesFloat#` y
!s = fmsubFloat# x y r
in (# r, s #)
twoProductDouble# :: Double# -> Double# -> (# Double#, Double# #)
twoProductDouble# x y = let !r = x *## y
!s = fmsubDouble# x y r
in (# r, s #)
#if defined(DONT_INLINE_FMA_PRIM)
{-# NOINLINE twoProductFloat# #-}
{-# NOINLINE twoProductDouble# #-}
#else
{-# INLINE twoProductFloat# #-}
{-# INLINE twoProductDouble# #-}
#endif
twoProductFloat (F# x) (F# y) = case twoProductFloat# x y of
(# r, s #) -> (F# r, F# s)
twoProductDouble (D# x) (D# y) = case twoProductDouble# x y of
(# r, s #) -> (D# r, D# s)
{-# INLINE twoProductFloat #-}
{-# INLINE twoProductDouble #-}
{-# RULES
"twoProduct/Float" twoProduct = twoProductFloat
"twoProduct/Double" twoProduct = twoProductDouble
"twoProduct_nonscaling/Float" twoProduct_nonscaling = twoProductFloat
"twoProduct_nonscaling/Double" twoProduct_nonscaling = twoProductDouble
#-}
#elif defined(HAS_FAST_FMA) || defined(HAS_FMA_PRIM)
twoProductFloat x y = let !r = x * y
!s = fusedMultiplyAddFloat x y (-r)
in (r, s)
twoProductDouble x y = let !r = x * y
!s = fusedMultiplyAddDouble x y (-r)
in (r, s)
{-# RULES
"twoProduct/Float" twoProduct = twoProductFloat
"twoProduct/Double" twoProduct = twoProductDouble
"twoProduct_nonscaling/Float" twoProduct_nonscaling = twoProductFloat
"twoProduct_nonscaling/Double" twoProduct_nonscaling = twoProductDouble
#-}
#else
twoProductFloat :: Float -> Float -> (Float, Float)
twoProductFloat = Float -> Float -> (Float, Float)
twoProductFloat_viaDouble
{-# INLINE twoProductFloat #-}
twoProductDouble :: Double -> Double -> (Double, Double)
twoProductDouble = forall a. RealFloat a => a -> a -> (a, a)
twoProduct
{-# INLINE twoProductDouble #-}
{-# RULES
"twoProduct/Float" twoProduct = twoProductFloat_viaDouble
"twoProduct_nonscaling/Float" twoProduct_nonscaling = twoProductFloat_viaDouble
#-}
{-# SPECIALIZE twoProduct :: Double -> Double -> (Double, Double) #-}
{-# SPECIALIZE twoProduct_nonscaling :: Double -> Double -> (Double, Double) #-}
#endif
fusedMultiplyAdd :: RealFloat a => a -> a -> a -> a
fusedMultiplyAdd :: forall a. RealFloat a => a -> a -> a -> a
fusedMultiplyAdd a
a a
b a
c
| forall a. RealFloat a => a -> Bool
isFinite a
a Bool -> Bool -> Bool
&& forall a. RealFloat a => a -> Bool
isFinite a
b Bool -> Bool -> Bool
&& forall a. RealFloat a => a -> Bool
isFinite a
c =
let eab :: Int
eab | a
a forall a. Eq a => a -> a -> Bool
== a
0 Bool -> Bool -> Bool
|| a
b forall a. Eq a => a -> a -> Bool
== a
0 = forall a b. (a, b) -> a
fst (forall a. RealFloat a => a -> (Int, Int)
floatRange a
a) forall a. Num a => a -> a -> a
- forall a. RealFloat a => a -> Int
floatDigits a
a
| Bool
otherwise = forall a. RealFloat a => a -> Int
exponent a
a forall a. Num a => a -> a -> a
+ forall a. RealFloat a => a -> Int
exponent a
b
ec :: Int
ec | a
c forall a. Eq a => a -> a -> Bool
== a
0 = forall a b. (a, b) -> a
fst (forall a. RealFloat a => a -> (Int, Int)
floatRange a
c) forall a. Num a => a -> a -> a
- forall a. RealFloat a => a -> Int
floatDigits a
c
| Bool
otherwise = forall a. RealFloat a => a -> Int
exponent a
c
a' :: a
a' = forall a. RealFloat a => a -> a
significand a
a
b' :: a
b' = forall a. RealFloat a => a -> a
significand a
b
(a
x', a
y') = forall a. RealFloat a => a -> a -> (a, a)
twoProduct_nonscaling a
a' a
b'
!()
_ = forall a. (?callStack::CallStack) => Bool -> a -> a
assert (forall a. Real a => a -> Rational
toRational a
a' forall a. Num a => a -> a -> a
* forall a. Real a => a -> Rational
toRational a
b' forall a. Eq a => a -> a -> Bool
== forall a. Real a => a -> Rational
toRational a
x' forall a. Num a => a -> a -> a
+ forall a. Real a => a -> Rational
toRational a
y') ()
e :: Int
e = forall a. Ord a => a -> a -> a
max Int
eab Int
ec
x :: a
x = forall a. RealFloat a => Int -> a -> a
scaleFloat (Int
eab forall a. Num a => a -> a -> a
- Int
e) a
x'
y :: a
y = forall a. RealFloat a => Int -> a -> a
scaleFloat (Int
eab forall a. Num a => a -> a -> a
- Int
e) a
y'
c'' :: a
c'' = forall a. RealFloat a => Int -> a -> a
scaleFloat (forall a. Ord a => a -> a -> a
max (forall a b. (a, b) -> a
fst (forall a. RealFloat a => a -> (Int, Int)
floatRange a
c) forall a. Num a => a -> a -> a
- forall a. RealFloat a => a -> Int
floatDigits a
c forall a. Num a => a -> a -> a
+ Int
1) (Int
ec forall a. Num a => a -> a -> a
- Int
e) forall a. Num a => a -> a -> a
- Int
ec) a
c
(a
u1,a
u2) = forall a. RealFloat a => a -> a -> (a, a)
twoSum a
y a
c''
(a
v1,a
v2) = forall a. RealFloat a => a -> a -> (a, a)
twoSum a
u1 a
x
w :: a
w = forall a. RealFloat a => a -> a -> a
addToOdd a
u2 a
v2
result0 :: a
result0 = a
v1 forall a. Num a => a -> a -> a
+ a
w
!()
_ = forall a. (?callStack::CallStack) => Bool -> a -> a
assert (a
result0 forall a. Eq a => a -> a -> Bool
== forall a. Fractional a => Rational -> a
fromRational (forall a. Real a => a -> Rational
toRational a
x forall a. Num a => a -> a -> a
+ forall a. Real a => a -> Rational
toRational a
y forall a. Num a => a -> a -> a
+ forall a. Real a => a -> Rational
toRational a
c'')) ()
result :: a
result = forall a. RealFloat a => Int -> a -> a
scaleFloat Int
e a
result0
!()
_ = forall a. (?callStack::CallStack) => Bool -> a -> a
assert (a
result forall a. Eq a => a -> a -> Bool
== forall a. Fractional a => Rational -> a
fromRational (forall a. Real a => a -> Rational
toRational a
a forall a. Num a => a -> a -> a
* forall a. Real a => a -> Rational
toRational a
b forall a. Num a => a -> a -> a
+ forall a. Real a => a -> Rational
toRational a
c) Bool -> Bool -> Bool
|| forall a. RealFloat a => a -> Bool
isDenormalized a
result) ()
in if a
result0 forall a. Eq a => a -> a -> Bool
== a
0 then
if a
c forall a. Eq a => a -> a -> Bool
== a
0 Bool -> Bool -> Bool
&& a
a forall a. Eq a => a -> a -> Bool
/= a
0 Bool -> Bool -> Bool
&& a
b forall a. Eq a => a -> a -> Bool
/= a
0 then
a
a forall a. Num a => a -> a -> a
* a
b
else
a
a forall a. Num a => a -> a -> a
* a
b forall a. Num a => a -> a -> a
+ a
c
else
if forall a. RealFloat a => a -> Bool
isDenormalized a
result then
case forall a. Real a => a -> Rational
toRational a
a forall a. Num a => a -> a -> a
* forall a. Real a => a -> Rational
toRational a
b forall a. Num a => a -> a -> a
+ forall a. Real a => a -> Rational
toRational a
c of
Rational
0 -> a
a forall a. Num a => a -> a -> a
* a
b forall a. Num a => a -> a -> a
+ a
c
Rational
r -> forall a. Fractional a => Rational -> a
fromRational Rational
r
else
a
result
| forall a. RealFloat a => a -> Bool
isFinite a
a Bool -> Bool -> Bool
&& forall a. RealFloat a => a -> Bool
isFinite a
b = a
c forall a. Num a => a -> a -> a
+ a
c
| Bool
otherwise = a
a forall a. Num a => a -> a -> a
* a
b forall a. Num a => a -> a -> a
+ a
c
{-# INLINABLE [1] fusedMultiplyAdd #-}
fusedMultiplyAddFloat_viaDouble :: Float -> Float -> Float -> Float
fusedMultiplyAddFloat_viaDouble :: Float -> Float -> Float -> Float
fusedMultiplyAddFloat_viaDouble Float
a Float
b Float
c
| forall a. RealFloat a => a -> Bool
isFinite Float
a Bool -> Bool -> Bool
&& forall a. RealFloat a => a -> Bool
isFinite Float
b Bool -> Bool -> Bool
&& forall a. RealFloat a => a -> Bool
isFinite Float
c =
let a', b', c' :: Double
a' :: Double
a' = Float -> Double
float2Double Float
a
b' :: Double
b' = Float -> Double
float2Double Float
b
c' :: Double
c' = Float -> Double
float2Double Float
c
ab :: Double
ab = Double
a' forall a. Num a => a -> a -> a
* Double
b'
!()
_ = forall a. (?callStack::CallStack) => Bool -> a -> a
assert (forall a. Real a => a -> Rational
toRational Double
ab forall a. Eq a => a -> a -> Bool
== forall a. Real a => a -> Rational
toRational Double
a' forall a. Num a => a -> a -> a
* forall a. Real a => a -> Rational
toRational Double
b') ()
result :: Float
result = Double -> Float
double2Float (forall a. RealFloat a => a -> a -> a
addToOdd Double
ab Double
c')
!()
_ = forall a. (?callStack::CallStack) => Bool -> a -> a
assert (Float
result forall a. Eq a => a -> a -> Bool
== forall a. Fractional a => Rational -> a
fromRational (forall a. Real a => a -> Rational
toRational Float
a forall a. Num a => a -> a -> a
* forall a. Real a => a -> Rational
toRational Float
b forall a. Num a => a -> a -> a
+ forall a. Real a => a -> Rational
toRational Float
c)) ()
in Float
result
| forall a. RealFloat a => a -> Bool
isFinite Float
a Bool -> Bool -> Bool
&& forall a. RealFloat a => a -> Bool
isFinite Float
b = Float
c forall a. Num a => a -> a -> a
+ Float
c
| Bool
otherwise = Float
a forall a. Num a => a -> a -> a
* Float
b forall a. Num a => a -> a -> a
+ Float
c
where
!() = if Bool
isFloatBinary32 then () else forall a. (?callStack::CallStack) => [Char] -> a
error [Char]
"fusedMultiplyAdd/Float: Float must be IEEE binary32"
!() = if Bool
isDoubleBinary64 then () else forall a. (?callStack::CallStack) => [Char] -> a
error [Char]
"fusedMultiplyAdd/Float: Double must be IEEE binary64"
#if defined(HAS_FMA_PRIM)
#if defined(DONT_INLINE_FMA_PRIM)
fusedMultiplyAddFloat# :: Float# -> Float# -> Float# -> Float#
fusedMultiplyAddFloat# x y z = fmaddFloat# x y z
{-# NOINLINE fusedMultiplyAddFloat# #-}
fusedMultiplyAddDouble# :: Double# -> Double# -> Double# -> Double#
fusedMultiplyAddDouble# x y z = fmaddDouble# x y z
{-# NOINLINE fusedMultiplyAddDouble# #-}
fusedMultiplyAddFloat :: Float -> Float -> Float -> Float
fusedMultiplyAddFloat (F# x) (F# y) (F# z) = F# (fusedMultiplyAddFloat# x y z)
fusedMultiplyAddDouble :: Double -> Double -> Double -> Double
fusedMultiplyAddDouble (D# x) (D# y) (D# z) = D# (fusedMultiplyAddDouble# x y z)
#else
fusedMultiplyAddFloat :: Float -> Float -> Float -> Float
fusedMultiplyAddFloat (F# x) (F# y) (F# z) = F# (fmaddFloat# x y z)
fusedMultiplyAddDouble :: Double -> Double -> Double -> Double
fusedMultiplyAddDouble (D# x) (D# y) (D# z) = D# (fmaddDouble# x y z)
#endif
{-# INLINE fusedMultiplyAddFloat #-}
{-# INLINE fusedMultiplyAddDouble #-}
{-# RULES
"fusedMultiplyAdd/Float" fusedMultiplyAdd = fusedMultiplyAddFloat
"fusedMultiplyAdd/Double" fusedMultiplyAdd = fusedMultiplyAddDouble
#-}
#elif defined(HAS_FAST_FMA)
foreign import ccall unsafe "hs_fusedMultiplyAddFloat"
fusedMultiplyAddFloat :: Float -> Float -> Float -> Float
foreign import ccall unsafe "hs_fusedMultiplyAddDouble"
fusedMultiplyAddDouble :: Double -> Double -> Double -> Double
{-# RULES
"fusedMultiplyAdd/Float" fusedMultiplyAdd = fusedMultiplyAddFloat
"fusedMultiplyAdd/Double" fusedMultiplyAdd = fusedMultiplyAddDouble
#-}
#elif defined(USE_C99_FMA)
foreign import ccall unsafe "fmaf"
fusedMultiplyAddFloat :: Float -> Float -> Float -> Float
foreign import ccall unsafe "fma"
fusedMultiplyAddDouble :: Double -> Double -> Double -> Double
{-# RULES
"fusedMultiplyAdd/Float" fusedMultiplyAdd = fusedMultiplyAddFloat
"fusedMultiplyAdd/Double" fusedMultiplyAdd = fusedMultiplyAddDouble
#-}
#else
fusedMultiplyAddFloat :: Float -> Float -> Float -> Float
fusedMultiplyAddFloat = fusedMultiplyAddFloat_viaDouble
{-# INLINE fusedMultiplyAddFloat #-}
fusedMultiplyAddDouble :: Double -> Double -> Double -> Double
fusedMultiplyAddDouble = fusedMultiplyAdd
{-# INLINE fusedMultiplyAddDouble #-}
{-# RULES
"fusedMultiplyAdd/Float" fusedMultiplyAdd = fusedMultiplyAddFloat_viaDouble
#-}
{-# SPECIALIZE fusedMultiplyAdd :: Double -> Double -> Double -> Double #-}
#endif