Hi everyone:

I (finally) ported boost's implementation of the Lagged Fibonacci generator to D. I am creating this thread for review.
https://github.com/D-Programming-Language/phobos/pull/1521

The Lagged Fibonacci generator has interesting properties: For starters, you can generate integers or floats with it. With floats, it generates numbers in a 0 .. 1 range, making it a very nice generator for users that want simple uniform floating point generation in that range.

Another interesting property, is that one can easily specify bit depth and return type. So for example, it is possible to generate ubytes in the [0 .. 128] range (7 bit depth), or floats with a 0.25 step (eg [0, 0.25, 0.5, 0.75]).

In terms of quality, I'm no expert, but supposedly, it's supposed to be good, when properly seeded.

Please review the design, and tell me what you think?

--------

One of the design goals with it, is that I think having a new PRNG is the perfect opportunity to try out the *long* discussed but never introduced PRNG reference-semantics. The LaggedFibonacciGenerator is designed the first of a new familly of generators: Implemented as a pimpl, and without a "save" primitive, it is *impossible* to accidently generate the same sequence twice. It does have "dup", for those that *must* have back tracking, but it is explicit.

Implemented as a pimpl, its pass-by-value is virtually free (MT19937 is an approx. 2KiB).

Seeding *must* be done explicitly, so as to provide the fastest possible iteration. There is no "seed()" function, so there is no default seed *value* either, which will prevent the newbie mistake of "why does random program always output the same random sequence", and promote the use of "seed(unpredictableSeed)".

Other than that, there is not much to say... the idea is to try to stress test this PRNG, and learn as much as possible, before we tackle random2.

--------

I'll copy pasted here the example documentation:

This is example *useage*

///
unittest
{
    //Create a new Generator.
    LaggedFibonacci!ulong lf;

    //It is not yet seeded.
    assert(!lf.isSeeded);

    //Seed with a random seed.
    lf.seed(unpredictableSeed);

    //generate a new array of 10 random numbers.
    ulong[] numbers1 = lf.take(10).array();

    //An existing array can be filled with an algorithm.
    ulong[] numbers2 = new ulong[](10);
    numbers2.fill(lf);

//Because of the reference semantics, and since there is no save,
    //we can rest assured both arrays are different.
    assert(!equal(numbers1, numbers2));
}

These are various flavours of the generator.

///
unittest
{
    //Simple declatation
    LaggedFibonacci!double myFloatingPointGenerator;
    LaggedFibonacci!ulong  myIntegralGenerator;

    //Declaration with specific length
    LaggedFibonacci607!double  mySimpleFloatingPointGenerator;
    LaggedFibonacci44497!ulong myComplexIntegralGenerator;

    //Generate specific type: ubytes in the range [0 .. 256]
    LaggedFibonacci!(ubyte, 8) myByteGenerator;

    //Generate specific type: doubles with a step of 0.125
    LaggedFibonacci!(double, 3) myPieGenerator;

    //Generate with high precision reals
    LaggedFibonacci!(real, 64) myPreciseGenerator;
}

--------

Please (kindly) destroy!

Reply via email to