// Copyright 2006 The Closure Library Authors. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS-IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. goog.provide('goog.mathTest'); goog.setTestOnly('goog.mathTest'); goog.require('goog.math'); goog.require('goog.testing.jsunit'); function testRandomInt() { assertEquals(0, goog.math.randomInt(0)); assertEquals(0, goog.math.randomInt(1)); var r = goog.math.randomInt(3); assertTrue(0 <= r && r < 3); } function testUniformRandom() { assertEquals(5.2, goog.math.uniformRandom(5.2, 5.2)); assertEquals(-6, goog.math.uniformRandom(-6, -6)); var r = goog.math.uniformRandom(-0.5, 0.5); assertTrue(-0.5 <= r && r < 0.5); } function testClamp() { assertEquals(3, goog.math.clamp(3, -5, 5)); assertEquals(5, goog.math.clamp(5, -5, 5)); assertEquals(-5, goog.math.clamp(-5, -5, 5)); assertEquals(-5, goog.math.clamp(-22, -5, 5)); assertEquals(5, goog.math.clamp(6, -5, 5)); } function testModulo() { assertEquals(0, goog.math.modulo(256, 8)); assertEquals(7, goog.math.modulo(7, 8)); assertEquals(7, goog.math.modulo(23, 8)); assertEquals(7, goog.math.modulo(-1, 8)); // Safari 5.1.7 has a bug in its JS engine where modulo is computed // incorrectly when using variables. We avoid using // goog.testing.ExpectedFailure here since it pulls in a bunch of // extra dependencies for maintaining a DOM console. var a = 1; var b = -5; if (a % b === 1 % -5) { assertEquals(-4, goog.math.modulo(1, -5)); assertEquals(-4, goog.math.modulo(6, -5)); } assertEquals(-4, goog.math.modulo(-4, -5)); } function testLerp() { assertEquals(0, goog.math.lerp(0, 0, 0)); assertEquals(3, goog.math.lerp(0, 6, 0.5)); assertEquals(3, goog.math.lerp(-1, 1, 2)); } function testNearlyEquals() { assertTrue( 'Numbers inside default tolerance should be equal', goog.math.nearlyEquals(0.000001, 0.000001001)); assertFalse( 'Numbers outside default tolerance should be unequal', goog.math.nearlyEquals(0.000001, 0.000003)); assertTrue( 'Numbers inside custom tolerance should be equal', goog.math.nearlyEquals(0.001, 0.002, 0.1)); assertFalse( 'Numbers outside custom tolerance should be unequal', goog.math.nearlyEquals(0.001, -0.1, 0.1)); assertTrue( 'Integer tolerance greater than one should succeed', goog.math.nearlyEquals(87, 85, 3)); } function testStandardAngleInRadians() { assertRoughlyEquals(0, goog.math.standardAngleInRadians(2 * Math.PI), 1e-10); assertRoughlyEquals( Math.PI, goog.math.standardAngleInRadians(Math.PI), 1e-10); assertRoughlyEquals( Math.PI, goog.math.standardAngleInRadians(-1 * Math.PI), 1e-10); assertRoughlyEquals( Math.PI / 2, goog.math.standardAngleInRadians(-1.5 * Math.PI), 1e-10); assertRoughlyEquals( Math.PI, goog.math.standardAngleInRadians(5 * Math.PI), 1e-10); assertEquals(0.01, goog.math.standardAngleInRadians(0.01)); assertEquals(0, goog.math.standardAngleInRadians(0)); } function testStandardAngle() { assertEquals(359.5, goog.math.standardAngle(-360.5)); assertEquals(0, goog.math.standardAngle(-360)); assertEquals(359.5, goog.math.standardAngle(-0.5)); assertEquals(0, goog.math.standardAngle(0)); assertEquals(0.5, goog.math.standardAngle(0.5)); assertEquals(0, goog.math.standardAngle(360)); assertEquals(1, goog.math.standardAngle(721)); } function testToRadians() { assertEquals(-Math.PI, goog.math.toRadians(-180)); assertEquals(0, goog.math.toRadians(0)); assertEquals(Math.PI, goog.math.toRadians(180)); } function testToDegrees() { assertEquals(-180, goog.math.toDegrees(-Math.PI)); assertEquals(0, goog.math.toDegrees(0)); assertEquals(180, goog.math.toDegrees(Math.PI)); } function testAngleDx() { assertRoughlyEquals(0, goog.math.angleDx(0, 0), 1e-10); assertRoughlyEquals(0, goog.math.angleDx(90, 0), 1e-10); assertRoughlyEquals(100, goog.math.angleDx(0, 100), 1e-10); assertRoughlyEquals(0, goog.math.angleDx(90, 100), 1e-10); assertRoughlyEquals(-100, goog.math.angleDx(180, 100), 1e-10); assertRoughlyEquals(0, goog.math.angleDx(270, 100), 1e-10); } function testAngleDy() { assertRoughlyEquals(0, goog.math.angleDy(0, 0), 1e-10); assertRoughlyEquals(0, goog.math.angleDy(90, 0), 1e-10); assertRoughlyEquals(0, goog.math.angleDy(0, 100), 1e-10); assertRoughlyEquals(100, goog.math.angleDy(90, 100), 1e-10); assertRoughlyEquals(0, goog.math.angleDy(180, 100), 1e-10); assertRoughlyEquals(-100, goog.math.angleDy(270, 100), 1e-10); } function testAngle() { assertRoughlyEquals(0, goog.math.angle(10, 10, 20, 10), 1e-10); assertRoughlyEquals(90, goog.math.angle(10, 10, 10, 20), 1e-10); assertRoughlyEquals(225, goog.math.angle(10, 10, 0, 0), 1e-10); assertRoughlyEquals(270, goog.math.angle(10, 10, 10, 0), 1e-10); // 0 is the conventional result, but mathematically this is undefined. assertEquals(0, goog.math.angle(10, 10, 10, 10)); } function testAngleDifference() { assertEquals(10, goog.math.angleDifference(30, 40)); assertEquals(-10, goog.math.angleDifference(40, 30)); assertEquals(180, goog.math.angleDifference(10, 190)); assertEquals(180, goog.math.angleDifference(190, 10)); assertEquals(20, goog.math.angleDifference(350, 10)); assertEquals(-20, goog.math.angleDifference(10, 350)); assertEquals(100, goog.math.angleDifference(350, 90)); assertEquals(-80, goog.math.angleDifference(350, 270)); assertEquals(0, goog.math.angleDifference(15, 15)); } function testSign() { assertEquals(0, goog.math.sign(0)); assertEquals(-1, goog.math.sign(-3)); assertEquals(1, goog.math.sign(3)); assertEquals(1, goog.math.sign(0.0001)); assertEquals(-1, goog.math.sign(-0.0001)); assertEquals(1, goog.math.sign(3141592653589793)); } function testSignOfSpecialFloatValues() { assertEquals(-1, goog.math.sign(-Infinity)); assertEquals(1, goog.math.sign(Infinity)); assertNaN(goog.math.sign(NaN)); assertEquals(0, goog.math.sign(0)); assertFalse(goog.math.isNegativeZero(goog.math.sign(0))); assertEquals(0, goog.math.sign(-0)); assertTrue(goog.math.isNegativeZero(goog.math.sign(-0))); } function testLongestCommonSubsequence() { var func = goog.math.longestCommonSubsequence; assertArrayEquals([2], func([1, 2], [2, 1])); assertArrayEquals([1, 2], func([1, 2, 5], [2, 1, 2])); assertArrayEquals( [1, 2, 3, 4, 5], func([1, 0, 2, 3, 8, 4, 9, 5], [8, 1, 2, 4, 3, 6, 4, 5])); assertArrayEquals([1, 1, 1, 1, 1], func([1, 1, 1, 1, 1], [1, 1, 1, 1, 1])); assertArrayEquals([5], func([1, 2, 3, 4, 5], [5, 4, 3, 2, 1])); assertArrayEquals( [1, 8, 11], func([1, 6, 8, 11, 13], [1, 3, 5, 8, 9, 11, 12])); } function testLongestCommonSubsequenceWithCustomComparator() { var func = goog.math.longestCommonSubsequence; var compareFn = function(a, b) { return a.field == b.field; }; var a1 = {field: 'a1', field2: 'hello'}; var a2 = {field: 'a2', field2: 33}; var a3 = {field: 'a3'}; var a4 = {field: 'a3'}; assertArrayEquals([a1, a2], func([a1, a2, a3], [a3, a1, a2], compareFn)); assertArrayEquals([a1, a3], func([a1, a3], [a1, a4], compareFn)); // testing the same arrays without compare function assertArrayEquals([a1], func([a1, a3], [a1, a4])); } function testLongestCommonSubsequenceWithCustomCollector() { var func = goog.math.longestCommonSubsequence; var collectorFn = function(a, b) { return b; }; assertArrayEquals( [1, 2, 4, 6, 7], func( [1, 0, 2, 3, 8, 4, 9, 5], [8, 1, 2, 4, 3, 6, 4, 5], null, collectorFn)); } function testSum() { assertEquals( 'sum() must return 0 if there are no arguments', 0, goog.math.sum()); assertEquals( 'sum() must return its argument if there is only one', 17, goog.math.sum(17)); assertEquals( 'sum() must handle positive integers', 10, goog.math.sum(1, 2, 3, 4)); assertEquals( 'sum() must handle real numbers', -2.5, goog.math.sum(1, -2, 3, -4.5)); assertTrue( 'sum() must return NaN if one of the arguments isn\'t numeric', isNaN(goog.math.sum(1, 2, 'foo', 3))); } function testAverage() { assertTrue( 'average() must return NaN if there are no arguments', isNaN(goog.math.average())); assertEquals( 'average() must return its argument if there is only one', 17, goog.math.average(17)); assertEquals( 'average() must handle positive integers', 3, goog.math.average(1, 2, 3, 4, 5)); assertEquals( 'average() must handle real numbers', -0.625, goog.math.average(1, -2, 3, -4.5)); assertTrue( 'average() must return NaN if one of the arguments isn\'t ' + 'numeric', isNaN(goog.math.average(1, 2, 'foo', 3))); } function testSampleVariance() { assertEquals( 'sampleVariance() must return 0 if there are no samples', 0, goog.math.sampleVariance()); assertEquals( 'sampleVariance() must return 0 if there is only one ' + 'sample', 0, goog.math.sampleVariance(17)); assertRoughlyEquals( 'sampleVariance() must handle positive integers', 48, goog.math.sampleVariance(3, 7, 7, 19), 0.0001); assertRoughlyEquals( 'sampleVariance() must handle real numbers', 12.0138, goog.math.sampleVariance(1.23, -2.34, 3.14, -4.56), 0.0001); } function testStandardDeviation() { assertEquals( 'standardDeviation() must return 0 if there are no samples', 0, goog.math.standardDeviation()); assertEquals( 'standardDeviation() must return 0 if there is only one ' + 'sample', 0, goog.math.standardDeviation(17)); assertRoughlyEquals( 'standardDeviation() must handle positive integers', 6.9282, goog.math.standardDeviation(3, 7, 7, 19), 0.0001); assertRoughlyEquals( 'standardDeviation() must handle real numbers', 3.4660, goog.math.standardDeviation(1.23, -2.34, 3.14, -4.56), 0.0001); } function testIsInt() { assertFalse(goog.math.isInt(12345.67)); assertFalse(goog.math.isInt(0.123)); assertFalse(goog.math.isInt(.1)); assertFalse(goog.math.isInt(-23.43)); assertFalse(goog.math.isInt(-.1)); assertFalse(goog.math.isInt(1e-1)); assertTrue(goog.math.isInt(1)); assertTrue(goog.math.isInt(0)); assertTrue(goog.math.isInt(-2)); assertTrue(goog.math.isInt(-2.0)); assertTrue(goog.math.isInt(10324231)); assertTrue(goog.math.isInt(1.)); assertTrue(goog.math.isInt(1e3)); } function testIsFiniteNumber() { assertFalse(goog.math.isFiniteNumber(NaN)); assertFalse(goog.math.isFiniteNumber(-Infinity)); assertFalse(goog.math.isFiniteNumber(+Infinity)); assertTrue(goog.math.isFiniteNumber(0)); assertTrue(goog.math.isFiniteNumber(1)); assertTrue(goog.math.isFiniteNumber(Math.PI)); } function testIsNegativeZero() { assertFalse(goog.math.isNegativeZero(0)); assertTrue(goog.math.isNegativeZero(-0)); assertFalse(goog.math.isNegativeZero(1)); assertFalse(goog.math.isNegativeZero(-1)); assertFalse(goog.math.isNegativeZero(-Number.MIN_VALUE)); } function testLog10Floor() { // The greatest floating point number that is less than 1. var oneMinusEpsilon = 1 - Math.pow(2, -53); for (var i = -30; i <= 30; i++) { assertEquals(i, goog.math.log10Floor(parseFloat('1e' + i))); assertEquals( i - 1, goog.math.log10Floor(parseFloat('1e' + i) * oneMinusEpsilon)); } assertEquals(-Infinity, goog.math.log10Floor(0)); assertTrue(isNaN(goog.math.log10Floor(-1))); } function testSafeFloor() { assertEquals(0, goog.math.safeFloor(0)); assertEquals(0, goog.math.safeFloor(1e-15)); assertEquals(0, goog.math.safeFloor(-1e-15)); assertEquals(-1, goog.math.safeFloor(-3e-15)); assertEquals(4, goog.math.safeFloor(5 - 3e-15)); assertEquals(5, goog.math.safeFloor(5 - 1e-15)); assertEquals(-5, goog.math.safeFloor(-5 - 1e-15)); assertEquals(-6, goog.math.safeFloor(-5 - 3e-15)); assertEquals(3, goog.math.safeFloor(2.91, 0.1)); assertEquals(2, goog.math.safeFloor(2.89, 0.1)); // Tests some real life examples with the default epsilon value. assertEquals(0, goog.math.safeFloor(Math.log(1000) / Math.LN10 - 3)); assertEquals(21, goog.math.safeFloor(Math.log(1e+21) / Math.LN10)); } function testSafeCeil() { assertEquals(0, goog.math.safeCeil(0)); assertEquals(0, goog.math.safeCeil(1e-15)); assertEquals(0, goog.math.safeCeil(-1e-15)); assertEquals(1, goog.math.safeCeil(3e-15)); assertEquals(6, goog.math.safeCeil(5 + 3e-15)); assertEquals(5, goog.math.safeCeil(5 + 1e-15)); assertEquals(-4, goog.math.safeCeil(-5 + 3e-15)); assertEquals(-5, goog.math.safeCeil(-5 + 1e-15)); assertEquals(3, goog.math.safeCeil(3.09, 0.1)); assertEquals(4, goog.math.safeCeil(3.11, 0.1)); }