math_test.js 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364
  1. // Copyright 2006 The Closure Library Authors. All Rights Reserved.
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS-IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. goog.provide('goog.mathTest');
  15. goog.setTestOnly('goog.mathTest');
  16. goog.require('goog.math');
  17. goog.require('goog.testing.jsunit');
  18. function testRandomInt() {
  19. assertEquals(0, goog.math.randomInt(0));
  20. assertEquals(0, goog.math.randomInt(1));
  21. var r = goog.math.randomInt(3);
  22. assertTrue(0 <= r && r < 3);
  23. }
  24. function testUniformRandom() {
  25. assertEquals(5.2, goog.math.uniformRandom(5.2, 5.2));
  26. assertEquals(-6, goog.math.uniformRandom(-6, -6));
  27. var r = goog.math.uniformRandom(-0.5, 0.5);
  28. assertTrue(-0.5 <= r && r < 0.5);
  29. }
  30. function testClamp() {
  31. assertEquals(3, goog.math.clamp(3, -5, 5));
  32. assertEquals(5, goog.math.clamp(5, -5, 5));
  33. assertEquals(-5, goog.math.clamp(-5, -5, 5));
  34. assertEquals(-5, goog.math.clamp(-22, -5, 5));
  35. assertEquals(5, goog.math.clamp(6, -5, 5));
  36. }
  37. function testModulo() {
  38. assertEquals(0, goog.math.modulo(256, 8));
  39. assertEquals(7, goog.math.modulo(7, 8));
  40. assertEquals(7, goog.math.modulo(23, 8));
  41. assertEquals(7, goog.math.modulo(-1, 8));
  42. // Safari 5.1.7 has a bug in its JS engine where modulo is computed
  43. // incorrectly when using variables. We avoid using
  44. // goog.testing.ExpectedFailure here since it pulls in a bunch of
  45. // extra dependencies for maintaining a DOM console.
  46. var a = 1;
  47. var b = -5;
  48. if (a % b === 1 % -5) {
  49. assertEquals(-4, goog.math.modulo(1, -5));
  50. assertEquals(-4, goog.math.modulo(6, -5));
  51. }
  52. assertEquals(-4, goog.math.modulo(-4, -5));
  53. }
  54. function testLerp() {
  55. assertEquals(0, goog.math.lerp(0, 0, 0));
  56. assertEquals(3, goog.math.lerp(0, 6, 0.5));
  57. assertEquals(3, goog.math.lerp(-1, 1, 2));
  58. }
  59. function testNearlyEquals() {
  60. assertTrue(
  61. 'Numbers inside default tolerance should be equal',
  62. goog.math.nearlyEquals(0.000001, 0.000001001));
  63. assertFalse(
  64. 'Numbers outside default tolerance should be unequal',
  65. goog.math.nearlyEquals(0.000001, 0.000003));
  66. assertTrue(
  67. 'Numbers inside custom tolerance should be equal',
  68. goog.math.nearlyEquals(0.001, 0.002, 0.1));
  69. assertFalse(
  70. 'Numbers outside custom tolerance should be unequal',
  71. goog.math.nearlyEquals(0.001, -0.1, 0.1));
  72. assertTrue(
  73. 'Integer tolerance greater than one should succeed',
  74. goog.math.nearlyEquals(87, 85, 3));
  75. }
  76. function testStandardAngleInRadians() {
  77. assertRoughlyEquals(0, goog.math.standardAngleInRadians(2 * Math.PI), 1e-10);
  78. assertRoughlyEquals(
  79. Math.PI, goog.math.standardAngleInRadians(Math.PI), 1e-10);
  80. assertRoughlyEquals(
  81. Math.PI, goog.math.standardAngleInRadians(-1 * Math.PI), 1e-10);
  82. assertRoughlyEquals(
  83. Math.PI / 2, goog.math.standardAngleInRadians(-1.5 * Math.PI), 1e-10);
  84. assertRoughlyEquals(
  85. Math.PI, goog.math.standardAngleInRadians(5 * Math.PI), 1e-10);
  86. assertEquals(0.01, goog.math.standardAngleInRadians(0.01));
  87. assertEquals(0, goog.math.standardAngleInRadians(0));
  88. }
  89. function testStandardAngle() {
  90. assertEquals(359.5, goog.math.standardAngle(-360.5));
  91. assertEquals(0, goog.math.standardAngle(-360));
  92. assertEquals(359.5, goog.math.standardAngle(-0.5));
  93. assertEquals(0, goog.math.standardAngle(0));
  94. assertEquals(0.5, goog.math.standardAngle(0.5));
  95. assertEquals(0, goog.math.standardAngle(360));
  96. assertEquals(1, goog.math.standardAngle(721));
  97. }
  98. function testToRadians() {
  99. assertEquals(-Math.PI, goog.math.toRadians(-180));
  100. assertEquals(0, goog.math.toRadians(0));
  101. assertEquals(Math.PI, goog.math.toRadians(180));
  102. }
  103. function testToDegrees() {
  104. assertEquals(-180, goog.math.toDegrees(-Math.PI));
  105. assertEquals(0, goog.math.toDegrees(0));
  106. assertEquals(180, goog.math.toDegrees(Math.PI));
  107. }
  108. function testAngleDx() {
  109. assertRoughlyEquals(0, goog.math.angleDx(0, 0), 1e-10);
  110. assertRoughlyEquals(0, goog.math.angleDx(90, 0), 1e-10);
  111. assertRoughlyEquals(100, goog.math.angleDx(0, 100), 1e-10);
  112. assertRoughlyEquals(0, goog.math.angleDx(90, 100), 1e-10);
  113. assertRoughlyEquals(-100, goog.math.angleDx(180, 100), 1e-10);
  114. assertRoughlyEquals(0, goog.math.angleDx(270, 100), 1e-10);
  115. }
  116. function testAngleDy() {
  117. assertRoughlyEquals(0, goog.math.angleDy(0, 0), 1e-10);
  118. assertRoughlyEquals(0, goog.math.angleDy(90, 0), 1e-10);
  119. assertRoughlyEquals(0, goog.math.angleDy(0, 100), 1e-10);
  120. assertRoughlyEquals(100, goog.math.angleDy(90, 100), 1e-10);
  121. assertRoughlyEquals(0, goog.math.angleDy(180, 100), 1e-10);
  122. assertRoughlyEquals(-100, goog.math.angleDy(270, 100), 1e-10);
  123. }
  124. function testAngle() {
  125. assertRoughlyEquals(0, goog.math.angle(10, 10, 20, 10), 1e-10);
  126. assertRoughlyEquals(90, goog.math.angle(10, 10, 10, 20), 1e-10);
  127. assertRoughlyEquals(225, goog.math.angle(10, 10, 0, 0), 1e-10);
  128. assertRoughlyEquals(270, goog.math.angle(10, 10, 10, 0), 1e-10);
  129. // 0 is the conventional result, but mathematically this is undefined.
  130. assertEquals(0, goog.math.angle(10, 10, 10, 10));
  131. }
  132. function testAngleDifference() {
  133. assertEquals(10, goog.math.angleDifference(30, 40));
  134. assertEquals(-10, goog.math.angleDifference(40, 30));
  135. assertEquals(180, goog.math.angleDifference(10, 190));
  136. assertEquals(180, goog.math.angleDifference(190, 10));
  137. assertEquals(20, goog.math.angleDifference(350, 10));
  138. assertEquals(-20, goog.math.angleDifference(10, 350));
  139. assertEquals(100, goog.math.angleDifference(350, 90));
  140. assertEquals(-80, goog.math.angleDifference(350, 270));
  141. assertEquals(0, goog.math.angleDifference(15, 15));
  142. }
  143. function testSign() {
  144. assertEquals(0, goog.math.sign(0));
  145. assertEquals(-1, goog.math.sign(-3));
  146. assertEquals(1, goog.math.sign(3));
  147. assertEquals(1, goog.math.sign(0.0001));
  148. assertEquals(-1, goog.math.sign(-0.0001));
  149. assertEquals(1, goog.math.sign(3141592653589793));
  150. }
  151. function testSignOfSpecialFloatValues() {
  152. assertEquals(-1, goog.math.sign(-Infinity));
  153. assertEquals(1, goog.math.sign(Infinity));
  154. assertNaN(goog.math.sign(NaN));
  155. assertEquals(0, goog.math.sign(0));
  156. assertFalse(goog.math.isNegativeZero(goog.math.sign(0)));
  157. assertEquals(0, goog.math.sign(-0));
  158. assertTrue(goog.math.isNegativeZero(goog.math.sign(-0)));
  159. }
  160. function testLongestCommonSubsequence() {
  161. var func = goog.math.longestCommonSubsequence;
  162. assertArrayEquals([2], func([1, 2], [2, 1]));
  163. assertArrayEquals([1, 2], func([1, 2, 5], [2, 1, 2]));
  164. assertArrayEquals(
  165. [1, 2, 3, 4, 5],
  166. func([1, 0, 2, 3, 8, 4, 9, 5], [8, 1, 2, 4, 3, 6, 4, 5]));
  167. assertArrayEquals([1, 1, 1, 1, 1], func([1, 1, 1, 1, 1], [1, 1, 1, 1, 1]));
  168. assertArrayEquals([5], func([1, 2, 3, 4, 5], [5, 4, 3, 2, 1]));
  169. assertArrayEquals(
  170. [1, 8, 11], func([1, 6, 8, 11, 13], [1, 3, 5, 8, 9, 11, 12]));
  171. }
  172. function testLongestCommonSubsequenceWithCustomComparator() {
  173. var func = goog.math.longestCommonSubsequence;
  174. var compareFn = function(a, b) { return a.field == b.field; };
  175. var a1 = {field: 'a1', field2: 'hello'};
  176. var a2 = {field: 'a2', field2: 33};
  177. var a3 = {field: 'a3'};
  178. var a4 = {field: 'a3'};
  179. assertArrayEquals([a1, a2], func([a1, a2, a3], [a3, a1, a2], compareFn));
  180. assertArrayEquals([a1, a3], func([a1, a3], [a1, a4], compareFn));
  181. // testing the same arrays without compare function
  182. assertArrayEquals([a1], func([a1, a3], [a1, a4]));
  183. }
  184. function testLongestCommonSubsequenceWithCustomCollector() {
  185. var func = goog.math.longestCommonSubsequence;
  186. var collectorFn = function(a, b) { return b; };
  187. assertArrayEquals(
  188. [1, 2, 4, 6, 7], func(
  189. [1, 0, 2, 3, 8, 4, 9, 5], [8, 1, 2, 4, 3, 6, 4, 5],
  190. null, collectorFn));
  191. }
  192. function testSum() {
  193. assertEquals(
  194. 'sum() must return 0 if there are no arguments', 0, goog.math.sum());
  195. assertEquals(
  196. 'sum() must return its argument if there is only one', 17,
  197. goog.math.sum(17));
  198. assertEquals(
  199. 'sum() must handle positive integers', 10, goog.math.sum(1, 2, 3, 4));
  200. assertEquals(
  201. 'sum() must handle real numbers', -2.5, goog.math.sum(1, -2, 3, -4.5));
  202. assertTrue(
  203. 'sum() must return NaN if one of the arguments isn\'t numeric',
  204. isNaN(goog.math.sum(1, 2, 'foo', 3)));
  205. }
  206. function testAverage() {
  207. assertTrue(
  208. 'average() must return NaN if there are no arguments',
  209. isNaN(goog.math.average()));
  210. assertEquals(
  211. 'average() must return its argument if there is only one', 17,
  212. goog.math.average(17));
  213. assertEquals(
  214. 'average() must handle positive integers', 3,
  215. goog.math.average(1, 2, 3, 4, 5));
  216. assertEquals(
  217. 'average() must handle real numbers', -0.625,
  218. goog.math.average(1, -2, 3, -4.5));
  219. assertTrue(
  220. 'average() must return NaN if one of the arguments isn\'t ' +
  221. 'numeric',
  222. isNaN(goog.math.average(1, 2, 'foo', 3)));
  223. }
  224. function testSampleVariance() {
  225. assertEquals(
  226. 'sampleVariance() must return 0 if there are no samples', 0,
  227. goog.math.sampleVariance());
  228. assertEquals(
  229. 'sampleVariance() must return 0 if there is only one ' +
  230. 'sample',
  231. 0, goog.math.sampleVariance(17));
  232. assertRoughlyEquals(
  233. 'sampleVariance() must handle positive integers', 48,
  234. goog.math.sampleVariance(3, 7, 7, 19), 0.0001);
  235. assertRoughlyEquals(
  236. 'sampleVariance() must handle real numbers', 12.0138,
  237. goog.math.sampleVariance(1.23, -2.34, 3.14, -4.56), 0.0001);
  238. }
  239. function testStandardDeviation() {
  240. assertEquals(
  241. 'standardDeviation() must return 0 if there are no samples', 0,
  242. goog.math.standardDeviation());
  243. assertEquals(
  244. 'standardDeviation() must return 0 if there is only one ' +
  245. 'sample',
  246. 0, goog.math.standardDeviation(17));
  247. assertRoughlyEquals(
  248. 'standardDeviation() must handle positive integers', 6.9282,
  249. goog.math.standardDeviation(3, 7, 7, 19), 0.0001);
  250. assertRoughlyEquals(
  251. 'standardDeviation() must handle real numbers', 3.4660,
  252. goog.math.standardDeviation(1.23, -2.34, 3.14, -4.56), 0.0001);
  253. }
  254. function testIsInt() {
  255. assertFalse(goog.math.isInt(12345.67));
  256. assertFalse(goog.math.isInt(0.123));
  257. assertFalse(goog.math.isInt(.1));
  258. assertFalse(goog.math.isInt(-23.43));
  259. assertFalse(goog.math.isInt(-.1));
  260. assertFalse(goog.math.isInt(1e-1));
  261. assertTrue(goog.math.isInt(1));
  262. assertTrue(goog.math.isInt(0));
  263. assertTrue(goog.math.isInt(-2));
  264. assertTrue(goog.math.isInt(-2.0));
  265. assertTrue(goog.math.isInt(10324231));
  266. assertTrue(goog.math.isInt(1.));
  267. assertTrue(goog.math.isInt(1e3));
  268. }
  269. function testIsFiniteNumber() {
  270. assertFalse(goog.math.isFiniteNumber(NaN));
  271. assertFalse(goog.math.isFiniteNumber(-Infinity));
  272. assertFalse(goog.math.isFiniteNumber(+Infinity));
  273. assertTrue(goog.math.isFiniteNumber(0));
  274. assertTrue(goog.math.isFiniteNumber(1));
  275. assertTrue(goog.math.isFiniteNumber(Math.PI));
  276. }
  277. function testIsNegativeZero() {
  278. assertFalse(goog.math.isNegativeZero(0));
  279. assertTrue(goog.math.isNegativeZero(-0));
  280. assertFalse(goog.math.isNegativeZero(1));
  281. assertFalse(goog.math.isNegativeZero(-1));
  282. assertFalse(goog.math.isNegativeZero(-Number.MIN_VALUE));
  283. }
  284. function testLog10Floor() {
  285. // The greatest floating point number that is less than 1.
  286. var oneMinusEpsilon = 1 - Math.pow(2, -53);
  287. for (var i = -30; i <= 30; i++) {
  288. assertEquals(i, goog.math.log10Floor(parseFloat('1e' + i)));
  289. assertEquals(
  290. i - 1, goog.math.log10Floor(parseFloat('1e' + i) * oneMinusEpsilon));
  291. }
  292. assertEquals(-Infinity, goog.math.log10Floor(0));
  293. assertTrue(isNaN(goog.math.log10Floor(-1)));
  294. }
  295. function testSafeFloor() {
  296. assertEquals(0, goog.math.safeFloor(0));
  297. assertEquals(0, goog.math.safeFloor(1e-15));
  298. assertEquals(0, goog.math.safeFloor(-1e-15));
  299. assertEquals(-1, goog.math.safeFloor(-3e-15));
  300. assertEquals(4, goog.math.safeFloor(5 - 3e-15));
  301. assertEquals(5, goog.math.safeFloor(5 - 1e-15));
  302. assertEquals(-5, goog.math.safeFloor(-5 - 1e-15));
  303. assertEquals(-6, goog.math.safeFloor(-5 - 3e-15));
  304. assertEquals(3, goog.math.safeFloor(2.91, 0.1));
  305. assertEquals(2, goog.math.safeFloor(2.89, 0.1));
  306. // Tests some real life examples with the default epsilon value.
  307. assertEquals(0, goog.math.safeFloor(Math.log(1000) / Math.LN10 - 3));
  308. assertEquals(21, goog.math.safeFloor(Math.log(1e+21) / Math.LN10));
  309. }
  310. function testSafeCeil() {
  311. assertEquals(0, goog.math.safeCeil(0));
  312. assertEquals(0, goog.math.safeCeil(1e-15));
  313. assertEquals(0, goog.math.safeCeil(-1e-15));
  314. assertEquals(1, goog.math.safeCeil(3e-15));
  315. assertEquals(6, goog.math.safeCeil(5 + 3e-15));
  316. assertEquals(5, goog.math.safeCeil(5 + 1e-15));
  317. assertEquals(-4, goog.math.safeCeil(-5 + 3e-15));
  318. assertEquals(-5, goog.math.safeCeil(-5 + 1e-15));
  319. assertEquals(3, goog.math.safeCeil(3.09, 0.1));
  320. assertEquals(4, goog.math.safeCeil(3.11, 0.1));
  321. }