Copyright | (c) 2014 Bryan O'Sullivan |
---|---|
License | BSD3 |
Maintainer | [email protected] |
Stability | experimental |
Portability | portable |
Safe Haskell | None |
Language | Haskell2010 |
Numeric.Sum
Description
Functions for summing floating point numbers more accurately than
the naive sum
function and its counterparts in the
vector
package and elsewhere.
When used with floating point numbers, in the worst case, the
sum
function accumulates numeric error at a rate
proportional to the number of values being summed. The algorithms
in this module implement different methods of /compensated
summation/, which reduce the accumulation of numeric error so that
it either grows much more slowly than the number of inputs
(e.g. logarithmically), or remains constant.
Synopsis
- class Summation s where
- sumVector :: (Vector v Double, Summation s) => (s -> Double) -> v Double -> Double
- data KBNSum = KBNSum !Double !Double
- kbn :: KBNSum -> Double
- data KB2Sum = KB2Sum !Double !Double !Double
- kb2 :: KB2Sum -> Double
- data KahanSum = KahanSum !Double !Double
- kahan :: KahanSum -> Double
- pairwiseSum :: Vector v Double => v Double -> Double
Summation type class
class Summation s where Source #
A class for summation of floating point numbers.
Methods
The identity for summation.
add :: s -> Double -> s Source #
Add a value to a sum.
sum :: Foldable f => (s -> Double) -> f Double -> Double Source #
sumVector :: (Vector v Double, Summation s) => (s -> Double) -> v Double -> Double Source #
O(n) Sum a vector of values.
Usage
Most of these summation algorithms are intended to be used via the
Summation
typeclass interface. Explicit type annotations should
not be necessary, as the use of a function such as kbn
or kb2
to extract the final sum out of a Summation
instance gives the
compiler enough information to determine the precise type of
summation algorithm to use.
As an example, here is a (somewhat silly) function that manually computes the sum of elements in a list.
sillySumList :: [Double] -> Double sillySumList = loopzero
where loop s [] =kbn
s loop s (x:xs) =seq
s' loop s' xs where s' =add
s x
In most instances, you can simply use the much more general sum
function instead of writing a summation function by hand.
-- Avoid ambiguity around which sum function we are using. import Prelude hiding (sum) -- betterSumList :: [Double] -> Double betterSumList xs =sum
kbn
xs
Kahan-Babuška-Neumaier summation
Kahan-Babuška-Neumaier summation. This is a little more computationally costly than plain Kahan summation, but is always at least as accurate.
Instances
Data KBNSum Source # | |
Defined in Numeric.Sum Methods gfoldl :: (forall d b. Data d => c (d -> b) -> d -> c b) -> (forall g. g -> c g) -> KBNSum -> c KBNSum # gunfold :: (forall b r. Data b => c (b -> r) -> c r) -> (forall r. r -> c r) -> Constr -> c KBNSum # toConstr :: KBNSum -> Constr # dataTypeOf :: KBNSum -> DataType # dataCast1 :: Typeable t => (forall d. Data d => c (t d)) -> Maybe (c KBNSum) # dataCast2 :: Typeable t => (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c KBNSum) # gmapT :: (forall b. Data b => b -> b) -> KBNSum -> KBNSum # gmapQl :: (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> KBNSum -> r # gmapQr :: forall r r'. (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> KBNSum -> r # gmapQ :: (forall d. Data d => d -> u) -> KBNSum -> [u] # gmapQi :: Int -> (forall d. Data d => d -> u) -> KBNSum -> u # gmapM :: Monad m => (forall d. Data d => d -> m d) -> KBNSum -> m KBNSum # gmapMp :: MonadPlus m => (forall d. Data d => d -> m d) -> KBNSum -> m KBNSum # gmapMo :: MonadPlus m => (forall d. Data d => d -> m d) -> KBNSum -> m KBNSum # | |
Monoid KBNSum Source # | Since: 0.3.0.0 |
Semigroup KBNSum Source # | Since: 0.3.0.0 |
Show KBNSum Source # | |
NFData KBNSum Source # | |
Defined in Numeric.Sum | |
Eq KBNSum Source # | |
Summation KBNSum Source # | |
Unbox KBNSum Source # | |
Defined in Numeric.Sum | |
Vector Vector KBNSum Source # | |
Defined in Numeric.Sum Methods basicUnsafeFreeze :: Mutable Vector s KBNSum -> ST s (Vector KBNSum) basicUnsafeThaw :: Vector KBNSum -> ST s (Mutable Vector s KBNSum) basicLength :: Vector KBNSum -> Int basicUnsafeSlice :: Int -> Int -> Vector KBNSum -> Vector KBNSum basicUnsafeIndexM :: Vector KBNSum -> Int -> Box KBNSum basicUnsafeCopy :: Mutable Vector s KBNSum -> Vector KBNSum -> ST s () | |
MVector MVector KBNSum Source # | |
Defined in Numeric.Sum Methods basicLength :: MVector s KBNSum -> Int basicUnsafeSlice :: Int -> Int -> MVector s KBNSum -> MVector s KBNSum basicOverlaps :: MVector s KBNSum -> MVector s KBNSum -> Bool basicUnsafeNew :: Int -> ST s (MVector s KBNSum) basicInitialize :: MVector s KBNSum -> ST s () basicUnsafeReplicate :: Int -> KBNSum -> ST s (MVector s KBNSum) basicUnsafeRead :: MVector s KBNSum -> Int -> ST s KBNSum basicUnsafeWrite :: MVector s KBNSum -> Int -> KBNSum -> ST s () basicClear :: MVector s KBNSum -> ST s () basicSet :: MVector s KBNSum -> KBNSum -> ST s () basicUnsafeCopy :: MVector s KBNSum -> MVector s KBNSum -> ST s () basicUnsafeMove :: MVector s KBNSum -> MVector s KBNSum -> ST s () basicUnsafeGrow :: MVector s KBNSum -> Int -> ST s (MVector s KBNSum) | |
newtype Vector KBNSum Source # | |
Defined in Numeric.Sum | |
newtype MVector s KBNSum Source # | |
Defined in Numeric.Sum |
Order-2 Kahan-Babuška summation
Second-order Kahan-Babuška summation. This is more computationally costly than Kahan-Babuška-Neumaier summation, running at about a third the speed. Its advantage is that it can lose less precision (in admittedly obscure cases).
This method compensates for error in both the sum and the first-order compensation term, hence the use of "second order" in the name.
Instances
Data KB2Sum Source # | |
Defined in Numeric.Sum Methods gfoldl :: (forall d b. Data d => c (d -> b) -> d -> c b) -> (forall g. g -> c g) -> KB2Sum -> c KB2Sum # gunfold :: (forall b r. Data b => c (b -> r) -> c r) -> (forall r. r -> c r) -> Constr -> c KB2Sum # toConstr :: KB2Sum -> Constr # dataTypeOf :: KB2Sum -> DataType # dataCast1 :: Typeable t => (forall d. Data d => c (t d)) -> Maybe (c KB2Sum) # dataCast2 :: Typeable t => (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c KB2Sum) # gmapT :: (forall b. Data b => b -> b) -> KB2Sum -> KB2Sum # gmapQl :: (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> KB2Sum -> r # gmapQr :: forall r r'. (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> KB2Sum -> r # gmapQ :: (forall d. Data d => d -> u) -> KB2Sum -> [u] # gmapQi :: Int -> (forall d. Data d => d -> u) -> KB2Sum -> u # gmapM :: Monad m => (forall d. Data d => d -> m d) -> KB2Sum -> m KB2Sum # gmapMp :: MonadPlus m => (forall d. Data d => d -> m d) -> KB2Sum -> m KB2Sum # gmapMo :: MonadPlus m => (forall d. Data d => d -> m d) -> KB2Sum -> m KB2Sum # | |
Monoid KB2Sum Source # | Since: 0.3.0.0 |
Semigroup KB2Sum Source # | Since: 0.3.0.0 |
Show KB2Sum Source # | |
NFData KB2Sum Source # | |
Defined in Numeric.Sum | |
Eq KB2Sum Source # | |
Summation KB2Sum Source # | |
Unbox KB2Sum Source # | |
Defined in Numeric.Sum | |
Vector Vector KB2Sum Source # | |
Defined in Numeric.Sum Methods basicUnsafeFreeze :: Mutable Vector s KB2Sum -> ST s (Vector KB2Sum) basicUnsafeThaw :: Vector KB2Sum -> ST s (Mutable Vector s KB2Sum) basicLength :: Vector KB2Sum -> Int basicUnsafeSlice :: Int -> Int -> Vector KB2Sum -> Vector KB2Sum basicUnsafeIndexM :: Vector KB2Sum -> Int -> Box KB2Sum basicUnsafeCopy :: Mutable Vector s KB2Sum -> Vector KB2Sum -> ST s () | |
MVector MVector KB2Sum Source # | |
Defined in Numeric.Sum Methods basicLength :: MVector s KB2Sum -> Int basicUnsafeSlice :: Int -> Int -> MVector s KB2Sum -> MVector s KB2Sum basicOverlaps :: MVector s KB2Sum -> MVector s KB2Sum -> Bool basicUnsafeNew :: Int -> ST s (MVector s KB2Sum) basicInitialize :: MVector s KB2Sum -> ST s () basicUnsafeReplicate :: Int -> KB2Sum -> ST s (MVector s KB2Sum) basicUnsafeRead :: MVector s KB2Sum -> Int -> ST s KB2Sum basicUnsafeWrite :: MVector s KB2Sum -> Int -> KB2Sum -> ST s () basicClear :: MVector s KB2Sum -> ST s () basicSet :: MVector s KB2Sum -> KB2Sum -> ST s () basicUnsafeCopy :: MVector s KB2Sum -> MVector s KB2Sum -> ST s () basicUnsafeMove :: MVector s KB2Sum -> MVector s KB2Sum -> ST s () basicUnsafeGrow :: MVector s KB2Sum -> Int -> ST s (MVector s KB2Sum) | |
newtype Vector KB2Sum Source # | |
newtype MVector s KB2Sum Source # | |
Less desirable approaches
Kahan summation
Kahan summation. This is the least accurate of the compensated summation methods. In practice, it only beats naive summation for inputs with large magnitude. Kahan summation can be less accurate than naive summation for small-magnitude inputs.
This summation method is included for completeness. Its use is not
recommended. In practice, KBNSum
is both 30% faster and more
accurate.
Instances
Data KahanSum Source # | |
Defined in Numeric.Sum Methods gfoldl :: (forall d b. Data d => c (d -> b) -> d -> c b) -> (forall g. g -> c g) -> KahanSum -> c KahanSum # gunfold :: (forall b r. Data b => c (b -> r) -> c r) -> (forall r. r -> c r) -> Constr -> c KahanSum # toConstr :: KahanSum -> Constr # dataTypeOf :: KahanSum -> DataType # dataCast1 :: Typeable t => (forall d. Data d => c (t d)) -> Maybe (c KahanSum) # dataCast2 :: Typeable t => (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c KahanSum) # gmapT :: (forall b. Data b => b -> b) -> KahanSum -> KahanSum # gmapQl :: (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> KahanSum -> r # gmapQr :: forall r r'. (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> KahanSum -> r # gmapQ :: (forall d. Data d => d -> u) -> KahanSum -> [u] # gmapQi :: Int -> (forall d. Data d => d -> u) -> KahanSum -> u # gmapM :: Monad m => (forall d. Data d => d -> m d) -> KahanSum -> m KahanSum # gmapMp :: MonadPlus m => (forall d. Data d => d -> m d) -> KahanSum -> m KahanSum # gmapMo :: MonadPlus m => (forall d. Data d => d -> m d) -> KahanSum -> m KahanSum # | |
Monoid KahanSum Source # | Since: 0.3.0.0 |
Semigroup KahanSum Source # | Since: 0.3.0.0 |
Show KahanSum Source # | |
NFData KahanSum Source # | |
Defined in Numeric.Sum | |
Eq KahanSum Source # | |
Summation KahanSum Source # | |
Unbox KahanSum Source # | |
Defined in Numeric.Sum | |
Vector Vector KahanSum Source # | |
Defined in Numeric.Sum Methods basicUnsafeFreeze :: Mutable Vector s KahanSum -> ST s (Vector KahanSum) basicUnsafeThaw :: Vector KahanSum -> ST s (Mutable Vector s KahanSum) basicLength :: Vector KahanSum -> Int basicUnsafeSlice :: Int -> Int -> Vector KahanSum -> Vector KahanSum basicUnsafeIndexM :: Vector KahanSum -> Int -> Box KahanSum basicUnsafeCopy :: Mutable Vector s KahanSum -> Vector KahanSum -> ST s () | |
MVector MVector KahanSum Source # | |
Defined in Numeric.Sum Methods basicLength :: MVector s KahanSum -> Int basicUnsafeSlice :: Int -> Int -> MVector s KahanSum -> MVector s KahanSum basicOverlaps :: MVector s KahanSum -> MVector s KahanSum -> Bool basicUnsafeNew :: Int -> ST s (MVector s KahanSum) basicInitialize :: MVector s KahanSum -> ST s () basicUnsafeReplicate :: Int -> KahanSum -> ST s (MVector s KahanSum) basicUnsafeRead :: MVector s KahanSum -> Int -> ST s KahanSum basicUnsafeWrite :: MVector s KahanSum -> Int -> KahanSum -> ST s () basicClear :: MVector s KahanSum -> ST s () basicSet :: MVector s KahanSum -> KahanSum -> ST s () basicUnsafeCopy :: MVector s KahanSum -> MVector s KahanSum -> ST s () basicUnsafeMove :: MVector s KahanSum -> MVector s KahanSum -> ST s () basicUnsafeGrow :: MVector s KahanSum -> Int -> ST s (MVector s KahanSum) | |
newtype Vector KahanSum Source # | |
Defined in Numeric.Sum | |
newtype MVector s KahanSum Source # | |
Defined in Numeric.Sum |
Pairwise summation
pairwiseSum :: Vector v Double => v Double -> Double Source #
O(n) Sum a vector of values using pairwise summation.
This approach is perhaps 10% faster than KBNSum
, but has poorer
bounds on its error growth. Instead of having roughly constant
error regardless of the size of the input vector, in the worst case
its accumulated error grows with O(log n).
References
- Kahan, W. (1965), Further remarks on reducing truncation errors. Communications of the ACM 8(1):40.
- Neumaier, A. (1974), Rundungsfehleranalyse einiger Verfahren zur Summation endlicher Summen. Zeitschrift für Angewandte Mathematik und Mechanik 54:39–51.
- Klein, A. (2006), A Generalized Kahan-Babuška-Summation-Algorithm. Computing 76(3):279-293.
- Higham, N.J. (1993), The accuracy of floating point summation. SIAM Journal on Scientific Computing 14(4):783–799.