An accumulator holds an exact sum in progress. Add vectors to it in any
order and in any number of pieces, merge accumulators built elsewhere,
and read the correctly rounded value at any time. The result is the same
as xsum() of all the pieces together, bit for bit.
Usage
xsum_acc(x = NULL, na.rm = FALSE)
xsum_add(acc, x, na.rm = FALSE)
xsum_merge(acc, other)
xsum_negate(acc)
xsum_value(acc)
xsum_mean_value(acc, n)Value
xsum_acc(), xsum_add(), xsum_merge() and xsum_negate()
return an accumulator. xsum_value() and xsum_mean_value() return a
double of length one.
Details
Accumulators are ordinary R values (raw vectors of class "xsum_acc",
568 bytes): xsum_add(), xsum_merge() and xsum_negate() return a new
accumulator and leave their argument unchanged. Because they are values,
they serialise: an accumulator built on a worker by parallel, mirai
or future comes back to the caller and merges there.
Reduce(xsum_merge, accs) combines a list of them in any order.
xsum_negate() changes the sign of the sum, so
xsum_merge(a, xsum_negate(b)) is the exact difference of two sums,
rounded once.
An accumulator does not count its terms; xsum_mean_value() takes the
count. Special values follow the table in xsum(); an accumulator
remembers whether it has seen NA, NaN, Inf or -Inf.
Accumulator bytes are those of the machine that made them. Every CRAN
platform is little-endian; an accumulator from a big-endian machine
signals a zuexact_accumulator_error.
Examples
acc <- xsum_acc()
acc <- xsum_add(acc, c(1e20, 1))
acc <- xsum_add(acc, -1e20)
xsum_value(acc)
#> [1] 1
# Pieces in any order, merged in any order.
chunks <- split(c(1e100, 1:10, -1e100), rep(1:3, length.out = 12))
accs <- lapply(chunks, xsum_acc)
xsum_value(Reduce(xsum_merge, rev(accs)))
#> [1] 55
# The exact difference of two sums.
a <- xsum_acc(c(0.1, 0.2))
b <- xsum_acc(0.3)
xsum_value(xsum_merge(a, xsum_negate(b)))
#> [1] 2.775558e-17