← Back to team overview

ubuntu-touch-coreapps-reviewers team mailing list archive

[Merge] lp:~gang65/ubuntu-calculator-app/ubuntu-calculator-app-mathjs-2.4.1 into lp:ubuntu-calculator-app

 

Bartosz Kosiorek has proposed merging lp:~gang65/ubuntu-calculator-app/ubuntu-calculator-app-mathjs-2.4.1 into lp:ubuntu-calculator-app.

Commit message:
Upgrade math.js to 2.4.1 to fix crash with factorial (LP: #1483600)

Requested reviews:
  Ubuntu Calculator Developers (ubuntu-calculator-dev)
Related bugs:
  Bug #1483600 in Ubuntu Calculator App: "The calculator will exit automaticlly when calculating result is too large "
  https://bugs.launchpad.net/ubuntu-calculator-app/+bug/1483600

For more details, see:
https://code.launchpad.net/~gang65/ubuntu-calculator-app/ubuntu-calculator-app-mathjs-2.4.1/+merge/276316

Upgrade math.js to 2.4.1 to fix crash with factorial (LP: #1483600)
-- 
Your team Ubuntu Calculator Developers is requested to review the proposed merge of lp:~gang65/ubuntu-calculator-app/ubuntu-calculator-app-mathjs-2.4.1 into lp:ubuntu-calculator-app.
=== modified file 'app/engine/math.js'
--- app/engine/math.js	2015-10-19 22:33:25 +0000
+++ app/engine/math.js	2015-10-30 20:23:23 +0000
@@ -14,8 +14,8 @@
  * It features real and complex numbers, units, matrices, a large set of
  * mathematical functions, and a flexible expression parser.
  *
- * @version 2.4.0
- * @date    2015-10-09
+ * @version 2.4.1
+ * @date    2015-10-29
  *
  * @license
  * Copyright (C) 2013-2015 Jos de Jong <wjosdejong@xxxxxxxxx>
@@ -35,8 +35,7 @@
 
 (function webpackUniversalModuleDefinition(root, factory) {
     // UCA: we delete all exports, we don't need them, and we keep only our var
-    mathJs = factory();
-})(this, function() {
+    mathJs = factory();})(this, function() {
 return /******/ (function(modules) { // webpackBootstrap
 /******/ 	// The module cache
 /******/ 	var installedModules = {};
@@ -2628,6 +2627,7 @@
 	    if (isFactory(object)) {
 	      _importFactory(object, options);
 	    }
+	    // TODO: allow a typed-function with name too
 	    else if (Array.isArray(object)) {
 	      object.forEach(function (entry) {
 	        math_import(entry, options);
@@ -2671,11 +2671,12 @@
 	    }
 
 	    if (isTypedFunction(math[name]) && isTypedFunction(value)) {
-	      // merge two typed functions
 	      if (options.override) {
-	        value = typed(extend({}, math[name].signatures, value.signatures));
+	        // give the typed function the right name
+	        value = typed(name, value.signatures);
 	      }
 	      else {
+	        // merge the existing and typed function
 	        value = typed(math[name], value);
 	      }
 
@@ -2747,11 +2748,11 @@
 	        var instance = load(factory);
 
 	        if (isTypedFunction(existing) && isTypedFunction(instance)) {
-	          // merge two typed functions
 	          if (options.override) {
-	            instance = typed(extend({}, existing.signatures, instance.signatures));
+	            // replace the existing typed function (nothing to do)
 	          }
 	          else {
+	            // merge the existing and new typed function
 	            instance = typed(existing, instance);
 	          }
 
@@ -13692,7 +13693,7 @@
 	      this._values = [];
 	      this._index = [];
 	      this._ptr = [0];
-	      this._size = [0];
+	      this._size = [0, 0];
 	      this._datatype = datatype;
 	    }
 	  }
@@ -18688,7 +18689,7 @@
 /* 79 */
 /***/ function(module, exports) {
 
-	module.exports = '2.4.0';
+	module.exports = '2.4.1';
 	// Note: This file is automatically generated when building math.js.
 	// Changes made in this file will be overwritten.
 
@@ -20851,16 +20852,15 @@
 	  'name': 'not',
 	  'category': 'Logical',
 	  'syntax': [
-	    '!x',
 	    'not x',
 	    'not(x)'
 	  ],
 	  'description': 'Logical not. Flips the boolean value of given argument.',
 	  'examples': [
-	    '!true',
+	    'not true',
 	    'not false',
-	    '!2',
-	    '!0'
+	    'not 2',
+	    'not 0'
 	  ],
 	  'seealso': [
 	    'and', 'or', 'xor'
@@ -39264,37 +39264,36 @@
 	   * @private
 	   */
 	  function _bigNthRoot(a, root) {
+	    var precision = type.BigNumber.precision;
+	    var Big = type.BigNumber.constructor({precision: precision + 2});
 	    var zero = new type.BigNumber(0);
-	    var one = new type.BigNumber(1);
+
+	    var one = new Big(1);
 	    var inv = root.isNegative();
-	    if (inv) root = root.negated();
+	    if (inv) {
+	      root = root.neg();
+	    }
 
-	    if (root.isZero()) throw new Error('Root must be non-zero');
-	    if (a.isNegative() && !root.abs().mod(2).equals(1)) throw new Error('Root must be odd when a is negative.');
+	    if (root.isZero()) {
+	      throw new Error('Root must be non-zero');
+	    }
+	    if (a.isNegative() && !root.abs().mod(2).equals(1)) {
+	      throw new Error('Root must be odd when a is negative.');
+	    }
 
 	    // edge cases zero and infinity
-	    if (a.isZero()) return zero;
-	    if (!a.isFinite())
-	    {
+	    if (a.isZero()) {
+	      return zero;
+	    }
+	    if (!a.isFinite()) {
 	      return inv ? zero : a;
 	    }
 
-	    var x = one; // Initial guess
-	    var i = 0;
-	    var iMax = 10000;
-	    do {
-	      var xPrev = x;
-	      var delta = a.div(x.pow(root.minus(1))).minus(x).div(root);
-	      x = x.plus(delta);
-	      i++;
-	    }
-	    while (!x.equals(xPrev) && i < iMax);
-
-	    if (!x.equals(xPrev)) {
-	      throw new Error('Function nthRoot failed to converge');
-	    }
-
-	    return inv ? one.div(x) : x;
+	    var x = a.abs().pow(one.div(root));
+	    // If a < 0, we require that root is an odd integer,
+	    // so (-1) ^ (1/root) = -1
+	    x = a.isNeg() ? x.neg() : x;
+	    return new type.BigNumber((inv ? one.div(x) : x).toPrecision(precision));
 	  }
 	}
 
@@ -39307,17 +39306,35 @@
 	 */
 	function _nthRoot(a, root) {
 	  var inv = root < 0;
-	  if (inv) root = -root;
+	  if (inv) {
+	    root = -root;
+	  }
 
-	  if (root === 0) throw new Error('Root must be non-zero');
-	  if (a < 0 && (Math.abs(root) % 2 != 1)) throw new Error('Root must be odd when a is negative.');
+	  if (root === 0) {
+	    throw new Error('Root must be non-zero');
+	  }
+	  if (a < 0 && (Math.abs(root) % 2 != 1)) {
+	    throw new Error('Root must be odd when a is negative.');
+	  }
 
 	  // edge cases zero and infinity
-	  if (a == 0) return 0;
-	  if (!Number.isFinite(a)) {
+	  if (a == 0) {
+	    return 0;
+	  }
+	  if (!isFinite(a)) {
 	    return inv ? 0 : a;
 	  }
 
+	  var x = Math.pow(Math.abs(a), 1/root);
+	  // If a < 0, we require that root is an odd integer,
+	  // so (-1) ^ (1/root) = -1
+	  x = a < 0 ? -x : x;
+	  return inv ? 1 / x : x;
+
+	  // Very nice algorithm, but fails with nthRoot(-2, 3).
+	  // Newton's method has some well-known problems at times:
+	  // https://en.wikipedia.org/wiki/Newton%27s_method#Failure_analysis
+	  /*
 	  var x = 1; // Initial guess
 	  var xPrev = 1;
 	  var i = 0;
@@ -39335,6 +39352,7 @@
 	  }
 
 	  return inv ? 1 / x : x;
+	  */
 	}
 
 	/**
@@ -42075,39 +42093,21 @@
 	   * @returns {BigNumber} Returns the factorial of n
 	   */
 	  function bigFactorial(n) {
-	    var value, res, preciseFacs;
-
-	    var num = n.toNumber();   // should definitely be below Number.MAX_VALUE
-	    if (num < smallBigFacs.length) {
-	      return new type.BigNumber(smallBigFacs[num]).toSD(config.precision);
+	    if (n.isZero()) {
+	      return new type.BigNumber(1); // 0! is per definition 1
 	    }
 
-	    // be wary of round-off errors
-	    var precision = config.precision + (Math.log(num) | 0);
+	    var precision = config.precision + (Math.log(n.toNumber()) | 0);
 	    var Big = type.BigNumber.constructor({precision: precision});
 
-	    // adjust n do align with the precision specific tables
-	    num -= smallBigFacs.length;
-	    if (preciseFacs = bigBigFacs[precision]) {
-	      if (preciseFacs[num]) {
-	        return new type.BigNumber(preciseFacs[num].toPrecision(config.precision));
-	      }
-	      res = preciseFacs[preciseFacs.length-1];
-	    } else {
-	      preciseFacs = bigBigFacs[precision] = [];
-	      res = new Big(smallBigFacs[smallBigFacs.length-1])
-	          .toSD(precision);
-	    }
-
-	    var one = new Big(1);
-	    value = new Big(preciseFacs.length + smallBigFacs.length);
-	    for (var i = preciseFacs.length; i < num; ++i) {
-	      preciseFacs[i] = res = res.times(value);
-	      value = value.plus(one);
-	    }
-
-	    preciseFacs[num] = res.times(value);
-	    return new type.BigNumber(preciseFacs[num].toPrecision(config.precision));
+	    var res = new Big(n);
+	    var value = n.toNumber() - 1; // number
+	    while (value > 1) {
+	      res = res.times(value);
+	      value--;
+	    }
+
+	    return new type.BigNumber(res.toPrecision(type.BigNumber.precision));
 	  }
 
 	  gamma.toTex = '\\Gamma\\left(${args[0]}\\right)';
@@ -42137,34 +42137,6 @@
 	  0.36899182659531622704e-5
 	];
 
-	// 21! >= values for each precision
-	var bigBigFacs = [];
-
-	// 0-20! values
-	var smallBigFacs = [
-	  1,
-	  1,
-	  2,
-	  6,
-	  24,
-	  120,
-	  720,
-	  5040,
-	  40320,
-	  362880,
-	  3628800,
-	  39916800,
-	  479001600,
-	  6227020800,
-	  87178291200,
-	  1307674368000,
-	  20922789888000,
-	  355687428096000,
-	  6402373705728000,
-	  121645100408832000,
-	  2432902008176640000
-	];
-
 	exports.name = 'gamma';
 	exports.factory = factory;
 
@@ -42208,6 +42180,9 @@
 	      if (!isInteger(n) || n < 0) {
 	        throw new TypeError('Positive integer value expected in function combinations');
 	      }
+	      if (!isInteger(k) || k < 0) {
+	        throw new TypeError('Positive integer value expected in function combinations');
+	      }
 	      if (k > n) {
 	        throw new TypeError('k must be less than or equal to n');
 	      }

=== modified file 'debian/changelog'
--- debian/changelog	2015-10-19 22:36:57 +0000
+++ debian/changelog	2015-10-30 20:23:23 +0000
@@ -27,6 +27,7 @@
   * Upgrade math.js to 2.1.1 to improve performance (LP: #1484851)
   * Upgrade math.js to 2.4.0 to resolve wrong calculation of sin and cos functions, 
     for values around multiples of tau (i.e. sin(7)) (LP: #1507799)
+  * Upgrade math.js to 2.4.1 to fix crash with factorial (LP: #1483600)
 
  -- Bartosz Kosiorek <gang65@xxxxxxxxxxxxxx>  Fri, 14 Aug 2015 11:04:30 +0200
 


Follow ups