numhask-0.2.3.1: numeric classes

Safe HaskellNone
LanguageHaskell2010

NumHask.Data.LogField

Contents

Synopsis

LogField

data LogField a Source #

Module : Data.Number.LogFloat Copyright : Copyright (c) 2007--2015 wren gayle romano License : BSD3 Maintainer : wren@community.haskell.org Stability : stable Portability : portable (with CPP, FFI) Link : https://hackage.haskell.org/package/logfloat

A LogField is just a Field with a special interpretation. The LogField 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 hence will underflow at that point. This behavior may change in the future.

Because logField performs the semantic conversion, we can use operators which say what we *mean* rather than saying what we're actually doing to the underlying representation. That is, equivalences like the following are true[1] thanks to type-class overloading:

logField (p + q) == logField p + logField q
logField (p * q) == logField p * logField q

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 * LogField q * LogField r it's faster to do lp * LogField (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. Also note that, for precision, if you're doing more than a few multiplications in the log-domain, you should use product rather than using '(*)' repeatedly.

Even more particularly, you should avoid addition whenever possible. Addition is provided because sometimes we need it, and the proper implementation is not immediately apparent. However, between two LogFields addition requires crossing the exp/log boundary twice; with a LogField and a Double 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 normal-domain operations first, do it!

1
That is, true up-to underflow and floating point fuzziness. Which is, of course, the whole point of this module.

Instances

Functor LogField Source # 

Methods

fmap :: (a -> b) -> LogField a -> LogField b #

(<$) :: a -> LogField b -> LogField a #

Foldable LogField Source # 

Methods

fold :: Monoid m => LogField m -> m #

foldMap :: Monoid m => (a -> m) -> LogField a -> m #

foldr :: (a -> b -> b) -> b -> LogField a -> b #

foldr' :: (a -> b -> b) -> b -> LogField a -> b #

foldl :: (b -> a -> b) -> b -> LogField a -> b #

foldl' :: (b -> a -> b) -> b -> LogField a -> b #

foldr1 :: (a -> a -> a) -> LogField a -> a #

foldl1 :: (a -> a -> a) -> LogField a -> a #

toList :: LogField a -> [a] #

null :: LogField a -> Bool #

length :: LogField a -> Int #

elem :: Eq a => a -> LogField a -> Bool #

maximum :: Ord a => LogField a -> a #

minimum :: Ord a => LogField a -> a #

sum :: Num a => LogField a -> a #

product :: Num a => LogField a -> a #

Traversable LogField Source # 

Methods

traverse :: Applicative f => (a -> f b) -> LogField a -> f (LogField b) #

sequenceA :: Applicative f => LogField (f a) -> f (LogField a) #

mapM :: Monad m => (a -> m b) -> LogField a -> m (LogField b) #

sequence :: Monad m => LogField (m a) -> m (LogField a) #

Eq a => Eq (LogField a) Source # 

Methods

(==) :: LogField a -> LogField a -> Bool #

(/=) :: LogField a -> LogField a -> Bool #

Data a => Data (LogField a) Source # 

Methods

gfoldl :: (forall d b. Data d => c (d -> b) -> d -> c b) -> (forall g. g -> c g) -> LogField a -> c (LogField a) #

gunfold :: (forall b r. Data b => c (b -> r) -> c r) -> (forall r. r -> c r) -> Constr -> c (LogField a) #

toConstr :: LogField a -> Constr #

dataTypeOf :: LogField a -> DataType #

dataCast1 :: Typeable (* -> *) t => (forall d. Data d => c (t d)) -> Maybe (c (LogField a)) #

dataCast2 :: Typeable (* -> * -> *) t => (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c (LogField a)) #

gmapT :: (forall b. Data b => b -> b) -> LogField a -> LogField a #

gmapQl :: (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> LogField a -> r #

gmapQr :: (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> LogField a -> r #

gmapQ :: (forall d. Data d => d -> u) -> LogField a -> [u] #

gmapQi :: Int -> (forall d. Data d => d -> u) -> LogField a -> u #

gmapM :: Monad m => (forall d. Data d => d -> m d) -> LogField a -> m (LogField a) #

gmapMp :: MonadPlus m => (forall d. Data d => d -> m d) -> LogField a -> m (LogField a) #

gmapMo :: MonadPlus m => (forall d. Data d => d -> m d) -> LogField a -> m (LogField a) #

Ord a => Ord (LogField a) Source # 

Methods

compare :: LogField a -> LogField a -> Ordering #

(<) :: LogField a -> LogField a -> Bool #

(<=) :: LogField a -> LogField a -> Bool #

(>) :: LogField a -> LogField a -> Bool #

(>=) :: LogField a -> LogField a -> Bool #

max :: LogField a -> LogField a -> LogField a #

min :: LogField a -> LogField a -> LogField a #

Read a => Read (LogField a) Source # 
(ExpField a, Show a) => Show (LogField a) Source # 

Methods

showsPrec :: Int -> LogField a -> ShowS #

show :: LogField a -> String #

showList :: [LogField a] -> ShowS #

Generic (LogField a) Source # 

Associated Types

type Rep (LogField a) :: * -> * #

Methods

from :: LogField a -> Rep (LogField a) x #

to :: Rep (LogField a) x -> LogField a #

(LowerBoundedField a, ExpField a, Ord a) => Additive (LogField a) Source # 

Methods

(+) :: LogField a -> LogField a -> LogField a Source #

(LowerBoundedField a, ExpField a, Ord a) => AdditiveCommutative (LogField a) Source # 
(LowerBoundedField a, ExpField a, Ord a) => AdditiveAssociative (LogField a) Source # 
(LowerBoundedField a, ExpField a, Ord a) => AdditiveUnital (LogField a) Source # 

Methods

zero :: LogField a Source #

(ExpField a, LowerBoundedField a, Ord a) => AdditiveMagma (LogField a) Source # 

Methods

plus :: LogField a -> LogField a -> LogField a Source #

(Multiplicative (LogField a), AdditiveInvertible a, AdditiveGroup a, LowerBoundedField a, Eq a) => MultiplicativeGroup (LogField a) Source # 

Methods

(/) :: LogField a -> LogField a -> LogField a Source #

(AdditiveUnital a, AdditiveAssociative a, AdditiveInvertible a, AdditiveRightCancellative a, LowerBoundedField a, Eq a) => MultiplicativeRightCancellative (LogField a) Source # 

Methods

(/~) :: LogField a -> LogField a -> LogField a Source #

(AdditiveUnital a, AdditiveAssociative a, AdditiveInvertible a, AdditiveLeftCancellative a, LowerBoundedField a, Eq a) => MultiplicativeLeftCancellative (LogField a) Source # 

Methods

(~/) :: LogField a -> LogField a -> LogField a Source #

(AdditiveUnital a, AdditiveAssociative a, AdditiveCommutative a, Additive a, LowerBoundedField a, Eq a) => Multiplicative (LogField a) Source # 

Methods

(*) :: LogField a -> LogField a -> LogField a Source #

(AdditiveInvertible a, LowerBoundedField a, Eq a) => MultiplicativeInvertible (LogField a) Source # 

Methods

recip :: LogField a -> LogField a Source #

(AdditiveCommutative a, LowerBoundedField a, Eq a) => MultiplicativeCommutative (LogField a) Source # 
(AdditiveAssociative a, LowerBoundedField a, Eq a) => MultiplicativeAssociative (LogField a) Source # 
(AdditiveUnital a, LowerBoundedField a, Eq a) => MultiplicativeUnital (LogField a) Source # 

Methods

one :: LogField a Source #

(AdditiveMagma a, LowerBoundedField a, Eq a) => MultiplicativeMagma (LogField a) Source # 

Methods

times :: LogField a -> LogField a -> LogField a Source #

(LowerBoundedField a, ExpField a, Ord a, AdditiveMagma a) => Distribution (LogField a) Source # 
(FromInteger a, ExpField a) => FromInteger (LogField a) Source # 
(ToInteger a, ExpField a) => ToInteger (LogField a) Source # 
(Epsilon a, ExpField a, LowerBoundedField a, Ord a) => Epsilon (LogField a) Source # 
(FromRatio a, ExpField a) => FromRatio (LogField a) Source # 
(ToRatio a, ExpField a) => ToRatio (LogField a) Source # 
Generic1 * LogField Source # 

Associated Types

type Rep1 LogField (f :: LogField -> *) :: k -> * #

Methods

from1 :: f a -> Rep1 LogField f a #

to1 :: Rep1 LogField f a -> f a #

type Rep (LogField a) Source # 
type Rep (LogField a) = D1 * (MetaData "LogField" "NumHask.Data.LogField" "numhask-0.2.3.1-5X1V1rZSUVsE9M1b0C2H1i" True) (C1 * (MetaCons "LogField" PrefixI False) (S1 * (MetaSel (Nothing Symbol) NoSourceUnpackedness NoSourceStrictness DecidedLazy) (Rec0 * a)))
type Rep1 * LogField Source # 
type Rep1 * LogField = D1 * (MetaData "LogField" "NumHask.Data.LogField" "numhask-0.2.3.1-5X1V1rZSUVsE9M1b0C2H1i" True) (C1 * (MetaCons "LogField" PrefixI False) (S1 * (MetaSel (Nothing Symbol) NoSourceUnpackedness NoSourceStrictness DecidedLazy) Par1))

Isomorphism to normal-domain

logField :: ExpField a => a -> LogField a Source #

Constructor which does semantic conversion from normal-domain to log-domain. Throws errors on negative and NaN inputs. If p is non-negative, then following equivalence holds:

logField p == logToLogField (log p)

fromLogField :: ExpField a => LogField a -> a Source #

Semantically convert our log-domain value back into the normal-domain. Beware of overflow/underflow. The following equivalence holds (without qualification):

fromLogField == exp . logFromLogField

Isomorphism to log-domain

logToLogField :: a -> LogField a Source #

Constructor which assumes the argument is already in the log-domain.

logFromLogField :: LogField a -> a Source #

Return the log-domain value itself without conversion.

Additional operations

accurateSum :: (ExpField a, Foldable f, Ord a) => f (LogField a) -> LogField a Source #

O(n). Compute the sum of a finite list of LogFields, being careful to avoid underflow issues. That is, the following equivalence holds (modulo underflow and all that):

LogField . accurateSum == accurateSum . map LogField

N.B., this function requires two passes over the input. Thus, it is not amenable to list fusion, and hence will use a lot of memory when summing long lists.

accurateProduct :: (ExpField a, Foldable f) => f (LogField a) -> LogField a Source #

O(n). Compute the product of a finite list of LogFields, being careful to avoid numerical error due to loss of precision. That is, the following equivalence holds (modulo underflow and all that):

LogField . accurateProduct == accurateProduct . map LogField

pow :: (ExpField a, LowerBoundedField a, Ord a) => LogField a -> a -> LogField a infixr 8 Source #

O(1). Compute powers in the log-domain; that is, the following equivalence holds (modulo underflow and all that):

LogField (p ** m) == LogField p `pow` m

Since: 0.13