1 /** Data sampling, typically randomly. 2 * 3 * Test: dmd -version=show -preview=dip1000 -preview=in -vcolumns -d -I.. -i -debug -g -checkaction=context -allinst -unittest -main -run sampling.d 4 */ 5 module nxt.sampling; 6 7 alias Offset = size_t; 8 alias Length = size_t; 9 10 /** Span. 11 * TODO: Relate|Unite with `nxt.limits.Limits`. 12 */ 13 struct Span { 14 Offset offset = 0; 15 Length length = 1; 16 } 17 18 @safe pure nothrow @nogc unittest { 19 Span x; 20 assert(x == Span.init); 21 } 22 23 /++ Format (flags) of sampling. +/ 24 struct Format { 25 /// Array length span. 26 Span arrayLengthSpan = Span(0,3); 27 /++ Field recursion depth span for recursive aggregate type with unbounded 28 depth like `std.json.JSONValue`. +/ 29 Span fieldDepth = Span(Length.min, 3); 30 } 31 32 import std.random : Random; 33 34 /++ Returns: A random sample of the type `T`. 35 TODO: Use direct field setting for T only when __traits(isPOD, T) is true 36 otherwise use __traits(getOverloads, T, "__ctor"). 37 Test on `std.json.JSONValue`. 38 +/ 39 auto sample(T)(ref Random rnd, in Format fmt = Format.init) { 40 static if (is(T == U[], U)) { // isArray 41 import std.random : uniform; 42 T t; 43 t.length = uniform(fmt.arrayLengthSpan.offset, fmt.arrayLengthSpan.length, rnd); 44 foreach (ref e; t) 45 e = rnd.sample!(U); 46 return t; 47 } else static if (is(T == struct)) { 48 import std.traits : FieldNameTuple; 49 T t; /+ TODO: = void +/ 50 foreach (mn; FieldNameTuple!T) 51 __traits(getMember, t, mn) = rnd.sample!(typeof(__traits(getMember, t, mn)))(fmt); 52 return t; 53 } else { 54 import std.random : uniform; 55 return uniform!(T); 56 } 57 } 58 59 /// scalar 60 @safe unittest { 61 auto rnd = Random(42); 62 auto s = rnd.sample!ubyte; 63 } 64 65 /// char[] 66 @safe unittest { 67 auto rnd = Random(42); 68 foreach (_; 0 .. 100) { 69 auto s = rnd.sample!(char[])(Format(arrayLengthSpan: Span(0,10))); 70 // dbg(s); 71 } 72 } 73 74 /// struct 75 @safe unittest { 76 auto rnd = Random(42); 77 struct S { byte x, y;} 78 struct T { short a, b; ushort c, d; S s; } 79 struct U { int a, b; uint c, d; T t; int[] ia; } 80 auto s = rnd.sample!U; 81 // dbg(s); 82 } 83 84 version (unittest) { 85 import nxt.debugio; 86 }