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 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.
|If you see no module description above, then the lhs2hs
script was not run correctly. Please rebuild the documentation
|IEEE floating-point special values
GHC.Real defines infinity and notANumber as
Rational. We export variants which are polymorphic because
that can be more helpful at times.
BUG: At present these constants are broken for Ratio
types including Rational, since Ratio types do not
typically permit a zero denominator. In GHC (6.8.2) the
result for infinity is a rational with a numerator
sufficiently large that fromRational will yield infinity
for Float and Double. In Hugs (September 2006) it
yields an arithmetic overflow error. For GHC, our notANumber
yields 0%1 rather than 0%0 as GHC.Real does.
Since the normal log throws an error on zero, we have
to redefine it in order for things to work right. Arguing from
limits it's obvious that log 0 == negativeInfinity.
If you're using some Floating type that's not built in, verify
this 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 discrepency.
|The most generic numeric converter I can come up with. All the
built-in numeric types are Real, though Int and Integer aren't
|LogFloat data type and conversion functions
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!
|A constructor which does semantic conversion from normal-domain
|Constructor which assumes the argument is already in the log-domain.
|Return our log-domain value back into normal-domain. Beware of
|Return the log-domain value itself without costly conversion
|Produced by Haddock version 2.4.2|