Description
I was reading R's implementation of log1pexp
and they include one additional branch (see https://cran.r-project.org/web/packages/Rmpfr/vignettes/log1mexp-note.pdf, equation 10).
Currently StatsFuns does this:
Whereas including the additional branch it would be:
log1pexp_v2(x::AbstractFloat) = x ≤ -37. ? exp(x) : x ≤ 18. ? log1p(exp(x)) : x ≤ 33.3 ? x + exp(-x) : x
Apparently including the x < -37.
check reduces the function's computation time by 25% (because it saves the call to log1p
I guess). But I am no expert doing this kind of performance tests so please can someone else more knowledgeable check this? Here is the test I did:
using BenchmarkTools
@btime for x = -100. : 1. : 100., _ = 1 : 100
log1pexp_v2(x)
end # 310.471 μs (0 allocations: 0 bytes)
@btime for x = -100. : 1. : 100., _ = 1 : 100
log1pexp(x)
end # 423.671 μs (0 allocations: 0 bytes)
Both log1pexp_v2
and log1pexp
give numerically identical results.
If this is worth it I can prepare a PR.
Update: Actually it seems much of the time is due to the oftype(exp(-x), x)
bit in the final branch. I think specializing on AbstractFloat
would take care of that. Even after this change the x ≤ -37.
check is faster.