mathjs 5.0.0 → 5.0.4
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of mathjs might be problematic. Click here for more details.
- package/HISTORY.md +48 -1
- package/README.md +2 -1
- package/dist/math.js +20114 -20090
- package/dist/math.min.js +7 -7
- package/dist/math.min.map +1 -1
- package/docs/core/configuration.md +1 -1
- package/docs/datatypes/numbers.md +1 -1
- package/docs/datatypes/units.md +1 -1
- package/docs/expressions/algebra.md +25 -1
- package/docs/getting_started.md +2 -2
- package/docs/reference/functions/format.md +2 -2
- package/docs/reference/functions/qr.md +2 -1
- package/docs/reference/functions/rationalize.md +13 -10
- package/docs/reference/functions/stirlingS2.md +1 -1
- package/docs/reference/functions/typeof.md +13 -13
- package/examples/advanced/add_new_datatypes/MyType.js +0 -10
- package/examples/advanced/add_new_datatypes/index.js +2 -6
- package/examples/browser/rocket_trajectory_optimization.html +2 -2
- package/lib/constants.js +3 -1
- package/lib/core/function/import.js +15 -2
- package/lib/core/typed.js +1 -1
- package/lib/expression/node/FunctionNode.js +5 -4
- package/lib/expression/parse.js +429 -466
- package/lib/function/algebra/decomposition/qr.js +1 -1
- package/lib/function/algebra/rationalize.js +41 -45
- package/lib/function/algebra/simplify/resolve.js +1 -1
- package/lib/function/algebra/simplify/simplifyCore.js +3 -3
- package/lib/function/algebra/simplify/util.js +1 -1
- package/lib/function/algebra/simplify.js +5 -0
- package/lib/function/combinatorics/stirlingS2.js +1 -1
- package/lib/function/probability/combinations.js +11 -10
- package/lib/function/probability/gamma.js +5 -13
- package/lib/function/probability/permutations.js +2 -12
- package/lib/function/probability/product.js +19 -0
- package/lib/function/string/format.js +2 -2
- package/lib/function/utils/typeof.js +13 -13
- package/lib/index.js +5 -1
- package/lib/type/bignumber/BigNumber.js +6 -2
- package/lib/type/matrix/utils/algorithm13.js +0 -2
- package/lib/type/unit/Unit.js +2 -2
- package/lib/utils/array.js +27 -19
- package/lib/utils/bignumber/formatter.js +3 -2
- package/lib/utils/number.js +15 -10
- package/lib/version.js +1 -1
- package/package.json +13 -8
- package/src/constants.js +3 -1
- package/src/core/function/import.js +15 -2
- package/src/core/typed.js +1 -1
- package/src/expression/node/FunctionNode.js +3 -4
- package/src/expression/parse.js +432 -470
- package/src/function/algebra/decomposition/qr.js +1 -1
- package/src/function/algebra/rationalize.js +41 -43
- package/src/function/algebra/simplify/resolve.js +1 -1
- package/src/function/algebra/simplify/simplifyCore.js +3 -3
- package/src/function/algebra/simplify/util.js +1 -1
- package/src/function/algebra/simplify.js +5 -0
- package/src/function/combinatorics/stirlingS2.js +1 -1
- package/src/function/probability/combinations.js +10 -8
- package/src/function/probability/gamma.js +5 -13
- package/src/function/probability/permutations.js +2 -11
- package/src/function/probability/product.js +17 -0
- package/src/function/string/format.js +2 -2
- package/src/function/utils/typeof.js +13 -13
- package/src/index.js +5 -1
- package/src/type/bignumber/BigNumber.js +2 -1
- package/src/type/matrix/utils/algorithm13.js +0 -2
- package/src/type/unit/Unit.js +2 -2
- package/src/utils/array.js +31 -23
- package/src/utils/bignumber/formatter.js +3 -2
- package/src/utils/number.js +15 -10
- package/src/version.js +1 -1
@@ -4,7 +4,6 @@ function factory (type, config, load, typed) {
|
|
4
4
|
const simplify = load(require('./simplify'))
|
5
5
|
const simplifyCore = load(require('./simplify/simplifyCore'))
|
6
6
|
const simplifyConstant = load(require('./simplify/simplifyConstant'))
|
7
|
-
const ArgumentsError = require('../../error/ArgumentsError')
|
8
7
|
const parse = load(require('../../expression/function/parse'))
|
9
8
|
const number = require('../../utils/number')
|
10
9
|
const ConstantNode = load(require('../../expression/node/ConstantNode'))
|
@@ -26,22 +25,25 @@ function factory (type, config, load, typed) {
|
|
26
25
|
*
|
27
26
|
* Examples:
|
28
27
|
*
|
29
|
-
* math.rationalize('sin(x)+y')
|
30
|
-
*
|
28
|
+
* math.rationalize('sin(x)+y')
|
29
|
+
* // Error: There is an unsolved function call
|
30
|
+
* math.rationalize('2x/y - y/(x+1)')
|
31
|
+
* // (2*x^2-y^2+2*x)/(x*y+y)
|
31
32
|
* math.rationalize('(2x+1)^6')
|
32
|
-
* //
|
33
|
+
* // 64*x^6+192*x^5+240*x^4+160*x^3+60*x^2+12*x+1
|
33
34
|
* math.rationalize('2x/( (2x-1) / (3x+2) ) - 5x/ ( (3x+4) / (2x^2-5) ) + 3')
|
34
|
-
* //
|
35
|
+
* // -20*x^4+28*x^3+104*x^2+6*x-12)/(6*x^2+5*x-4)
|
35
36
|
* math.rationalize('x/(1-x)/(x-2)/(x-3)/(x-4) + 2x/ ( (1-2x)/(2-3x) )/ ((3-4x)/(4-5x) )') =
|
36
|
-
* //
|
37
|
-
* //
|
37
|
+
* // (-30*x^7+344*x^6-1506*x^5+3200*x^4-3472*x^3+1846*x^2-381*x)/
|
38
|
+
* // (-8*x^6+90*x^5-383*x^4+780*x^3-797*x^2+390*x-72)
|
38
39
|
*
|
39
40
|
* math.rationalize('x+x+x+y',{y:1}) // 3*x+1
|
40
41
|
* math.rationalize('x+x+x+y',{}) // 3*x+y
|
41
|
-
*
|
42
|
-
*
|
43
|
-
*
|
44
|
-
*
|
42
|
+
*
|
43
|
+
* const ret = math.rationalize('x+x+x+y',{},true)
|
44
|
+
* // ret.expression=3*x+y, ret.variables = ["x","y"]
|
45
|
+
* const ret = math.rationalize('-2+5x^2',{},true)
|
46
|
+
* // ret.expression=5*x^2-2, ret.variables = ["x"], ret.coefficients=[-2,0,5]
|
45
47
|
*
|
46
48
|
* See also:
|
47
49
|
*
|
@@ -98,31 +100,20 @@ function factory (type, config, load, typed) {
|
|
98
100
|
if (nVars >= 1) { // If expression in not a constant
|
99
101
|
const setRules = rulesRationalize() // Rules for change polynomial in near canonical form
|
100
102
|
expr = expandPower(expr) // First expand power of polynomials (cannot be made from rules!)
|
101
|
-
let redoInic = true // If has change after start, redo the beginning
|
102
|
-
let s = '' // New expression
|
103
103
|
let sBefore // Previous expression
|
104
|
-
let rules
|
105
|
-
let eDistrDiv = true
|
106
|
-
|
107
|
-
expr = simplify(expr, setRules.firstRules) // Apply the initial rules, including succ div rules
|
108
|
-
s = expr.toString()
|
109
104
|
|
110
105
|
while (true) { // Apply alternately successive division rules and distr.div.rules
|
111
|
-
|
112
|
-
expr = simplify(expr,
|
113
|
-
eDistrDiv = !eDistrDiv // Swap between Distr.Div and Succ. Div. Rules
|
106
|
+
expr = simplify(expr, setRules.firstRules) // Apply the initial rules, including succ div rules
|
107
|
+
expr = simplify(expr, setRules.distrDivRules) // and distr.div.rules until no more changes
|
114
108
|
|
115
|
-
s = expr.toString()
|
109
|
+
const s = expr.toString()
|
116
110
|
if (s === sBefore) break // No changes : end of the loop
|
117
111
|
|
118
|
-
redoInic = true
|
119
112
|
sBefore = s
|
120
113
|
}
|
121
114
|
|
122
|
-
|
123
|
-
|
124
|
-
}
|
125
|
-
expr = simplify(expr, setRules.finalRules) // Aplly final rules
|
115
|
+
expr = simplify(expr, setRules.firstRulesAgain)
|
116
|
+
expr = simplify(expr, setRules.finalRules) // Apply final rules
|
126
117
|
} // NVars >= 1
|
127
118
|
|
128
119
|
const coefficients = []
|
@@ -208,17 +199,23 @@ function factory (type, config, load, typed) {
|
|
208
199
|
const tp = node.type // node type
|
209
200
|
if (tp === 'FunctionNode') {
|
210
201
|
// No function call in polynomial expression
|
211
|
-
throw new
|
202
|
+
throw new Error('There is an unsolved function call')
|
212
203
|
} else if (tp === 'OperatorNode') {
|
213
204
|
if (node.op === '^' && node.isBinary()) {
|
214
|
-
if (node.args[1].
|
215
|
-
|
205
|
+
if (node.args[1].op === '-' && node.args[1].isUnary()) {
|
206
|
+
if (node.args[1].args[0].type !== 'ConstantNode' || !number.isInteger(parseFloat(node.args[1].args[0].value))) {
|
207
|
+
throw new Error('There is a non-integer exponent')
|
208
|
+
} else {
|
209
|
+
recPoly(node.args[0])
|
210
|
+
}
|
211
|
+
} else if (node.args[1].type !== 'ConstantNode' || !number.isInteger(parseFloat(node.args[1].value))) {
|
212
|
+
throw new Error('There is a non-integer exponent')
|
216
213
|
} else {
|
217
214
|
recPoly(node.args[0])
|
218
215
|
}
|
219
216
|
} else {
|
220
217
|
if (oper.indexOf(node.op) === -1) {
|
221
|
-
throw new
|
218
|
+
throw new Error('Operator ' + node.op + ' invalid in polynomial expression')
|
222
219
|
}
|
223
220
|
for (let i = 0; i < node.args.length; i++) {
|
224
221
|
recPoly(node.args[i])
|
@@ -234,7 +231,7 @@ function factory (type, config, load, typed) {
|
|
234
231
|
} else if (tp === 'ParenthesisNode') {
|
235
232
|
recPoly(node.content)
|
236
233
|
} else if (tp !== 'ConstantNode') {
|
237
|
-
throw new
|
234
|
+
throw new Error('type ' + tp + ' is not allowed in polynomial expression')
|
238
235
|
}
|
239
236
|
} // end of recPoly
|
240
237
|
} // end of polynomial
|
@@ -257,6 +254,7 @@ function factory (type, config, load, typed) {
|
|
257
254
|
{l: 'n*(n1^-1)', r: 'n/n1'},
|
258
255
|
{l: 'n*n1^-n2', r: 'n/n1^n2'},
|
259
256
|
{l: 'n1^-1', r: '1/n1'},
|
257
|
+
{l: 'n1^-n2', r: '1/n1^n2'},
|
260
258
|
{l: 'n*(n1/n2)', r: '(n*n1)/n2'},
|
261
259
|
{l: '1*n', r: 'n'}]
|
262
260
|
|
@@ -493,23 +491,23 @@ function factory (type, config, load, typed) {
|
|
493
491
|
if (tp === 'FunctionNode') {
|
494
492
|
// ***** FunctionName *****
|
495
493
|
// No function call in polynomial expression
|
496
|
-
throw new
|
494
|
+
throw new Error('There is an unsolved function call')
|
497
495
|
} else if (tp === 'OperatorNode') {
|
498
496
|
// ***** OperatorName *****
|
499
|
-
if ('+-*^'.indexOf(node.op) === -1) throw new
|
497
|
+
if ('+-*^'.indexOf(node.op) === -1) throw new Error('Operator ' + node.op + ' invalid')
|
500
498
|
|
501
499
|
if (noPai !== null) {
|
502
500
|
// -(unary),^ : children of *,+,-
|
503
501
|
if ((node.fn === 'unaryMinus' || node.fn === 'pow') && noPai.fn !== 'add' &&
|
504
|
-
noPai.fn !== 'subtract' && noPai.fn !== 'multiply') { throw new
|
502
|
+
noPai.fn !== 'subtract' && noPai.fn !== 'multiply') { throw new Error('Invalid ' + node.op + ' placing') }
|
505
503
|
|
506
504
|
// -,+,* : children of +,-
|
507
505
|
if ((node.fn === 'subtract' || node.fn === 'add' || node.fn === 'multiply') &&
|
508
|
-
noPai.fn !== 'add' && noPai.fn !== 'subtract') { throw new
|
506
|
+
noPai.fn !== 'add' && noPai.fn !== 'subtract') { throw new Error('Invalid ' + node.op + ' placing') }
|
509
507
|
|
510
508
|
// -,+ : first child
|
511
509
|
if ((node.fn === 'subtract' || node.fn === 'add' ||
|
512
|
-
node.fn === 'unaryMinus') && o.noFil !== 0) { throw new
|
510
|
+
node.fn === 'unaryMinus') && o.noFil !== 0) { throw new Error('Invalid ' + node.op + ' placing') }
|
513
511
|
} // Has parent
|
514
512
|
|
515
513
|
// Firers: ^,* Old: ^,&,-(unary): firers
|
@@ -529,7 +527,7 @@ function factory (type, config, load, typed) {
|
|
529
527
|
recurPol(node.args[i], node, o)
|
530
528
|
} // for in children
|
531
529
|
} else if (tp === 'SymbolNode') { // ***** SymbolName *****
|
532
|
-
if (node.name !== varname && varname !== '') { throw new
|
530
|
+
if (node.name !== varname && varname !== '') { throw new Error('There is more than one variable') }
|
533
531
|
varname = node.name
|
534
532
|
if (noPai === null) {
|
535
533
|
coefficients[1] = 1
|
@@ -537,10 +535,10 @@ function factory (type, config, load, typed) {
|
|
537
535
|
}
|
538
536
|
|
539
537
|
// ^: Symbol is First child
|
540
|
-
if (noPai.op === '^' && o.noFil !== 0) { throw new
|
538
|
+
if (noPai.op === '^' && o.noFil !== 0) { throw new Error('In power the variable should be the first parameter') }
|
541
539
|
|
542
540
|
// *: Symbol is Second child
|
543
|
-
if (noPai.op === '*' && o.noFil !== 1) { throw new
|
541
|
+
if (noPai.op === '*' && o.noFil !== 1) { throw new Error('In multiply the variable should be the second parameter') }
|
544
542
|
|
545
543
|
// Symbol: firers '',* => it means there is no exponent above, so it's 1 (cte * var)
|
546
544
|
if (o.fire === '' || o.fire === '*') {
|
@@ -556,9 +554,9 @@ function factory (type, config, load, typed) {
|
|
556
554
|
}
|
557
555
|
if (noPai.op === '^') {
|
558
556
|
// cte: second child of power
|
559
|
-
if (o.noFil !== 1) throw new
|
557
|
+
if (o.noFil !== 1) throw new Error('Constant cannot be powered')
|
560
558
|
|
561
|
-
if (!number.isInteger(valor) || valor <= 0) { throw new
|
559
|
+
if (!number.isInteger(valor) || valor <= 0) { throw new Error('Non-integer exponent is not allowed') }
|
562
560
|
|
563
561
|
for (let i = maxExpo + 1; i < valor; i++) coefficients[i] = 0
|
564
562
|
if (valor > maxExpo) coefficients[valor] = 0
|
@@ -570,7 +568,7 @@ function factory (type, config, load, typed) {
|
|
570
568
|
|
571
569
|
// Cte: firer '' => There is no exponent and no multiplication, so the exponent is 0.
|
572
570
|
if (o.fire === '') { coefficients[0] += o.cte * (o.oper === '+' ? 1 : -1) }
|
573
|
-
} else { throw new
|
571
|
+
} else { throw new Error('Type ' + tp + ' is not allowed') }
|
574
572
|
} // End of recurPol
|
575
573
|
} // End of polyToCanonical
|
576
574
|
|
@@ -38,7 +38,7 @@ function factory (type, config, load, typed, math) {
|
|
38
38
|
const args = node.args.map(function (arg) {
|
39
39
|
return resolve(arg, scope)
|
40
40
|
})
|
41
|
-
return new OperatorNode(node.op, node.fn, args)
|
41
|
+
return new OperatorNode(node.op, node.fn, args, node.implicit)
|
42
42
|
} else if (type.isParenthesisNode(node)) {
|
43
43
|
return new ParenthesisNode(resolve(node.content, scope))
|
44
44
|
} else if (type.isFunctionNode(node)) {
|
@@ -114,12 +114,12 @@ function factory (type, config, load, typed, math) {
|
|
114
114
|
const a00 = a0.args[0]
|
115
115
|
if (type.isConstantNode(a00)) {
|
116
116
|
const a00a1 = new ConstantNode(multiply(a00.value, a1.value))
|
117
|
-
return new OperatorNode(node.op, node.fn, [a00a1, a0.args[1]]) // constants on left
|
117
|
+
return new OperatorNode(node.op, node.fn, [a00a1, a0.args[1]], node.implicit) // constants on left
|
118
118
|
}
|
119
119
|
}
|
120
|
-
return new OperatorNode(node.op, node.fn, [a1, a0]) // constants on left
|
120
|
+
return new OperatorNode(node.op, node.fn, [a1, a0], node.implicit) // constants on left
|
121
121
|
}
|
122
|
-
return new OperatorNode(node.op, node.fn, [a0, a1])
|
122
|
+
return new OperatorNode(node.op, node.fn, [a0, a1], node.implicit)
|
123
123
|
} else if (node.op === '/') {
|
124
124
|
if (type.isConstantNode(a0)) {
|
125
125
|
if (isZero(a0.value)) {
|
@@ -127,7 +127,7 @@ function factory (type, config, load, typed, math) {
|
|
127
127
|
if (type.isOperatorNode(node)) {
|
128
128
|
return function (args) {
|
129
129
|
try {
|
130
|
-
return new OperatorNode(node.op, node.fn, args)
|
130
|
+
return new OperatorNode(node.op, node.fn, args, node.implicit)
|
131
131
|
} catch (err) {
|
132
132
|
console.error(err)
|
133
133
|
return []
|
@@ -351,7 +351,12 @@ function factory (type, config, load, typed, math) {
|
|
351
351
|
// const before = res.toString({parenthesis: 'all'})
|
352
352
|
|
353
353
|
// Create a new node by cloning the rhs of the matched rule
|
354
|
+
// we keep any implicit multiplication state if relevant
|
355
|
+
const implicit = res.implicit
|
354
356
|
res = repl.clone()
|
357
|
+
if (implicit && 'implicit' in repl) {
|
358
|
+
res.implicit = true
|
359
|
+
}
|
355
360
|
|
356
361
|
// Replace placeholders with their respective nodes without traversing deeper into the replaced nodes
|
357
362
|
const _transform = function (node) {
|
@@ -1,7 +1,7 @@
|
|
1
1
|
'use strict'
|
2
2
|
|
3
3
|
const isInteger = require('../../utils/number').isInteger
|
4
|
-
|
4
|
+
const product = require('./product')
|
5
5
|
function factory (type, config, load, typed) {
|
6
6
|
/**
|
7
7
|
* Compute the number of ways of picking `k` unordered outcomes from `n`
|
@@ -26,9 +26,10 @@ function factory (type, config, load, typed) {
|
|
26
26
|
* @param {number | BigNumber} k Number of objects in the subset
|
27
27
|
* @return {number | BigNumber} Number of possible combinations.
|
28
28
|
*/
|
29
|
+
|
29
30
|
const combinations = typed('combinations', {
|
30
31
|
'number, number': function (n, k) {
|
31
|
-
let
|
32
|
+
let prodrange, nMinusk
|
32
33
|
|
33
34
|
if (!isInteger(n) || n < 0) {
|
34
35
|
throw new TypeError('Positive integer value expected in function combinations')
|
@@ -40,13 +41,14 @@ function factory (type, config, load, typed) {
|
|
40
41
|
throw new TypeError('k must be less than or equal to n')
|
41
42
|
}
|
42
43
|
|
43
|
-
|
44
|
-
result = 1
|
45
|
-
for (i = 1; i <= n - max; i++) {
|
46
|
-
result = result * (max + i) / i
|
47
|
-
}
|
44
|
+
nMinusk = n - k
|
48
45
|
|
49
|
-
|
46
|
+
if (k < nMinusk) {
|
47
|
+
prodrange = product(nMinusk + 1, n)
|
48
|
+
return prodrange / product(1, k)
|
49
|
+
}
|
50
|
+
prodrange = product(k + 1, n)
|
51
|
+
return prodrange / product(1, nMinusk)
|
50
52
|
},
|
51
53
|
|
52
54
|
'BigNumber, BigNumber': function (n, k) {
|
@@ -6,7 +6,7 @@ const isInteger = require('../../utils/number').isInteger
|
|
6
6
|
function factory (type, config, load, typed) {
|
7
7
|
const multiply = load(require('../arithmetic/multiply'))
|
8
8
|
const pow = load(require('../arithmetic/pow'))
|
9
|
-
|
9
|
+
const product = require('./product')
|
10
10
|
/**
|
11
11
|
* Compute the gamma function of a value using Lanczos approximation for
|
12
12
|
* small values, and an extended Stirling approximation for large values.
|
@@ -30,7 +30,9 @@ function factory (type, config, load, typed) {
|
|
30
30
|
* @param {number | Array | Matrix} n A real or complex number
|
31
31
|
* @return {number | Array | Matrix} The gamma of `n`
|
32
32
|
*/
|
33
|
+
|
33
34
|
const gamma = typed('gamma', {
|
35
|
+
|
34
36
|
'number': function (n) {
|
35
37
|
let t, x
|
36
38
|
|
@@ -43,18 +45,7 @@ function factory (type, config, load, typed) {
|
|
43
45
|
return Infinity // Will overflow
|
44
46
|
}
|
45
47
|
|
46
|
-
|
47
|
-
let res = n - 1
|
48
|
-
while (value > 1) {
|
49
|
-
res *= value
|
50
|
-
value--
|
51
|
-
}
|
52
|
-
|
53
|
-
if (res === 0) {
|
54
|
-
res = 1 // 0! is per definition 1
|
55
|
-
}
|
56
|
-
|
57
|
-
return res
|
48
|
+
return product(1, n - 1)
|
58
49
|
}
|
59
50
|
|
60
51
|
if (n < 0.5) {
|
@@ -153,6 +144,7 @@ function factory (type, config, load, typed) {
|
|
153
144
|
* @param {BigNumber} n
|
154
145
|
* @returns {BigNumber} Returns the factorial of n
|
155
146
|
*/
|
147
|
+
|
156
148
|
function bigFactorial (n) {
|
157
149
|
if (n.isZero()) {
|
158
150
|
return new type.BigNumber(1) // 0! is per definition 1
|
@@ -4,7 +4,7 @@ const isInteger = require('../../utils/number').isInteger
|
|
4
4
|
|
5
5
|
function factory (type, config, load, typed) {
|
6
6
|
const factorial = load(require('./factorial'))
|
7
|
-
|
7
|
+
const product = require('./product')
|
8
8
|
/**
|
9
9
|
* Compute the number of ways of obtaining an ordered subset of `k` elements
|
10
10
|
* from a set of `n` elements.
|
@@ -32,10 +32,7 @@ function factory (type, config, load, typed) {
|
|
32
32
|
*/
|
33
33
|
const permutations = typed('permutations', {
|
34
34
|
'number | BigNumber': factorial,
|
35
|
-
|
36
35
|
'number, number': function (n, k) {
|
37
|
-
let result, i
|
38
|
-
|
39
36
|
if (!isInteger(n) || n < 0) {
|
40
37
|
throw new TypeError('Positive integer value expected in function permutations')
|
41
38
|
}
|
@@ -45,14 +42,8 @@ function factory (type, config, load, typed) {
|
|
45
42
|
if (k > n) {
|
46
43
|
throw new TypeError('second argument k must be less than or equal to first argument n')
|
47
44
|
}
|
48
|
-
|
49
45
|
// Permute n objects, k at a time
|
50
|
-
|
51
|
-
for (i = n - k + 1; i <= n; i++) {
|
52
|
-
result = result * i
|
53
|
-
}
|
54
|
-
|
55
|
-
return result
|
46
|
+
return product((n - k) + 1, n)
|
56
47
|
},
|
57
48
|
|
58
49
|
'BigNumber, BigNumber': function (n, k) {
|
@@ -0,0 +1,17 @@
|
|
1
|
+
/** @param {integer} i
|
2
|
+
* @param {integer} n
|
3
|
+
* @returns : product of i to n
|
4
|
+
*/
|
5
|
+
function product (i, n) {
|
6
|
+
let half
|
7
|
+
if (n < i) {
|
8
|
+
return 1
|
9
|
+
}
|
10
|
+
if (n === i) {
|
11
|
+
return n
|
12
|
+
}
|
13
|
+
half = (n + i) >> 1 // divide (n + i) by 2 and truncate to integer
|
14
|
+
return product(i, half) * product(half + 1, n)
|
15
|
+
}
|
16
|
+
|
17
|
+
module.exports = product
|
@@ -37,8 +37,8 @@ function factory (type, config, load, typed) {
|
|
37
37
|
* For example '123.4' and '1.4e7'.
|
38
38
|
* - `precision: number`
|
39
39
|
* A number between 0 and 16 to round the digits of the number. In case
|
40
|
-
* of notations 'exponential' and 'auto', `precision`
|
41
|
-
* number of significant digits returned.
|
40
|
+
* of notations 'exponential', 'engineering', and 'auto', `precision`
|
41
|
+
* defines the total number of significant digits returned.
|
42
42
|
* In case of notation 'fixed', `precision` defines the number of
|
43
43
|
* significant digits after the decimal point.
|
44
44
|
* `precision` is undefined by default.
|
@@ -29,19 +29,19 @@ function factory (type, config, load, typed) {
|
|
29
29
|
* math.type.Range | `'Range'` | `math.typeof(math.range(0, 10))`
|
30
30
|
* math.type.ResultSet | `'ResultSet'` | `math.typeof(math.eval('a=2\nb=3'))`
|
31
31
|
* math.type.Unit | `'Unit'` | `math.typeof(math.unit('45 deg'))`
|
32
|
-
* math.expression.node
|
33
|
-
* math.expression.node
|
34
|
-
* math.expression.node
|
35
|
-
* math.expression.node
|
36
|
-
* math.expression.node
|
37
|
-
* math.expression.node
|
38
|
-
* math.expression.node
|
39
|
-
* math.expression.node
|
40
|
-
* math.expression.node
|
41
|
-
* math.expression.node
|
42
|
-
* math.expression.node
|
43
|
-
* math.expression.node
|
44
|
-
* math.expression.node
|
32
|
+
* math.expression.node​.AccessorNode | `'AccessorNode'` | `math.typeof(math.parse('A[2]'))`
|
33
|
+
* math.expression.node​.ArrayNode | `'ArrayNode'` | `math.typeof(math.parse('[1,2,3]'))`
|
34
|
+
* math.expression.node​.AssignmentNode | `'AssignmentNode'` | `math.typeof(math.parse('x=2'))`
|
35
|
+
* math.expression.node​.BlockNode | `'BlockNode'` | `math.typeof(math.parse('a=2; b=3'))`
|
36
|
+
* math.expression.node​.ConditionalNode | `'ConditionalNode'` | `math.typeof(math.parse('x<0 ? -x : x'))`
|
37
|
+
* math.expression.node​.ConstantNode | `'ConstantNode'` | `math.typeof(math.parse('2.3'))`
|
38
|
+
* math.expression.node​.FunctionAssignmentNode | `'FunctionAssignmentNode'` | `math.typeof(math.parse('f(x)=x^2'))`
|
39
|
+
* math.expression.node​.FunctionNode | `'FunctionNode'` | `math.typeof(math.parse('sqrt(4)'))`
|
40
|
+
* math.expression.node​.IndexNode | `'IndexNode'` | `math.typeof(math.parse('A[2]').index)`
|
41
|
+
* math.expression.node​.ObjectNode | `'ObjectNode'` | `math.typeof(math.parse('{a:2}'))`
|
42
|
+
* math.expression.node​.ParenthesisNode | `'ParenthesisNode'` | `math.typeof(math.parse('(2+3)'))`
|
43
|
+
* math.expression.node​.RangeNode | `'RangeNode'` | `math.typeof(math.parse('1:10'))`
|
44
|
+
* math.expression.node​.SymbolNode | `'SymbolNode'` | `math.typeof(math.parse('x'))`
|
45
45
|
*
|
46
46
|
* Syntax:
|
47
47
|
*
|
package/src/index.js
CHANGED
@@ -3,8 +3,12 @@
|
|
3
3
|
module.exports = [
|
4
4
|
require('./type'), // data types (Matrix, Complex, Unit, ...)
|
5
5
|
require('./constants'), // constants
|
6
|
-
require('./expression'), // expression parsing
|
7
6
|
require('./function'), // functions
|
7
|
+
|
8
|
+
// load ./expression *after* ./function since we need to
|
9
|
+
// attach transforms to functions that are imported there
|
10
|
+
require('./expression'), // expression parsing
|
11
|
+
|
8
12
|
require('./json'), // serialization utility (math.json.reviver)
|
9
13
|
require('./error') // errors
|
10
14
|
]
|
package/src/type/unit/Unit.js
CHANGED
@@ -801,7 +801,7 @@ function factory (type, config, load, typed, math) {
|
|
801
801
|
// other = new Unit(null, valuelessUnit)
|
802
802
|
other = Unit.parse(valuelessUnit)
|
803
803
|
if (!this.equalBase(other)) {
|
804
|
-
throw new Error(
|
804
|
+
throw new Error(`Units do not match ('${other.toString()}' != '${this.toString()}')`)
|
805
805
|
}
|
806
806
|
if (other.value !== null) {
|
807
807
|
throw new Error('Cannot convert to a unit with a value')
|
@@ -813,7 +813,7 @@ function factory (type, config, load, typed, math) {
|
|
813
813
|
return other
|
814
814
|
} else if (type.isUnit(valuelessUnit)) {
|
815
815
|
if (!this.equalBase(valuelessUnit)) {
|
816
|
-
throw new Error(
|
816
|
+
throw new Error(`Units do not match ('${valuelessUnit.toString()}' != '${this.toString()}')`)
|
817
817
|
}
|
818
818
|
if (valuelessUnit.value !== null) {
|
819
819
|
throw new Error('Cannot convert to a unit with a value')
|
package/src/utils/array.js
CHANGED
@@ -218,6 +218,19 @@ export function reshape (array, sizes) {
|
|
218
218
|
throw new DimensionError(0, product(exports.size(array)), '!=')
|
219
219
|
}
|
220
220
|
|
221
|
+
var totalSize = 1
|
222
|
+
for (var sizeIndex = 0; sizeIndex < sizes.length; sizeIndex++) {
|
223
|
+
totalSize *= sizes[sizeIndex]
|
224
|
+
}
|
225
|
+
|
226
|
+
if (flatArray.length !== totalSize) {
|
227
|
+
throw new DimensionError(
|
228
|
+
product(sizes),
|
229
|
+
product(exports.size(array)),
|
230
|
+
'!='
|
231
|
+
)
|
232
|
+
}
|
233
|
+
|
221
234
|
try {
|
222
235
|
newArray = _reshape(flatArray, sizes)
|
223
236
|
} catch (e) {
|
@@ -231,41 +244,36 @@ export function reshape (array, sizes) {
|
|
231
244
|
throw e
|
232
245
|
}
|
233
246
|
|
234
|
-
if (flatArray.length > 0) {
|
235
|
-
throw new DimensionError(
|
236
|
-
product(sizes),
|
237
|
-
product(exports.size(array)),
|
238
|
-
'!='
|
239
|
-
)
|
240
|
-
}
|
241
|
-
|
242
247
|
return newArray
|
243
248
|
}
|
244
249
|
|
245
250
|
/**
|
246
|
-
*
|
251
|
+
* Iteratively re-shape a multi dimensional array to fit the specified dimensions
|
247
252
|
* @param {Array} array Array to be reshaped
|
248
253
|
* @param {Array.<number>} sizes List of sizes for each dimension
|
249
254
|
* @returns {Array} Array whose data has been formatted to fit the
|
250
255
|
* specified dimensions
|
251
|
-
*
|
252
|
-
* @throws {DimensionError} If the product of the new dimension sizes does
|
253
|
-
* not equal that of the old ones
|
254
256
|
*/
|
255
|
-
function _reshape (array, sizes) {
|
256
|
-
let accumulator = []
|
257
|
-
let i
|
258
257
|
|
259
|
-
|
260
|
-
|
261
|
-
|
258
|
+
function _reshape (array, sizes) {
|
259
|
+
// testing if there are enough elements for the requested shape
|
260
|
+
var tmpArray = array
|
261
|
+
var tmpArray2
|
262
|
+
// for each dimensions starting by the last one and ignoring the first one
|
263
|
+
for (var sizeIndex = sizes.length - 1; sizeIndex > 0; sizeIndex--) {
|
264
|
+
var size = sizes[sizeIndex]
|
265
|
+
tmpArray2 = []
|
266
|
+
|
267
|
+
// aggregate the elements of the current tmpArray in elements of the requested size
|
268
|
+
var length = tmpArray.length / size
|
269
|
+
for (var i = 0; i < length; i++) {
|
270
|
+
tmpArray2.push(tmpArray.slice(i * size, (i + 1) * size))
|
262
271
|
}
|
263
|
-
return
|
264
|
-
|
265
|
-
for (i = 0; i < sizes[0]; i += 1) {
|
266
|
-
accumulator.push(_reshape(array, sizes.slice(1)))
|
272
|
+
// set it as the new tmpArray for the next loop turn or for return
|
273
|
+
tmpArray = tmpArray2
|
267
274
|
}
|
268
|
-
|
275
|
+
|
276
|
+
return tmpArray
|
269
277
|
}
|
270
278
|
|
271
279
|
/**
|
@@ -31,8 +31,9 @@ const objectUtils = require('../object')
|
|
31
31
|
* For example '123.4' and '1.4e7'.
|
32
32
|
* {number} precision A number between 0 and 16 to round
|
33
33
|
* the digits of the number.
|
34
|
-
* In case of notations 'exponential'
|
35
|
-
* '
|
34
|
+
* In case of notations 'exponential',
|
35
|
+
* 'engineering', and 'auto',
|
36
|
+
* `precision` defines the total
|
36
37
|
* number of significant digits returned.
|
37
38
|
* In case of notation 'fixed',
|
38
39
|
* `precision` defines the number of
|