Skip to content

Commit

Permalink
fix: Uniformize bigint construction
Browse files Browse the repository at this point in the history
   Adds options to the bigint constructor function `math.bigint()` to
   control whether/how non-integer inputs are rounded or errors thrown,
   and whether "unsafe" values outside the range where integers can be
   uniquely represented are converted. Changes `math.numeric(x, 'bigint')`
   to call the bigint constructor configured to allow unsafe values but
   throw on non-integers (closest approximation to its previous buggy
   behavior).

   Also restores documentation generation for constructor functions,
   and initiates History sections in function doc pages.

   Resolves josdejong#3366.
   Resolves josdejong#3368.
   Resolves josdejong#3341.
  • Loading branch information
gwhitney committed Jan 31, 2025
1 parent 3be5a74 commit 37c550d
Show file tree
Hide file tree
Showing 22 changed files with 481 additions and 92 deletions.
15 changes: 12 additions & 3 deletions src/core/function/import.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,17 +45,26 @@ export function importFactory (typed, load, math, importedFactories) {
* return 'hello, ' + name + '!'
* }
* })
*
* // use the imported function and variable
* // use the imported function and variable
* math.myvalue * 2 // 84
*
* math.hello('user') // 'hello, user!'
*
* // import the npm module 'numbers'
* // (must be installed first with `npm install numbers`)
* math.import(numbers, {wrap: true})
*
* math.fibonacci(7) // returns 13
*
* See also:
*
* create, all
*
* History:
*
* v0.2 Created
* v0.7 Changed second parameter to an options object
* v2 Dropped support for direct import of a module by name
*
* @param {Object | Array} functions Object with functions to be imported.
* @param {Object} [options] Import options.
*/
Expand Down
26 changes: 21 additions & 5 deletions src/expression/parse.js
Original file line number Diff line number Diff line change
Expand Up @@ -66,19 +66,35 @@ export const createParse = /* #__PURE__ */ factory(name, dependencies, ({
* node1.compile().evaluate() // 5
*
* let scope = {a:3, b:4}
* const node2 = math.parse('a * b') // 12
* const node2 = math.parse('a * b')
* node2.evaluate(scope) // 12
* const code2 = node2.compile()
* code2.evaluate(scope) // 12
* scope.b = 5
* code2.evaluate(scope) // 15
* scope.a = 5
* code2.evaluate(scope) // 20
* code2.evaluate(scope) // 25
*
* const nodes = math.parse(['a = 3', 'b = 4', 'a * b'])
* nodes[2].compile().evaluate() // 12
* const nodes = math.parse(['a = 3', 'b = 2', 'a * b'])
* const newscope = {}
* nodes.map(node => node.compile().evaluate(newscope)) // [3, 2, 6]
*
* See also:
*
* evaluate, compile
*
* History:
*
* v0.9 Created
* v0.13 Switched to one-based indices
* v0.14 Added `[1,2;3,4]` notation for matrices
* v0.18 Dropped the `function` keyword
* v0.20 Added ternary conditional
* v0.27 Allow multi-line expressions; allow functions that receive
* unevaluated parameters (`rawArgs`)
* v3 Add object notation; allow assignments internal to other
* expressions
* v7.3 Supported binary, octal, and hexadecimal notation
*
* @param {string | string[] | Matrix} expr Expression to be parsed
* @param {{nodes: Object<string, Node>}} [options] Available options:
* - `nodes` a set of custom nodes
Expand Down
10 changes: 7 additions & 3 deletions src/function/algebra/polynomialRoot.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,17 +42,17 @@ export const createPolynomialRoot = /* #__PURE__ */ factory(name, dependencies,
* math.polynomialRoot(constant, linearCoeff, quadraticCoeff, cubicCoeff)
*
* Examples:
* // linear
* // linear
* math.polynomialRoot(6, 3) // [-2]
* math.polynomialRoot(math.complex(6,3), 3) // [-2 - i]
* math.polynomialRoot(math.complex(6,3), math.complex(2,1)) // [-3 + 0i]
* // quadratic
* // quadratic
* math.polynomialRoot(2, -3, 1) // [2, 1]
* math.polynomialRoot(8, 8, 2) // [-2]
* math.polynomialRoot(-2, 0, 1) // [1.4142135623730951, -1.4142135623730951]
* math.polynomialRoot(2, -2, 1) // [1 + i, 1 - i]
* math.polynomialRoot(math.complex(1,3), math.complex(-3, -2), 1) // [2 + i, 1 + i]
* // cubic
* // cubic
* math.polynomialRoot(-6, 11, -6, 1) // [1, 3, 2]
* math.polynomialRoot(-8, 0, 0, 1) // [-1 - 1.7320508075688774i, 2, -1 + 1.7320508075688774i]
* math.polynomialRoot(0, 8, 8, 2) // [0, -2]
Expand All @@ -61,6 +61,10 @@ export const createPolynomialRoot = /* #__PURE__ */ factory(name, dependencies,
* See also:
* cbrt, sqrt
*
* History:
*
* v11.4 Created
*
* @param {... number | Complex} coeffs
* The coefficients of the polynomial, starting with with the constant coefficent, followed
* by the linear coefficient and subsequent coefficients of increasing powers.
Expand Down
23 changes: 22 additions & 1 deletion src/function/arithmetic/log.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,13 @@ export const createLog = /* #__PURE__ */ factory(name, dependencies, ({ typed, t
* To avoid confusion with the matrix logarithm, this function does not
* apply to matrices.
*
* Note that when the value is a Fraction, then the
* base must be specified as a Fraction, and the log() will only be
* returned when the result happens to be rational. When there is an
* attempt to take a log of Fractions that would result in an irrational
* value, a TypeError against implicit conversion of BigInt to Fraction
* is thrown.
*
* Syntax:
*
* math.log(x)
Expand All @@ -34,11 +41,25 @@ export const createLog = /* #__PURE__ */ factory(name, dependencies, ({ typed, t
*
* exp, log2, log10, log1p
*
* History:
*
* v0.0.2 Created
* v0.2 Add optional base argument
* v0.3 Handle Array input
* v0.5 Handle Matrix input
* v0.16 Handle BigNumber input
* v0.21 Support negative BigNumbers
* v11 Drop Array/Matrix support in favor of explicit map of
* the scalar log function, to avoid confusion with the log
* of a matrix
* v14 Allow value and base to be Fractions, when the log is rational
*
* @param {number | BigNumber | Fraction | Complex} x
* Value for which to calculate the logarithm.
* @param {number | BigNumber | Fraction | Complex} [base=e]
* Optional base for the logarithm. If not provided, the natural
* logarithm of `x` is calculated.
* logarithm of `x` is calculated, unless x is a Fraction, in
* which case an error is thrown.
* @return {number | BigNumber | Fraction | Complex}
* Returns the logarithm of `x`
*/
Expand Down
10 changes: 8 additions & 2 deletions src/function/matrix/map.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,13 +38,19 @@ export const createMap = /* #__PURE__ */ factory(name, dependencies, ({ typed })
* // callback(value, index, Array)
* // If you want to call with only one argument, use:
* math.map([1, 2, 3], x => math.format(x)) // returns ['1', '2', '3']
* // It can also be called with 2N + 1 arguments: for N arrays
* // callback(value1, value2, index, BroadcastedArray1, BroadcastedArray2)
* // It can also be called with 2N + 1 arguments: for N arrays
* // callback(value1, value2, index, BroadcastedArray1, BroadcastedArray2)
*
* See also:
*
* filter, forEach, sort
*
* History:
*
* v0.13 Created
* v1.1 Clone the indices on each callback in case callback mutates
* v13.1 Support multiple inputs to the callback
*
* @param {Matrix | Array} x The input to iterate on.
* @param {Function} callback
* The function to call (as described above) on each entry of the input
Expand Down
5 changes: 5 additions & 0 deletions src/function/relational/compare.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,11 @@ export const createCompare = /* #__PURE__ */ factory(name, dependencies, ({ type
*
* equal, unequal, smaller, smallerEq, larger, largerEq, compareNatural, compareText
*
* History:
*
* v0.19 Created
* v4 Changed to compare strings by numerical value
*
* @param {number | BigNumber | bigint | Fraction | Unit | string | Array | Matrix} x First value to compare
* @param {number | BigNumber | bigint | Fraction | Unit | string | Array | Matrix} y Second value to compare
* @return {number | BigNumber | bigint | Fraction | Array | Matrix} Returns the result of the comparison:
Expand Down
9 changes: 8 additions & 1 deletion src/function/string/format.js
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,6 @@ export const createFormat = /* #__PURE__ */ factory(name, dependencies, ({ typed
* function formatCurrency(value) {
* // return currency notation with two digits:
* return '$' + value.toFixed(2)
*
* // you could also use math.format inside the callback:
* // return '$' + math.format(value, {notation: 'fixed', precision: 2})
* }
Expand All @@ -119,6 +118,14 @@ export const createFormat = /* #__PURE__ */ factory(name, dependencies, ({ typed
*
* print
*
* History:
*
* v0.4 Created
* v0.7 Round to a consistent number of digits (rather than decimals)
* v0.15 Added multiple number notations and configurable precision
* v3 Added support for JSON objects
* v9 Added binary, hexadecimal, and octal notations
*
* @param {*} value Value to be stringified
* @param {Object | Function | number} [options] Formatting options
* @return {string} The formatted value
Expand Down
13 changes: 10 additions & 3 deletions src/function/utils/numeric.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,13 @@ import { factory } from '../../utils/factory.js'
import { noBignumber, noFraction } from '../../utils/noop.js'

const name = 'numeric'
const dependencies = ['number', '?bignumber', '?fraction']
const dependencies = ['number', 'bigint', '?bignumber', '?fraction']

export const createNumeric = /* #__PURE__ */ factory(name, dependencies, ({ number, bignumber, fraction }) => {
export const createNumeric = /* #__PURE__ */ factory(name, dependencies, ({ number, bigint, bignumber, fraction }) => {
const validInputTypes = {
string: true,
number: true,
bigint: true,
BigNumber: true,
Fraction: true
}
Expand All @@ -19,7 +20,7 @@ export const createNumeric = /* #__PURE__ */ factory(name, dependencies, ({ numb
BigNumber: bignumber
? (x) => bignumber(x)
: noBignumber,
bigint: (x) => BigInt(x),
bigint: (x) => bigint(x, { round: 'throw', safe: false }),
Fraction: fraction
? (x) => fraction(x)
: noFraction
Expand All @@ -46,6 +47,12 @@ export const createNumeric = /* #__PURE__ */ factory(name, dependencies, ({ numb
*
* number, fraction, bignumber, bigint, string, format
*
* History:
*
* v6 Created
* v13 Added `bigint` support
* v14.2.1 Prefer mathjs `bigint()` to built-in `BigInt()`
*
* @param {string | number | BigNumber | bigint | Fraction } value
* A numeric value or a string containing a numeric value
* @param {string} outputType
Expand Down
Loading

0 comments on commit 37c550d

Please sign in to comment.