@hackage / rounded-hw

Directed rounding for built-in floating types

Latest0.4.0.2

About

Metadata

  • Last updated , by aratamizuki
  • License BSD-3-Clause
  • Categories Mathematics
  • Maintained by: minorinoki@gmail.com

  • Lottery factor: 1

Links

Installation

This package uses the Custom cabal build type

Tested Compilers

  1. 9.12.2
  2. 9.10.3
  3. 9.8.4
  4. 9.6.7
  5. 9.4.8
  6. 9.2.8
  7. 9.0.2
  8. 8.10.7
  9. 8.8.4
  10. 8.6.5

Package Flags

Use the -f option with cabal commands to enable flags

    pure-hs (off by default)

    Disable FFI

    c99 (off by default)

    Restrict use of platform-dependent features (e.g. SSE2) and only use C99 features

    avx512 (off by default)

    Use AVX512 EVEX encoding

    ghc-prim (on by default)

    Use GHC's "foreign import prim" on the supported platform

    x87-long-double (off by default)

    Support x87 "long double"

    float128 (off by default)

    Support Float128

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
    • 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.

>>> backendName (Proxy :: Proxy Double)
"FastFFI+SSE2"