Thread overview | |||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
April 23, 2012 Range of random numbers | ||||
---|---|---|---|---|
| ||||
For some reason this got lost in the ether, so I'm resending. Related to my earlier question on passing a function -- I was wondering if there's a trivial way of generating a lazily-evaluated range of random numbers according to a given distribution and parameters. I wrote up the code below to generate a range of uniformly-distributed numbers, but am not sure how to generalize it for arbitrary distribution and/or parameters, and I'm also not sure that I'm overcomplicating what might be more easily achieved with existing D functionality. The larger goal here is that I want some way to pass an _arbitrary_ number source (may be deterministic, may be stochastic) to a function. A range seemed a good way to do that (after all, in the deterministic case I can just pass an array, no?). ... but I couldn't work out how to generalize the stochastic case beyond what's shown here. /////////////////////////////////////////////////////////////////////////////// import std.array, std.random, std.range, std.stdio; struct UniformRange(T1, T2) { T1 _lower; T2 _upper; @property enum bool empty = false; this(T1 a, T2 b) { _lower = a; _upper = b; } @property auto ref front() { assert(!empty); return uniform(_lower, _upper); } void popFront() { } } auto uniformRange(T1, T2)(T1 a, T2 b) { return UniformRange!(T1, T2)(a, b); } auto uniformRange(T1, T2)(size_t n, T1 a, T2 b) { return take(UniformRange!(T1, T2)(a, b), n); } void main() { auto ur = uniformRange!(double, double)(5, 10.0, 20.0); double[] x = array( take(uniformRange(1.0, 2.0), 5) ); double[] y = array(x); foreach(r; ur) writeln(r); writeln; foreach(r; ur) writeln(r); writeln; foreach(r; x) writeln(r); writeln; foreach(r; y) writeln(r); writeln; } |
April 23, 2012 Re: Range of random numbers | ||||
---|---|---|---|---|
| ||||
Posted in reply to Joseph Rushton Wakeling | Joseph Rushton Wakeling: > struct UniformRange(T1, T2) > { > T1 _lower; > T2 _upper; > > @property enum bool empty = false; > > this(T1 a, T2 b) > { > _lower = a; > _upper = b; > } > > @property auto ref front() > { > assert(!empty); > return uniform(_lower, _upper); > } > > void popFront() > { > } > } What about (untested): auto uniformRange(T1 lower, T2 upper) { return count().map!(_ => uniform(lower, upper))(); } Where count() is just: http://d.puremagic.com/issues/show_bug.cgi?id=7839 In the meantime cycle([0]) is acceptable but slower (untested): return cycle([0]).map!(_ => uniform(lower, upper))(); Bye, bearophile |
April 23, 2012 Re: Range of random numbers | ||||
---|---|---|---|---|
| ||||
Posted in reply to bearophile | On 23.04.2012 17:52, bearophile wrote: > Joseph Rushton Wakeling: > >> struct UniformRange(T1, T2) >> { >> T1 _lower; >> T2 _upper; >> >> @property enum bool empty = false; >> >> this(T1 a, T2 b) >> { >> _lower = a; >> _upper = b; >> } >> >> @property auto ref front() >> { >> assert(!empty); >> return uniform(_lower, _upper); >> } >> >> void popFront() >> { >> } >> } > > What about (untested): > > auto uniformRange(T1 lower, T2 upper) { > return count().map!(_ => uniform(lower, upper))(); > } > > Where count() is just: > http://d.puremagic.com/issues/show_bug.cgi?id=7839 > What's wrong with: http://dlang.org/phobos/std_algorithm.html#count > In the meantime cycle([0]) is acceptable but slower (untested): > > return cycle([0]).map!(_ => uniform(lower, upper))(); > > Bye, > bearophile -- Dmitry Olshansky |
April 23, 2012 Re: Range of random numbers | ||||
---|---|---|---|---|
| ||||
Posted in reply to bearophile | > What about (untested):
>
> auto uniformRange(T1 lower, T2 upper) {
> return count().map!(_ => uniform(lower, upper))();
> }
>
> Where count() is just:
> http://d.puremagic.com/issues/show_bug.cgi?id=7839
>
> In the meantime cycle([0]) is acceptable but slower (untested):
>
> return cycle([0]).map!(_ => uniform(lower, upper))();
He could also use repeat in this case:
return repeat(0).map!(_ => uniform(lower, upper))();
repeat(0) returns the same sequence as cycle([0]) and is as fast
as it gets, since popFront does nothing and empty is an enum.
|
April 23, 2012 Re: Range of random numbers | ||||
---|---|---|---|---|
| ||||
Posted in reply to jerro | jerro: > return repeat(0).map!(_ => uniform(lower, upper))(); > > repeat(0) returns the same sequence as cycle([0]) and is as fast > as it gets, since popFront does nothing and empty is an enum. Good idea. ------------------- Dmitry Olshansky: > What's wrong with: http://dlang.org/phobos/std_algorithm.html#count It's for a different purpose. So the count() I was proposing will need a different name. Bye, bearophile |
April 23, 2012 Re: Range of random numbers | ||||
---|---|---|---|---|
| ||||
Posted in reply to bearophile | On 23/04/12 18:56, bearophile wrote:
> jerro:
>
>> return repeat(0).map!(_ => uniform(lower, upper))();
>>
>> repeat(0) returns the same sequence as cycle([0]) and is as fast
>> as it gets, since popFront does nothing and empty is an enum.
>
> Good idea.
Yes, this works nicely. Thanks very much!
|
April 23, 2012 Re: Range of random numbers | ||||
---|---|---|---|---|
| ||||
On 23/04/12 19:46, Joseph Rushton Wakeling wrote:
> On 23/04/12 18:56, bearophile wrote:
>> jerro:
>>
>>> return repeat(0).map!(_ => uniform(lower, upper))();
>>>
>
> Yes, this works nicely. Thanks very much!
Is this a new addition? With GDC I get a compiler error:
expression expected, not '>'
... suggesting => isn't supported.
|
April 23, 2012 Re: Range of random numbers | ||||
---|---|---|---|---|
| ||||
Posted in reply to Joseph Rushton Wakeling | On 04/23/2012 10:56 AM, Joseph Rushton Wakeling wrote: > On 23/04/12 19:46, Joseph Rushton Wakeling wrote: >> On 23/04/12 18:56, bearophile wrote: >>> jerro: >>> >>>> return repeat(0).map!(_ => uniform(lower, upper))(); >>>> >> >> Yes, this works nicely. Thanks very much! > > Is this a new addition? With GDC I get a compiler error: > > expression expected, not '>' > > ... suggesting => isn't supported. > The lambda syntax was added in 2.058: http://dlang.org/changelog.html Ali |
April 23, 2012 Re: Range of random numbers | ||||
---|---|---|---|---|
| ||||
Posted in reply to bearophile | > It's for a different purpose. So the count() I was proposing will need a different name.
Couldn't it just be iota with no parameters?
|
April 23, 2012 Re: Range of random numbers | ||||
---|---|---|---|---|
| ||||
Posted in reply to jerro | jerro:
> Couldn't it just be iota with no parameters?
The Count range has a helper count() function similar to this, that's meant to have an argument that defaults to zero:
Count!T count(T)(T start=0) if (isIntegral!T) { return Count!T(start); }
The argument allows it to start from another starting point, and it allows you to specify the type of the numbers it yields, while in iota() without arguments it's less easy to specify the type of the numbers it yields.
Count(5) is easy to replace with iota(5, int.max), but count(BigInt(0)) is less easy to replace with iota, because it doesn't give you a way to denote a right-open BigInt interval. And using iota(BigInt(0), BigInt(ulong.max)) is not that good. Currently using BigInt in iota seems to not even being supported...
Bye,
bearophile
|
Copyright © 1999-2021 by the D Language Foundation