rounded-hw: Directed rounding for built-in floating types

[ bsd3, library, math, numeric ] [ Propose Tags ]


Manual Flags


Disable FFI


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


Use AVX512 EVEX encoding


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


Support x87 "long double"


Support Float128


Use -f <flag> to enable a flag, or -f -<flag> to disable that flag. More info


Note: This package has metadata revisions in the cabal description newer than included in the tarball. To unpack the package including the revisions, use 'cabal get'.

Maintainer's Corner

For package maintainers and hackage trustees


Versions [RSS], 0.2.0, 0.3.0
Change log
Dependencies array, base (>=4.12 && <5), deepseq, fp-ieee (>=0.1 && <0.2), long-double, primitive, tagged, vector [details]
License BSD-3-Clause
Copyright 2022 ARATA Mizuki
Author ARATA Mizuki
Revised Revision 1 made by aratamizuki at 2022-01-08T08:34:50Z
Category Numeric, Math
Home page
Bug tracker
Source repo head: git clone
Uploaded by aratamizuki at 2022-01-08T07:30:28Z
Distributions NixOS:0.3.0
Downloads 349 total (14 in the last 30 days)
Rating (no votes yet) [estimated by Bayesian average]
Your Rating
  • λ
  • λ
  • λ
Status Docs available [build log]
Last success reported on 2022-01-08 [all 1 reports]

Readme for rounded-hw-0.3.0

[back to package description]

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.


{-# 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


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)