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.
Files changed (61) hide show
  1. package/HISTORY.md +15 -0
  2. package/docs/reference/functions/lgamma.md +46 -0
  3. package/docs/reference/functions/pinv.md +44 -0
  4. package/docs/reference/functions/pow.md +8 -2
  5. package/docs/reference/functions.md +2 -0
  6. package/lib/browser/math.js +6 -6
  7. package/lib/browser/math.js.map +1 -1
  8. package/lib/cjs/entry/dependenciesAny/dependenciesDet.generated.js +5 -2
  9. package/lib/cjs/entry/dependenciesAny/dependenciesLgamma.generated.js +23 -0
  10. package/lib/cjs/entry/dependenciesAny/dependenciesPinv.generated.js +53 -0
  11. package/lib/cjs/entry/dependenciesAny/dependenciesPow.generated.js +3 -0
  12. package/lib/cjs/entry/dependenciesAny.generated.js +16 -0
  13. package/lib/cjs/entry/dependenciesNumber/dependenciesLgamma.generated.js +20 -0
  14. package/lib/cjs/entry/dependenciesNumber.generated.js +8 -0
  15. package/lib/cjs/entry/impureFunctionsAny.generated.js +96 -94
  16. package/lib/cjs/entry/impureFunctionsNumber.generated.js +5 -4
  17. package/lib/cjs/entry/pureFunctionsAny.generated.js +215 -193
  18. package/lib/cjs/entry/pureFunctionsNumber.generated.js +14 -10
  19. package/lib/cjs/expression/embeddedDocs/embeddedDocs.js +6 -0
  20. package/lib/cjs/expression/embeddedDocs/function/arithmetic/pow.js +1 -1
  21. package/lib/cjs/expression/embeddedDocs/function/matrix/pinv.js +15 -0
  22. package/lib/cjs/expression/embeddedDocs/function/probability/lgamma.js +15 -0
  23. package/lib/cjs/factoriesAny.js +16 -0
  24. package/lib/cjs/factoriesNumber.js +3 -1
  25. package/lib/cjs/function/arithmetic/pow.js +25 -6
  26. package/lib/cjs/function/matrix/det.js +37 -31
  27. package/lib/cjs/function/matrix/pinv.js +223 -0
  28. package/lib/cjs/function/probability/lgamma.js +146 -0
  29. package/lib/cjs/header.js +2 -2
  30. package/lib/cjs/plain/number/probability.js +43 -3
  31. package/lib/cjs/utils/latex.js +6 -0
  32. package/lib/cjs/utils/number.js +17 -2
  33. package/lib/cjs/version.js +1 -1
  34. package/lib/esm/entry/dependenciesAny/dependenciesDet.generated.js +4 -2
  35. package/lib/esm/entry/dependenciesAny/dependenciesLgamma.generated.js +12 -0
  36. package/lib/esm/entry/dependenciesAny/dependenciesPinv.generated.js +32 -0
  37. package/lib/esm/entry/dependenciesAny/dependenciesPow.generated.js +2 -0
  38. package/lib/esm/entry/dependenciesAny.generated.js +2 -0
  39. package/lib/esm/entry/dependenciesNumber/dependenciesLgamma.generated.js +10 -0
  40. package/lib/esm/entry/dependenciesNumber.generated.js +1 -0
  41. package/lib/esm/entry/impureFunctionsAny.generated.js +90 -88
  42. package/lib/esm/entry/impureFunctionsNumber.generated.js +6 -5
  43. package/lib/esm/entry/pureFunctionsAny.generated.js +179 -159
  44. package/lib/esm/entry/pureFunctionsNumber.generated.js +8 -5
  45. package/lib/esm/expression/embeddedDocs/embeddedDocs.js +4 -0
  46. package/lib/esm/expression/embeddedDocs/function/arithmetic/pow.js +1 -1
  47. package/lib/esm/expression/embeddedDocs/function/matrix/pinv.js +8 -0
  48. package/lib/esm/expression/embeddedDocs/function/probability/lgamma.js +8 -0
  49. package/lib/esm/factoriesAny.js +2 -0
  50. package/lib/esm/factoriesNumber.js +2 -1
  51. package/lib/esm/function/arithmetic/pow.js +25 -6
  52. package/lib/esm/function/matrix/det.js +35 -31
  53. package/lib/esm/function/matrix/pinv.js +205 -0
  54. package/lib/esm/function/probability/lgamma.js +137 -0
  55. package/lib/esm/plain/number/probability.js +33 -1
  56. package/lib/esm/utils/latex.js +6 -0
  57. package/lib/esm/utils/number.js +13 -1
  58. package/lib/esm/version.js +1 -1
  59. package/package.json +7 -7
  60. package/types/index.d.ts +22 -1
  61. 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
- * Matrix exponentiation is supported for square matrices `x`, and positive
22
- * integer exponents `y`.
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, integer value
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) || y < 0) {
146
- throw new TypeError('For A^b, b must be a positive integer (value is ' + y + ')');
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', 'unaryMinus', 'lup'];
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
- unaryMinus,
14
- lup
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
- // Compute the LU decomposition
110
- var decomp = lup(matrix); // The determinant is the product of the diagonal entries of U (and those of L, but they are all 1)
111
-
112
- var det = decomp.U[0][0];
113
-
114
- for (var _i = 1; _i < rows; _i++) {
115
- det = multiply(det, decomp.U[_i][_i]);
116
- } // The determinant will be multiplied by 1 or -1 depending on the parity of the permutation matrix.
117
- // This can be determined by counting the cycles. This is roughly a linear time algorithm.
118
-
119
-
120
- var evenCycles = 0;
121
- var i = 0;
122
- var visited = [];
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
- while (true) {
125
- while (visited[i]) {
126
- i++;
132
+ if (_k === rows) return matrix[k_][k]; // some zero of the type
127
133
  }
128
134
 
129
- if (i >= rows) break;
130
- var j = i;
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
- while (!visited[decomp.p[j]]) {
134
- visited[decomp.p[j]] = true;
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
- if (cycleLen % 2 === 0) {
140
- evenCycles++;
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
- return evenCycles % 2 === 0 ? det : unaryMinus(det);
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';
@@ -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)")
@@ -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
+ }
@@ -1,2 +1,2 @@
1
- export var version = '10.4.3'; // Note: This file is automatically generated when building math.js.
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.4.3",
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.8",
29
- "complex.js": "^2.1.0",
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.8",
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.21.1",
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.17",
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.2",
82
+ "typescript": "4.6.3",
83
83
  "webpack": "4.46.0",
84
84
  "zeros": "1.0.0"
85
85
  },