packages feed

logfloat 0.12.0.1 → 0.12.1

raw patch · 7 files changed

+82/−77 lines, 7 filesPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

API changes (from Hackage documentation)

- Data.Number.PartialOrd: instance [overlap ok] (Ord a) => PartialOrd a
+ Data.Number.PartialOrd: instance [overlap ok] Ord a => PartialOrd a
- Data.Number.PartialOrd: cmp :: (PartialOrd a) => a -> a -> Maybe Ordering
+ Data.Number.PartialOrd: cmp :: PartialOrd a => a -> a -> Maybe Ordering
- Data.Number.PartialOrd: comparingPO :: (PartialOrd b) => (a -> b) -> a -> a -> Maybe Ordering
+ Data.Number.PartialOrd: comparingPO :: PartialOrd b => (a -> b) -> a -> a -> Maybe Ordering
- Data.Number.PartialOrd: eq :: (PartialOrd a) => a -> a -> Maybe Bool
+ Data.Number.PartialOrd: eq :: PartialOrd a => a -> a -> Maybe Bool
- Data.Number.PartialOrd: ge :: (PartialOrd a) => a -> a -> Maybe Bool
+ Data.Number.PartialOrd: ge :: PartialOrd a => a -> a -> Maybe Bool
- Data.Number.PartialOrd: gt :: (PartialOrd a) => a -> a -> Maybe Bool
+ Data.Number.PartialOrd: gt :: PartialOrd a => a -> a -> Maybe Bool
- Data.Number.PartialOrd: le :: (PartialOrd a) => a -> a -> Maybe Bool
+ Data.Number.PartialOrd: le :: PartialOrd a => a -> a -> Maybe Bool
- Data.Number.PartialOrd: lt :: (PartialOrd a) => a -> a -> Maybe Bool
+ Data.Number.PartialOrd: lt :: PartialOrd a => a -> a -> Maybe Bool
- Data.Number.PartialOrd: maxPO :: (PartialOrd a) => a -> a -> Maybe a
+ Data.Number.PartialOrd: maxPO :: PartialOrd a => a -> a -> Maybe a
- Data.Number.PartialOrd: minPO :: (PartialOrd a) => a -> a -> Maybe a
+ Data.Number.PartialOrd: minPO :: PartialOrd a => a -> a -> Maybe a
- Data.Number.PartialOrd: ne :: (PartialOrd a) => a -> a -> Maybe Bool
+ Data.Number.PartialOrd: ne :: PartialOrd a => a -> a -> Maybe Bool
- Data.Number.RealToFrac: realToFrac :: (RealToFrac a b) => a -> b
+ Data.Number.RealToFrac: realToFrac :: RealToFrac a b => a -> b
- Data.Number.Transfinite: class (PartialOrd a) => Transfinite a
+ Data.Number.Transfinite: class PartialOrd a => Transfinite a
- Data.Number.Transfinite: infinity :: (Transfinite a) => a
+ Data.Number.Transfinite: infinity :: Transfinite a => a
- Data.Number.Transfinite: isInfinite :: (Transfinite a) => a -> Bool
+ Data.Number.Transfinite: isInfinite :: Transfinite a => a -> Bool
- Data.Number.Transfinite: isNaN :: (Transfinite a) => a -> Bool
+ Data.Number.Transfinite: isNaN :: Transfinite a => a -> Bool
- Data.Number.Transfinite: negativeInfinity :: (Transfinite a) => a
+ Data.Number.Transfinite: negativeInfinity :: Transfinite a => a
- Data.Number.Transfinite: notANumber :: (Transfinite a) => a
+ Data.Number.Transfinite: notANumber :: Transfinite a => a
- Hugs.RealFloat: isInfinite :: (RealFloat a) => a -> Bool
+ Hugs.RealFloat: isInfinite :: RealFloat a => a -> Bool
- Hugs.RealFloat: isNaN :: (RealFloat a) => a -> Bool
+ Hugs.RealFloat: isNaN :: RealFloat a => a -> Bool

Files

LICENSE view
@@ -1,4 +1,4 @@-Copyright (c) 2007--2009, wren ng thornton.+Copyright (c) 2007--2010, wren ng thornton. ALL RIGHTS RESERVED.  Redistribution and use in source and binary forms, with or without
logfloat.cabal view
@@ -1,19 +1,19 @@ ------------------------------------------------------------------- wren ng thornton <wren@community.haskell.org>    ~ 2009.03.17+-- wren ng thornton <wren@community.haskell.org>    ~ 2010.03.19 ----------------------------------------------------------------  Name:           logfloat-Version:        0.12.0.1+Version:        0.12.1 Cabal-Version:  >= 1.2 Build-Type:     Simple Stability:      experimental-Copyright:      Copyright (c) 2007--2009 wren ng thornton+Copyright:      Copyright (c) 2007--2010 wren ng thornton License:        BSD3 License-File:   LICENSE Author:         wren ng thornton Maintainer:     wren@community.haskell.org Homepage:       http://code.haskell.org/~wren/-Category:       Data, Math, Natural Language Processing+Category:       Data, Math, Natural Language Processing, Statistics Synopsis:       Log-domain floating point numbers Description:    This module presents a type for storing numbers                 in the log-domain. The main reason for doing this
src/Data/Number/LogFloat.hs view
@@ -1,7 +1,10 @@- -- FlexibleContexts needed by our RealToFrac contexts -- CPP needed for IArray UArray instance -- FFI is for log1p+--     N.B. can't mix FFI and -fvia-C under ghc==6.10.1+--     <http://hackage.haskell.org/trac/ghc/ticket/3117>+--     TODO: figure out how to conditionally use "-fvia-C -optc-O3"+--     for ghc6.8 when not using Cabal to compile. {-# LANGUAGE FlexibleContexts            , CPP            , ForeignFunctionInterface@@ -17,19 +20,11 @@ -- cf <http://www.mail-archive.com/glasgow-haskell-users@haskell.org/msg14313.html> {-# OPTIONS_GHC -O2 -fexcess-precision -fglasgow-exts #-} --- BUG: Can't mix FFI and -fvia-C under GHC 6.10.1--- <http://hackage.haskell.org/trac/ghc/ticket/3117>--- TODO: see if -fasm gives the same performance boost--- TODO: figure out how to get these flags parsed.-#if defined(__GLASGOW_HASKELL__) && __GLASGOW_HASKELL__ < 610-{-# OPTIONS_GHC -fvia-C -optc-O3 #-}-#endif- -------------------------------------------------------------------                                                  ~ 2009.03.10+--                                                  ~ 2010.03.19 -- | -- Module      :  Data.Number.LogFloat--- Copyright   :  Copyright (c) 2007--2009 wren ng thornton+-- Copyright   :  Copyright (c) 2007--2010 wren ng thornton -- License     :  BSD3 -- Maintainer  :  wren@community.haskell.org -- Stability   :  stable@@ -48,9 +43,8 @@ -- are frequently done within a /O(n^3)/ loop. -- -- The 'LogFloat' of this module is restricted to non-negative--- numbers for efficiency's sake, see the forthcoming--- "Data.Number.LogFloat.Signed" for doing signed log-domain--- calculations. (Or harass the maintainer to write it already.)+-- numbers for efficiency's sake, see "Data.Number.LogFloat.Signed"+-- for doing signed log-domain calculations. ----------------------------------------------------------------  module Data.Number.LogFloat@@ -160,13 +154,15 @@ logFromLFUArray :: UArray a LogFloat -> UArray a Double logFromLFUArray = unsafeCoerce -{-# INLINE logToLFUArray #-}-logToLFUArray   :: UArray a Double -> UArray a LogFloat-logToLFUArray   = unsafeCoerce+-- Named unsafe because it could allow injecting NaN if misused+{-# INLINE unsafeLogToLFUArray #-}+unsafeLogToLFUArray :: UArray a Double -> UArray a LogFloat+unsafeLogToLFUArray = unsafeCoerce -{-# INLINE logToLFFunc #-}-logToLFFunc :: (LogFloat -> a -> LogFloat) -> (Double -> a -> Double)-logToLFFunc = ($. unsafeLogToLogFloat ~> id ~> logFromLogFloat)+-- Named unsafe because it could allow injecting NaN if misused+{-# INLINE unsafeLogToLFFunc #-}+unsafeLogToLFFunc :: (LogFloat -> a -> LogFloat) -> (Double -> a -> Double)+unsafeLogToLFFunc = ($. unsafeLogToLogFloat ~> id ~> logFromLogFloat)  -- | Remove the extranious 'isNaN' test of 'logToLogFloat', when -- we know it's safe.@@ -188,7 +184,7 @@          {-# INLINE unsafeArray #-}     unsafeArray =-        unsafeArray $. id ~> logFromLFAssocs ~> logToLFUArray+        unsafeArray $. id ~> logFromLFAssocs ~> unsafeLogToLFUArray          {-# INLINE unsafeAt #-}     unsafeAt =@@ -196,18 +192,20 @@          {-# INLINE unsafeReplace #-}     unsafeReplace =-        unsafeReplace $. logFromLFUArray ~> logFromLFAssocs ~> logToLFUArray+        unsafeReplace $. logFromLFUArray ~> logFromLFAssocs ~> unsafeLogToLFUArray          {-# INLINE unsafeAccum #-}     unsafeAccum =-        unsafeAccum $. logToLFFunc ~> logFromLFUArray ~> id ~> logToLFUArray+        unsafeAccum $. unsafeLogToLFFunc ~> logFromLFUArray ~> id ~> unsafeLogToLFUArray          {-# INLINE unsafeAccumArray #-}     unsafeAccumArray =-        unsafeAccumArray $. logToLFFunc ~> logFromLogFloat ~> id ~> id ~> logToLFUArray+        unsafeAccumArray $. unsafeLogToLFFunc ~> logFromLogFloat ~> id ~> id ~> unsafeLogToLFUArray #endif -+-- TODO: the Nothing branch should never be reachable. Once we get+-- a test suite up and going to *verify* the never-NaN invariant,+-- we should be able to eliminate the branch and the isNaN checks. instance PartialOrd LogFloat where     cmp (LogFloat x) (LogFloat y)          | isNaN x || isNaN y = Nothing@@ -216,23 +214,20 @@  ---------------------------------------------------------------- -- | Reduce the number of constant string literals we need to store.-errorOutOfRange    :: String -> a+errorOutOfRange :: String -> a {-# NOINLINE errorOutOfRange #-} errorOutOfRange fun = error $! "Data.Number.LogFloat."++fun                             ++ ": argument out of range" +-- Both guards are redundant due to the subsequent call to+-- 'Data.Number.Transfinite.log' at all use sites. However we use+-- this function to give local error messages. Perhaps we should+-- catch the exception and throw the new message instead? Portability? --- | We need these guards in order to ensure some invariants. guardNonNegative      :: String -> Double -> Double-guardNonNegative fun x | x >= 0    = x-                       | otherwise = errorOutOfRange fun-+guardNonNegative fun x | isNaN x || x < 0 = errorOutOfRange fun+                       | otherwise        = x --- | In general @log . guardNonNegative fun == guardIsANumber fun . log@--- This even holds on Hugs now. However, the latter issues an error--- from 'Data.Number.Transfinite.log' whereas the former issues an--- error from the calling function and is therefore more helpful--- for debugging. guardIsANumber        :: String -> Double -> Double guardIsANumber   fun x | isNaN x   = errorOutOfRange fun                        | otherwise = x@@ -315,12 +310,19 @@   ----------------------------------------------------------------+-- Technically these should use 'Foreign.C.CDouble' however there's+-- no isomorphism provided to normal 'Double'. The former is+-- documented as being a newtype of the later, and so this should+-- be safe.+ #ifdef __USE_FFI__ #define LOG1P_WHICH_VERSION specialized version. #else #define LOG1P_WHICH_VERSION naive version! \     Contact the maintainer with any FFI difficulties. #endif++ -- | Definition: @log1p == log . (1+)@. The C language provides a -- special definition for 'log1p' which is more accurate than doing -- the naive thing, especially for very small arguments. For example,@@ -333,14 +335,7 @@ #ifdef __USE_FFI__ foreign import ccall unsafe "math.h log1p"     log1p :: Double -> Double---- Technically we should use 'Foreign.C.CDouble' however there's--- no isomorphism provided to normal 'Double'. The former is--- documented as being a newtype of the later, and so this should--- be safe.- #else- log1p :: Double -> Double {-# INLINE log1p #-} log1p x = log (1 + x)@@ -374,24 +369,30 @@ -- +\/- 4e-16.  instance Num LogFloat where -    -- BUG? In Hugs (Sept2006) the (>=) always returns True if-    --      either isNaN. Only questionably a bug, since we try to-    --      ensure that notANumber never occurs. Still... perhaps-    --      we should use `ge` and other PartialOrd things in order-    --      to play it safe.-    -- TODO: benchmark and check core to see how much that hurts GHC.-    +    -- N.B. In Hugs (Sept2006) the (>=) always returns True if+    --      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) = LogFloat (x+y)+    (*) (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    = LogFloat (x + log1p (exp (y - x)))-        | otherwise = LogFloat (y + log1p (exp (x - 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)))     -    -- Without the guard this would return NaN instead of error     (-) (LogFloat x) (LogFloat y)-        | x >= y    = LogFloat (x + log1p (negate (exp (y - x))))-        | otherwise = errorOutOfRange "(-)"+        |    x == negativeInfinity+          && y == negativeInfinity = LogFloat negativeInfinity -- @0-0 == 0@+        | otherwise =+            -- Will throw error if x < y or if (x,y) is (infinity,infinity)+            LogFloat (guardIsANumber "(-)" (x + log1p (negate (exp (y - x)))))          signum (LogFloat x)         | x == negativeInfinity = 0@@ -401,21 +402,23 @@         -- 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   instance Fractional LogFloat where-    -- n/0 is handled seamlessly for us; we must catch 0/0 though+    -- n/0 == infinity is handled seamlessly for us. We must catch 0/0 and infinity/infinity NaNs, and handle 0/infinity.     (/) (LogFloat x) (LogFloat y)-        |    x == negativeInfinity-          && y == negativeInfinity = errorOutOfRange "(/)" -- protect vs NaN-        | otherwise                = LogFloat (x-y)+        | x == y+          && isInfinite x+          && isInfinite y       = errorOutOfRange "(/)"+        | x == negativeInfinity = LogFloat negativeInfinity -- @0/infinity == 0@+        | otherwise             = LogFloat (x-y)          fromRational = LogFloat . log                  . guardNonNegative "fromRational" . fromRational
src/Data/Number/PartialOrd.hs view
@@ -9,11 +9,11 @@ --                                                  ~ 2009.01.29 -- | -- Module      :  Data.Number.PartialOrd--- Copyright   :  Copyright (c) 2007--2009 wren ng thornton+-- Copyright   :  Copyright (c) 2007--2010 wren ng thornton -- License     :  BSD3 -- Maintainer  :  wren@community.haskell.org--- Stability   :  experimental--- Portability :  semi-portable (overlapping instances, etc)+-- Stability   :  stable+-- Portability :  semi-portable (OverlappingInstances,...) --  -- The Prelude's 'Ord' class for dealing with ordered types is often -- onerous to use because it requires 'Eq' as well as a total
src/Data/Number/RealToFrac.hs view
@@ -14,11 +14,11 @@ --                                                  ~ 2009.01.29 -- | -- Module      :  Data.Number.RealToFrac--- Copyright   :  Copyright (c) 2007--2009 wren ng thornton+-- Copyright   :  Copyright (c) 2007--2010 wren ng thornton -- License     :  BSD3 -- Maintainer  :  wren@community.haskell.org--- Stability   :  experimental--- Portability :  non-portable (CPP, MPTC, OverlappingInstances)+-- Stability   :  stable+-- Portability :  semi-portable (CPP, MPTC, OverlappingInstances) --  -- This module presents a type class for generic conversion between -- numeric types, generalizing @realToFrac@ in order to overcome
src/Data/Number/Transfinite.hs view
@@ -11,10 +11,10 @@ --                                                  ~ 2009.03.09 -- | -- Module      :  Data.Number.Transfinite--- Copyright   :  Copyright (c) 2007--2009 wren ng thornton+-- Copyright   :  Copyright (c) 2007--2010 wren ng thornton -- License     :  BSD3 -- Maintainer  :  wren@community.haskell.org--- Stability   :  experimental+-- Stability   :  stable -- Portability :  portable --  -- This module presents a type class for numbers which have
src/Hugs/RealFloat.hs view
@@ -11,10 +11,10 @@ #define REALFLOAT_VERSION normal Prelude version. This could be buggy. #endif -------------------------------------------------------------------                                                  ~ 2009.03.10+--                                                  ~ 2010.03.19 -- | -- Module      :  Hugs.RealFloat--- Copyright   :  Copyright (c) 2007--2009 wren ng thornton+-- Copyright   :  Copyright (c) 2007--2010 wren ng thornton -- License     :  BSD3 -- Maintainer  :  wren@community.haskell.org -- Stability   :  stable@@ -46,6 +46,7 @@  isInfinite  :: (RealFloat a) => a -> Bool {-# SPECIALIZE isInfinite :: Double -> Bool #-}+{-# SPECIALIZE isInfinite :: Float  -> Bool #-} {-# INLINE isInfinite #-} #if defined(__HUGS__) && (__HUGS__ <= 200609) isInfinite x = (1/0) == abs x@@ -56,6 +57,7 @@  isNaN :: (RealFloat a) => a -> Bool {-# SPECIALIZE isNaN :: Double -> Bool #-}+{-# SPECIALIZE isNaN :: Float  -> Bool #-} {-# INLINE isNaN #-} #if defined(__HUGS__) && (__HUGS__ <= 200609) isNaN x = compareEQ x 0 && compareEQ x 1