Numerically stable derivative of logerf without catastrophic cancellation

user22
Sun, 15 Jan 2023 13:16:53 +0000
Numerics

I need to evaluate the derivative of a logerf function fun with respect to x within the widest possible range of x. At the moment, the derivative is calculated through the function dfun.

using LogExpFunctions
using FiniteDifferences
using SpecialFunctions
using KahanSummation

function ksum(x...)
    return sum_kbn(x)
end

function fun(x,a,b)
    return logerf(a+x,b+x)
end

function dfun(x,a,b)

    ldeno = fun(x,a,b)
    v1 = -(b+x)^2
    v2 = -(a+x)^2

    if (v1 < v2)
        t = ksum(-ldeno,v2,log(2/(sqrt(pi))),log1p(-exp(v1-v2)) )
        return -exp(t)
    else
        t = ksum(-ldeno,v1,log(2/(sqrt(pi))),log1p(-exp(v2-v1)) )
        return exp(t)
    end

end

x0 = -3*10.0^4
a = -3000.0
b = 3000.0

d1 = central_fdm(5,1)(t->fun(t,a,b),x0)
d2 = dfun(x0,a,b)

d1-d2

With the current values of a and b, the finite-difference approximation and the handcrafted derivative function agree well up to |x| < 10.0^4. For higher values of x, the derivatives begin to differ, until around x ≈ 10.0^9, the handcrafted derivative function starts to return a constant value of -1.1284 or so.
Meanwhile, the numerical precision of logerf implementation allows to evaluate fun up to 10^19 without double point precision under- or overflows.

Can the derivative of the presented logerf function be evaluated more precisely without using tricks like BigFloat? I already use logarithm transform trick in the evaluation.

5 posts - 3 participants