1 /** 2 Generate numeric test values hitting all the likely corner cases for simple 3 integer math algorithms. Floating-point is also well-covered, with the 4 exception of subnormal values. 5 6 Copyright: Copyright Thomas Stuart Bockman 2015 7 License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0). 8 Authors: Thomas Stuart Bockman 9 **/ 10 module checkedint.tests.values; 11 12 import std.math, future.traits0; 13 import std.meta : AliasSeq; 14 15 pure: nothrow: @nogc: @safe: 16 17 alias 18 IntegralTypes = AliasSeq!(byte, ubyte, short, ushort, int, uint, long, ulong), 19 FloatingTypes = AliasSeq!(float, double ,real), 20 NumericTypes = AliasSeq!(IntegralTypes, FloatingTypes), 21 CharTypes = AliasSeq!(char, wchar, dchar), 22 FixedTypes = AliasSeq!(bool, CharTypes, IntegralTypes), 23 ScalarTypes = AliasSeq!(FixedTypes, FloatingTypes); 24 25 struct TestValues(N) 26 if (is(N == void*)) 27 { 28 bool empty = false; 29 void* front() const 30 { 31 return null; 32 } 33 void popFront() 34 { 35 empty = true; 36 } 37 } 38 39 struct TestValues(N) 40 if (is(N == bool)) 41 { 42 private: 43 int idx = 0; 44 45 public: 46 @property bool empty() const 47 { 48 return idx <= 1; 49 } 50 @property bool front() const 51 { 52 return idx != 0; 53 } 54 @property void popFront() 55 { 56 ++idx; 57 } 58 } 59 60 private enum ulong[] naturals = function() 61 { 62 ulong[34 + 3*(64 - 5) - 2] nats; 63 64 size_t n = 0; 65 while (n <= 33) 66 { 67 nats[n] = n; 68 ++n; 69 } 70 71 int sh = 6; 72 while (sh < 64) 73 { 74 nats[n++] = (1uL << sh) -1; 75 nats[n++] = (1uL << sh); 76 nats[n++] = (1uL << sh) + 1; 77 ++sh; 78 } 79 nats[n] = ulong.max; 80 81 return nats; 82 }(); 83 struct TestValues(N) 84 if (isIntegral!N || isSomeChar!N) 85 { 86 private: 87 enum maxIdx = function() 88 { 89 // Test dchar values greater than dchar.max, also: 90 enum ulong trueNmax = isSomeChar!N? ~cast(N)0 : N.max; 91 92 auto x = cast(ptrdiff_t)(naturals.length - 1); 93 while (naturals[x] > trueNmax) 94 --x; 95 return x; 96 }(); 97 enum minIdx = isSigned!N? -(maxIdx + 1) : 0; 98 99 ptrdiff_t index = minIdx; 100 101 public: 102 @property bool empty() const 103 { 104 return index > maxIdx; 105 } 106 @property N front() const 107 { 108 static if (isSigned!N) 109 { 110 if (index < 0) 111 return -cast(N)naturals[-index]; 112 } 113 114 return cast(N)naturals[index]; 115 } 116 @property void popFront() 117 { 118 ++index; 119 } 120 } 121 122 private enum real[] normal_exps = [ 123 real.min_exp < double.min_exp? pow(2.0L, real.min_exp - 1) : 0.0, 124 real.min_exp < double.min_exp? pow(2.0L, real.min_exp) : 0.0, 125 126 pow(2.0L, double.min_exp - 1), 127 pow(2.0L, double.min_exp), 128 129 pow(2.0L, -722), 130 131 pow(2.0L, float.min_exp - 1), 132 pow(2.0L, float.min_exp), 133 134 pow(2.0L, -13), 135 pow(2.0L, -12), 136 137 pow(2.0L, -4), 138 pow(2.0L, -3), 139 pow(2.0L, -2), 140 pow(2.0L, -1), 141 142 1uL << 0, 143 1uL << 1, 144 1uL << 2, 145 1uL << 3, 146 1uL << 4, 147 148 // byte 149 (byte.max >> 1) + 1, 150 // ubyte 151 (ubyte.max >> 1) + 1, 152 1uL << 8, 153 1uL << 10, 154 1uL << 11, 155 1uL << 12, 156 1uL << 13, 157 // short 158 (short.max >> 1) + 1, 159 // ushort 160 (ushort.max >> 1) + 1, 161 1uL << 16, 162 1uL << 23, 163 1uL << 24, 164 1uL << 25, 165 // int 166 (int.max >> 1) + 1, 167 // uint 168 (uint.max >> 1) + 1, 169 1uL << 32, 170 1uL << 52, 171 1uL << 53, 172 1uL << 54, 173 1uL << 61, 174 // long 175 (long.max >> 1) + 1, 176 // ulong 177 (ulong.max >> 1) + 1, 178 pow(2.0L, 64), 179 180 pow(2.0L, 104), 181 pow(2.0L, 105), 182 pow(2.0L, 106), 183 pow(2.0L, 111), 184 pow(2.0L, 112), 185 pow(2.0L, 113), 186 pow(2.0L, 125), 187 188 // cent 189 pow(2.0L, float.max_exp - 2), 190 // ucent 191 pow(2.0L, float.max_exp - 1), 192 pow(2.0L, float.max_exp), 193 pow(2.0L, 437), 194 pow(2.0L, double.max_exp - 2), 195 pow(2.0L, double.max_exp - 1), 196 pow(2.0L, double.max_exp), 197 real.max_exp > double.max_exp? pow(2.0L, real.max_exp - 2) : real.infinity, 198 real.max_exp > double.max_exp? pow(2.0L, real.max_exp - 1) : real.infinity 199 ]; 200 struct TestValues(N) 201 if (isFloatingPoint!N) 202 { 203 private: 204 enum minExpIdx = function() 205 { 206 ptrdiff_t expX = 0; 207 while (!(normal_exps[expX] >= N.min_normal)) 208 ++expX; 209 return expX; 210 }(); 211 enum maxExpIdx = function() 212 { 213 ptrdiff_t expX = normal_exps.length - 1; 214 while (!(normal_exps[expX] <= N.max)) 215 --expX; 216 return expX; 217 }(); 218 enum expCount = (maxExpIdx - minExpIdx) + 1; 219 220 enum N[] normal_mants = [ 221 1.0L, 222 1.0L + N.epsilon, 223 LN2 * 2.0L, 224 E * 0.5L, 225 SQRT2, 226 PI * 0.5L, 227 2.0L - (N.epsilon * 2.0L), 228 2.0L - N.epsilon 229 ]; 230 enum ptrdiff_t maxIdx = (expCount * normal_mants.length) + 2; 231 232 auto index = -maxIdx; 233 N _front = -N.infinity; 234 235 public: 236 @property bool empty() const 237 { 238 return index > maxIdx; 239 } 240 @property N front() const 241 { 242 return _front; 243 } 244 @property void popFront() 245 { 246 ++index; 247 248 const negIdx = index < 0; 249 const absIdx = negIdx? -index : index; 250 251 if (absIdx <= 1) 252 _front = (absIdx == 0)? N.nan : 0; 253 else if (absIdx < maxIdx) 254 { 255 const mant = normal_mants[(absIdx - 2) % normal_mants.length]; 256 const expC = normal_exps[minExpIdx + (absIdx - 2) / normal_mants.length]; 257 _front = mant * expC; 258 } 259 else 260 _front = N.infinity; 261 262 if (negIdx) 263 _front = -_front; 264 } 265 }