// 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. // VMOptions=--optimization-counter-threshold=5 --no-background-compilation 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 for 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 // would 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 ]; test() { // Tests of pow(x, y): for (var d in samples) { // if `y` is zero (0.0 or -0.0), the result is always 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) { // if `x` is 1.0, the result is always 1.0. Expect.identical(1.0, pow(1.0, d), "$d"); } for (var d in samples) { // otherwise, if either `x` or `y` is NaN then the result is NaN. if (d != 0.0) Expect.isTrue(pow(NaN, d).isNaN, "$d"); if (d != 1.0) Expect.isTrue(pow(d, NaN).isNaN, "$d"); } for (var d in samples) { // if `x` is a finite and strictly negative and `y` is a finite non-integer, // the result is NaN. if (d < 0 && !d.isInfinite) { Expect.isTrue(pow(d, 0.5).isNaN, "$d"); Expect.isTrue(pow(d, -0.5).isNaN, "$d"); Expect.isTrue(pow(d, 1.5).isNaN, "$d"); Expect.isTrue(pow(d, -1.5).isNaN, "$d"); } } for (var d in samples) { if (d < 0) { // if `x` is Infinity and `y` is strictly negative, the result is 0.0. Expect.identical(0.0, pow(Infinity, d), "$d"); } if (d > 0) { // if `x` is Infinity and `y` is strictly positive, the result is Infinity. Expect.identical(Infinity, pow(Infinity, d), "$d"); } } for (var d in samples) { if (d < 0) { // if `x` is 0.0 and `y` is strictly negative, the result is Infinity. Expect.identical(Infinity, pow(0.0, d), "$d"); } if (d > 0) { // if `x` is 0.0 and `y` is strictly positive, the result is 0.0. Expect.identical(0.0, pow(0.0, d), "$d"); } } for (var d in samples) { if (!d.isInfinite && !d.isNaN) { var dint = d.toInt(); if (d == dint && dint.isOdd) { // if `x` is -Infinity or -0.0 and `y` is an odd integer, then the // result is`-pow(-x ,y)`. Expect.identical(-pow(Infinity, d), pow(-Infinity, d)); Expect.identical(-pow(0.0, d), pow(-0.0, d)); continue; } } // if `x` is -Infinity or -0.0 and `y` is not an odd integer, then the // result is the same as `pow(-x , y)`. if (d.isNaN) { Expect.isTrue(pow(Infinity, d).isNaN); Expect.isTrue(pow(-Infinity, d).isNaN); Expect.isTrue(pow(0.0, d).isNaN); Expect.isTrue(pow(-0.0, d).isNaN); continue; } Expect.identical(pow(Infinity, d), pow(-Infinity, d)); Expect.identical(pow(0.0, d), pow(-0.0, d)); } for (var d in samples) { if (d.abs() < 1) { // if `y` is Infinity and the absolute value of `x` is less than 1, the // result is 0.0. Expect.identical(0.0, pow(d, Infinity)); } else if (d.abs() > 1) { // if `y` is Infinity and the absolute value of `x` is greater than 1, // the result is Infinity. Expect.identical(Infinity, pow(d, Infinity)); } else if (d == -1) { // if `y` is Infinity and `x` is -1, the result is 1.0. Expect.identical(1.0, pow(d, Infinity)); } // if `y` is -Infinity, the result is `1/pow(x, Infinity)`. if (d.isNaN) { Expect.isTrue((1 / pow(d, Infinity)).isNaN); Expect.isTrue(pow(d, -Infinity).isNaN); } else { Expect.identical(1 / pow(d, Infinity), pow(d, -Infinity)); } } // Some non-exceptional 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, -9223372036854775807)); } main() { for (int i = 0; i < 10; i++) test(); }