diff --git a/ChangeLog.md b/ChangeLog.md
--- a/ChangeLog.md
+++ b/ChangeLog.md
@@ -1,5 +1,10 @@
 # Changelog for fp-ieee
 
+## Version 0.1.0.2 (2021-11-30)
+
+* Allow ghc-bignum 1.2.
+* Documentation changes.
+
 ## Version 0.1.0.1 (2021-01-02)
 
 Fix some packaging issues.
diff --git a/decimal-test/NextFloatSpec.hs b/decimal-test/NextFloatSpec.hs
deleted file mode 100644
--- a/decimal-test/NextFloatSpec.hs
+++ /dev/null
@@ -1,42 +0,0 @@
-module NextFloatSpec where
-import           Data.Proxy
-import           Numeric.Decimal
-import           Numeric.Floating.IEEE
-import           Test.Hspec
-import           Test.Hspec.QuickCheck (prop)
-import           Test.QuickCheck
-import           Util (forAllFloats, sameFloatP)
-
-isPositiveZero :: RealFloat a => a -> Bool
-isPositiveZero x = x == 0 && not (isNegativeZero x)
-
-prop_nextUp_nextDown :: (RealFloat a, Show a) => Proxy 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) => Proxy a -> a -> Property
-prop_nextDown_nextUp _ x = x /= (1/0) ==>
-  let x' = nextDown (nextUp x)
-  in x' `sameFloatP` x .||. (isNegativeZero x .&&. isPositiveZero x')
-
-{-# NOINLINE spec #-}
-spec :: Spec
-spec = do
-  describe "Decimal32" $ do
-    let proxy :: Proxy Decimal32
-        proxy = Proxy
-    prop "nextUp . nextDown == id (unless -inf)" $ forAllFloats $ prop_nextUp_nextDown proxy
-    prop "nextDown . nextUp == id (unless inf)" $ forAllFloats $ prop_nextDown_nextUp proxy
-
-  describe "Decimal64" $ do
-    let proxy :: Proxy Decimal64
-        proxy = Proxy
-    prop "nextUp . nextDown == id (unless -inf)" $ forAllFloats $ prop_nextUp_nextDown proxy
-    prop "nextDown . nextUp == id (unless inf)" $ forAllFloats $ prop_nextDown_nextUp proxy
-
-  describe "Decimal128" $ do
-    let proxy :: Proxy Decimal128
-        proxy = Proxy
-    prop "nextUp . nextDown == id (unless -inf)" $ forAllFloats $ prop_nextUp_nextDown proxy
-    prop "nextDown . nextUp == id (unless inf)" $ forAllFloats $ prop_nextDown_nextUp proxy
diff --git a/decimal-test/Spec.hs b/decimal-test/Spec.hs
deleted file mode 100644
--- a/decimal-test/Spec.hs
+++ /dev/null
@@ -1,27 +0,0 @@
-{-# LANGUAGE NumericUnderscores #-}
-import qualified NextFloatSpec
-import           Numeric.Decimal
-import           Numeric.Floating.IEEE
-import           Test.Hspec
-import           Test.Hspec.Core.Spec
-
-allowFailure :: String -> Item a -> Item a
-allowFailure message item@(Item { itemExample = origExample }) = item { itemExample = newExample }
-  where
-    newExample params around callback = do
-      result <- origExample params around callback
-      case result of
-        Result { resultStatus = Failure loc reason } -> do
-          let message' = case reason of
-                           NoReason -> message
-                           _ -> message ++ ": " ++ show reason
-          return result { resultStatus = Pending loc (Just message') }
-        _ -> return result
-
-main :: IO ()
-main = hspec $ do
-  mapSpecItem_ (allowFailure "decimal-arithmetic's floatRange may be incorrect") $ do
-    it "maxFinite :: Decimal32" $ (maxFinite :: Decimal32) == 9.999_999e96 -- 7 digits
-    it "maxFinite :: Decimal64" $ (maxFinite :: Decimal64) == 9.999_999_999_999_999e384 -- 16 digits
-    it "maxFinite :: Decimal128" $ (maxFinite :: Decimal128) == 9.999_999_999_999_999_999_999_999_999_999_999e6144 -- 34 digits
-  describe "NextFloat" NextFloatSpec.spec
diff --git a/decimal-test/Util.hs b/decimal-test/Util.hs
deleted file mode 100644
--- a/decimal-test/Util.hs
+++ /dev/null
@@ -1,71 +0,0 @@
-{-# LANGUAGE ScopedTypeVariables #-}
-{-# OPTIONS_GHC -Wno-orphans #-}
-module Util where
-import           Control.Applicative
-import           Data.Ratio
-import           Numeric
-import           Numeric.Decimal
-import           Numeric.Floating.IEEE
-import           System.Random
-import           Test.QuickCheck
-
--- | Compares two floating point values.
---
--- Unlike @(==)@, @+0@ and @-0@ are considered distinct and NaNs are equal.
---
--- >>> sameFloat 0 (-0 :: Double)
--- False
--- >>> sameFloat (0/0) (0/0 :: Double)
--- True
-sameFloat :: RealFloat a => a -> a -> Bool
-sameFloat x y | isNaN x && isNaN y = True
-              | x == 0 && y == 0 = isNegativeZero x == isNegativeZero y
-              | otherwise = x == y
-
-sameFloatP :: (RealFloat a, Show a) => a -> a -> Property
-sameFloatP x y = counterexample (shows x . showString (interpret res) . showHFloat y $ "") res
-  where
-    res = sameFloat x y
-    interpret True  = " === "
-    interpret False = " =/= "
-
-infix 4 `sameFloat`, `sameFloatP`
-
-variousFloats :: forall a. (RealFloat a, Arbitrary a, Random a, Show a) => Gen a
-variousFloats = frequency
-  [ (10, arbitrary)
-  , (10, choose (-1, 1))
-  , (10, (* encodeFloat 1 expMin) <$> choose (-1, 1) ) -- subnormal or very small normal
-  , (10, (* encodeFloat 1 (expMax-1)) <$> choose (-2, 2) ) -- infinity or very large normal
-  , (1, pure 0) -- positive zero
-  , (1, pure (-0)) -- negative zero
-  , (1, pure (1/0)) -- positive infinity
-  , (1, pure (-1/0)) -- negative infinity
-  , (1, pure (0/0)) -- NaN
-  , (1, pure maxFinite) -- max finite
-  , (1, pure (-maxFinite)) -- min negative
-  , (1, pure minPositive) -- min positive
-  , (1, pure (-minPositive)) -- max negative
-  ]
-  where (expMin,expMax) = floatRange (undefined :: a)
-
-forAllFloats :: (RealFloat a, Arbitrary a, Random a, Show a, Testable prop) => (a -> prop) -> Property
-forAllFloats = forAllShow variousFloats (\x -> show x)
-
-forAllFloats2 :: (RealFloat a, Arbitrary a, Random a, Show a, Testable prop) => (a -> a -> prop) -> Property
-forAllFloats2 f = forAllFloats $ \x -> forAllFloats $ \y -> f x y
-
-forAllFloats3 :: (RealFloat a, Arbitrary a, Random a, Show a, Testable prop) => (a -> a -> a -> prop) -> Property
-forAllFloats3 f = forAllFloats $ \x -> forAllFloats $ \y -> forAllFloats $ \z -> f x y z
-
--- orphan instances
-instance (FinitePrecision p, Rounding r) => Arbitrary (Decimal p r) where
-  arbitrary = arbitrarySizedFractional
-  shrink = shrinkDecimal
-
-instance (FinitePrecision p, Rounding r) => Random (Decimal p r) where
-  randomR (lo,hi) g = let (x,g') = random g
-                      in (lo + x * (hi - lo), g') -- TODO: avoid overflow
-  random g = let x :: Int
-                 (x,g') = random g
-             in (fromRational (toInteger x % 1000), g') -- TODO
diff --git a/fp-ieee.cabal b/fp-ieee.cabal
--- a/fp-ieee.cabal
+++ b/fp-ieee.cabal
@@ -1,13 +1,7 @@
-cabal-version: 1.12
-
--- This file has been generated from package.yaml by hpack version 0.33.0.
---
--- see: https://github.com/sol/hpack
---
--- hash: 62a346063dd10a9b7bb7de4d7624dd805ceef339ead48206730d6c47e94e17d2
+cabal-version: 2.2
 
 name:           fp-ieee
-version:        0.1.0.1
+version:        0.1.0.2
 synopsis:       IEEE 754-2019 compliant operations
 description:    Please see the README on GitHub at <https://github.com/minoki/haskell-floating-point/tree/master/fp-ieee#readme>
 category:       Numeric, Math
@@ -16,7 +10,7 @@
 author:         ARATA Mizuki
 maintainer:     minorinoki@gmail.com
 copyright:      2020-2021 ARATA Mizuki
-license:        BSD3
+license:        BSD-3-Clause
 license-file:   LICENSE
 build-type:     Simple
 extra-source-files:
@@ -26,14 +20,15 @@
 source-repository head
   type: git
   location: https://github.com/minoki/haskell-floating-point
+  subdir: fp-ieee
 
-flag f16c
-  description: Use F16C instructions on x86
+flag pure-hs
+  description: Disable FFI
   manual: True
   default: False
 
-flag float128
-  description: Support Float128 via float128 package
+flag sse4_1
+  description: Use SSE4.1 instructions on x86
   manual: True
   default: False
 
@@ -42,32 +37,69 @@
   manual: True
   default: False
 
-flag ghc-bignum
-  description: Use ghc-bignum package
-  manual: False
-  default: True
+flag f16c
+  description: Use F16C instructions on x86
+  manual: True
+  default: False
 
+-- flag x87-long-double
+--   description: Support x87 "long double" via long-double package
+--   manual: True
+--   default: False
+
+flag float128
+  description: Support Float128 via float128 package
+  manual: True
+  default: False
+
 flag half
   description: Support Half (float16) via half package
   manual: True
   default: False
 
 flag integer-gmp
-  description: Use integer-gmp package
+  description: Use integer-gmp package on GHC 8.x
   manual: False
   default: True
 
-flag pure-hs
-  description: Disable FFI
-  manual: True
-  default: False
+flag ghc-bignum
+  description: Use ghc-bignum package on GHC 9.x
+  manual: False
+  default: True
 
-flag sse4_1
-  description: Use SSE4.1 instructions on x86
-  manual: True
-  default: False
+common deps
+  build-depends:
+      -- We use a post-GHC 8.6 language extension: NumericUnderscores
+      -- cast{Word32,Word64}To{Float,Double}, cast{Float,Double}To{Word32,Word64} are since base-4.10.0.0 (GHC 8.2)
+      -- Semigroup((<>)) is exported from Prelude since base-4.11.0.0 (GHC 8.4)
+      base >=4.12 && <5
+  if !flag(pure-hs)
+    cpp-options: -DUSE_FFI
+  if flag(float128)
+    -- Support Float128
+    cpp-options: -DUSE_FLOAT128
+    build-depends:
+        float128 ==0.1.*
+  if flag(half)
+    -- Support Half
+    -- Note that half-0.3's isInfinite is buggy (https://github.com/ekmett/half/issues/23)
+    cpp-options: -DUSE_HALF
+    build-depends:
+        half ==0.3.*
+  -- if flag(x87-long-double)
+  --   cpp-options: -DUSE_X87_LONG_DOUBLE
+  --   build-depends:
+  --       long-double ==???
 
+common options
+  ghc-options: -Wcompat
+  if arch(i386)
+    -- Always enable SSE2 on i386
+    ghc-options: -msse2
+    cc-options: -msse2 -mfpmath=sse
+
 library
+  import: deps, options
   exposed-modules:
       Numeric.Floating.IEEE
       Numeric.Floating.IEEE.Internal
@@ -94,60 +126,9 @@
       Numeric.Floating.IEEE.Internal.Rounding.Rational
   hs-source-dirs:
       src
-  ghc-options: -Wall
   build-depends:
-      base >=4.12 && <5
-    , integer-logarithms >=1 && <1.1
-  if arch(i386)
-    ghc-options: -msse2
-    cc-options: -msse2 -mfpmath=sse
-  if !flag(pure-hs)
-    cpp-options: -DUSE_FFI
-  if !flag(pure-hs) && (arch(i386) || arch(x86_64)) && flag(sse4_1)
-    cpp-options: -DHAS_FAST_ROUNDEVEN
-    cc-options: -msse4.1
-    c-sources:
-        cbits/roundeven.c
-  if !flag(pure-hs) && arch(aarch64)
-    cpp-options: -DHAS_FAST_ROUNDEVEN
-    c-sources:
-        cbits/roundeven.c
-  if !flag(pure-hs) && (arch(i386) || arch(x86_64)) && flag(fma3)
-    cpp-options: -DHAS_FAST_FMA
-    cc-options: -mfma
-    c-sources:
-        cbits/fma.c
-  if !flag(pure-hs) && arch(aarch64)
-    cpp-options: -DHAS_FAST_FMA
-    c-sources:
-        cbits/fma.c
-  if !flag(pure-hs) && (arch(i386) || arch(x86_64)) && !os(windows)
-    cpp-options: -DUSE_C99_FMA
-  if !flag(pure-hs) && arch(aarch64)
-    cpp-options: -DHAS_FAST_MINMAX
-    c-sources:
-        cbits/minmax.c
-  if flag(float128)
-    cpp-options: -DUSE_FLOAT128
-    build-depends:
-        float128 >=0.1 && <0.2
-  if flag(half)
-    cpp-options: -DUSE_HALF
-    build-depends:
-        half >=0.3 && <0.4
-  if !flag(pure-hs) && flag(half) && arch(x86_64) && flag(f16c)
-    cpp-options: -DHAS_FAST_HALF_CONVERSION
-    cc-options: -mf16c
-    c-sources:
-        cbits/half.c
-  if !flag(pure-hs) && flag(half) && arch(aarch64)
-    cpp-options: -DHAS_FAST_HALF_CONVERSION
-    c-sources:
-        cbits/half.c
-  if !flag(pure-hs) && (arch(aarch64) || arch(x86_64))
-    cpp-options: -DHAS_FAST_CANONICALIZE
-    c-sources:
-        cbits/canonicalize.c
+      integer-logarithms >=1 && <1.1
+  ghc-options: -Wall
   if flag(half)
     other-modules:
         Numeric.Floating.IEEE.Internal.Half
@@ -156,66 +137,42 @@
         Numeric.Floating.IEEE.Internal.Float128
   if flag(integer-gmp) && impl(ghc < 9.0.0)
     build-depends:
-        integer-gmp >=1.0 && <1.1
+        -- integer-gmp-1.1 is based on ghc-bignum, which is not what we want
+        integer-gmp ==1.0.*
   if flag(ghc-bignum) && impl(ghc >= 9.0.0)
     build-depends:
-        ghc-bignum >=1.0 && <1.1
-  default-language: Haskell2010
-
-test-suite fp-ieee-decimal-test
-  type: exitcode-stdio-1.0
-  main-is: Spec.hs
-  other-modules:
-      NextFloatSpec
-      Util
-  hs-source-dirs:
-      decimal-test
-  ghc-options: -threaded -rtsopts -with-rtsopts=-N -fno-ignore-asserts
-  build-depends:
-      QuickCheck
-    , base >=4.12 && <5
-    , decimal-arithmetic
-    , fp-ieee
-    , hspec
-    , hspec-core
-    , random
-  if arch(i386)
-    ghc-options: -msse2
-    cc-options: -msse2 -mfpmath=sse
-  if !flag(pure-hs)
-    cpp-options: -DUSE_FFI
+        ghc-bignum >=1.0 && <1.3
+  -- Fast roundeven: needs SSE4.1 on x86
   if !flag(pure-hs) && (arch(i386) || arch(x86_64)) && flag(sse4_1)
     cpp-options: -DHAS_FAST_ROUNDEVEN
     cc-options: -msse4.1
     c-sources:
         cbits/roundeven.c
+  -- Fast roundeven: always available on AArch64
   if !flag(pure-hs) && arch(aarch64)
     cpp-options: -DHAS_FAST_ROUNDEVEN
     c-sources:
         cbits/roundeven.c
+  -- Fast FMA: needs FMA3 on x86 (FMA4 is not supported by this package)
   if !flag(pure-hs) && (arch(i386) || arch(x86_64)) && flag(fma3)
     cpp-options: -DHAS_FAST_FMA
     cc-options: -mfma
     c-sources:
         cbits/fma.c
+  -- Fast FMA: always available on AArch64
   if !flag(pure-hs) && arch(aarch64)
     cpp-options: -DHAS_FAST_FMA
     c-sources:
         cbits/fma.c
+  -- Enable use of libm's fma unless "pure-hs" is set; but not on Windows
+  -- (mingw-w64's fma is not reliable)
   if !flag(pure-hs) && (arch(i386) || arch(x86_64)) && !os(windows)
     cpp-options: -DUSE_C99_FMA
+  -- Fast min/max: available on AArch64
   if !flag(pure-hs) && arch(aarch64)
     cpp-options: -DHAS_FAST_MINMAX
     c-sources:
         cbits/minmax.c
-  if flag(float128)
-    cpp-options: -DUSE_FLOAT128
-    build-depends:
-        float128 >=0.1 && <0.2
-  if flag(half)
-    cpp-options: -DUSE_HALF
-    build-depends:
-        half >=0.3 && <0.4
   if !flag(pure-hs) && flag(half) && arch(x86_64) && flag(f16c)
     cpp-options: -DHAS_FAST_HALF_CONVERSION
     cc-options: -mf16c
@@ -232,66 +189,16 @@
   default-language: Haskell2010
 
 test-suite fp-ieee-doctests
+  import: deps, options
   type: exitcode-stdio-1.0
   main-is: doctests.hs
-  other-modules:
-      Paths_fp_ieee
   build-depends:
-      base >=4.12 && <5
-    , doctest >=0.8
-  if arch(i386)
-    ghc-options: -msse2
-    cc-options: -msse2 -mfpmath=sse
-  if !flag(pure-hs)
-    cpp-options: -DUSE_FFI
-  if !flag(pure-hs) && (arch(i386) || arch(x86_64)) && flag(sse4_1)
-    cpp-options: -DHAS_FAST_ROUNDEVEN
-    cc-options: -msse4.1
-    c-sources:
-        cbits/roundeven.c
-  if !flag(pure-hs) && arch(aarch64)
-    cpp-options: -DHAS_FAST_ROUNDEVEN
-    c-sources:
-        cbits/roundeven.c
-  if !flag(pure-hs) && (arch(i386) || arch(x86_64)) && flag(fma3)
-    cpp-options: -DHAS_FAST_FMA
-    cc-options: -mfma
-    c-sources:
-        cbits/fma.c
-  if !flag(pure-hs) && arch(aarch64)
-    cpp-options: -DHAS_FAST_FMA
-    c-sources:
-        cbits/fma.c
-  if !flag(pure-hs) && (arch(i386) || arch(x86_64)) && !os(windows)
-    cpp-options: -DUSE_C99_FMA
-  if !flag(pure-hs) && arch(aarch64)
-    cpp-options: -DHAS_FAST_MINMAX
-    c-sources:
-        cbits/minmax.c
-  if flag(float128)
-    cpp-options: -DUSE_FLOAT128
-    build-depends:
-        float128 >=0.1 && <0.2
-  if flag(half)
-    cpp-options: -DUSE_HALF
-    build-depends:
-        half >=0.3 && <0.4
-  if !flag(pure-hs) && flag(half) && arch(x86_64) && flag(f16c)
-    cpp-options: -DHAS_FAST_HALF_CONVERSION
-    cc-options: -mf16c
-    c-sources:
-        cbits/half.c
-  if !flag(pure-hs) && flag(half) && arch(aarch64)
-    cpp-options: -DHAS_FAST_HALF_CONVERSION
-    c-sources:
-        cbits/half.c
-  if !flag(pure-hs) && (arch(aarch64) || arch(x86_64))
-    cpp-options: -DHAS_FAST_CANONICALIZE
-    c-sources:
-        cbits/canonicalize.c
+      doctest >=0.8
+    , QuickCheck
   default-language: Haskell2010
 
 test-suite fp-ieee-test
+  import: deps, options
   type: exitcode-stdio-1.0
   main-is: Spec.hs
   other-modules:
@@ -311,63 +218,12 @@
   ghc-options: -threaded -rtsopts -with-rtsopts=-N -fno-ignore-asserts
   build-depends:
       QuickCheck
-    , base >=4.12 && <5
     , fp-ieee
     , hspec
     , hspec-core
     , integer-logarithms
     , random
-  if arch(i386)
-    ghc-options: -msse2
-    cc-options: -msse2 -mfpmath=sse
-  if !flag(pure-hs)
-    cpp-options: -DUSE_FFI
-  if !flag(pure-hs) && (arch(i386) || arch(x86_64)) && flag(sse4_1)
-    cpp-options: -DHAS_FAST_ROUNDEVEN
-    cc-options: -msse4.1
-    c-sources:
-        cbits/roundeven.c
-  if !flag(pure-hs) && arch(aarch64)
-    cpp-options: -DHAS_FAST_ROUNDEVEN
-    c-sources:
-        cbits/roundeven.c
-  if !flag(pure-hs) && (arch(i386) || arch(x86_64)) && flag(fma3)
-    cpp-options: -DHAS_FAST_FMA
-    cc-options: -mfma
-    c-sources:
-        cbits/fma.c
-  if !flag(pure-hs) && arch(aarch64)
-    cpp-options: -DHAS_FAST_FMA
-    c-sources:
-        cbits/fma.c
-  if !flag(pure-hs) && (arch(i386) || arch(x86_64)) && !os(windows)
-    cpp-options: -DUSE_C99_FMA
-  if !flag(pure-hs) && arch(aarch64)
-    cpp-options: -DHAS_FAST_MINMAX
-    c-sources:
-        cbits/minmax.c
-  if flag(float128)
-    cpp-options: -DUSE_FLOAT128
-    build-depends:
-        float128 >=0.1 && <0.2
   if flag(half)
-    cpp-options: -DUSE_HALF
-    build-depends:
-        half >=0.3 && <0.4
-  if !flag(pure-hs) && flag(half) && arch(x86_64) && flag(f16c)
-    cpp-options: -DHAS_FAST_HALF_CONVERSION
-    cc-options: -mf16c
-    c-sources:
-        cbits/half.c
-  if !flag(pure-hs) && flag(half) && arch(aarch64)
-    cpp-options: -DHAS_FAST_HALF_CONVERSION
-    c-sources:
-        cbits/half.c
-  if !flag(pure-hs) && (arch(aarch64) || arch(x86_64))
-    cpp-options: -DHAS_FAST_CANONICALIZE
-    c-sources:
-        cbits/canonicalize.c
-  if flag(half)
     other-modules:
         HalfSpec
   if flag(float128)
@@ -376,64 +232,14 @@
   default-language: Haskell2010
 
 benchmark fp-ieee-benchmark
+  import: deps, options
   type: exitcode-stdio-1.0
   main-is: Benchmark.hs
-  other-modules:
-      Paths_fp_ieee
   hs-source-dirs:
       benchmark
   build-depends:
-      base >=4.12 && <5
-    , fp-ieee
-    , gauge
-  if arch(i386)
-    ghc-options: -msse2
-    cc-options: -msse2 -mfpmath=sse
-  if !flag(pure-hs)
-    cpp-options: -DUSE_FFI
-  if !flag(pure-hs) && (arch(i386) || arch(x86_64)) && flag(sse4_1)
-    cpp-options: -DHAS_FAST_ROUNDEVEN
-    cc-options: -msse4.1
-    c-sources:
-        cbits/roundeven.c
-  if !flag(pure-hs) && arch(aarch64)
-    cpp-options: -DHAS_FAST_ROUNDEVEN
-    c-sources:
-        cbits/roundeven.c
-  if !flag(pure-hs) && (arch(i386) || arch(x86_64)) && flag(fma3)
-    cpp-options: -DHAS_FAST_FMA
-    cc-options: -mfma
-    c-sources:
-        cbits/fma.c
-  if !flag(pure-hs) && arch(aarch64)
-    cpp-options: -DHAS_FAST_FMA
-    c-sources:
-        cbits/fma.c
-  if !flag(pure-hs) && (arch(i386) || arch(x86_64)) && !os(windows)
-    cpp-options: -DUSE_C99_FMA
-  if !flag(pure-hs) && arch(aarch64)
-    cpp-options: -DHAS_FAST_MINMAX
-    c-sources:
-        cbits/minmax.c
-  if flag(float128)
-    cpp-options: -DUSE_FLOAT128
-    build-depends:
-        float128 >=0.1 && <0.2
-  if flag(half)
-    cpp-options: -DUSE_HALF
-    build-depends:
-        half >=0.3 && <0.4
-  if !flag(pure-hs) && flag(half) && arch(x86_64) && flag(f16c)
-    cpp-options: -DHAS_FAST_HALF_CONVERSION
-    cc-options: -mf16c
-    c-sources:
-        cbits/half.c
-  if !flag(pure-hs) && flag(half) && arch(aarch64)
-    cpp-options: -DHAS_FAST_HALF_CONVERSION
-    c-sources:
-        cbits/half.c
-  if !flag(pure-hs) && (arch(aarch64) || arch(x86_64))
-    cpp-options: -DHAS_FAST_CANONICALIZE
-    c-sources:
-        cbits/canonicalize.c
+      fp-ieee
+    , tasty-bench
+  mixins:
+      tasty-bench (Test.Tasty.Bench as Gauge, Test.Tasty.Bench as Gauge.Main)
   default-language: Haskell2010
diff --git a/src/Numeric/Floating/IEEE.hs b/src/Numeric/Floating/IEEE.hs
--- a/src/Numeric/Floating/IEEE.hs
+++ b/src/Numeric/Floating/IEEE.hs
@@ -117,7 +117,8 @@
   -- ** 5.5.1 Sign bit operations
   --
   -- |
-  -- For IEEE-compliant floating-point types, 'negate' and 'abs' from "Prelude" should comply with IEEE semantics.
+  -- For IEEE-compliant floating-point types, 'negate' from "Prelude" should comply with IEEE semantics.
+  -- 'abs' should also comply with IEEE semantics, but unfortunately it does not handle the sign bit of NaN on via-C backend and SPARC NCG backend.
   , negate
   , abs
   -- |
@@ -208,9 +209,10 @@
 -- == 'Num'
 --
 --     * '(+)', '(-)', and '(*)' should be correctly-rounding.
---     * 'negate', 'abs' should comply with IEEE semantics.
---     * 'fromInteger' should be correctly-rounding, but unfortunately not for 'Float' and 'Double' (see GHC's [#17231](https://gitlab.haskell.org/ghc/ghc/-/issues/17231)).
---       This module provides a correctly-rounding alternative: 'fromIntegerTiesToEven'.
+--     * 'negate' should comply with IEEE semantics.
+--     * 'abs' should comply with IEEE semantics, but unfortunately it does not handle the sign bit of NaN for 'Float' and 'Double' on via-C backend and SPARC NCG backend.
+--     * 'fromInteger' should be correctly-rounding, but unfortunately not for 'Float' and 'Double' on GHC <= 9.0 (see GHC's [#17231](https://gitlab.haskell.org/ghc/ghc/-/issues/17231)).
+--       This module provides an always-correctly-rounding alternative: 'fromIntegerTiesToEven'.
 --
 -- == 'Fractional'
 --
@@ -242,9 +244,17 @@
 --     * 'encodeFloat' should accept the significand in the range @[0, floatRadix x ^ floatDigits x]@. This library does not assume a particular rounding behavior when the result cannot be expressed in the target type.
 --     * @'exponent' x@: The exponent offset by 1: \(\mathrm{logB}(x)+1\). Returns an integer in \([\mathit{emin}+1,\mathit{emax}+1]\) if @x@ is normal, or in \([\mathit{emin}-p+2,\mathit{emin}]\) if @x@ is subnormal.
 --     * @'significand' x@: Returns the significand of @x@ as a value between \([1/b,1)\).
---     * 'scaleFloat': This library does not assume a particular rounding behavior when the result is subnormal.
+--     * 'scaleFloat': Rounding may occur when the result is subnormal. This library does not assume a particular rounding behavior when the result is subnormal.
 --     * 'isNaN'
 --     * 'isInfinite'
 --     * 'isDenormalized'
 --     * 'isNegativeZero'
 --     * 'isIEEE' should return @True@ if you are using the type with this library.
+--
+-- == Other functions
+--
+-- Here is a list of known issues with other floating-point functions on GHC 8.6 or later:
+--
+--     * @('^^')@ may cause undue underflow when constructing very small value like @2^^(-1074)@ (see [GHC's #4413](https://gitlab.haskell.org/ghc/ghc/-/issues/4413)).
+--     * 'realToFrac' may behave differently depending on optimization flags (see [GHC's #3676](https://gitlab.haskell.org/ghc/ghc/-/issues/3676)). Don't use 'realToFrac' on values that potentially contain signed zeroes, infinities or NaN, or use 'realFloatToFrac' instead.
+--     * On GHC <= 8.8, 'GHC.Float.castFloatToWord32' may produce exotic 'Word32' value on 64-bit systems (see [GHC's #16617](https://gitlab.haskell.org/ghc/ghc/-/issues/16617)).
diff --git a/src/Numeric/Floating/IEEE/Internal/Classify.hs b/src/Numeric/Floating/IEEE/Internal/Classify.hs
--- a/src/Numeric/Floating/IEEE/Internal/Classify.hs
+++ b/src/Numeric/Floating/IEEE/Internal/Classify.hs
@@ -61,12 +61,14 @@
 -- |
 -- Comparison with IEEE 754 @totalOrder@ predicate.
 --
+-- Floating-point numbers are ordered as,
+-- \(-\infty < \text{negative reals} < -0 < +0 < \text{positive reals} < +\infty < \mathrm{NaN}\).
+--
 -- Since 'RealFloat' constraint is insufficient to query the sign and payload of NaNs,
 -- this function treats all NaNs as positive and does not make distinction between them.
 -- See also "Numeric.Floating.IEEE.NaN".
 --
--- Floating-point numbers are ordered as,
--- \(-\infty < \text{negative reals} < -0 < +0 < \text{positive reals} < +\infty < \mathrm{NaN}\).
+-- Also, for the same reason, this function cannot distinguish the members of a cohort.
 compareByTotalOrder :: RealFloat a => a -> a -> Ordering
 compareByTotalOrder x y
   | x < y = LT
diff --git a/src/Numeric/Floating/IEEE/Internal/NaN.hs b/src/Numeric/Floating/IEEE/Internal/NaN.hs
--- a/src/Numeric/Floating/IEEE/Internal/NaN.hs
+++ b/src/Numeric/Floating/IEEE/Internal/NaN.hs
@@ -35,6 +35,8 @@
   -- Returns @True@ if the operand is a signaling NaN.
   --
   -- IEEE 754 @isSignaling@ operation.
+  --
+  -- Warning: GHC's optimizer is not aware of signaling NaNs.
   isSignaling :: a -> Bool
   isSignaling x = classify x == SignalingNaN
 
@@ -73,6 +75,9 @@
 
   -- |
   -- Comparison with IEEE 754 @totalOrder@ operation.
+  --
+  -- Floating-point numbers should be ordered as,
+  -- \(-\mathrm{qNaN} < -\mathrm{sNaN} < -\infty < \text{negative reals} < -0 < +0 < \text{positive reals} < +\infty < +\mathrm{sNaN} < +\mathrm{qNaN}\).
   compareByTotalOrder :: a -> a -> Ordering
   compareByTotalOrder = compareByTotalOrderDefault
 
@@ -98,7 +103,7 @@
   | x == y = if x == 0 then
                compare (isNegativeZero y) (isNegativeZero x)
              else
-               EQ -- TODO: non-canonical?
+               EQ -- TODO: cohort?
   | otherwise = compare (isSignMinus y) (isSignMinus x)
                 <> let r = compare (isNaN x) (isNaN y) -- number < +NaN
                            <> compare (isSignaling y) (isSignaling x) -- +(signaling NaN) < +(quiet NaN)
diff --git a/test/HalfSpec.hs b/test/HalfSpec.hs
--- a/test/HalfSpec.hs
+++ b/test/HalfSpec.hs
@@ -51,10 +51,10 @@
 isInfiniteWorkaround :: (Half -> Property) -> (Half -> Property)
 isInfiniteIsKnownToBeBuggy :: Bool
 #if MIN_VERSION_half(0,3,1)
--- I hope https://github.com/ekmett/half/issues/23 is fixed before the next releaso
 isInfiniteWorkaround = id
 isInfiniteIsKnownToBeBuggy = False
 #else
+-- Workaround for https://github.com/ekmett/half/issues/23
 isInfiniteWorkaround f x = not (isNaN x) ==> f x
 isInfiniteIsKnownToBeBuggy = True
 #endif
