OLD | NEW |
| (Empty) |
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | |
2 // for details. All rights reserved. Use of this source code is governed by a | |
3 // BSD-style license that can be found in the LICENSE file. | |
4 | |
5 // A test to compare the results of the fixnum library with the Dart VM | |
6 | |
7 #library('int64vmtest'); | |
8 #source('../../../lib/fixnum/intx.dart'); | |
9 #source('../../../lib/fixnum/int32.dart'); | |
10 #source('../../../lib/fixnum/int64.dart'); | |
11 | |
12 void main() { | |
13 int64VMTest test = new int64VMTest(); | |
14 test.doTestBinary(new BinaryOp("&", (a, b) => a & b)); | |
15 test.doTestBinary(new BinaryOp("|", (a, b) => a | b)); | |
16 test.doTestBinary(new BinaryOp("^", (a, b) => a ^ b)); | |
17 test.doTestBinary(new BinaryOp("+", (a, b) => a + b)); | |
18 test.doTestBinary(new BinaryOp("-", (a, b) => a - b)); | |
19 test.doTestBinary(new BinaryOp("*", (a, b) => a * b)); | |
20 test.doTestUnary(new UnaryOp("-", (a) => -a)); | |
21 test.doTestUnary(new UnaryOp("~", (a) => ~a)); | |
22 test.doTestShift(new ShiftOp("<<", (a, n) => a << (n & 63))); | |
23 test.doTestShift(new ShiftOp(">>", (a, n) => a >> (n & 63))); | |
24 test.doTestBoolean(new BooleanOp("compareTo", (a, b) => a.compareTo(b))); | |
25 test.doTestBoolean(new BooleanOp("==", (a, b) => a == b)); | |
26 test.doTestBoolean(new BooleanOp("!=", (a, b) => a != b)); | |
27 test.doTestBoolean(new BooleanOp("<", (a, b) => a < b)); | |
28 test.doTestBoolean(new BooleanOp("<=", (a, b) => a <= b)); | |
29 test.doTestBoolean(new BooleanOp(">", (a, b) => a > b)); | |
30 test.doTestBoolean(new BooleanOp(">=", (a, b) => a >= b)); | |
31 test.doTestBinary(new BinaryOp("%", (a, b) => a % b)); | |
32 test.doTestBinary(new BinaryOp("~/", (a, b) => a ~/ b)); | |
33 test.doTestBinary(new BinaryOp("remainder", (a, b) => a.remainder(b))); | |
34 } | |
35 | |
36 final int DISCARD = 0; | |
37 | |
38 int64 _randomInt64() { | |
39 int i = 0; | |
40 for (int b = 0; b < 64; b++) { | |
41 double rand = Math.random(); | |
42 for (int j = 0; j < DISCARD; j++) { | |
43 rand = Math.random(); | |
44 } | |
45 i = (i << 1) | ((rand > 0.5) ? 1 : 0); | |
46 } | |
47 return new int64.fromInt(i); | |
48 } | |
49 | |
50 int _randomInt(int n) { | |
51 double rand = Math.random(); | |
52 for (int i = 0; i < DISCARD; i++) { | |
53 rand = Math.random(); | |
54 } | |
55 return (rand * n).floor().toInt(); | |
56 } | |
57 | |
58 class Op { | |
59 String name; | |
60 Function op; | |
61 | |
62 Op(String this.name, Function this.op); | |
63 | |
64 // Truncate x to a value in the range [-2^63, 2^63 - 1] | |
65 int trunc64(int x) { | |
66 int trunc = x & 0xffffffffffffffff; | |
67 if ((trunc & 0x8000000000000000) != 0) { | |
68 trunc -= 18446744073709551616; // 2^64 | |
69 } | |
70 return trunc; | |
71 } | |
72 } | |
73 | |
74 class UnaryOp extends Op { | |
75 UnaryOp(String name, Function op) : super(name, op); | |
76 int ref(int val) => trunc64(op(val)); | |
77 int64 test(int64 val) => op(val); | |
78 } | |
79 | |
80 class BinaryOp extends Op { | |
81 BinaryOp(String name, Function op) : super(name, op); | |
82 int ref(int val0, int val1) => trunc64(op(val0, val1)); | |
83 int64 test(int64 val0, int64 val1) => op(val0, val1); | |
84 } | |
85 | |
86 class BooleanOp extends Op { | |
87 BooleanOp(String name, Function op) : super(name, op); | |
88 bool ref(int val0, int val1) => op(val0, val1); | |
89 bool test(int64 val0, int64 val1) => op(val0, val1); | |
90 } | |
91 | |
92 class ShiftOp extends Op { | |
93 ShiftOp(String name, Function op) : super(name, op); | |
94 int ref(int val0, int shift) => trunc64(op(val0, shift)); | |
95 int64 test(int64 val0, int shift) => op(val0, shift); | |
96 } | |
97 | |
98 class int64VMTest { | |
99 static final int BASE_VALUES = 32; | |
100 static final int RANDOM_TESTS = 32; | |
101 List<int64> TEST_VALUES; | |
102 | |
103 int64VMTest() { | |
104 Set<int64> testSet = new Set<int64>(); | |
105 for (int i = 0; i < BASE_VALUES; i++) { | |
106 testSet.add(new int64.fromInt(i)); | |
107 testSet.add(new int64.fromInt(-i)); | |
108 | |
109 testSet.add(int64.MIN_VALUE + i); | |
110 testSet.add(int64.MAX_VALUE - i); | |
111 | |
112 testSet.add(new int64.fromInt(i << int64._BITS ~/ 2)); | |
113 testSet.add(new int64.fromInt(i << int64._BITS)); | |
114 testSet.add(new int64.fromInt(i << (3 * int64._BITS) ~/ 2)); | |
115 testSet.add(new int64.fromInt(i << 2 * int64._BITS)); | |
116 testSet.add(new int64.fromInt(i << (5 * int64._BITS) ~/ 2)); | |
117 } | |
118 | |
119 int64 one = new int64.fromInt(1); | |
120 int64 three = new int64.fromInt(3); | |
121 int64 ones = int64.parseHex("1111111111111111"); | |
122 int64 tens = int64.parseHex("1010101010101010"); | |
123 int64 oh_ones = int64.parseHex("0101010101010101"); | |
124 int64 digits = int64.parseHex("123456789ABCDEFF"); | |
125 for (int i = 0; i < 16; i++) { | |
126 testSet.add(ones * i); | |
127 testSet.add(~(ones * i)); | |
128 testSet.add(-(ones * i)); | |
129 testSet.add(tens * i); | |
130 testSet.add(~(tens * i)); | |
131 testSet.add(-(tens * i)); | |
132 testSet.add(oh_ones * i); | |
133 testSet.add(~(oh_ones * i)); | |
134 testSet.add(-(oh_ones * i)); | |
135 testSet.add(digits * i); | |
136 testSet.add(~(digits * i)); | |
137 testSet.add(-(digits * i)); | |
138 } | |
139 | |
140 for (int i = 0; i < 64; i += 4) { | |
141 testSet.add(one << i); | |
142 testSet.add(~(one << i)); | |
143 testSet.add(digits >> i); | |
144 testSet.add(-(digits >> i)); | |
145 | |
146 // Powers of two and nearby numbers | |
147 testSet.add(one << i); | |
148 for (int j = 1; j <= 16; j++) { | |
149 testSet.add((one << i) + j); | |
150 testSet.add(-((one << i) + j)); | |
151 testSet.add(~((one << i) + j)); | |
152 testSet.add((one << i) - j); | |
153 testSet.add(-((one << i) - j)); | |
154 testSet.add(~((one << i) - j)); | |
155 testSet.add((three << i) + j); | |
156 testSet.add(-((three << i) + j)); | |
157 testSet.add(~((three << i) + j)); | |
158 testSet.add((three << i) - j); | |
159 testSet.add(-((three << i) - j)); | |
160 testSet.add(~((three << i) - j)); | |
161 } | |
162 } | |
163 | |
164 for (int a = 0; a < 19; a++) { | |
165 // Math.pow(10, a) | |
166 int pow = 1; | |
167 for (int j = 0; j < a; j++) { | |
168 pow *= 10; | |
169 } | |
170 testSet.add(new int64.fromInt(pow)); | |
171 } | |
172 | |
173 TEST_VALUES = new List<int64>(testSet.length); | |
174 int index = 0; | |
175 for (int64 val in testSet) { | |
176 TEST_VALUES[index++] = val; | |
177 } | |
178 | |
179 print("VALUES.length = $index"); | |
180 } | |
181 | |
182 void _doTestUnary(UnaryOp op, int64 val) { | |
183 int ref = op.ref(val.toInt()); | |
184 int64 result64 = op.test(val); | |
185 int result = result64.toInt(); | |
186 if (ref != result) { | |
187 Expect.fail("${op.name}: val = $val"); | |
188 } | |
189 } | |
190 | |
191 void doTestUnary(UnaryOp op) { | |
192 print("Testing operator ${op.name}"); | |
193 for (int i = 0; i < TEST_VALUES.length; i++) { | |
194 _doTestUnary(op, TEST_VALUES[i]); | |
195 } | |
196 for (int i = 0; i < RANDOM_TESTS; i++) { | |
197 int64 randomLong = _randomInt64(); | |
198 _doTestUnary(op, randomLong); | |
199 } | |
200 } | |
201 | |
202 void _doTestBinary(BinaryOp op, int64 val0, int64 val1) { | |
203 // print("Test val0 = $val0, val1 = $val1"); | |
204 var refException = null; | |
205 int ref = -1; | |
206 try { | |
207 ref = op.ref(val0.toInt(), val1.toInt()); | |
208 } catch (Exception e) { | |
209 refException = e; | |
210 } | |
211 var testException = null; | |
212 int result = -2; | |
213 int64 result64; | |
214 try { | |
215 int64 val0_save = new int64._copy(val0); | |
216 int64 val1_save = new int64._copy(val1); | |
217 result64 = op.test(val0, val1); | |
218 result = result64.toInt(); | |
219 if (val0 != val0_save) { | |
220 print( | |
221 "Test altered first argument val0 = $val0, val0_save = $val0_save"); | |
222 } | |
223 if (val1 != val1_save) { | |
224 print("Test altered second argument"); | |
225 } | |
226 } catch (Exception e) { | |
227 testException = e; | |
228 } | |
229 if (testException is IntegerDivisionByZeroException && | |
230 refException is IntegerDivisionByZeroException) { | |
231 } else if (testException != null || refException != null) { | |
232 Expect.fail("${op.name}: val0 = $val0, val1 = $val1, " | |
233 "testException = $testException, refException = $refException"); | |
234 return; | |
235 } else if (ref != result) { | |
236 if ("%" == op.name && ref < 0) { | |
237 // print("Dart VM bug: ${op.name}: val0 = $val0, val1 = $val1, " | |
238 // "ref = $ref, result64 = $result64, result = $result"); | |
239 } else { | |
240 Expect.fail("${op.name}: val0 = $val0, val1 = $val1, " | |
241 "ref = $ref, result64 = $result64, result = $result"); | |
242 } | |
243 } | |
244 } | |
245 | |
246 void doTestBinary(BinaryOp op) { | |
247 print("Testing operator ${op.name}"); | |
248 for (int i = 0; i < TEST_VALUES.length; i++) { | |
249 int64 randomLong = _randomInt64(); | |
250 _doTestBinary(op, TEST_VALUES[i], randomLong); | |
251 _doTestBinary(op, randomLong, TEST_VALUES[i]); | |
252 for (int j = 0; j < TEST_VALUES.length; j++) { | |
253 _doTestBinary(op, TEST_VALUES[i], TEST_VALUES[j]); | |
254 } | |
255 } | |
256 for (int i = 0; i < RANDOM_TESTS; i++) { | |
257 int64 longVal0 = _randomInt64(); | |
258 int64 longVal1 = _randomInt64(); | |
259 if (_randomInt(20) == 0) { | |
260 if (_randomInt(2) == 0) { | |
261 longVal1 = longVal0; | |
262 } else { | |
263 longVal1 = -longVal0; | |
264 } | |
265 } | |
266 _doTestBinary(op, longVal0, longVal1); | |
267 } | |
268 } | |
269 | |
270 void _doTestBoolean(BooleanOp op, int64 val0, int64 val1) { | |
271 bool ref = op.ref(val0.toInt(), val1.toInt()); | |
272 bool result = op.test(val0, val1); | |
273 if (ref != result) { | |
274 Expect.fail("${op.name}: val0 = $val0, val1 = $val1"); | |
275 } | |
276 } | |
277 | |
278 void doTestBoolean(BooleanOp op) { | |
279 print("Testing operator ${op.name}"); | |
280 for (int i = 0; i < TEST_VALUES.length; i++) { | |
281 int64 randomLong = _randomInt64(); | |
282 _doTestBoolean(op, TEST_VALUES[i], randomLong); | |
283 _doTestBoolean(op, randomLong, TEST_VALUES[i]); | |
284 for (int j = 0; j < TEST_VALUES.length; j++) { | |
285 _doTestBoolean(op, TEST_VALUES[i], TEST_VALUES[j]); | |
286 } | |
287 } | |
288 for (int i = 0; i < RANDOM_TESTS; i++) { | |
289 int64 longVal0 = _randomInt64(); | |
290 int64 longVal1 = _randomInt64(); | |
291 if (_randomInt(20) == 0) { | |
292 if (_randomInt(2) == 0) { | |
293 longVal1 = longVal0; | |
294 } else { | |
295 longVal1 = -longVal0; | |
296 } | |
297 } | |
298 _doTestBoolean(op, longVal0, longVal1); | |
299 } | |
300 } | |
301 | |
302 void _doTestShift(ShiftOp op, int64 val, int shift) { | |
303 int ref = op.ref(val.toInt(), shift); | |
304 int64 result64 = op.test(val, shift); | |
305 int result = result64.toInt(); | |
306 if (ref != result) { | |
307 Expect.fail("${op.name}: val = $val, shift = $shift"); | |
308 } | |
309 } | |
310 | |
311 void doTestShift(ShiftOp op) { | |
312 print("Testing operator ${op.name}"); | |
313 for (int i = 0; i < TEST_VALUES.length; i++) { | |
314 for (int shift = -64; shift <= 64; shift++) { | |
315 _doTestShift(op, TEST_VALUES[i], shift); | |
316 } | |
317 } | |
318 for (int i = 0; i < RANDOM_TESTS; i++) { | |
319 int64 randomLong = _randomInt64(); | |
320 for (int shift = -64; shift <= 64; shift++) { | |
321 _doTestShift(op, randomLong, shift); | |
322 } | |
323 } | |
324 } | |
325 } | |
OLD | NEW |