Skip to content

Commit

Permalink
Merge branch 'develop'
Browse files Browse the repository at this point in the history
  • Loading branch information
josdejong committed May 31, 2024
2 parents 3985417 + 247e605 commit b0105a7
Show file tree
Hide file tree
Showing 323 changed files with 7,569 additions and 15,442 deletions.
4 changes: 4 additions & 0 deletions .browserslistrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Test out at: https://browsersl.ist/

fully supports es6 and fully supports bigint
not dead
3 changes: 2 additions & 1 deletion .eslintrc.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ module.exports = {
env: {
browser: true,
es2021: true,
node: true
node: true,
mocha: true
},
extends: ['eslint:recommended'],
parserOptions: {
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/build.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ jobs:

strategy:
matrix:
node-version: [18.x, 20.x]
node-version: [18.x, 20.x, 22.x]

steps:
- uses: actions/checkout@v4
Expand Down
19 changes: 19 additions & 0 deletions HISTORY.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,24 @@
# History

# 2024-05-31, 13.0.0

Breaking changes:

- Change `isZero`, `isPositive`, and `isNegative` to respect `config.epsilon`
(#3139, #2838).
- Change the behavior of the internal `nearlyEqual` to align with Python and
Julia (#3152, #2838)
- Upgrade to `[email protected]`,
see https://github.com/rawify/Fraction.js/issues/68.

Non-breaking changes:

- Implemented support for `bigint` (#3207, #3207)
- Implemented a new config option `config.numberFallback` needed for `bigint`
(#3207).
- Internal: refactored tooling to ES modules and upgraded all devDependencies.


# 2024-05-31, 12.4.3

- Fix: serialization of Units without a value, see #1240.
Expand Down
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ Math.js is an extensive math library for JavaScript and Node.js. It features a f

## Features

- Supports numbers, big numbers, complex numbers, fractions, units, strings, arrays, and matrices.
- Supports numbers, bignumbers, bigints, complex numbers, fractions, units, strings, arrays, and matrices.
- Is compatible with JavaScript's built-in Math library.
- Contains a flexible expression parser.
- Does symbolic computation.
Expand Down Expand Up @@ -118,13 +118,13 @@ The code of `mathjs` is written in ES modules, and requires all files to have a

What mathjs tries to achieve is to offer an environment where you can do calculations with mixed data types,
like multiplying a regular `number` with a `Complex` number or a `BigNumber`, and work with all of those in matrices.
Mathjs also allows to add a new data type, like say `BigInt`, with little effort.
Mathjs also allows to add a new data type with little effort.

The solution that mathjs uses has two main ingredients:

- **Typed functions**. All functions are created using [`typed-function`](https://github.com/josdejong/typed-function/). This makes it easier to (dynamically) create and extend a single function with new data types, automatically do type conversions on function inputs, etc. So, if you create function multiply for two `number`s, you can extend it with support for multiplying two `BigInts`. If you define a conversion from `BigInt` to `number`, the typed-function will automatically allow you to multiply a `BigInt` with a `number`.
- **Typed functions**. All functions are created using [`typed-function`](https://github.com/josdejong/typed-function/). This makes it easier to (dynamically) create and extend a single function with new data types, automatically do type conversions on function inputs, etc. So, if you create function multiply for two `number`s, you can extend it with support for multiplying your own data type, say `MyDecimal`. If you define a conversion from `MyDecimal` to `number`, the typed-function will automatically allow you to multiply a `MyDecimal` with a `number`.

- **Dependency injection**. When we have a function `multiply` with support for `BigInt`, thanks to the dependency injection, other functions using `multiply` under the hood, like `prod`, will automatically support `BigInt` too. This also works the other way around: if you don't need the heavyweight `multiply` (which supports BigNumbers, matrices, etc), and you just need a plain and simple number support, you can use a lightweight implementation of `multiply` just for numbers, and inject that in `prod` and other functions.
- **Dependency injection**. When we have a function `multiply` with support for `MyDecimal`, thanks to the dependency injection, other functions using `multiply` under the hood, like `prod`, will automatically support `MyDecimal` too. This also works the other way around: if you don't need the heavyweight `multiply` (which supports BigNumbers, matrices, etc), and you just need a plain and simple number support, you can use a lightweight implementation of `multiply` just for numbers, and inject that in `prod` and other functions.

At the lowest level, mathjs has immutable factory functions which create immutable functions. The core function `math.create(...)` creates a new instance having functions created from all passed factory functions. A mathjs instance is a collection of created functions. It contains a function like `math.import` to allow extending the instance with new functions, which can then be used in the expression parser.

Expand Down
3 changes: 0 additions & 3 deletions dist/math.js

This file was deleted.

3 changes: 0 additions & 3 deletions dist/math.min.js

This file was deleted.

3 changes: 0 additions & 3 deletions dist/package.json

This file was deleted.

47 changes: 30 additions & 17 deletions docs/core/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ import { create, all } from 'mathjs'

// create a mathjs instance with configuration
const config = {
epsilon: 1e-12,
relTol: 1e-12,
absTol: 1e-15,
matrix: 'Matrix',
number: 'number',
precision: 64,
Expand All @@ -28,10 +29,14 @@ math.config({

The following configuration options are available:

- `epsilon`. The minimum relative difference used to test equality between two
- `relTol`. The minimum relative difference used to test equality between two
compared values. This value is used by all relational functions.
Default value is `1e-12`.

- `absTol`. The minimum absolute difference used to test equality between two
compared values. This value is used by all relational functions.
Default value is `1e-15`.

- `matrix`. The default type of matrix output for functions.
Available values are: `'Matrix'` (default) or `'Array'`.
Where possible, the type of matrix output from functions is determined from
Expand All @@ -40,21 +45,29 @@ The following configuration options are available:
determined by the option `matrix`. In case of mixed matrix
inputs, a matrix will be returned always.

- `number`. The type of numeric output for functions which cannot
determine the numeric type from the inputs. For most functions though,
the type of output is determined from the the input:
a number as input will return a number as output,
a BigNumber as input returns a BigNumber as output.

For example the functions `math.evaluate('2+3')`, `math.parse('2+3')`,
`math.range('1:10')`, and `math.unit('5cm')` use the `number` configuration
setting. But `math.sqrt(4)` will always return the number `2`
regardless of the `number` configuration, because the input is a number.

Available values are: `'number'` (default), `'BigNumber'`, or `'Fraction'`.
[BigNumbers](../datatypes/bignumbers.js) have higher precision than the default
numbers of JavaScript, and [`Fractions`](../datatypes/fractions.js) store
values in terms of a numerator and denominator.
- `number`. The type used to parse strings into a numeric value or create a new
numeric value internally.

For most functions, the type of output is determined from the input:
a number as input will return a number as output, a BigNumber as input
returns a BigNumber as output. But for example the functions
`math.evaluate('2+3')`, `math.parse('2+3')`, `math.range('1:10')`,
and `math.unit('5cm')` use the `number` configuration setting.

Note that `math.sqrt(4)` will always return the number `2` regardless of
the `number` configuration, because the numeric type can be determined from
the input value.

Available values are: `'number'` (default), `'BigNumber'`, `'bigint'`, or `'Fraction'`.
[BigNumbers](../datatypes/bignumbers.js) have higher precision than the default numbers of JavaScript,
[bigint](../datatypes/bigints.md) can represent large integer numbers,
and [`Fractions`](../datatypes/fractions.js) store values in terms of a numerator and
denominator.

- `numberFallback`. When `number` is configured for example with value `'bigint'`,
and a value cannot be represented as `bigint` like in `math.evaluate('2.3')`,
the value will be parsed in the type configured with `numberFallback`.
Available values: `'number'` (default) or `'BigNumber'`.

- `precision`. The maximum number of significant digits for BigNumbers.
This setting only applies to BigNumbers, not to numbers.
Expand Down
54 changes: 54 additions & 0 deletions docs/datatypes/bigints.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
# BigInts

For calculations with large integer numbers, math.js supports the built-in `bigint` data type.

## Usage

A bigint can be created either by adding the suffix `n` to a `number`, using the `BigInt` constructor function, or using the util function `math.bigint`:

```js
42n
BigInt('42')
math.bigint('42')
```

Most functions can determine the type of output from the type of input:
a `number` as input will return a `number` as output, a `bigint` as input returns
a `bigint` as output. Functions which cannot determine the type of output
from the input (for example `math.evaluate`) use the default number type `number`,
which can be configured when instantiating math.js. To configure the use of
`bigint` instead of [numbers](numbers.md) by default, configure math.js like:

```js
math.config({
number: 'bigint'
})

// use math
math.evaluate('70000000000000000123') // bigint 70000000000000000123n
```

## Support

All basic arithmetic functions in math.js support `bigint`. Since `bigint` can only hold integer values, it is not applicable to for example trigonometric functions. When using a `bigint` in a function that does not support it, like `sqrt`, it will convert the `bigint` into a regular `number` and then execute the function:

```js
math.sin(2n) // number 0.9092974268256817
```

## Conversion

There are utility functions to convert a `bigint` into a `number` or `BigNumber`:

```js
// convert a number to bigint or BigNumber
math.bigint(42) // bigint, 42n
math.bignumber(42) // BigNumber, 42

// convert a bigint to a number or BigNumber
math.number(42n) // number, 42
math.bignumber(42n) // BigNumber, 42

// losing digits when converting to number
math.number(70000000000000000123n) // number, 7000000000000000000
```
11 changes: 6 additions & 5 deletions docs/datatypes/bignumbers.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ math.config({
number: 'BigNumber', // Default type of number:
// 'number' (default), 'BigNumber', or 'Fraction'
precision: 64, // Number of significant digits for BigNumbers
epsilon: 1e-60
relTol: 1e-60,
absTol: 1e-63
})

// use math
Expand All @@ -34,12 +35,12 @@ math.evaluate('0.1 + 0.2') // BigNumber, 0.3
The default precision for BigNumber is 64 digits, and can be configured with
the option `precision`.

Note that we also change the configuration of `epsilon`
to be close to the precision limit of our BigNumbers. `epsilon` is used for
Note that we also change the configuration of `relTol` and `absTol`
to be close to the precision limit of our BigNumbers. `relTol` and `absTol` are used for
example in relational and rounding functions (`equal`, `larger`, `smaller`,
`round`, `floor`, etc) to determine when a value is nearly equal,
see [Equality](numbers.md#equality). If we would leave `epsilon` unchanged,
having the default value of `1e-12`, we could get inaccurate and misleading
see [Equality](numbers.md#equality). If we would leave `relTol` and `absTol` unchanged,
having the default value of `1e-12` and `1e-15` respectively, we could get inaccurate and misleading
results since we're now working with a higher precision.


Expand Down
3 changes: 3 additions & 0 deletions docs/datatypes/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@ math.sqrt(4.41e2) // 21
// use BigNumbers
math.add(math.bignumber(0.1), math.bignumber(0.2)) // BigNumber, 0.3

// use bigint
math.add(300000000000000000n, 1n) // 300000000000000001n

// use Fractions
math.add(math.fraction(1), math.fraction(3)) // Fraction, 0.(3)

Expand Down
12 changes: 5 additions & 7 deletions docs/datatypes/numbers.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ const ans = math.add(0.1, 0.2) // 0.30000000000000004
math.format(ans, {precision: 14}) // '0.3'
```

Alternatives are to use [Fractions](fractions.md) which store a number as a numerator and denominator, or [BigNumbers](bignumbers.md), which store a number with a higher precision.
Alternatives are to use [Fractions](fractions.md) which store a number as a numerator and denominator, [BigNumbers](bignumbers.md) which store a number with a higher precision, or [bigint](bigints.md) which can store larger integer numbers.


## Minimum and maximum
Expand All @@ -73,16 +73,14 @@ false, as the addition `0.1 + 0.2` introduces a round-off error and does not
return exactly `0.3`.

To solve this problem, the relational functions of math.js check whether the
relative difference between the compared values is smaller than the configured
option `epsilon`. In pseudo code (without exceptions for 0, Infinity and NaN):
relative and absolute differences between the compared values is smaller than the configured
option `relTol` and `absTol`. In pseudo code (without exceptions for 0, Infinity and NaN):

diff = abs(x - y)
nearlyEqual = (diff <= max(abs(x), abs(y)) * EPSILON) OR (diff < DBL_EPSILON)
abs(a-b) <= max(relTol * max(abs(a), abs(b)), absTol)

where:

- `EPSILON` is the relative difference between x and y. Epsilon is configurable
and is `1e-12` by default. See [Configuration](../core/configuration.md).
- `relTol` is the relative tolerance between x and y and `absTol` the absolute tolerance. Relative tolerance and absolute tolerance are configurable and are `1e-12` and `1e-15` respectively by default. See [Configuration](../core/configuration.md).
- `DBL_EPSILON` is the minimum positive floating point number such that
`1.0 + DBL_EPSILON !== 1.0`. This is a constant with a value of approximately
`2.2204460492503130808472633361816e-16`.
Expand Down
1 change: 1 addition & 0 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ Math.js can be used in the browser, in node.js and in any JavaScript engine. Ins
- **[Data Types](datatypes/index.md)**
- [Numbers](datatypes/numbers.md)
- [BigNumbers](datatypes/bignumbers.md)
- [bigints](datatypes/bigints.md)
- [Fractions](datatypes/fractions.md)
- [Complex Numbers](datatypes/complex_numbers.md)
- [Matrices](datatypes/matrices.md)
Expand Down
4 changes: 2 additions & 2 deletions examples/advanced/convert_fraction_to_bignumber.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@

// Create an empty math.js instance, with only typed
// (every instance contains `import` and `config` also out of the box)
const { create, typedDependencies, all } = require('../..')
import { create, typedDependencies, all } from '../../lib/esm/index.js'
const math = create({
typedDependencies
})
Expand All @@ -30,7 +30,7 @@ math.config({ number: 'Fraction' })
// this conversion:
// - must be inserted in the conversions list before the conversion Fraction -> number
// - must be added to the conversions before loading functions into math.js
math.typed.conversions.unshift({
math.typed.addConversion({
from: 'Fraction',
to: 'BigNumber',
convert: function (fraction) {
Expand Down
2 changes: 1 addition & 1 deletion examples/advanced/custom_argument_parsing.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
* will be invoked with unevaluated arguments, allowing the function
* to process the arguments in a customized way.
*/
const { create, all } = require('../..')
import { create, all } from '../../lib/esm/index.js'
const math = create(all)

/**
Expand Down
3 changes: 2 additions & 1 deletion examples/advanced/custom_datatype.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
// This example demonstrates importing a custom data type,
// and extending an existing function (add) with support for this data type.

const { create, factory, all } = require('../..')
import { all, create, factory } from '../../lib/esm/index.js'

const math = create(all)

// factory function which defines a new data type CustomValue
Expand Down
4 changes: 2 additions & 2 deletions examples/advanced/custom_evaluate_using_factories.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// we use the number only implementation in order to not pull in
// the `Unit` class for example. when using as library,
// use require('mathjs/number')
const { create, evaluateDependencies, factory } = require('../../lib/cjs/number.js')
// use import 'mathjs/number'
import { create, evaluateDependencies, factory } from '../../lib/esm/number.js'

// custom implementations of all functions you want to support
const add = (a, b) => a + b
Expand Down
2 changes: 1 addition & 1 deletion examples/advanced/custom_evaluate_using_import.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// we use the number only implementation in order to not pull in
// the `Unit` class for example. when using as library,
// use require('mathjs/number')
const { create, evaluateDependencies } = require('../../lib/cjs/number.js')
import { create, evaluateDependencies } from '../../lib/esm/number.js'

// custom implementations of all functions you want to support
const add = (a, b) => a + b
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import {
create,
fractionDependencies,
addDependencies,
create,
divideDependencies,
formatDependencies
formatDependencies,
fractionDependencies
} from '../../lib/esm/index.js'

const config = {
Expand Down
2 changes: 1 addition & 1 deletion examples/advanced/custom_relational_functions.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
const { create, all, factory } = require('../..')
import { all, create, factory } from '../../lib/esm/index.js'

// First let's see what the default behavior is:
// strings are compared by their numerical value
Expand Down
2 changes: 1 addition & 1 deletion examples/advanced/custom_scope_objects.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
const { create, all } = require('../..')
import { all, create } from '../../lib/esm/index.js'

const math = create(all)

Expand Down
2 changes: 1 addition & 1 deletion examples/advanced/expression_trees.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
const { parse, ConstantNode } = require('../..')
import { parse, ConstantNode } from '../../lib/esm/index.js'

// Filter an expression tree
console.log('Filter all symbol nodes "x" in the expression "x^2 + x/4 + 3*y"')
Expand Down
2 changes: 1 addition & 1 deletion examples/advanced/function_transform.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
* *transform* for the function. A transform is a function wrapping around a
* function to be transformed or completely replaces a function.
*/
const { create, all } = require('../..')
import { all, create } from '../../lib/esm/index.js'
const math = create(all)

// create a function
Expand Down
2 changes: 1 addition & 1 deletion examples/advanced/more_secure_eval.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
// functionality, these functions can be disabled, as demonstrated in this
// example.

const { create, all } = require('../..')
import { all, create } from '../../lib/esm/index.js'
const math = create(all)

const limitedEvaluate = math.evaluate
Expand Down
Loading

0 comments on commit b0105a7

Please sign in to comment.