logfloat 0.13.3.3 → 0.13.4
raw patch · 4 files changed
+110/−74 lines, 4 filesnew-uploader
Files
- CHANGELOG +29/−13
- README.md +13/−12
- logfloat.cabal +19/−16
- src/Data/Number/LogFloat.hs +49/−33
CHANGELOG view
@@ -1,3 +1,6 @@+0.13.4 (2017-06-18):+ - Added Read LogFloat instance. (h/t Rob Zinkov)+ - Corrected a bug where `product` returns NaN on `logFloat 0`. 0.13.3.2 (2015-08-06): - Fixed the buggy Show LogFloat instance 0.13.3.1 (2015-05-30):@@ -15,7 +18,9 @@ - removed support for older versions of GHC, in order to clean things up 0.12.1 (2010-03-19):- - Fixed some NaN injection bugs in the Num instance. These would only have been triggered by non-probabilistic uses of LogFloat (i.e., if you used @logFloat infinity@)+ - Fixed some NaN injection bugs in the Num instance. These would+ only have been triggered by non-probabilistic uses of LogFloat+ (i.e., if you used @logFloat infinity@) 0.12.0.3 (2009-04-03): - Added notes to INSTALL about Windows compatibility 0.12.0.2 (2009-04-03):@@ -24,9 +29,10 @@ - Disabled -fvia-C so the FFI can be used in GHC 6.10 0.12 (2009-03-10): - Added log1p.- - Added Storable instance (for GHC only)- - removed orphaned toRational/fromRational rules. The RealToFrac module obviates those optimizations.- - Adjusted Real LogFloat instance to throw errors on transfinite values+ - Added Storable instance (for GHC only)+ - removed orphaned toRational/fromRational rules. The+ RealToFrac module obviates those optimizations.+ - Adjusted Real LogFloat instance to throw errors on transfinite values 0.11.2 (2009-03-09): - Moved log/exp rules from LogFloat into Transfinite@@ -35,26 +41,36 @@ 0.11.1 (2009-03-08): - Added IArray UArray LogFloat instance (thanks to Felipe Lessa). 0.11 (2009-01-29):- - Moved the RealToFrac class from Data.Number.Transfinite to Data.Number.RealToFrac. This breaks backwards compatibility if you depended directly on that module for the class. If you imported the class from Data.Number.LogFloat then you're still fine.- - Cabal build fail due to missing new module (Fixed in 0.11.0.1).+ - Moved the RealToFrac class from Data.Number.Transfinite to+ Data.Number.RealToFrac. This breaks backwards compatibility if+ you depended directly on that module for the class. If you+ imported the class from Data.Number.LogFloat then you're still+ fine.+ - Cabal build fail due to missing new module (Fixed in 0.11.0.1). 0.10 (2009-01-29):- - Hugs' Prelude definitions of isInfinite and isNaN for Float and Double are buggy. The new Hugs.RealFloat module provides correct implementations (defaulting to the Prelude definition for non-Hugs compilers).- - The PartialOrd and Transfinite instances for Double and Float have been updated to use these corrected functions.- - Added maxPO and minPO to PartialOrd and added comparingPO to Data.Number.PartialOrd.- - Minor changes to circumvent bugs in Hackage's new version of Haddock. You should be able to see all the documentation now.+ - Hugs' Prelude definitions of isInfinite and isNaN for Float+ and Double are buggy. The new Hugs.RealFloat module provides+ correct implementations (defaulting to the Prelude definition+ for non-Hugs compilers).+ - The PartialOrd and Transfinite instances for Double and Float+ have been updated to use these corrected functions.+ - Added maxPO and minPO to PartialOrd and added comparingPO to+ Data.Number.PartialOrd.+ - Minor changes to circumvent bugs in Hackage's new version of+ Haddock. You should be able to see all the documentation now. 0.9.1 (2008-08-30): - Fixed some PartialOrd stuff and sanitized documentation- - Build fail on GHC 6.10 due to GHC.Prim (Fixed in 0.9.1.1).+ - Build fail on GHC 6.10 due to GHC.Prim (Fixed in 0.9.1.1). 0.9.0 (2008-08-30): - s/toFractional/realToFrac/g. - Also moved realToFrac and log to Transfinite- - Build fail on GHC 6.10 due to GHC.Prim+ - Build fail on GHC 6.10 due to GHC.Prim 0.8.6 (2008-08-17): - Removed buggy RULES- - Build fail on GHC 6.10 due to -Werror and removal of -fno-warn-orphans+ - Build fail on GHC 6.10 due to -Werror and removal of -fno-warn-orphans 0.8.5 (2008-08-17): - Gave up and converted from lhs to hs so Hackage docs work 0.8.4 (2008-08-17):
README.md view
@@ -1,8 +1,8 @@ logfloat ========-[](https://hackage.haskell.org/package/logfloat) +[](https://hackage.haskell.org/package/logfloat) [](http://packdeps.haskellers.com/specific?package=logfloat)-[](https://travis-ci.org/wrengr/logfloat) +[](https://travis-ci.org/wrengr/logfloat) [](https://circleci.com/gh/wrengr/logfloat) This package provides a type for storing numbers in the log-domain,@@ -35,11 +35,11 @@ -- With cabal-install and without the source: $> cabal install logfloat- + -- With cabal-install and with the source already: $> cd logfloat $> cabal install- + -- Without cabal-install, but with the source already: $> cd logfloat $> runhaskell Setup.hs configure --user@@ -77,14 +77,15 @@ ### Windows FFI -The logfloat package builds and installs cleanly with GHC on Windows-(without needing Cygwin nor Mingw/Msys), and the installed package-can be used in compiled programs without any issues.+The logfloat package builds and installs cleanly with GHC 8.0 and+later on Windows (without needing Cygwin nor Mingw/Msys), and the+installed package can be used in compiled programs without any+issues. -However, by default, the package does not work from the GHCi debugger-and gives errors like "can't load .so/.DLL for: m (addDLL: could-not load DLL)". This is a long-standing issue with GHCi having to-do with the fact that, on Windows, the so-called "libm" file does+Prior to GHC 8.0, the package does not work from the GHCi debugger+by default and gives errors like "can't load .so/.DLL for: m (addDLL:+could not load DLL)". This is a long-standing issue with GHCi having+to do with the fact that, on Windows, the so-called "libm" file does not actually contain anything (as it does on POSIX) and the C functions we use are instead placed in `libmingwex.a` (which comes bundled with GHC). The problem is that `ghc` (the compiler) knows@@ -168,7 +169,7 @@ to find <math.h>, not having prototypes for functions, or linking errors, be sure *not* to pass -D__USE_FFI__ to the cpp filter for ffihugs.- + Notably, Hugs installs cpphs under the name "cpphs-hugs" by default. The `which` command will try to resolve the location, assuming it's on your $PATH. If it isn't, then change the --with-cpphs= flag to
logfloat.cabal view
@@ -1,21 +1,18 @@ ------------------------------------------------------------------- wren gayle romano <wren@community.haskell.org> ~ 2015.10.02+-- wren gayle romano <wren@community.haskell.org> ~ 2021.10.16 ---------------------------------------------------------------- --- By and large Cabal >=1.2 is fine; but--- * >=1.6 gives tested-with: and source-repository:--- * >=1.8 allows executables to build-depends: on the library--- * >=1.9.2 allows Test-Suite-Cabal-Version: >= 1.9.2+-- Cabal >=1.10 is required by Hackage.+Cabal-Version: >= 1.10 Build-Type: Simple Name: logfloat-Version: 0.13.3.3+Version: 0.13.4 Stability: experimental-Homepage: http://code.haskell.org/~wren/+Homepage: http://wrengr.org Author: wren gayle romano-Maintainer: wren@community.haskell.org-Copyright: Copyright (c) 2007--2015 wren gayle romano+Maintainer: wren@cpan.org+Copyright: Copyright (c) 2007--2021 wren gayle romano License: BSD3 License-File: LICENSE @@ -31,16 +28,21 @@ Extra-source-files: README.md, CHANGELOG --- Cf., <https://travis-ci.org/wrengr/bytestring-lexing>+-- This should work as far back as GHC 7.6.1, but we don't verify that by CI.+-- <https://github.com/wrengr/logfloat/actions?query=workflow%3Aci> Tested-With:- GHC ==7.6.1, GHC ==7.6.2, GHC ==7.6.3,- GHC ==7.8.1, GHC ==7.8.2, GHC ==7.8.3, GHC ==7.8.4,- GHC ==7.10.1, GHC ==7.10.2+ GHC ==8.0.2,+ GHC ==8.2.2,+ GHC ==8.4.4,+ GHC ==8.6.5,+ GHC ==8.8.4,+ GHC ==8.10.3,+ GHC ==9.0.1 ---------------------------------------------------------------- Source-Repository head- Type: darcs- Location: http://community.haskell.org/~wren/logfloat+ Type: git+ Location: git://github.com/wrengr/logfloat.git ---------------------------------------------------------------- Flag useFFI@@ -52,6 +54,7 @@ ---------------------------------------------------------------- Library+ Default-Language: Haskell2010 Hs-Source-Dirs: src Exposed-Modules: Data.Number.LogFloat , Data.Number.RealToFrac
src/Data/Number/LogFloat.hs view
@@ -14,10 +14,10 @@ {-# OPTIONS_GHC -O2 -fexcess-precision -fenable-rewrite-rules #-} ------------------------------------------------------------------- ~ 2015.08.06+-- ~ 2017.06.18 -- | -- Module : Data.Number.LogFloat--- Copyright : Copyright (c) 2007--2015 wren gayle romano+-- Copyright : Copyright (c) 2007--2017 wren gayle romano -- License : BSD3 -- Maintainer : wren@community.haskell.org -- Stability : stable@@ -44,7 +44,7 @@ ( -- * Exceptional numeric values module Data.Number.Transfinite- + -- * @LogFloat@ data type , LogFloat() -- ** Isomorphism to normal-domain@@ -56,7 +56,7 @@ -- ** Additional operations , sum, product , pow- + -- * Accurate versions of logarithm\/exponentiation , log1p, expm1 ) where@@ -80,7 +80,7 @@ #elif __NHC__ import NonStdUnsafeCoerce (unsafeCoerce) #elif __GLASGOW_HASKELL__ >= 710--- For when the *heap* representations are the same +-- For when the *heap* representations are the same --import Data.Coerce (coerce) -- For when the *unboxed array* storage representations are the same import Unsafe.Coerce (unsafeCoerce)@@ -98,6 +98,9 @@ -- in order to ensure semantic conversion. At present the 'Show' -- instance will convert back to the normal-domain, and hence will -- underflow at that point. This behavior may change in the future.+-- At present, the 'Read' instance parses things in the normal-domain+-- and then converts them to the log-domain. Again, this behavior+-- may change in the future. -- -- Because 'logFloat' performs the semantic conversion, we can use -- operators which say what we *mean* rather than saying what we're@@ -159,33 +162,38 @@ #if __GLASGOW_HASKELL__ >= 710 -- TODO: this version should also work for NHC and Hugs, I think...--- HACK: we should be able to just unsafeCoerce the functions themselves, instead of coercing the inputs and the outputs; but, GHC 7.10 seems to get confused about trying to coerce the index types too... To fix this we give explicit signatures, as below, but this requires both ScopedTypeVariables and InstanceSigs; and I'm not sure when InstanceSigs was introduced.+-- HACK: we should be able to just unsafeCoerce the functions+-- themselves, instead of coercing the inputs and the outputs; but,+-- GHC 7.10 seems to get confused about trying to coerce the index+-- types too... To fix this we give explicit signatures, as below,+-- but this requires both ScopedTypeVariables and InstanceSigs; and+-- I'm not sure when InstanceSigs was introduced. instance IArray UArray LogFloat where {-# INLINE bounds #-} bounds :: forall i. Ix i => UArray i LogFloat -> (i, i) bounds = unsafeCoerce (bounds :: UArray i Double -> (i, i))- + {-# INLINE numElements #-} numElements :: forall i. Ix i => UArray i LogFloat -> Int numElements = unsafeCoerce (numElements :: UArray i Double -> Int)- + {-# INLINE unsafeArray #-} unsafeArray :: forall i. Ix i => (i,i) -> [(Int,LogFloat)] -> UArray i LogFloat unsafeArray = unsafeCoerce (unsafeArray :: (i,i) -> [(Int,Double)] -> UArray i Double)- + {-# INLINE unsafeAt #-} unsafeAt :: forall i. Ix i => UArray i LogFloat -> Int -> LogFloat unsafeAt = unsafeCoerce (unsafeAt :: UArray i Double -> Int -> Double)- + {-# INLINE unsafeReplace #-} unsafeReplace :: forall i. Ix i => UArray i LogFloat -> [(Int,LogFloat)] -> UArray i LogFloat unsafeReplace = unsafeCoerce (unsafeReplace :: UArray i Double -> [(Int,Double)] -> UArray i Double)- + {-# INLINE unsafeAccum #-} unsafeAccum :: forall i e. Ix i => (LogFloat -> e -> LogFloat) -> UArray i LogFloat -> [(Int,e)] -> UArray i LogFloat unsafeAccum = unsafeCoerce (unsafeAccum :: (Double -> e -> Double) -> UArray i Double -> [(Int,e)] -> UArray i Double)- + {-# INLINE unsafeAccumArray #-} unsafeAccumArray :: forall i e. Ix i => (LogFloat -> e -> LogFloat) -> LogFloat -> (i,i) -> [(Int,e)] -> UArray i LogFloat unsafeAccumArray = unsafeCoerce (unsafeAccumArray :: (Double -> e -> Double) -> Double -> (i,i) -> [(Int,e)] -> UArray i Double)@@ -241,30 +249,30 @@ instance IArray UArray LogFloat where {-# INLINE bounds #-} bounds = bounds . logFromLFUArray- + -- Apparently this method was added in base-2.0/GHC-6.6 but Hugs -- (Sept 2006) doesn't have it. Not sure about NHC's base #if (!(defined(__HUGS__))) || (__HUGS__ > 200609) {-# INLINE numElements #-} numElements = numElements . logFromLFUArray #endif- + {-# INLINE unsafeArray #-} unsafeArray = unsafeArray $:: id ~> logFromLFAssocs ~> unsafeLogToLFUArray- + {-# INLINE unsafeAt #-} unsafeAt = unsafeAt $:: logFromLFUArray ~> id ~> unsafeLogToLogFloat- + {-# INLINE unsafeReplace #-} unsafeReplace = unsafeReplace $:: logFromLFUArray ~> logFromLFAssocs ~> unsafeLogToLFUArray- + {-# INLINE unsafeAccum #-} unsafeAccum = unsafeAccum $:: unsafeLogToLFFunc ~> logFromLFUArray ~> id ~> unsafeLogToLFUArray- + {-# INLINE unsafeAccumArray #-} unsafeAccumArray = unsafeAccumArray $:: unsafeLogToLFFunc ~> logFromLogFloat ~> id ~> id ~> unsafeLogToLFUArray@@ -278,6 +286,9 @@ | isNaN x || isNaN y = Nothing | otherwise = Just $! x `compare` y +instance Read LogFloat where+ readsPrec p s =+ [(LogFloat (log x), r) | (x, r) <- readsPrec p s, not (isNaN x), x >= 0] ---------------------------------------------------------------- -- | Reduce the number of constant string literals we need to store.@@ -458,20 +469,20 @@ -- either isNaN. This does not constitute a bug since we -- maintain the invariant that values wrapped by 'LogFloat' -- are not NaN.- + (*) (LogFloat x) (LogFloat y) | isInfinite x && isInfinite y && x == negate y = LogFloat negativeInfinity -- @0*infinity == 0@ | otherwise = LogFloat (x+y)- + (+) (LogFloat x) (LogFloat y) | x == y && isInfinite x && isInfinite y = LogFloat x -- @0+0 == 0@, @infinity+infinity == infinity@ | x >= y = LogFloat (x + log1p (exp (y - x))) | otherwise = LogFloat (y + log1p (exp (x - y)))- + (-) (LogFloat x) (LogFloat y) | x == negativeInfinity && y == negativeInfinity = LogFloat negativeInfinity -- @0-0 == 0@@@ -480,7 +491,7 @@ -- TODO: flip @x@ and @y@ when @y > x@. -- Also, will throw error if (x,y) is (infinity,infinity) LogFloat (guardIsANumber "(-)" (x + log1p (negate (exp (y - x)))))- + signum (LogFloat x) | x == negativeInfinity = 0 | x > negativeInfinity = 1@@ -489,11 +500,11 @@ -- broke the invariant. That shouldn't be possible and -- so noone else bothers to check, but we check here just -- in case.- + negate _ = errorOutOfRange "negate"- + abs = id- + fromInteger = LogFloat . log . guardNonNegative "fromInteger" . fromInteger @@ -507,7 +518,7 @@ && isInfinite y = errorOutOfRange "(/)" | x == negativeInfinity = LogFloat negativeInfinity -- @0/infinity == 0@ | otherwise = LogFloat (x-y)- + fromRational = LogFloat . log . guardNonNegative "fromRational" . fromRational @@ -577,7 +588,7 @@ sum xs = LogFloat (theMax + log theSum) where LogFloat theMax = maximum xs- + -- compute @\log \sum_{x \in xs} \exp(x - theMax)@ theSum = foldl' (\ acc (LogFloat x) -> acc + exp (x - theMax)) 0 xs @@ -600,12 +611,17 @@ where kahan t c _ | t `seq` c `seq` False = undefined kahan t _ [] = LogFloat t- kahan t c (LogFloat x : xs) =- -- Beware this getting incorrectly optimized away by constant folding!- let y = x - c- t' = t + y- c' = (t' - t) - y- in kahan t' c' xs+ kahan t c (LogFloat x : xs)+ -- Avoid NaN when there's a negInfty in the list. N.B.,+ -- this causes zero to annihilate infinity.+ | x == negativeInfinity = LogFloat negativeInfinity+ | otherwise =+ -- Beware this getting incorrectly optimized away by+ -- constant folding!+ let y = x - c+ t' = t + y+ c' = (t' - t) - y+ in kahan t' c' xs -- This version *completely* eliminates rounding errors and loss -- of significance due to catastrophic cancellation during summation.