1 /** 2 Copyright: Copyright Thomas Stuart Bockman 2015 3 License: <a href="http://www.boost.org/LICENSE_1_0.txt">Boost License 1.0</a>. 4 Authors: Thomas Stuart Bockman 5 */ 6 7 module checkedint.tests.benchmark; 8 import checkedint, checkedint.flags, checkedint.traits; 9 10 import std.algorithm, std.stdio; 11 static if(__VERSION__ >= 2068) { 12 version(GNU) { static assert(false); } 13 import std.meta : AliasSeq; 14 } else 15 import std.typetuple : AliasSeq = TypeTuple; 16 17 /+@safe:+/ 18 19 void benchMacro() { 20 benchMacro!"trialPrimes"(); 21 benchMacro!"collatzSort"(); 22 } 23 24 ulong checkSum; 25 bool invalid; 26 void benchMacro(string testStr)() { 27 import std.conv : to; 28 import std.datetime : benchmark, Duration; 29 30 mixin("alias test = " ~ testStr ~ ";"); 31 writeln(); 32 write("Running "); write(testStr); writeln("() benchmark... "); 33 function() @trusted { stdout.flush(); }(); 34 35 checkSum = 0; 36 test!int(); 37 enum trials = 3; 38 enum laps = 3; 39 const compSum = checkSum * laps * trials; 40 41 foreach(V; AliasSeq!(int, uint, long, ulong)) { 42 foreach(N; AliasSeq!( 43 V, 44 SafeInt!(V, true, false), 45 SafeInt!(V, true, true), 46 SmartInt!(V, true, false), 47 SmartInt!(V, true, true))) 48 { 49 checkSum = 0; 50 invalid = false; 51 writef("%40s: ", N.stringof); 52 53 auto best = Duration.max; 54 foreach(i; 0 .. trials) { 55 auto r = to!Duration(benchmark!(test!N)(laps)[0]) / laps; 56 if(r < best) 57 best = r; 58 } 59 60 if(checkSum != compSum) 61 write("!CHECKSUM "); 62 if(invalid) 63 write("!INVALID "); 64 writeln(to!Duration(best)); 65 } 66 } 67 68 writeln("DONE"); 69 } 70 71 template SafeFold(N) { 72 template SafeFold(real folded) { 73 alias BN = BasicScalar!N; 74 static assert(BN.min <= folded && folded <= BN.max); 75 enum SafeFold = cast(BN)folded; 76 } 77 } 78 79 /+pragma(inline, true) {+/ 80 auto mulPow2(N, M)(const N coef, const M exp) { 81 return coef << exp; } 82 auto divPow2(N, M)(const N coef, const M exp) { 83 return coef >> exp; } 84 /+}+/ 85 86 void trialPrimes(N)() { 87 alias V = SafeFold!N; 88 89 static auto floorSqrt(N n) { 90 assert(n >= V!0); 91 92 enum N maxT = isSigned!N? 93 V!((1414L.mulPow2((N.sizeof * 4) - 11)) - 1L) : 94 V!((1L.mulPow2(N.sizeof * 4)) - 1L); 95 N t = min((n/V!2 + V!1), maxT); 96 N r0 = t; 97 N sq0 = r0 * r0; 98 assert(n <= sq0); 99 100 while(t >= V!1) { 101 if(sq0 < n) { 102 const r1 = r0 + t; 103 const sq1 = r1 * r1; 104 105 if(sq1 <= n) { 106 r0 = r1; 107 sq0 = sq1; 108 } else 109 t /= V!2; 110 } else if(sq0 > n) { 111 r0 = r0 - t; 112 sq0 = r0 * r0; 113 114 t /= V!2; 115 } else 116 break; 117 } 118 119 return r0; 120 } 121 122 enum PrimeCount = V!40000; 123 N[PrimeCount] primes; 124 N[PrimeCount] primeRoots; 125 126 N p = V!0; 127 primes[idx(p)] = N.max; 128 N n = V!2; 129 while(true) { 130 const N rootN = floorSqrt(n); 131 132 bool pass = true; 133 for(N dP = V!0; primes[idx(dP)] <= rootN; ++dP) { 134 if(n % primes[idx(dP)] == V!0) { 135 pass = false; 136 break; 137 } 138 } 139 140 if(pass) { 141 primes[idx(p)] = n; 142 primeRoots[idx(p)] = rootN; 143 144 ++p; 145 if(p < PrimeCount) 146 primes[idx(p)] = N.max; 147 else 148 break; 149 } 150 151 ++n; 152 } 153 154 N subSum = V!0; 155 for(N pu = V!0; pu < PrimeCount; ++pu) 156 subSum += primeRoots[idx(pu)]; 157 checkSum += subSum.bscal; 158 invalid = invalid || IntFlags.local; 159 IntFlags.local.clear(); 160 161 /+for(N q = 0; q < p; ++q) { 162 write(primes[idx(q)]); 163 write(" : "); 164 write(primeRoots[idx(q)]); 165 if(q % 8 != 7) 166 write(", "); 167 else 168 writeln(); 169 } 170 writeln(); 171 stdin.readln();+/ 172 } 173 174 void collatzSort(N)() { 175 alias V = SafeFold!N; 176 177 static void quickSort(N[] array, N lowX, N highX) { 178 if(lowX >= highX) 179 return; 180 181 N pivotX = (lowX + highX).divPow2(1u); 182 N pivotV = array[idx(pivotX)]; 183 array[idx(pivotX)] = array[idx(highX)]; 184 array[idx(highX)] = pivotV; 185 186 N storeX = lowX; 187 N iX = lowX; 188 while(iX < highX) { 189 const iV = array[idx(iX)]; 190 if(iV < pivotV) { 191 array[idx(iX)] = array[idx(storeX)]; 192 array[idx(storeX)] = iV; 193 ++storeX; 194 } 195 ++iX; 196 } 197 pivotX = storeX; 198 199 pivotV = array[idx(pivotX)]; 200 array[idx(pivotX)] = array[idx(highX)]; 201 array[idx(highX)] = pivotV; 202 203 quickSort(array, lowX, pivotX - V!1); 204 quickSort(array, pivotX + V!1, highX); 205 } 206 207 enum N maxN = V!113_382; 208 N[idx(maxN)] finalIs; 209 210 for(N n = V!0; n < maxN; ++n) { 211 N i = V!0; 212 N ai = n + V!1; 213 while(ai != V!1) { 214 if((ai & V!0x1) == V!0) 215 ai = ai.divPow2(1u); 216 else 217 ai = V!3*ai + V!1; 218 219 ++i; 220 } 221 222 finalIs[idx(n)] = i; 223 } 224 225 quickSort(finalIs, N(V!0), maxN - V!1); 226 227 N subSum = finalIs[0]; 228 for(N x = V!1; x < maxN; ++x) { 229 subSum += finalIs[idx(x)]; 230 if(finalIs[idx(x)] < finalIs[idx(x - V!1)]) 231 invalid = true; 232 } 233 checkSum += subSum.bscal; 234 invalid = invalid || IntFlags.local; 235 IntFlags.local.clear(); 236 }