333 lines
12 KiB
JavaScript
333 lines
12 KiB
JavaScript
// 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(-1, goog.math.sign(-1));
|
|
assertEquals(1, goog.math.sign(1));
|
|
assertEquals(0, goog.math.sign(0));
|
|
assertEquals(0, goog.math.sign(-0));
|
|
assertEquals(1, goog.math.sign(0.0001));
|
|
assertEquals(-1, goog.math.sign(-0.0001));
|
|
assertEquals(-1, goog.math.sign(-Infinity));
|
|
assertEquals(1, goog.math.sign(Infinity));
|
|
assertEquals(1, goog.math.sign(3141592653589793));
|
|
}
|
|
|
|
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 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));
|
|
}
|