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 }