mathjs 3.1.3 → 3.1.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.

@@ -11,7 +11,7 @@ Format a value of any type into a string.
11
11
  math.format(value)
12
12
  math.format(value, options)
13
13
  math.format(value, precision)
14
- math.format(value, fn)
14
+ math.format(value, callback)
15
15
  ```
16
16
 
17
17
  ### Where
@@ -47,10 +47,12 @@ math.format(value, fn)
47
47
  - `fraction: string`. Available values: 'ratio' (default) or 'decimal'.
48
48
  For example `format(fraction(1, 3))` will output '1/3' when 'ratio' is
49
49
  configured, and will output `0.(3)` when 'decimal' is configured.
50
- - `fn: Function`
51
- A custom formatting function. Can be used to override the built-in notations.
52
- Function `fn` is called with `value` as parameter and must return a string.
53
- Is useful for example to format all values inside a matrix in a particular way.
50
+ - `callback: function`
51
+ A custom formatting function, invoked for all numeric elements in `value`,
52
+ for example all elements of a matrix, or the real and imaginary
53
+ parts of a complex number. This callback can be used to override the
54
+ built-in numeric notation with any type of formatting. Function `callback`
55
+ is called with `value` as parameter and must return a string.
54
56
 
55
57
  ### Parameters
56
58
 
@@ -77,6 +79,11 @@ math.format(21385, 2); // returns '21000'
77
79
  math.format(12.071, {notation: 'fixed'}); // returns '12'
78
80
  math.format(2.3, {notation: 'fixed', precision: 2}); // returns '2.30'
79
81
  math.format(52.8, {notation: 'exponential'}); // returns '5.28e+1'
82
+
83
+ function formatCurrency(value) {
84
+ return '$' + value.toFixed(2);
85
+ }
86
+ math.format([2.1, 3, 0.016], formatCurrency}; // returns '[$2.10, $3.00, $0.02]'
80
87
  ```
81
88
 
82
89
 
@@ -2,7 +2,7 @@
2
2
 
3
3
  # Function log10
4
4
 
5
- Calculate the 10-base of a value. This is the same as calculating `log(x, 10)`.
5
+ Calculate the 10-base logarithm of a value. This is the same as calculating `log(x, 10)`.
6
6
 
7
7
  For matrices, the function is evaluated element wise.
8
8
 
@@ -64,7 +64,7 @@ Function | Description
64
64
  [math.hypot(a, b, ...)](functions/hypot.md) | Calculate the hypotenusa of a list with values.
65
65
  [math.lcm(a, b)](functions/lcm.md) | Calculate the least common multiple for two or more values or arrays.
66
66
  [math.log(x [, base])](functions/log.md) | Calculate the logarithm of a value.
67
- [math.log10(x)](functions/log10.md) | Calculate the 10-base of a value.
67
+ [math.log10(x)](functions/log10.md) | Calculate the 10-base logarithm of a value.
68
68
  [math.mod(x, y)](functions/mod.md) | Calculates the modulus, the remainder of an integer division.
69
69
  [math.multiply(x, y)](functions/multiply.md) | Multiply two values, `x * y`.
70
70
  [math.norm(x [, p])](functions/norm.md) | Calculate the norm of a number, vector or matrix.
@@ -195,7 +195,7 @@ function factory (type, config, load, typed, math) {
195
195
  */
196
196
  FunctionNode.prototype.toString = function (options) {
197
197
  var customString;
198
- var name = this.fn.toString();
198
+ var name = this.fn.toString(options);
199
199
  if (options && (typeof options.handler === 'object') && options.handler.hasOwnProperty(name)) {
200
200
  //callback is a map of callback functions
201
201
  customString = options.handler[name](this, options);
@@ -215,8 +215,12 @@ function factory (type, config, load, typed, math) {
215
215
  * @return {string} str
216
216
  */
217
217
  FunctionNode.prototype._toString = function (options) {
218
- // format the parameters like "add(2, 4.2)"
219
- return this.fn.toString() + '(' + this.args.join(', ') + ')';
218
+ var args = this.args.map(function (arg) {
219
+ return arg.toString(options);
220
+ });
221
+
222
+ // format the arguments like "add(2, 4.2)"
223
+ return this.fn.toString(options) + '(' + args.join(', ') + ')';
220
224
  };
221
225
 
222
226
  /*
@@ -328,9 +332,6 @@ function factory (type, config, load, typed, math) {
328
332
  * @return {string} str
329
333
  */
330
334
  FunctionNode.prototype._toTex = function (options) {
331
- var parenthesis = (options && options.parenthesis) ? options.parenthesis : 'keep';
332
-
333
-
334
335
  var args = this.args.map(function (arg) { //get LaTeX of the arguments
335
336
  return arg.toTex(options);
336
337
  });
@@ -14,10 +14,10 @@ function factory (type, config, load, typed, math) {
14
14
  * @extends {Node}
15
15
  * An operator with two arguments, like 2+3
16
16
  *
17
- * @param {string} op Operator name, for example '+'
18
- * @param {string} fn Function name, for example 'add'
19
- * @param {Node[]} args Operator arguments
20
- * @param {boolean} implicit Is this an implicit multiplication?
17
+ * @param {string} op Operator name, for example '+'
18
+ * @param {string} fn Function name, for example 'add'
19
+ * @param {Node[]} args Operator arguments
20
+ * @param {boolean} [implicit] Is this an implicit multiplication?
21
21
  */
22
22
  function OperatorNode(op, fn, args, implicit) {
23
23
  if (!(this instanceof OperatorNode)) {
@@ -271,7 +271,7 @@ function factory (type, config, load, typed) {
271
271
  next();
272
272
 
273
273
  if (!isDigit(c)) {
274
- // this is no legal number, it is just a dot
274
+ // this is no legal number, it is just a dot (can be dot notation)
275
275
  token_type = TOKENTYPE.UNKNOWN;
276
276
  }
277
277
  }
@@ -292,24 +292,33 @@ function factory (type, config, load, typed) {
292
292
 
293
293
  // check for exponential notation like "2.3e-4", "1.23e50" or "2e+4"
294
294
  c2 = nextPreview();
295
- if ((c == 'E' || c == 'e') && (isDigit(c2) || c2 == '-' || c2 == '+')) {
296
- token += c;
297
- next();
298
-
299
- if (c == '+' || c == '-') {
295
+ if (c == 'E' || c == 'e') {
296
+ if (isDigit(c2) || c2 == '-' || c2 == '+') {
300
297
  token += c;
301
298
  next();
302
- }
303
299
 
304
- // Scientific notation MUST be followed by an exponent
305
- if (!isDigit(c)) {
306
- // this is no legal number, exponent is missing.
307
- token_type = TOKENTYPE.UNKNOWN;
308
- }
300
+ if (c == '+' || c == '-') {
301
+ token += c;
302
+ next();
303
+ }
309
304
 
310
- while (isDigit(c)) {
311
- token += c;
305
+ // Scientific notation MUST be followed by an exponent
306
+ if (!isDigit(c)) {
307
+ throw createSyntaxError('Digit expected, got "' + c + '"');
308
+ }
309
+
310
+ while (isDigit(c)) {
311
+ token += c;
312
+ next();
313
+ }
314
+
315
+ if (c == '.') {
316
+ throw createSyntaxError('Digit expected, got "' + c + '"');
317
+ }
318
+ }
319
+ else if (c2 == '.') {
312
320
  next();
321
+ throw createSyntaxError('Digit expected, got "' + c + '"');
313
322
  }
314
323
  }
315
324
 
@@ -774,8 +783,16 @@ function factory (type, config, load, typed) {
774
783
  fn = operators[name];
775
784
 
776
785
  getTokenSkipNewline();
777
- params = [node, parseRange()];
778
- node = new OperatorNode(name, fn, params);
786
+
787
+ if (name === 'in' && token === '') {
788
+ // end of expression -> this is the unit 'in' ('inch')
789
+ node = new OperatorNode('*', 'multiply', [node, new SymbolNode('in')], true);
790
+ }
791
+ else {
792
+ // operator 'a to b' or 'a in b'
793
+ params = [node, parseRange()];
794
+ node = new OperatorNode(name, fn, params);
795
+ }
779
796
  }
780
797
 
781
798
  return node;
@@ -1196,11 +1213,15 @@ function factory (type, config, load, typed) {
1196
1213
  */
1197
1214
  function parseStringToken () {
1198
1215
  var str = '';
1199
- var tPrev = '';
1200
1216
 
1201
- while (c != '' && (c != '\"' || tPrev == '\\')) { // also handle escape character
1217
+ while (c != '' && c != '\"') {
1218
+ if (c == '\\') {
1219
+ // escape character
1220
+ str += c;
1221
+ next();
1222
+ }
1223
+
1202
1224
  str += c;
1203
- tPrev = c;
1204
1225
  next();
1205
1226
  }
1206
1227
 
@@ -67,38 +67,6 @@ function factory (type, config, load, typed) {
67
67
  }
68
68
  });
69
69
 
70
- /**
71
- * Calculate cbrt for a number
72
- *
73
- * Code from es6-shim.js:
74
- * https://github.com/paulmillr/es6-shim/blob/master/es6-shim.js#L1564-L1577
75
- *
76
- * @param {number} x
77
- * @returns {number | Complex} Returns the cubic root of x
78
- * @private
79
- */
80
- function _cbrtNumber(x) {
81
- if (x === 0) {
82
- return x;
83
- }
84
-
85
- var negate = x < 0;
86
- var result;
87
- if (negate) {
88
- x = -x;
89
- }
90
-
91
- if (isFinite(x)) {
92
- result = Math.exp(Math.log(x) / 3);
93
- // from http://en.wikipedia.org/wiki/Cube_root#Numerical_methods
94
- result = (x / (result * result) + (2 * result)) / 3;
95
- } else {
96
- result = x;
97
- }
98
-
99
- return negate ? -result : result;
100
- }
101
-
102
70
  /**
103
71
  * Calculate the cubic root for a complex number
104
72
  * @param {Complex} x
@@ -181,5 +149,37 @@ function factory (type, config, load, typed) {
181
149
  return cbrt;
182
150
  }
183
151
 
152
+ /**
153
+ * Calculate cbrt for a number
154
+ *
155
+ * Code from es6-shim.js:
156
+ * https://github.com/paulmillr/es6-shim/blob/master/es6-shim.js#L1564-L1577
157
+ *
158
+ * @param {number} x
159
+ * @returns {number | Complex} Returns the cubic root of x
160
+ * @private
161
+ */
162
+ var _cbrtNumber = Math.cbrt || function (x) {
163
+ if (x === 0) {
164
+ return x;
165
+ }
166
+
167
+ var negate = x < 0;
168
+ var result;
169
+ if (negate) {
170
+ x = -x;
171
+ }
172
+
173
+ if (isFinite(x)) {
174
+ result = Math.exp(Math.log(x) / 3);
175
+ // from http://en.wikipedia.org/wiki/Cube_root#Numerical_methods
176
+ result = (x / (result * result) + (2 * result)) / 3;
177
+ } else {
178
+ result = x;
179
+ }
180
+
181
+ return negate ? -result : result;
182
+ };
183
+
184
184
  exports.name = 'cbrt';
185
185
  exports.factory = factory;
@@ -4,7 +4,7 @@ var deepMap = require('../../utils/collection/deepMap');
4
4
 
5
5
  function factory (type, config, load, typed) {
6
6
  /**
7
- * Calculate the 10-base of a value. This is the same as calculating `log(x, 10)`.
7
+ * Calculate the 10-base logarithm of a value. This is the same as calculating `log(x, 10)`.
8
8
  *
9
9
  * For matrices, the function is evaluated element wise.
10
10
  *
@@ -31,7 +31,7 @@ function factory (type, config, load, typed) {
31
31
  var log10 = typed('log10', {
32
32
  'number': function (x) {
33
33
  if (x >= 0 || config.predictable) {
34
- return Math.log(x) / Math.LN10;
34
+ return _log10(x);
35
35
  }
36
36
  else {
37
37
  // negative value -> complex value computation
@@ -63,6 +63,16 @@ function factory (type, config, load, typed) {
63
63
  return log10;
64
64
  }
65
65
 
66
+ /**
67
+ * Calculate the 10-base logarithm of a number
68
+ * @param {number} x
69
+ * @return {number}
70
+ * @private
71
+ */
72
+ var _log10 = Math.log10 || function (x) {
73
+ return Math.log(x) / Math.LN10;
74
+ };
75
+
66
76
  exports.name = 'log10';
67
77
  exports.factory = factory;
68
78
 
@@ -11,7 +11,7 @@ function factory (type, config, load, typed) {
11
11
  * math.format(value)
12
12
  * math.format(value, options)
13
13
  * math.format(value, precision)
14
- * math.format(value, fn)
14
+ * math.format(value, callback)
15
15
  *
16
16
  * Where:
17
17
  *
@@ -46,10 +46,12 @@ function factory (type, config, load, typed) {
46
46
  * - `fraction: string`. Available values: 'ratio' (default) or 'decimal'.
47
47
  * For example `format(fraction(1, 3))` will output '1/3' when 'ratio' is
48
48
  * configured, and will output `0.(3)` when 'decimal' is configured.
49
- * - `fn: Function`
50
- * A custom formatting function. Can be used to override the built-in notations.
51
- * Function `fn` is called with `value` as parameter and must return a string.
52
- * Is useful for example to format all values inside a matrix in a particular way.
49
+ * - `callback: function`
50
+ * A custom formatting function, invoked for all numeric elements in `value`,
51
+ * for example all elements of a matrix, or the real and imaginary
52
+ * parts of a complex number. This callback can be used to override the
53
+ * built-in numeric notation with any type of formatting. Function `callback`
54
+ * is called with `value` as parameter and must return a string.
53
55
  *
54
56
  * When `value` is an Object:
55
57
  *
@@ -77,6 +79,11 @@ function factory (type, config, load, typed) {
77
79
  * math.format(2.3, {notation: 'fixed', precision: 2}); // returns '2.30'
78
80
  * math.format(52.8, {notation: 'exponential'}); // returns '5.28e+1'
79
81
  *
82
+ * function formatCurrency(value) {
83
+ * return '$' + value.toFixed(2);
84
+ * }
85
+ * math.format([2.1, 3, 0.016], formatCurrency}; // returns '[$2.10, $3.00, $0.02]'
86
+ *
80
87
  * See also:
81
88
  *
82
89
  * print
@@ -28,7 +28,7 @@ function factory (type, config, load, typed) {
28
28
  var acosh = typed('acosh', {
29
29
  'number': function (x) {
30
30
  if (x >= 1 || config.predictable) {
31
- return Math.log(Math.sqrt(x*x - 1) + x);
31
+ return _acosh(x);
32
32
  }
33
33
  if (x <= -1) {
34
34
  return new type.Complex(Math.log(Math.sqrt(x*x - 1) - x), Math.PI);
@@ -54,5 +54,15 @@ function factory (type, config, load, typed) {
54
54
  return acosh;
55
55
  }
56
56
 
57
+ /**
58
+ * Calculate the hyperbolic arccos of a number
59
+ * @param {number} x
60
+ * @return {number}
61
+ * @private
62
+ */
63
+ var _acosh = Math.acosh || function (x) {
64
+ return Math.log(Math.sqrt(x*x - 1) + x)
65
+ };
66
+
57
67
  exports.name = 'acosh';
58
68
  exports.factory = factory;
@@ -26,7 +26,7 @@ function factory (type, config, load, typed) {
26
26
  * @return {number | Complex | Array | Matrix} Hyperbolic arcsine of x
27
27
  */
28
28
  var asinh = typed('asinh', {
29
- 'number': function (x) {
29
+ 'number': Math.asinh || function (x) {
30
30
  return Math.log(Math.sqrt(x*x + 1) + x);
31
31
  },
32
32
 
@@ -27,7 +27,7 @@ function factory (type, config, load, typed) {
27
27
  var atanh = typed('atanh', {
28
28
  'number': function (x) {
29
29
  if ((x <= 1 && x >= -1) || config.predictable) {
30
- return Math.log((1 + x)/(1 - x)) / 2;
30
+ return _atanh(x);
31
31
  }
32
32
  return new type.Complex(x, 0).atanh();
33
33
  },
@@ -51,5 +51,15 @@ function factory (type, config, load, typed) {
51
51
  return atanh;
52
52
  }
53
53
 
54
+ /**
55
+ * Calculate the hyperbolic arctangent of a number
56
+ * @param {number} x
57
+ * @return {number}
58
+ * @private
59
+ */
60
+ var _atanh = Math.atanh || function (x) {
61
+ return Math.log((1 + x)/(1 - x)) / 2
62
+ };
63
+
54
64
  exports.name = 'atanh';
55
65
  exports.factory = factory;
@@ -58,9 +58,9 @@ function factory (type, config, load, typed) {
58
58
  * @returns {number}
59
59
  * @private
60
60
  */
61
- function _cosh(x) {
61
+ var _cosh = Math.cosh || function (x) {
62
62
  return (Math.exp(x) + Math.exp(-x)) / 2;
63
- }
63
+ };
64
64
 
65
65
  exports.name = 'cosh';
66
66
  exports.factory = factory;
@@ -59,13 +59,9 @@ function factory (type, config, load, typed) {
59
59
  * @returns {number}
60
60
  * @private
61
61
  */
62
- function _sinh (x) {
63
- if (Math.abs(x) < 1) {
64
- return x + (x * x * x) / 6 + (x * x * x * x * x) / 120;
65
- } else {
66
- return (Math.exp(x) - Math.exp(-x)) / 2;
67
- }
68
- }
62
+ var _sinh = Math.sinh || function (x) {
63
+ return (Math.exp(x) - Math.exp(-x)) / 2;
64
+ };
69
65
 
70
66
  exports.name = 'sinh';
71
67
  exports.factory = factory;
@@ -62,10 +62,10 @@ function factory (type, config, load, typed) {
62
62
  * @returns {number}
63
63
  * @private
64
64
  */
65
- function _tanh (x) {
65
+ var _tanh = Math.tanh || function (x) {
66
66
  var e = Math.exp(2 * x);
67
67
  return (e - 1) / (e + 1);
68
- }
68
+ };
69
69
 
70
70
  exports.name = 'tanh';
71
71
  exports.factory = factory;
@@ -2633,6 +2633,9 @@ function factory (type, config, load, typed, math) {
2633
2633
  hr: 'hour',
2634
2634
  hrs: 'hour',
2635
2635
  days: 'day',
2636
+ weeks: 'week',
2637
+ months: 'month',
2638
+ years: 'year',
2636
2639
 
2637
2640
  hertz: 'hertz',
2638
2641
 
@@ -28,7 +28,7 @@ exports.isInteger = function(value) {
28
28
  * @param {number} x
29
29
  * @returns {*}
30
30
  */
31
- exports.sign = function(x) {
31
+ exports.sign = Math.sign || function(x) {
32
32
  if (x > 0) {
33
33
  return 1;
34
34
  }
package/lib/version.js CHANGED
@@ -1,3 +1,3 @@
1
- module.exports = '3.1.3';
1
+ module.exports = '3.1.4';
2
2
  // Note: This file is automatically generated when building math.js.
3
3
  // Changes made in this file will be overwritten.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mathjs",
3
- "version": "3.1.3",
3
+ "version": "3.1.4",
4
4
  "description": "Math.js is an extensive math library for JavaScript and Node.js. It features a flexible expression parser and offers an integrated solution to work with numbers, big numbers, complex numbers, units, and matrices.",
5
5
  "author": "Jos de Jong <wjosdejong@gmail.com> (https://github.com/josdejong)",
6
6
  "contributors": [
@@ -362,6 +362,18 @@ describe('FunctionNode', function() {
362
362
  assert.equal(n.toString(), 'sqrt(4)');
363
363
  });
364
364
 
365
+ it ('should pass options when stringifying a FunctionNode', function () {
366
+ var s = new SymbolNode('sqrt');
367
+ var a = new ConstantNode(2);
368
+ var b = new SymbolNode('x');
369
+ var c = new OperatorNode('*', 'multiply', [a, b], true); // implicit
370
+ var n = new FunctionNode(s, [c]);
371
+
372
+ assert.equal(n.toString(), 'sqrt(2 x)');
373
+ var options = {implicit: 'show'};
374
+ assert.equal(n.toString(options), 'sqrt(2 * x)');
375
+ });
376
+
365
377
  it ('should stringify a FunctionNode with custom toString', function () {
366
378
  //Also checks if the custom functions get passed on to the children
367
379
  var customFunction = function (node, options) {
@@ -231,6 +231,17 @@ describe('parse', function() {
231
231
  assert.throws(function () {parseAndEval('.'); }, SyntaxError);
232
232
  assert.throws(function () {parseAndEval('3.2.2'); }, SyntaxError);
233
233
  assert.throws(function () {parseAndEval('3.2e2.2'); }, SyntaxError);
234
+
235
+ assert.throws(function () {parseAndEval('3e0.5'); }, /Digit expected, got "."/);
236
+ assert.throws(function () {parseAndEval('3e.5'); }, /Digit expected, got "."/);
237
+ assert.throws(function () {parseAndEval('-3e0.5'); }, /Digit expected, got "."/);
238
+ assert.throws(function () {parseAndEval('-3e.5'); }, /Digit expected, got "."/);
239
+ assert.throws(function () {parseAndEval('3e-0.5'); }, /Digit expected, got "."/);
240
+ assert.throws(function () {parseAndEval('3e-.5'); }, /Digit expected, got "."/);
241
+ assert.throws(function () {parseAndEval('-3e-0.5'); }, /Digit expected, got "."/);
242
+ assert.throws(function () {parseAndEval('-3e-.5'); }, /Digit expected, got "."/);
243
+
244
+ assert.throws(function () {parseAndEval('2e+a'); }, /Digit expected, got "a"/);
234
245
  });
235
246
 
236
247
  });
@@ -274,6 +285,15 @@ describe('parse', function() {
274
285
  assert.deepEqual(parseAndEval(' "hi" '), "hi");
275
286
  });
276
287
 
288
+ it('should parse a with escaped characters', function() {
289
+ assert.deepEqual(parseAndEval('"line end\\nnext"'), 'line end\nnext');
290
+ assert.deepEqual(parseAndEval('"line end\\n"'), 'line end\n');
291
+ assert.deepEqual(parseAndEval('"tab\\tnext"'), 'tab\tnext');
292
+ assert.deepEqual(parseAndEval('"tab\\t"'), 'tab\t');
293
+ assert.deepEqual(parseAndEval('"escaped backslash\\\\next"'), 'escaped backslash\\next');
294
+ assert.deepEqual(parseAndEval('"escaped backslash\\\\"'), 'escaped backslash\\');
295
+ });
296
+
277
297
  it('should throw an error with invalid strings', function() {
278
298
  assert.throws(function () {parseAndEval('"hi'); }, SyntaxError);
279
299
  assert.throws(function () {parseAndEval(' hi" '); }, Error);
@@ -364,9 +384,9 @@ describe('parse', function() {
364
384
  approx.deepEqual(parseAndEval('2 in to meter'), new Unit(2, 'inch').to('meter'));
365
385
  approx.deepEqual(parseAndEval('2 in in meter'), new Unit(2, 'inch').to('meter'));
366
386
  approx.deepEqual(parseAndEval('a in inch', {a: new Unit(5.08, 'cm')}), new Unit(2, 'inch').to('inch'));
367
- // Note: the following is not supported (due to conflicts):
368
- //approx.deepEqual(parseAndEval('(2+3) in'), new Unit(5, 'inch'));
369
- //approx.deepEqual(parseAndEval('a in', {a: 5}), new Unit(5, 'inch'));
387
+ approx.deepEqual(parseAndEval('(2+3) in'), new Unit(5, 'in'));
388
+ approx.deepEqual(parseAndEval('a in', {a: 5}), new Unit(5, 'in'));
389
+ approx.deepEqual(parseAndEval('0.5in + 1.5in to cm'), new Unit(5.08, 'cm').to('cm'));
370
390
  });
371
391
  });
372
392