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