fp-ieee 0.1.0.1 → 0.1.0.2
raw patch · 9 files changed
+110/−422 lines, 9 filesdep +tasty-benchdep −decimal-arithmeticdep −gaugedep ~ghc-bignumPVP ok
version bump matches the API change (PVP)
Dependencies added: tasty-bench
Dependencies removed: decimal-arithmetic, gauge
Dependency ranges changed: ghc-bignum
API changes (from Hackage documentation)
Files
- ChangeLog.md +5/−0
- decimal-test/NextFloatSpec.hs +0/−42
- decimal-test/Spec.hs +0/−27
- decimal-test/Util.hs +0/−71
- fp-ieee.cabal +79/−273
- src/Numeric/Floating/IEEE.hs +15/−5
- src/Numeric/Floating/IEEE/Internal/Classify.hs +4/−2
- src/Numeric/Floating/IEEE/Internal/NaN.hs +6/−1
- test/HalfSpec.hs +1/−1
ChangeLog.md view
@@ -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.
− decimal-test/NextFloatSpec.hs
@@ -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
− decimal-test/Spec.hs
@@ -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
− decimal-test/Util.hs
@@ -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
fp-ieee.cabal view
@@ -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
src/Numeric/Floating/IEEE.hs view
@@ -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)).
src/Numeric/Floating/IEEE/Internal/Classify.hs view
@@ -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
src/Numeric/Floating/IEEE/Internal/NaN.hs view
@@ -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)
test/HalfSpec.hs view
@@ -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