1 // ♓🌟 Piscēs ∷ numeric.js 
   2 // ==================================================================== 
   4 // Copyright © 2022 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 
} from "./function.js"; 
  18 import { sameValue
, toPrimitive 
} from "./value.js"; 
  24    * ※ This is an alias for Math.LN10. 
  31    * ※ This is an alias for Math.LN2. 
  38    * ※ This is an alias for Math.LOG10E. 
  45    * ※ This is an alias for Math.LOG2E. 
  52    * ※ This is an alias for Math.SQRT1_2. 
  54   SQRT1_2: RECIPROCAL_SQRT2
, 
  59    * ※ This is an alias for Math.SQRT2. 
  64    * Returns the arccos of the provided value. 
  66    * ※ This is an alias for Math.acos. 
  68    * ☡ This function does not allow big·int arguments. 
  73    * Returns the arccosh of the provided value. 
  75    * ※ This is an alias for Math.acosh. 
  77    * ☡ This function does not allow big·int arguments. 
  82    * Returns the arcsin of the provided value. 
  84    * ※ This is an alias for Math.asin. 
  86    * ☡ This function does not allow big·int arguments. 
  91    * Returns the arcsinh of the provided value. 
  93    * ※ This is an alias for Math.asinh. 
  95    * ☡ This function does not allow big·int arguments. 
 100    * Returns the arctan of the provided value. 
 102    * ※ This is an alias for Math.atan. 
 104    * ☡ This function does not allow big·int arguments. 
 109    * Returns the arctanh of the provided value. 
 111    * ※ This is an alias for Math.atanh. 
 113    * ☡ This function does not allow big·int arguments. 
 118    * Returns the cube root of the provided value. 
 120    * ※ This is an alias for Math.cbrt. 
 122    * ☡ This function does not allow big·int arguments. 
 127    * Returns the ceiling of the provided value. 
 129    * ※ This is an alias for Math.ceil. 
 131    * ☡ This function does not allow big·int arguments. 
 136    * Returns the cos of the provided value. 
 138    * ※ This is an alias for Math.cos. 
 140    * ☡ This function does not allow big·int arguments. 
 145    * Returns the cosh of the provided value. 
 147    * ※ This is an alias for Math.cosh. 
 149    * ☡ This function does not allow big·int arguments. 
 154    * Returns the Euler number raised to the provided value. 
 156    * ※ This is an alias for Math.exp. 
 158    * ☡ This function does not allow big·int arguments. 
 163    * Returns the Euler number raised to the provided value, minus one. 
 165    * ※ This is an alias for Math.expm1. 
 167    * ☡ This function does not allow big·int arguments. 
 172    * Returns the floor of the provided value. 
 174    * ※ This is an alias for Math.floor. 
 176    * ☡ This function does not allow big·int arguments. 
 181    * Returns the square root of the sum of the squares of the provided 
 184    * ※ This is an alias for Math.hypot. 
 186    * ☡ This function does not allow big·int arguments. 
 191    * Returns the ln of the provided value. 
 193    * ※ This is an alias for Math.log. 
 195    * ☡ This function does not allow big·int arguments. 
 200    * Returns the log10 of the provided value. 
 202    * ※ This is an alias for Math.log10. 
 204    * ☡ This function does not allow big·int arguments. 
 209    * Returns the ln of one plus the provided value. 
 211    * ※ This is an alias for Math.log1p. 
 213    * ☡ This function does not allow big·int arguments. 
 218    * Returns the log2 of the provided value. 
 220    * ※ This is an alias for Math.log2. 
 222    * ☡ This function does not allow big·int arguments. 
 227    * Returns a pseudo·random value in the range [0, 1). 
 229    * ※ This is an alias for Math.random. 
 234    * Returns the round of the provided value. 
 236    * ※ This is an alias for Math.round. 
 238    * ☡ This function does not allow big·int arguments. 
 243    * Returns the sinh of the provided value. 
 245    * ※ This is an alias for Math.sinh. 
 247    * ☡ This function does not allow big·int arguments. 
 252    * Returns the square root of the provided value. 
 254    * ※ This is an alias for Math.sqrt. 
 256    * ☡ This function does not allow big·int arguments. 
 261    * Returns the tan of the provided value. 
 263    * ※ This is an alias for Math.tan. 
 265    * ☡ This function does not allow big·int arguments. 
 270    * Returns the tanh of the provided value. 
 272    * ※ This is an alias for Math.tanh. 
 274    * ☡ This function does not allow big·int arguments. 
 279    * Returns the trunc of the provided value. 
 281    * ※ This is an alias for Math.trunc. 
 283    * ☡ This function does not allow big·int arguments. 
 288    * The mathematical constant π. 
 290    * ※ This is an alias for Math.PI. 
 297    * ※ This is an alias for Math.E. 
 304    * The largest number value less than infinity. 
 306    * ※ This is an alias for Number.MAX_VALUE. 
 308   MAX_VALUE: MAXIMUM_NUMBER
, 
 313    * ※ This is an alias for Number.MAX_SAFE_INTEGER. 
 315   MAX_SAFE_INTEGER: MAXIMUM_SAFE_INTEGRAL_NUMBER
, 
 318    * The smallest number value greater than negative infinity. 
 320    * ※ This is an alias for Number.MIN_VALUE. 
 322   MIN_VALUE: MINIMUM_NUMBER
, 
 327    * ※ This is an alias for Number.MIN_SAFE_INTEGER. 
 329   MIN_SAFE_INTEGER: MINIMUM_SAFE_INTEGRAL_NUMBER
, 
 334    * ※ This is an alias for Number.NEGATIVE_INFINITY. 
 341    * ※ This is an alias for Number.NaN. 
 348    * ※ This is an alias for Number.POSITIVE_INFINITY. 
 353    * The difference between 1 and the smallest number greater than 1. 
 355    * ※ This is an alias for Number.EPSILON. 
 360    * Returns whether the provided value is a finite number. 
 362    * ※ This is an alias for Number.isFinite. 
 364   isFinite: isFiniteNumber
, 
 367    * Returns whether the provided value is an integral number. 
 369    * ※ This is an alias for Number.isInteger. 
 371   isInteger: isIntegralNumber
, 
 374    * Returns whether the provided value is nan. 
 376    * ※ This is an alias for Number.isNaN. 
 381    * Returns whether the provided value is a safe integral number. 
 383    * ※ This is an alias for Number.isSafeInteger. 
 385   isSafeInteger: isSafeIntegralNumber
, 
 388 /** Positive zero. */ 
 389 export const POSITIVE_ZERO 
= 0; 
 391 /** Negative zero. */ 
 392 export const NEGATIVE_ZERO 
= -0; 
 395  * Returns the magnitude (absolute value) of the provided value. 
 397  * ※ Unlike Math.abs, this function can take big·int arguments. 
 399 export const abs 
= ($) => { 
 400   const n 
= toNumeric($); 
 401   return typeof n 
=== "bigint" 
 407     : sameValue(n
, NEGATIVE_INFINITY
) 
 416    * Returns the arctangent of the dividend of the provided values. 
 418    * ※ Unlike Math.atan2, this function can take big·int arguments. 
 419    * However, the result will always be a number. 
 424    * Returns the number of leading zeroes in the 32‐bit representation of 
 425    * the provided value. 
 427    * ※ Unlike Math.clz32, this function accepts either number or big·int 
 433    * Returns the 32‐bit float which best approximate the provided 
 436    * ※ Unlike Math.fround, this function can take big·int arguments. 
 437    * However, the result will always be a number. 
 441   const { atan2
, fround
, clz32 
} = Math
; 
 443     atan2: (y
, x
) => atan2(toNumber(y
), toNumber(x
)), 
 445       const n 
= toNumeric($); 
 447         typeof n 
=== "bigint" ? toNumber(toUintN(32, n
)) : n
, 
 450     toFloat32: ($) => fround(toNumber($)), 
 455  * Returns the highest value of the provided arguments, or negative 
 456  * infinity if no argument is provided. 
 458  * ※ Unlike Math.max, this function accepts either number or big·int 
 459  * values. All values must be of the same type, or this function will 
 462  * ☡ If no argument is supplied, the result will be a number, not a 
 465 export const max 
= (...$s
) => { 
 466   let highest 
= undefined; 
 467   for (let i 
= 0; i 
< $s
.length
; ++i
) { 
 468     // Iterate over all the numbers. 
 469     const number 
= toNumeric($s
[i
]); 
 470     if (highest 
=== undefined) { 
 471       // The current number is the first one. 
 473         // The current number is nan. 
 476         // The current number is not nan. 
 480       if (typeof highest 
!== typeof number
) { 
 481         // The type of the current number and the lowest number don’t 
 483         throw new TypeError("Piscēs: Type mismatch."); 
 484       } else if (isNan(number
)) { 
 485         // The current number is nan. 
 487       } else if (sameValue(number
, 0) && sameValue(highest
, -0)) { 
 488         // The current number is +0 and the highest number is -0. 
 490       } else if (highest 
=== undefined || number 
> highest
) { 
 491         // The current number is greater than the highest number. 
 494         // The current number is less than or equal to the lowest 
 500   return highest 
?? NEGATIVE_INFINITY
; 
 504  * Returns the lowest value of the provided arguments, or positive 
 505  * infinity if no argument is provided. 
 507  * ※ Unlike Math.min, this function accepts either number or big·int 
 508  * values. All values must be of the same type, or this function will 
 511  * ☡ If no argument is supplied, the result will be a number, not a 
 514 export const min 
= (...$s
) => { 
 515   let lowest 
= undefined; 
 516   for (let i 
= 0; i 
< $s
.length
; ++i
) { 
 517     // Iterate over all the numbers. 
 518     const number 
= toNumeric($s
[i
]); 
 519     if (lowest 
=== undefined) { 
 520       // The current number is the first one. 
 522         // The current number is nan. 
 525         // The current number is not nan. 
 529       // The current number is not the first one. 
 530       if (typeof lowest 
!== typeof number
) { 
 531         // The type of the current number and the lowest number don’t 
 533         throw new TypeError("Piscēs: Type mismatch."); 
 534       } else if (isNan(number
)) { 
 535         // The current number is nan. 
 537       } else if (sameValue(number
, -0) && sameValue(lowest
, 0)) { 
 538         // The current number is -0 and the lowest number is +0. 
 540       } else if (number 
< lowest
) { 
 541         // The current number is less than the lowest number. 
 544         // The current number is greater than or equal to the lowest 
 550   return lowest 
?? POSITIVE_INFINITY
; 
 554  * Returns a unit value with the same sign as the provided value, or 
 555  * the provided value itself if it is not a number or (potentially 
 558  * For big·ints, the return value of this function is 0n if the 
 559  * provided value is 0n, -1n if the provided value is negative, and +1n 
 562  * For numbers, the return value is nan, -0, or +0 if the provided 
 563  * value is nan, -0, or +0, respectively, and -1 if the provided value 
 564  * is negative and +1 if the provided value is positive otherwise. Note 
 565  * that positive and negative infinity will return +1 and -1 
 568  * ※ Unlike Math.sign, this function accepts either number or big·int 
 571 export const sgn 
= ($) => { 
 572   const n 
= toNumeric($); 
 573   return typeof n 
=== "bigint" 
 574     ? n 
=== 0n 
? 0n : n 
< 0n 
? -1n : 1n
 
 575     : isNan(n
) || n 
=== 0 
 577     //deno-lint-ignore no-compare-neg-zero 
 584  * Returns the result of converting the provided value to a big·int. 
 586  * ※ This method is safe to use with numbers. 
 588  * ※ This is effectively an alias for BigInt. 
 590 export const { toBigInt 
} = (() => { 
 591   const makeBigInt 
= BigInt
; 
 592   return { toBigInt: ($) => makeBigInt($) }; 
 597    * Returns the result of converting the provided value to an 
 598    * exponential notation string. 
 600    * If a second argument is provided, it gives the number of 
 601    * fractional digits to use in the mantissa. Otherwise, the smallest 
 602    * number which does not result in a reduction in precision is used. 
 604    * ※ This method is safe to use with big·ints. 
 606   toExponentialNotation
, 
 609    * Returns the result of converting the provided value to a fixed 
 610    * decimal notation string with the provided number of fractional 
 613    * ※ This method is safe to use with big·ints. 
 615   toFixedDecimalNotation
, 
 618     toExponential: numberToExponential
, 
 619     toFixed: numberToFixed
, 
 620   } = Number
.prototype; 
 621   const { toString: bigintToString 
} = BigInt
.prototype; 
 623     toExponentialNotation: ($, fractionDigits
) => { 
 624       const n 
= toNumeric($); 
 625       const f 
= toIntegralNumberOrInfinity(fractionDigits
); 
 626       if (!isFiniteNumber(f
) || f 
< 0 || f 
> 100) { 
 627         throw new RangeError( 
 628           `Piscēs: The number of fractional digits must be a finite number between 0 and 100 inclusive; got: ${f}.`, 
 631         if (typeof n 
=== "number") { 
 635             [fractionDigits 
=== undefined ? fractionDigits : f
], 
 638           const digits 
= call(bigintToString
, n
, [10]); 
 639           const { length 
} = digits
; 
 640           if (fractionDigits 
=== undefined) { 
 643               : `${digits[0]}.${substring(digits, 1)}e+${length - 1}`; 
 644           } else if (f 
=== 0) { 
 645             return `${digits[0]}e+0`; 
 647             const fractionalPart 
= toString( 
 650                   stringPadEnd(substring(digits
, 1, f 
+ 1), f
, "0"), 
 652                   digits
[f 
+ 1] || "0", 
 656             return `${digits[0]}.${fractionalPart}e+${length - 1}`; 
 661     toFixedDecimalNotation: ($, fractionDigits
) => { 
 662       const f 
= toIntegralNumberOrInfinity(fractionDigits
); 
 663       if (!isFiniteNumber(f
) || f 
< 0 || f 
> 100) { 
 664         throw new RangeError( 
 665           `Piscēs: The number of fractional digits must be a finite number between 0 and 100 inclusive; got: ${f}.`, 
 668         const n 
= toNumeric($); 
 669         if (typeof n 
=== "number") { 
 670           return call(numberToFixed
, n
, [f
]); 
 672           const digits 
= call(bigintToString
, n
, [10]); 
 675             : `${digits}.${stringRepeat("0", f)}`; 
 684    * Returns the result of converting the provided value to fit within 
 685    * the provided number of bits as a signed integer. 
 687    * ※ Unlike BigInt.asIntN, this function accepts both big·int and 
 690    * ☡ The first argument, the number of bits, must be a number. 
 695    * Returns the result of converting the provided value to fit within 
 696    * the provided number of bits as an unsigned integer. 
 698    * ※ Unlike BigInt.asUintN, this function accepts both big·int and 
 701    * ☡ The first argument, the number of bits, must be a number. 
 705   const { asIntN
, asUintN 
} = BigInt
; 
 708       const prim 
= toPrimitive($); 
 709       if (typeof prim 
=== "bigint") { 
 710         // The primitive value is a big·int. 
 711         return asIntN(n
, prim
); 
 713         // The primitive value is not a big·int. 
 714         const int = trunc(prim
); 
 715         if (!isFiniteNumber(int) || int == 0) { 
 716           // The truncated value is zero or not finite. 
 719           // The truncated value is finite. 
 720           return toNumber(asIntN(n
, toBigInt(int))); 
 725       const prim 
= toPrimitive($); 
 726       if (typeof prim 
=== "bigint") { 
 727         // The primitive value is a big·int. 
 728         return asUintN(n
, prim
); 
 730         // The primitive value is not a big·int. 
 731         const int = trunc(prim
); 
 732         if (!isFiniteNumber(int) || int == 0) { 
 733           // The truncated value is zero or not finite. 
 736           // The truncated value is finite. 
 737           return toNumber(asUintN(n
, toBigInt(int))); 
 745  * Returns the result of converting the provided number to an integral 
 748  * ※ This function will never return negative zero. 
 750 export const toIntegralNumber 
= ($) => { 
 751   const n 
= toIntegralNumberOrInfinity($); 
 752   return !isFiniteNumber(n
) || n 
== 0 ? 0 : n
; 
 756  * Returns the result of converting the provided number to an integer 
 759  * ※ Unlike the ToIntegerOrInfinity function defined in the Ecmascript 
 760  * specification, this function is safe to use with big·ints. However, 
 761  * the result will always be a number. 
 763  * ※ This function will never return negative zero. 
 765 export const toIntegralNumberOrInfinity 
= ($) => { 
 766   const integer 
= trunc(toNumber($)); 
 767   if (isNan(integer
) || integer 
== 0) { 
 768     // The provided value truncs to nan or (positive or negative) zero. 
 770   } else if (integer 
== POSITIVE_INFINITY
) { 
 771     // The provided value truncs to positive infinity. 
 772     return POSITIVE_INFINITY
; 
 773   } else if (integer 
== NEGATIVE_INFINITY
) { 
 774     // The provided value truncs to negative infinity. 
 775     return NEGATIVE_INFINITY
; 
 777     // The provided value truncs to an integer. 
 783  * Returns the result of converting the provided value to a number. 
 785  * ※ This function is safe to use with big·ints. 
 787  * ※ This is effectively a nonconstructible version of the Number 
 790 export const { toNumber 
} = (() => { 
 791   const makeNumber 
= Number
; 
 792   return { toNumber: ($) => makeNumber($) }; 
 796  * Returns the result of converting the provided value to a number or 
 799  * ※ If the result of converting the provided value to a primitive is 
 800  * not a big·int, this function will return a number. 
 802 export const toNumeric 
= ($) => { 
 803   const primValue 
= toPrimitive($, "number"); 
 804   return typeof primValue 
=== "bigint" ? primValue : +primValue
;