UNPKG

32.4 kBJavaScriptView Raw
1var EPSILON = Number.EPSILON || 2.2204460492503130808472633361816e-16;
2
3var Assertion = expect().constructor;
4Assertion.prototype.almostEqual = function (obj, precision) {
5 'use strict';
6
7 var allowedDiff = precision || 1e-11;
8 return this.within(obj - allowedDiff, obj + allowedDiff);
9};
10
11Assertion.prototype.haveULPDistance = function (expected, distance) {
12 var actual = this._obj;
13 return this.above(Math.abs(1 - (actual / expected)) / EPSILON, distance);
14};
15
16describe('Math', function () {
17 var functionsHaveNames = (function foo() {}).name === 'foo';
18 var ifFunctionsHaveNamesIt = functionsHaveNames ? it : xit;
19 var ifShimIt = (typeof process !== 'undefined' && process.env.NO_ES6_SHIM) ? it.skip : it;
20
21 var isPositiveZero = function (zero) {
22 'use strict';
23
24 return zero === 0 && 1 / zero === Infinity;
25 };
26 var isNegativeZero = function (zero) {
27 'use strict';
28
29 return zero === 0 && 1 / zero === -Infinity;
30 };
31 var numberIsNaN = Number.isNaN || function (value) {
32 return value !== value;
33 };
34 var valueOfIsNaN = { valueOf: function () { return NaN; } };
35 var valueOfIsInfinity = { valueOf: function () { return Infinity; } };
36
37 ifShimIt('is on the exported object', function () {
38 var exported = require('../');
39 expect(exported.Math).to.equal(Math);
40 });
41
42 describe('.acosh()', function () {
43 if (!Object.prototype.hasOwnProperty.call(Math, 'acosh')) {
44 return it('exists', function () {
45 expect(Math).to.have.property('acosh');
46 });
47 }
48
49 ifFunctionsHaveNamesIt('has the right name', function () {
50 expect(Math.acosh).to.have.property('name', 'acosh');
51 });
52
53 it('is not enumerable', function () {
54 expect(Math).ownPropertyDescriptor('acosh').to.have.property('enumerable', false);
55 });
56
57 it('has the right arity', function () {
58 expect(Math.acosh).to.have.property('length', 1);
59 });
60
61 it('should be correct', function () {
62 expect(numberIsNaN(Math.acosh(NaN))).to.equal(true);
63 expect(numberIsNaN(Math.acosh(0))).to.equal(true);
64 expect(numberIsNaN(Math.acosh(0.9999999))).to.equal(true);
65 expect(numberIsNaN(Math.acosh(-1e300))).to.equal(true);
66 expect(Math.acosh(1e+99)).to.almostEqual(228.64907138697046);
67 expect(isPositiveZero(Math.acosh(1))).to.equal(true);
68 expect(Math.acosh(Infinity)).to.equal(Infinity);
69 expect(Math.acosh(1234)).to.almostEqual(7.811163220849231);
70 expect(Math.acosh(8.88)).to.almostEqual(2.8737631531629235);
71 expect(Math.acosh(1e160)).to.almostEqual(369.10676205960726);
72 expect(Math.acosh(Number.MAX_VALUE)).to.almostEqual(710.4758600739439);
73 });
74
75 it('works for EPSILON values near 1', function () {
76 var result = Math.acosh(1 + EPSILON);
77 var expected = Math.sqrt(2 * EPSILON);
78
79 expect(result).to.almostEqual(expected);
80 expect(result).to.haveULPDistance(expected, 8);
81 });
82 });
83
84 describe('.asinh()', function () {
85 if (!Object.prototype.hasOwnProperty.call(Math, 'asinh')) {
86 return it('exists', function () {
87 expect(Math).to.have.property('asinh');
88 });
89 }
90
91 ifFunctionsHaveNamesIt('has the right name', function () {
92 expect(Math.asinh).to.have.property('name', 'asinh');
93 });
94
95 it('is not enumerable', function () {
96 expect(Math).ownPropertyDescriptor('asinh').to.have.property('enumerable', false);
97 });
98
99 it('has the right arity', function () {
100 expect(Math.asinh).to.have.property('length', 1);
101 });
102
103 it('should be correct for NaN', function () {
104 expect(numberIsNaN(Math.asinh(NaN))).to.equal(true);
105 });
106
107 it('should be correct for zeroes', function () {
108 expect(isPositiveZero(Math.asinh(+0))).to.equal(true);
109 expect(isNegativeZero(Math.asinh(-0))).to.equal(true);
110 });
111
112 it('should be correct for Infinities', function () {
113 expect(Math.asinh(Infinity)).to.equal(Infinity);
114 expect(Math.asinh(-Infinity)).to.equal(-Infinity);
115 });
116
117 it('should be correct', function () {
118 expect(Math.asinh(1234)).to.almostEqual(7.811163549201245);
119 expect(Math.asinh(9.99)).to.almostEqual(2.997227420191335);
120 expect(Math.asinh(1e150)).to.almostEqual(346.0809111296668);
121 expect(Math.asinh(1e7)).to.almostEqual(16.811242831518268);
122 expect(Math.asinh(-1e7)).to.almostEqual(-16.811242831518268);
123 });
124
125 it('is correct for extreme non-infinities', function () {
126 expect(Math.asinh(1e+300)).not.to.equal(Infinity);
127 expect(Math.asinh(1e+300)).to.almostEqual(691.4686750787736);
128 });
129 });
130
131 describe('.atanh()', function () {
132 if (!Object.prototype.hasOwnProperty.call(Math, 'atanh')) {
133 return it('exists', function () {
134 expect(Math).to.have.property('atanh');
135 });
136 }
137
138 ifFunctionsHaveNamesIt('has the right name', function () {
139 expect(Math.atanh).to.have.property('name', 'atanh');
140 });
141
142 it('is not enumerable', function () {
143 expect(Math).ownPropertyDescriptor('atanh').to.have.property('enumerable', false);
144 });
145
146 it('has the right arity', function () {
147 expect(Math.atanh).to.have.property('length', 1);
148 });
149
150 it('should be correct', function () {
151 expect(numberIsNaN(Math.atanh(NaN))).to.equal(true);
152 expect(numberIsNaN(Math.atanh(-1.00000001))).to.equal(true);
153 expect(numberIsNaN(Math.atanh(1.00000001))).to.equal(true);
154 expect(numberIsNaN(Math.atanh(-1e300))).to.equal(true);
155 expect(numberIsNaN(Math.atanh(1e300))).to.equal(true);
156 expect(Math.atanh(-1)).to.equal(-Infinity);
157 expect(Math.atanh(1)).to.equal(Infinity);
158 expect(isPositiveZero(Math.atanh(+0))).to.equal(true);
159 expect(isNegativeZero(Math.atanh(-0))).to.equal(true);
160 expect(Math.atanh(0.5)).to.almostEqual(0.5493061443340549);
161 expect(Math.atanh(-0.5)).to.almostEqual(-0.5493061443340549);
162 expect(Math.atanh(-0.5)).to.almostEqual(-0.5493061443340549);
163 expect(Math.atanh(0.444)).to.almostEqual(0.47720201260109457);
164 });
165
166 it('is correct for extreme non-infinities', function () {
167 expect(Math.atanh(1e-300)).not.to.equal(0);
168 expect(Math.atanh(1e-300)).to.almostEqual(1e-300);
169 });
170 });
171
172 describe('.cbrt()', function () {
173 if (!Object.prototype.hasOwnProperty.call(Math, 'cbrt')) {
174 return it('exists', function () {
175 expect(Math).to.have.property('cbrt');
176 });
177 }
178
179 ifFunctionsHaveNamesIt('has the right name', function () {
180 expect(Math.cbrt).to.have.property('name', 'cbrt');
181 });
182
183 it('is not enumerable', function () {
184 expect(Math).ownPropertyDescriptor('cbrt').to.have.property('enumerable', false);
185 });
186
187 it('has the right arity', function () {
188 expect(Math.cbrt).to.have.property('length', 1);
189 });
190
191 it('should be correct', function () {
192 expect(isNaN(Math.cbrt(NaN))).to.equal(true);
193 expect(isPositiveZero(Math.cbrt(+0))).to.equal(true);
194 expect(isNegativeZero(Math.cbrt(-0))).to.equal(true);
195 expect(Math.cbrt(Infinity)).to.equal(Infinity);
196 expect(Math.cbrt(-Infinity)).to.equal(-Infinity);
197 expect(Math.cbrt(-8)).to.almostEqual(-2);
198 expect(Math.cbrt(8)).to.almostEqual(2);
199 expect(Math.cbrt(-1000)).to.almostEqual(-10);
200 expect(Math.cbrt(1000)).to.almostEqual(10);
201 });
202
203 it('is correct at extremes', function () {
204 var result = Math.cbrt(1e-300);
205 var expected = 1e-100;
206 expect(result).to.almostEqual(expected);
207 expect(result).to.haveULPDistance(expected, 8);
208
209 expect(Math.cbrt(-1e-300)).to.almostEqual(-1e-100);
210 expect(Math.cbrt(-1e+300)).to.almostEqual(-1e+100);
211 expect(Math.cbrt(1e+300)).to.almostEqual(1e+100);
212 });
213 });
214
215 describe('.clz32()', function () {
216 if (!Object.prototype.hasOwnProperty.call(Math, 'clz32')) {
217 return it('exists', function () {
218 expect(Math).to.have.property('clz32');
219 });
220 }
221
222 ifFunctionsHaveNamesIt('has the right name', function () {
223 expect(Math.clz32).to.have.property('name', 'clz32');
224 });
225
226 it('is not enumerable', function () {
227 expect(Math).ownPropertyDescriptor('clz32').to.have.property('enumerable', false);
228 });
229
230 it('has the right arity', function () {
231 expect(Math.clz32).to.have.property('length', 1);
232 });
233
234 it('should have proper uint32 conversion', function () {
235 var integers = [5295, -5295, -9007199254740991, 9007199254740991, 0, -0];
236 var nonNumbers = [undefined, true, null, {}, [], 'str'];
237 var nonIntegers = [-9007199254741992, 9007199254741992, 5.9];
238
239 integers.forEach(function (item) {
240 expect(Math.clz32(item)).to.be.within(0, 32);
241 });
242 nonIntegers.forEach(function (item) {
243 expect(Math.clz32(item)).to.be.within(0, 32);
244 });
245 nonNumbers.forEach(function (item) {
246 expect(Math.clz32(item)).to.equal(item === true ? 31 : 32);
247 });
248 expect(Math.clz32(true)).to.equal(Math.clz32(1));
249 expect(Math.clz32('')).to.equal(Math.clz32(0));
250 expect(Math.clz32('10')).to.equal(Math.clz32(10));
251 expect(Math.clz32(0.1)).to.equal(32);
252 expect(Math.clz32(-1)).to.equal(0);
253 expect(Math.clz32(1)).to.equal(31);
254 expect(Math.clz32(0xFFFFFFFF)).to.equal(0);
255 expect(Math.clz32(0x1FFFFFFFF)).to.equal(0);
256 expect(Math.clz32(0x111111111)).to.equal(3);
257 expect(Math.clz32(0x11111111)).to.equal(3);
258 });
259
260 it('returns 32 for numbers that coerce to 0', function () {
261 var zeroishes = [
262 0,
263 -0,
264 NaN,
265 Infinity,
266 -Infinity,
267 0x100000000,
268 undefined,
269 null,
270 false,
271 '',
272 'str',
273 {},
274 [],
275 [1, 2]
276 ];
277 zeroishes.forEach(function (zeroish) {
278 expect(Math.clz32(zeroish)).to.equal(32);
279 });
280 });
281 });
282
283 describe('.cosh()', function () {
284 if (!Object.prototype.hasOwnProperty.call(Math, 'cosh')) {
285 return it('exists', function () {
286 expect(Math).to.have.property('cosh');
287 });
288 }
289
290 ifFunctionsHaveNamesIt('has the right name', function () {
291 expect(Math.cosh).to.have.property('name', 'cosh');
292 });
293
294 it('is not enumerable', function () {
295 expect(Math).ownPropertyDescriptor('cosh').to.have.property('enumerable', false);
296 });
297
298 it('has the right arity', function () {
299 expect(Math.cosh).to.have.property('length', 1);
300 });
301
302 it('should be correct for NaN', function () {
303 expect(numberIsNaN(Math.cosh(NaN))).to.equal(true);
304 });
305
306 it('should be correct for Infinities', function () {
307 expect(Math.cosh(Infinity)).to.equal(Infinity);
308 expect(Math.cosh(-Infinity)).to.equal(Infinity);
309 });
310
311 it('should be correct for zeroes', function () {
312 expect(Math.cosh(-0)).to.equal(1);
313 expect(Math.cosh(+0)).to.equal(1);
314 });
315
316 it('should be correct', function () {
317 // Overridden precision values here are for Chrome, as of v25.0.1364.172
318 // Broadened slightly for Firefox 31
319 expect(Math.cosh(12)).to.almostEqual(81377.39571257407, 9e-11);
320 expect(Math.cosh(22)).to.almostEqual(1792456423.065795780980053377, 1e-5);
321 expect(Math.cosh(-10)).to.almostEqual(11013.23292010332313972137);
322 expect(Math.cosh(-23)).to.almostEqual(4872401723.1244513000, 1e-5);
323 expect(Math.cosh(-2e-17)).to.equal(1);
324 });
325
326 it('is correct for extreme non-infinities', function () {
327 expect(Math.cosh(710)).not.to.equal(Infinity);
328 expect(Math.cosh(710) / 1e+308).to.almostEqual(1.1169973830808557);
329 });
330 });
331
332 describe('.expm1()', function () {
333 if (!Object.prototype.hasOwnProperty.call(Math, 'expm1')) {
334 return it('exists', function () {
335 expect(Math).to.have.property('expm1');
336 });
337 }
338
339 ifFunctionsHaveNamesIt('has the right name', function () {
340 expect(Math.expm1).to.have.property('name', 'expm1');
341 });
342
343 it('is not enumerable', function () {
344 expect(Math).ownPropertyDescriptor('expm1').to.have.property('enumerable', false);
345 });
346
347 it('has the right arity', function () {
348 expect(Math.expm1).to.have.property('length', 1);
349 });
350
351 it('should be correct for NaN', function () {
352 expect(numberIsNaN(Math.expm1(NaN))).to.equal(true);
353 });
354
355 it('should be correct for zeroes', function () {
356 expect(isPositiveZero(Math.expm1(+0))).to.equal(true);
357 expect(isNegativeZero(Math.expm1(-0))).to.equal(true);
358 });
359
360 it('should be correct for Infinity', function () {
361 expect(Math.expm1(Infinity)).to.equal(Infinity);
362 expect(Math.expm1(-Infinity)).to.equal(-1);
363 });
364
365 it('should be correct for arbitrary numbers', function () {
366 expect(Math.expm1(10)).to.almostEqual(22025.465794806716516957900645284244366353512618556781);
367 expect(Math.expm1(-10)).to.almostEqual(-0.99995460007023751514846440848443944938976208191113);
368 expect(Math.expm1(-2e-17)).to.almostEqual(-2e-17);
369 });
370
371 it('works with very negative numbers', function () {
372 expect(Math.expm1(-38)).to.almostEqual(-1);
373 expect(Math.expm1(-8675309)).to.almostEqual(-1);
374 expect(Math.expm1(-4815162342)).to.almostEqual(-1);
375 });
376 });
377
378 describe('.hypot()', function () {
379 if (!Object.prototype.hasOwnProperty.call(Math, 'hypot')) {
380 return it('exists', function () {
381 expect(Math).to.have.property('hypot');
382 });
383 }
384
385 ifFunctionsHaveNamesIt('has the right name', function () {
386 expect(Math.hypot).to.have.property('name', 'hypot');
387 });
388
389 it('is not enumerable', function () {
390 expect(Math).ownPropertyDescriptor('hypot').to.have.property('enumerable', false);
391 });
392
393 it('has the right arity', function () {
394 expect(Math.hypot).to.have.property('length', 2);
395 });
396
397 it('should be correct', function () {
398 expect(Math.hypot(Infinity)).to.equal(Infinity);
399 expect(Math.hypot(-Infinity)).to.equal(Infinity);
400 expect(Math.hypot(Infinity, NaN)).to.equal(Infinity);
401 expect(Math.hypot(NaN, Infinity)).to.equal(Infinity);
402 expect(Math.hypot(-Infinity, 'Hello')).to.equal(Infinity);
403 expect(Math.hypot(1, 2, Infinity)).to.equal(Infinity);
404 expect(numberIsNaN(Math.hypot(NaN, 1))).to.equal(true);
405 expect(isPositiveZero(Math.hypot())).to.equal(true);
406 expect(isPositiveZero(Math.hypot(0, 0, 0))).to.equal(true);
407 expect(isPositiveZero(Math.hypot(0, -0, 0))).to.equal(true);
408 expect(isPositiveZero(Math.hypot(-0, -0, -0))).to.equal(true);
409 expect(Math.hypot(66, 66)).to.almostEqual(93.33809511662427);
410 expect(Math.hypot(0.1, 100)).to.almostEqual(100.0000499999875);
411 });
412
413 it('should coerce to a number', function () {
414 expect(Math.hypot('Infinity', 0)).to.equal(Infinity);
415 expect(Math.hypot('3', '3', '3', '3')).to.equal(6);
416 });
417
418 it('should take more than 3 arguments', function () {
419 expect(Math.hypot(66, 66, 66)).to.almostEqual(114.3153532995459);
420 expect(Math.hypot(66, 66, 66, 66)).to.equal(132);
421 });
422
423 it('should have the right length', function () {
424 expect(Math.hypot.length).to.equal(2);
425 });
426
427 it('works for very large or small numbers', function () {
428 expect(Math.hypot(1e+300, 1e+300)).to.almostEqual(1.4142135623730952e+300);
429 expect(Math.hypot(1e-300, 1e-300)).to.almostEqual(1.4142135623730952e-300);
430 expect(Math.hypot(1e+300, 1e+300, 2, 3)).to.almostEqual(1.4142135623730952e+300);
431 });
432 });
433
434 describe('.log2()', function () {
435 if (!Object.prototype.hasOwnProperty.call(Math, 'log2')) {
436 return it('exists', function () {
437 expect(Math).to.have.property('log2');
438 });
439 }
440
441 ifFunctionsHaveNamesIt('has the right name', function () {
442 expect(Math.log2).to.have.property('name', 'log2');
443 });
444
445 it('is not enumerable', function () {
446 expect(Math).ownPropertyDescriptor('log2').to.have.property('enumerable', false);
447 });
448
449 it('has the right arity', function () {
450 expect(Math.log2).to.have.property('length', 1);
451 });
452
453 it('is correct for small numbers', function () {
454 expect(numberIsNaN(Math.log2(-1e-50))).to.equal(true);
455 });
456
457 it('is correct for edge cases', function () {
458 expect(numberIsNaN(Math.log2(NaN))).to.equal(true);
459 expect(Math.log2(+0)).to.equal(-Infinity);
460 expect(Math.log2(-0)).to.equal(-Infinity);
461 expect(isPositiveZero(Math.log2(1))).to.equal(true);
462 expect(Math.log2(Infinity)).to.equal(Infinity);
463 });
464
465 it('should have the right precision', function () {
466 expect(Math.log2(5)).to.almostEqual(2.321928094887362);
467 expect(Math.log2(32)).to.almostEqual(5);
468 });
469 });
470
471 describe('.log10', function () {
472 if (!Object.prototype.hasOwnProperty.call(Math, 'log10')) {
473 return it('exists', function () {
474 expect(Math).to.have.property('log10');
475 });
476 }
477
478 ifFunctionsHaveNamesIt('has the right name', function () {
479 expect(Math.log10).to.have.property('name', 'log10');
480 });
481
482 it('is not enumerable', function () {
483 expect(Math).ownPropertyDescriptor('log10').to.have.property('enumerable', false);
484 });
485
486 it('has the right arity', function () {
487 expect(Math.log10).to.have.property('length', 1);
488 });
489
490 it('should be correct for edge cases', function () {
491 expect(numberIsNaN(Math.log10(NaN))).to.equal(true);
492 expect(numberIsNaN(Math.log10(-1e-50))).to.equal(true);
493 expect(Math.log10(+0)).to.equal(-Infinity);
494 expect(Math.log10(-0)).to.equal(-Infinity);
495 expect(isPositiveZero(Math.log10(1))).to.equal(true);
496 expect(Math.log10(Infinity)).to.equal(Infinity);
497 });
498
499 it('should have the right precision', function () {
500 expect(Math.log10(5)).to.almostEqual(0.698970004336018);
501 expect(Math.log10(50)).to.almostEqual(1.6989700043360187);
502 });
503 });
504
505 describe('.log1p', function () {
506 if (!Object.prototype.hasOwnProperty.call(Math, 'log1p')) {
507 return it('exists', function () {
508 expect(Math).to.have.property('log1p');
509 });
510 }
511
512 ifFunctionsHaveNamesIt('has the right name', function () {
513 expect(Math.log1p).to.have.property('name', 'log1p');
514 });
515
516 it('is not enumerable', function () {
517 expect(Math).ownPropertyDescriptor('log1p').to.have.property('enumerable', false);
518 });
519
520 it('has the right arity', function () {
521 expect(Math.log1p).to.have.property('length', 1);
522 });
523
524 it('should be correct', function () {
525 expect(numberIsNaN(Math.log1p(NaN))).to.equal(true);
526 expect(numberIsNaN(Math.log1p(-1.000000001))).to.equal(true);
527 expect(Math.log1p(-1)).to.equal(-Infinity);
528 expect(isPositiveZero(Math.log1p(+0))).to.equal(true);
529 expect(isNegativeZero(Math.log1p(-0))).to.equal(true);
530 expect(Math.log1p(Infinity)).to.equal(Infinity);
531
532 expect(Math.log1p(5)).to.almostEqual(1.791759469228055);
533 expect(Math.log1p(50)).to.almostEqual(3.9318256327243257);
534 expect(Math.log1p(-1e-17)).to.equal(-1e-17);
535 expect(Math.log1p(-2e-17)).to.equal(-2e-17);
536 });
537 });
538
539 describe('.sign()', function () {
540 if (!Object.prototype.hasOwnProperty.call(Math, 'sign')) {
541 return it('exists', function () {
542 expect(Math).to.have.property('sign');
543 });
544 }
545
546 ifFunctionsHaveNamesIt('has the right name', function () {
547 expect(Math.sign).to.have.property('name', 'sign');
548 });
549
550 it('is not enumerable', function () {
551 expect(Math).ownPropertyDescriptor('sign').to.have.property('enumerable', false);
552 });
553
554 it('has the right arity', function () {
555 expect(Math.sign).to.have.property('length', 1);
556 });
557
558 it('should be correct', function () {
559 // we also verify that [[ToNumber]] is being called
560 [Infinity, 1].forEach(function (value) {
561 expect(Math.sign(value)).to.equal(1);
562 expect(Math.sign(String(value))).to.equal(1);
563 });
564 expect(Math.sign(true)).to.equal(1);
565
566 [-Infinity, -1].forEach(function (value) {
567 expect(Math.sign(value)).to.equal(-1);
568 expect(Math.sign(String(value))).to.equal(-1);
569 });
570
571 expect(isPositiveZero(Math.sign(+0))).to.equal(true);
572 expect(isPositiveZero(Math.sign('0'))).to.equal(true);
573 expect(isPositiveZero(Math.sign('+0'))).to.equal(true);
574 expect(isPositiveZero(Math.sign(''))).to.equal(true);
575 expect(isPositiveZero(Math.sign(' '))).to.equal(true);
576 expect(isPositiveZero(Math.sign(null))).to.equal(true);
577 expect(isPositiveZero(Math.sign(false))).to.equal(true);
578 expect(isNegativeZero(Math.sign(-0))).to.equal(true);
579 expect(isNegativeZero(Math.sign('-0'))).to.equal(true);
580 expect(numberIsNaN(Math.sign(NaN))).to.equal(true);
581 expect(numberIsNaN(Math.sign('NaN'))).to.equal(true);
582 expect(numberIsNaN(Math.sign(undefined))).to.equal(true);
583 });
584 });
585
586 describe('.sinh()', function () {
587 if (!Object.prototype.hasOwnProperty.call(Math, 'sinh')) {
588 return it('exists', function () {
589 expect(Math).to.have.property('sinh');
590 });
591 }
592
593 ifFunctionsHaveNamesIt('has the right name', function () {
594 expect(Math.sinh).to.have.property('name', 'sinh');
595 });
596
597 it('is not enumerable', function () {
598 expect(Math).ownPropertyDescriptor('sinh').to.have.property('enumerable', false);
599 });
600
601 it('has the right arity', function () {
602 expect(Math.sinh).to.have.property('length', 1);
603 });
604
605 it('should be correct', function () {
606 expect(numberIsNaN(Math.sinh(NaN))).to.equal(true);
607 expect(isPositiveZero(Math.sinh(+0))).to.equal(true);
608 expect(isNegativeZero(Math.sinh(-0))).to.equal(true);
609 expect(Math.sinh(Infinity)).to.equal(Infinity);
610 expect(Math.sinh(-Infinity)).to.equal(-Infinity);
611 expect(Math.sinh(-5)).to.almostEqual(-74.20321057778875);
612 expect(Math.sinh(2)).to.almostEqual(3.6268604078470186);
613 expect(Math.sinh(-2e-17)).to.equal(-2e-17);
614 });
615
616 it('is correct for extreme non-infinities', function () {
617 expect(Math.sinh(710)).not.to.equal(Infinity);
618 expect(Math.sinh(710) / 1e+308).to.almostEqual(1.1169973830808557);
619 });
620 });
621
622 describe('.tanh()', function () {
623 if (!Object.prototype.hasOwnProperty.call(Math, 'tanh')) {
624 return it('exists', function () {
625 expect(Math).to.have.property('tanh');
626 });
627 }
628
629 ifFunctionsHaveNamesIt('has the right name', function () {
630 expect(Math.tanh).to.have.property('name', 'tanh');
631 });
632
633 it('is not enumerable', function () {
634 expect(Math).ownPropertyDescriptor('tanh').to.have.property('enumerable', false);
635 });
636
637 it('has the right arity', function () {
638 expect(Math.tanh).to.have.property('length', 1);
639 });
640
641 it('should be correct', function () {
642 expect(numberIsNaN(Math.tanh(NaN))).to.equal(true);
643 expect(isPositiveZero(Math.tanh(+0))).to.equal(true);
644 expect(isNegativeZero(Math.tanh(-0))).to.equal(true);
645 expect(Math.tanh(Infinity)).to.equal(1);
646 expect(Math.tanh(-Infinity)).to.equal(-1);
647 expect(Math.tanh(19)).to.almostEqual(1);
648 expect(Math.tanh(-19)).to.almostEqual(-1);
649 expect(Math.tanh(20)).to.equal(1); // JS loses precision for true value at this integer
650 expect(Math.tanh(-20)).to.equal(-1); // JS loses precision for true value at this integer
651 expect(Math.tanh(10)).to.almostEqual(0.9999999958776927);
652 expect(Math.tanh(-2e-17)).to.equal(-2e-17);
653 });
654 });
655
656 describe('.trunc()', function () {
657 if (!Object.prototype.hasOwnProperty.call(Math, 'trunc')) {
658 return it('exists', function () {
659 expect(Math).to.have.property('trunc');
660 });
661 }
662
663 ifFunctionsHaveNamesIt('has the right name', function () {
664 expect(Math.trunc).to.have.property('name', 'trunc');
665 });
666
667 it('is not enumerable', function () {
668 expect(Math).ownPropertyDescriptor('trunc').to.have.property('enumerable', false);
669 });
670
671 it('has the right arity', function () {
672 expect(Math.trunc).to.have.property('length', 1);
673 });
674
675 it('should be correct', function () {
676 expect(numberIsNaN(Math.trunc(NaN))).to.equal(true);
677 expect(isNegativeZero(Math.trunc(-0))).to.equal(true);
678 expect(isPositiveZero(Math.trunc(+0))).to.equal(true);
679 expect(Math.trunc(Infinity)).to.equal(Infinity);
680 expect(Math.trunc(-Infinity)).to.equal(-Infinity);
681 expect(Math.trunc(1.01)).to.equal(1);
682 expect(Math.trunc(1.99)).to.equal(1);
683 expect(Math.trunc(-555.555)).to.equal(-555);
684 expect(Math.trunc(-1.99)).to.equal(-1);
685 });
686
687 it('should coerce to a number immediately', function () {
688 expect(Math.trunc(valueOfIsInfinity)).to.equal(Infinity);
689 expect(numberIsNaN(Math.trunc(valueOfIsNaN))).to.equal(true);
690 });
691 });
692
693 describe('.imul()', function () {
694 if (!Object.prototype.hasOwnProperty.call(Math, 'imul')) {
695 return it('exists', function () {
696 expect(Math).to.have.property('imul');
697 });
698 }
699
700 ifFunctionsHaveNamesIt('has the right name', function () {
701 expect(Math.imul).to.have.property('name', 'imul');
702 });
703
704 it('is not enumerable', function () {
705 expect(Math).ownPropertyDescriptor('imul').to.have.property('enumerable', false);
706 });
707
708 it('has the right arity', function () {
709 expect(Math.imul).to.have.property('length', 2);
710 });
711
712 var str = 'str';
713 var obj = {};
714 var arr = [];
715
716 it('should be correct for non-numbers', function () {
717 expect(Math.imul(false, 7)).to.equal(0);
718 expect(Math.imul(7, false)).to.equal(0);
719 expect(Math.imul(false, false)).to.equal(0);
720 expect(Math.imul(true, 7)).to.equal(7);
721 expect(Math.imul(7, true)).to.equal(7);
722 expect(Math.imul(true, true)).to.equal(1);
723 expect(Math.imul(undefined, 7)).to.equal(0);
724 expect(Math.imul(7, undefined)).to.equal(0);
725 expect(Math.imul(undefined, undefined)).to.equal(0);
726 expect(Math.imul(str, 7)).to.equal(0);
727 expect(Math.imul(7, str)).to.equal(0);
728 expect(Math.imul(obj, 7)).to.equal(0);
729 expect(Math.imul(7, obj)).to.equal(0);
730 expect(Math.imul(arr, 7)).to.equal(0);
731 expect(Math.imul(7, arr)).to.equal(0);
732 });
733
734 it('should be correct for hex values', function () {
735 expect(Math.imul(0xffffffff, 5)).to.equal(-5);
736 expect(Math.imul(0xfffffffe, 5)).to.equal(-10);
737 });
738
739 it('should be correct', function () {
740 expect(Math.imul(2, 4)).to.equal(8);
741 expect(Math.imul(-1, 8)).to.equal(-8);
742 expect(Math.imul(-2, -2)).to.equal(4);
743 expect(Math.imul(-0, 7)).to.equal(0);
744 expect(Math.imul(7, -0)).to.equal(0);
745 expect(Math.imul(0.1, 7)).to.equal(0);
746 expect(Math.imul(7, 0.1)).to.equal(0);
747 expect(Math.imul(0.9, 7)).to.equal(0);
748 expect(Math.imul(7, 0.9)).to.equal(0);
749 expect(Math.imul(1.1, 7)).to.equal(7);
750 expect(Math.imul(7, 1.1)).to.equal(7);
751 expect(Math.imul(1.9, 7)).to.equal(7);
752 expect(Math.imul(7, 1.9)).to.equal(7);
753 });
754
755 it('should be correct for objects with valueOf', function () {
756 var x = {
757 x: 0,
758 valueOf: function () { this.x += 1; return this.x; }
759 };
760 expect(Math.imul(x, 1)).to.equal(1);
761 expect(Math.imul(1, x)).to.equal(2);
762 expect(Math.imul(x, 1)).to.equal(3);
763 expect(Math.imul(1, x)).to.equal(4);
764 expect(Math.imul(x, 1)).to.equal(5);
765 });
766 });
767
768 describe('.round()', function () {
769 ifFunctionsHaveNamesIt('has the right name', function () {
770 expect(Math.round).to.have.property('name', 'round');
771 });
772
773 it('is not enumerable', function () {
774 expect(Math).ownPropertyDescriptor('round').to.have.property('enumerable', false);
775 });
776
777 it('has the right arity', function () {
778 expect(Math.round).to.have.property('length', 1);
779 });
780
781 it('works for edge cases', function () {
782 expect(numberIsNaN(Math.round(NaN))).to.equal(true);
783 expect(isPositiveZero(Math.round(0))).to.equal(true);
784 expect(isNegativeZero(Math.round(-0))).to.equal(true);
785 expect(Math.round(Infinity)).to.equal(Infinity);
786 expect(Math.round(-Infinity)).to.equal(-Infinity);
787 });
788
789 it('returns 0 for (0,0.5)', function () {
790 expect(Math.round(0.5)).not.to.equal(0);
791 expect(Math.round(0.5 - (EPSILON / 4))).to.equal(0);
792 expect(Math.round(0 + (EPSILON / 4))).to.equal(0);
793 });
794
795 it('returns -0 for (-0.5,0)', function () {
796 expect(Math.round(-0.5)).to.equal(0);
797 expect(Math.round(-0.5 - (EPSILON / 3.99))).not.to.equal(0);
798 expect(isNegativeZero(Math.round(-0.5 + (EPSILON / 3.99)))).to.equal(true);
799 expect(isNegativeZero(Math.round(0 - (EPSILON / 3.99)))).to.equal(true);
800 });
801
802 it('returns 1 / Number.EPSILON + 1 for 1 / Number.EPSILON + 1', function () {
803 var inverseEpsilonPlus1 = (1 / EPSILON) + 1;
804 expect(Math.round(inverseEpsilonPlus1)).to.equal(inverseEpsilonPlus1);
805 });
806
807 it('returns 2 / Number.EPSILON - 1 for 2 / Number.EPSILON - 1', function () {
808 var twiceInverseEpsilonMinus1 = (2 / EPSILON) - 1;
809 expect(Math.round(twiceInverseEpsilonMinus1)).to.equal(twiceInverseEpsilonMinus1);
810 });
811 });
812
813 describe('.fround()', function () {
814 if (!Object.prototype.hasOwnProperty.call(Math, 'fround')) {
815 return it('exists', function () {
816 expect(Math).to.have.property('fround');
817 });
818 }
819
820 ifFunctionsHaveNamesIt('has the right name', function () {
821 expect(Math.fround).to.have.property('name', 'fround');
822 });
823
824 it('is not enumerable', function () {
825 expect(Math).ownPropertyDescriptor('fround').to.have.property('enumerable', false);
826 });
827
828 it('has the right arity', function () {
829 expect(Math.fround).to.have.property('length', 1);
830 });
831
832 // Mozilla's reference tests: https://bug900125.bugzilla.mozilla.org/attachment.cgi?id=793163
833 it('returns NaN for undefined', function () {
834 expect(numberIsNaN(Math.fround())).to.equal(true);
835 });
836
837 it('returns NaN for NaN', function () {
838 expect(numberIsNaN(Math.fround(NaN))).to.equal(true);
839 });
840
841 it('works for zeroes and infinities', function () {
842 expect(isPositiveZero(Math.fround(0))).to.equal(true);
843 expect(isPositiveZero(Math.fround({ valueOf: function () { return 0; } }))).to.equal(true);
844 expect(isNegativeZero(Math.fround(-0))).to.equal(true);
845 expect(isNegativeZero(Math.fround({ valueOf: function () { return -0; } }))).to.equal(true);
846 expect(Math.fround(Infinity)).to.equal(Infinity);
847 expect(Math.fround({ valueOf: function () { return Infinity; } })).to.equal(Infinity);
848 expect(Math.fround(-Infinity)).to.equal(-Infinity);
849 expect(Math.fround({ valueOf: function () { return -Infinity; } })).to.equal(-Infinity);
850 });
851
852 it('returns infinity for large numbers', function () {
853 expect(Math.fround(1.7976931348623157e+308)).to.equal(Infinity);
854 expect(Math.fround(-1.7976931348623157e+308)).to.equal(-Infinity);
855 expect(Math.fround(3.4028235677973366e+38)).to.equal(Infinity);
856 });
857
858 it('returns zero for really small numbers', function () {
859 expect(Number.MIN_VALUE).to.equal(5e-324);
860
861 expect(Math.fround(Number.MIN_VALUE)).to.equal(0);
862 expect(Math.fround(-Number.MIN_VALUE)).to.equal(0);
863 });
864
865 it('rounds properly', function () {
866 expect(Math.fround(3)).to.equal(3);
867 expect(Math.fround(-3)).to.equal(-3);
868 });
869
870 it('rounds properly with the max float 32', function () {
871 var maxFloat32 = 3.4028234663852886e+38;
872 expect(Math.fround(maxFloat32)).to.equal(maxFloat32);
873 expect(Math.fround(-maxFloat32)).to.equal(-maxFloat32);
874
875 // round-nearest rounds down to maxFloat32
876 expect(Math.fround(maxFloat32 + Math.pow(2, Math.pow(2, 8 - 1) - 1 - 23 - 2))).to.equal(maxFloat32);
877 });
878
879 it('rounds properly with the min float 32', function () {
880 var minFloat32 = 1.401298464324817e-45;
881 expect(Math.fround(minFloat32)).to.equal(minFloat32);
882 expect(Math.fround(-minFloat32)).to.equal(-minFloat32);
883 expect(Math.fround(minFloat32 / 2)).to.equal(0);
884 expect(Math.fround(-minFloat32 / 2)).to.equal(0);
885 expect(Math.fround((minFloat32 / 2) + Math.pow(2, -202))).to.equal(minFloat32);
886 expect(Math.fround((-minFloat32 / 2) - Math.pow(2, -202))).to.equal(-minFloat32);
887 });
888 });
889});