Directed rounding for built-in floating types.
Please see the README on GitHub at https://github.com/minoki/haskell-floating-point/tree/master/rounded-hw#readme
rounded-hw: Rounding control for built-in floating-point types
This package provides directed rounding and interval arithmetic for built-in floating-point types (i.e. Float
, Double
). Unlike rounded, this package does not depend on an external C library.
In addition to Float
and Double
, LongDouble
from long-double package is supported on x86. There is also support for Float128
from float128 package under a package flag.
API overview
Controlling the rounding direction
The type RoundingMode
represents the four rounding directions.
The type Rounded (r :: RoundingMode) a
is a wrapper for a
, with instances honoring the rounding direction given by r
.
module Numeric.Rounded.Hardware where
data RoundingMode
= ToNearest -- ^ Round to the nearest value (IEEE754 roundTiesToEven)
| TowardNegInf -- ^ Round downward (IEEE754 roundTowardNegative)
| TowardInf -- ^ Round upward (IEEE754 roundTowardPositive)
| TowardZero -- ^ Round toward zero (IEEE754 roundTowardZero)
newtype Rounded (r :: RoundingMode) a = Rounded { getRounded :: a }
instance ... => Num (Rounded r a)
instance ... => Fractional (Rounded r a)
instance ... => Real (Rounded r a)
instance ... => RealFrac (Rounded r a)
Interval arithmetic
This library also provides basic interval types. See Numeric.Rounded.Hardware.Interval
and Numeric.Rounded.Hardware.Interval.NonEmpty
.
Usage
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE HexFloatLiterals #-}
import Numeric
import Numeric.Rounded.Hardware
main = do
putStrLn $ showHFloat (1 + 0x1p-100 :: Double) "" -- -> 0x1p0
putStrLn $ showHFloat (1 + 0x1p-100 :: Rounded TowardInf Double) "" -- -> 0x1.0000000000001p0
Backends
There are several options to control the rounding direction.
- Pure Haskell (via
Rational
)- Very slow, but does not depend on FFI and therefore can be used on non-native backends.
- This implementation is always available via a newtype in
Numeric.Rounded.Hardware.Backend.ViaRational
.
- C FFI
- One of the technologies below is used:
- C99 (
fesetround
) - SSE2 (
_mm_setcsr
) - AVX512 EVEX encoding (
_mm_*_round_*
) - x87 Control Word (for x87 long double)
- AArch64 FPCR
- C99 (
- On x86_64,
foreign import prim
is used to provide faster interval addition/subtraction.
- One of the technologies below is used:
By default, C FFI is used and an appropriate technology is detected. To disable use of C FFI, set pure-hs
flag when building.
The name of the backend used can be obtained with Numeric.Rounded.Hardware.Backend.backendName
.
>>> backendName (Proxy :: Proxy Double)
"FastFFI+SSE2"