]> Lady’s Gitweb - Pisces/blob - numeric.js
Add numeric functions and unit tests
[Pisces] / numeric.js
1 // ♓🌟 Piscēs ∷ numeric.js
2 // ====================================================================
3 //
4 // Copyright © 2022 Lady [@ Lady’s Computer].
5 //
6 // This Source Code Form is subject to the terms of the Mozilla Public
7 // License, v. 2.0. If a copy of the MPL was not distributed with this
8 // file, You can obtain one at <https://mozilla.org/MPL/2.0/>.
9
10 import { sameValue, toPrimitive } from "./value.js";
11
12 export const {
13 /**
14 * ln(10).
15 *
16 * ※ This is an alias for Math.LN10.
17 */
18 LN10,
19
20 /**
21 * ln(2).
22 *
23 * ※ This is an alias for Math.LN2.
24 */
25 LN2,
26
27 /**
28 * log10(ℇ).
29 *
30 * ※ This is an alias for Math.LOG10E.
31 */
32 LOG10E: LOG10ℇ,
33
34 /**
35 * log2(ℇ).
36 *
37 * ※ This is an alias for Math.LOG2E.
38 */
39 LOG2E: LOG2ℇ,
40
41 /**
42 * sqrt(.5).
43 *
44 * ※ This is an alias for Math.SQRT1_2.
45 */
46 SQRT1_2: RECIPROCAL_SQRT2,
47
48 /**
49 * sqrt(2).
50 *
51 * ※ This is an alias for Math.SQRT2.
52 */
53 SQRT2,
54
55 /**
56 * Returns the arccos of the provided value.
57 *
58 * ※ This is an alias for Math.acos.
59 *
60 * ☡ This function does not allow big·int arguments.
61 */
62 acos: arccos,
63
64 /**
65 * Returns the arccosh of the provided value.
66 *
67 * ※ This is an alias for Math.acosh.
68 *
69 * ☡ This function does not allow big·int arguments.
70 */
71 acosh: arccosh,
72
73 /**
74 * Returns the arcsin of the provided value.
75 *
76 * ※ This is an alias for Math.asin.
77 *
78 * ☡ This function does not allow big·int arguments.
79 */
80 asin: arcsin,
81
82 /**
83 * Returns the arcsinh of the provided value.
84 *
85 * ※ This is an alias for Math.asinh.
86 *
87 * ☡ This function does not allow big·int arguments.
88 */
89 asinh: arcsinh,
90
91 /**
92 * Returns the arctan of the provided value.
93 *
94 * ※ This is an alias for Math.atan.
95 *
96 * ☡ This function does not allow big·int arguments.
97 */
98 atan: arctan,
99
100 /**
101 * Returns the arctanh of the provided value.
102 *
103 * ※ This is an alias for Math.atanh.
104 *
105 * ☡ This function does not allow big·int arguments.
106 */
107 atanh: arctanh,
108
109 /**
110 * Returns the cube root of the provided value.
111 *
112 * ※ This is an alias for Math.cbrt.
113 *
114 * ☡ This function does not allow big·int arguments.
115 */
116 cbrt,
117
118 /**
119 * Returns the ceiling of the provided value.
120 *
121 * ※ This is an alias for Math.ceil.
122 *
123 * ☡ This function does not allow big·int arguments.
124 */
125 ceil,
126
127 /**
128 * Returns the cos of the provided value.
129 *
130 * ※ This is an alias for Math.cos.
131 *
132 * ☡ This function does not allow big·int arguments.
133 */
134 cos,
135
136 /**
137 * Returns the cosh of the provided value.
138 *
139 * ※ This is an alias for Math.cosh.
140 *
141 * ☡ This function does not allow big·int arguments.
142 */
143 cosh,
144
145 /**
146 * Returns the Euler number raised to the provided value.
147 *
148 * ※ This is an alias for Math.exp.
149 *
150 * ☡ This function does not allow big·int arguments.
151 */
152 exp,
153
154 /**
155 * Returns the Euler number raised to the provided value, minus one.
156 *
157 * ※ This is an alias for Math.expm1.
158 *
159 * ☡ This function does not allow big·int arguments.
160 */
161 expm1,
162
163 /**
164 * Returns the floor of the provided value.
165 *
166 * ※ This is an alias for Math.floor.
167 *
168 * ☡ This function does not allow big·int arguments.
169 */
170 floor,
171
172 /**
173 * Returns the square root of the sum of the squares of the provided
174 * arguments.
175 *
176 * ※ This is an alias for Math.hypot.
177 *
178 * ☡ This function does not allow big·int arguments.
179 */
180 hypot,
181
182 /**
183 * Returns the ln of the provided value.
184 *
185 * ※ This is an alias for Math.log.
186 *
187 * ☡ This function does not allow big·int arguments.
188 */
189 log: ln,
190
191 /**
192 * Returns the log10 of the provided value.
193 *
194 * ※ This is an alias for Math.log10.
195 *
196 * ☡ This function does not allow big·int arguments.
197 */
198 log10,
199
200 /**
201 * Returns the ln of one plus the provided value.
202 *
203 * ※ This is an alias for Math.log1p.
204 *
205 * ☡ This function does not allow big·int arguments.
206 */
207 log1p: ln1p,
208
209 /**
210 * Returns the log2 of the provided value.
211 *
212 * ※ This is an alias for Math.log2.
213 *
214 * ☡ This function does not allow big·int arguments.
215 */
216 log2,
217
218 /**
219 * Returns a pseudo·random value in the range [0, 1).
220 *
221 * ※ This is an alias for Math.random.
222 */
223 random: rand,
224
225 /**
226 * Returns the round of the provided value.
227 *
228 * ※ This is an alias for Math.round.
229 *
230 * ☡ This function does not allow big·int arguments.
231 */
232 round,
233
234 /**
235 * Returns the sinh of the provided value.
236 *
237 * ※ This is an alias for Math.sinh.
238 *
239 * ☡ This function does not allow big·int arguments.
240 */
241 sinh,
242
243 /**
244 * Returns the square root of the provided value.
245 *
246 * ※ This is an alias for Math.sqrt.
247 *
248 * ☡ This function does not allow big·int arguments.
249 */
250 sqrt,
251
252 /**
253 * Returns the tan of the provided value.
254 *
255 * ※ This is an alias for Math.tan.
256 *
257 * ☡ This function does not allow big·int arguments.
258 */
259 tan,
260
261 /**
262 * Returns the tanh of the provided value.
263 *
264 * ※ This is an alias for Math.tanh.
265 *
266 * ☡ This function does not allow big·int arguments.
267 */
268 tanh,
269
270 /**
271 * Returns the trunc of the provided value.
272 *
273 * ※ This is an alias for Math.trunc.
274 *
275 * ☡ This function does not allow big·int arguments.
276 */
277 trunc,
278
279 /**
280 * The mathematical constant π.
281 *
282 * ※ This is an alias for Math.PI.
283 */
284 PI: Π,
285
286 /**
287 * The Euler number.
288 *
289 * ※ This is an alias for Math.E.
290 */
291 E: ℇ,
292 } = Math;
293
294 export const {
295 /**
296 * The largest number value less than infinity.
297 *
298 * ※ This is an alias for Number.MAX_VALUE.
299 */
300 MAX_VALUE: MAXIMUM_NUMBER,
301
302 /**
303 * 2**53 - 1.
304 *
305 * ※ This is an alias for Number.MAX_SAFE_INTEGER.
306 */
307 MAX_SAFE_INTEGER: MAXIMUM_SAFE_INTEGRAL_NUMBER,
308
309 /**
310 * The smallest number value greater than negative infinity.
311 *
312 * ※ This is an alias for Number.MIN_VALUE.
313 */
314 MIN_VALUE: MINIMUM_NUMBER,
315
316 /**
317 * -(2**53 - 1).
318 *
319 * ※ This is an alias for Number.MIN_SAFE_INTEGER.
320 */
321 MIN_SAFE_INTEGER: MINIMUM_SAFE_INTEGRAL_NUMBER,
322
323 /**
324 * Negative infinity.
325 *
326 * ※ This is an alias for Number.NEGATIVE_INFINITY.
327 */
328 NEGATIVE_INFINITY,
329
330 /**
331 * Nan.
332 *
333 * ※ This is an alias for Number.NaN.
334 */
335 NaN: NAN,
336
337 /**
338 * Positive infinity.
339 *
340 * ※ This is an alias for Number.POSITIVE_INFINITY.
341 */
342 POSITIVE_INFINITY,
343
344 /**
345 * The difference between 1 and the smallest number greater than 1.
346 *
347 * ※ This is an alias for Number.EPSILON.
348 */
349 EPSILON: Ε,
350
351 /**
352 * Returns whether the provided value is a finite number.
353 *
354 * ※ This is an alias for Number.isFinite.
355 */
356 isFinite: isFiniteNumber,
357
358 /**
359 * Returns whether the provided value is an integral number.
360 *
361 * ※ This is an alias for Number.isInteger.
362 */
363 isInteger: isIntegralNumber,
364
365 /**
366 * Returns whether the provided value is nan.
367 *
368 * ※ This is an alias for Number.isNaN.
369 */
370 isNaN: isNan,
371
372 /**
373 * Returns whether the provided value is a safe integral number.
374 *
375 * ※ This is an alias for Number.isSafeInteger.
376 */
377 isSafeInteger: isSafeIntegralNumber,
378 } = Number;
379
380 /**
381 * Returns the magnitude (absolute value) of the provided value.
382 *
383 * ※ Unlike Math.abs, this function can take big·int arguments.
384 */
385 export const abs = ($) => {
386 const n = toNumeric($);
387 return typeof n === "bigint"
388 ? n < 0n ? -n : n
389 : isNan(n)
390 ? NAN
391 : sameValue(n, -0)
392 ? 0
393 : sameValue(n, NEGATIVE_INFINITY)
394 ? POSITIVE_INFINITY
395 : n < 0
396 ? -n
397 : n;
398 };
399
400 export const {
401 /**
402 * Returns the arctangent of the dividend of the provided values.
403 *
404 * ※ Unlike Math.atan2, this function can take big·int arguments.
405 * However, the result will always be a number.
406 */
407 atan2,
408
409 /**
410 * Returns the number of leading zeroes in the 32‐bit representation of
411 * the provided value.
412 *
413 * ※ Unlike Math.clz32, this function accepts either number or big·int
414 * values.
415 */
416 clz32,
417
418 /**
419 * Returns the 32‐bit float which best approximate the provided
420 * value.
421 *
422 * ※ Unlike Math.fround, this function can take big·int arguments.
423 * However, the result will always be a number.
424 */
425 toFloat32,
426 } = (() => {
427 const { atan2, fround, clz32 } = Math;
428 return {
429 atan2: (y, x) => atan2(toNumber(y), toNumber(x)),
430 clz32: ($) => {
431 const n = toNumeric($);
432 return clz32(
433 typeof n === "bigint" ? toNumber(toUintN(32, n)) : n,
434 );
435 },
436 toFloat32: ($) => fround(toNumber($)),
437 };
438 })();
439
440 /**
441 * Returns the highest value of the provided arguments, or negative
442 * infinity if no argument is provided.
443 *
444 * ※ Unlike Math.max, this function accepts either number or big·int
445 * values. All values must be of the same type, or this function will
446 * throw an error.
447 *
448 * ☡ If no argument is supplied, the result will be a number, not a
449 * big·int.
450 */
451 export const max = (...$s) => {
452 let highest = undefined;
453 for (let i = 0; i < $s.length; ++i) {
454 // Iterate over all the numbers.
455 const number = toNumeric($s[i]);
456 if (highest === undefined) {
457 // The current number is the first one.
458 if (isNan(number)) {
459 // The current number is nan.
460 return NAN;
461 } else {
462 // The current number is not nan.
463 highest = number;
464 }
465 } else {
466 if (typeof highest !== typeof number) {
467 // The type of the current number and the lowest number don’t
468 // match.
469 throw new TypeError("Piscēs: Type mismatch.");
470 } else if (isNan(number)) {
471 // The current number is nan.
472 return NAN;
473 } else if (sameValue(number, 0) && sameValue(highest, -0)) {
474 // The current number is +0 and the highest number is -0.
475 highest = 0;
476 } else if (highest === undefined || number > highest) {
477 // The current number is greater than the highest number.
478 highest = number;
479 } else {
480 // The current number is less than or equal to the lowest
481 // number.
482 /* do nothing */
483 }
484 }
485 }
486 return highest ?? NEGATIVE_INFINITY;
487 };
488
489 /**
490 * Returns the lowest value of the provided arguments, or positive
491 * infinity if no argument is provided.
492 *
493 * ※ Unlike Math.min, this function accepts either number or big·int
494 * values. All values must be of the same type, or this function will
495 * throw an error.
496 *
497 * ☡ If no argument is supplied, the result will be a number, not a
498 * big·int.
499 */
500 export const min = (...$s) => {
501 let lowest = undefined;
502 for (let i = 0; i < $s.length; ++i) {
503 // Iterate over all the numbers.
504 const number = toNumeric($s[i]);
505 if (lowest === undefined) {
506 // The current number is the first one.
507 if (isNan(number)) {
508 // The current number is nan.
509 return NAN;
510 } else {
511 // The current number is not nan.
512 lowest = number;
513 }
514 } else {
515 // The current number is not the first one.
516 if (typeof lowest !== typeof number) {
517 // The type of the current number and the lowest number don’t
518 // match.
519 throw new TypeError("Piscēs: Type mismatch.");
520 } else if (isNan(number)) {
521 // The current number is nan.
522 return NAN;
523 } else if (sameValue(number, -0) && sameValue(lowest, 0)) {
524 // The current number is -0 and the lowest number is +0.
525 lowest = -0;
526 } else if (number < lowest) {
527 // The current number is less than the lowest number.
528 lowest = number;
529 } else {
530 // The current number is greater than or equal to the lowest
531 // number.
532 /* do nothing */
533 }
534 }
535 }
536 return lowest ?? POSITIVE_INFINITY;
537 };
538
539 /**
540 * Returns a unit value with the same sign as the provided value, or
541 * the provided value itself if it is not a number or (potentially
542 * signed) zero.
543 *
544 * For big·ints, the return value of this function is 0n if the
545 * provided value is 0n, -1n if the provided value is negative, and +1n
546 * otherwise.
547 *
548 * For numbers, the return value is nan, -0, or +0 if the provided
549 * value is nan, -0, or +0, respectively, and -1 if the provided value
550 * is negative and +1 if the provided value is positive otherwise. Note
551 * that positive and negative infinity will return +1 and -1
552 * respectively.
553 *
554 * ※ Unlike Math.sign, this function accepts either number or big·int
555 * values.
556 */
557 export const sgn = ($) => {
558 const n = toNumeric($);
559 return typeof n === "bigint"
560 ? n === 0n ? 0n : n < 0n ? -1n : 1n
561 : isNan(n) || n === 0
562 ? n
563 : //deno-lint-ignore no-compare-neg-zero
564 n < -0
565 ? -1
566 : 1;
567 };
568
569 /**
570 * Returns the result of converting the provided value to a big·int.
571 *
572 * ※ This method is safe to use with numbers.
573 *
574 * ※ This is effectively an alias for BigInt.
575 */
576 export const { toBigInt } = (() => {
577 const makeBigInt = BigInt;
578 return { toBigInt: ($) => makeBigInt($) };
579 })();
580
581 export const {
582 /**
583 * Returns the result of converting the provided value to fit within
584 * the provided number of bits as a signed integer.
585 *
586 * ※ Unlike BigInt.asIntN, this function accepts both big·int and
587 * number values.
588 *
589 * ☡ The first argument, the number of bits, must be a number.
590 */
591 toIntN,
592
593 /**
594 * Returns the result of converting the provided value to fit within
595 * the provided number of bits as an unsigned integer.
596 *
597 * ※ Unlike BigInt.asUintN, this function accepts both big·int and
598 * number values.
599 *
600 * ☡ The first argument, the number of bits, must be a number.
601 */
602 toUintN,
603 } = (() => {
604 const { asIntN, asUintN } = BigInt;
605 return {
606 toIntN: (n, $) => {
607 const prim = toPrimitive($);
608 const big·int = toBigInt(prim);
609 const intN = asIntN(n, big·int);
610 return typeof prim === "bigint" ? intN : toNumber(intN);
611 },
612 toUintN: (n, $) => {
613 const prim = toPrimitive($);
614 const big·int = toBigInt(prim);
615 const uintN = asUintN(n, big·int);
616 return typeof prim === "bigint" ? uintN : toNumber(uintN);
617 },
618 };
619 })();
620
621 /**
622 * Returns the result of converting the provided value to a number.
623 *
624 * ※ This method is safe to use with big·ints.
625 *
626 * ※ This is effectively a nonconstructible version of the Number
627 * constructor.
628 */
629 export const { toNumber } = (() => {
630 const makeNumber = Number;
631 return { toNumber: ($) => makeNumber($) };
632 })();
633
634 /**
635 * Returns the result of converting the provided value to a number or
636 * big·int.
637 *
638 * ※ If the result of converting the provided value to a primitive is
639 * not a big·int, this function will return a number.
640 */
641 export const toNumeric = ($) => {
642 const primValue = toPrimitive($, "number");
643 return typeof primValue === "bigint" ? primValue : +primValue;
644 };
This page took 0.106531 seconds and 5 git commands to generate.