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