Chromium Code Reviews| Index: tests/lib/math/double_pow_test.dart |
| diff --git a/tests/lib/math/double_pow_test.dart b/tests/lib/math/double_pow_test.dart |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..9002007af14b196730c0aa5170fbd5d5509f1bcf |
| --- /dev/null |
| +++ b/tests/lib/math/double_pow_test.dart |
| @@ -0,0 +1,160 @@ |
| +// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file |
| +// for details. All rights reserved. Use of this source code is governed by a |
| +// BSD-style license that can be found in the LICENSE file. |
| + |
| +library math_test; |
| +import "package:expect/expect.dart"; |
| +import 'dart:math'; |
| + |
| +void checkVeryClose(double a, double b) { |
| + // We find a ulp (unit in the last place) by shifting the original number |
| + // to the right. This only works if we are not too close to infinity or if |
| + // we work with denormals. |
| + // We special case or 0.0, but not for infinity. |
| + if (a == 0.0) { |
| + final minimalDouble = 4.9406564584124654e-324; |
| + Expect.equals(true, b.abs() <= minimalDouble); |
| + return; |
| + } |
| + if (b == 0.0) { |
| + // No need to look if they are close. Otherwise the check for 'a' above |
| + // whould have triggered. |
| + Expect.equals(a, b); |
| + } |
| + final double shiftRightBy52 = 2.220446049250313080847263336181640625e-16; |
| + final double shiftedA = (a * shiftRightBy52).abs(); |
| + // Compared to 'a', 'shiftedA' is now ~1-2 ulp. |
| + |
| + final double limitLow = a - shiftedA; |
| + final double limitHigh = a + shiftedA; |
| + Expect.equals(false, a == limitLow); |
| + Expect.equals(false, a == limitHigh); |
| + Expect.equals(true, limitLow <= b); |
| + Expect.equals(true, b <= limitHigh); |
| +} |
| + |
| +const NaN = double.NAN; |
| +const Infinity = double.INFINITY; |
| + |
| +var samples = [ |
| + NaN, |
| + -Infinity, |
| + -3.0, // Odd integer |
| + -2.0, // Even integer |
| + -1.5, // Non-integer, magnitude > 1 |
| + -1.0, // Unit |
| + -0.5, // Non-integer, magnitude < 1. |
| + -0.0, |
| + 0.5, // Non-integer, magnitude < 1. |
| + 1.0, // Unit |
| + 1.5, // Non-integer, magnitude > 1 |
| + 2.0, // Even integer |
| + 3.0, // Odd integer |
| + Infinity |
| +]; |
| + |
| +main() { |
|
floitsch
2013/08/20 10:56:23
add documentation edge-cases one by one (as writte
Lasse Reichstein Nielsen
2013/08/20 12:18:11
Done.
|
| + for (var d in samples) { |
| + // pow(anything, [-]0.0) is 1.0. |
| + Expect.identical(1.0, pow(d, 0.0), "$d"); |
| + Expect.identical(1.0, pow(d, -0.0), "$d"); |
| + } |
| + for (var d in samples) { |
| + // pow(1.0, anything) is 1.0. |
| + Expect.identical(1.0, pow(1.0, d), "$d"); |
| + } |
| + for (var d in samples) { |
| + // Except for the above, NaN is contagious. |
| + if (d != 0.0) Expect.identical(NaN, pow(NaN, d), "$d"); |
| + if (d != 1.0) Expect.identical(NaN, pow(d, NaN), "$d"); |
| + } |
| + for (var d in samples) { |
| + // pow(Negative, finite non-integer) => irrational result, so NaN. |
| + if (d < 0 && !d.isInfinite) { |
| + Expect.identical(NaN, pow(d, 0.5), "$d"); |
| + Expect.identical(NaN, pow(d, -0.5), "$d"); |
| + Expect.identical(NaN, pow(d, 1.5), "$d"); |
| + Expect.identical(NaN, pow(d, -1.5), "$d"); |
| + } |
| + } |
| + |
| + for (var d in samples) { |
| + // pow(Negative, finite non-integer) => irrational result, so NaN. |
| + if (d < 0 && !d.isInfinite) { |
| + Expect.identical(NaN, pow(d, 0.5), "$d"); |
| + Expect.identical(NaN, pow(d, -0.5), "$d"); |
| + Expect.identical(NaN, pow(d, 1.5), "$d"); |
| + Expect.identical(NaN, pow(d, -1.5), "$d"); |
| + } |
| + } |
| + |
| + for (var d in samples) { |
| + // pow(Infinity, negative) == 0.0 |
| + if (d < 0) { |
| + Expect.identical(0.0, pow(Infinity, d), "$d"); |
| + } |
| + // pow(Infinity, positive) == Infinity |
| + if (d > 0) { |
| + Expect.identical(Infinity, pow(Infinity, d), "$d"); |
| + } |
| + } |
| + |
| + for (var d in samples) { |
| + // pow(0.0, negative) == Infinity; |
| + if (d < 0) { |
| + Expect.identical(Infinity, pow(0.0, d), "$d"); |
| + } |
| + // pow(0.0, positive) == 0.0; |
| + if (d > 0) { |
| + Expect.identical(0.0, pow(0.0, d), "$d"); |
| + } |
| + } |
| + |
| + for (var d in samples) { |
| + // pow(-Infinity, x) = x odd int ? -pow(Infinity, x) : pow(Infinity, x); |
| + // pow(-0.0, x) = x odd int ? -pow(0.0, x) : pow(0.0, x); |
| + if (!d.isInfinite && !d.isNaN) { |
| + var dint = d.toInt(); |
| + if (d == dint && dint.isOdd) { |
| + Expect.identical(-pow(Infinity, d), pow(-Infinity, d)); |
| + Expect.identical(-pow(0.0, d), pow(-0.0, d)); |
| + continue; |
| + } |
| + } |
| + Expect.identical(pow(Infinity, d), pow(-Infinity, d)); |
| + Expect.identical(pow(0.0, d), pow(-0.0, d)); |
| + } |
| + |
| + for (var d in samples) { |
| + // pow(<1, Infinity) == 0 |
| + // pow(-1, Infinity) == 1.0 |
| + // pow(>1, Infinity) == Infinity |
| + if (d.abs() < 1) { |
| + Expect.identical(0.0, pow(d, Infinity)); |
| + } else if (d.abs() > 1) { |
| + Expect.identical(Infinity, pow(d, Infinity)); |
| + } else if (d == -1) { |
| + Expect.identical(1.0, pow(d, Infinity)); |
| + } |
| + // pow(x, -Infinity) = 1/pow(x, Infinity) |
| + Expect.identical(1/pow(d, Infinity), pow(d, -Infinity)); |
| + } |
| + |
| + // Some normal values. |
| + checkVeryClose(16.0, pow(4.0, 2.0)); |
| + checkVeryClose(SQRT2, pow(2.0, 0.5)); |
| + checkVeryClose(SQRT1_2, pow(0.5, 0.5)); |
| + // Denormal result. |
| + Expect.identical(5e-324, pow(2.0, -1074.0)); |
| + // Overflow. |
| + Expect.identical(Infinity, pow(10.0, 309.0)); |
| + // Underflow. |
| + Expect.identical(0.0, pow(10.0, -325.0)); |
| + |
| + // Conversion to double. |
| + |
| + // The second argument is an odd integer as int, but not when converted |
| + // to double. |
| + Expect.identical(Infinity, pow(-0.0, -9223372036854775809)); |
| +} |
| + |