mathjs 10.4.3 → 10.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/HISTORY.md +15 -0
- package/docs/reference/functions/lgamma.md +46 -0
- package/docs/reference/functions/pinv.md +44 -0
- package/docs/reference/functions/pow.md +8 -2
- package/docs/reference/functions.md +2 -0
- package/lib/browser/math.js +6 -6
- package/lib/browser/math.js.map +1 -1
- package/lib/cjs/entry/dependenciesAny/dependenciesDet.generated.js +5 -2
- package/lib/cjs/entry/dependenciesAny/dependenciesLgamma.generated.js +23 -0
- package/lib/cjs/entry/dependenciesAny/dependenciesPinv.generated.js +53 -0
- package/lib/cjs/entry/dependenciesAny/dependenciesPow.generated.js +3 -0
- package/lib/cjs/entry/dependenciesAny.generated.js +16 -0
- package/lib/cjs/entry/dependenciesNumber/dependenciesLgamma.generated.js +20 -0
- package/lib/cjs/entry/dependenciesNumber.generated.js +8 -0
- package/lib/cjs/entry/impureFunctionsAny.generated.js +96 -94
- package/lib/cjs/entry/impureFunctionsNumber.generated.js +5 -4
- package/lib/cjs/entry/pureFunctionsAny.generated.js +215 -193
- package/lib/cjs/entry/pureFunctionsNumber.generated.js +14 -10
- package/lib/cjs/expression/embeddedDocs/embeddedDocs.js +6 -0
- package/lib/cjs/expression/embeddedDocs/function/arithmetic/pow.js +1 -1
- package/lib/cjs/expression/embeddedDocs/function/matrix/pinv.js +15 -0
- package/lib/cjs/expression/embeddedDocs/function/probability/lgamma.js +15 -0
- package/lib/cjs/factoriesAny.js +16 -0
- package/lib/cjs/factoriesNumber.js +3 -1
- package/lib/cjs/function/arithmetic/pow.js +25 -6
- package/lib/cjs/function/matrix/det.js +37 -31
- package/lib/cjs/function/matrix/pinv.js +223 -0
- package/lib/cjs/function/probability/lgamma.js +146 -0
- package/lib/cjs/header.js +2 -2
- package/lib/cjs/plain/number/probability.js +43 -3
- package/lib/cjs/utils/latex.js +6 -0
- package/lib/cjs/utils/number.js +17 -2
- package/lib/cjs/version.js +1 -1
- package/lib/esm/entry/dependenciesAny/dependenciesDet.generated.js +4 -2
- package/lib/esm/entry/dependenciesAny/dependenciesLgamma.generated.js +12 -0
- package/lib/esm/entry/dependenciesAny/dependenciesPinv.generated.js +32 -0
- package/lib/esm/entry/dependenciesAny/dependenciesPow.generated.js +2 -0
- package/lib/esm/entry/dependenciesAny.generated.js +2 -0
- package/lib/esm/entry/dependenciesNumber/dependenciesLgamma.generated.js +10 -0
- package/lib/esm/entry/dependenciesNumber.generated.js +1 -0
- package/lib/esm/entry/impureFunctionsAny.generated.js +90 -88
- package/lib/esm/entry/impureFunctionsNumber.generated.js +6 -5
- package/lib/esm/entry/pureFunctionsAny.generated.js +179 -159
- package/lib/esm/entry/pureFunctionsNumber.generated.js +8 -5
- package/lib/esm/expression/embeddedDocs/embeddedDocs.js +4 -0
- package/lib/esm/expression/embeddedDocs/function/arithmetic/pow.js +1 -1
- package/lib/esm/expression/embeddedDocs/function/matrix/pinv.js +8 -0
- package/lib/esm/expression/embeddedDocs/function/probability/lgamma.js +8 -0
- package/lib/esm/factoriesAny.js +2 -0
- package/lib/esm/factoriesNumber.js +2 -1
- package/lib/esm/function/arithmetic/pow.js +25 -6
- package/lib/esm/function/matrix/det.js +35 -31
- package/lib/esm/function/matrix/pinv.js +205 -0
- package/lib/esm/function/probability/lgamma.js +137 -0
- package/lib/esm/plain/number/probability.js +33 -1
- package/lib/esm/utils/latex.js +6 -0
- package/lib/esm/utils/number.js +13 -1
- package/lib/esm/version.js +1 -1
- package/package.json +7 -7
- package/types/index.d.ts +22 -1
- package/types/index.ts +10 -0
@@ -1,4 +1,4 @@
|
|
1
|
-
import { absNumber, acoshNumber, acosNumber, acothNumber, acotNumber, acschNumber, acscNumber, addNumber, andNumber, asechNumber, asecNumber, asinhNumber, asinNumber, atan2Number, atanhNumber, atanNumber, bitAndNumber, bitNotNumber, bitOrNumber, bitXorNumber, cbrtNumber, ceilNumber, combinationsNumber, coshNumber, cosNumber, cothNumber, cotNumber, cschNumber, cscNumber, cubeNumber, divideNumber, expm1Number, expNumber, fixNumber, floorNumber, gammaNumber, gcdNumber, isIntegerNumber, isNaNNumber, isNegativeNumber, isPositiveNumber, isZeroNumber, lcmNumber, leftShiftNumber, log10Number, log1pNumber, log2Number, logNumber, modNumber, multiplyNumber, normNumber, notNumber, orNumber, powNumber, rightArithShiftNumber, rightLogShiftNumber, sechNumber, secNumber, signNumber, sinhNumber, sinNumber, sqrtNumber, squareNumber, subtractNumber, tanhNumber, tanNumber, unaryMinusNumber, unaryPlusNumber, xgcdNumber, xorNumber } from './plain/number/index.js';
|
1
|
+
import { absNumber, acoshNumber, acosNumber, acothNumber, acotNumber, acschNumber, acscNumber, addNumber, andNumber, asechNumber, asecNumber, asinhNumber, asinNumber, atan2Number, atanhNumber, atanNumber, bitAndNumber, bitNotNumber, bitOrNumber, bitXorNumber, cbrtNumber, ceilNumber, combinationsNumber, coshNumber, cosNumber, cothNumber, cotNumber, cschNumber, cscNumber, cubeNumber, divideNumber, expm1Number, expNumber, fixNumber, floorNumber, gammaNumber, gcdNumber, isIntegerNumber, isNaNNumber, isNegativeNumber, isPositiveNumber, isZeroNumber, lcmNumber, leftShiftNumber, lgammaNumber, log10Number, log1pNumber, log2Number, logNumber, modNumber, multiplyNumber, normNumber, notNumber, orNumber, powNumber, rightArithShiftNumber, rightLogShiftNumber, sechNumber, secNumber, signNumber, sinhNumber, sinNumber, sqrtNumber, squareNumber, subtractNumber, tanhNumber, tanNumber, unaryMinusNumber, unaryPlusNumber, xgcdNumber, xorNumber } from './plain/number/index.js';
|
2
2
|
import { factory } from './utils/factory.js';
|
3
3
|
import { noIndex, noMatrix, noSubset } from './utils/noop.js'; // ----------------------------------------------------------------------------
|
4
4
|
// classes and functions
|
@@ -118,6 +118,7 @@ export { createPartitionSelect } from './function/matrix/partitionSelect.js'; //
|
|
118
118
|
|
119
119
|
export var createCombinations = createNumberFactory('combinations', combinationsNumber);
|
120
120
|
export var createGamma = createNumberFactory('gamma', gammaNumber);
|
121
|
+
export var createLgamma = createNumberFactory('lgamma', lgammaNumber);
|
121
122
|
export { createCombinationsWithRep } from './function/probability/combinationsWithRep.js';
|
122
123
|
export { createFactorial } from './function/probability/factorial.js';
|
123
124
|
export { createMultinomial } from './function/probability/multinomial.js';
|
@@ -3,7 +3,7 @@ import { isInteger } from '../../utils/number.js';
|
|
3
3
|
import { arraySize as size } from '../../utils/array.js';
|
4
4
|
import { powNumber } from '../../plain/number/index.js';
|
5
5
|
var name = 'pow';
|
6
|
-
var dependencies = ['typed', 'config', 'identity', 'multiply', 'matrix', 'fraction', 'number', 'Complex'];
|
6
|
+
var dependencies = ['typed', 'config', 'identity', 'multiply', 'matrix', 'inv', 'fraction', 'number', 'Complex'];
|
7
7
|
export var createPow = /* #__PURE__ */factory(name, dependencies, _ref => {
|
8
8
|
var {
|
9
9
|
typed,
|
@@ -11,6 +11,7 @@ export var createPow = /* #__PURE__ */factory(name, dependencies, _ref => {
|
|
11
11
|
identity,
|
12
12
|
multiply,
|
13
13
|
matrix,
|
14
|
+
inv,
|
14
15
|
number,
|
15
16
|
fraction,
|
16
17
|
Complex
|
@@ -18,8 +19,11 @@ export var createPow = /* #__PURE__ */factory(name, dependencies, _ref => {
|
|
18
19
|
|
19
20
|
/**
|
20
21
|
* Calculates the power of x to y, `x ^ y`.
|
21
|
-
*
|
22
|
-
*
|
22
|
+
*
|
23
|
+
* Matrix exponentiation is supported for square matrices `x` and integers `y`:
|
24
|
+
* when `y` is nonnegative, `x` may be any square matrix; and when `y` is
|
25
|
+
* negative, `x` must be invertible, and then this function returns
|
26
|
+
* inv(x)^(-y).
|
23
27
|
*
|
24
28
|
* For cubic roots of negative numbers, the function returns the principal
|
25
29
|
* root by default. In order to let the function return the real root,
|
@@ -40,6 +44,9 @@ export var createPow = /* #__PURE__ */factory(name, dependencies, _ref => {
|
|
40
44
|
* const b = [[1, 2], [4, 3]]
|
41
45
|
* math.pow(b, 2) // returns Array [[9, 8], [16, 17]]
|
42
46
|
*
|
47
|
+
* const c = [[1, 2], [4, 3]]
|
48
|
+
* math.pow(c, -1) // returns Array [[-0.6, 0.4], [0.8, -0.2]]
|
49
|
+
*
|
43
50
|
* See also:
|
44
51
|
*
|
45
52
|
* multiply, sqrt, cbrt, nthRoot
|
@@ -135,15 +142,15 @@ export var createPow = /* #__PURE__ */factory(name, dependencies, _ref => {
|
|
135
142
|
/**
|
136
143
|
* Calculate the power of a 2d array
|
137
144
|
* @param {Array} x must be a 2 dimensional, square matrix
|
138
|
-
* @param {number} y a positive
|
145
|
+
* @param {number} y a integer value (positive if `x` is not invertible)
|
139
146
|
* @returns {Array}
|
140
147
|
* @private
|
141
148
|
*/
|
142
149
|
|
143
150
|
|
144
151
|
function _powArray(x, y) {
|
145
|
-
if (!isInteger(y)
|
146
|
-
throw new TypeError('For A^b, b must be
|
152
|
+
if (!isInteger(y)) {
|
153
|
+
throw new TypeError('For A^b, b must be an integer (value is ' + y + ')');
|
147
154
|
} // verify that A is a 2 dimensional square matrix
|
148
155
|
|
149
156
|
|
@@ -157,6 +164,18 @@ export var createPow = /* #__PURE__ */factory(name, dependencies, _ref => {
|
|
157
164
|
throw new Error('For A^b, A must be square (size is ' + s[0] + 'x' + s[1] + ')');
|
158
165
|
}
|
159
166
|
|
167
|
+
if (y < 0) {
|
168
|
+
try {
|
169
|
+
return _powArray(inv(x), -y);
|
170
|
+
} catch (error) {
|
171
|
+
if (error.message === 'Cannot calculate inverse, determinant is zero') {
|
172
|
+
throw new TypeError('For A^b, when A is not invertible, b must be a positive integer (value is ' + y + ')');
|
173
|
+
}
|
174
|
+
|
175
|
+
throw error;
|
176
|
+
}
|
177
|
+
}
|
178
|
+
|
160
179
|
var res = identity(s[0]).valueOf();
|
161
180
|
var px = x;
|
162
181
|
|
@@ -3,15 +3,16 @@ import { clone } from '../../utils/object.js';
|
|
3
3
|
import { format } from '../../utils/string.js';
|
4
4
|
import { factory } from '../../utils/factory.js';
|
5
5
|
var name = 'det';
|
6
|
-
var dependencies = ['typed', 'matrix', 'subtract', 'multiply', '
|
6
|
+
var dependencies = ['typed', 'matrix', 'subtract', 'multiply', 'divideScalar', 'isZero', 'unaryMinus'];
|
7
7
|
export var createDet = /* #__PURE__ */factory(name, dependencies, _ref => {
|
8
8
|
var {
|
9
9
|
typed,
|
10
10
|
matrix,
|
11
11
|
subtract,
|
12
12
|
multiply,
|
13
|
-
|
14
|
-
|
13
|
+
divideScalar,
|
14
|
+
isZero,
|
15
|
+
unaryMinus
|
15
16
|
} = _ref;
|
16
17
|
|
17
18
|
/**
|
@@ -106,42 +107,45 @@ export var createDet = /* #__PURE__ */factory(name, dependencies, _ref => {
|
|
106
107
|
// the determinant of [a11,a12;a21,a22] is det = a11*a22-a21*a12
|
107
108
|
return subtract(multiply(matrix[0][0], matrix[1][1]), multiply(matrix[1][0], matrix[0][1]));
|
108
109
|
} else {
|
109
|
-
//
|
110
|
-
|
111
|
-
|
112
|
-
var
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
110
|
+
// Bareiss algorithm
|
111
|
+
// this algorithm have same complexity as LUP decomposition (O(n^3))
|
112
|
+
// but it preserve precision of floating point more relative to the LUP decomposition
|
113
|
+
var negated = false;
|
114
|
+
var rowIndices = new Array(rows).fill(0).map((_, i) => i); // matrix index of row i
|
115
|
+
|
116
|
+
for (var k = 0; k < rows; k++) {
|
117
|
+
var k_ = rowIndices[k];
|
118
|
+
|
119
|
+
if (isZero(matrix[k_][k])) {
|
120
|
+
var _k = void 0;
|
121
|
+
|
122
|
+
for (_k = k + 1; _k < rows; _k++) {
|
123
|
+
if (!isZero(matrix[rowIndices[_k]][k])) {
|
124
|
+
k_ = rowIndices[_k];
|
125
|
+
rowIndices[_k] = rowIndices[k];
|
126
|
+
rowIndices[k] = k_;
|
127
|
+
negated = !negated;
|
128
|
+
break;
|
129
|
+
}
|
130
|
+
}
|
123
131
|
|
124
|
-
|
125
|
-
while (visited[i]) {
|
126
|
-
i++;
|
132
|
+
if (_k === rows) return matrix[k_][k]; // some zero of the type
|
127
133
|
}
|
128
134
|
|
129
|
-
|
130
|
-
var
|
131
|
-
var cycleLen = 0;
|
135
|
+
var piv = matrix[k_][k];
|
136
|
+
var piv_ = k === 0 ? 1 : matrix[rowIndices[k - 1]][k - 1];
|
132
137
|
|
133
|
-
|
134
|
-
|
135
|
-
j = decomp.p[j];
|
136
|
-
cycleLen++;
|
137
|
-
}
|
138
|
+
for (var i = k + 1; i < rows; i++) {
|
139
|
+
var i_ = rowIndices[i];
|
138
140
|
|
139
|
-
|
140
|
-
|
141
|
+
for (var j = k + 1; j < rows; j++) {
|
142
|
+
matrix[i_][j] = divideScalar(subtract(multiply(matrix[i_][j], piv), multiply(matrix[i_][k], matrix[k_][j])), piv_);
|
143
|
+
}
|
141
144
|
}
|
142
145
|
}
|
143
146
|
|
144
|
-
|
147
|
+
var det = matrix[rowIndices[rows - 1]][rows - 1];
|
148
|
+
return negated ? unaryMinus(det) : det;
|
145
149
|
}
|
146
150
|
}
|
147
151
|
});
|
@@ -0,0 +1,205 @@
|
|
1
|
+
import { isMatrix } from '../../utils/is.js';
|
2
|
+
import { arraySize } from '../../utils/array.js';
|
3
|
+
import { factory } from '../../utils/factory.js';
|
4
|
+
import { format } from '../../utils/string.js';
|
5
|
+
import { clone } from '../../utils/object.js';
|
6
|
+
var name = 'pinv';
|
7
|
+
var dependencies = ['typed', 'matrix', 'inv', 'deepEqual', 'equal', 'dotDivide', 'dot', 'ctranspose', 'divideScalar', 'multiply', 'add', 'Complex'];
|
8
|
+
export var createPinv = /* #__PURE__ */factory(name, dependencies, _ref => {
|
9
|
+
var {
|
10
|
+
typed,
|
11
|
+
matrix,
|
12
|
+
inv,
|
13
|
+
deepEqual,
|
14
|
+
equal,
|
15
|
+
dotDivide,
|
16
|
+
dot,
|
17
|
+
ctranspose,
|
18
|
+
divideScalar,
|
19
|
+
multiply,
|
20
|
+
add,
|
21
|
+
Complex
|
22
|
+
} = _ref;
|
23
|
+
|
24
|
+
/**
|
25
|
+
* Calculate the Moore–Penrose inverse of a matrix.
|
26
|
+
*
|
27
|
+
* Syntax:
|
28
|
+
*
|
29
|
+
* math.pinv(x)
|
30
|
+
*
|
31
|
+
* Examples:
|
32
|
+
*
|
33
|
+
* math.pinv([[1, 2], [3, 4]]) // returns [[-2, 1], [1.5, -0.5]]
|
34
|
+
* math.pinv([[1, 0], [0, 1], [0, 1]]) // returns [[1, 0, 0], [0, 0.5, 0.5]]
|
35
|
+
* math.pinv(4) // returns 0.25
|
36
|
+
*
|
37
|
+
* See also:
|
38
|
+
*
|
39
|
+
* inv
|
40
|
+
*
|
41
|
+
* @param {number | Complex | Array | Matrix} x Matrix to be inversed
|
42
|
+
* @return {number | Complex | Array | Matrix} The inverse of `x`.
|
43
|
+
*/
|
44
|
+
return typed(name, {
|
45
|
+
'Array | Matrix': function ArrayMatrix(x) {
|
46
|
+
var size = isMatrix(x) ? x.size() : arraySize(x);
|
47
|
+
|
48
|
+
switch (size.length) {
|
49
|
+
case 1:
|
50
|
+
// vector
|
51
|
+
if (_isZeros(x)) return ctranspose(x); // null vector
|
52
|
+
|
53
|
+
if (size[0] === 1) {
|
54
|
+
return inv(x); // invertible matrix
|
55
|
+
} else {
|
56
|
+
return dotDivide(ctranspose(x), dot(x, x));
|
57
|
+
}
|
58
|
+
|
59
|
+
case 2:
|
60
|
+
// two dimensional array
|
61
|
+
{
|
62
|
+
if (_isZeros(x)) return ctranspose(x); // zero matrixx
|
63
|
+
|
64
|
+
var rows = size[0];
|
65
|
+
var cols = size[1];
|
66
|
+
|
67
|
+
if (rows === cols) {
|
68
|
+
try {
|
69
|
+
return inv(x); // invertible matrix
|
70
|
+
} catch (err) {
|
71
|
+
if (err instanceof Error && err.message.match(/Cannot calculate inverse, determinant is zero/)) {// Expected
|
72
|
+
} else {
|
73
|
+
throw err;
|
74
|
+
}
|
75
|
+
}
|
76
|
+
}
|
77
|
+
|
78
|
+
if (isMatrix(x)) {
|
79
|
+
return matrix(_pinv(x.valueOf(), rows, cols), x.storage());
|
80
|
+
} else {
|
81
|
+
// return an Array
|
82
|
+
return _pinv(x, rows, cols);
|
83
|
+
}
|
84
|
+
}
|
85
|
+
|
86
|
+
default:
|
87
|
+
// multi dimensional array
|
88
|
+
throw new RangeError('Matrix must be two dimensional ' + '(size: ' + format(size) + ')');
|
89
|
+
}
|
90
|
+
},
|
91
|
+
any: function any(x) {
|
92
|
+
// scalar
|
93
|
+
if (equal(x, 0)) return clone(x); // zero
|
94
|
+
|
95
|
+
return divideScalar(1, x);
|
96
|
+
}
|
97
|
+
});
|
98
|
+
/**
|
99
|
+
* Calculate the Moore–Penrose inverse of a matrix
|
100
|
+
* @param {Array[]} mat A matrix
|
101
|
+
* @param {number} rows Number of rows
|
102
|
+
* @param {number} cols Number of columns
|
103
|
+
* @return {Array[]} pinv Pseudoinverse matrix
|
104
|
+
* @private
|
105
|
+
*/
|
106
|
+
|
107
|
+
function _pinv(mat, rows, cols) {
|
108
|
+
var {
|
109
|
+
C,
|
110
|
+
F
|
111
|
+
} = _rankFact(mat, rows, cols); // TODO: Use SVD instead (may improve precision)
|
112
|
+
|
113
|
+
|
114
|
+
var Cpinv = multiply(inv(multiply(ctranspose(C), C)), ctranspose(C));
|
115
|
+
var Fpinv = multiply(ctranspose(F), inv(multiply(F, ctranspose(F))));
|
116
|
+
return multiply(Fpinv, Cpinv);
|
117
|
+
}
|
118
|
+
/**
|
119
|
+
* Calculate the reduced row echelon form of a matrix
|
120
|
+
*
|
121
|
+
* Modified from https://rosettacode.org/wiki/Reduced_row_echelon_form
|
122
|
+
*
|
123
|
+
* @param {Array[]} mat A matrix
|
124
|
+
* @param {number} rows Number of rows
|
125
|
+
* @param {number} cols Number of columns
|
126
|
+
* @return {Array[]} Reduced row echelon form
|
127
|
+
* @private
|
128
|
+
*/
|
129
|
+
|
130
|
+
|
131
|
+
function _rref(mat, rows, cols) {
|
132
|
+
var M = clone(mat);
|
133
|
+
var lead = 0;
|
134
|
+
|
135
|
+
for (var r = 0; r < rows; r++) {
|
136
|
+
if (cols <= lead) {
|
137
|
+
return M;
|
138
|
+
}
|
139
|
+
|
140
|
+
var i = r;
|
141
|
+
|
142
|
+
while (_isZero(M[i][lead])) {
|
143
|
+
i++;
|
144
|
+
|
145
|
+
if (rows === i) {
|
146
|
+
i = r;
|
147
|
+
lead++;
|
148
|
+
|
149
|
+
if (cols === lead) {
|
150
|
+
return M;
|
151
|
+
}
|
152
|
+
}
|
153
|
+
}
|
154
|
+
|
155
|
+
[M[i], M[r]] = [M[r], M[i]];
|
156
|
+
var val = M[r][lead];
|
157
|
+
|
158
|
+
for (var j = 0; j < cols; j++) {
|
159
|
+
M[r][j] = dotDivide(M[r][j], val);
|
160
|
+
}
|
161
|
+
|
162
|
+
for (var _i = 0; _i < rows; _i++) {
|
163
|
+
if (_i === r) continue;
|
164
|
+
val = M[_i][lead];
|
165
|
+
|
166
|
+
for (var _j = 0; _j < cols; _j++) {
|
167
|
+
M[_i][_j] = add(M[_i][_j], multiply(-1, multiply(val, M[r][_j])));
|
168
|
+
}
|
169
|
+
}
|
170
|
+
|
171
|
+
lead++;
|
172
|
+
}
|
173
|
+
|
174
|
+
return M;
|
175
|
+
}
|
176
|
+
/**
|
177
|
+
* Calculate the rank factorization of a matrix
|
178
|
+
*
|
179
|
+
* @param {Array[]} mat A matrix (M)
|
180
|
+
* @param {number} rows Number of rows
|
181
|
+
* @param {number} cols Number of columns
|
182
|
+
* @return {{C: Array, F: Array}} rank factorization where M = C F
|
183
|
+
* @private
|
184
|
+
*/
|
185
|
+
|
186
|
+
|
187
|
+
function _rankFact(mat, rows, cols) {
|
188
|
+
var rref = _rref(mat, rows, cols);
|
189
|
+
|
190
|
+
var C = mat.map((_, i) => _.filter((_, j) => j < rows && !_isZero(dot(rref[j], rref[j]))));
|
191
|
+
var F = rref.filter((_, i) => !_isZero(dot(rref[i], rref[i])));
|
192
|
+
return {
|
193
|
+
C,
|
194
|
+
F
|
195
|
+
};
|
196
|
+
}
|
197
|
+
|
198
|
+
function _isZero(x) {
|
199
|
+
return equal(add(x, Complex(1, 1)), add(0, Complex(1, 1)));
|
200
|
+
}
|
201
|
+
|
202
|
+
function _isZeros(arr) {
|
203
|
+
return deepEqual(add(arr, Complex(1, 1)), add(multiply(arr, 0), Complex(1, 1)));
|
204
|
+
}
|
205
|
+
});
|
@@ -0,0 +1,137 @@
|
|
1
|
+
/* eslint-disable no-loss-of-precision */
|
2
|
+
// References
|
3
|
+
// ----------
|
4
|
+
// [1] Hare, "Computing the Principal Branch of log-Gamma", Journal of Algorithms, 1997.
|
5
|
+
// [2] https://math.stackexchange.com/questions/1338753/how-do-i-calculate-values-for-gamma-function-with-complex-arguments
|
6
|
+
import { lgammaNumber, lnSqrt2PI } from '../../plain/number/index.js';
|
7
|
+
import { factory } from '../../utils/factory.js';
|
8
|
+
import { copysign } from '../../utils/number.js';
|
9
|
+
var name = 'lgamma';
|
10
|
+
var dependencies = ['Complex', 'typed'];
|
11
|
+
export var createLgamma = /* #__PURE__ */factory(name, dependencies, _ref => {
|
12
|
+
var {
|
13
|
+
Complex: _Complex,
|
14
|
+
typed
|
15
|
+
} = _ref;
|
16
|
+
// Stirling series is non-convergent, we need to use the recurrence `lgamma(z) = lgamma(z+1) - log z` to get
|
17
|
+
// sufficient accuracy.
|
18
|
+
//
|
19
|
+
// These two values are copied from Scipy implementation:
|
20
|
+
// https://github.com/scipy/scipy/blob/v1.8.0/scipy/special/_loggamma.pxd#L37
|
21
|
+
var SMALL_RE = 7;
|
22
|
+
var SMALL_IM = 7;
|
23
|
+
/**
|
24
|
+
* The coefficients are B[2*n]/(2*n*(2*n - 1)) where B[2*n] is the (2*n)th Bernoulli number. See (1.1) in [1].
|
25
|
+
*
|
26
|
+
* If you cannot access the paper, can also get these values from the formula in [2].
|
27
|
+
*
|
28
|
+
* 1 / 12 = 0.00833333333333333333333333333333
|
29
|
+
* 1 / 360 = 0.00277777777777777777777777777778
|
30
|
+
* ...
|
31
|
+
* 3617 / 133400 = 0.02955065359477124183006535947712
|
32
|
+
*/
|
33
|
+
|
34
|
+
var coeffs = [-2.955065359477124183e-2, 6.4102564102564102564e-3, -1.9175269175269175269e-3, 8.4175084175084175084e-4, -5.952380952380952381e-4, 7.9365079365079365079e-4, -2.7777777777777777778e-3, 8.3333333333333333333e-2];
|
35
|
+
/**
|
36
|
+
* Logarithm of the gamma function for real, positive numbers and complex numbers,
|
37
|
+
* using Lanczos approximation for numbers and Stirling series for complex numbers.
|
38
|
+
*
|
39
|
+
* Syntax:
|
40
|
+
*
|
41
|
+
* math.lgamma(n)
|
42
|
+
*
|
43
|
+
* Examples:
|
44
|
+
*
|
45
|
+
* math.lgamma(5) // returns 3.178053830347945
|
46
|
+
* math.lgamma(0) // returns Infinity
|
47
|
+
* math.lgamma(-0.5) // returns NaN
|
48
|
+
* math.lgamma(math.i) // returns -0.6509231993018536 - 1.8724366472624294i
|
49
|
+
*
|
50
|
+
* See also:
|
51
|
+
*
|
52
|
+
* gamma
|
53
|
+
*
|
54
|
+
* @param {number | Complex} n A real or complex number
|
55
|
+
* @return {number | Complex} The log gamma of `n`
|
56
|
+
*/
|
57
|
+
|
58
|
+
return typed(name, {
|
59
|
+
number: lgammaNumber,
|
60
|
+
Complex: function Complex(n) {
|
61
|
+
var TWOPI = 6.2831853071795864769252842; // 2*pi
|
62
|
+
|
63
|
+
var LOGPI = 1.1447298858494001741434262; // log(pi)
|
64
|
+
|
65
|
+
var REFLECTION = 0.1;
|
66
|
+
|
67
|
+
if (n.isNaN()) {
|
68
|
+
return new _Complex(NaN, NaN);
|
69
|
+
} else if (n.im === 0) {
|
70
|
+
return new _Complex(lgammaNumber(n.re), 0);
|
71
|
+
} else if (n.re >= SMALL_RE || Math.abs(n.im) >= SMALL_IM) {
|
72
|
+
return lgammaStirling(n);
|
73
|
+
} else if (n.re <= REFLECTION) {
|
74
|
+
// Reflection formula. see Proposition 3.1 in [1]
|
75
|
+
var tmp = copysign(TWOPI, n.im) * Math.floor(0.5 * n.re + 0.25); // TODO: `complex.js sin` doesn't have extremely high precision, so this value `a` may lose a little precision,
|
76
|
+
// causing the computation results to be less accurate than the lgamma of real numbers
|
77
|
+
|
78
|
+
var a = n.mul(Math.PI).sin().log();
|
79
|
+
var b = this(new _Complex(1 - n.re, -n.im));
|
80
|
+
return new _Complex(LOGPI, tmp).sub(a).sub(b);
|
81
|
+
} else if (n.im >= 0) {
|
82
|
+
return lgammaRecurrence(n);
|
83
|
+
} else {
|
84
|
+
return lgammaRecurrence(n.conjugate()).conjugate();
|
85
|
+
}
|
86
|
+
},
|
87
|
+
BigNumber: function BigNumber() {
|
88
|
+
throw new Error("mathjs doesn't yet provide an implementation of the algorithm lgamma for BigNumber");
|
89
|
+
}
|
90
|
+
});
|
91
|
+
|
92
|
+
function lgammaStirling(z) {
|
93
|
+
// formula ref in [2]
|
94
|
+
// computation ref:
|
95
|
+
// https://github.com/scipy/scipy/blob/v1.8.0/scipy/special/_loggamma.pxd#L101
|
96
|
+
// left part
|
97
|
+
// x (log(x) - 1) + 1/2 (log(2PI) - log(x))
|
98
|
+
// => (x - 0.5) * log(x) - x + log(2PI) / 2
|
99
|
+
var leftPart = z.sub(0.5).mul(z.log()).sub(z).add(lnSqrt2PI); // right part
|
100
|
+
|
101
|
+
var rz = new _Complex(1, 0).div(z);
|
102
|
+
var rzz = rz.div(z);
|
103
|
+
var a = coeffs[0];
|
104
|
+
var b = coeffs[1];
|
105
|
+
var r = 2 * rzz.re;
|
106
|
+
var s = rzz.re * rzz.re + rzz.im * rzz.im;
|
107
|
+
|
108
|
+
for (var i = 2; i < 8; i++) {
|
109
|
+
var tmp = b;
|
110
|
+
b = -s * a + coeffs[i];
|
111
|
+
a = r * a + tmp;
|
112
|
+
}
|
113
|
+
|
114
|
+
var rightPart = rz.mul(rzz.mul(a).add(b)); // plus left and right
|
115
|
+
|
116
|
+
return leftPart.add(rightPart);
|
117
|
+
}
|
118
|
+
|
119
|
+
function lgammaRecurrence(z) {
|
120
|
+
// computation ref:
|
121
|
+
// https://github.com/scipy/scipy/blob/v1.8.0/scipy/special/_loggamma.pxd#L78
|
122
|
+
var signflips = 0;
|
123
|
+
var sb = 0;
|
124
|
+
var shiftprod = z;
|
125
|
+
z = z.add(1);
|
126
|
+
|
127
|
+
while (z.re <= SMALL_RE) {
|
128
|
+
shiftprod = shiftprod.mul(z);
|
129
|
+
var nsb = shiftprod.im < 0 ? 1 : 0;
|
130
|
+
if (nsb !== 0 && sb === 0) signflips++;
|
131
|
+
sb = nsb;
|
132
|
+
z = z.add(1);
|
133
|
+
}
|
134
|
+
|
135
|
+
return lgammaStirling(z).sub(shiftprod.log()).sub(new _Complex(0, signflips * 2 * Math.PI * 1));
|
136
|
+
}
|
137
|
+
});
|
@@ -46,4 +46,36 @@ export function gammaNumber(n) {
|
|
46
46
|
gammaNumber.signature = 'number'; // TODO: comment on the variables g and p
|
47
47
|
|
48
48
|
export var gammaG = 4.7421875;
|
49
|
-
export var gammaP = [0.99999999999999709182, 57.156235665862923517, -59.597960355475491248, 14.136097974741747174, -0.49191381609762019978, 0.33994649984811888699e-4, 0.46523628927048575665e-4, -0.98374475304879564677e-4, 0.15808870322491248884e-3, -0.21026444172410488319e-3, 0.21743961811521264320e-3, -0.16431810653676389022e-3, 0.84418223983852743293e-4, -0.26190838401581408670e-4, 0.36899182659531622704e-5];
|
49
|
+
export var gammaP = [0.99999999999999709182, 57.156235665862923517, -59.597960355475491248, 14.136097974741747174, -0.49191381609762019978, 0.33994649984811888699e-4, 0.46523628927048575665e-4, -0.98374475304879564677e-4, 0.15808870322491248884e-3, -0.21026444172410488319e-3, 0.21743961811521264320e-3, -0.16431810653676389022e-3, 0.84418223983852743293e-4, -0.26190838401581408670e-4, 0.36899182659531622704e-5]; // lgamma implementation ref: https://mrob.com/pub/ries/lanczos-gamma.html#code
|
50
|
+
// log(2 * pi) / 2
|
51
|
+
|
52
|
+
export var lnSqrt2PI = 0.91893853320467274178;
|
53
|
+
export var lgammaG = 5; // Lanczos parameter "g"
|
54
|
+
|
55
|
+
export var lgammaN = 7; // Range of coefficients "n"
|
56
|
+
|
57
|
+
export var lgammaSeries = [1.000000000190015, 76.18009172947146, -86.50532032941677, 24.01409824083091, -1.231739572450155, 0.1208650973866179e-2, -0.5395239384953e-5];
|
58
|
+
export function lgammaNumber(n) {
|
59
|
+
if (n < 0) return NaN;
|
60
|
+
if (n === 0) return Infinity;
|
61
|
+
if (!isFinite(n)) return n;
|
62
|
+
|
63
|
+
if (n < 0.5) {
|
64
|
+
// Use Euler's reflection formula:
|
65
|
+
// gamma(z) = PI / (sin(PI * z) * gamma(1 - z))
|
66
|
+
return Math.log(Math.PI / Math.sin(Math.PI * n)) - lgammaNumber(1 - n);
|
67
|
+
} // Compute the logarithm of the Gamma function using the Lanczos method
|
68
|
+
|
69
|
+
|
70
|
+
n = n - 1;
|
71
|
+
var base = n + lgammaG + 0.5; // Base of the Lanczos exponential
|
72
|
+
|
73
|
+
var sum = lgammaSeries[0]; // We start with the terms that have the smallest coefficients and largest denominator
|
74
|
+
|
75
|
+
for (var i = lgammaN - 1; i >= 1; i--) {
|
76
|
+
sum += lgammaSeries[i] / (n + i);
|
77
|
+
}
|
78
|
+
|
79
|
+
return lnSqrt2PI + (n + 0.5) * Math.log(base) - base + Math.log(sum);
|
80
|
+
}
|
81
|
+
lgammaNumber.signature = 'number';
|
package/lib/esm/utils/latex.js
CHANGED
@@ -284,6 +284,9 @@ export var latexFunctions = {
|
|
284
284
|
inv: {
|
285
285
|
1: '\\left(${args[0]}\\right)^{-1}'
|
286
286
|
},
|
287
|
+
pinv: {
|
288
|
+
1: '\\left(${args[0]}\\right)^{+}'
|
289
|
+
},
|
287
290
|
sqrtm: {
|
288
291
|
1: "{${args[0]}}".concat(latexOperators.pow, "{\\frac{1}{2}}")
|
289
292
|
},
|
@@ -306,6 +309,9 @@ export var latexFunctions = {
|
|
306
309
|
gamma: {
|
307
310
|
1: '\\Gamma\\left(${args[0]}\\right)'
|
308
311
|
},
|
312
|
+
lgamma: {
|
313
|
+
1: '\\ln\\Gamma\\left(${args[0]}\\right)'
|
314
|
+
},
|
309
315
|
// relational
|
310
316
|
equal: {
|
311
317
|
2: "\\left(${args[0]}".concat(latexOperators.equal, "${args[1]}\\right)")
|
package/lib/esm/utils/number.js
CHANGED
@@ -685,4 +685,16 @@ export var sinh = Math.sinh || function (x) {
|
|
685
685
|
export var tanh = Math.tanh || function (x) {
|
686
686
|
var e = Math.exp(2 * x);
|
687
687
|
return (e - 1) / (e + 1);
|
688
|
-
};
|
688
|
+
};
|
689
|
+
/**
|
690
|
+
* Returns a value with the magnitude of x and the sign of y.
|
691
|
+
* @param {number} x
|
692
|
+
* @param {number} y
|
693
|
+
* @returns {number}
|
694
|
+
*/
|
695
|
+
|
696
|
+
export function copysign(x, y) {
|
697
|
+
var signx = x > 0 ? true : x < 0 ? false : 1 / x === Infinity;
|
698
|
+
var signy = y > 0 ? true : y < 0 ? false : 1 / y === Infinity;
|
699
|
+
return signx ^ signy ? -x : x;
|
700
|
+
}
|
package/lib/esm/version.js
CHANGED
@@ -1,2 +1,2 @@
|
|
1
|
-
export var version = '10.
|
1
|
+
export var version = '10.5.0'; // Note: This file is automatically generated when building math.js.
|
2
2
|
// Changes made in this file will be overwritten.
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "mathjs",
|
3
|
-
"version": "10.
|
3
|
+
"version": "10.5.0",
|
4
4
|
"description": "Math.js is an extensive math library for JavaScript and Node.js. It features a flexible expression parser with support for symbolic computation, comes with a large set of built-in functions and constants, and offers an integrated solution to work with different data types like numbers, big numbers, complex numbers, fractions, units, and matrices.",
|
5
5
|
"author": "Jos de Jong <wjosdejong@gmail.com> (https://github.com/josdejong)",
|
6
6
|
"homepage": "https://mathjs.org",
|
@@ -25,8 +25,8 @@
|
|
25
25
|
"unit"
|
26
26
|
],
|
27
27
|
"dependencies": {
|
28
|
-
"@babel/runtime": "^7.17.
|
29
|
-
"complex.js": "^2.1.
|
28
|
+
"@babel/runtime": "^7.17.9",
|
29
|
+
"complex.js": "^2.1.1",
|
30
30
|
"decimal.js": "^10.3.1",
|
31
31
|
"escape-latex": "^1.2.0",
|
32
32
|
"fraction.js": "^4.2.0",
|
@@ -36,7 +36,7 @@
|
|
36
36
|
"typed-function": "^2.1.0"
|
37
37
|
},
|
38
38
|
"devDependencies": {
|
39
|
-
"@babel/core": "7.17.
|
39
|
+
"@babel/core": "7.17.9",
|
40
40
|
"@babel/plugin-transform-object-assign": "7.16.7",
|
41
41
|
"@babel/plugin-transform-runtime": "7.17.0",
|
42
42
|
"@babel/preset-env": "7.16.11",
|
@@ -46,7 +46,7 @@
|
|
46
46
|
"babel-loader": "8.2.4",
|
47
47
|
"benchmark": "2.1.4",
|
48
48
|
"codecov": "3.8.3",
|
49
|
-
"core-js": "3.
|
49
|
+
"core-js": "3.22.0",
|
50
50
|
"del": "6.0.0",
|
51
51
|
"dtslint": "4.2.1",
|
52
52
|
"expect-type": "^0.13.0",
|
@@ -58,7 +58,7 @@
|
|
58
58
|
"handlebars": "4.7.7",
|
59
59
|
"istanbul": "0.4.5",
|
60
60
|
"jsep": "1.3.4",
|
61
|
-
"karma": "6.3.
|
61
|
+
"karma": "6.3.18",
|
62
62
|
"karma-browserstack-launcher": "1.6.0",
|
63
63
|
"karma-firefox-launcher": "2.1.2",
|
64
64
|
"karma-mocha": "2.0.1",
|
@@ -79,7 +79,7 @@
|
|
79
79
|
"standard": "16.0.4",
|
80
80
|
"sylvester": "0.0.21",
|
81
81
|
"ts-node": "10.7.0",
|
82
|
-
"typescript": "4.6.
|
82
|
+
"typescript": "4.6.3",
|
83
83
|
"webpack": "4.46.0",
|
84
84
|
"zeros": "1.0.0"
|
85
85
|
},
|