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.

Files changed (71) hide show
  1. package/HISTORY.md +48 -1
  2. package/README.md +2 -1
  3. package/dist/math.js +20114 -20090
  4. package/dist/math.min.js +7 -7
  5. package/dist/math.min.map +1 -1
  6. package/docs/core/configuration.md +1 -1
  7. package/docs/datatypes/numbers.md +1 -1
  8. package/docs/datatypes/units.md +1 -1
  9. package/docs/expressions/algebra.md +25 -1
  10. package/docs/getting_started.md +2 -2
  11. package/docs/reference/functions/format.md +2 -2
  12. package/docs/reference/functions/qr.md +2 -1
  13. package/docs/reference/functions/rationalize.md +13 -10
  14. package/docs/reference/functions/stirlingS2.md +1 -1
  15. package/docs/reference/functions/typeof.md +13 -13
  16. package/examples/advanced/add_new_datatypes/MyType.js +0 -10
  17. package/examples/advanced/add_new_datatypes/index.js +2 -6
  18. package/examples/browser/rocket_trajectory_optimization.html +2 -2
  19. package/lib/constants.js +3 -1
  20. package/lib/core/function/import.js +15 -2
  21. package/lib/core/typed.js +1 -1
  22. package/lib/expression/node/FunctionNode.js +5 -4
  23. package/lib/expression/parse.js +429 -466
  24. package/lib/function/algebra/decomposition/qr.js +1 -1
  25. package/lib/function/algebra/rationalize.js +41 -45
  26. package/lib/function/algebra/simplify/resolve.js +1 -1
  27. package/lib/function/algebra/simplify/simplifyCore.js +3 -3
  28. package/lib/function/algebra/simplify/util.js +1 -1
  29. package/lib/function/algebra/simplify.js +5 -0
  30. package/lib/function/combinatorics/stirlingS2.js +1 -1
  31. package/lib/function/probability/combinations.js +11 -10
  32. package/lib/function/probability/gamma.js +5 -13
  33. package/lib/function/probability/permutations.js +2 -12
  34. package/lib/function/probability/product.js +19 -0
  35. package/lib/function/string/format.js +2 -2
  36. package/lib/function/utils/typeof.js +13 -13
  37. package/lib/index.js +5 -1
  38. package/lib/type/bignumber/BigNumber.js +6 -2
  39. package/lib/type/matrix/utils/algorithm13.js +0 -2
  40. package/lib/type/unit/Unit.js +2 -2
  41. package/lib/utils/array.js +27 -19
  42. package/lib/utils/bignumber/formatter.js +3 -2
  43. package/lib/utils/number.js +15 -10
  44. package/lib/version.js +1 -1
  45. package/package.json +13 -8
  46. package/src/constants.js +3 -1
  47. package/src/core/function/import.js +15 -2
  48. package/src/core/typed.js +1 -1
  49. package/src/expression/node/FunctionNode.js +3 -4
  50. package/src/expression/parse.js +432 -470
  51. package/src/function/algebra/decomposition/qr.js +1 -1
  52. package/src/function/algebra/rationalize.js +41 -43
  53. package/src/function/algebra/simplify/resolve.js +1 -1
  54. package/src/function/algebra/simplify/simplifyCore.js +3 -3
  55. package/src/function/algebra/simplify/util.js +1 -1
  56. package/src/function/algebra/simplify.js +5 -0
  57. package/src/function/combinatorics/stirlingS2.js +1 -1
  58. package/src/function/probability/combinations.js +10 -8
  59. package/src/function/probability/gamma.js +5 -13
  60. package/src/function/probability/permutations.js +2 -11
  61. package/src/function/probability/product.js +17 -0
  62. package/src/function/string/format.js +2 -2
  63. package/src/function/utils/typeof.js +13 -13
  64. package/src/index.js +5 -1
  65. package/src/type/bignumber/BigNumber.js +2 -1
  66. package/src/type/matrix/utils/algorithm13.js +0 -2
  67. package/src/type/unit/Unit.js +2 -2
  68. package/src/utils/array.js +31 -23
  69. package/src/utils/bignumber/formatter.js +3 -2
  70. package/src/utils/number.js +15 -10
  71. package/src/version.js +1 -1
@@ -53,7 +53,7 @@ function factory (type, config, load, typed) {
53
53
  *
54
54
  * See also:
55
55
  *
56
- * lu
56
+ * lup, lusolve
57
57
  *
58
58
  * @param {Matrix | Array} A A two dimensional matrix or array
59
59
  * for which to get the QR decomposition.
@@ -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') // Error: There is an unsolved function call
30
- * math.rationalize('2x/y - y/(x+1)') // (2*x^2-y^2+2*x)/(x*y+y)
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
- * // 64*x^6+192*x^5+240*x^4+160*x^3+60*x^2+12*x+1
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
- * // -20*x^4+28*x^3+104*x^2+6*x-12)/(6*x^2+5*x-4)
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
- * // (-30*x^7+344*x^6-1506*x^5+3200*x^4-3472*x^3+1846*x^2-381*x)/
37
- * // (-8*x^6+90*x^5-383*x^4+780*x^3-797*x^2+390*x-72)
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
- * ret = math.rationalize('x+x+x+y',{},true)
42
- * // ret.expression=3*x+y, ret.variables = ["x","y"]
43
- * ret = math.rationalize('-2+5x^2',{},true)
44
- * // ret.expression=5*x^2-2, ret.variables = ["x"], ret.coefficients=[-2,0,5]
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
- rules = eDistrDiv ? setRules.distrDivRules : setRules.sucDivRules
112
- expr = simplify(expr, rules) // until no more changes
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
- if (redoInic) { // Apply first rules again without succ div rules (if there are changes)
123
- expr = simplify(expr, setRules.firstRulesAgain)
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 ArgumentsError('There is an unsolved function call')
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].type !== 'ConstantNode' || !number.isInteger(parseFloat(node.args[1].value))) {
215
- throw new ArgumentsError('There is a non-integer exponent')
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 ArgumentsError('Operator ' + node.op + ' invalid in polynomial expression')
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 ArgumentsError('type ' + tp + ' is not allowed in polynomial expression')
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 ArgumentsError('There is an unsolved function call')
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 ArgumentsError('Operator ' + node.op + ' invalid')
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 ArgumentsError('Invalid ' + node.op + ' placing') }
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 ArgumentsError('Invalid ' + node.op + ' placing') }
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 ArgumentsError('Invalid ' + node.op + ' placing') }
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 ArgumentsError('There is more than one variable') }
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 ArgumentsError('In power the variable should be the first parameter') }
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 ArgumentsError('In multiply the variable should be the second parameter') }
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 ArgumentsError('Constant cannot be powered')
557
+ if (o.noFil !== 1) throw new Error('Constant cannot be powered')
560
558
 
561
- if (!number.isInteger(valor) || valor <= 0) { throw new ArgumentsError('Non-integer exponent is not allowed') }
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 ArgumentsError('Type ' + tp + ' is not allowed') }
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) {
@@ -30,7 +30,7 @@ function factory (type, config, load, typed) {
30
30
  *
31
31
  * See also:
32
32
  *
33
- * Bell numbers
33
+ * bellNumbers
34
34
  *
35
35
  * @param {Number | BigNumber} n Total number of objects in the set
36
36
  * @param {Number | BigNumber} k Number of objects in the subset
@@ -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 max, result, i
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
- max = Math.max(k, n - k)
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
- return result
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
- let value = n - 2
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
- result = 1
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` defines the total
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.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'))`
32
+ * math.expression.node&#8203;.AccessorNode | `'AccessorNode'` | `math.typeof(math.parse('A[2]'))`
33
+ * math.expression.node&#8203;.ArrayNode | `'ArrayNode'` | `math.typeof(math.parse('[1,2,3]'))`
34
+ * math.expression.node&#8203;.AssignmentNode | `'AssignmentNode'` | `math.typeof(math.parse('x=2'))`
35
+ * math.expression.node&#8203;.BlockNode | `'BlockNode'` | `math.typeof(math.parse('a=2; b=3'))`
36
+ * math.expression.node&#8203;.ConditionalNode | `'ConditionalNode'` | `math.typeof(math.parse('x<0 ? -x : x'))`
37
+ * math.expression.node&#8203;.ConstantNode | `'ConstantNode'` | `math.typeof(math.parse('2.3'))`
38
+ * math.expression.node&#8203;.FunctionAssignmentNode | `'FunctionAssignmentNode'` | `math.typeof(math.parse('f(x)=x^2'))`
39
+ * math.expression.node&#8203;.FunctionNode | `'FunctionNode'` | `math.typeof(math.parse('sqrt(4)'))`
40
+ * math.expression.node&#8203;.IndexNode | `'IndexNode'` | `math.typeof(math.parse('A[2]').index)`
41
+ * math.expression.node&#8203;.ObjectNode | `'ObjectNode'` | `math.typeof(math.parse('{a:2}'))`
42
+ * math.expression.node&#8203;.ParenthesisNode | `'ParenthesisNode'` | `math.typeof(math.parse('(2+3)'))`
43
+ * math.expression.node&#8203;.RangeNode | `'RangeNode'` | `math.typeof(math.parse('1:10'))`
44
+ * math.expression.node&#8203;.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
  ]
@@ -1,5 +1,6 @@
1
1
  'use strict'
2
- const Decimal = require('decimal.js/decimal.js') // make sure to pick the es5 version
2
+
3
+ import Decimal from 'decimal.js'
3
4
 
4
5
  function factory (type, config, load, typed, math) {
5
6
  const BigNumber = Decimal.clone({precision: config.precision})
@@ -51,8 +51,6 @@ function factory (type, config, load, typed) {
51
51
  if (typeof adt === 'string' && adt === bdt) {
52
52
  // datatype
53
53
  dt = adt
54
- // convert b to the same datatype
55
- b = typed.convert(b, dt)
56
54
  // callback
57
55
  cf = typed.find(callback, [dt, dt])
58
56
  }
@@ -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('Units do not match')
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('Units do not match')
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')
@@ -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
- * Recursively re-shape a multi dimensional array to fit the specified dimensions
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
- if (sizes.length === 0) {
260
- if (array.length === 0) {
261
- throw new DimensionError(null, null, '!=')
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 array.shift()
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
- return accumulator
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' and
35
- * 'auto', `precision` defines the total
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