Repository: josdejong/mathjs
Pull request #835 (2017-04-23 12:24:20)

Extension of pow function to support Infinite exponents.
Goes someway towards addressing #804.

Tests pass with current behaviour of complex.js and will need updating when full support of infinite numbers is added there.

New behaviour of pow function:
* `(-2)^Infinity = ComplexNAN`
* `(-1)^Infinity = ComplexNAN`
* `(-0.5)^Infinity = 0` (real)
* `(-2)^(-Infinity) = 0` (real)
* `(-0.5)^(-Infinty) = ComplexNaN`

If `config.predictible = true` results are the same but `ComplexNaN` becomes `NaN`.




Patch:
diff --git a/README.md b/README.md
index ccc488b18..3fd49a6e5 100644
--- a/README.md
+++ b/README.md
@@ -4,11 +4,6 @@
 
 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. Powerful and easy to use.
 
-[![Version](https://img.shields.io/npm/v/mathjs.svg)](https://www.npmjs.com/package/mathjs)
-[![Downloads](https://img.shields.io/npm/dm/mathjs.svg)](https://www.npmjs.com/package/mathjs)
-[![Build Status](https://img.shields.io/travis/josdejong/mathjs.svg)](https://travis-ci.org/josdejong/mathjs)
-![Maintenance](https://img.shields.io/maintenance/yes/2017.svg)
-[![License](https://img.shields.io/github/license/josdejong/mathjs.svg)](https://github.com/josdejong/mathjs/blob/master/LICENSE)
 
 ## Features
 
diff --git a/docs/expressions/expression_trees.md b/docs/expressions/expression_trees.md
index ce154e4a2..1be3392e2 100644
--- a/docs/expressions/expression_trees.md
+++ b/docs/expressions/expression_trees.md
@@ -88,7 +88,7 @@ All nodes have the following methods:
     ```js
     var node = math.parse('x^2 + x/4 + 3*y');
     var filtered = node.filter(function (node) {
-      return node.isSymbolNode && node.name === 'x';
+      return node.isSymbolNode && node.name == 'x';
     });
     // returns an array with two entries: two SymbolNodes 'x'
     ```
@@ -168,7 +168,7 @@ All nodes have the following methods:
     ```js
     var node = math.parse('x^2 + 5*x');
     var transformed = node.transform(function (node, path, parent) {
-      if (node.isSymbolNode && node.name === 'x') {
+      if (node.SymbolNode && node.name == 'x') {
         return new math.expression.node.ConstantNode(3);
       }
       else {
diff --git a/lib/function/arithmetic/pow.js b/lib/function/arithmetic/pow.js
index 9ed92827d..47553248c 100644
--- a/lib/function/arithmetic/pow.js
+++ b/lib/function/arithmetic/pow.js
@@ -120,6 +120,23 @@ function factory (type, config, load, typed) {
       // Unable to express y as a fraction, so continue on
     }
 
+
+    // x^Infinity === 0 if -1 < x < 1
+    // A real number 0 is returned instead of complex(0)
+    if ((x*x < 1 && y ===  Infinity) ||
+        (x*x > 1 && y === -Infinity)) {
+      return 0;
+    }
+
+    // **for predictable mode** x^Infinity === NaN if x < -1
+    // N.B. this behavour is different from `Math.pow` which gives
+    // (-2)^Infinity === Infinity
+    if (config.predictable &&
+        ((x < -1 &&          y ===  Infinity) ||
+         (x > -1 && x < 0 && y === -Infinity))) {
+      return NaN;
+    }
+
     if (isInteger(y) || x >= 0 || config.predictable) {
       return Math.pow(x, y);
     }
diff --git a/lib/utils/bignumber/constants.js b/lib/utils/bignumber/constants.js
index fb4190a07..c41abe487 100644
--- a/lib/utils/bignumber/constants.js
+++ b/lib/utils/bignumber/constants.js
@@ -24,7 +24,7 @@ exports.phi = memoize(function (BigNumber) {
  * @returns {BigNumber} Returns pi
  */
 exports.pi = memoize(function (BigNumber) {
-  return BigNumber.acos(-1);
+  return pi = BigNumber.acos(-1);
 }, hasher);
 
 /**


Test patch:
diff --git a/test/function/arithmetic/pow.test.js b/test/function/arithmetic/pow.test.js
index 10897da97..267f1842c 100644
--- a/test/function/arithmetic/pow.test.js
+++ b/test/function/arithmetic/pow.test.js
@@ -131,6 +131,31 @@ describe('pow', function() {
     assert.throws(function () {pow(1, 2, 3)}, /TypeError: Too many arguments in function pow \(expected: 2, actual: 3\)/);
   });
 
+  it('should handle infitie exponents', function() {
+    var Ptbl = mathPredictable;
+
+     // TODO replace isNaN with complexInfinity when complex.js updates
+
+
+    assert.equal(math.pow( 3,  Infinity), Infinity);
+    assert.equal(math.pow( 3, -Infinity), 0);
+    assert(isNaN(Ptbl.pow(-3,  Infinity)));
+    assert(      math.pow(-3,  Infinity).isNaN());
+    assert.equal(math.pow(-3, -Infinity), 0);
+
+    assert.equal(math.pow( 0.3,  Infinity), 0);
+    assert.equal(math.pow( 0.3, -Infinity), Infinity);
+    assert.equal(math.pow(-0.3,  Infinity), 0);
+    assert(isNaN(Ptbl.pow(-0.3, -Infinity)));
+    assert(      math.pow(-0.3, -Infinity).isNaN());
+
+    assert.equal(math.pow( Infinity,  Infinity), Infinity);
+    assert.equal(math.pow( Infinity, -Infinity), 0); // https://www.wolframalpha.com/input/?i=infinity%5E(-infinity)
+    assert(isNaN(Ptbl.pow(-Infinity,  Infinity)));
+    assert(      math.pow(-Infinity,  Infinity).isNaN());
+    assert.equal(math.pow(-Infinity, -Infinity), 0);
+  });
+
   it('should exponentiate a complex number to the given power', function() {
     approx.deepEqual(pow(complex(3, 0), 2), complex(9, 0));
     approx.deepEqual(pow(complex(0, 2), 2), complex(-4, 0));