mathjs 10.4.3 → 10.5.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
},
|