Unlimited learning, half price | 50% off

Last chance! 50% off unlimited learning

Sale ends in


DPQ (version 0.4-1)

lssum: Compute Logarithm of a Sum with Signed Large Summands

Description

Properly compute log(x1++xn) for given log absolute values lxabs = log(|x1|),..,log(|xn|) and corresponding signs signs = sign(x1),..,sign(xn). Here, xi is of arbitrary sign.

Notably this works in many cases where the direct sum would have summands that had overflown to +Inf or underflown to -Inf.

This is a (simpler, vector-only) version of copula:::lssum() (CRAN package copula).

Note that the precision is often not the problem for the direct summation, as R's sum() internally uses "long double" precision on most platforms.

Usage

lssum(lxabs, signs, l.off = max(lxabs), strict = TRUE)

Arguments

lxabs

n-vector of values log(|x1|),,log(|xn|).

signs

corresponding signs sign(x1),,sign(xn).

l.off

the offset to substract and re-add; ideally in the order of max(.).

strict

logical indicating if the function should stop on some negative sums.

Value

log(x1+..+xn)==log(sum(x))=log(sum(sign(x)|x|))==log(sum(sign(x)exp(log(|x|))))==log(exp(log(x0))sum(signsexp(log(|x|)log(x0))))==log(x0)+log(sum(signsexp(log(|x|)log(x0))))==l.off+log(sum(signsexp(lxabsl.off)))

See Also

lsum() which computes an exponential sum in log scale with out signs.

Examples

Run this code
# NOT RUN {
rSamp <- function(n, lmean, lsd = 1/4, roundN = 16) {
  lax <- sort((1+1e-14*rnorm(n))*round(roundN*rnorm(n, m = lmean, sd = lsd))/roundN)
  sx <- rep_len(c(-1,1), n)
  list(lax=lax, sx=sx, x = sx*exp(lax))
}

set.seed(101)
L1 <- rSamp(1000, lmean = 700) # here, lssum() is not needed (no under-/overflow)
summary(as.data.frame(L1))
ax <- exp(lax <- L1$lax)
hist(lax); rug(lax)
hist( ax); rug( ax)
sx <- L1$sx
table(sx)
(lsSimple <- log(sum(L1$x)))           # 700.0373
(lsS <- lssum(lxabs = lax, signs = sx))# ditto
lsS - lsSimple # even exactly zero (in 64b Fedora 30 Linux which has nice 'long double')
stopifnot(all.equal(700.037327351478, lsS, tol=1e-14), all.equal(lsS, lsSimple))

L2 <- within(L1, { lax <- lax + 10; x <- sx*exp(lax) }) ; summary(L2$x) # some -Inf, +Inf
(lsSimpl2 <- log(sum(L2$ x)))                    # NaN
(lsS2 <- lssum(lxabs = L2$ lax, signs = L2$ sx)) # 710.0373
stopifnot(all.equal(lsS2, lsS + 10, tol = 1e-14))
# }

Run the code above in your browser using DataLab