| 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 |