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