1 // ♓🌟 Piscēs ∷ numeric.js
2 // ====================================================================
4 // Copyright © 2022–2023 Lady [@ Lady’s Computer].
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/>.
10 import { call
, createArrowFunction
} from "./function.js";
27 * Returns the magnitude (absolute value) of the provided value.
29 * ※ Unlike `Math.abs`, this function can take big·int arguments.
31 export const abs
= ($) => {
32 const n
= toNumeric($);
33 return typeof n
=== "bigint"
39 : sameValue(n
, NEGATIVE_INFINITY
)
47 * Returns the arccos of the provided value.
49 * ※ This function is effectively an alias for `Math.acos`.
51 * ☡ This function does not allow big·int arguments.
53 export const arccos
= createArrowFunction(
59 * Returns the arccosh of the provided value.
61 * ※ This function is effectively an alias for `Math.acosh`.
63 * ☡ This function does not allow big·int arguments.
65 export const arccosh
= createArrowFunction(
71 * Returns the arcsin of the provided value.
73 * ※ This function is effectively an alias for `Math.asin`.
75 * ☡ This function does not allow big·int arguments.
77 export const arcsin
= createArrowFunction(
83 * Returns the arcsinh of the provided value.
85 * ※ This function is effectively an alias for `Math.asinh`.
87 * ☡ This function does not allow big·int arguments.
89 export const arcsinh
= createArrowFunction(
95 * Returns the arctan of the provided value.
97 * ※ This function is effectively an alias for `Math.atan`.
99 * ☡ This function does not allow big·int arguments.
101 export const arctan
= createArrowFunction(
108 * Returns the arctangent of the dividend of the provided values.
110 * ※ Unlike `Math.atan2`, this function can take big·int arguments.
111 * However, the result will always be a number.
116 * Returns the number of leading zeroes in the 32‐bit representation
117 * of the provided value.
119 * ※ Unlike `Math.clz32`, this function accepts either number or
125 * Returns the 32‐bit float which best approximate the provided
128 * ※ Unlike `Math.fround`, this function can take big·int arguments.
129 * However, the result will always be a number.
133 const { atan2
, fround
, clz32
} = Math
;
135 arctan2
: (y
, x
) => atan2(toNumber(y
), toNumber(x
)),
137 const n
= toNumeric($);
139 typeof n
=== "bigint"
140 ? toNumber(toUnsignedIntegralNumeric(32, n
))
144 toFloat32
: ($) => fround(toNumber($)),
149 * Returns the arctanh of the provided value.
151 * ※ This function is effectively an alias for `Math.atanh`.
153 * ☡ This function does not allow big·int arguments.
155 export const arctanh
= createArrowFunction(
161 * Returns the cube root of the provided value.
163 * ※ This function is effectively an alias for `Math.cbrt`.
165 * ☡ This function does not allow big·int arguments.
167 export const cbrt
= createArrowFunction(Math
.cbrt
);
170 * Returns the ceiling of the provided value.
172 * ※ This function is effectively an alias for `Math.ceil`.
174 * ☡ This function does not allow big·int arguments.
176 export const ceil
= createArrowFunction(Math
.ceil
);
179 * Returns the cos of the provided value.
181 * ※ This function is effectively an alias for `Math.cos`.
183 * ☡ This function does not allow big·int arguments.
185 export const cos
= createArrowFunction(Math
.cos
);
188 * Returns the cosh of the provided value.
190 * ※ This function is effectively an alias for `Math.cosh`.
192 * ☡ This function does not allow big·int arguments.
194 export const cosh
= createArrowFunction(Math
.cosh
);
197 * Returns the Euler number raised to the provided value.
199 * ※ This function is effectively an alias for `Math.exp`.
201 * ☡ This function does not allow big·int arguments.
203 export const exp
= createArrowFunction(Math
.exp
);
206 * Returns the Euler number raised to the provided value, minus one.
208 * ※ This function is effectively an alias for `Math.expm1`.
210 * ☡ This function does not allow big·int arguments.
212 export const expm1
= createArrowFunction(Math
.expm1
);
215 * Returns the floor of the provided value.
217 * ※ This function is effectively an alias for `Math.floor`.
219 * ☡ This function does not allow big·int arguments.
221 export const floor
= createArrowFunction(Math
.floor
);
224 * Returns the square root of the sum of the squares of the provided
227 * ※ This function is effectively an alias for `Math.hypot`.
229 * ☡ This function does not allow big·int arguments.
231 export const hypot
= createArrowFunction(Math
.hypot
);
234 * Returns whether the provided value is a finite number.
236 * ※ This function is effectively an alias for `Number.isFinite`.
238 export const isFiniteNumber
= createArrowFunction(
240 { name
: "isFiniteNumber" },
244 * Returns whether the provided value is an integral number.
246 * ※ This function is effectively an alias for `Number.isInteger`.
248 export const isIntegralNumber
= createArrowFunction(
250 { name
: "isIntegralNumber" },
254 * Returns whether the provided value is nan.
256 * ※ This function is effectively an alias for `Number.isNaN`.
258 export const isNan
= createArrowFunction(
264 * Returns whether the provided value is a safe integral number.
266 * ※ This function is effectively an alias for `Number.isSafeInteger`.
268 export const isSafeIntegralNumber
= createArrowFunction(
269 Number
.isSafeInteger
,
270 { name
: "isSafeIntegralNumber" },
274 * Returns the ln of the provided value.
276 * ※ This function is effectively an alias for `Math.log`.
278 * ☡ This function does not allow big·int arguments.
280 export const ln
= createArrowFunction(Math
.log
, { name
: "ln" });
283 * Returns the ln of one plus the provided value.
285 * ※ This function is effectively an alias for `Math.log1p`.
287 * ☡ This function does not allow big·int arguments.
289 export const ln1p
= createArrowFunction(Math
.log1p
, { name
: "ln1p" });
292 * Returns the log10 of the provided value.
294 * ※ This function is effectively an alias for `Math.log10`.
296 * ☡ This function does not allow big·int arguments.
298 export const log10
= createArrowFunction(Math
.log10
);
301 * Returns the log2 of the provided value.
303 * ※ This function is effectively an alias for `Math.log2`.
305 * ☡ This function does not allow big·int arguments.
307 export const log2
= createArrowFunction(Math
.log2
);
310 * Returns the highest value of the provided arguments, or negative
311 * infinity if no argument is provided.
313 * ※ Unlike `Math.max`, this function accepts either number or big·int
314 * values. All values must be of the same type, or this function will
317 * ☡ If no argument is supplied, the result will be a number, not a
320 export const max
= Object
.defineProperties((...$s
) => {
321 let highest
= undefined;
322 for (let i
= 0; i
< $s
.length
; ++i
) {
323 // Iterate over all the numbers.
324 const number
= toNumeric($s
[i
]);
325 if (highest
=== undefined) {
326 // The current number is the first one.
328 // The current number is nan.
331 // The current number is not nan.
335 if (typeof highest
!== typeof number
) {
336 // The type of the current number and the lowest number don’t
338 throw new TypeError("Piscēs: Type mismatch.");
339 } else if (isNan(number
)) {
340 // The current number is nan.
342 } else if (sameValue(number
, 0) && sameValue(highest
, -0)) {
343 // The current number is +0 and the highest number is -0.
345 } else if (highest
=== undefined || number
> highest
) {
346 // The current number is greater than the highest number.
349 // The current number is less than or equal to the lowest
355 return highest
?? NEGATIVE_INFINITY
;
356 }, { name
: { value
: "max" }, length
: { value
: 2 } });
359 * Returns the lowest value of the provided arguments, or positive
360 * infinity if no argument is provided.
362 * ※ Unlike `Math.min`, this function accepts either number or big·int
363 * values. All values must be of the same type, or this function will
366 * ☡ If no argument is supplied, the result will be a number, not a
369 export const min
= Object
.defineProperties((...$s
) => {
370 let lowest
= undefined;
371 for (let i
= 0; i
< $s
.length
; ++i
) {
372 // Iterate over all the numbers.
373 const number
= toNumeric($s
[i
]);
374 if (lowest
=== undefined) {
375 // The current number is the first one.
377 // The current number is nan.
380 // The current number is not nan.
384 // The current number is not the first one.
385 if (typeof lowest
!== typeof number
) {
386 // The type of the current number and the lowest number don’t
388 throw new TypeError("Piscēs: Type mismatch.");
389 } else if (isNan(number
)) {
390 // The current number is nan.
392 } else if (sameValue(number
, -0) && sameValue(lowest
, 0)) {
393 // The current number is -0 and the lowest number is +0.
395 } else if (number
< lowest
) {
396 // The current number is less than the lowest number.
399 // The current number is greater than or equal to the lowest
405 return lowest
?? POSITIVE_INFINITY
;
406 }, { name
: { value
: "min" }, length
: { value
: 2 } });
409 * Returns a pseudo·random value in the range [0, 1).
411 * ※ This function is effectively an alias for `Math.random`.
413 export const rand
= createArrowFunction(
419 * Returns the round of the provided value.
421 * ※ This function is effectively an alias for `Math.round`.
423 * ☡ This function does not allow big·int arguments.
425 export const round
= createArrowFunction(Math
.round
);
428 * Returns a unit value with the same sign as the provided value, or
429 * the provided value itself if it is not a number or (potentially
432 * For big·ints, the return value of this function is 0n if the
433 * provided value is 0n, −1n if the provided value is negative, and +1n
436 * For numbers, the return value is nan, −0, or +0 if the provided
437 * value is nan, −0, or +0, respectively, and −1 if the provided value
438 * is negative and +1 if the provided value is positive otherwise. Note
439 * that positive and negative infinity will return +1 and −1
442 * ※ Unlike `Math.sign`, this function accepts either number or
445 export const sgn
= ($) => {
446 const n
= toNumeric($);
447 return typeof n
=== "bigint"
448 ? n
=== 0n
? 0n
: n
< 0n
? -1n
: 1n
449 : isNan(n
) || n
=== 0
451 //deno-lint-ignore no-compare-neg-zero
458 * Returns the sin of the provided value.
460 * ※ This function is effectively an alias for `Math.sin`.
462 * ☡ This function does not allow big·int arguments.
464 export const sin
= createArrowFunction(Math
.sin
);
467 * Returns the sinh of the provided value.
469 * ※ This function is effectively an alias for `Math.sinh`.
471 * ☡ This function does not allow big·int arguments.
473 export const sinh
= createArrowFunction(Math
.sinh
);
476 * Returns the square root of the provided value.
478 * ※ This function is effectively an alias for `Math.sqrt`.
480 * ☡ This function does not allow big·int arguments.
482 export const sqrt
= createArrowFunction(Math
.sqrt
);
485 * Returns the tan of the provided value.
487 * ※ This function is effectively an alias for `Math.tan`.
489 * ☡ This function does not allow big·int arguments.
491 export const tan
= createArrowFunction(Math
.tan
);
494 * Returns the tanh of the provided value.
496 * ※ This function is effectively an alias for `Math.tanh`.
498 * ☡ This function does not allow big·int arguments.
500 export const tanh
= createArrowFunction(Math
.tanh
);
503 * Returns the result of converting the provided value to a big·int.
505 * ※ This method is safe to use with numbers.
507 * ※ This is effectively an alias for `BigInt`.
509 export const { toBigInt
} = (() => {
510 const makeBigInt
= BigInt
;
511 return { toBigInt
: ($) => makeBigInt($) };
516 * Returns the result of converting the provided value to an
517 * exponential notation string.
519 * If a second argument is provided, it gives the number of
520 * fractional digits to use in the mantissa. Otherwise, the smallest
521 * number which does not result in a reduction in precision is used.
523 * ※ This method is safe to use with big·ints.
525 toExponentialNotation
,
528 * Returns the result of converting the provided value to a fixed
529 * decimal notation string with the provided number of fractional
532 * ※ This method is safe to use with big·ints.
534 toFixedDecimalNotation
,
537 toExponential
: numberToExponential
,
538 toFixed
: numberToFixed
,
539 } = Number
.prototype;
540 const { toString
: bigintToString
} = BigInt
.prototype;
542 toExponentialNotation
: ($, fractionDigits
) => {
543 const n
= toNumeric($);
544 const f
= toIntegralNumberOrInfinity(fractionDigits
);
545 if (!isFiniteNumber(f
) || f
< 0 || f
> 100) {
546 throw new RangeError(
547 `Piscēs: The number of fractional digits must be a finite number between 0 and 100 inclusive; got: ${f}.`,
550 if (typeof n
=== "number") {
554 [fractionDigits
=== undefined ? fractionDigits
: f
],
557 const digits
= call(bigintToString
, n
, [10]);
558 const { length
} = digits
;
559 if (fractionDigits
=== undefined) {
562 : `${digits[0]}.${substring(digits, 1)}e+${length - 1}`;
563 } else if (f
=== 0) {
564 return `${digits[0]}e+0`;
566 const fractionalPart
= toString(
569 stringPadEnd(substring(digits
, 1, f
+ 1), f
, "0"),
571 digits
[f
+ 1] || "0",
575 return `${digits[0]}.${fractionalPart}e+${length - 1}`;
580 toFixedDecimalNotation
: ($, fractionDigits
) => {
581 const f
= toIntegralNumberOrInfinity(fractionDigits
);
582 if (!isFiniteNumber(f
) || f
< 0 || f
> 100) {
583 throw new RangeError(
584 `Piscēs: The number of fractional digits must be a finite number between 0 and 100 inclusive; got: ${f}.`,
587 const n
= toNumeric($);
588 if (typeof n
=== "number") {
589 return call(numberToFixed
, n
, [f
]);
591 const digits
= call(bigintToString
, n
, [10]);
594 : `${digits}.${stringRepeat("0", f)}`;
602 * Returns the result of converting the provided number to an integral
605 * ※ This function will never return negative zero.
607 export const toIntegralNumber
= ($) => {
608 const n
= toIntegralNumberOrInfinity($);
609 return !isFiniteNumber(n
) || n
== 0 ? 0 : n
;
613 * Returns the result of converting the provided number to an integer
616 * ※ Unlike the ToIntegerOrInfinity function defined in the Ecmascript
617 * specification, this function is safe to use with big·ints. However,
618 * the result will always be a number.
620 * ※ This function will never return negative zero.
622 export const toIntegralNumberOrInfinity
= ($) => {
623 const integer
= trunc(toNumber($));
624 if (isNan(integer
) || integer
== 0) {
625 // The provided value truncs to nan or (positive or negative) zero.
627 } else if (integer
== POSITIVE_INFINITY
) {
628 // The provided value truncs to positive infinity.
629 return POSITIVE_INFINITY
;
630 } else if (integer
== NEGATIVE_INFINITY
) {
631 // The provided value truncs to negative infinity.
632 return NEGATIVE_INFINITY
;
634 // The provided value truncs to an integer.
640 * Returns the result of converting the provided value to a number.
642 * ※ This function is safe to use with big·ints.
644 * ※ This is effectively a nonconstructible version of the `Number`
647 export const { toNumber
} = (() => {
648 const makeNumber
= Number
;
649 return { toNumber
: ($) => makeNumber($) };
653 * Returns the result of converting the provided value to a number or
656 * ※ If the result of converting the provided value to a primitive is
657 * not a big·int, this function will return a number.
659 export const toNumeric
= ($) => {
660 const primValue
= toPrimitive($, "number");
661 return typeof primValue
=== "bigint" ? primValue
: +primValue
;
666 * Returns the result of converting the provided value to fit within
667 * the provided number of bits as a signed integer.
669 * ※ Unlike `BigInt.asIntN`, this function accepts both big·int and
672 * ☡ The first argument, the number of bits, must be a number.
674 toSignedIntegralNumeric
,
677 * Returns the result of converting the provided value to fit within
678 * the provided number of bits as an unsigned integer.
680 * ※ Unlike `BigInt.asUintN`, this function accepts both big·int and
683 * ☡ The first argument, the number of bits, must be a number.
685 toUnsignedIntegralNumeric
,
687 const { asIntN
, asUintN
} = BigInt
;
689 toSignedIntegralNumeric
: (n
, $) => {
690 const prim
= toPrimitive($);
691 if (typeof prim
=== "bigint") {
692 // The primitive value is a big·int.
693 return asIntN(n
, prim
);
695 // The primitive value is not a big·int.
696 const int = trunc(prim
);
697 if (!isFiniteNumber(int) || int == 0) {
698 // The truncated value is zero or not finite.
701 // The truncated value is finite.
702 return toNumber(asIntN(n
, toBigInt(int)));
706 toUnsignedIntegralNumeric
: (n
, $) => {
707 const prim
= toPrimitive($);
708 if (typeof prim
=== "bigint") {
709 // The primitive value is a big·int.
710 return asUintN(n
, prim
);
712 // The primitive value is not a big·int.
713 const int = trunc(prim
);
714 if (!isFiniteNumber(int) || int == 0) {
715 // The truncated value is zero or not finite.
718 // The truncated value is finite.
719 return toNumber(asUintN(n
, toBigInt(int)));
727 * Returns the trunc of the provided value.
729 * ※ This function is effectively an alias for `Math.trunc`.
731 * ☡ This function does not allow big·int arguments.
733 export const trunc
= createArrowFunction(Math
.trunc
);