1 module chimpfella.kernels;
2 import chimpfella.measurement;
3 import std.traits;
4 import std.range.primitives;
5 
6 @nogc:
7 @safe:
8 /+++
9 If you want to generate templated data for a `TemplateBenchmark`, this will forward the current iterated
10 parameter to the parameter of ForwardTemplate.
11 +/
12 struct ForwardTemplate(alias forwardThis)
13 {
14     alias contents = forwardThis;
15 }
16 
17 ///
18 struct FunctionBenchmark(string name, alias genIndependantVariable, alias independantToData = void)
19         if (!is(genIndependantVariable == void) && isValidIndependantRange!genIndependantVariable)
20 {
21     static if (!is(independantToData == void))
22     {
23         static if (isInstanceOf!(ForwardTemplate, independantToData))
24         {
25             //Forward template to it
26             enum forward = true;
27             //pragma(msg, "wowo");
28         }
29         else
30         {
31             enum forward = false;
32             //Try to check some things early.
33             static if (isCallable!(genIndependantVariable))
34                 alias elemT = ElementType!(typeof(genIndependantVariable()));
35             else
36                 alias elemT = ElementType!(typeof(genIndependantVariable));
37             alias forceEval = elemT;
38             static if (__traits(isTemplate, independantToData))
39                 alias finalFunc = independantToData!forceEval;
40             else
41                 alias finalFunc = independantToData;
42 
43             static if (arity!finalFunc)
44             {
45                 enum compiles = __traits(compiles, finalFunc(elemT.init));
46                 //pragma(msg, fullyQualifiedName!finalFunc);
47                 static if (__traits(isTemplate, finalFunc))
48                 {
49                     //pragma(msg, "Magic");
50                 }
51                 else
52                 {
53                     static assert(__traits(compiles, finalFunc(elemT.init)));
54                 }
55 
56             }
57         }
58 
59     }
60 
61     //The library knows everything about a function so running it with external data can be handled someplace else
62 
63     ///Template parameter repeated as a struct field to simplify code elsewhere.
64     immutable string benchmarkName = name;
65 
66     alias genIndSet = genIndependantVariable;
67 
68     alias genData = independantToData;
69 
70     ///
71     const Measurements[] measurementList;
72     this(in Measurements[] theList)
73     {
74         measurementList = theList;
75     }
76 }
77 ///
78 enum isValidIndependantRange(alias T) = isInputRange!(typeof(T))
79     || isInputRange!(ReturnType!(typeof(T)));
80 ///
81 @safe unittest
82 {
83     import std.range : iota;
84 
85     enum meas = [PhobosTimer("A stub").toMeasurement];
86     @FunctionBenchmark!("Something with an integer", iota(1, 10_000))(meas) void func(int l)
87     {
88 
89     }
90 
91     alias getIota = () => iota(1, 200);
92     @FunctionBenchmark!("Something with an integer", getIota)(meas) void func2(int l)
93     {
94 
95     }
96 }
97 ///
98 struct TemplateBenchmark(uint pIndex, Args...)
99 {
100     uint paramIndex = pIndex;
101     alias paramPack = Args;
102 }
103 ///
104 @safe unittest
105 {
106     import std.meta;
107     import std.range : repeat;
108 
109     auto getRandPair(T)()
110     {
111         import std.random;
112 
113         struct rndParams
114         {
115             AliasSeq!(T, T) pack;
116         }
117 
118         rndParams tmp;
119         auto rnd = Random(unpredictableSeed);
120 
121         // Generate an integer in [0, 1023]
122         tmp.pack[0] = cast(T) uniform(0, 1024, rnd);
123         tmp.pack[1] = cast(T) uniform(0, 1024, rnd);
124     }
125 
126     @FunctionBenchmark!("int add benchmark", 0.repeat(100), getRandPair!int) int add(int x, int y)
127     {
128         return x + y;
129     }
130 
131     @TemplateBenchmark!(0, int, float, double) @FunctionBenchmark!(
132             "Templated add benchmark", 0.repeat(100), getRandPair) T templatedAdd(T)(T x, T y)
133     {
134         return x + y;
135     }
136 }