# 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](https://hackage.haskell.org/package/rounded), this package does not depend on an external C library. In addition to `Float` and `Double`, `LongDouble` from [long-double](https://hackage.haskell.org/package/long-double) package is supported on x86. There is also support for `Float128` from [float128](https://hackage.haskell.org/package/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`. ```haskell 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 ```haskell {-# 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 * On x86_64, `foreign import prim` is used to provide faster interval addition/subtraction. 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`. ```haskell >>> backendName (Proxy :: Proxy Double) "FastFFI+SSE2" ```