comp.lang.idl-pvwave archive
Messages from Usenet group comp.lang.idl-pvwave, compiled by Paulo Penteado

Home » Public Forums » archive » Multiplying very high with very low numbers: erfc * exp
Show: Today's Messages :: Show Polls :: Message Navigator
E-mail to friend 
Switch to threaded view of this topic Create a new topic Submit Reply
Multiplying very high with very low numbers: erfc * exp [message #88263] Thu, 03 April 2014 02:35 Go to next message
tho.siegert is currently offline  tho.siegert
Messages: 6
Registered: April 2014
Junior Member
Hello,
for my MCMC fitting program, I need to evaluate functions of the form (Gaussian with a one sided exponential tail towards lower x-values):

f(a,b,c,d) * erfc( g(a,b,c,d) ) * exp( h(a,b,c,d) ) := X * Y * Z = F

where f,g and h are certain functions of the parameters a,b,c and d.

It almost always happens that the numbers of these three factors are like:

F = X * Y * Z = 1e2 * 1e-999 * 1e1000 = 1e3

Which is a big problem since 1e-999 is represented as 0 and 1e1000 is represented as infinity, thus the result being 0, infinity or nan, but definetly not 1e3.
As a work-around, I went to log-space such that:

F = exp( ln(F) ) = exp( ln(X * Y * Z) ) = exp( ln(X) + ln(Y) + ln(Z) ) =
= exp( ln(f(a,b,c,d)) + ln(erfc(g(a,b,c,d))) + ln(exp(h(a,b,c,d))) ) :=
:= exp( Q + W + E )

Q and E are no problem to evaluate since f() is just a rational function and ln(exp(h())) is just h().
However, W = ln(erfc(g())) contains the same problem as above. If g() is far negative from 0, erfc(g()) is just 2 (and not e.g. 2 - 1e-99). If g() is far positive from 0, erfc(g()) is just 0, returning W as -Inf (as erfc(g()) should actually be something like 1e-99).

Now, I looked up several representations of the erfc() function in order to build something like a lnerfc - function. I have chosen the erfcc() function in Numerical recipes, Chapter 6, Special Functions (around page 214) which is also given in Wikipedia at http://en.wikipedia.org/wiki/Error_function#Numerical_approx imation
This approximation has two major advantages:
1) It is represented as proprotional to an exponential function, for which the ln can easily be calculated.
2) The fractional error is "everywhere less than 1.2e-7".

Including all these work-arounds, F = X * Y * Z can be calculated to a good enough precision (for me).

However (again), as you might already think of, it takes a while to calculate F. In a MCMC run, this function has to be evaluated over and over again. If there is more than one such a function present in my data (say N), I need to fit, i.e. evaluate something like:

sum(F_i, i=0..N)

over and over again (typically N = 20..30).

To put it in a nutshell:
I am looking for a speed-up to calculate W = ln(erfc(g(a,b,c,d))).
I know that I can calculate the erfc - function by:
erfc(x) = 1 - sgn(x) * igamma(0.5,x^2)
where igamma is the incomplete gamma-function.
Unfortunately, there is no LNIGAMMA - function in IDL, as for the complete gamma-function (LNGAMMA). As this does not necessarily have to work good then because of the "1 - ".

I hope you understand the problem and are not overwhelmed by this wall of text.
I appreciate any suggestions.

Cheers,
Thomas
Re: Multiplying very high with very low numbers: erfc * exp [message #88264 is a reply to message #88263] Thu, 03 April 2014 06:21 Go to previous messageGo to next message
lecacheux.alain is currently offline  lecacheux.alain
Messages: 325
Registered: January 2008
Senior Member
On Thursday, April 3, 2014 11:35:10 AM UTC+2, tho.s...@gmail.com wrote:
> Hello,
>
> for my MCMC fitting program, I need to evaluate functions of the form (Gaussian with a one sided exponential tail towards lower x-values):
>
>
>
> f(a,b,c,d) * erfc( g(a,b,c,d) ) * exp( h(a,b,c,d) ) := X * Y * Z = F
>
>
>
> where f,g and h are certain functions of the parameters a,b,c and d.
>
>
>
> It almost always happens that the numbers of these three factors are like:
>
>
>
> F = X * Y * Z = 1e2 * 1e-999 * 1e1000 = 1e3
>
>
>
> Which is a big problem since 1e-999 is represented as 0 and 1e1000 is represented as infinity, thus the result being 0, infinity or nan, but definetly not 1e3.
>
> As a work-around, I went to log-space such that:
>
>
>
> F = exp( ln(F) ) = exp( ln(X * Y * Z) ) = exp( ln(X) + ln(Y) + ln(Z) ) =
>
> = exp( ln(f(a,b,c,d)) + ln(erfc(g(a,b,c,d))) + ln(exp(h(a,b,c,d))) ) :=
>
> := exp( Q + W + E )
>
>
>
> Q and E are no problem to evaluate since f() is just a rational function and ln(exp(h())) is just h().
>
> However, W = ln(erfc(g())) contains the same problem as above. If g() is far negative from 0, erfc(g()) is just 2 (and not e.g. 2 - 1e-99). If g() is far positive from 0, erfc(g()) is just 0, returning W as -Inf (as erfc(g()) should actually be something like 1e-99).
>
>
>
> Now, I looked up several representations of the erfc() function in order to build something like a lnerfc - function. I have chosen the erfcc() function in Numerical recipes, Chapter 6, Special Functions (around page 214) which is also given in Wikipedia at http://en.wikipedia.org/wiki/Error_function#Numerical_approx imation
>
> This approximation has two major advantages:
>
> 1) It is represented as proprotional to an exponential function, for which the ln can easily be calculated.
>
> 2) The fractional error is "everywhere less than 1.2e-7".
>
>
>
> Including all these work-arounds, F = X * Y * Z can be calculated to a good enough precision (for me).
>
>
>
> However (again), as you might already think of, it takes a while to calculate F. In a MCMC run, this function has to be evaluated over and over again. If there is more than one such a function present in my data (say N), I need to fit, i.e. evaluate something like:
>
>
>
> sum(F_i, i=0..N)
>
>
>
> over and over again (typically N = 20..30).
>
>
>
> To put it in a nutshell:
>
> I am looking for a speed-up to calculate W = ln(erfc(g(a,b,c,d))).
>
> I know that I can calculate the erfc - function by:
>
> erfc(x) = 1 - sgn(x) * igamma(0.5,x^2)
>
> where igamma is the incomplete gamma-function.
>
> Unfortunately, there is no LNIGAMMA - function in IDL, as for the complete gamma-function (LNGAMMA). As this does not necessarily have to work good then because of the "1 - ".
>
>
>
> I hope you understand the problem and are not overwhelmed by this wall of text.
>
> I appreciate any suggestions.
>
>
>
> Cheers,
>
> Thomas

I am afraid that IDL will not be able to help you without some reformulation of your problem.
In order to avoid underflow and overflow when computing each of your Y and Z functions, you have to find a derived or approximated expression for their product, which indeed is finite and of order about 10.
You might for instance consider Rational Chebyshev approximations of X*Y, which are often used for computing the "erfcx" function (i.e. exp(x^2)*erfc(x)), whose shape is not far from the one you are dealing with.
Hoping this can help you.
alx.
Re: Multiplying very high with very low numbers: erfc * exp [message #88352 is a reply to message #88264] Wed, 16 April 2014 05:09 Go to previous message
tho.siegert is currently offline  tho.siegert
Messages: 6
Registered: April 2014
Junior Member
On Thursday, April 3, 2014 3:21:31 PM UTC+2, alx wrote:
> On Thursday, April 3, 2014 11:35:10 AM UTC+2, tho.s...@gmail.com wrote:
>
>> Hello,
>
>>
>
>> for my MCMC fitting program, I need to evaluate functions of the form (Gaussian with a one sided exponential tail towards lower x-values):
>
>>
>
>>
>
>>
>
>> f(a,b,c,d) * erfc( g(a,b,c,d) ) * exp( h(a,b,c,d) ) := X * Y * Z = F
>
>>
>
>>
>
>>
>
>> where f,g and h are certain functions of the parameters a,b,c and d.
>
>>
>
>>
>
>>
>
>> It almost always happens that the numbers of these three factors are like:
>
>>
>
>>
>
>>
>
>> F = X * Y * Z = 1e2 * 1e-999 * 1e1000 = 1e3
>
>>
>
>>
>
>>
>
>> Which is a big problem since 1e-999 is represented as 0 and 1e1000 is represented as infinity, thus the result being 0, infinity or nan, but definetly not 1e3.
>
>>
>
>> As a work-around, I went to log-space such that:
>
>>
>
>>
>
>>
>
>> F = exp( ln(F) ) = exp( ln(X * Y * Z) ) = exp( ln(X) + ln(Y) + ln(Z) ) =
>
>>
>
>> = exp( ln(f(a,b,c,d)) + ln(erfc(g(a,b,c,d))) + ln(exp(h(a,b,c,d))) ) :=
>
>>
>
>> := exp( Q + W + E )
>
>>
>
>>
>
>>
>
>> Q and E are no problem to evaluate since f() is just a rational function and ln(exp(h())) is just h().
>
>>
>
>> However, W = ln(erfc(g())) contains the same problem as above. If g() is far negative from 0, erfc(g()) is just 2 (and not e.g. 2 - 1e-99). If g() is far positive from 0, erfc(g()) is just 0, returning W as -Inf (as erfc(g()) should actually be something like 1e-99).
>
>>
>
>>
>
>>
>
>> Now, I looked up several representations of the erfc() function in order to build something like a lnerfc - function. I have chosen the erfcc() function in Numerical recipes, Chapter 6, Special Functions (around page 214) which is also given in Wikipedia at http://en.wikipedia.org/wiki/Error_function#Numerical_approx imation
>
>>
>
>> This approximation has two major advantages:
>
>>
>
>> 1) It is represented as proprotional to an exponential function, for which the ln can easily be calculated.
>
>>
>
>> 2) The fractional error is "everywhere less than 1.2e-7".
>
>>
>
>>
>
>>
>
>> Including all these work-arounds, F = X * Y * Z can be calculated to a good enough precision (for me).
>
>>
>
>>
>
>>
>
>> However (again), as you might already think of, it takes a while to calculate F. In a MCMC run, this function has to be evaluated over and over again. If there is more than one such a function present in my data (say N), I need to fit, i.e. evaluate something like:
>
>>
>
>>
>
>>
>
>> sum(F_i, i=0..N)
>
>>
>
>>
>
>>
>
>> over and over again (typically N = 20..30).
>
>>
>
>>
>
>>
>
>> To put it in a nutshell:
>
>>
>
>> I am looking for a speed-up to calculate W = ln(erfc(g(a,b,c,d))).
>
>>
>
>> I know that I can calculate the erfc - function by:
>
>>
>
>> erfc(x) = 1 - sgn(x) * igamma(0.5,x^2)
>
>>
>
>> where igamma is the incomplete gamma-function.
>
>>
>
>> Unfortunately, there is no LNIGAMMA - function in IDL, as for the complete gamma-function (LNGAMMA). As this does not necessarily have to work good then because of the "1 - ".
>
>>
>
>>
>
>>
>
>> I hope you understand the problem and are not overwhelmed by this wall of text.
>
>>
>
>> I appreciate any suggestions.
>
>>
>
>>
>
>>
>
>> Cheers,
>
>>
>
>> Thomas
>
>
>
> I am afraid that IDL will not be able to help you without some reformulation of your problem.
>
> In order to avoid underflow and overflow when computing each of your Y and Z functions, you have to find a derived or approximated expression for their product, which indeed is finite and of order about 10.
>
> You might for instance consider Rational Chebyshev approximations of X*Y, which are often used for computing the "erfcx" function (i.e. exp(x^2)*erfc(x)), whose shape is not far from the one you are dealing with.
>
> Hoping this can help you.
>
> alx.



On Thursday, April 3, 2014 3:21:31 PM UTC+2, alx wrote:
> On Thursday, April 3, 2014 11:35:10 AM UTC+2, tho.s...@gmail.com wrote:
>
>> Hello,
>
>>
>
>> for my MCMC fitting program, I need to evaluate functions of the form (Gaussian with a one sided exponential tail towards lower x-values):
>
>>
>
>>
>
>>
>
>> f(a,b,c,d) * erfc( g(a,b,c,d) ) * exp( h(a,b,c,d) ) := X * Y * Z = F
>
>>
>
>>
>
>>
>
>> where f,g and h are certain functions of the parameters a,b,c and d.
>
>>
>
>>
>
>>
>
>> It almost always happens that the numbers of these three factors are like:
>
>>
>
>>
>
>>
>
>> F = X * Y * Z = 1e2 * 1e-999 * 1e1000 = 1e3
>
>>
>
>>
>
>>
>
>> Which is a big problem since 1e-999 is represented as 0 and 1e1000 is represented as infinity, thus the result being 0, infinity or nan, but definetly not 1e3.
>
>>
>
>> As a work-around, I went to log-space such that:
>
>>
>
>>
>
>>
>
>> F = exp( ln(F) ) = exp( ln(X * Y * Z) ) = exp( ln(X) + ln(Y) + ln(Z) ) =
>
>>
>
>> = exp( ln(f(a,b,c,d)) + ln(erfc(g(a,b,c,d))) + ln(exp(h(a,b,c,d))) ) :=
>
>>
>
>> := exp( Q + W + E )
>
>>
>
>>
>
>>
>
>> Q and E are no problem to evaluate since f() is just a rational function and ln(exp(h())) is just h().
>
>>
>
>> However, W = ln(erfc(g())) contains the same problem as above. If g() is far negative from 0, erfc(g()) is just 2 (and not e.g. 2 - 1e-99). If g() is far positive from 0, erfc(g()) is just 0, returning W as -Inf (as erfc(g()) should actually be something like 1e-99).
>
>>
>
>>
>
>>
>
>> Now, I looked up several representations of the erfc() function in order to build something like a lnerfc - function. I have chosen the erfcc() function in Numerical recipes, Chapter 6, Special Functions (around page 214) which is also given in Wikipedia at http://en.wikipedia.org/wiki/Error_function#Numerical_approx imation
>
>>
>
>> This approximation has two major advantages:
>
>>
>
>> 1) It is represented as proprotional to an exponential function, for which the ln can easily be calculated.
>
>>
>
>> 2) The fractional error is "everywhere less than 1.2e-7".
>
>>
>
>>
>
>>
>
>> Including all these work-arounds, F = X * Y * Z can be calculated to a good enough precision (for me).
>
>>
>
>>
>
>>
>
>> However (again), as you might already think of, it takes a while to calculate F. In a MCMC run, this function has to be evaluated over and over again. If there is more than one such a function present in my data (say N), I need to fit, i.e. evaluate something like:
>
>>
>
>>
>
>>
>
>> sum(F_i, i=0..N)
>
>>
>
>>
>
>>
>
>> over and over again (typically N = 20..30).
>
>>
>
>>
>
>>
>
>> To put it in a nutshell:
>
>>
>
>> I am looking for a speed-up to calculate W = ln(erfc(g(a,b,c,d))).
>
>>
>
>> I know that I can calculate the erfc - function by:
>
>>
>
>> erfc(x) = 1 - sgn(x) * igamma(0.5,x^2)
>
>>
>
>> where igamma is the incomplete gamma-function.
>
>>
>
>> Unfortunately, there is no LNIGAMMA - function in IDL, as for the complete gamma-function (LNGAMMA). As this does not necessarily have to work good then because of the "1 - ".
>
>>
>
>>
>
>>
>
>> I hope you understand the problem and are not overwhelmed by this wall of text.
>
>>
>
>> I appreciate any suggestions.
>
>>
>
>>
>
>>
>
>> Cheers,
>
>>
>
>> Thomas
>
>
>
> I am afraid that IDL will not be able to help you without some reformulation of your problem.
>
> In order to avoid underflow and overflow when computing each of your Y and Z functions, you have to find a derived or approximated expression for their product, which indeed is finite and of order about 10.
>
> You might for instance consider Rational Chebyshev approximations of X*Y, which are often used for computing the "erfcx" function (i.e. exp(x^2)*erfc(x)), whose shape is not far from the one you are dealing with.
>
> Hoping this can help you.
>
> alx.




Okay, since I already actually had a lnerfc function, but was too silly to make it work properly, i post my solution:


function lnerfc, x, y

a = [-1.26551223d, 1.00002368d, 0.37409196d, 0.09678418d, -0.18628806d, 0.27886807d, -1.13520398d, 1.48851587d, -0.82215223d, 0.17087277d]

t = 1d / (1d + 0.5d * abs(x))

tau = t * exp( -x*x + (a[0] + t * (a[1] + t * (a[2] + t * (a[3] + t * (a[4] + t * (a[5] + t * (a[6] + t * (a[7] + t * (a[8] + t * a[9]))))))))))

y = alog(t) + ( -x*x + (a[0] + t * (a[1] + t * (a[2] + t * (a[3] + t * (a[4] + t * (a[5] + t * (a[6] + t * (a[7] + t * (a[8] + t * a[9]))))))))))

lt0 = where(x lt 0d,/null)

y[lt0] = y[lt0] + alog(2d / tau - 1d)

return, y

end



It is again taken from Numerical recipes, Chapter 6.2, Special Functions, just translated to logarithm space. This is indeed based on Chebyshev fitting. Thanks alx!

Regards,
Thomas
  Switch to threaded view of this topic Create a new topic Submit Reply
Previous Topic: How to control the lat-lon axis when using Google Static map as background?
Next Topic: SVDC procedure

-=] Back to Top [=-
[ Syndicate this forum (XML) ] [ RSS ] [ PDF ]

Current Time: Wed Oct 08 15:38:04 PDT 2025

Total time taken to generate the page: 0.00787 seconds