-- Hoogle documentation, generated by Haddock -- See Hoogle, http://www.haskell.org/hoogle/ -- | Log-domain floating point numbers -- -- This module presents a class for storing numbers in the log-domain. -- The main reason for doing this is to prevent underflow when -- multiplying many probabilities as is done in Hidden Markov Models. It -- is also helpful for preventing overflow. @package logfloat @version 0.8.4 -- | This module presents a type class for numbers which have -- representations for transfinite values. The idea originated from the -- IEEE-754 floating-point special values, used by -- Data.Number.LogFloat. However not all Fractional types -- necessarily support transfinite values. In particular, Ratio -- types including Rational do not have portable representations. -- -- For the Glasgow compiler (GHC 6.8.2), GHC.Real defines -- 1%0 and 0%0 as representations for infinity -- and notANumber, but most operations on them will raise -- exceptions. If toRational is used on an infinite floating -- value, the result is a rational with a numerator sufficiently large -- that it will overflow when converted back to a Double. If -- used on NaN, the result would convert back as negativeInfinity. -- -- Hugs (September 2006) stays closer to the haskell98 spec and offers no -- way of constructing those values, raising arithmetic overflow errors -- if attempted. module Data.Number.Transfinite -- | Many numbers are not Bounded yet, even though they can -- represent arbitrarily large values, they are not necessarily able to -- represent transfinite values such as infinity itself. This class is -- for types which are capable of representing such values. Notably, this -- class does not require the type to be Fractional nor -- Floating since integral types could also have representations -- for transfinite values. -- -- In particular, this class extends the Ord projection to have a -- maximum value infinity and a minimum value -- negativeInfinity, as well as an exceptional value -- notANumber. All the natural laws regarding infinity -- and negativeInfinity should pertain. Additionally, -- infinity - infinity should return notANumber (as -- should 0/0 and infinity/infinity if the type is -- Fractional). Any operations on notANumber will also -- return notANumber, and any equality or ordering comparison on -- notANumber must return False. -- -- Minimum complete definition is infinity, isInfinite, -- and isNaN. class (Num a, Ord a) => Transfinite a infinity :: (Transfinite a) => a negativeInfinity :: (Transfinite a) => a notANumber :: (Transfinite a) => a isInfinite :: (Transfinite a) => a -> Bool isNaN :: (Transfinite a) => a -> Bool instance Transfinite Float instance Transfinite Double -- | This module presents a type for storing numbers in the log-domain. The -- main reason for doing this is to prevent underflow when multiplying -- many small probabilities as is done in Hidden Markov Models and other -- statistical models often used for natural language processing. The -- log-domain also helps prevent overflow when multiplying many large -- numbers. In rare cases it can speed up numerical computation (since -- addition is faster than multiplication, though logarithms are -- exceptionally slow), but the primary goal is to improve accuracy of -- results. A secondary goal has been to maximize efficiency since these -- computations 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. module Data.Number.LogFloat -- | Since the normal log throws an error on zero, we have to -- redefine it in order for things to work right. Arguing from limits we -- can see that log 0 == negativeInfinity. -- -- In order to improve portability, the Transfinite class is -- required to indicate that the Floating type does in fact have a -- representation for negative infinity. Both native Floating -- types (Double and Float) are supported. If you define -- your own instance of Transfinite, verify the above equation -- holds for your 0 and negativeInfinity. If it -- doesn't, then you should avoid importing our log and will -- probably want converters to handle the discrepancy when dealing with -- LogFloats. log :: (Floating a, Transfinite a) => a -> a -- | The most generic numeric converter I can come up with. All the -- built-in numeric types are Real, though Int and -- Integer aren't Fractional. Beware that converting -- transfinite values into Ratio types is error-prone and -- non-portable, as discussed in Data.Number.Transfinite. toFractional :: (Real a, Fractional b) => a -> b -- | A LogFloat is just a Double with a special -- interpretation. The logFloat function is presented instead of -- the constructor, in order to ensure semantic conversion. At present -- the Show instance will convert back to the normal-domain, and -- so will underflow at that point. This behavior may change in the -- future. -- -- Performing operations in the log-domain is cheap, prevents underflow, -- and is otherwise very nice for dealing with miniscule probabilities. -- However, crossing into and out of the log-domain is expensive and -- should be avoided as much as possible. In particular, if you're doing -- a series of multiplications as in lp * logFloat q * logFloat -- r it's faster to do lp * logFloat (q * r) if you're -- reasonably sure the normal-domain multiplication won't underflow, -- because that way you enter the log-domain only once, instead of twice. -- -- Even more particularly, you should avoid addition whenever -- possible. Addition is provided because it's necessary at times and the -- proper implementation is not immediately transparent. However, between -- two LogFloats addition requires crossing the exp/log boundary -- twice; with a LogFloat and a regular number it's three times -- since the regular number needs to enter the log-domain first. This -- makes addition incredibly slow. Again, if you can parenthesize to do -- plain operations first, do it! data LogFloat -- | A constructor which does semantic conversion from normal-domain to -- log-domain. logFloat :: (Real a) => a -> LogFloat -- | Constructor which assumes the argument is already in the log-domain. logToLogFloat :: (Real a) => a -> LogFloat -- | Return our log-domain value back into normal-domain. Beware of -- overflow/underflow. fromLogFloat :: (Fractional a, Transfinite a) => LogFloat -> a -- | Return the log-domain value itself without costly conversion logFromLogFloat :: (Fractional a, Transfinite a) => LogFloat -> a instance Eq LogFloat instance Ord LogFloat instance Real LogFloat instance Fractional LogFloat instance Num LogFloat instance Show LogFloat