bug-gsl
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Bug: Laplace RNG formula seems to be incorrect


From: Peter Johansson
Subject: Re: Bug: Laplace RNG formula seems to be incorrect
Date: Sun, 29 Nov 2020 14:09:15 +1000
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Thunderbird/68.10.0

Hi Elias,

I'm just a user of GSL, not maintainer or contributor of this code, but

On 27/11/20 9:18 am, Elias Youssef H Netto wrote:
Dear all,

Thanks for your effort on this awesome package.
It is great to have a fast, free implementation of several useful
algorithms.

Bug Report:

Apparently, the formula for the Laplace RNG in the function gsl_ran_laplace
(file /randist/laplace.c) seems to be wrong.

See details below:
- GSL version: 2.6.2
- OS - Arch on Lenovo desktop
- The compiler used - not relevant
- A description of the bug behavior - see below
- A short program which exercises the bug - see below

My own calculations point to a formula that should be (see the attached
pdf):

$F^{-1}(y) &= u -sgn(y - 0.5) \cdot b \cdot log(1 - sgn(y - 0.5)(2y - 1))$

Which agrees with what Wikipedia presents on its page (
https://en.wikipedia.org/wiki/Laplace_distribution).

The gsl_ran_laplace function is currently implemented as:

```C
double
gsl_ran_laplace (const gsl_rng * r, const double a)
{
   double u;
   do
     {
       u = 2 * gsl_rng_uniform (r) - 1.0;
     }
   while (u == 0.0);

   if (u < 0)
     {
       return a * log (-u);
     }
   else
     {
       return -a * log (u);
     }
}
```
The problem is in the returns inside the if...else statement.
It should be:

```C
double
gsl_ran_laplace (const gsl_rng * r, const double a)
{
   double u;
   do
     {
       u = 2 * gsl_rng_uniform (r) - 1.0;
     }
   while (u == 0.0);

   if (u < 0)
     {
       return a * log (1+u);
     }
   else
     {
       return -a * log (1-u);
     }
}
```


I don't see what the problem is. In the if (u<0.0) clause we have u uniformly distributed on [-1.0, 0.0) and the GSL implementation returns

return a * log (-u);

and you suggest

return a * log (1+u)

that is very similar because -u belongs to (0.0, 1.0] and 1+u belongs to [0.0, 1.0) so only difference is that you include 0.0 instead of 1.0. Returning log(0.0) seems problematic, while including log(1.0) = 0.0 in the possible return value seems perfectly legit.

Cheers,

Peter





reply via email to

[Prev in Thread] Current Thread [Next in Thread]