diff --git a/ChangeLog.md b/ChangeLog.md
--- a/ChangeLog.md
+++ b/ChangeLog.md
@@ -1,5 +1,11 @@
 # Changelog for rounded-hw
 
+## 0.2.0 (2020-12-27)
+
+* Some functionality was moved to fp-ieee.
+* Fix roundedFusedMultiplyAdd of ViaRational.
+* Fix showFFloatRn.
+
 ## 0.1.0.0 (2020-06-23)
 
 * Initial release.
diff --git a/benchmark/Benchmark.hs b/benchmark/Benchmark.hs
--- a/benchmark/Benchmark.hs
+++ b/benchmark/Benchmark.hs
@@ -13,38 +13,26 @@
 import qualified Data.Vector.Unboxed as VU
 import           Gauge.Main
 import           IGA
-import           Numeric
 import           Numeric.Rounded.Hardware.Internal
 import           Numeric.Rounded.Hardware.Interval
 import           Numeric.Rounded.Hardware.Interval.Class (makeInterval)
 import qualified Numeric.Rounded.Hardware.Interval.NonEmpty as NE
 import qualified Numeric.Rounded.Hardware.Vector.Unboxed as RVU
 
-foreign import ccall unsafe "nextafter"
-  c_nextafter_double :: Double -> Double -> Double
-foreign import ccall unsafe "nextafterf"
-  c_nextafter_float :: Float -> Float -> Float
 foreign import ccall unsafe "fma"
   c_fma_double :: Double -> Double -> Double -> Double
 foreign import ccall unsafe "fmaf"
   c_fma_float :: Float -> Float -> Float -> Float
 
 class Fractional a => CFloat a where
-  c_nextafter :: a -> a -> a
   c_fma :: a -> a -> a -> a
 
 instance CFloat Double where
-  c_nextafter = c_nextafter_double
   c_fma = c_fma_double
 
 instance CFloat Float where
-  c_nextafter = c_nextafter_float
   c_fma = c_fma_float
 
-c_nextUp, c_nextDown :: (RealFloat a, CFloat a) => a -> a
-c_nextUp x = c_nextafter x (1/0)
-c_nextDown x = c_nextafter x (-1/0)
-
 main :: IO ()
 main =
   defaultMain
@@ -114,8 +102,6 @@
          , bench "mul" $ nf (uncurry (*)) (iv1, iv2)
          , bench "div" $ nf (uncurry (/)) (iv1, iv2)
          , bench "sqrt" $ nf sqrt iv1
-         , bench "fromInteger" $ nf (fromInteger :: Integer -> Interval Double) (2^60 + 1)
-         , bench "fromIntegral/Int64" $ nf (fromIntegral :: Int64 -> Interval Double) (2^60 + 1)
          ]
     , let vec :: V.Vector (Interval Double)
           vec = V.generate 100000 $ \i -> fromRational (1 % (1 + fromIntegral i))
@@ -128,46 +114,6 @@
       , bench "NE.exp" $ nf exp (0.3 :: NE.Interval Double)
       , bench "sin" $ nf sin (7.3 :: Interval Double)
       , bench "NE.sin" $ nf sin (7.3 :: NE.Interval Double)
-      ]
-    , bgroup "nextUp"
-      [ let cases = [0,1,0x1.ffff_ffff_ffff_fp200] :: [Double]
-        in bgroup "Double"
-           [ bgroup "C"
-             [ bench (showHFloat x "") $ nf c_nextUp x | x <- cases ]
-           , bgroup "Haskell"
-             [ bench (showHFloat x "") $ nf nextUp x | x <- cases ]
-           , bgroup "Haskell (generic)"
-             [ bench (showHFloat x "") $ nf nextUp (Identity x) | x <- cases ]
-           ]
-      , let cases = [0,1,0x1.fffffep100] :: [Float]
-        in bgroup "Float"
-           [ bgroup "C"
-             [ bench (showHFloat x "") $ nf c_nextUp x | x <- cases ]
-           , bgroup "Haskell"
-             [ bench (showHFloat x "") $ nf nextUp x | x <- cases ]
-           , bgroup "Haskell (generic)"
-             [ bench (showHFloat x "") $ nf nextUp (Identity x) | x <- cases ]
-           ]
-      ]
-    , bgroup "nextDown"
-      [ let cases = [0,1,0x1.ffff_ffff_ffff_fp200] :: [Double]
-        in bgroup "Double"
-           [ bgroup "C"
-             [ bench (showHFloat x "") $ nf c_nextDown x | x <- cases ]
-           , bgroup "Haskell"
-             [ bench (showHFloat x "") $ nf nextDown x | x <- cases ]
-           , bgroup "Haskell (generic)"
-             [ bench (showHFloat x "") $ nf nextDown (Identity x) | x <- cases ]
-           ]
-      , let cases = [0,1,0x1.fffffep100] :: [Float]
-        in bgroup "Float"
-           [ bgroup "C"
-             [ bench (showHFloat x "") $ nf c_nextDown x | x <- cases ]
-           , bgroup "Haskell"
-             [ bench (showHFloat x "") $ nf nextDown x | x <- cases ]
-           , bgroup "Haskell (generic)"
-             [ bench (showHFloat x "") $ nf nextDown (Identity x) | x <- cases ]
-           ]
       ]
     , bgroup "FMA"
       [ let arg = (1.0, 2.0, 3.0) :: (Double, Double, Double)
diff --git a/benchmark/Conversion.hs b/benchmark/Conversion.hs
--- a/benchmark/Conversion.hs
+++ b/benchmark/Conversion.hs
@@ -4,11 +4,15 @@
 {-# OPTIONS_GHC -Wno-type-defaults #-}
 module Conversion (benchmark) where
 import           Data.Bits
+import           Data.Functor.Product
 import           Data.Int
 import           Data.Ratio
 import           Data.Word
 import           Gauge.Benchmark
+import           Numeric.Floating.IEEE
+import qualified Numeric.Floating.IEEE.Internal as IEEE.Internal
 import           Numeric.Rounded.Hardware
+import qualified Numeric.Rounded.Hardware.Backend.C as C
 import           Numeric.Rounded.Hardware.Class
 import           Numeric.Rounded.Hardware.Interval
 
@@ -38,62 +42,87 @@
 
 benchmark :: Benchmark
 benchmark = bgroup "Conversion"
-  [ let smallInteger = -2^50+2^13+127 :: Integer
-        mediumInteger = -2^60 + 42 * 2^53 - 137 * 2^24 + 3 :: Integer
-        largeInteger = -2^100-37*2^80+2^13+127 :: Integer
-    in bgroup "fromInteger"
-       [ bench "Double/small" $ nf (fromInteger :: Integer -> Double) smallInteger
-       , bench "Double/medium" $ nf (fromInteger :: Integer -> Double) mediumInteger
-       , bench "Double/large" $ nf (fromInteger :: Integer -> Double) largeInteger
-       , bench "RoundedDouble/ToNearest/small" $ nf (fromInteger :: Integer -> Rounded 'ToNearest Double) smallInteger
-       , bench "RoundedDouble/ToNearest/medium" $ nf (fromInteger :: Integer -> Rounded 'ToNearest Double) mediumInteger
-       , bench "RoundedDouble/ToNearest/large" $ nf (fromInteger :: Integer -> Rounded 'ToNearest Double) largeInteger
-       , bench "RoundedDouble/TowardInf/small" $ nf (fromInteger :: Integer -> Rounded 'TowardInf Double) smallInteger
-       , bench "RoundedDouble/TowardInf/medium" $ nf (fromInteger :: Integer -> Rounded 'TowardInf Double) mediumInteger
-       , bench "RoundedDouble/TowardInf/large" $ nf (fromInteger :: Integer -> Rounded 'TowardInf Double) largeInteger
-       , bench "roundedFromInteger/Double/ToNearest/small" $ nf (roundedFromInteger ToNearest :: Integer -> Double) smallInteger
-       , bench "roundedFromInteger/Double/ToNearest/medium" $ nf (roundedFromInteger ToNearest :: Integer -> Double) mediumInteger
-       , bench "roundedFromInteger/Double/ToNearest/large" $ nf (roundedFromInteger ToNearest :: Integer -> Double) largeInteger
-       , bench "roundedFromInteger/Double/TowardInf/small" $ nf (roundedFromInteger TowardInf :: Integer -> Double) smallInteger
-       , bench "roundedFromInteger/Double/TowardInf/medium" $ nf (roundedFromInteger TowardInf :: Integer -> Double) mediumInteger
-       , bench "roundedFromInteger/Double/TowardInf/large" $ nf (roundedFromInteger TowardInf :: Integer -> Double) largeInteger
-       , bench "IntervalDouble/small" $ nf (fromInteger :: Integer -> Interval Double) smallInteger
-       , bench "IntervalDouble/medium" $ nf (fromInteger :: Integer -> Interval Double) mediumInteger
-       , bench "IntervalDouble/large" $ nf (fromInteger :: Integer -> Interval Double) largeInteger
-       ]
-  , let smallInteger = -2^50+2^13+127 :: Int64
-        mediumInteger = -2^60 + 42 * 2^53 - 137 * 2^24 + 3 :: Int64
-    in bgroup "fromIntegral/Int64"
-       [ bench "Double/small" $ nf (fromIntegral :: Int64 -> Double) smallInteger
-       , bench "Double/medium" $ nf (fromIntegral :: Int64 -> Double) mediumInteger
-       , bench "RoundedDouble/ToNearest/small" $ nf (fromIntegral :: Int64 -> Rounded 'ToNearest Double) smallInteger
-       , bench "RoundedDouble/ToNearest/medium" $ nf (fromIntegral :: Int64 -> Rounded 'ToNearest Double) mediumInteger
-       , bench "RoundedDouble/TowardInf/small" $ nf (fromIntegral :: Int64 -> Rounded 'TowardInf Double) smallInteger
-       , bench "RoundedDouble/TowardInf/medium" $ nf (fromIntegral :: Int64 -> Rounded 'TowardInf Double) mediumInteger
-       , bench "roundedFromInteger/Double/ToNearest/small" $ nf (roundedFromInteger ToNearest . fromIntegral :: Int64 -> Double) smallInteger
-       , bench "roundedFromInteger/Double/ToNearest/medium" $ nf (roundedFromInteger ToNearest . fromIntegral :: Int64 -> Double) mediumInteger
-       , bench "roundedFromInteger/Double/TowardInf/small" $ nf (roundedFromInteger TowardInf . fromIntegral :: Int64 -> Double) smallInteger
-       , bench "roundedFromInteger/Double/TowardInf/medium" $ nf (roundedFromInteger TowardInf . fromIntegral :: Int64 -> Double) mediumInteger
-       , bench "int64ToDouble/Double/ToNearest/small" $ nf (int64ToDouble ToNearest :: Int64 -> Double) smallInteger
-       , bench "int64ToDouble/Double/ToNearest/medium" $ nf (int64ToDouble ToNearest :: Int64 -> Double) mediumInteger
-       , bench "int64ToDouble/Double/TowardInf/small" $ nf (int64ToDouble TowardInf :: Int64 -> Double) smallInteger
-       , bench "int64ToDouble/Double/TowardInf/medium" $ nf (int64ToDouble TowardInf :: Int64 -> Double) mediumInteger
-       ]
-  , let pi' = 3.14159265358979323846264338327950 :: Rational
-        smallRational = 22 % 7 :: Rational
-        largeRational = 78326489123342523452342137498719847192 % 348912374981749170413424213275017 :: Rational
-    in bgroup "fromRational"
-       [ bench "Double/decimal" $ nf (fromRational :: Rational -> Double) pi'
-       , bench "Double/small" $ nf (fromRational :: Rational -> Double) smallRational
-       , bench "Double/large" $ nf (fromRational :: Rational -> Double) largeRational
-       , bench "RoundedDouble/ToNearest/decimal" $ nf (fromRational :: Rational -> Rounded 'ToNearest Double) pi'
-       , bench "RoundedDouble/ToNearest/small" $ nf (fromRational :: Rational -> Rounded 'ToNearest Double) smallRational
-       , bench "RoundedDouble/ToNearest/large" $ nf (fromRational :: Rational -> Rounded 'ToNearest Double) largeRational
-       , bench "RoundedDouble/TowardInf/decimal" $ nf (fromRational :: Rational -> Rounded 'TowardInf Double) pi'
-       , bench "RoundedDouble/TowardInf/small" $ nf (fromRational :: Rational -> Rounded 'TowardInf Double) smallRational
-       , bench "RoundedDouble/TowardInf/large" $ nf (fromRational :: Rational -> Rounded 'TowardInf Double) largeRational
-       , bench "IntervalDouble/decimal" $ nf (fromRational :: Rational -> Interval Double) pi'
-       , bench "IntervalDouble/small" $ nf (fromRational :: Rational -> Interval Double) smallRational
-       , bench "IntervalDouble/large" $ nf (fromRational :: Rational -> Interval Double) largeRational
-       ]
+  [ bgroup "fromInteger/to Double"
+    [ bgroup name $ map ($ value)
+      [ bench "plain" . nf (fromInteger :: Integer -> Double)
+      , bench "Rounded/ToNearest" . nf (fromInteger :: Integer -> Rounded 'ToNearest Double)
+      , bench "Rounded/TowardInf" . nf (fromInteger :: Integer -> Rounded 'TowardInf Double)
+      , bench "roundedFromInteger/ToNearest" . nf (roundedFromInteger ToNearest :: Integer -> Double)
+      , bench "roundedFromInteger/TowardInf" . nf (roundedFromInteger TowardInf :: Integer -> Double)
+      , bench "fp-ieee/ToNearest" . nf (fromIntegerTiesToEven :: Integer -> Double)
+      , bench "fp-ieee/TowardInf" . nf (fromIntegerTowardPositive :: Integer -> Double)
+      , bench "Interval/default" . nf (fromInteger :: Integer -> Interval Double)
+      , bench "Interval/individual" . nf (\n -> (fromIntegerTowardNegative n, fromIntegerTowardPositive n) :: (Double, Double))
+      , bench "Interval/fromIntegerR" . nf (\n -> case IEEE.Internal.fromIntegerR n of
+                                                    Pair (IEEE.Internal.RoundTowardNegative x) (IEEE.Internal.RoundTowardPositive y) -> (x, y) :: (Double, Double)
+                                           )
+      ]
+    | (name, value) <- [ ("small", -2^50 + 2^13 + 127)
+                       , ("medium", -2^60 + 42 * 2^53 - 137 * 2^24 + 3)
+                       , ("large",  -2^100 - 37 * 2^80 + 2^13 + 127)
+                       ] :: [(String, Integer)]
     ]
+  , bgroup "fromIntegral/Int64->Double"
+    [ bgroup name $ map ($ value)
+      [ bench "plain" . nf (fromIntegral :: Int64 -> Double)
+      , bench "Rounded/ToNearest" . nf (fromIntegral :: Int64 -> Rounded 'ToNearest Double)
+      , bench "Rounded/TowardInf" . nf (fromIntegral :: Int64 -> Rounded 'TowardInf Double)
+      , bench "roundedFromInteger/ToNearest" . nf (roundedFromInteger ToNearest . fromIntegral :: Int64 -> Double)
+      , bench "roundedFromInteger/TowardInf" . nf (roundedFromInteger TowardInf . fromIntegral :: Int64 -> Double)
+      , bench "fp-ieee/ToNearest" . nf (fromIntegralTiesToEven :: Int64 -> Double)
+      , bench "fp-ieee/TowardInf" . nf (fromIntegralTowardPositive :: Int64 -> Double)
+      , bench "int64ToDouble/ToNearest" . nf (int64ToDouble ToNearest :: Int64 -> Double)
+      , bench "int64ToDouble/TowardInf" . nf (int64ToDouble TowardInf :: Int64 -> Double)
+      , bench "Interval/default" . nf (fromIntegral :: Int64 -> Interval Double)
+      , bench "Interval/individual" . nf (\n -> (fromIntegralTowardNegative n, fromIntegralTowardPositive n) :: (Double, Double))
+      , bench "Interval/fromIntegralR" . nf (\n -> case IEEE.Internal.fromIntegralR n of
+                                                Pair (IEEE.Internal.RoundTowardNegative x) (IEEE.Internal.RoundTowardPositive y) -> (x, y) :: (Double, Double)
+                                            )
+      , bench "Interval/individual/C" . nf (\n -> (C.roundedDoubleFromInt64 TowardNegInf n, C.roundedDoubleFromInt64 TowardInf n))
+      ]
+    | (name, value) <- [ ("small", -2^50 + 2^13 + 127)
+                       , ("medium", -2^60 + 42 * 2^53 - 137 * 2^24 + 3)
+                       ] :: [(String, Int64)]
+    ]
+  , bgroup "fromIntegral/Word64->Double"
+    [ bgroup name $ map ($ value)
+      [ bench "plain" . nf (fromIntegral :: Word64 -> Double)
+      , bench "Rounded/ToNearest" . nf (fromIntegral :: Word64 -> Rounded 'ToNearest Double)
+      , bench "Rounded/TowardInf" . nf (fromIntegral :: Word64 -> Rounded 'TowardInf Double)
+      , bench "roundedFromInteger/ToNearest" . nf (roundedFromInteger ToNearest . fromIntegral :: Word64 -> Double)
+      , bench "roundedFromInteger/TowardInf" . nf (roundedFromInteger TowardInf . fromIntegral :: Word64 -> Double)
+      , bench "fp-ieee/ToNearest" . nf (fromIntegralTiesToEven :: Word64 -> Double)
+      , bench "fp-ieee/TowardInf" . nf (fromIntegralTowardPositive :: Word64 -> Double)
+      , bench "word64ToDouble/ToNearest" . nf (word64ToDouble ToNearest :: Word64 -> Double)
+      , bench "word64ToDouble/TowardInf" . nf (word64ToDouble TowardInf :: Word64 -> Double)
+      , bench "Interval/default" . nf (fromIntegral :: Word64 -> Interval Double)
+      , bench "Interval/individual" . nf (\n -> (fromIntegralTowardNegative n, fromIntegralTowardPositive n) :: (Double, Double))
+      , bench "Interval/fromIntegralR" . nf (\n -> case IEEE.Internal.fromIntegralR n of
+                                                Pair (IEEE.Internal.RoundTowardNegative x) (IEEE.Internal.RoundTowardPositive y) -> (x, y) :: (Double, Double)
+                                            )
+      , bench "Interval/individual/C" . nf (\n -> (C.roundedDoubleFromWord64 TowardNegInf n, C.roundedDoubleFromWord64 TowardInf n))
+      ]
+    | (name, value) <- [ ("small", 2^50 + 2^13 + 127)
+                       , ("medium", 2^63 + 42 * 2^53 - 137 * 2^24 + 3)
+                       ] :: [(String, Word64)]
+    ]
+  , bgroup "fromRational/to Double"
+    [ bgroup name $ map ($ value)
+      [ bench "plain" . nf (fromRational :: Rational -> Double)
+      , bench "Rounded/ToNearest" . nf (fromRational :: Rational -> Rounded 'ToNearest Double)
+      , bench "Rounded/TowardInf" . nf (fromRational :: Rational -> Rounded 'TowardInf Double)
+      , bench "fp-ieee/ToNearest" . nf (fromRationalTiesToEven :: Rational -> Double)
+      , bench "fp-ieee/TowardInf" . nf (fromRationalTowardPositive :: Rational -> Double)
+      , bench "Interval/default" . nf (fromRational :: Rational -> Interval Double)
+      , bench "Interval/individual" . nf (\x -> (fromRationalTowardNegative x :: Double, fromRationalTowardPositive x :: Double))
+      , bench "Interval/fromRationalR" . nf (\x -> case IEEE.Internal.fromRationalR x of
+                                                     Pair (IEEE.Internal.RoundTowardNegative a) (IEEE.Internal.RoundTowardPositive b) -> (a, b) :: (Double, Double)
+                                            )
+      ]
+    | (name, value) <- [ ("decimal", 3.14159265358979323846264338327950)
+                       , ("binary", 0xcafec0ffeecafec0ffeep-177)
+                       , ("small", 22 % 7)
+                       , ("large", 78326489123342523452342137498719847192 % 348912374981749170413424213275017)
+                       ] :: [(String, Rational)]
+    ]
+  ]
diff --git a/rounded-hw.cabal b/rounded-hw.cabal
--- a/rounded-hw.cabal
+++ b/rounded-hw.cabal
@@ -4,21 +4,21 @@
 --
 -- see: https://github.com/sol/hpack
 --
--- hash: 5ac460c3766d27889d7b32a2cbe50446f113a5403dec5125affc436d900f452d
+-- hash: c52684ece684d2a3e1a2bde6e2919d961a59bd69724c32a8e7ab1ac0b9230685
 
 name:           rounded-hw
-version:        0.1.0.0
+version:        0.2.0
 synopsis:       Directed rounding for built-in floating types
-description:    Please see the README on GitHub at <https://github.com/minoki/rounded-hw#readme>
+description:    Please see the README on GitHub at <https://github.com/minoki/haskell-floating-point/tree/master/rounded-hw#readme>
 category:       Numeric, Math
-homepage:       https://github.com/minoki/rounded-hw#readme
-bug-reports:    https://github.com/minoki/rounded-hw/issues
+homepage:       https://github.com/minoki/haskell-floating-point#readme
+bug-reports:    https://github.com/minoki/haskell-floating-point/issues
 author:         ARATA Mizuki
 maintainer:     minorinoki@gmail.com
 copyright:      2020 ARATA Mizuki
 license:        BSD3
 license-file:   LICENSE
-tested-with:    GHC == 8.6.5, GHC == 8.8.3
+tested-with:    GHC == 8.6.5, GHC == 8.8.4, GHC == 8.10.2
 build-type:     Custom
 extra-source-files:
     README.md
@@ -29,7 +29,7 @@
 
 source-repository head
   type: git
-  location: https://github.com/minoki/rounded-hw
+  location: https://github.com/minoki/haskell-floating-point
 
 custom-setup
   setup-depends:
@@ -85,7 +85,6 @@
       Numeric.Rounded.Hardware.Internal.Constants
       Numeric.Rounded.Hardware.Internal.Conversion
       Numeric.Rounded.Hardware.Internal.FloatUtil
-      Numeric.Rounded.Hardware.Internal.RoundedResult
       Numeric.Rounded.Hardware.Internal.Show
       Numeric.Rounded.Hardware.Backend.Default
       Numeric.Rounded.Hardware.Interval.ElementaryFunctions
@@ -95,7 +94,7 @@
       array
     , base >=4.12 && <5
     , deepseq
-    , integer-logarithms
+    , fp-ieee ==0.1.*
     , primitive
     , tagged
     , vector
@@ -150,7 +149,7 @@
     , base >=4.12 && <5
     , deepseq
     , doctest >=0.8
-    , integer-logarithms
+    , fp-ieee ==0.1.*
     , primitive
     , vector
   default-language: Haskell2010
@@ -160,7 +159,6 @@
   main-is: Spec.hs
   other-modules:
       ConstantsSpec
-      FloatUtilSpec
       FromIntegerSpec
       FromRationalSpec
       IntervalArithmeticSpec
@@ -177,8 +175,8 @@
     , array
     , base >=4.12 && <5
     , deepseq
+    , fp-ieee ==0.1.*
     , hspec
-    , integer-logarithms
     , primitive
     , random
     , rounded-hw
@@ -210,8 +208,8 @@
       array
     , base >=4.12 && <5
     , deepseq
+    , fp-ieee ==0.1.*
     , gauge
-    , integer-logarithms
     , primitive
     , rounded-hw
     , vector
diff --git a/src/Numeric/Rounded/Hardware/Backend/C.hs b/src/Numeric/Rounded/Hardware/Backend/C.hs
--- a/src/Numeric/Rounded/Hardware/Backend/C.hs
+++ b/src/Numeric/Rounded/Hardware/Backend/C.hs
@@ -32,6 +32,10 @@
   , CDouble(..)
   , VUM.MVector(..)
   , VU.Vector(..)
+  , roundedFloatFromInt64
+  , roundedFloatFromWord64
+  , roundedDoubleFromInt64
+  , roundedDoubleFromWord64
   ) where
 import           Control.DeepSeq (NFData (..))
 import           Data.Bifunctor
@@ -39,7 +43,6 @@
 import           Data.Int (Int64)
 import           Data.Primitive (Prim)
 import           Data.Primitive.ByteArray
-import           Data.Ratio
 import           Data.Tagged
 import qualified Data.Vector.Generic as VG
 import qualified Data.Vector.Generic.Mutable as VGM
@@ -87,23 +90,6 @@
   (F.roundedFromWord64 r x)
 {-# INLINE roundedFloatFromWord64 #-}
 
-roundedFloatFromInteger :: RoundingMode -> Integer -> Float
-roundedFloatFromInteger r x
-  | -0x1000000 <= x && x <= 0x1000000 {- abs x <= 2^24 -} = fromInteger x
-  | otherwise = fromInt r x
-{-# NOINLINE [1] roundedFloatFromInteger #-}
-
-{-# RULES
-"roundeFloatFromInteger/Int" forall r (x :: Int).
-  roundedFloatFromInteger r (fromIntegral x) = roundedFloatFromInt64 r (fromIntegral x)
-"roundeFloatFromInteger/Int64" forall r (x :: Int64).
-  roundedFloatFromInteger r (fromIntegral x) = roundedFloatFromInt64 r x
-"roundeFloatFromInteger/Word" forall r (x :: Word).
-  roundedFloatFromInteger r (fromIntegral x) = roundedFloatFromWord64 r (fromIntegral x)
-"roundeFloatFromInteger/Word64" forall r (x :: Word64).
-  roundedFloatFromInteger r (fromIntegral x) = roundedFloatFromWord64 r x
-  #-}
-
 intervalFloatFromInteger :: Integer -> (Rounded 'TowardNegInf Float, Rounded 'TowardInf Float)
 intervalFloatFromInteger x
   | -0x1000000 <= x && x <= 0x1000000 {- abs x <= 2^24 -} = (Rounded (fromInteger x), Rounded (fromInteger x))
@@ -127,8 +113,8 @@
   roundedFusedMultiplyAdd = coerce F.roundedFMA
   intervalMul x x' y y' = (coerce F.intervalMul_down x x' y y', coerce F.intervalMul_up x x' y y')
   intervalMulAdd x x' y y' z z' = (coerce F.intervalMulAdd_down x x' y y' z, coerce F.intervalMulAdd_up x x' y y' z')
-  roundedFromInteger r x = CFloat (roundedFloatFromInteger r x)
-  intervalFromInteger = coerce intervalFloatFromInteger
+  roundedFromInteger r x = CFloat (roundedFromInteger_default r x)
+  intervalFromInteger = (coerce `asTypeOf` (bimap (CFloat <$>) (CFloat <$>) .)) intervalFromInteger_default
   backendNameT = Tagged cBackendName
   {-# INLINE roundedAdd #-}
   {-# INLINE roundedSub #-}
@@ -142,7 +128,7 @@
   roundedDiv = coerce F.roundedDiv
   intervalDiv x x' y y' = (coerce F.intervalDiv_down x x' y y', coerce F.intervalDiv_up x x' y y')
   intervalDivAdd x x' y y' z z' = (coerce F.intervalDivAdd_down x x' y y' z, coerce F.intervalDivAdd_up x x' y y' z')
-  roundedFromRational r x = CFloat $ fromRatio r (numerator x) (denominator x)
+  roundedFromRational r x = CFloat (roundedFromRational_default r x)
   intervalFromRational = (coerce `asTypeOf` (bimap (CFloat <$>) (CFloat <$>) .)) intervalFromRational_default
   roundedFromRealFloat r x = coerce (roundedFloatFromRealFloat r x)
   {-# INLINE roundedDiv #-}
@@ -209,28 +195,6 @@
   (D.roundedFromWord64 r x)
 {-# INLINE roundedDoubleFromWord64 #-}
 
-roundedDoubleFromInteger :: RoundingMode -> Integer -> Double
-roundedDoubleFromInteger r x
-  | -0x20000000000000 <= x && x <= 0x20000000000000 {- abs x <= 2^53 -} = fromInteger x
-  | otherwise = fromInt r x
-{-# NOINLINE [1] roundedDoubleFromInteger #-}
-
-{-# RULES
-"roundedDoubleFromInteger/Int" forall r (x :: Int).
-  roundedDoubleFromInteger r (fromIntegral x) = roundedDoubleFromInt64 r (fromIntegral x)
-"roundedDoubleFromInteger/Int64" forall r (x :: Int64).
-  roundedDoubleFromInteger r (fromIntegral x) = roundedDoubleFromInt64 r x
-"roundedDoubleFromInteger/Word" forall r (x :: Word).
-  roundedDoubleFromInteger r (fromIntegral x) = roundedDoubleFromWord64 r (fromIntegral x)
-"roundedDoubleFromInteger/Word64" forall r (x :: Word64).
-  roundedDoubleFromInteger r (fromIntegral x) = roundedDoubleFromWord64 r x
-  #-}
-
-intervalDoubleFromInteger :: Integer -> (Rounded 'TowardNegInf Double, Rounded 'TowardInf Double)
-intervalDoubleFromInteger x
-  | -0x20000000000000 <= x && x <= 0x20000000000000 {- abs x <= 2^53 -} = (Rounded (fromInteger x), Rounded (fromInteger x))
-  | otherwise = intervalFromInteger_default x
-
 roundedDoubleFromRealFloat :: RealFloat a => RoundingMode -> a -> Double
 roundedDoubleFromRealFloat r x | isNaN x = 0/0
                                | isInfinite x = if x > 0 then 1/0 else -1/0
@@ -251,8 +215,8 @@
   roundedFusedMultiplyAdd = coerce D.roundedFMA
   intervalMul x x' y y' = (coerce D.intervalMul_down x x' y y', coerce D.intervalMul_up x x' y y')
   intervalMulAdd x x' y y' z z' = (coerce D.intervalMulAdd_down x x' y y' z, coerce D.intervalMulAdd_up x x' y y' z')
-  roundedFromInteger = coerce roundedDoubleFromInteger
-  intervalFromInteger = coerce intervalDoubleFromInteger
+  roundedFromInteger r x = CDouble (roundedFromInteger_default r x)
+  intervalFromInteger = (coerce `asTypeOf` (bimap (CDouble <$>) (CDouble <$>) .)) intervalFromInteger_default
   backendNameT = Tagged cBackendName
   {-# INLINE roundedAdd #-}
   {-# INLINE roundedSub #-}
@@ -266,7 +230,7 @@
   roundedDiv = coerce D.roundedDiv
   intervalDiv x x' y y' = (coerce D.intervalDiv_down x x' y y', coerce D.intervalDiv_up x x' y y')
   intervalDivAdd x x' y y' z z' = (coerce D.intervalDivAdd_down x x' y y' z, coerce D.intervalDivAdd_up x x' y y' z')
-  roundedFromRational r x = CDouble $ fromRatio r (numerator x) (denominator x)
+  roundedFromRational r x = CDouble (roundedFromRational_default r x)
   intervalFromRational = (coerce `asTypeOf` (bimap (CDouble <$>) (CDouble <$>) .)) intervalFromRational_default
   -- TODO: Specialize small case in ***FromRational?
   roundedFromRealFloat r x = coerce (roundedDoubleFromRealFloat r x)
diff --git a/src/Numeric/Rounded/Hardware/Backend/Default.hs b/src/Numeric/Rounded/Hardware/Backend/Default.hs
--- a/src/Numeric/Rounded/Hardware/Backend/Default.hs
+++ b/src/Numeric/Rounded/Hardware/Backend/Default.hs
@@ -1,13 +1,13 @@
 {-# LANGUAGE CPP #-}
-{-# LANGUAGE StandaloneDeriving #-}
-{-# LANGUAGE DerivingVia #-}
 {-# LANGUAGE DataKinds #-}
+{-# LANGUAGE DerivingVia #-}
 {-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE StandaloneDeriving #-}
 {-# OPTIONS_GHC -Wno-orphans -Wno-unused-imports #-}
 module Numeric.Rounded.Hardware.Backend.Default
   () where
-import           Numeric.Rounded.Hardware.Internal.Class
 import qualified Numeric.Rounded.Hardware.Backend.ViaRational as VR
+import           Numeric.Rounded.Hardware.Internal.Class
 #ifdef USE_FFI
 import qualified Numeric.Rounded.Hardware.Backend.C as C
 #ifdef USE_GHC_PRIM
@@ -20,10 +20,11 @@
 import           Numeric.Rounded.Hardware.Backend.Float128 ()
 #endif
 #endif
+import           Data.Coerce
 import qualified Data.Vector.Storable as VS
 import qualified Data.Vector.Unboxed as VU
+import           Numeric.Floating.IEEE
 import           Unsafe.Coerce
-import           Data.Coerce
 
 #ifdef USE_FFI
 #ifdef USE_GHC_PRIM
@@ -91,19 +92,19 @@
 -- orphaned rules
 {-# RULES
 "fromIntegral/a->Rounded ToNearest Float"
-  forall x. fromIntegral x = Rounded (roundedFromInteger ToNearest (fromIntegral x)) :: Rounded 'ToNearest Float
+  fromIntegral = \x -> (Rounded (fromIntegralTiesToEven x) :: Rounded 'ToNearest Float)
 "fromIntegral/a->Rounded TowardInf Float"
-  forall x. fromIntegral x = Rounded (roundedFromInteger TowardInf (fromIntegral x)) :: Rounded 'TowardInf Float
+  fromIntegral = \x -> (Rounded (fromIntegralTowardPositive x) :: Rounded 'TowardInf Float)
 "fromIntegral/a->Rounded TowardNegInf Float"
-  forall x. fromIntegral x = Rounded (roundedFromInteger TowardNegInf (fromIntegral x)) :: Rounded 'TowardNegInf Float
+  fromIntegral = \x -> (Rounded (fromIntegralTowardNegative x) :: Rounded 'TowardNegInf Float)
 "fromIntegral/a->Rounded TowardZero Float"
-  forall x. fromIntegral x = Rounded (roundedFromInteger TowardZero (fromIntegral x)) :: Rounded 'TowardZero Float
+  fromIntegral = \x -> (Rounded (fromIntegralTowardZero x) :: Rounded 'TowardZero Float)
 "fromIntegral/a->Rounded ToNearest Double"
-  forall x. fromIntegral x = Rounded (roundedFromInteger ToNearest (fromIntegral x)) :: Rounded 'ToNearest Double
+  fromIntegral = \x -> (Rounded (fromIntegralTiesToEven x) :: Rounded 'ToNearest Double)
 "fromIntegral/a->Rounded TowardInf Double"
-  forall x. fromIntegral x = Rounded (roundedFromInteger TowardInf (fromIntegral x)) :: Rounded 'TowardInf Double
+  fromIntegral = \x -> (Rounded (fromIntegralTowardPositive x) :: Rounded 'TowardInf Double)
 "fromIntegral/a->Rounded TowardNegInf Double"
-  forall x. fromIntegral x = Rounded (roundedFromInteger TowardNegInf (fromIntegral x)) :: Rounded 'TowardNegInf Double
+  fromIntegral = \x -> (Rounded (fromIntegralTowardNegative x) :: Rounded 'TowardNegInf Double)
 "fromIntegral/a->Rounded TowardZero Double"
-  forall x. fromIntegral x = Rounded (roundedFromInteger TowardZero (fromIntegral x)) :: Rounded 'TowardZero Double
+  fromIntegral = \x -> (Rounded (fromIntegralTowardZero x) :: Rounded 'TowardZero Double)
   #-}
diff --git a/src/Numeric/Rounded/Hardware/Backend/FastFFI.hs b/src/Numeric/Rounded/Hardware/Backend/FastFFI.hs
--- a/src/Numeric/Rounded/Hardware/Backend/FastFFI.hs
+++ b/src/Numeric/Rounded/Hardware/Backend/FastFFI.hs
@@ -27,6 +27,7 @@
 {-# LANGUAGE TypeFamilies #-}
 {-# LANGUAGE UnboxedTuples #-}
 {-# LANGUAGE UnliftedFFITypes #-}
+{-# OPTIONS_GHC -fobject-code #-}
 module Numeric.Rounded.Hardware.Backend.FastFFI
   ( CDouble(..)
   , fastIntervalAdd
diff --git a/src/Numeric/Rounded/Hardware/Backend/Float128.hs b/src/Numeric/Rounded/Hardware/Backend/Float128.hs
--- a/src/Numeric/Rounded/Hardware/Backend/Float128.hs
+++ b/src/Numeric/Rounded/Hardware/Backend/Float128.hs
@@ -4,7 +4,6 @@
 module Numeric.Rounded.Hardware.Backend.Float128
   (
   ) where
-import           Data.Ratio
 import           Data.Tagged
 import           Foreign.C.String (CString, peekCString)
 import           Foreign.Marshal (alloca, with)
@@ -125,7 +124,7 @@
   roundedSub = roundedSub_f128
   roundedMul = roundedMul_f128
   roundedFusedMultiplyAdd = roundedFMA_f128
-  roundedFromInteger = fromInt
+  roundedFromInteger = roundedFromInteger_default
   intervalFromInteger = intervalFromInteger_default
   backendNameT = Tagged cBackendName
   {-# INLINE roundedAdd #-}
@@ -137,7 +136,7 @@
 
 instance RoundedFractional Float128 where
   roundedDiv = roundedDiv_f128
-  roundedFromRational r x = fromRatio r (numerator x) (denominator x)
+  roundedFromRational = roundedFromRational_default
   intervalFromRational = intervalFromRational_default
   {-# INLINE roundedDiv #-}
   {-# INLINE roundedFromRational #-}
diff --git a/src/Numeric/Rounded/Hardware/Backend/ViaRational.hs b/src/Numeric/Rounded/Hardware/Backend/ViaRational.hs
--- a/src/Numeric/Rounded/Hardware/Backend/ViaRational.hs
+++ b/src/Numeric/Rounded/Hardware/Backend/ViaRational.hs
@@ -8,8 +8,6 @@
 import           Control.DeepSeq (NFData (..))
 import           Control.Exception (assert)
 import           Data.Coerce
-import           Data.Functor.Product
-import           Data.Ratio
 import           Data.Tagged
 import qualified Data.Vector.Generic as VG
 import qualified Data.Vector.Generic.Mutable as VGM
@@ -21,7 +19,7 @@
 import           Numeric.Rounded.Hardware.Internal.Class
 import           Numeric.Rounded.Hardware.Internal.Constants
 import           Numeric.Rounded.Hardware.Internal.Conversion
-import           Numeric.Rounded.Hardware.Internal.FloatUtil (nextDown, nextUp)
+import           Numeric.Floating.IEEE (isFinite, nextDown, nextUp)
 
 newtype ViaRational a = ViaRational a
   deriving (Eq,Ord,Show,Generic,Num,Storable)
@@ -59,20 +57,21 @@
     | isNaN x || isNaN y || isInfinite x || isInfinite y || isNegativeZero x || isNegativeZero y = ViaRational (x * y)
     | otherwise = roundedFromRational r (toRational x * toRational y)
   roundedFusedMultiplyAdd r (ViaRational x) (ViaRational y) (ViaRational z)
-    | isNaN x || isNaN y || isNaN z || isInfinite x || isInfinite y || isInfinite z = ViaRational (x * y + z)
-    | otherwise = case toRational x * toRational y + toRational z of
+    | isFinite x && isFinite y && isFinite z = case toRational x * toRational y + toRational z of
                     0 -> if z == 0 && isNegativeZero (x * y) == isNegativeZero z
                          then ViaRational z
                          else ViaRational roundedZero
                     w -> roundedFromRational r w
+    | isFinite x && isFinite y = ViaRational z -- Infinity or NaN
+    | otherwise = ViaRational (x * y + z)
       where roundedZero = case r of
               ToNearest    ->  0
               TowardNegInf -> -0
               TowardInf    ->  0
               TowardZero   ->  0
-  roundedFromInteger r x = ViaRational (fromInt r x)
-  intervalFromInteger x = case fromIntF x :: Product (Rounded 'TowardNegInf) (Rounded 'TowardInf) a of
-    Pair a b -> (ViaRational <$> a, ViaRational <$> b)
+  roundedFromInteger r x = ViaRational (roundedFromInteger_default r x)
+  intervalFromInteger x = case intervalFromInteger_default x of
+    (a, b) -> (ViaRational <$> a, ViaRational <$> b)
   backendNameT = Tagged "via Rational"
   {-# INLINE roundedFromInteger #-}
   {-# INLINE intervalFromInteger #-}
@@ -83,13 +82,13 @@
   roundedDiv r (ViaRational x) (ViaRational y)
     | isNaN x || isNaN y || isInfinite x || isInfinite y || x == 0 || y == 0 = ViaRational (x / y)
     | otherwise = roundedFromRational r (toRational x / toRational y)
-  roundedFromRational r x = ViaRational $ fromRatio r (numerator x) (denominator x)
+  roundedFromRational r x = ViaRational $ roundedFromRational_default r x
   roundedFromRealFloat r x | isNaN x = ViaRational (0/0)
                            | isInfinite x = ViaRational (if x > 0 then 1/0 else -1/0)
                            | isNegativeZero x = ViaRational (-0)
                            | otherwise = roundedFromRational r (toRational x)
-  intervalFromRational x = case fromRatioF (numerator x) (denominator x) :: Product (Rounded 'TowardNegInf) (Rounded 'TowardInf) a of
-    Pair a b -> (ViaRational <$> a, ViaRational <$> b)
+  intervalFromRational x = case intervalFromRational_default x of
+    (a, b) -> (ViaRational <$> a, ViaRational <$> b)
   {-# INLINE roundedFromRational #-}
   {-# INLINE intervalFromRational #-}
   {-# SPECIALIZE instance RoundedFractional (ViaRational Float) #-}
diff --git a/src/Numeric/Rounded/Hardware/Backend/X87LongDouble.hs b/src/Numeric/Rounded/Hardware/Backend/X87LongDouble.hs
--- a/src/Numeric/Rounded/Hardware/Backend/X87LongDouble.hs
+++ b/src/Numeric/Rounded/Hardware/Backend/X87LongDouble.hs
@@ -3,7 +3,6 @@
 module Numeric.Rounded.Hardware.Backend.X87LongDouble
   (
   ) where
-import           Data.Ratio
 import           Data.Tagged
 import           Foreign.C.String (CString, peekCString)
 import           Foreign.Marshal (alloca, with)
@@ -124,7 +123,7 @@
   roundedSub = roundedSub_ld
   roundedMul = roundedMul_ld
   roundedFusedMultiplyAdd = roundedFMA_ld
-  roundedFromInteger = fromInt
+  roundedFromInteger = roundedFromInteger_default
   intervalFromInteger = intervalFromInteger_default
   backendNameT = Tagged cBackendName
   {-# INLINE roundedAdd #-}
@@ -138,7 +137,7 @@
 -- Note that 'LongDouble' may not work correctly on Win64.
 instance RoundedFractional LongDouble where
   roundedDiv = roundedDiv_ld
-  roundedFromRational r x = fromRatio r (numerator x) (denominator x)
+  roundedFromRational = roundedFromRational_default
   intervalFromRational = intervalFromRational_default
   {-# INLINE roundedDiv #-}
   {-# INLINE roundedFromRational #-}
diff --git a/src/Numeric/Rounded/Hardware/Internal.hs b/src/Numeric/Rounded/Hardware/Internal.hs
--- a/src/Numeric/Rounded/Hardware/Internal.hs
+++ b/src/Numeric/Rounded/Hardware/Internal.hs
@@ -8,6 +8,5 @@
 import           Numeric.Rounded.Hardware.Internal.Constants     as Internal
 import           Numeric.Rounded.Hardware.Internal.Conversion    as Internal
 import           Numeric.Rounded.Hardware.Internal.FloatUtil     as Internal
-import           Numeric.Rounded.Hardware.Internal.RoundedResult as Internal
 import           Numeric.Rounded.Hardware.Internal.Rounding      as Internal
 import           Numeric.Rounded.Hardware.Internal.Show          as Internal
diff --git a/src/Numeric/Rounded/Hardware/Internal/Class.hs b/src/Numeric/Rounded/Hardware/Internal/Class.hs
--- a/src/Numeric/Rounded/Hardware/Internal/Class.hs
+++ b/src/Numeric/Rounded/Hardware/Internal/Class.hs
@@ -18,6 +18,8 @@
 import           Data.Ratio
 import           Data.Tagged
 import qualified Data.Vector.Generic as VG
+import           Numeric.Floating.IEEE
+import           Numeric.Rounded.Hardware.Internal.Conversion
 import           Numeric.Rounded.Hardware.Internal.Rounding
 import           Prelude hiding (fromInteger, fromRational, recip, sqrt, (*),
                           (+), (-), (/))
@@ -30,6 +32,8 @@
   roundedMul :: RoundingMode -> a -> a -> a
   roundedFusedMultiplyAdd :: RoundingMode -> a -> a -> a -> a
   roundedFromInteger :: RoundingMode -> Integer -> a
+  default roundedFromInteger :: RealFloat a => RoundingMode -> Integer -> a
+  roundedFromInteger = roundedFromInteger_default
   -- roundedToFloat :: RoundingMode -> a -> Float
   -- roundedToDouble :: RoundingMode -> a -> Double
 
@@ -95,6 +99,8 @@
   default roundedRecip :: Num a => RoundingMode -> a -> a
   roundedRecip r = roundedDiv r 1
   roundedFromRational :: RoundingMode -> Rational -> a
+  default roundedFromRational :: RealFloat a => RoundingMode -> Rational -> a
+  roundedFromRational = roundedFromRational_default
   roundedFromRealFloat :: RealFloat b => RoundingMode -> b -> a
   default roundedFromRealFloat :: (Fractional a, RealFloat b) => RoundingMode -> b -> a
   roundedFromRealFloat r x | isNaN x = 0 Prelude./ 0
diff --git a/src/Numeric/Rounded/Hardware/Internal/Conversion.hs b/src/Numeric/Rounded/Hardware/Internal/Conversion.hs
--- a/src/Numeric/Rounded/Hardware/Internal/Conversion.hs
+++ b/src/Numeric/Rounded/Hardware/Internal/Conversion.hs
@@ -1,203 +1,44 @@
-{-# LANGUAGE HexFloatLiterals #-}
-{-# LANGUAGE BangPatterns #-}
 {-# LANGUAGE DataKinds #-}
-{-# LANGUAGE ScopedTypeVariables #-}
 module Numeric.Rounded.Hardware.Internal.Conversion
-  ( fromInt
-  , fromIntF
+  ( roundedFromInteger_default
+  , roundedFromRational_default
   , intervalFromInteger_default
-  , fromRatio
-  , fromRatioF
+  , intervalFromIntegral
   , intervalFromRational_default
   ) where
-import Numeric.Rounded.Hardware.Internal.Rounding
-import Numeric.Rounded.Hardware.Internal.RoundedResult
-import Numeric.Rounded.Hardware.Internal.FloatUtil
-import Data.Bits
-import Data.Functor.Product
-import Math.NumberTheory.Logarithms (integerLog2')
-import Data.Ratio
-import Control.Exception (assert)
--- import GHC.Integer.Logarithms.Internals (integerLog2IsPowerOf2#)
--- integerLog2IsPowerOf2# :: Integer -> (# Int#, Int# #)
-
-intervalFromInteger_default :: RealFloat a => Integer -> (Rounded 'TowardNegInf a, Rounded 'TowardInf a)
-intervalFromInteger_default x = case fromIntF x of Pair a b -> (a, b)
-{-# SPECIALIZE intervalFromInteger_default :: Integer -> (Rounded 'TowardNegInf Float, Rounded 'TowardInf Float) #-}
-{-# SPECIALIZE intervalFromInteger_default :: Integer -> (Rounded 'TowardNegInf Double, Rounded 'TowardInf Double) #-}
-
-intervalFromRational_default :: RealFloat a => Rational -> (Rounded 'TowardNegInf a, Rounded 'TowardInf a)
-intervalFromRational_default x = case fromRatioF (numerator x) (denominator x) of Pair a b -> (a, b)
-{-# SPECIALIZE intervalFromRational_default :: Rational -> (Rounded 'TowardNegInf Float, Rounded 'TowardInf Float) #-}
-{-# SPECIALIZE intervalFromRational_default :: Rational -> (Rounded 'TowardNegInf Double, Rounded 'TowardInf Double) #-}
-
-fromInt :: RealFloat a => RoundingMode -> Integer -> a
-fromInt r n = withRoundingMode (fromIntF n) r
-{-# SPECIALIZE fromInt :: RoundingMode -> Integer -> Float #-}
-{-# SPECIALIZE fromInt :: RoundingMode -> Integer -> Double #-}
+import           Data.Functor.Product
+import           Numeric.Floating.IEEE
+import           Numeric.Floating.IEEE.Internal (fromIntegerR, fromIntegralR,
+                                                 fromRationalR,
+                                                 roundTowardNegative,
+                                                 roundTowardPositive)
+import           Numeric.Rounded.Hardware.Internal.Rounding
 
-fromIntF :: forall a f. (RealFloat a, Result f) => Integer -> f a
-fromIntF !_ | floatRadix (undefined :: a) /= 2 = error "radix other than 2 is not supported"
-fromIntF 0 = exact 0
-fromIntF n | n < 0 = negate <$> withOppositeRoundingMode (fromPositiveIntF (- n))
-           | otherwise = fromPositiveIntF n
-{-# INLINE fromIntF #-}
+roundedFromInteger_default :: RealFloat a => RoundingMode -> Integer -> a
+roundedFromInteger_default ToNearest    = fromIntegerTiesToEven
+roundedFromInteger_default TowardZero   = fromIntegerTowardZero
+roundedFromInteger_default TowardInf    = fromIntegerTowardPositive
+roundedFromInteger_default TowardNegInf = fromIntegerTowardNegative
+{-# INLINE roundedFromInteger_default #-}
 
--- n > 0
-fromPositiveIntF :: forall a f. (RealFloat a, Result f) => Integer -> f a
-fromPositiveIntF !n
-  = let !k = integerLog2' n -- floor (log2 n)
-        -- 2^k <= n < 2^(k+1)
-        !fDigits = floatDigits (undefined :: a) -- 53 for Double
-    in if k < fDigits
-       then exact (fromInteger n)
-       else let e = k - (fDigits - 1)
-                  -- (!q, !r) = n `quotRem` (1 `unsafeShiftL` e)
-                q = n `unsafeShiftR` e
-                r = n .&. ((1 `unsafeShiftL` e) - 1)
-                    -- 2^52 <= q < 2^53, 0 <= r < 2^(k-52)
-                (_expMin, !expMax) = floatRange (undefined :: a) -- (-1021, 1024) for Double
-            in if k >= expMax
-               then
-                 -- infinity
-                 inexact (1 / 0) -- ToNearest
-                         (1 / 0) -- TowardInf
-                         maxFinite_ieee -- TowardNegInf
-                         maxFinite_ieee -- TowardZero
-               else
-                 if r == 0
-                 then exact $ encodeFloat q e -- exact
-                 else
-                   -- inexact
-                   let down = encodeFloat q e
-                       up = encodeFloat (q + 1) e
-                       toNearest = case compare r (1 `unsafeShiftL` (e-1)) of
-                         LT -> down
-                         EQ | even q -> down
-                            | otherwise -> up
-                         GT -> up
-                   in inexact toNearest up down down
-{-# SPECIALIZE fromPositiveIntF :: Integer -> DynamicRoundingMode Float #-}
-{-# SPECIALIZE fromPositiveIntF :: Integer -> OppositeRoundingMode DynamicRoundingMode Float #-}
-{-# SPECIALIZE fromPositiveIntF :: Rounding r => Integer -> Rounded r Float #-}
-{-# SPECIALIZE fromPositiveIntF :: Rounding r => Integer -> OppositeRoundingMode (Rounded r) Float #-}
-{-# SPECIALIZE fromPositiveIntF :: Integer -> Product (Rounded 'TowardNegInf) (Rounded 'TowardInf) Float #-}
-{-# SPECIALIZE fromPositiveIntF :: Integer -> OppositeRoundingMode (Product (Rounded 'TowardNegInf) (Rounded 'TowardInf)) Float #-}
-{-# SPECIALIZE fromPositiveIntF :: Integer -> DynamicRoundingMode Double #-}
-{-# SPECIALIZE fromPositiveIntF :: Integer -> OppositeRoundingMode DynamicRoundingMode Double #-}
-{-# SPECIALIZE fromPositiveIntF :: Rounding r => Integer -> Rounded r Double #-}
-{-# SPECIALIZE fromPositiveIntF :: Rounding r => Integer -> OppositeRoundingMode (Rounded r) Double #-}
-{-# SPECIALIZE fromPositiveIntF :: Integer -> Product (Rounded 'TowardNegInf) (Rounded 'TowardInf) Double #-}
-{-# SPECIALIZE fromPositiveIntF :: Integer -> OppositeRoundingMode (Product (Rounded 'TowardNegInf) (Rounded 'TowardInf)) Double #-}
+roundedFromRational_default :: RealFloat a => RoundingMode -> Rational -> a
+roundedFromRational_default ToNearest    = fromRationalTiesToEven
+roundedFromRational_default TowardZero   = fromRationalTowardZero
+roundedFromRational_default TowardInf    = fromRationalTowardPositive
+roundedFromRational_default TowardNegInf = fromRationalTowardNegative
+{-# INLINE roundedFromRational_default #-}
 
-fromRatio :: (RealFloat a)
-          => RoundingMode
-          -> Integer -- ^ numerator
-          -> Integer -- ^ denominator
-          -> a
-fromRatio r n d = withRoundingMode (fromRatioF n d) r
-{-# SPECIALIZE fromRatio :: RoundingMode -> Integer -> Integer -> Float #-}
-{-# SPECIALIZE fromRatio :: RoundingMode -> Integer -> Integer -> Double #-}
+intervalFromInteger_default :: RealFloat a => Integer -> (Rounded 'TowardNegInf a, Rounded 'TowardInf a)
+intervalFromInteger_default x = case fromIntegerR x of
+  Pair a b -> (Rounded (roundTowardNegative a), Rounded (roundTowardPositive b))
+{-# INLINE intervalFromInteger_default #-}
 
-fromRatioF :: forall a f. (RealFloat a, Result f)
-           => Integer -- ^ numerator
-           -> Integer -- ^ denominator
-           -> f a
-fromRatioF !_ !_ | floatRadix (undefined :: a) /= 2 = error "radix other than 2 is not supported"
-fromRatioF 0 _ = exact 0
-fromRatioF n 0 | n > 0 = exact (1 / 0) -- positive infinity
-               | otherwise = exact (- 1 / 0) -- negative infinity
-fromRatioF n d | d < 0 = error "fromRatio: negative denominator"
-               | n < 0 = negate <$> withOppositeRoundingMode (fromPositiveRatioF (- n) d)
-               | otherwise = fromPositiveRatioF n d
-{-# INLINE fromRatioF #-}
+intervalFromRational_default :: RealFloat a => Rational -> (Rounded 'TowardNegInf a, Rounded 'TowardInf a)
+intervalFromRational_default x = case fromRationalR x of
+  Pair a b -> (Rounded (roundTowardNegative a), Rounded (roundTowardPositive b))
+{-# INLINE intervalFromRational_default #-}
 
--- n > 0, d > 0
-fromPositiveRatioF :: forall a f. (RealFloat a, Result f)
-                   => Integer -> Integer -> f a
-fromPositiveRatioF !n !d
-  = let ln, ld, e :: Int
-        ln = integerLog2' n
-        ld = integerLog2' d
-        e = ln - ld - fDigits
-        q, r, d_ :: Integer
-        d_ | e >= 0 = d `unsafeShiftL` e
-           | otherwise = d
-        (!q, !r) | e >= 0 = n `quotRem` d_
-                 | otherwise = (n `unsafeShiftL` (-e)) `quotRem` d
-        -- e >= 0: n = q * (d * 2^e) + r, 0 <= r < d * 2^e
-        -- e <= 0: n * 2^(-e) = q * d + r, 0 <= r < d
-        -- n / d * 2^^(-e) = q + r / d_
-        -- 52 <= log2 q < 54
-        q', r', d' :: Integer
-        e' :: Int
-        (!q', !r', !d', !e') | q < (1 `unsafeShiftL` fDigits) = (q, r, d_, e)
-                             | otherwise = let (q'', r'') = q `quotRem` 2
-                                           in (q'', r'' * d_ + r, 2 * d_, e + 1)
-        -- n / d * 2^^(-e') = q' + r' / d', 2^52 <= q' < 2^53, 0 <= r' < d'
-        -- q' * 2^^e' <= n/d < (q'+1) * 2^^e', 2^52 <= q' < 2^53
-        -- (q'/2^53) * 2^^(e'+53) <= n/d < (q'+1)/2^53 * 2^^(e'+53), 1/2 <= q'/2^53 < 1
-        -- normal: 0x1p-1022 <= x <= 0x1.fffffffffffffp+1023
-    in assert (n % d * 2^^(-e) == fromInteger q + r % d_) $
-       assert (n % d * 2^^(-e') == fromInteger q' + r' % d') $
-       if expMin <= e' + fDigits && e' + fDigits <= expMax
-       then
-         -- normal
-         if r' == 0
-         then
-           exact $ encodeFloat q' e' -- exact
-         else
-           -- inexact
-           let down = encodeFloat q' e'
-               up = encodeFloat (q' + 1) e' -- may be infinity
-               toNearest = case compare (2 * r') d' of
-                 LT -> down
-                 EQ | even q' -> down
-                    | otherwise -> up -- q' + 1 is even
-                 GT -> up
-           in inexact toNearest up down down
-       else
-         -- infinity or subnormal
-         if expMax <= e' + fDigits
-         then
-           -- infinity
-           inexact (1 / 0) -- ToNearest
-                   (1 / 0) -- TowardInf
-                   maxFinite_ieee -- TowardNegInf
-                   maxFinite_ieee -- TowardZero
-         else
-           -- subnormal
-           -- e' + fDigits < expMin (or, e' < expMin - fDigits = -1074)
-           -- 0 <= rounded(n/d) <= 2^(expMin - 1) = 0x1p-1022, minimum (positive) subnormal: 0x1p-1074
-           let (!q'', !r'') = q' `quotRem` (1 `unsafeShiftL` (expMin - fDigits - e'))
-               -- q' = q'' * 2^(expMin - fDigits - e') + r'', 0 <= r'' < 2^(expMin - fDigits - e')
-               -- 2^(fDigits-1) <= q' = q'' * 2^(expMin - fDigits - e') + r'' < 2^fDigits
-               -- n / d * 2^^(-e') = q' + r' / d' = q'' * 2^(expMin - fDigits - e') + r'' + r' / d'
-               -- n / d = q'' * 2^^(expMin - fDigits) + (r'' + r' / d') * 2^^e'
-               -- 0 <= r'' < 2^(expMin - fDigits - e')
-           in if r' == 0 && r'' == 0
-              then exact $ encodeFloat q'' (expMin - fDigits) -- exact
-              else let down = encodeFloat q'' (expMin - fDigits)
-                       up = encodeFloat (q'' + 1) (expMin - fDigits)
-                       toNearest = case compare r'' (1 `unsafeShiftL` (expMin - fDigits - e' - 1)) of
-                         LT -> down
-                         GT -> up
-                         EQ | r' /= 0   -> up
-                            | even q'   -> down
-                            | otherwise -> up
-                   in inexact toNearest up down down
-  where
-    !fDigits = floatDigits (undefined :: a) -- 53 for Double
-    (!expMin, !expMax) = floatRange (undefined :: a) -- (-1021, 1024) for Double
-{-# SPECIALIZE fromPositiveRatioF :: Integer -> Integer -> DynamicRoundingMode Float #-}
-{-# SPECIALIZE fromPositiveRatioF :: Integer -> Integer -> OppositeRoundingMode DynamicRoundingMode Float #-}
-{-# SPECIALIZE fromPositiveRatioF :: Rounding r => Integer -> Integer -> Rounded r Float #-}
-{-# SPECIALIZE fromPositiveRatioF :: Rounding r => Integer -> Integer -> OppositeRoundingMode (Rounded r) Float #-}
-{-# SPECIALIZE fromPositiveRatioF :: Integer -> Integer -> Product (Rounded 'TowardNegInf) (Rounded 'TowardInf) Float #-}
-{-# SPECIALIZE fromPositiveRatioF :: Integer -> Integer -> OppositeRoundingMode (Product (Rounded 'TowardNegInf) (Rounded 'TowardInf)) Float #-}
-{-# SPECIALIZE fromPositiveRatioF :: Integer -> Integer -> DynamicRoundingMode Double #-}
-{-# SPECIALIZE fromPositiveRatioF :: Integer -> Integer -> OppositeRoundingMode DynamicRoundingMode Double #-}
-{-# SPECIALIZE fromPositiveRatioF :: Rounding r => Integer -> Integer -> Rounded r Double #-}
-{-# SPECIALIZE fromPositiveRatioF :: Rounding r => Integer -> Integer -> OppositeRoundingMode (Rounded r) Double #-}
-{-# SPECIALIZE fromPositiveRatioF :: Integer -> Integer -> Product (Rounded 'TowardNegInf) (Rounded 'TowardInf) Double #-}
-{-# SPECIALIZE fromPositiveRatioF :: Integer -> Integer -> OppositeRoundingMode (Product (Rounded 'TowardNegInf) (Rounded 'TowardInf)) Double #-}
+intervalFromIntegral :: (Integral i, RealFloat a) => i -> (Rounded 'TowardNegInf a, Rounded 'TowardInf a)
+intervalFromIntegral x = case fromIntegralR x of
+  Pair a b -> (Rounded (roundTowardNegative a), Rounded (roundTowardPositive b))
+{-# INLINE intervalFromIntegral #-}
diff --git a/src/Numeric/Rounded/Hardware/Internal/FloatUtil.hs b/src/Numeric/Rounded/Hardware/Internal/FloatUtil.hs
--- a/src/Numeric/Rounded/Hardware/Internal/FloatUtil.hs
+++ b/src/Numeric/Rounded/Hardware/Internal/FloatUtil.hs
@@ -4,317 +4,11 @@
   ( nextUp
   , nextDown
   , nextTowardZero
-  , minPositive_ieee
-  , maxFinite_ieee
   , distanceUlp
   , fusedMultiplyAdd
   ) where
-import           Data.Bits
 import           Data.Ratio
-import           GHC.Float (castDoubleToWord64, castFloatToWord32,
-                            castWord32ToFloat, castWord64ToDouble)
-
--- $setup
--- >>> :set -XHexFloatLiterals -XNumericUnderscores
-
--- |
--- prop> (minPositive_ieee :: Double) == 0x1p-1074
--- prop> (minPositive_ieee :: Float) == 0x1p-149
-minPositive_ieee :: RealFloat a => a
-minPositive_ieee = let d = floatDigits x
-                       (expMin,_expMax) = floatRange x
-                       x = encodeFloat 1 (expMin - d)
-                   in x
-{-# SPECIALIZE minPositive_ieee :: Double #-}
-{-# SPECIALIZE minPositive_ieee :: Float #-}
-
--- |
--- prop> (maxFinite_ieee :: Double) == 0x1.ffff_ffff_ffff_fp+1023
--- prop> (maxFinite_ieee :: Float) == 0x1.fffffep+127
-maxFinite_ieee :: RealFloat a => a
-maxFinite_ieee = let d = floatDigits x
-                     (_expMin,expMax) = floatRange x
-                     r = floatRadix x
-                     x = encodeFloat (r ^! d - 1) (expMax - d)
-                 in x
-{-# SPECIALIZE maxFinite_ieee :: Double #-}
-{-# SPECIALIZE maxFinite_ieee :: Float #-}
-
--- A variant of (^) allowing constant folding for base = 2
-infixr 8 ^!
-(^!) :: Integer -> Int -> Integer
-(^!) = (^)
-{-# INLINE [2] (^!) #-}
-{-# RULES
-"2^!" forall y. 2 ^! y = staticIf (y >= 0) (1 `shiftL` y) (2 ^ y)
-  #-}
-
-staticIf :: Bool -> a -> a -> a
-staticIf _ _ x = x
-{-# INLINE [0] staticIf #-}
-{-# RULES
-"staticIf/True" forall x y. staticIf True x y = x
-"staticIf/False" forall x y. staticIf False x y = y
-  #-}
-
--- |
--- prop> nextUp 1 == (0x1.0000_0000_0000_1p0 :: Double)
--- prop> nextUp 1 == (0x1.000002p0 :: Float)
--- prop> nextUp (1/0) == (1/0 :: Double)
--- prop> nextUp (-1/0) == (- maxFinite_ieee :: Double)
--- prop> nextUp 0 == (0x1p-1074 :: Double)
--- prop> nextUp (-0) == (0x1p-1074 :: Double)
--- prop> nextUp (-0x1p-1074) == (-0 :: Double)
--- prop> isNegativeZero (nextUp (-0x1p-1074) :: Double)
-nextUp :: RealFloat a => a -> a
-nextUp x | not (isIEEE x) = error "non-IEEE numbers are not supported"
-         | floatRadix x /= 2 = error "non-binary types are not supported"
-         | isNaN x || (isInfinite x && x > 0) = x -- NaN or positive infinity
-         | x >= 0 = nextUp_ieee_positive x
-         | otherwise = - nextDown_ieee_positive (- x)
-{-# INLINE [1] nextUp #-}
-
--- |
--- prop> nextDown 1 == (0x1.ffff_ffff_ffff_fp-1 :: Double)
--- prop> nextDown 1 == (0x1.fffffep-1 :: Float)
--- prop> nextDown (1/0) == (maxFinite_ieee :: Double)
--- prop> nextDown (-1/0) == (-1/0 :: Double)
--- prop> nextDown 0 == (-0x1p-1074 :: Double)
--- prop> nextDown (-0) == (-0x1p-1074 :: Double)
--- prop> nextDown 0x1p-1074 == (0 :: Double)
-nextDown :: RealFloat a => a -> a
-nextDown x | not (isIEEE x) = error "non-IEEE numbers are not supported"
-           | floatRadix x /= 2 = error "non-binary types are not supported"
-           | isNaN x || (isInfinite x && x < 0) = x -- NaN or negative infinity
-           | x >= 0 = nextDown_ieee_positive x
-           | otherwise = - nextUp_ieee_positive (- x)
-{-# INLINE [1] nextDown #-}
-
--- |
--- prop> nextTowardZero 1 == (0x1.ffff_ffff_ffff_fp-1 :: Double)
--- prop> nextTowardZero 1 == (0x1.fffffep-1 :: Float)
--- prop> nextTowardZero (1/0) == (maxFinite_ieee :: Double)
--- prop> nextTowardZero (-1/0) == (-maxFinite_ieee :: Double)
--- prop> nextTowardZero 0 == (0 :: Double)
--- prop> isNegativeZero (nextTowardZero (-0 :: Double))
--- prop> nextTowardZero 0x1p-1074 == (0 :: Double)
-nextTowardZero :: RealFloat a => a -> a
-nextTowardZero x | not (isIEEE x) = error "non-IEEE numbers are not supported"
-                 | floatRadix x /= 2 = error "non-binary types are not supported "
-                 | isNaN x || x == 0 = x -- NaN or zero
-                 | x >= 0 = nextDown_ieee_positive x
-                 | otherwise = - nextDown_ieee_positive (- x)
-{-# INLINE [1] nextTowardZero #-}
-
-nextUp_ieee_positive :: RealFloat a => a -> a
-nextUp_ieee_positive x
-  | isNaN x || x < 0 = error "nextUp_ieee_positive"
-  | isInfinite x = x
-  | x == 0 = encodeFloat 1 (expMin - d) -- min positive
-  | otherwise = let m :: Integer
-                    e :: Int
-                    (m,e) = decodeFloat x
-                    -- x = m * 2^e, 2^(d-1) <= m < 2^d
-                    -- 2^expMin < x < 2^expMax
-                    -- 2^(expMin-d): min positive
-                    -- 2^(expMin - 1): min normal 0x1p-1022
-                    -- expMin - d <= e <= expMax - d (-1074 .. 971)
-                in if expMin - d <= e
-                   then encodeFloat (m + 1) e -- normal
-                   else let m' = m `shiftR` (expMin - d - e)
-                        in encodeFloat (m' + 1) (expMin - d) -- subnormal
-  where
-    d, expMin :: Int
-    d = floatDigits x -- 53 for Double
-    (expMin,_expMax) = floatRange x -- (-1021,1024) for Double
-{-# INLINE nextUp_ieee_positive #-}
-
-nextDown_ieee_positive :: RealFloat a => a -> a
-nextDown_ieee_positive x
-  | isNaN x || x < 0 = error "nextDown_ieee_positive"
-  | isInfinite x = encodeFloat ((1 `unsafeShiftL` d) - 1) (expMax - d) -- max finite
-  | x == 0 = encodeFloat (-1) (expMin - d) -- max negative
-  | otherwise = let m :: Integer
-                    e :: Int
-                    (m,e) = decodeFloat x
-                    -- x = m * 2^e, 2^(d-1) <= m < 2^d
-                    -- 2^expMin < x < 2^expMax
-                    -- 2^(expMin-d): min positive
-                    -- 2^(expMin - 1): min normal 0x1p-1022
-                    -- expMin - d <= e <= expMax - d (-1074 .. 971)
-                in if expMin - d <= e
-                   then -- normal
-                     let m1 = m - 1
-                     in if m .&. m1 == 0
-                        then encodeFloat (2 * m - 1) (e - 1)
-                        else encodeFloat m1 e
-                   else -- subnormal
-                     let m' = m `shiftR` (expMin - d - e)
-                     in encodeFloat (m' - 1) (expMin - d)
-  where
-    d, expMin :: Int
-    d = floatDigits x -- 53 for Double
-    (expMin,expMax) = floatRange x -- (-1021,1024) for Double
-{-# INLINE nextDown_ieee_positive #-}
-
-{-# RULES
-"nextUp/Float" [~1] nextUp = nextUpFloat
-"nextUp/Double" [~1] nextUp = nextUpDouble
-"nextDown/Float" [~1] nextDown = nextDownFloat
-"nextDown/Double" [~1] nextDown = nextDownDouble
-"nextTowardZero/Float" [~1] nextTowardZero = nextTowardZeroFloat
-"nextTowardZero/Double" [~1] nextTowardZero = nextTowardZeroDouble
-  #-}
-
--- |
--- prop> nextUpFloat 1 == 0x1.000002p0
--- prop> nextUpFloat (1/0) == 1/0
--- prop> nextUpFloat (-1/0) == - maxFinite_ieee
--- prop> nextUpFloat 0 == 0x1p-149
--- prop> nextUpFloat (-0) == 0x1p-149
--- prop> isNegativeZero (nextUpFloat (-0x1p-149))
-nextUpFloat :: Float -> Float
-nextUpFloat x
-  | not (isIEEE x) || floatRadix x /= 2 || d /= 24 || expMin /= -125 || expMax /= 128 = error "rounded-hw assumes Float is IEEE binary32"
-  | isNaN x = x -- NaN -> itself
-  | isNegativeZero x = encodeFloat 1 (expMin - d) -- -0 -> min positive
-  | x < 0 = castWord32ToFloat (castFloatToWord32 x - 1) -- negative
-  | otherwise = case castFloatToWord32 x of
-                  0x7f80_0000 -> x -- positive infinity -> itself
-                  w           -> castWord32ToFloat (w + 1) -- positive
-  where
-    d, expMin :: Int
-    d = floatDigits x -- 53 for Double
-    (expMin,expMax) = floatRange x -- (-1021,1024) for Double
-    -- Note: castFloatToWord32 is buggy on GHC <= 8.8 on x86_64, so we can't use it to test for NaN or negative number
-    --   https://gitlab.haskell.org/ghc/ghc/issues/16617
-
--- |
--- prop> nextUpDouble 1 == 0x1.0000_0000_0000_1p0
--- prop> nextUpDouble (1/0) == 1/0
--- prop> nextUpDouble (-1/0) == - maxFinite_ieee
--- prop> nextUpDouble 0 == 0x1p-1074
--- prop> nextUpDouble (-0) == 0x1p-1074
--- prop> isNegativeZero (nextUpDouble (-0x1p-1074))
-nextUpDouble :: Double -> Double
-nextUpDouble x
-  | not (isIEEE x) || floatRadix x /= 2 || d /= 53 || expMin /= -1021 || expMax /= 1024 = error "rounded-hw assumes Double is IEEE binary64"
-  | otherwise = case castDoubleToWord64 x of
-                  w | w .&. 0x7ff0_0000_0000_0000 == 0x7ff0_0000_0000_0000
-                    , w /= 0xfff0_0000_0000_0000 -> x -- NaN or positive infinity -> itself
-                  0x8000_0000_0000_0000 -> encodeFloat 1 (expMin - d) -- -0 -> min positive
-                  w | testBit w 63 -> castWord64ToDouble (w - 1) -- negative
-                    | otherwise -> castWord64ToDouble (w + 1) -- positive
-  where
-    d, expMin :: Int
-    d = floatDigits x -- 53 for Double
-    (expMin,expMax) = floatRange x -- (-1021,1024) for Double
-
--- |
--- prop> nextDownFloat 1 == 0x1.fffffep-1
--- prop> nextDownFloat (1/0) == maxFinite_ieee
--- prop> nextDownFloat (-1/0) == -1/0
--- prop> nextDownFloat 0 == -0x1p-149
--- prop> nextDownFloat (-0) == -0x1p-149
--- prop> nextDownFloat 0x1p-149 == 0
-nextDownFloat :: Float -> Float
-nextDownFloat x
-  | not (isIEEE x) || floatRadix x /= 2 || d /= 24 || expMin /= -125 || expMax /= 128 = error "rounded-hw assumes Float is IEEE binary32"
-  | isNaN x || (isInfinite x && x < 0) = x -- NaN or negative infinity -> itself
-  | isNegativeZero x || x < 0 = castWord32ToFloat (castFloatToWord32 x + 1) -- negative
-  | x == 0 = encodeFloat (-1) (expMin - d) -- +0 -> max negative
-  | otherwise = castWord32ToFloat (castFloatToWord32 x - 1) -- positive
-  where
-    d, expMin :: Int
-    d = floatDigits x -- 53 for Double
-    (expMin,expMax) = floatRange x -- (-1021,1024) for Double
-    -- Note: castFloatToWord32 is buggy on GHC <= 8.8 on x86_64, so we can't use it to test for NaN or negative number
-    --   https://gitlab.haskell.org/ghc/ghc/issues/16617
-
--- |
--- prop> nextDownDouble 1 == 0x1.ffff_ffff_ffff_fp-1
--- prop> nextDownDouble (1/0) == maxFinite_ieee
--- prop> nextDownDouble (-1/0) == -1/0
--- prop> nextDownDouble 0 == -0x1p-1074
--- prop> nextDownDouble (-0) == -0x1p-1074
--- prop> nextDownDouble 0x1p-1074 == 0
-nextDownDouble :: Double -> Double
-nextDownDouble x
-  | not (isIEEE x) || floatRadix x /= 2 || d /= 53 || expMin /= -1021 || expMax /= 1024 = error "rounded-hw assumes Double is IEEE binary64"
-  | otherwise = case castDoubleToWord64 x of
-                  w | w .&. 0x7ff0_0000_0000_0000 == 0x7ff0_0000_0000_0000
-                    , w /= 0x7ff0_0000_0000_0000 -> x -- NaN or negative infinity -> itself
-                  0x0000_0000_0000_0000 -> encodeFloat (-1) (expMin - d) -- +0 -> max negative
-                  w | testBit w 63 -> castWord64ToDouble (w + 1) -- negative
-                    | otherwise -> castWord64ToDouble (w - 1) -- positive
-  where
-    d, expMin :: Int
-    d = floatDigits x -- 53 for Double
-    (expMin,expMax) = floatRange x -- (-1021,1024) for Double
-
--- |
--- prop> nextTowardZeroFloat 1 == 0x1.fffffep-1
--- prop> nextTowardZeroFloat (-1) == -0x1.fffffep-1
--- prop> nextTowardZeroFloat (1/0) == maxFinite_ieee
--- prop> nextTowardZeroFloat (-1/0) == -maxFinite_ieee
--- prop> nextTowardZeroFloat 0 == 0
--- prop> isNegativeZero (nextTowardZeroFloat (-0))
--- prop> nextTowardZeroFloat 0x1p-149 == 0
-nextTowardZeroFloat :: Float -> Float
-nextTowardZeroFloat x
-  | not (isIEEE x) || floatRadix x /= 2 || d /= 24 || expMin /= -125 || expMax /= 128 = error "rounded-hw assumes Float is IEEE binary32"
-  | isNaN x || x == 0 = x -- NaN or zero -> itself
-  | otherwise = castWord32ToFloat (castFloatToWord32 x - 1) -- positive / negative
-  where
-    d, expMin :: Int
-    d = floatDigits x -- 53 for Double
-    (expMin,expMax) = floatRange x -- (-1021,1024) for Double
-    -- Note: castFloatToWord32 is buggy on GHC <= 8.8 on x86_64, so we can't use it to test for NaN or negative number
-    --   https://gitlab.haskell.org/ghc/ghc/issues/16617
-
--- |
--- prop> nextTowardZeroDouble 1 == 0x1.ffff_ffff_ffff_fp-1
--- prop> nextTowardZeroDouble (-1) == -0x1.ffff_ffff_ffff_fp-1
--- prop> nextTowardZeroDouble (1/0) == maxFinite_ieee
--- prop> nextTowardZeroDouble (-1/0) == -maxFinite_ieee
--- prop> nextTowardZeroDouble 0 == 0
--- prop> isNegativeZero (nextTowardZeroDouble (-0))
--- prop> nextTowardZeroDouble 0x1p-1074 == 0
-nextTowardZeroDouble :: Double -> Double
-nextTowardZeroDouble x
-  | not (isIEEE x) || floatRadix x /= 2 || d /= 53 || expMin /= -1021 || expMax /= 1024 = error "rounded-hw assumes Double is IEEE binary64"
-  | otherwise = case castDoubleToWord64 x of
-                  w | w .&. 0x7ff0_0000_0000_0000 == 0x7ff0_0000_0000_0000
-                    , w .&. 0x000f_ffff_ffff_ffff /= 0 -> x -- NaN -> itself
-                  0x8000_0000_0000_0000 -> x -- -0 -> itself
-                  0x0000_0000_0000_0000 -> x -- +0 -> itself
-                  w -> castWord64ToDouble (w - 1) -- positive / negative
-  where
-    d, expMin :: Int
-    d = floatDigits x -- 53 for Double
-    (expMin,expMax) = floatRange x -- (-1021,1024) for Double
-
-fusedMultiplyAdd :: RealFloat a => a -> a -> a -> a
-fusedMultiplyAdd x y z
-  | isNaN x || isNaN y || isNaN z || isInfinite x || isInfinite y || isInfinite z = x * y + z
-  | otherwise = case toRational x * toRational y + toRational z of
-                  0 | isNegativeZero (x * y + z) -> -0
-                  r -> fromRational r
-{-# NOINLINE [1] fusedMultiplyAdd #-}
-
-#ifdef USE_FFI
-
-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
-  #-}
-
-#endif
+import           Numeric.Floating.IEEE
 
 distanceUlp :: RealFloat a => a -> a -> Maybe Integer
 distanceUlp x y
diff --git a/src/Numeric/Rounded/Hardware/Internal/RoundedResult.hs b/src/Numeric/Rounded/Hardware/Internal/RoundedResult.hs
deleted file mode 100644
--- a/src/Numeric/Rounded/Hardware/Internal/RoundedResult.hs
+++ /dev/null
@@ -1,54 +0,0 @@
-{-# LANGUAGE DeriveFunctor #-}
-{-# LANGUAGE KindSignatures #-}
-{-# LANGUAGE DataKinds #-}
-{-# LANGUAGE ScopedTypeVariables #-}
-module Numeric.Rounded.Hardware.Internal.RoundedResult where
-import Data.Proxy
-import Data.Functor.Product
-import Numeric.Rounded.Hardware.Internal.Rounding
-
-class Functor f => Result f where
-  exact :: a -> f a
-  inexact :: a -- toward nearest
-          -> a -- toward inf
-          -> a -- toward neg inf
-          -> a -- toward zero
-          -> f a
-
-newtype Exactness a = Exactness { getExactness :: Bool }
-  deriving (Eq, Ord, Show, Functor)
-
-instance Rounding r => Result (Rounded r) where
-  exact x = Rounded x
-  inexact n inf ninf z = case rounding (Proxy :: Proxy r) of
-                           ToNearest -> Rounded n
-                           TowardInf -> Rounded inf
-                           TowardNegInf -> Rounded ninf
-                           TowardZero -> Rounded z
-
-newtype DynamicRoundingMode a = DynamicRoundingMode { withRoundingMode :: RoundingMode -> a }
-  deriving (Functor)
-instance Result DynamicRoundingMode where
-  exact x = DynamicRoundingMode (\_ -> x)
-  inexact n inf ninf z = DynamicRoundingMode $ \r ->
-    case r of
-      ToNearest -> n
-      TowardInf -> inf
-      TowardNegInf -> ninf
-      TowardZero -> z
-
-instance Result Exactness where
-  exact _ = Exactness True
-  inexact _ _ _ _ = Exactness False
-
--- Usage: Product (Rounded TowardNegInf) (Rounded TowardInf)
-instance (Result f, Result g) => Result (Product f g) where
-  exact x = Pair (exact x) (exact x)
-  inexact n inf ninf z = Pair (inexact n inf ninf z) (inexact n inf ninf z)
-
-newtype OppositeRoundingMode f a = OppositeRoundingMode { withOppositeRoundingMode :: f a }
-  deriving (Eq, Ord, Show, Functor)
-
-instance Result f => Result (OppositeRoundingMode f) where
-  exact x = OppositeRoundingMode (exact x)
-  inexact n inf ninf z = OppositeRoundingMode (inexact n ninf inf z)
diff --git a/src/Numeric/Rounded/Hardware/Internal/Show.hs b/src/Numeric/Rounded/Hardware/Internal/Show.hs
--- a/src/Numeric/Rounded/Hardware/Internal/Show.hs
+++ b/src/Numeric/Rounded/Hardware/Internal/Show.hs
@@ -1,26 +1,15 @@
 {-# LANGUAGE BangPatterns #-}
 {-# LANGUAGE ScopedTypeVariables #-}
 module Numeric.Rounded.Hardware.Internal.Show where
-import Numeric.Rounded.Hardware.Internal.Rounding
-import Data.Char (intToDigit)
-import Data.Bifunctor (first)
-import Data.Bits
-import Math.NumberTheory.Logarithms
+import           Data.Bifunctor (first)
+import           Data.Bits
+import           Data.Char (intToDigit)
+import           Numeric.Floating.IEEE.Internal (countTrailingZerosInteger)
+import           Numeric.Rounded.Hardware.Internal.Rounding
 
 -- $setup
 -- >>> import Data.Int
 
--- |
--- prop> \x -> x == 0 || countTrailingZerosInteger (fromIntegral x) == countTrailingZeros (x :: Int64)
--- >>> countTrailingZerosInteger 7
--- 0
--- >>> countTrailingZerosInteger 8
--- 3
-countTrailingZerosInteger :: Integer -> Int
-countTrailingZerosInteger x
-  | x == 0 = error "countTrailingZerosInteger: zero"
-  | otherwise = integerLog2 (x `xor` (x - 1))
-
 -- ratToDigitsRn :: RoundingMode -> Int -> Int -> Rational -> ([Int], Int)
 
 -- binaryFloatToDecimalDigitsRn _ prec x = ([d1,d2,...,dn], e)
@@ -221,8 +210,8 @@
                      (d:ds) -> showString $ (intToDigit d : '.' : map intToDigit ds) ++ ('e' : show e')
   where
     padRight0 :: Int -> [Int] -> [Int]
-    padRight0 0 ys = ys
-    padRight0 !n [] = replicate n 0
+    padRight0 0 ys      = ys
+    padRight0 !n []     = replicate n 0
     padRight0 !n (y:ys) = y : padRight0 (n - 1) ys
 {-# SPECIALIZE showEFloatRn :: RoundingMode -> Maybe Int -> Double -> ShowS #-}
 
@@ -243,32 +232,49 @@
   | otherwise = case mprec of
                   Nothing -> let (xs,e) = binaryFloatToDecimalDigits x
                                  l = length xs
-                             in if e >= l
-                                then if null xs
-                                     then showString "0.0"
-                                     else showString (map intToDigit xs ++ replicate (e - l) '0' ++ ".0")
-                                else if e > 0 -- 0 < e < l
-                                     then if l == e -- null zs
-                                          then showString (map intToDigit xs ++ ".0")
-                                          else let (ys,zs) = splitAt (l - e) xs
-                                                   ys' | null ys = [0]
-                                                       | otherwise = ys
-                                               in showString (map intToDigit ys' ++ "." ++ map intToDigit zs)
-                                     else -- e < 0
-                                       showString ("0." ++ replicate (-e) '0' ++ map intToDigit xs)
+                                 -- binaryFloatToDecimalDigits x = ([d1,d2,...,dl], e)
+                                 -- x = 0.d1d2...dl * (10^^e)
+                                 -- 0 <= di < 10
+                             in if e >= l then
+                                  -- d1d2...dl<replicate (e-l) '0'>.0
+                                  if null xs then
+                                    showString "0.0"
+                                  else
+                                    showString (map intToDigit xs ++ replicate (e - l) '0' ++ ".0")
+                                else
+                                  if e > 0 then -- 0 < e < l
+                                    -- d1d2...d<e>.d<e+1>...dl
+                                    if l == e then-- null zs
+                                      showString (map intToDigit xs ++ ".0")
+                                    else
+                                      let (ys,zs) = splitAt e xs
+                                          ys' = if null ys then [0] else ys
+                                      in showString (map intToDigit ys' ++ "." ++ map intToDigit zs)
+                                  else -- e < 0
+                                    -- 0.<replicate (-e) '0'>d1d2...dl
+                                    showString ("0." ++ replicate (-e) '0' ++ map intToDigit xs)
                   Just prec -> let prec' = max prec 0
                                    xs = binaryFloatToFixedDecimalDigitsRn r prec' x
                                    l = length xs
-                               in if prec' == 0
-                                  then if null xs
-                                       then showString "0"
-                                       else showString $ map intToDigit xs
-                                  else if l <= prec'
-                                       then showString $ "0." ++ replicate (prec' - l) '0' ++ map intToDigit xs
-                                       else let (ys,zs) = splitAt (l - prec') xs
-                                                ys' | null ys = [0]
-                                                    | otherwise = ys
-                                            in showString $ map intToDigit ys' ++ "." ++ map intToDigit zs
+                                   -- binaryFloatToFixedDecimalDigitsRn _ prec' x = [d1,d2,...,dl]
+                                   -- x = d1d2...dl * (10^^(-prec')) up to rounding
+                                   -- 0 <= di < 10
+                               in if prec' == 0 then
+                                    -- d1d2...dl or "0"
+                                    if null xs then
+                                      showString "0"
+                                    else
+                                      showString $ map intToDigit xs
+                                  else
+                                    if l <= prec' then
+                                      -- 0.<replicate (prec'-l) '0'>d1d2...dl
+                                      showString $ "0." ++ replicate (prec' - l) '0' ++ map intToDigit xs
+                                    else
+                                      -- l > prec'
+                                      -- d1d2...d<l-prec'>.d<l-prec'+1>...dl
+                                      let (ys,zs) = splitAt (l - prec') xs
+                                          ys' = if null ys then [0] else ys
+                                      in showString $ map intToDigit ys' ++ "." ++ map intToDigit zs
 {-# SPECIALIZE showFFloatRn :: RoundingMode -> Maybe Int -> Double -> ShowS #-}
 
 showGFloatRn :: RealFloat a => RoundingMode -> Maybe Int -> a -> ShowS
diff --git a/src/Numeric/Rounded/Hardware/Interval.hs b/src/Numeric/Rounded/Hardware/Interval.hs
--- a/src/Numeric/Rounded/Hardware/Interval.hs
+++ b/src/Numeric/Rounded/Hardware/Interval.hs
@@ -315,3 +315,10 @@
         y = indexByteArray (ByteArray byteArr) (2 * i + 1)
     in pairToInterval (x, y)
   -- unsafeReplace, unsafeAccum, unsafeAccumArray: Use default
+
+{-# RULES
+"fromIntegral/a->Interval Float"
+  fromIntegral = \x -> case intervalFromIntegral x of (l, u) -> I l u :: Interval Float
+"fromIntegral/a->Interval Double"
+  fromIntegral = \x -> case intervalFromIntegral x of (l, u) -> I l u :: Interval Double
+  #-}
diff --git a/src/Numeric/Rounded/Hardware/Interval/NonEmpty.hs b/src/Numeric/Rounded/Hardware/Interval/NonEmpty.hs
--- a/src/Numeric/Rounded/Hardware/Interval/NonEmpty.hs
+++ b/src/Numeric/Rounded/Hardware/Interval/NonEmpty.hs
@@ -354,3 +354,10 @@
         y = indexByteArray (ByteArray byteArr) (2 * i + 1)
     in pairToInterval (x, y)
   -- unsafeReplace, unsafeAccum, unsafeAccumArray: Use default
+
+{-# RULES
+"fromIntegral/a->Interval Float"
+  fromIntegral = \x -> case intervalFromIntegral x of (l, u) -> I l u :: Interval Float
+"fromIntegral/a->Interval Double"
+  fromIntegral = \x -> case intervalFromIntegral x of (l, u) -> I l u :: Interval Double
+  #-}
diff --git a/test/FloatUtilSpec.hs b/test/FloatUtilSpec.hs
deleted file mode 100644
--- a/test/FloatUtilSpec.hs
+++ /dev/null
@@ -1,75 +0,0 @@
-module FloatUtilSpec where
-import           Numeric.Rounded.Hardware.Internal
-import           Test.Hspec
-import           Test.Hspec.QuickCheck (prop)
-import           Test.QuickCheck
-import           Util (sameFloatP, variousFloats)
-
-foreign import ccall unsafe "nextafter"
-  c_nextafter_double :: Double -> Double -> Double
-foreign import ccall unsafe "nextafterf"
-  c_nextafter_float :: Float -> Float -> Float
-foreign import ccall unsafe "fma"
-  c_fma_double :: Double -> Double -> Double -> Double
-foreign import ccall unsafe "fmaf"
-  c_fma_float :: Float -> Float -> Float -> Float
-
-class Fractional a => CFloat a where
-  c_nextafter :: a -> a -> a
-  c_fma :: a -> a -> a -> a
-
-instance CFloat Double where
-  c_nextafter = c_nextafter_double
-  c_fma = c_fma_double
-
-instance CFloat Float where
-  c_nextafter = c_nextafter_float
-  c_fma = c_fma_float
-
-c_nextUp, c_nextDown, c_nextTowardZero :: (RealFloat a, CFloat a) => a -> a
-c_nextUp x = c_nextafter x (1/0)
-c_nextDown x = c_nextafter x (-1/0)
-c_nextTowardZero x | isNegativeZero x = x
-                   | otherwise = c_nextafter x 0
-
-prop_nextUp_match :: (RealFloat a, CFloat a, Show a) => a -> Property
-prop_nextUp_match x = nextUp x `sameFloatP` c_nextUp x
-
-prop_nextDown_match :: (RealFloat a, CFloat a, Show a) => a -> Property
-prop_nextDown_match x = nextDown x `sameFloatP` c_nextDown x
-
-prop_nextTowardZero_match :: (RealFloat a, CFloat a, Show a) => a -> Property
-prop_nextTowardZero_match x = nextTowardZero x `sameFloatP` c_nextTowardZero x
-
-prop_fma_match :: (RealFloat a, CFloat a, Show a) => a -> a -> a -> Property
-prop_fma_match x y z = fusedMultiplyAdd x y z `sameFloatP` c_fma x y z
-
-isPositiveZero :: RealFloat a => a -> Bool
-isPositiveZero x = x == 0 && not (isNegativeZero x)
-
-prop_nextUp_nextDown :: (RealFloat a, Show a) => a -> Property
-prop_nextUp_nextDown x = x /= (-1/0) ==>
-  let x' = nextUp (nextDown x)
-  in x' `sameFloatP` x .||. (isPositiveZero x .&&. isNegativeZero x')
-
-prop_nextDown_nextUp :: (RealFloat a, Show a) => a -> Property
-prop_nextDown_nextUp x = x /= (1/0) ==>
-  let x' = nextDown (nextUp x)
-  in x' `sameFloatP` x .||. (isNegativeZero x .&&. isPositiveZero x')
-
-spec :: Spec
-spec = do
-  describe "Double" $ do
-    prop "nextUp vs C nextafter" $ forAll variousFloats (prop_nextUp_match :: Double -> Property)
-    prop "nextDown vs C nextafter" $ forAll variousFloats (prop_nextDown_match :: Double -> Property)
-    prop "nextTowardZero vs C nextafter" $ forAll variousFloats (prop_nextTowardZero_match :: Double -> Property)
-    prop "nextUp . nextDown == id (unless -inf)" $ forAll variousFloats (prop_nextUp_nextDown :: Double -> Property)
-    prop "nextDown . nextUp == id (unless inf)" $ forAll variousFloats (prop_nextDown_nextUp :: Double -> Property)
-    prop "fusedMultiplyAdd vs C fma" $ forAll variousFloats (prop_fma_match :: Double -> Double -> Double -> Property)
-  describe "Float" $ do
-    prop "nextUp vs C nextafter" $ forAll variousFloats (prop_nextUp_match :: Float -> Property)
-    prop "nextDown vs C nextafter" $ forAll variousFloats (prop_nextDown_match :: Float -> Property)
-    prop "nextTowardZero vs C nextafter" $ forAll variousFloats (prop_nextTowardZero_match :: Float -> Property)
-    prop "nextUp . nextDown == id (unless -inf)" $ forAll variousFloats (prop_nextUp_nextDown :: Float -> Property)
-    prop "nextDown . nextUp == id (unless inf)" $ forAll variousFloats (prop_nextDown_nextUp :: Float -> Property)
-    prop "fusedMultiplyAdd vs C fma" $ forAll variousFloats (prop_fma_match :: Float -> Float -> Float -> Property)
diff --git a/test/FromIntegerSpec.hs b/test/FromIntegerSpec.hs
--- a/test/FromIntegerSpec.hs
+++ b/test/FromIntegerSpec.hs
@@ -19,32 +19,32 @@
 prop_roundedFromInteger_check :: forall a. (RealFloat a, RoundedRing a) => Proxy a -> RoundingMode -> Integer -> Property
 prop_roundedFromInteger_check _proxy r x
   = (roundedFromInteger r x :: a)
-    `sameFloatP` (fromInt r x :: a)
+    `sameFloatP` (roundedFromInteger_default r x :: a)
 
 prop_roundedFromInt64_check :: forall a. (RealFloat a, RoundedRing a) => Proxy a -> RoundingMode -> Int64 -> Property
 prop_roundedFromInt64_check _proxy r x
   = (roundedFromInteger r (fromIntegral x) :: a)
-    `sameFloatP` (fromInt r (fromIntegral x) :: a)
+    `sameFloatP` (roundedFromInteger_default r (fromIntegral x) :: a)
 
 prop_roundedFromWord64_check :: forall a. (RealFloat a, RoundedRing a) => Proxy a -> RoundingMode -> Word64 -> Property
 prop_roundedFromWord64_check _proxy r x
   = (roundedFromInteger r (fromIntegral x) :: a)
-    `sameFloatP` (fromInt r (fromIntegral x) :: a)
+    `sameFloatP` (roundedFromInteger_default r (fromIntegral x) :: a)
 
-prop_fromInt_order :: forall a. RealFloat a => Proxy a -> Integer -> Property
-prop_fromInt_order _proxy x
-  = let ne   = fromInt ToNearest    x :: a
-        ze   = fromInt TowardZero   x :: a
-        inf  = fromInt TowardInf    x :: a
-        ninf = fromInt TowardNegInf x :: a
+prop_roundedFromInteger_order :: forall a. (RealFloat a, RoundedRing a) => Proxy a -> Integer -> Property
+prop_roundedFromInteger_order _proxy x
+  = let ne   = roundedFromInteger ToNearest    x :: a
+        ze   = roundedFromInteger TowardZero   x :: a
+        inf  = roundedFromInteger TowardInf    x :: a
+        ninf = roundedFromInteger TowardNegInf x :: a
     in ninf <= inf
        .&&. (ne == ninf || ne == inf)
        .&&. (if x < 0 then ze == inf else ze == ninf)
 
-prop_fromInt_exact :: forall a. RealFloat a => Proxy a -> Integer -> Property
-prop_fromInt_exact _proxy x
-  = let inf  = fromInt TowardInf    x :: a
-        ninf = fromInt TowardNegInf x :: a
+prop_roundedFromInteger_exact :: forall a. (RealFloat a, RoundedRing a) => Proxy a -> Integer -> Property
+prop_roundedFromInteger_exact _proxy x
+  = let inf  = roundedFromInteger TowardInf    x :: a
+        ninf = roundedFromInteger TowardNegInf x :: a
     in if ninf == inf
        then not (isInfinite inf) .&&. toRational inf === fromInteger x
        else if isInfinite inf
@@ -71,9 +71,9 @@
   prop "roundedFromInteger/Word64" $ \r ->
     prop_roundedFromWord64_check proxy r
   prop "order" $
-    forAllShrink variousIntegers shrinkIntegral (prop_fromInt_order proxy)
+    forAllShrink variousIntegers shrinkIntegral (prop_roundedFromInteger_order proxy)
   prop "exactness" $
-    forAllShrink variousIntegers shrinkIntegral (prop_fromInt_exact proxy)
+    forAllShrink variousIntegers shrinkIntegral (prop_roundedFromInteger_exact proxy)
 
 spec :: Spec
 spec = do
diff --git a/test/FromRationalSpec.hs b/test/FromRationalSpec.hs
--- a/test/FromRationalSpec.hs
+++ b/test/FromRationalSpec.hs
@@ -17,23 +17,23 @@
 
 prop_roundedFromRational_check :: forall a. (RealFloat a, RoundedFractional a) => Proxy a -> RoundingMode -> Rational -> Property
 prop_roundedFromRational_check _proxy r x
-  = (fromRatio r (numerator x) (denominator x) :: a) -- the standard implementation
+  = (roundedFromRational_default r x :: a) -- the standard implementation
     `sameFloatP` (roundedFromRational r x :: a) -- may be optimized
 
 prop_fromRatio_order :: forall a. RealFloat a => Proxy a -> Rational -> Property
 prop_fromRatio_order _proxy x
-  = let ne   = fromRatio ToNearest    (numerator x) (denominator x) :: a
-        ze   = fromRatio TowardZero   (numerator x) (denominator x) :: a
-        inf  = fromRatio TowardInf    (numerator x) (denominator x) :: a
-        ninf = fromRatio TowardNegInf (numerator x) (denominator x) :: a
+  = let ne   = roundedFromRational_default ToNearest    x :: a
+        ze   = roundedFromRational_default TowardZero   x :: a
+        inf  = roundedFromRational_default TowardInf    x :: a
+        ninf = roundedFromRational_default TowardNegInf x :: a
     in ninf <= inf
        .&&. (ne == ninf || ne == inf)
        .&&. (if x < 0 then ze == inf else ze == ninf)
 
 prop_fromRatio_exact :: forall a. RealFloat a => Proxy a -> Rational -> Property
 prop_fromRatio_exact _proxy x
-  = let inf  = fromRatio TowardInf    (numerator x) (denominator x) :: a
-        ninf = fromRatio TowardNegInf (numerator x) (denominator x) :: a
+  = let inf  = roundedFromRational_default TowardInf    x :: a
+        ninf = roundedFromRational_default TowardNegInf x :: a
     in if ninf == inf
        then not (isInfinite inf) .&&. toRational inf === x
        else if isInfinite inf
@@ -47,7 +47,7 @@
                  else toRational inf =/= x
                       .&&. toRational ninf =/= x
 
-specT :: forall a. (RealFloat a, RoundedFractional a) => Proxy a -> Bool -> Spec
+specT :: (RealFloat a, RoundedFractional a) => Proxy a -> Bool -> Spec
 specT proxy checkAgainstStock = do
   when checkAgainstStock $ do
     -- Although fromRational for Double/Float correctly round to nearest, other types may not.
diff --git a/test/ShowFloatSpec.hs b/test/ShowFloatSpec.hs
--- a/test/ShowFloatSpec.hs
+++ b/test/ShowFloatSpec.hs
@@ -69,15 +69,31 @@
   prop "showGFloat" $ prop_showGFloat proxy
 
   -- 0.5 should be exactly representable in the type...
-  prop "showFFloatRn Nothing 0.5"  $ \r -> showFFloatRn r Nothing  (0.5 :: a) "" === "0.5"
-  prop "showFFloatRn (Just 0) 0.5" $ \r -> showFFloatRn r (Just 0) (0.5 :: a) "" === (if r == TowardInf then "1" else "0")
-  prop "showFFloatRn (Just 3) 0.5" $ \r -> showFFloatRn r (Just 3) (0.5 :: a) "" === "0.500"
-  prop "showGFloatRn Nothing 0.5"  $ \r -> showGFloatRn r Nothing  (0.5 :: a) "" === "0.5"
-  prop "showGFloatRn (Just 0) 0.5" $ \r -> showGFloatRn r (Just 0) (0.5 :: a) "" === (if r == TowardInf then "1" else "0")
-  prop "showGFloatRn (Just 3) 0.5" $ \r -> showGFloatRn r (Just 3) (0.5 :: a) "" === "0.500"
-  prop "showEFloatRn Nothing 0.5"  $ \r -> showEFloatRn r Nothing  (0.5 :: a) "" === "5.0e-1"
-  prop "showEFloatRn (Just 0) 0.5" $ \r -> showEFloatRn r (Just 0) (0.5 :: a) "" === "5e-1"
-  prop "showEFloatRn (Just 3) 0.5" $ \r -> showEFloatRn r (Just 3) (0.5 :: a) "" === "5.000e-1"
+  do let x = 0.5 `asProxyTypeOf` proxy
+     prop "showFFloatRn Nothing 0.5"  $ \r -> showFFloatRn r Nothing  x "" === "0.5"
+     prop "showFFloatRn (Just 0) 0.5" $ \r -> showFFloatRn r (Just 0) x "" === (if r == TowardInf then "1" else "0")
+     prop "showFFloatRn (Just 3) 0.5" $ \r -> showFFloatRn r (Just 3) x "" === "0.500"
+     prop "showGFloatRn Nothing 0.5"  $ \r -> showGFloatRn r Nothing  x "" === "0.5"
+     prop "showGFloatRn (Just 0) 0.5" $ \r -> showGFloatRn r (Just 0) x "" === (if r == TowardInf then "1" else "0")
+     prop "showGFloatRn (Just 3) 0.5" $ \r -> showGFloatRn r (Just 3) x "" === "0.500"
+     prop "showEFloatRn Nothing 0.5"  $ \r -> showEFloatRn r Nothing  x "" === "5.0e-1"
+     prop "showEFloatRn (Just 0) 0.5" $ \r -> showEFloatRn r (Just 0) x "" === "5e-1"
+     prop "showEFloatRn (Just 3) 0.5" $ \r -> showEFloatRn r (Just 3) x "" === "5.000e-1"
+
+  -- -17.5625 should be exactly representable in the type...
+  do let x = (-17.5625) `asProxyTypeOf` proxy
+     prop "showFFloatRn Nothing -17.5625"  $ \r -> showFFloatRn r Nothing  x "" === "-17.5625"
+     prop "showFFloatRn (Just 0) -17.5625" $ \r -> showFFloatRn r (Just 0) x "" === (if r == TowardInf || r == TowardZero then "-17" else "-18")
+     prop "showFFloatRn (Just 3) -17.5625" $ \r -> showFFloatRn r (Just 3) x "" === (if r == TowardNegInf then "-17.563" else "-17.562")
+     prop "showFFloatRn (Just 6) -17.5625" $ \r -> showFFloatRn r (Just 6) x "" === "-17.562500"
+     prop "showGFloatRn Nothing -17.5625"  $ \r -> showGFloatRn r Nothing  x "" === "-17.5625"
+     prop "showGFloatRn (Just 0) -17.5625" $ \r -> showGFloatRn r (Just 0) x "" === (if r == TowardInf || r == TowardZero then "-17" else "-18")
+     prop "showGFloatRn (Just 3) -17.5625" $ \r -> showGFloatRn r (Just 3) x "" === (if r == TowardNegInf then "-17.563" else "-17.562")
+     prop "showGFloatRn (Just 6) -17.5625" $ \r -> showGFloatRn r (Just 6) x "" === "-17.562500"
+     prop "showEFloatRn Nothing -17.5625"  $ \r -> showEFloatRn r Nothing  x "" === "-1.75625e1"
+     prop "showEFloatRn (Just 0) -17.5625" $ \r -> showEFloatRn r (Just 0) x "" === (if r == TowardInf || r == TowardZero then "-1e1" else "-2e1")
+     prop "showEFloatRn (Just 3) -17.5625" $ \r -> showEFloatRn r (Just 3) x "" === (if r == TowardNegInf then "-1.757e1" else "-1.756e1")
+     prop "showEFloatRn (Just 6) -17.5625" $ \r -> showEFloatRn r (Just 6) x "" === "-1.756250e1"
 
 spec :: Spec
 spec = do
diff --git a/test/Spec.hs b/test/Spec.hs
--- a/test/Spec.hs
+++ b/test/Spec.hs
@@ -9,7 +9,6 @@
 import           Numeric.Rounded.Hardware.Backend (backendName)
 import qualified RoundedArithmeticSpec
 import qualified ShowFloatSpec
-import qualified FloatUtilSpec
 import           Test.Hspec
 import qualified VectorSpec
 #ifdef TEST_X87_LONG_DOUBLE
@@ -41,7 +40,6 @@
     describe "showFloat" ShowFloatSpec.spec
     describe "rounded arithmetic" RoundedArithmeticSpec.spec
     describe "interval arithmetic" IntervalArithmeticSpec.spec
-    describe "FloatUtil" FloatUtilSpec.spec
     describe "Vector" VectorSpec.spec
     describe "Constants" ConstantsSpec.spec
 #ifdef TEST_X87_LONG_DOUBLE
diff --git a/test/X87LongDoubleSpec.hs b/test/X87LongDoubleSpec.hs
--- a/test/X87LongDoubleSpec.hs
+++ b/test/X87LongDoubleSpec.hs
@@ -3,7 +3,6 @@
 import qualified ConstantsSpec
 import           Data.Int
 import           Data.Proxy
-import qualified FloatUtilSpec
 import qualified FromIntegerSpec
 import qualified FromRationalSpec
 import qualified IntervalArithmeticSpec
@@ -37,8 +36,6 @@
   describe "fromRational"        $ FromRationalSpec.specT ldProxy False
   describe "showFloat"           $ ShowFloatSpec.specT ldProxy
   describe "constants"           $ ConstantsSpec.specT ldProxy
-  prop "nextUp . nextDown == id (unless -inf)" $ forAll variousFloats (FloatUtilSpec.prop_nextUp_nextDown :: LongDouble -> Property)
-  prop "nextDown . nextUp == id (unless inf)" $ forAll variousFloats (FloatUtilSpec.prop_nextDown_nextUp :: LongDouble -> Property)
   where
     ldProxy :: Proxy LongDouble
     ldProxy = Proxy
