Skip to content

Commit 07833fb

Browse files
authored
fix algorithms API (#69)
* fix algorithms API * ditto * rm test code
1 parent d7de9a9 commit 07833fb

File tree

3 files changed

+190
-37
lines changed

3 files changed

+190
-37
lines changed

README.md

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,38 @@ Professional Random Number Generators
1313

1414
Documentation: http://docs.random.dlang.io/latest/index.html
1515

16+
17+
### Example (3 seconds)
18+
```d
19+
#!/usr/bin/env dub
20+
/+ dub.json:
21+
{
22+
"name": "test_random",
23+
"dependencies": {"mir-random": "~>0.3.3"}
24+
}
25+
+/
26+
27+
import std.range, std.stdio;
28+
29+
import mir.random.variable: NormalVariable;
30+
import mir.random.algorithm: range;
31+
32+
void main()
33+
{
34+
auto sample = NormalVariable!double(0, 1).range.take(10).array;
35+
36+
sample[$.randIndex].writeln; // prints random element from the sample
37+
}
38+
```
39+
40+
41+
### Example (10 seconds)
1642
```d
1743
#!/usr/bin/env dub
1844
/+ dub.json:
1945
{
2046
"name": "test_random",
21-
"dependencies": {"mir-random": "~>0.3.1"}
47+
"dependencies": {"mir-random": "~>0.3.3"}
2248
}
2349
+/
2450
@@ -31,12 +57,12 @@ import mir.random.algorithm: range;
3157
3258
void main(){
3359
auto rng = Random(unpredictableSeed); // Engines are allocated on stack or global
34-
auto sample = range!rng // Engines can passed by alias to algorithms
60+
auto sample = range!rng // Engines can passed to algorithms by alias or by pointer
3561
(NormalVariable!double(0, 1)) // Random variables are passed by value
36-
.take(1000) // Fix sample length to 1000 elements (Input Range API)
62+
.take(10) // Fix sample length to 10 elements (Input Range API)
3763
.array; // Allocates memory and performs computation
3864
39-
writeln(sample);
65+
sample[$.randIndex].writeln; // prints random element from the sample
4066
}
4167
```
4268

source/mir/random/algorithm.d

Lines changed: 44 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import mir.math.common;
1111

1212
import mir.random;
1313
public import mir.random.engine;
14+
import mir.random.variable: isRandomVariable;
1415

1516
private enum bool isPassByRef(P) = !is(P == struct) && !is(P == union) && !isPointer!P && !isScalarType!P
1617
&& (isFunction!P || isDelegate!P || is(P == class) || is(P == interface));
@@ -140,28 +141,28 @@ struct RandomField(alias gen)
140141

141142
/// ditto
142143
RandomField!(G, D, T) field(T, G, D)(ref G gen, D var)
143-
if (isReferenceToSaturatedRandomEngine!G)
144+
if (isReferenceToSaturatedRandomEngine!G && isRandomVariable!D)
144145
{
145146
return typeof(return)(gen, var);
146147
}
147148

148149
/// ditto
149150
RandomField!(gen, D, T) field(alias gen, D, T)(D var)
150-
if (isSaturatedRandomEngine!(typeof(gen)))
151+
if (isSaturatedRandomEngine!(typeof(gen)) && isRandomVariable!D)
151152
{
152153
return RandomField!(gen,D,T)(var);
153154
}
154155

155156
/// ditto
156157
auto field(G, D)(ref G gen, D var)
157-
if (isReferenceToSaturatedRandomEngine!G)
158+
if (isReferenceToSaturatedRandomEngine!G && isRandomVariable!D)
158159
{
159160
return RandomField!(G, D, Unqual!(typeof(var(deref(gen)))))(gen, var);
160161
}
161162

162163
/// ditto
163164
auto field(alias gen, D)(D var)
164-
if (isSaturatedRandomEngine!(typeof(gen)))
165+
if (isSaturatedRandomEngine!(typeof(gen)) && isRandomVariable!D)
165166
{
166167
return RandomField!(gen,D,Unqual!(typeof(var(gen))))(var);
167168
}
@@ -268,7 +269,7 @@ Range interface for random distributions and uniform random bit generators.
268269
Note: $(UL $(LI The structure holds a pointer to a generator.) $(LI The structure must not be copied (explicitly or implicitly) outside from a function.))
269270
+/
270271
struct RandomRange(G, D)
271-
if (isReferenceToSaturatedRandomEngine!G)
272+
if (isReferenceToSaturatedRandomEngine!G && isRandomVariable!D)
272273
{
273274
private D _var;
274275
private G _gen;
@@ -288,7 +289,7 @@ struct RandomRange(G, D)
288289

289290
/// ditto
290291
struct RandomRange(alias gen, D)
291-
if (isSaturatedRandomEngine!(typeof(gen)))
292+
if (isSaturatedRandomEngine!(typeof(gen)) && isRandomVariable!D)
292293
{
293294
private D _var;
294295
private Unqual!(typeof(_var(gen))) _val;
@@ -364,21 +365,21 @@ struct RandomRange(alias gen)
364365
}
365366

366367
/// ditto
367-
RandomRange!(G, D) range(G, D)(ref G gen, D var)
368-
if (isReferenceToSaturatedRandomEngine!G)
368+
RandomRange!(G, D) range(G, D)(G gen, D var)
369+
if (isReferenceToSaturatedRandomEngine!G && isRandomVariable!D)
369370
{
370371
return typeof(return)(gen, var);
371372
}
372373

373374
/// ditto
374-
RandomRange!(gen, D) range(alias gen, D)(D var)
375-
if (isSaturatedRandomEngine!(typeof(gen)))
375+
RandomRange!(gen, D) range(alias gen = rne, D)(D var)
376+
if (isSaturatedRandomEngine!(typeof(gen)) && isRandomVariable!D)
376377
{
377378
return typeof(return)(var);
378379
}
379380

380381
/// ditto
381-
RandomRange!G range(G)(ref G gen)
382+
RandomRange!G range(G)(G gen)
382383
if (isReferenceToSaturatedRandomEngine!G)
383384
{
384385
return typeof(return)(gen);
@@ -743,17 +744,30 @@ void shuffle(Range, G)(scope ref G gen, scope Range range)
743744
}
744745
}
745746

747+
/// ditto
748+
void shuffle(Range, G)(scope G* gen, scope Range range)
749+
if (isSaturatedRandomEngine!G && isRandomAccessRange!Range && hasLength!Range)
750+
{
751+
return .shuffle(*gen, range);
752+
}
753+
754+
/// ditto
755+
void shuffle(Range)(scope Range range)
756+
if (isRandomAccessRange!Range && hasLength!Range)
757+
{
758+
return .shuffle(rne, range);
759+
}
760+
746761
///
747762
nothrow @safe version(mir_random_test) unittest
748763
{
749764
import mir.ndslice.allocation: slice;
750765
import mir.ndslice.topology: iota;
751766
import mir.ndslice.sorting;
752767

753-
auto gen = Random(unpredictableSeed);
754768
auto a = iota(10).slice;
755769

756-
gen.shuffle(a);
770+
shuffle(a);
757771

758772
sort(a);
759773
assert(a == iota(10));
@@ -768,15 +782,14 @@ These will be in an undefined order, but will not be random in the sense that th
768782
`shuffle` returns will not be independent of their order before
769783
`shuffle` was called.
770784
Params:
771-
gen = random number engine to use
785+
gen = (optional) random number engine to use
772786
range = random-access range with length whose elements are to be shuffled
773787
n = number of elements of `r` to shuffle (counting from the beginning);
774788
must be less than `r.length`
775789
Complexity: O(n)
776790
+/
777791
void shuffle(Range, G)(scope ref G gen, scope Range range, size_t n)
778-
if ((isSaturatedRandomEngine!G || isReferenceToSaturatedRandomEngine!G)
779-
&& isRandomAccessRange!Range && hasLength!Range)
792+
if (isSaturatedRandomEngine!G && isRandomAccessRange!Range && hasLength!Range)
780793
{
781794
import std.algorithm.mutation : swapAt;
782795
assert(n <= range.length, "n must be <= range.length for shuffle.");
@@ -789,17 +802,30 @@ void shuffle(Range, G)(scope ref G gen, scope Range range, size_t n)
789802
}
790803
}
791804

805+
/// ditto
806+
void shuffle(Range, G)(scope G* gen, scope Range range, size_t n)
807+
if (isSaturatedRandomEngine!G && isRandomAccessRange!Range && hasLength!Range)
808+
{
809+
return .shuffle(*gen, range, n);
810+
}
811+
812+
/// ditto
813+
void shuffle(Range)(scope Range range, size_t n)
814+
if (isRandomAccessRange!Range && hasLength!Range)
815+
{
816+
return .shuffle(rne, range, n);
817+
}
818+
792819
///
793820
nothrow @safe version(mir_random_test) unittest
794821
{
795822
import mir.ndslice.allocation: slice;
796823
import mir.ndslice.topology: iota;
797824
import mir.ndslice.sorting;
798825

799-
auto gen = Random(unpredictableSeed);
800826
auto a = iota(10).slice;
801827

802-
gen.shuffle(a, 4);
828+
shuffle(a, 4);
803829

804830
sort(a);
805831
assert(a == iota(10));

0 commit comments

Comments
 (0)