Skip to content

Commit

Permalink
Added AEq instance and convenience wrappers around IEEE functions. Fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
dmcclean committed Jan 27, 2016
1 parent d4bd3af commit 2e80f5b
Show file tree
Hide file tree
Showing 4 changed files with 88 additions and 2 deletions.
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ vNext
unknown dimension, suitable for performing arithmetic with such quantities.
* Added `nroot` function for term-level dimensions.
* Added the Numeric.Units.Dimensional.Float module with convenient wrappers around functions
from RealFloat for inspecting floating point quantities.
from RealFloat and IEEE for inspecting floating point quantities.
* Added an `AEq` instance for `Quantity`.
* Relocated git repository to https://github.com/bjornbm/dimensional

1.0.1.1 (2015-11)
Expand Down
1 change: 1 addition & 0 deletions dimensional.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ library
build-depends: base >= 4.7 && < 5,
deepseq >= 1.3,
exact-pi >= 0.2.1.1 && < 0.5,
ieee754 >= 0.7.6,
numtype-dk >= 0.5 && < 1.1,
vector >= 0.10
hs-source-dirs: src
Expand Down
82 changes: 82 additions & 0 deletions src/Numeric/Units/Dimensional/Float.hs
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,25 @@ module Numeric.Units.Dimensional.Float
isDenormalized, isInfinite, isNaN, isNegativeZero
-- * Convenience Functions
, isFiniteNumber, scaleFloat
-- * Lifted Functions from "Numeric.IEEE"
-- ** Values
, infinity, minNormal, maxFinite, epsilon, nan
-- ** Arithmetic
, predIEEE, succIEEE, bisectIEEE, copySign
-- ** NaN with Payload
, nanWithPayload, nanPayload, F.maxNaNPayload
-- ** Comparisons
, identicalIEEE, minNum, maxNum, minNaN, maxNaN
)
where

import Control.Applicative
import Data.Word (Word64)
import Prelude (RealFloat)
import qualified Prelude as P
import Numeric.IEEE (IEEE)
import qualified Numeric.IEEE as F
import Numeric.Units.Dimensional.Internal (liftQ, liftQ2)
import Numeric.Units.Dimensional.Prelude hiding (RealFloat(..))
import Numeric.Units.Dimensional.Coercion

Expand Down Expand Up @@ -64,3 +77,72 @@ isNegativeZero = P.isNegativeZero . unQuantity
-- True
scaleFloat :: RealFloat a => Int -> Quantity d a -> Quantity d a
scaleFloat x = Quantity . P.scaleFloat x . unQuantity

-- | An infinite floating-point quantity.
infinity :: IEEE a => Quantity d a
infinity = Quantity $ F.infinity

-- | The smallest representable positive quantity whose representation is normalized.
minNormal :: IEEE a => Quantity d a
minNormal = Quantity $ F.minNormal

-- | The largest representable finite floating-point quantity.
maxFinite :: IEEE a => Quantity d a
maxFinite = Quantity $ F.maxFinite

-- | The smallest positive value @x@ such that @1 + x@ is representable.
epsilon :: IEEE a => Dimensionless a
epsilon = Quantity $ F.epsilon

-- | @copySign x y@ returns the quantity @x@ with its sign changed to match that of @y@.
copySign :: IEEE a => Quantity d a -> Quantity d a -> Quantity d a
copySign = liftQ2 F.copySign

-- | Return 'True' if two floating-point quantities are /exactly/ (bitwise) equal.
identicalIEEE :: IEEE a => Quantity d a -> Quantity d a -> Bool
identicalIEEE (Quantity x) (Quantity y) = F.identicalIEEE x y

-- | Return the next largest representable floating-point quantity (@Infinity@ and @NaN@ are unchanged).
succIEEE :: IEEE a => Quantity d a -> Quantity d a
succIEEE = liftQ F.succIEEE

-- | Return the next smallest representable floating-point quantity (@Infinity@ and @NaN@ are unchanged).
predIEEE :: IEEE a => Quantity d a -> Quantity d a
predIEEE = liftQ F.predIEEE

-- | Given two floating-point quantities with the same sign, return the quantity whose representation is halfway
-- between their representations on the IEEE number line. If the signs of the values differ or either is @NaN@,
-- the value is undefined.
bisectIEEE :: IEEE a => Quantity d a -> Quantity d a -> Quantity d a
bisectIEEE (Quantity x) (Quantity y) = Quantity $ F.bisectIEEE x y

-- | Default @NaN@ quantity.
nan :: IEEE a => Quantity d a
nan = Quantity $ F.nan

-- | Quiet @NaN@ quantity with a positive integer payload.
-- Payload must be less than 'maxNaNPayload' of the representation type.
--
-- Beware that while some platforms allow using 0 as a payload, this behavior is not portable.
nanWithPayload :: IEEE a => Word64 -> Quantity d a
nanWithPayload = Quantity . F.nanWithPayload

-- | The payload stored in a @NaN@ quantity. Undefined if the argument is not @NaN@.
nanPayload :: IEEE a => Quantity d a -> Word64
nanPayload = F.nanPayload . unQuantity

-- | Return the minimum of two quantities; if one value is @NaN@, return the other. Prefer the first if both values are @NaN@.
minNum :: RealFloat a => Quantity d a -> Quantity d a -> Quantity d a
minNum = liftQ2 F.minNum

-- | Return the maximum of two quantities; if one value is @NaN@, return the other. Prefer the first if both values are @NaN@.
maxNum :: RealFloat a => Quantity d a -> Quantity d a -> Quantity d a
maxNum = liftQ2 F.maxNum

-- | Return the minimum of two quantities; if one value is @NaN@, return it. Prefer the first if both values are @NaN@.
minNaN :: RealFloat a => Quantity d a -> Quantity d a -> Quantity d a
minNaN = liftQ2 F.minNaN

-- | Return the maximum of two quantities; if one value is @NaN@, return it. Prefer the first if both values are @NaN@.
maxNaN :: RealFloat a => Quantity d a -> Quantity d a -> Quantity d a
maxNaN = liftQ2 F.maxNaN
4 changes: 3 additions & 1 deletion src/Numeric/Units/Dimensional/Internal.hs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE MultiParamTypeClasses #-} -- for Vector instances only
{-# LANGUAGE RankNTypes #-}
Expand All @@ -27,6 +28,7 @@ where
import Control.Applicative
import Control.DeepSeq
import Control.Monad (liftM)
import Data.AEq (AEq)
import Data.Coerce (coerce)
import Data.Data
import Data.ExactPi
Expand Down Expand Up @@ -75,7 +77,7 @@ deriving instance Typeable Dimensional

instance KnownVariant 'DQuantity where
newtype Dimensional 'DQuantity d a = Quantity a
deriving (Eq, Ord, Data, Generic, Generic1
deriving (Eq, Ord, AEq, Data, Generic, Generic1
#if MIN_VERSION_base(4,8,0)
, Typeable -- GHC 7.8 doesn't support deriving this instance
#endif
Expand Down

0 comments on commit 2e80f5b

Please sign in to comment.