Re: Experimental approach to reference-type random number generators

2013-09-01 Thread bearophile

See also this idea (and API problem):
http://d.puremagic.com/issues/show_bug.cgi?id=5849

Bye,
bearophile


Re: Experimental approach to reference-type random number generators

2013-09-01 Thread Joseph Rushton Wakeling

On 01/09/13 14:21, bearophile wrote:

See also this idea (and API problem):
http://d.puremagic.com/issues/show_bug.cgi?id=5849


On dice(): I think this is one case of what is in practice a random number 
_distribution_, akin to uniform().


My own instinct is that as much as possible, random number distributions should 
come in two forms -- functions, and ranges.  So, it should be possible to go,


foreach(_; 0 .. 10)
{
writeln(uniform(0.0, 1.0));
writeln(dice(10, 5, 7));
}

but equally well to go,

auto uniDist = uniformDistribution(0.0, 1.0);
auto biasedDice = diceDistribution(10, 5, 7);
foreach(u, d; lockstep(uniDist, biasedDice).take(10))
{
writeln(u);
writeln(d);
}

(I'm sure you can find something to improve in how I've written the second 
example, but you get the idea of how the distributions could behave:-)


Re: Experimental approach to reference-type random number generators

2013-09-01 Thread bearophile

Joseph Rushton Wakeling:


auto uniDist = uniformDistribution(0.0, 1.0);
auto biasedDice = diceDistribution(10, 5, 7);
foreach(u, d; lockstep(uniDist, biasedDice).take(10))
{
writeln(u);
writeln(d);
}

(I'm sure you can find something to improve in how I've written 
the second example, but you get the idea of how the 
distributions could behave:-)


Perhaps it's better for it to only accept a range (despite this 
causes a memory allocation):


diceDistribution([10, 5, 7])

It's usable like this:

[0.3, 0.5, 0.1, 0.1].diceDistribution.map!(i = 
ACGT[i]).take(10).writeln;


diceDistribution() is much more efficient than calling dice() 
many times in map.


In the enhancement request I have also suggested to support an 
optional list of items, so the code becomes:


[0.3, 0.5, 0.1, 0.1].diceDistribution(ACGT).take(10).writeln;

The name diceDistribution is rather long, but at the moment I 
don't know of better names. diceDist is shorter, but less clear.


I usually don't have a continuous distribution to sample (beside 
the most common ones, like the gaussian), so for me a 
diceDistribution is enough for now.


Bye,
bearophile


Re: Experimental approach to reference-type random number generators

2013-09-01 Thread Joseph Rushton Wakeling

On 02/09/13 00:54, bearophile wrote:

diceDistribution() is much more efficient than calling dice() many times in map.


Surely, but you should have both available in any case.  I think there's a good 
argument that for all random number distributions, there should be a function 
_and_ a range implementation, so depending on your needs do either:


auto dist = someDistribution(/* ... parameters ... */, rng);
foreach (x; dist.take(10))
{
writeln(x);
}

... or:

foreach(_; 0 .. 10)
{
auto x = some(/* ... parameters ... */, rng);
writeln(x);
}

Of course in practice sometimes the range might just wrap the function, or the 
function might contain within a static instance of the range.


Re: Experimental approach to reference-type random number generators

2013-08-30 Thread Dmitry Olshansky

24-Aug-2013 22:48, Joseph Rushton Wakeling пишет:

On 24/08/13 20:35, Joseph Rushton Wakeling wrote:

I do have one specific query


Actually, two.  Lines 448-457 of the second codepad paste have this
unittest, with the last line commented out:


 // Check .save works
 foreach (Type; TypeTuple!(MinstdRand0, MinstdRand))
 {
 auto rnd1 = Type(unpredictableSeed);
 auto rnd2 = rnd1.save;
 //assert(rnd1 == rnd2);
 // Enable next test when RNGs are reference types
 version(none) { assert(rnd1 !is rnd2); }
 //assert(rnd1.take(100).array() == rnd2.take(100).array());
 }

If the last assert is uncommented,

 assert(rnd1.take(100).array() == rnd2.take(100).array());

... then running the unittests results in the following error:

 /opt/dmd/include/d2/std/array.d(37): Error: variable
std.array.array!(Take!(RandomGenerator!(LinearCongruentialEngine!(uint,
16807, 0, 2147483647.array.r has scoped destruction, cannot build
closure


Now I'm in the same boat in the midst of wrok of applying new std.uni 
facilities to std.regex. As soon as std.array.array started using 
trusted lambda internally it doesn't accept any range with destructor.


This is simply not acceptable, I'll put a minimized test-case in 
Bugzilla if nobody beats me to it.




This is rather worrying and I'm concerned that this could be a
fundamental flaw in the whole design.  Can anyone advise on how to fix it?


It seems a fundamental bug in closures. They have to work somehow with 
these structs esp as in this case there need not to allocate GC closure 
(no references escapes scope of std.array.array).


--
Dmitry Olshansky


Re: Experimental approach to reference-type random number generators

2013-08-30 Thread Joseph Rushton Wakeling

On 30/08/13 15:32, Dmitry Olshansky wrote:

This is simply not acceptable, I'll put a minimized test-case in Bugzilla if
nobody beats me to it.


Please do, I think you will state the case better than me :-)


It seems a fundamental bug in closures. They have to work somehow with these
structs esp as in this case there need not to allocate GC closure (no references
escapes scope of std.array.array).


Oddly enough that's a relief, because it means that the approach I've outlined 
to RNGs probably isn't fundamentally flawed.




Re: Experimental approach to reference-type random number generators

2013-08-30 Thread monarch_dodra

On Friday, 30 August 2013 at 13:32:31 UTC, Dmitry Olshansky wrote:
Now I'm in the same boat in the midst of wrok of applying new 
std.uni facilities to std.regex. As soon as std.array.array 
started using trusted lambda internally it doesn't accept any 
range with destructor.


Is the bug specific to trusted lambdas? I mean, would simply 
using a named function work around the problem?


If so, then we should simply patch array immediately, while 
waiting for a lambda improvement. Having a broken 
std.array.array is problematic for everyone...


Re: Experimental approach to reference-type random number generators

2013-08-30 Thread Dmitry Olshansky

30-Aug-2013 17:38, Joseph Rushton Wakeling пишет:

On 30/08/13 15:32, Dmitry Olshansky wrote:

This is simply not acceptable, I'll put a minimized test-case in
Bugzilla if
nobody beats me to it.


Please do, I think you will state the case better than me :-)



Not very colorful but with minimal test-case ...
http://d.puremagic.com/issues/show_bug.cgi?id=10928



--
Dmitry Olshansky


Re: Experimental approach to reference-type random number generators

2013-08-30 Thread monarch_dodra

On Friday, 30 August 2013 at 15:18:09 UTC, Dmitry Olshansky wrote:

30-Aug-2013 17:38, Joseph Rushton Wakeling пишет:

On 30/08/13 15:32, Dmitry Olshansky wrote:
This is simply not acceptable, I'll put a minimized test-case 
in

Bugzilla if
nobody beats me to it.


Please do, I think you will state the case better than me :-)



Not very colorful but with minimal test-case ...
http://d.puremagic.com/issues/show_bug.cgi?id=10928


I took a look at your bug report. This works:

//
struct D
{
int x;
~this()
{

}
}

void foo(D bar)
{
void do_it(){ bar.x++; }
do_it();
}

void main()
{
foo(D.init);
}
//

So while lambdas remain broken we can easily work around the 
problem in std.array.array.


If you'd care to file a pull request, I can review it double 
quick.


Re: Experimental approach to reference-type random number generators

2013-08-30 Thread Dmitry Olshansky

30-Aug-2013 19:31, monarch_dodra пишет:

On Friday, 30 August 2013 at 15:18:09 UTC, Dmitry Olshansky wrote:

30-Aug-2013 17:38, Joseph Rushton Wakeling пишет:

On 30/08/13 15:32, Dmitry Olshansky wrote:

This is simply not acceptable, I'll put a minimized test-case in
Bugzilla if
nobody beats me to it.


Please do, I think you will state the case better than me :-)



Not very colorful but with minimal test-case ...
http://d.puremagic.com/issues/show_bug.cgi?id=10928


I took a look at your bug report. This works:

//
struct D
{
 int x;
 ~this()
 {

 }
}

void foo(D bar)
{
 void do_it(){ bar.x++; }
 do_it();
}

void main()
{
 foo(D.init);
}
//

So while lambdas remain broken we can easily work around the problem in
std.array.array.

If you'd care to file a pull request, I can review it double quick.


Got it:
https://github.com/D-Programming-Language/phobos/pull/1535

--
Dmitry Olshansky


Re: Experimental approach to reference-type random number generators

2013-08-24 Thread Joseph Rushton Wakeling

On 24/08/13 20:35, Joseph Rushton Wakeling wrote:

Apart from that, {enj, destr}oy.  Does this look like a valid route to a
next-gen std.random? :-)


I should offer a vote of thanks to monarch_dodra, who referred me to ByLine as 
an example of a reference range (from where I got the idea to use RefCounted), 
and to John Colvin and Artur Skawina who pointed me at some useful info on 
wrapping arbitrary structs.




Re: Experimental approach to reference-type random number generators

2013-08-24 Thread Joseph Rushton Wakeling

On 24/08/13 20:35, Joseph Rushton Wakeling wrote:

I do have one specific query


Actually, two.  Lines 448-457 of the second codepad paste have this unittest, 
with the last line commented out:



// Check .save works
foreach (Type; TypeTuple!(MinstdRand0, MinstdRand))
{
auto rnd1 = Type(unpredictableSeed);
auto rnd2 = rnd1.save;
//assert(rnd1 == rnd2);
// Enable next test when RNGs are reference types
version(none) { assert(rnd1 !is rnd2); }
//assert(rnd1.take(100).array() == rnd2.take(100).array());
}

If the last assert is uncommented,

assert(rnd1.take(100).array() == rnd2.take(100).array());

... then running the unittests results in the following error:

/opt/dmd/include/d2/std/array.d(37): Error: variable 
std.array.array!(Take!(RandomGenerator!(LinearCongruentialEngine!(uint, 16807, 
0, 2147483647.array.r has scoped destruction, cannot build closure


This is rather worrying and I'm concerned that this could be a fundamental flaw 
in the whole design.  Can anyone advise on how to fix it?


Re: Experimental approach to reference-type random number generators

2013-08-24 Thread bearophile

Joseph Rushton Wakeling:

Today I spent some time playing around with an attempt at a 
wrapper for random number generation.  The idea is that random 
number generators should exist as reference types, but without 
needing to be implemented as classes.


I think I'd like std.random2.Random to be a final class.

Bye,
bearophile


Re: Experimental approach to reference-type random number generators

2013-08-24 Thread Joseph Rushton Wakeling

On Saturday, 24 August 2013 at 19:42:18 UTC, bearophile wrote:

I think I'd like std.random2.Random to be a final class.


That was also an approach I considered.  It's easy -- even 
trivial -- to do.  But since Phobos has such a strong 
struct-oriented approach, I thought I'd try something that could 
make that work.


One of the benefits of that approach is that it should be 
possible to drop std.random2 into 99% of code and have it Just 
Work, without downstreams having to change a line of their own 
code.