half 0.2.2.3 → 0.3
raw patch · 6 files changed
+154/−18 lines, 6 filesdep +QuickCheckdep +deepseqdep +ghc-primPVP ok
version bump matches the API change (PVP)
Dependencies added: QuickCheck, deepseq, ghc-prim, half, hspec, template-haskell
API changes (from Hackage documentation)
- Numeric.Half: newtype Half
+ Numeric.Half: instance Control.DeepSeq.NFData Numeric.Half.Half
+ Numeric.Half: instance GHC.Generics.Generic Numeric.Half.Half
+ Numeric.Half: instance Language.Haskell.TH.Syntax.Lift Numeric.Half.Half
+ Numeric.Half: newtype {-# CTYPE "unsigned short" #-} Half
Files
- .gitignore +2/−0
- .travis.yml +23/−6
- CHANGELOG.markdown +6/−0
- half.cabal +22/−4
- src/Numeric/Half.hs +69/−8
- test/Spec.hs +32/−0
.gitignore view
@@ -1,4 +1,6 @@ dist/+dist-newstyle/+.ghc.env* .hsenv/ docs wiki
.travis.yml view
@@ -14,24 +14,41 @@ include: - env: CABALVER=1.16 GHCVER=7.4.2 compiler: ": #GHC 7.4.2"- addons: {apt: {packages: [cabal-install-1.16,ghc-7.4.2,alex-3.1.4,happy-1.19.5], sources: [hvr-ghc]}}+ addons: {apt: {packages: [cabal-install-1.16,ghc-7.4.2,alex-3.1.7,happy-1.19.5], sources: [hvr-ghc]}} - env: CABALVER=1.16 GHCVER=7.6.3 compiler: ": #GHC 7.6.3"- addons: {apt: {packages: [cabal-install-1.16,ghc-7.6.3,alex-3.1.4,happy-1.19.5], sources: [hvr-ghc]}}+ addons: {apt: {packages: [cabal-install-1.16,ghc-7.6.3,alex-3.1.7,happy-1.19.5], sources: [hvr-ghc]}} - env: CABALVER=1.18 GHCVER=7.8.4 compiler: ": #GHC 7.8.4"- addons: {apt: {packages: [cabal-install-1.18,ghc-7.8.4,alex-3.1.4,happy-1.19.5], sources: [hvr-ghc]}}+ addons: {apt: {packages: [cabal-install-1.18,ghc-7.8.4,alex-3.1.7,happy-1.19.5], sources: [hvr-ghc]}} - env: CABALVER=1.22 GHCVER=7.10.1 compiler: ": #GHC 7.10.1"- addons: {apt: {packages: [cabal-install-1.22,ghc-7.10.1,alex-3.1.4,happy-1.19.5], sources: [hvr-ghc]}}+ addons: {apt: {packages: [cabal-install-1.22,ghc-7.10.1,alex-3.1.7,happy-1.19.5], sources: [hvr-ghc]}} - env: CABALVER=1.22 GHCVER=7.10.2 compiler: ": #GHC 7.10.2"- addons: {apt: {packages: [cabal-install-1.22,ghc-7.10.2,alex-3.1.4,happy-1.19.5], sources: [hvr-ghc]}}+ addons: {apt: {packages: [cabal-install-1.22,ghc-7.10.2,alex-3.1.7,happy-1.19.5], sources: [hvr-ghc]}}+ - env: CABALVER=1.24 GHCVER=8.0.2+ compiler: ": #GHC 8.0.2"+ addons: {apt: {packages: [cabal-install-1.24,ghc-8.0.2,alex-3.1.7,happy-1.19.5], sources: [hvr-ghc]}}+ - env: CABALVER=1.24 GHCVER=8.2.2+ compiler: ": #GHC 8.2.2"+ addons: {apt: {packages: [cabal-install-1.24,ghc-8.2.2,alex-3.1.7,happy-1.19.5], sources: [hvr-ghc]}}+ - env: CABALVER=2.0 GHCVER=8.4.1+ compiler: ": #GHC 8.4.1"+ addons: {apt: {packages: [cabal-install-2.0,ghc-8.4.1,alex-3.1.7,happy-1.19.5], sources: [hvr-ghc]}}+ - env: CABALVER=head GHCVER=head+ compiler: ": #GHC head"+ addons: {apt: {packages: [cabal-install-head,ghc-head,alex-3.1.7,happy-1.19.5], sources: [hvr-ghc]}} +# NOTE: The `primitve` package is currently broken with 8.4.1, remove the line below when this is fixed.+ allow_failures:+ - env: CABALVER=2.0 GHCVER=8.4.1+ - env: CABALVER=head GHCVER=head+ before_install: - unset CC - export HAPPYVER=1.19.5- - export ALEXVER=3.1.4+ - export ALEXVER=3.1.7 - export PATH=~/.cabal/bin:/opt/ghc/$GHCVER/bin:/opt/cabal/$CABALVER/bin:/opt/happy/$HAPPYVER/bin:/opt/alex/$ALEXVER/bin:$PATH install:
CHANGELOG.markdown view
@@ -1,3 +1,9 @@+0.3+---+* Fixed bound in `floatRange`.+* Fixed `decodeFloat`.+* Added a `Lift` instance for `Half` for `template-haskell` support.+ 0.2.2.3 ------- * Avoid the new warnings for missing pattern synonym signatures on GHC 8
half.cabal view
@@ -1,6 +1,6 @@ name: half category: Numeric-version: 0.2.2.3+version: 0.3 license: BSD3 cabal-version: >= 1.8 license-file: LICENSE@@ -11,9 +11,8 @@ bug-reports: http://github.com/ekmett/half/issues copyright: Copyright (C) 2014 Edward A. Kmett build-type: Simple-tested-with: GHC == 7.8.3 synopsis: Half-precision floating-point-description: Half-precision floating-point+description: Half-precision floating-point. extra-source-files: .travis.yml@@ -29,9 +28,28 @@ hs-source-dirs: src c-sources: cbits/half.c build-depends: base >= 4.3 && < 5+ , template-haskell+ if impl(ghc >= 7.8)+ build-depends: deepseq >= 1.4 && < 1.5+ if impl(ghc < 7.6)+ build-depends: ghc-prim ghc-options: -Wall -fwarn-tabs -O2 if impl(ghc >= 8)- ghc-options: -fno-warn-missing-pat-syn-sigs+ ghc-options: -Wno-missing-pattern-synonym-signatures exposed-modules: Numeric.Half++test-suite spec+ type: exitcode-stdio-1.0+ main-is: Spec.hs+ hs-source-dirs: test+ ghc-options: -Wall+ if impl(ghc >= 7.8)+ build-depends:+ base >= 4.3 && < 5+ , half+ , hspec >= 2.4+ , QuickCheck >= 2.9+ else+ buildable: False
src/Numeric/Half.hs view
@@ -1,9 +1,12 @@-{-# LANGUAGE CPP #-}+{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE CPP #-}+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE ForeignFunctionInterface #-}+{-# LANGUAGE TemplateHaskell #-} #if __GLASGOW_HASKELL__ >= 708 {-# LANGUAGE PatternSynonyms #-} #endif-{-# LANGUAGE DeriveDataTypeable #-}-{-# LANGUAGE ForeignFunctionInterface #-} #ifndef MIN_VERSION_base #define MIN_VERSION_base(x,y,z) 1@@ -42,13 +45,20 @@ #endif ) where +#if __GLASGOW_HASKELL__ >= 708+import Control.DeepSeq (NFData)+#endif import Data.Bits import Data.Function (on)+import Data.Int import Data.Typeable import Foreign.C.Types import Foreign.Ptr (castPtr) import Foreign.Storable-import Text.Read+import GHC.Generics+import Language.Haskell.TH+import Language.Haskell.TH.Syntax+import Text.Read hiding (lift) -- | Convert a 'Float' to a 'Half' with proper rounding, while preserving NaN and dealing appropriately with infinity foreign import ccall unsafe "hs_floatToHalf" toHalf :: Float -> Half@@ -62,12 +72,16 @@ #if __GLASGOW_HASKELL__ >= 706 {-# CTYPE "unsigned short" #-} #endif- Half = Half { getHalf :: CUShort } deriving (Typeable)+ Half = Half { getHalf :: CUShort } deriving (Generic, Typeable) +#if __GLASGOW_HASKELL__ >= 708+instance NFData Half where+#endif+ instance Storable Half where sizeOf = sizeOf . getHalf alignment = alignment . getHalf- peek p = peek (castPtr p) >>= return . Half+ peek p = fmap Half (peek (castPtr p)) poke p = poke (castPtr p) . getHalf instance Show Half where@@ -81,6 +95,10 @@ instance Ord Half where compare = compare `on` fromHalf+ (<) = (<) `on` fromHalf+ (<=) = (<=) `on` fromHalf+ (>) = (>) `on` fromHalf+ (>=) = (>=) `on` fromHalf instance Real Half where toRational = toRational . fromHalf@@ -121,7 +139,7 @@ instance RealFloat Half where floatRadix _ = 2 floatDigits _ = 11- decodeFloat = decodeFloat . fromHalf+ decodeFloat = ieee754_f16_decode isIEEE _ = isIEEE (undefined :: Float) atan2 a b = toHalf $ atan2 (fromHalf a) (fromHalf b) #if MIN_VERSION_base(4,5,0)@@ -135,7 +153,7 @@ #endif isNegativeZero (Half h) = h == 0x8000- floatRange _ = (16,-13)+ floatRange _ = (-13,16) encodeFloat i j = toHalf $ encodeFloat i j exponent = exponent . fromHalf significand = toHalf . significand . fromHalf@@ -190,3 +208,46 @@ abs = toHalf . abs . fromHalf signum = toHalf . signum . fromHalf fromInteger a = toHalf (fromInteger a)++instance Lift Half where+ lift (Half (CUShort w)) =+ appE (conE 'Half) . appE (conE 'CUShort) . litE . integerL . fromIntegral $+ w+++-- Adapted from ghc/rts/StgPrimFloat.c+--+ieee754_f16_decode :: Half -> (Integer, Int)+ieee754_f16_decode (Half (CUShort i)) =+ let+ _HHIGHBIT = 0x0400+ _HMSBIT = 0x8000+ _HMINEXP = ((_HALF_MIN_EXP) - (_HALF_MANT_DIG) - 1)+ _HALF_MANT_DIG = floatDigits (undefined::Half)+ (_HALF_MIN_EXP, _HALF_MAX_EXP) = floatRange (undefined::Half)++ high1 = fromIntegral i+ high2 = high1 .&. (_HHIGHBIT - 1)++ exp1 = ((fromIntegral high1 `unsafeShiftR` 10) .&. 0x1F) + _HMINEXP+ exp2 = exp1 + 1++ (high3, exp3)+ = if exp1 /= _HMINEXP+ then (high2 .|. _HHIGHBIT, exp1)+ else+ let go (!h, !e) =+ if h .&. _HHIGHBIT /= 0+ then go (h `unsafeShiftL` 1, e-1)+ else (h, e)+ in+ go (high2, exp2)++ high4 = if fromIntegral i < (0 :: Int16)+ then -high3+ else high3+ in+ if high1 .&. complement _HMSBIT == 0+ then (0,0)+ else (high4, exp3)+
+ test/Spec.hs view
@@ -0,0 +1,32 @@+{-# OPTIONS_GHC -fno-warn-orphans #-}++import Numeric.Half+import Test.Hspec+import Test.QuickCheck++instance Arbitrary Half where+ arbitrary = fmap Half arbitrary++main :: IO ()+main = hspec $ do+ describe "Half Ord instance" $ do+ it "(>=) is the opposite of (<) except for NaN" $+ property $ \x y ->+ ((x >= y) /= (x < y)) || isNaN x || isNaN (y :: Half)++ let nans = [QNaN, SNaN]++ it "returns False for NaN > NaN" $+ or [a > b | a <- nans, b <- nans] `shouldBe` False++ it "returns False for NaN < NaN" $+ or [a < b | a <- nans, b <- nans] `shouldBe` False++ describe "Round trip" $ do+ let roundTrip w = (getHalf . toHalf . fromHalf . Half $ w) == w++ it "should round trip properly" $+ property roundTrip++ it "should round trip for a NaN value" $+ roundTrip 0x7d00 `shouldBe` True