GithubHelp home page GithubHelp logo

Comments (12)

simonbyrne avatar simonbyrne commented on July 19, 2024

Not imminently: you could use

SpecialFunctions.erfcx(x::BigFloat) = exp(x^2)*erfc(x)

but this only works up to 10^10 or so.

from specialfunctions.jl.

simonbyrne avatar simonbyrne commented on July 19, 2024

By the way, it is in the MPFR TODO list.

We could easily roll our own though: use the naive approach below some threshold, and DLMF 7.6.2 above it (which is what MPFR itself uses anyway, see http://www.mpfr.org/algorithms.pdf).

from specialfunctions.jl.

stevengj avatar stevengj commented on July 19, 2024

For large arguments, wouldn't the continued fraction expansion converge faster?

from specialfunctions.jl.

stevengj avatar stevengj commented on July 19, 2024

Oh, I see, MPFR uses a slightly different series than the DLMF 7.6.2 that you linked (which was for erf) — for erfcx(x), you get a series in x^{-2k}, which indeed should converge fast for large x.

from specialfunctions.jl.

simonbyrne avatar simonbyrne commented on July 19, 2024

Ah, yes, you're right, I wasn't looking too closely, it is actually DLMF 7.12.1

from specialfunctions.jl.

kalmarek avatar kalmarek commented on July 19, 2024

I am not sure I did that correctly, as there are problems with convergence (sometimes)

function lpochhammer(x::Number,n::Integer)
    sum([log(x+i) for i in 0:n-1])
end

function SpecialFunctions.erfcx(x::T, tol=eps(x)) where T<:Real
    s = T(0)
    coeff = log(1/√T(π))
    half = T(1)/2
    err = T(1)
    
    m = 0
    while abs(err) >= tol
        c = (-T(1))^m * exp(coeff + lpochhammer(half, m) - log(x)*(2m+1))
        if abs(c) > err
            warn("Loosing precision at iteration $m !")
            break
        end
        s += c
        m += 1
        err = abs(c)
    end
    @show err, m
    return s
end

By the way I realized that I need high precision erfcx for arguments close to zero, where the series does not converge ;-)

from specialfunctions.jl.

simonbyrne avatar simonbyrne commented on July 19, 2024

It is an asymptotic series, so it never actually converges (so higher precision won't actually help). Therefore it can only really be used above some threshold, which is fine because the naive approach of exp(x^2)*erfc(x) works fine for smallish numbers.

from specialfunctions.jl.

simonbyrne avatar simonbyrne commented on July 19, 2024

For the record, I would do something like

function SpecialFunctions.erfcx(x::BigFloat)
    if x < 1e7 # this probably needs to be chosen better
        return exp(x^2)*erfc(x)
    else
        ϵ = eps(BigFloat)/4
        v = 1/(2*x*x)
        k = 1
        s = w = -k*v
        while abs(w) > ϵ
            k += 2
            w *= -k*v
            s += w
        end
        return (1+s)/(x*sqrt(big(pi)))
    end
end

from specialfunctions.jl.

kalmarek avatar kalmarek commented on July 19, 2024

yeah, that was just a naive version to see if using it changes anything in my computations (it doesn't)
Your version is pro, though ;-)

I vaguely remember asymptotic series popping up in analytic number theory class, good to recall they exist!

from specialfunctions.jl.

stevengj avatar stevengj commented on July 19, 2024

@simonbyrne, you can't use a fixed threshold like 1e7 here because BigFloat is arbitrary precision. For any fixed x, there will be some accuracy that is impossible to achieve with the asymptotic series. So, the threshold x to use the asymptotic series has to depend on the precision.

(The continued-fraction expansion doesn't have this problem, because it actually converges. But it is more expensive to compute.)

from specialfunctions.jl.

simonbyrne avatar simonbyrne commented on July 19, 2024

Yes, I know. In fact, the main reason I didn't turn it into a PR is that I haven't had time to work through to figure out what a good cutoff would be!

from specialfunctions.jl.

simonbyrne avatar simonbyrne commented on July 19, 2024

Actually, I think we could just choose 2^30, based on the rationale that any higher numbers would result in the naive version overflowing.

By my calculation, this means that the series would start to diverge at the 2^60th term:

  1. if you're iterating through 2^60 BigFloats, you've got bigger problems to worry about
  2. it should be accurate to approximately 6.87e19 bits, which implies a significand of O(1 exabyte).

from specialfunctions.jl.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.