{-# LANGUAGE CPP #-}
{-# LANGUAGE NumericUnderscores #-}
module Numeric.Rounded.Hardware.Internal.FloatUtil
  ( nextUp
  , nextDown
  , nextTowardZero
  , distanceUlp
  , fusedMultiplyAdd
  ) where
import           Data.Ratio
import           Numeric.Floating.IEEE

distanceUlp :: RealFloat a => a -> a -> Maybe Integer
distanceUlp :: forall a. RealFloat a => a -> a -> Maybe Integer
distanceUlp a
x a
y
  | a -> Bool
forall a. RealFloat a => a -> Bool
isInfinite a
x 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
x Bool -> Bool -> Bool
|| a -> Bool
forall a. RealFloat a => a -> Bool
isNaN a
y = Maybe Integer
forall a. Maybe a
Nothing
  | Bool
otherwise = let m :: a
m = a -> a -> a
forall a. Ord a => a -> a -> a
min (a -> a
forall a. Num a => a -> a
abs a
x) (a -> a
forall a. Num a => a -> a
abs a
y)
                    m' :: a
m' = a -> a
forall a. RealFloat a => a -> a
nextUp a
m
                    v :: Rational
v = (a -> Rational
forall a. Real a => a -> Rational
toRational a
y Rational -> Rational -> Rational
forall a. Num a => a -> a -> a
- 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
m' a -> a -> a
forall a. Num a => a -> a -> a
- a
m)
                in if Rational -> Integer
forall a. Ratio a -> a
denominator Rational
v Integer -> Integer -> Bool
forall a. Eq a => a -> a -> Bool
== Integer
1
                   then Integer -> Maybe Integer
forall a. a -> Maybe a
Just (Integer -> Integer
forall a. Num a => a -> a
abs (Rational -> Integer
forall a. Ratio a -> a
numerator Rational
v))
                   else [Char] -> Maybe Integer
forall a. HasCallStack => [Char] -> a
error [Char]
"distanceUlp"