www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.bugs - [Issue 14001] New: Optionally nogc std.random.randomCover

https://issues.dlang.org/show_bug.cgi?id=14001

          Issue ID: 14001
           Summary: Optionally  nogc std.random.randomCover
           Product: D
           Version: D2
          Hardware: All
                OS: All
            Status: NEW
          Severity: enhancement
          Priority: P1
         Component: Phobos
          Assignee: nobody puremagic.com
          Reporter: bearophile_hugs eml.cc

This is part of randomCover code:


struct RandomCover(Range, UniformRNG = void)
    if (isRandomAccessRange!Range && (isUniformRNG!UniformRNG || is(UniformRNG
== void)))
{
    private Range _input;
    private bool[] _chosen;
    private size_t _current;
    private size_t _alreadyChosen = 0;

    static if (is(UniformRNG == void))
    {
        this(Range input)
        {
            _input = input;
            _chosen.length = _input.length;
            if (_chosen.length == 0)
            {
                _alreadyChosen = 1;
            }
        }
    }
...

auto randomCover(Range, UniformRNG)(Range r, auto ref UniformRNG rng)
    if (isRandomAccessRange!Range && isUniformRNG!UniformRNG)
{
    return RandomCover!(Range, UniformRNG)(r, rng);
}

auto randomCover(Range)(Range r)
    if (isRandomAccessRange!Range)
{
    return RandomCover!(Range, void)(r);
}


Currently randomCover can't be  nogc because of the random generator, but also
because of that allocation of _chosen inside the struct constructor. To solve
this problem I suggest to remove the allocation of _chosen from the struct
constructor and move it inside the helper functions. And then add two more
overloads for the helper functions, something like this:


auto randomCover(Range, UniformRNG)(Range r, auto ref UniformRNG rng)
    if (isRandomAccessRange!Range && isUniformRNG!UniformRNG)
{
    return RandomCover!(Range, UniformRNG)(r, rng, new bool[r.length]);
}

auto randomCover(Range)(Range r)
    if (isRandomAccessRange!Range)
{
    return RandomCover!(Range, void)(r, new bool[r.length]);
}

auto randomCover(Range, UniformRNG)(Range r, auto ref UniformRNG rng, bool[]
buf)  nogc
    if (isRandomAccessRange!Range && isUniformRNG!UniformRNG)
{
    if (buf.length < r.length) {
        // Is this correct in presence of chaining?
        static immutable err = new Error("Not sufficient 'buf' size");
        throw err;
    }
    return RandomCover!(Range, UniformRNG)(r, rng, buf[0 .. r.length]);
}

auto randomCover(Range)(Range r, bool[] buf)  nogc
    if (isRandomAccessRange!Range)
{
    if (buf.length < r.length) {
        static immutable err = new Error("Not sufficient 'buf' size");
        throw err;
    }
    return RandomCover!(Range, void)(r, buf[0 .. r.length]);
}


The two more overloads take an extra "buf" input, that will be used by the
RandomCover. If the buf is not long enough, an error is raised.

Optionally randomCover could take a std.bitmanip.BitArray instead.

--
Jan 18 2015