[FFmpeg-devel] [PATCH] Box-Muller gaussian generator

Stefano Sabatini stefano.sabatini-lala
Fri Dec 11 13:11:29 CET 2009


On date Friday 2009-12-11 01:49:21 +0100, Michael Niedermayer encoded:
> On Fri, Dec 11, 2009 at 01:40:08AM +0100, Michael Niedermayer wrote:
> > On Sun, Dec 06, 2009 at 11:13:37PM +0100, Stefano Sabatini wrote:
> > > On date Sunday 2009-12-06 19:40:20 +0100, Vitor Sessak encoded:
> > > > Stefano Sabatini wrote:
> > > >> Hi,
> > > >>
> > > >> I'm going to use this for a noise filter, I believe this could be
> > > >> useful in other part of libav* though.
> > > >
> > > >> +double av_bmg_get(AVBMG *bmg)
> > > >> +{
> > > >> +    double x1, x2, w, y;
> > > >> +    AVLFG *lfg = &bmg->lfg;
> > > >> +
> > > >> +    do {
> > > >> +        x1 = 2.0 * ranf(lfg) - 1.0;
> > > >> +        x2 = 2.0 * ranf(lfg) - 1.0;
> > > >> +        w = x1*x1 + x2*x2;
> > > >> +    } while (w >= 1.0);
> > > >> +
> > > >> +    w = sqrt((-2.0 * log(w)) / w);
> > > >> +    y = x2 * w;
> > > >> +
> > > >> +    return bmg->mean + y * bmg->std_dev;
> > > >> +}
> > > >
> > > > This generates two numbers to use only one. Isn't it faster to store the  
> > > > second number for the next call or have a function to fill a buffer of  
> > > > random numbers?
> > > 
> > > Implemented the first idea.
> > 
> > void av_bmg_get(AVLFG *lfg, double out[2]);
> >     double x1, x2, w;
> > 
> >     do {
> >         x1 = 2.0/UINT_MAX*av_lfg_get(lfg) - 1.0;
> >         x2 = 2.0/UINT_MAX*av_lfg_get(lfg) - 1.0;
> >         w = x1*x1 + x2*x2;
> >     } while (w >= 1.0);
> >
> >     w = sqrt((-2.0 * log(w)) / w);

If av_lfg_get() returns UINT_MAX/2 two times in a row then we have:
x1 = x2 = w = 0
while this isn't very likely (I don't even know if av_lfg() can return
two times in a row the same number) we'll have a division-by-zero.
Is this the bug you mentioned in your first mail?
Also how it is fixed in this second variant?

> >     out[0] = x1 * w;
> >     out[1] = x2 * w;
> > }
> > 
> > comments welcome, if none ill commit above
> > 
> > libavutil is supposed to be clean and i wont tolerate it being filled up with
> 
> hmm, the word tolerate sounds a little harsh, i guess i could have said this
> more diplomatically but the point stands we dont need a new file and whole
> struct+API for something that could be a single 8 line function

I appreciate your wish to keep simple the API, well this slightly
complicates its usage which becomes:

int main(void)
{
    int i;
    AVLFG lfg;
    double mean   = 1000;
    double stddev = 53;

    av_lfg_init(&lfg, 42);

    for (i = 0; i < 1000; i+=2) {
        double bmg_out[2];
        av_bmg_get(&lfg, bmg_out);
        printf("%f\n%f\n",
               bmg_out[0] * stddev + mean,
               bmg_out[1] * stddev + mean);
    }

    return 0;
}

but I can easily live with it and maybe I even prefer your variant.

Regards.
-- 
FFmpeg = Fundamental and Forgiving Mastering Portable EnGine



More information about the ffmpeg-devel mailing list