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

Added BigNumber support for distance() and intersect() functions
This PR fixes  #992 . 
`distance` and `intersect` functions from geometry package now can work with big numbers.


Patch:
diff --git a/lib/function/geometry/distance.js b/lib/function/geometry/distance.js
index 1826191fb..9e95ef798 100644
--- a/lib/function/geometry/distance.js
+++ b/lib/function/geometry/distance.js
@@ -2,6 +2,13 @@
 
 function factory (type, config, load, typed) {
   var matrix = load(require('../../type/matrix/function/matrix'));
+  var add = load(require('../arithmetic/addScalar'));
+  var subtract = load(require('../arithmetic/subtract'));
+  var multiply = load(require('../arithmetic/multiplyScalar'));
+  var divide = load(require('../arithmetic/divideScalar'));
+  var negate = load(require('../arithmetic/unaryMinus'));
+  var sqrt = load(require('../arithmetic/sqrt'));
+  var abs = load(require('../arithmetic/abs'));
 
   /**
     * Calculates:
@@ -59,12 +66,12 @@ function factory (type, config, load, typed) {
     'Array, Array, Array': function(x, y, z){
       // Point to Line 2D; (x=Point, y=LinePoint1, z=LinePoint2)
       if (x.length == 2 && y.length == 2 && z.length == 2){
-        if (!_2d(x)) { throw new TypeError('Array with 2 numbers expected for first argument'); }
-        if (!_2d(y)) { throw new TypeError('Array with 2 numbers expected for second argument'); }
-        if (!_2d(z)) { throw new TypeError('Array with 2 numbers expected for third argument'); }
-        var m = (z[1]-z[0])/(y[1]-y[0]);
-        var xCoeff = m*m*y[0];
-        var yCoeff = -1*(m*y[0]);
+        if (!_2d(x)) { throw new TypeError('Array with 2 numbers or BigNumbers expected for first argument'); }
+        if (!_2d(y)) { throw new TypeError('Array with 2 numbers or BigNumbers expected for second argument'); }
+        if (!_2d(z)) { throw new TypeError('Array with 2 numbers or BigNumbers expected for third argument'); }
+        var m = divide(subtract(z[1], z[0]), subtract(y[1], y[0]));
+        var xCoeff = multiply(multiply(m, m), y[0]);
+        var yCoeff = negate(multiply(m, y[0]));
         var constant = x[1];
 
         return _distancePointLine2D(x[0], x[1], xCoeff, yCoeff, constant);
@@ -75,14 +82,14 @@ function factory (type, config, load, typed) {
     },
     'Object, Object, Object': function(x, y, z){
       if (Object.keys(x).length == 2 && Object.keys(y).length == 2 && Object.keys(z).length == 2){
-        if (!_2d(x)) { throw new TypeError('Values of pointX and pointY should be numbers'); }
-        if (!_2d(y)) { throw new TypeError('Values of lineOnePtX and lineOnePtY should be numbers'); }
-        if (!_2d(z)) { throw new TypeError('Values of lineTwoPtX and lineTwoPtY should be numbers'); }
+        if (!_2d(x)) { throw new TypeError('Values of pointX and pointY should be numbers or BigNumbers'); }
+        if (!_2d(y)) { throw new TypeError('Values of lineOnePtX and lineOnePtY should be numbers or BigNumbers'); }
+        if (!_2d(z)) { throw new TypeError('Values of lineTwoPtX and lineTwoPtY should be numbers or BigNumbers'); }
         if (x.hasOwnProperty('pointX') && x.hasOwnProperty('pointY') && y.hasOwnProperty('lineOnePtX') &&
           y.hasOwnProperty('lineOnePtY') && z.hasOwnProperty('lineTwoPtX') && z.hasOwnProperty('lineTwoPtY')){
-          var m = (z.lineTwoPtY-z.lineTwoPtX)/(y.lineOnePtY-y.lineOnePtX);
-          var xCoeff = m*m*y.lineOnePtX;
-          var yCoeff = -1*(m*y.lineOnePtX);
+          var m = divide(subtract(z.lineTwoPtY, z.lineTwoPtX), subtract(y.lineOnePtY, y.lineOnePtX));
+          var xCoeff = multiply(multiply(m, m), y.lineOnePtX);
+          var yCoeff = negate(multiply(m, y.lineOnePtX));
           var constant = x.pointX;
 
           return _distancePointLine2D(x.pointX, x.pointY, xCoeff, yCoeff, constant);
@@ -98,29 +105,29 @@ function factory (type, config, load, typed) {
     'Array, Array': function(x, y){
       // Point to Line 2D; (x=[pointX, pointY], y=[x-coeff, y-coeff, const])
       if (x.length == 2 && y.length == 3){
-        if (!_2d(x)) { throw new TypeError('Array with 2 numbers expected for first argument'); }
-        if (!_3d(y)) { throw new TypeError('Array with 3 numbers expected for second argument'); }
+        if (!_2d(x)) { throw new TypeError('Array with 2 numbers or BigNumbers expected for first argument'); }
+        if (!_3d(y)) { throw new TypeError('Array with 3 numbers or BigNumbers expected for second argument'); }
 
         return _distancePointLine2D(x[0], x[1], y[0], y[1], y[2]);
       }
       // Point to Line 3D
       else if (x.length == 3 && y.length == 6){
-        if (!_3d(x)) { throw new TypeError('Array with 3 numbers expected for first argument'); }
-        if (!_parametricLine(y)) { throw new TypeError('Array with 6 numbers expected for second argument'); }
+        if (!_3d(x)) { throw new TypeError('Array with 3 numbers or BigNumbers expected for first argument'); }
+        if (!_parametricLine(y)) { throw new TypeError('Array with 6 numbers or BigNumbers expected for second argument'); }
 
         return _distancePointLine3D(x[0], x[1], x[2], y[0], y[1], y[2], y[3], y[4], y[5]);
       }
       // Point to Point 2D
       else if (x.length == 2 && y.length == 2){
-        if (!_2d(x)) { throw new TypeError('Array with 2 numbers expected for first argument'); }
-        if (!_2d(y)) { throw new TypeError('Array with 2 numbers expected for second argument'); }
+        if (!_2d(x)) { throw new TypeError('Array with 2 numbers or BigNumbers expected for first argument'); }
+        if (!_2d(y)) { throw new TypeError('Array with 2 numbers or BigNumbers expected for second argument'); }
 
         return _distance2d(x[0], x[1], y[0], y[1]);
       }
       // Point to Point 3D
       else if(x.length == 3 && y.length == 3){
-        if (!_3d(x)) { throw new TypeError('Array with 3 numbers expected for first argument'); }
-        if (!_3d(y)) { throw new TypeError('Array with 3 numbers expected for second argument'); }
+        if (!_3d(x)) { throw new TypeError('Array with 3 numbers or BigNumbers expected for first argument'); }
+        if (!_3d(y)) { throw new TypeError('Array with 3 numbers or BigNumbers expected for second argument'); }
 
         return _distance3d(x[0], x[1], x[2], y[0], y[1], y[2]);
       }
@@ -130,10 +137,10 @@ function factory (type, config, load, typed) {
     },
     'Object, Object': function(x, y){
       if (Object.keys(x).length == 2 && Object.keys(y).length == 3){
-        if (!_2d(x)) { throw new TypeError('Values of pointX and pointY should be numbers'); }
-        if (!_3d(y)) { throw new TypeError('Values of xCoeffLine, yCoeffLine and constant should be numbers'); }
+        if (!_2d(x)) { throw new TypeError('Values of pointX and pointY should be numbers or BigNumbers'); }
+        if (!_3d(y)) { throw new TypeError('Values of xCoeffLine, yCoeffLine and constant should be numbers or BigNumbers'); }
         if (x.hasOwnProperty('pointX') && x.hasOwnProperty('pointY') && y.hasOwnProperty('xCoeffLine') &&
-          y.hasOwnProperty('yCoeffLine') && y.hasOwnProperty('yCoeffLine')){
+          y.hasOwnProperty('yCoeffLine') && y.hasOwnProperty('constant')){
 
           return _distancePointLine2D(x.pointX, x.pointY, y.xCoeffLine, y.yCoeffLine, y.constant);
         }
@@ -143,8 +150,8 @@ function factory (type, config, load, typed) {
       }
       // Point to Line 3D
       else if (Object.keys(x).length == 3 && Object.keys(y).length == 6){
-        if (!_3d(x)) { throw new TypeError('Values of pointX, pointY and pointZ should be numbers'); }
-        if (!_parametricLine(y)) { throw new TypeError('Values of x0, y0, z0, a, b and c should be numbers'); }
+        if (!_3d(x)) { throw new TypeError('Values of pointX, pointY and pointZ should be numbers or BigNumbers'); }
+        if (!_parametricLine(y)) { throw new TypeError('Values of x0, y0, z0, a, b and c should be numbers or BigNumbers'); }
         if (x.hasOwnProperty('pointX') && x.hasOwnProperty('pointY') && y.hasOwnProperty('x0') &&
           y.hasOwnProperty('y0') && y.hasOwnProperty('z0') && y.hasOwnProperty('a') &&
           y.hasOwnProperty('b') && y.hasOwnProperty('c')){
@@ -157,8 +164,8 @@ function factory (type, config, load, typed) {
       }
       // Point to Point 2D
       else if (Object.keys(x).length == 2 && Object.keys(y).length == 2){
-        if (!_2d(x)) { throw new TypeError('Values of pointOneX and pointOneY should be numbers'); }
-        if (!_2d(y)) { throw new TypeError('Values of pointTwoX and pointTwoY should be numbers'); }
+        if (!_2d(x)) { throw new TypeError('Values of pointOneX and pointOneY should be numbers or BigNumbers'); }
+        if (!_2d(y)) { throw new TypeError('Values of pointTwoX and pointTwoY should be numbers or BigNumbers'); }
         if (x.hasOwnProperty('pointOneX') && x.hasOwnProperty('pointOneY') &&
           y.hasOwnProperty('pointTwoX') && y.hasOwnProperty('pointTwoY')){
 
@@ -170,8 +177,8 @@ function factory (type, config, load, typed) {
       }
       // Point to Point 3D
       else if(Object.keys(x).length == 3 && Object.keys(y).length == 3){
-        if (!_3d(x)) { throw new TypeError('Values of pointOneX, pointOneY and pointOneZ should be numbers'); }
-        if (!_3d(y)) { throw new TypeError('Values of pointTwoX, pointTwoY and pointTwoZ should be numbers'); }
+        if (!_3d(x)) { throw new TypeError('Values of pointOneX, pointOneY and pointOneZ should be numbers or BigNumbers'); }
+        if (!_3d(y)) { throw new TypeError('Values of pointTwoX, pointTwoY and pointTwoZ should be numbers or BigNumbers'); }
         if (x.hasOwnProperty('pointOneX') && x.hasOwnProperty('pointOneY') && x.hasOwnProperty('pointOneZ') &&
           y.hasOwnProperty('pointTwoX') && y.hasOwnProperty('pointTwoY') && y.hasOwnProperty('pointTwoZ')){
 
@@ -191,110 +198,117 @@ function factory (type, config, load, typed) {
       return _distancePairwise(arr);
     }
   });
-  return distance;
-}
 
-function _2d(a){
-  // checks if the number of arguments are correct in count and are valid (should be numbers)
-  if (a.constructor !== Array){
-    a = _objectToArray(a);
+  function _isNumber(a) {
+    // distance supports numbers and bignumbers
+    return (typeof a === 'number' || type.isBigNumber(a));
   }
-  return typeof a[0] === 'number' && typeof a[1] === 'number';
-}
 
-function _3d(a){
-  // checks if the number of arguments are correct in count and are valid (should be numbers)
-  if (a.constructor !== Array){
-    a = _objectToArray(a);
+  function _2d(a){
+    // checks if the number of arguments are correct in count and are valid (should be numbers)
+    if (a.constructor !== Array){
+      a = _objectToArray(a);
+    }
+    return _isNumber(a[0]) && _isNumber(a[1]);
   }
-  return typeof a[0] === 'number' && typeof a[1] === 'number' && typeof a[2] === 'number';
-}
 
-function _parametricLine(a){
-  if (a.constructor !== Array){
-    a = _objectToArray(a);
+  function _3d(a){
+    // checks if the number of arguments are correct in count and are valid (should be numbers)
+    if (a.constructor !== Array){
+      a = _objectToArray(a);
+    }
+    return _isNumber(a[0]) && _isNumber(a[1]) &&  _isNumber(a[2]);
   }
-  return typeof a[0] === 'number' && typeof a[1] === 'number' && typeof a[2] === 'number' &&
-    typeof a[3] === 'number' && typeof a[4] === 'number' && typeof a[5] === 'number';
 
-}
+  function _parametricLine(a){
+    if (a.constructor !== Array){
+      a = _objectToArray(a);
+    }
+    return _isNumber(a[0]) && _isNumber(a[1]) && _isNumber(a[2]) &&
+      _isNumber(a[3]) && _isNumber(a[4]) && _isNumber(a[5]);
+  }
 
-function _objectToArray(o){
-  var keys = Object.keys(o);
-  var a = [];
-  for (var i = 0; i < keys.length; i++) {
-    a.push(o[keys[i]]);
+  function _objectToArray(o){
+    var keys = Object.keys(o);
+    var a = [];
+    for (var i = 0; i < keys.length; i++) {
+      a.push(o[keys[i]]);
+    }
+    return a;
   }
-  return a;
-}
 
-function _pairwise(a){
-  //checks for valid arguments passed to _distancePairwise(Array)
-  if (a[0].length == 2 && typeof a[0][0] === 'number' && typeof a[0][1] === 'number'){
-    for(var i in a){
-      if (a[i].length != 2 || typeof a[i][0] !== 'number' || typeof a[i][1] !== 'number'){
-        return false;
+  function _pairwise(a){
+    //checks for valid arguments passed to _distancePairwise(Array)
+    if (a[0].length == 2 && _isNumber(a[0][0]) && _isNumber(a[0][1])){
+      for(var i in a){
+        if (a[i].length != 2 || !_isNumber(a[i][0]) || !_isNumber(a[i][1])){
+          return false;
+        }
       }
     }
-  }
-  else if (a[0].length == 3 && typeof a[0][0] === 'number' && typeof a[0][1] === 'number' && typeof a[0][2] === 'number'){
-    for(var i in a){
-      if (a[i].length != 3 || typeof a[i][0] !== 'number' || typeof a[i][1] !== 'number' || typeof a[i][2] !== 'number'){
-        return false;
+    else if (a[0].length == 3 && _isNumber(a[0][0]) && _isNumber(a[0][1]) && _isNumber(a[0][2])){
+      for(var i in a){
+        if (a[i].length != 3 || !_isNumber(a[i][0]) || !_isNumber(a[i][1]) || !_isNumber(a[i][2])){
+          return false;
+        }
       }
     }
+    else{
+      return false;
+    }
+    return true;
   }
-  else{
-    return false;
-  }
-  return true;
-}
 
-function _distancePointLine2D(x, y, a, b, c){
-  var num =  Math.abs(a*x + b*y + c);
-  var den = Math.pow((a*a + b*b), 0.5);
-  var result = (num/den);
-  return result;
-}
+  function _distancePointLine2D(x, y, a, b, c){
+    var num =  abs(add(add(multiply(a, x), multiply(b, y)), c));
+    var den = sqrt(add(multiply(a, a), multiply(b, b)));
+    var result = divide(num, den);
+    return result;
+  }
 
-function _distancePointLine3D(x, y, z, x0, y0, z0, a, b, c){
-  var num = [((y0-y)*(c))-((z0-z)*(b)), ((z0-z)*(a))-((x0-x)*(c)), ((x0-x)*(b))-((y0-y)*(a))]
-  num = Math.pow(num[0]*num[0] + num[1]*num[1] + num[2]*num[2], 0.5);
-  var den = Math.pow(a*a + b*b + c*c, 0.5);
-  var result = num/den;
-  return result;
-}
+  function _distancePointLine3D(x, y, z, x0, y0, z0, a, b, c){
+    var num = [ subtract(multiply(subtract(y0, y), c), multiply(subtract(z0, z), b)),
+                subtract(multiply(subtract(z0, z), a), multiply(subtract(x0, x), c)),
+                subtract(multiply(subtract(x0, x), b), multiply(subtract(y0, y), a)) ];
+    num = sqrt(add(add(multiply(num[0], num[0]), multiply(num[1], num[1])), multiply(num[2], num[2])));
+    var den = sqrt(add(add(multiply(a, a), multiply(b, b)), multiply(c, c)));
+    var result = divide(num, den);
+    return result;
+  }
 
-function _distance2d(x1, y1, x2, y2){
-  var yDiff = y2 - y1;
-  var xDiff = x2 - x1;
-  var radicant = yDiff * yDiff + xDiff * xDiff;
-  var result = Math.pow(radicant, 0.5);
-  return result;
-}
+  function _distance2d(x1, y1, x2, y2){
+    var yDiff = subtract(y2, y1);
+    var xDiff = subtract(x2, x1);
+    var radicant = add(multiply(yDiff, yDiff), multiply(xDiff, xDiff));
+    var result = sqrt(radicant);
+    return result;
+  }
 
-function _distance3d(x1, y1, z1, x2, y2, z2){
-  var zDiff = z2 - z1;
-  var yDiff = y2 - y1;
-  var xDiff = x2 - x1;
-  var radicant = zDiff * zDiff + yDiff * yDiff + xDiff * xDiff;
-  var result = Math.pow(radicant, 0.5);
-  return result;
-}
+  function _distance3d(x1, y1, z1, x2, y2, z2){
+    var zDiff = subtract(z2, z1);
+    var yDiff = subtract(y2, y1);
+    var xDiff = subtract(x2, x1);
+    var radicant = add(add(multiply(zDiff, zDiff), multiply(yDiff, yDiff)), multiply(xDiff, xDiff));
+    var result = sqrt(radicant);
+    return result;
+  }
 
-function _distancePairwise(a){
-  var result = [];
-  for(var i = 0; i < a.length-1; i++){
-    for(var j = i+1; j < a.length; j++){
-      if (a[0].length == 2){
-        result.push(_distance2d(a[i][0], a[i][1], a[j][0], a[j][1]));
-      }
-      else if (a[0].length == 3){
-        result.push(_distance3d(a[i][0], a[i][1], a[i][2], a[j][0], a[j][1], a[j][2]));
+  function _distancePairwise(a){
+    var result = [];
+    for(var i = 0; i < a.length-1; i++){
+      for(var j = i+1; j < a.length; j++){
+        if (a[0].length == 2){
+          result.push(_distance2d(a[i][0], a[i][1], a[j][0], a[j][1]));
+        }
+        else if (a[0].length == 3){
+          result.push(_distance3d(a[i][0], a[i][1], a[i][2], a[j][0], a[j][1], a[j][2]));
+        }
       }
     }
+    return result;
   }
-  return result;
+
+  return distance;
 }
 
 exports.name = 'distance';
diff --git a/lib/function/geometry/intersect.js b/lib/function/geometry/intersect.js
index ad2be7e55..2fcc4fbe4 100644
--- a/lib/function/geometry/intersect.js
+++ b/lib/function/geometry/intersect.js
@@ -4,9 +4,14 @@ function factory (type, config, load, typed) {
 
   var abs = load(require('../arithmetic/abs'));
   var add = load(require('../arithmetic/add'));
+  var addScalar = load(require('../arithmetic/addScalar'));
   var matrix = load(require('../../type/matrix/function/matrix'));
   var multiply = load(require('../arithmetic/multiply'));
+  var multiplyScalar = load(require('../arithmetic/multiplyScalar'));
+  var divideScalar = load(require('../arithmetic/divideScalar'));
   var subtract = load(require('../arithmetic/subtract'));
+  var smaller = load(require('../relational/smaller'));
+  var equalScalar = load(require('../relational/equalScalar'));
 
   /**
    * Calculates the point of intersection of two lines in two or three dimensions
@@ -37,8 +42,8 @@ function factory (type, config, load, typed) {
    */
   var intersect = typed('intersect', {
     'Array, Array, Array': function (x, y, plane) {
-      if (!_3d(x)) { throw new TypeError('Array with 3 numbers expected for first argument'); }
-      if (!_3d(y)) { throw new TypeError('Array with 3 numbers expected for second argument'); }
+      if (!_3d(x)) { throw new TypeError('Array with 3 numbers or BigNumbers expected for first argument'); }
+      if (!_3d(y)) { throw new TypeError('Array with 3 numbers or BigNumbers expected for second argument'); }
       if (!_4d(plane)) { throw new TypeError('Array with 4 numbers expected as third argument'); }
 
       return _intersectLinePlane(x[0], x[1], x[2], y[0], y[1], y[2], plane[0], plane[1], plane[2], plane[3]);
@@ -46,18 +51,18 @@ function factory (type, config, load, typed) {
 
     'Array, Array, Array, Array': function (w, x, y, z) {
       if (w.length === 2) {
-        if (!_2d(w)) { throw new TypeError('Array with 2 numbers expected for first argument'); }
-        if (!_2d(x)) { throw new TypeError('Array with 2 numbers expected for second argument'); }
-        if (!_2d(y)) { throw new TypeError('Array with 2 numbers expected for third argument'); }
-        if (!_2d(z)) { throw new TypeError('Array with 2 numbers expected for fourth argument'); }
+        if (!_2d(w)) { throw new TypeError('Array with 2 numbers or BigNumbers expected for first argument'); }
+        if (!_2d(x)) { throw new TypeError('Array with 2 numbers or BigNumbers expected for second argument'); }
+        if (!_2d(y)) { throw new TypeError('Array with 2 numbers or BigNumbers expected for third argument'); }
+        if (!_2d(z)) { throw new TypeError('Array with 2 numbers or BigNumbers expected for fourth argument'); }
 
         return _intersect2d(w, x, y, z);
       }
       else if (w.length === 3) {
-        if (!_3d(w)) { throw new TypeError('Array with 3 numbers expected for first argument'); }
-        if (!_3d(x)) { throw new TypeError('Array with 3 numbers expected for second argument'); }
-        if (!_3d(y)) { throw new TypeError('Array with 3 numbers expected for third argument'); }
-        if (!_3d(z)) { throw new TypeError('Array with 3 numbers expected for fourth argument'); }
+        if (!_3d(w)) { throw new TypeError('Array with 3 numbers or BigNumbers expected for first argument'); }
+        if (!_3d(x)) { throw new TypeError('Array with 3 numbers or BigNumbers expected for second argument'); }
+        if (!_3d(y)) { throw new TypeError('Array with 3 numbers or BigNumbers expected for third argument'); }
+        if (!_3d(z)) { throw new TypeError('Array with 3 numbers or BigNumbers expected for fourth argument'); }
 
         return _intersect3d(w[0], w[1], w[2], x[0], x[1], x[2], y[0], y[1], y[2], z[0], z[1], z[2]);
       }
@@ -76,16 +81,21 @@ function factory (type, config, load, typed) {
     }
   });
 
+  function _isNumber(a) {
+    // intersect supports numbers and bignumbers
+    return (typeof a === 'number' || type.isBigNumber(a));
+  }
+
   function _2d(x) {
-    return x.length === 2 && typeof x[0] === 'number' && typeof x[1] === 'number';
+    return x.length === 2 && _isNumber(x[0]) && _isNumber(x[1]);
   }
 
   function _3d(x) {
-    return x.length === 3 && typeof x[0] === 'number' && typeof x[1] === 'number' && typeof x[2] === 'number';
+    return x.length === 3 && _isNumber(x[0]) && _isNumber(x[1]) && _isNumber(x[2]);
   }
 
   function _4d(x) {
-    return x.length === 4 && typeof x[0] === 'number' && typeof x[1] === 'number' && typeof x[2] === 'number' && typeof x[3] === 'number';
+    return x.length === 4 && _isNumber(x[0]) && _isNumber(x[1]) && _isNumber(x[2]) && _isNumber(x[3]);
   }
 
   function _intersect2d(p1a, p1b, p2a, p2b){
@@ -93,30 +103,44 @@ function factory (type, config, load, typed) {
     var o2 = p2a;
     var d1 = subtract(o1, p1b);
     var d2 = subtract(o2, p2b);
-    var det = d1[0]*d2[1] - d2[0]*d1[1];
-    if (abs(det) < config.epsilon) {
+    var det = subtract(multiplyScalar(d1[0], d2[1]), multiplyScalar(d2[0], d1[1]));
+    if (smaller(abs(det), config.epsilon)) {
       return null;
     }
-    var t = (d2[0]*o1[1] - d2[1]*o1[0] - d2[0]*o2[1] + d2[1]*o2[0]) / det;
-    return add(multiply(d1, t), o1); 
+    var d20o11 = multiplyScalar(d2[0], o1[1]);
+    var d21o10 = multiplyScalar(d2[1], o1[0]);
+    var d20o21 = multiplyScalar(d2[0], o2[1]);
+    var d21o20 = multiplyScalar(d2[1], o2[0]);
+    var t = divideScalar(addScalar(subtract(subtract(d20o11, d21o10), d20o21), d21o20), det);
+    return add(multiply(d1, t), o1);
+  }
+
+  function _intersect3dHelper(a, b, c, d, e, f, g, h, i, j, k, l){
+      // (a - b)*(c - d) + (e - f)*(g - h) + (i - j)*(k - l)
+      var add1 = multiplyScalar(subtract(a, b), subtract(c, d));
+      var add2 = multiplyScalar(subtract(e, f), subtract(g, h));
+      var add3 = multiplyScalar(subtract(i, j), subtract(k, l));
+      return addScalar(addScalar(add1, add2), add3);
   }
 
   function _intersect3d(x1, y1, z1, x2, y2, z2, x3, y3, z3, x4, y4, z4){
-    var d1343 = (x1 - x3)*(x4 - x3) + (y1 - y3)*(y4 - y3) + (z1 - z3)*(z4 - z3);
-    var d4321 = (x4 - x3)*(x2 - x1) + (y4 - y3)*(y2 - y1) + (z4 - z3)*(z2 - z1);
-    var d1321 = (x1 - x3)*(x2 - x1) + (y1 - y3)*(y2 - y1) + (z1 - z3)*(z2 - z1);
-    var d4343 = (x4 - x3)*(x4 - x3) + (y4 - y3)*(y4 - y3) + (z4 - z3)*(z4 - z3);
-    var d2121 = (x2 - x1)*(x2 - x1) + (y2 - y1)*(y2 - y1) + (z2 - z1)*(z2 - z1);
-    var ta = ( d1343*d4321 - d1321*d4343 ) / ( d2121*d4343 - d4321*d4321 );
-    var tb = ( d1343 + ta * d4321 ) / (d4343);
-
-    var pax = x1 + ta * (x2 - x1);
-    var pay = y1 + ta * (y2 - y1);
-    var paz = z1 + ta * (z2 - z1);
-    var pbx = x3 + tb * (x4 - x3);
-    var pby = y3 + tb * (y4 - y3);
-    var pbz = z3 + tb * (z4 - z3);
-    if (pax === pbx && pay === pby && paz === pbz){
+    var d1343 = _intersect3dHelper(x1, x3, x4, x3, y1, y3, y4, y3, z1, z3, z4, z3);
+    var d4321 = _intersect3dHelper(x4, x3, x2, x1, y4, y3, y2, y1, z4, z3, z2, z1);
+    var d1321 = _intersect3dHelper(x1, x3, x2, x1, y1, y3, y2, y1, z1, z3, z2, z1);
+    var d4343 = _intersect3dHelper(x4, x3, x4, x3, y4, y3, y4, y3, z4, z3, z4, z3);
+    var d2121 = _intersect3dHelper(x2, x1, x2, x1, y2, y1, y2, y1, z2, z1, z2, z1);
+    var ta = divideScalar(
+      subtract(multiplyScalar(d1343, d4321), multiplyScalar(d1321, d4343)),
+      subtract(multiplyScalar(d2121, d4343), multiplyScalar(d4321, d4321)));
+    var tb = divideScalar(addScalar(d1343, multiplyScalar(ta, d4321)), d4343);
+
+    var pax = addScalar(x1, multiplyScalar(ta, subtract(x2, x1)));
+    var pay = addScalar(y1, multiplyScalar(ta, subtract(y2, y1)));
+    var paz = addScalar(z1, multiplyScalar(ta, subtract(z2, z1)));
+    var pbx = addScalar(x3, multiplyScalar(tb, subtract(x4, x3)));
+    var pby = addScalar(y3, multiplyScalar(tb, subtract(y4, y3)));
+    var pbz = addScalar(z3, multiplyScalar(tb, subtract(z4, z3)));
+    if (equalScalar(pax, pbx) && equalScalar(pay, pby) && equalScalar(paz, pbz)){
       return [pax, pay, paz];
     }
     else{
@@ -125,10 +149,18 @@ function factory (type, config, load, typed) {
   }
 
   function _intersectLinePlane(x1, y1, z1, x2, y2, z2, x, y, z, c){
-    var t = (c - x1*x - y1*y - z1*z)/(x2*x + y2*y + z2*z - x1*x - y1*y - z1*z);
-    var px = x1 + t * (x2 - x1);
-    var py = y1 + t * (y2 - y1);
-    var pz = z1 + t * (z2 - z1);
+    var x1x = multiplyScalar(x1, x);
+    var x2x = multiplyScalar(x2, x);
+    var y1y = multiplyScalar(y1, y);
+    var y2y = multiplyScalar(y2, y);
+    var z1z = multiplyScalar(z1, z);
+    var z2z = multiplyScalar(z2, z);
+    var t = divideScalar(
+      subtract(subtract(subtract(c, x1x), y1y), z1z),
+      subtract(subtract(subtract(addScalar(addScalar(x2x, y2y), z2z), x1x), y1y), z1z));
+    var px = addScalar(x1, multiplyScalar(t, subtract(x2, x1)));
+    var py = addScalar(y1, multiplyScalar(t, subtract(y2, y1)));
+    var pz = addScalar(z1, multiplyScalar(t, subtract(z2, z1)));
     return [px, py, pz];
     // TODO: Add cases when line is parallel to the plane:
     //       (a) no intersection,


Test patch:
diff --git a/test/function/geometry/distance.test.js b/test/function/geometry/distance.test.js
index e4be63687..51be58e7b 100644
--- a/test/function/geometry/distance.test.js
+++ b/test/function/geometry/distance.test.js
@@ -89,4 +89,27 @@ describe('distance', function() {
     assert.deepEqual(math.distance({pointX: 2, pointY: 3, pointZ: 1}, {x0: 1, y0: 1, z0: 2, a: 5, b: 0, c: 1}), 2.3204774044612857);
   });
 
+  it('should calculate the distance if coordinates are bignumbers', function() {
+    var bigmath = math.create({number: 'BigNumber', precision: 32});
+    var bigdistance = bigmath.distance;
+    var bignumber = bigmath.bignumber;
+
+    assert.deepEqual(bigmath.eval('distance([1, 2], [4, 6])'), bignumber(5));
+    assert.deepEqual(bigdistance([bignumber(1), bignumber(2)], [bignumber(4), bignumber(6)]), bignumber(5));
+    assert.deepEqual(bigdistance([bignumber(1), 2], [4, bignumber(6)]), bignumber(5));
+    assert.deepEqual(bigmath.eval('distance([3, 5], [10, 1])'), bignumber('8.0622577482985496523666132303038'));
+    assert.deepEqual(bigmath.eval('distance([1, 2, 3], [-2, -3, -4])'), bignumber('9.1104335791442988819456261046887'));
+    assert.deepEqual(bigmath.eval('distance({pointOneX: 0, pointOneY: 0}, {pointTwoX: 10, pointTwoY: 10})'), bignumber('14.142135623730950488016887242097'));
+    assert.deepEqual(bigmath.eval('distance({pointOneX: 4, pointOneY: 5, pointOneZ: 8}, {pointTwoX: 2, pointTwoY: 7, pointTwoZ: 10})'), bignumber('3.4641016151377545870548926830117'));
+    assert.deepEqual(bigmath.eval('distance([[0,2],[-2,0],[0,2]])'), [ bignumber('2.8284271247461900976033774484194'), bignumber('0'), bignumber('2.8284271247461900976033774484194') ]);
+    assert.deepEqual(bigmath.eval('distance([[1,2,4],[1,2,6],[8,1,3]])'), [bignumber('2'), bignumber('7.1414284285428499979993998113673'), bignumber('7.6811457478686081757696870217314')]);
+    assert.deepEqual(bigmath.eval('distance([0.23, -0.1240], [-0.232, 13.292], [-0.34, 0.346])'), bignumber('10.658908662088362142660358292758'));
+    assert.deepEqual(bigmath.eval('distance({pointX: 1, pointY: 4}, {lineOnePtX: 6, lineOnePtY: 3}, {lineTwoPtX: 2, lineTwoPtY: 8})'),
+      bignumber('2.7205493726247441306311612969564'));
+    assert.deepEqual(bigmath.eval('distance([0.1123, -0.242], [0.1316, -0.2421, 0.122135])'), bignumber('0.709482134734344383494644726006'));
+    assert.deepEqual(bigmath.eval('distance({pointX: 10, pointY: 10}, {xCoeffLine: 8, yCoeffLine: 1, constant: 3})'), bignumber('11.535230316796386425693769698742'));
+    assert.deepEqual(bigmath.eval('distance([2, 3, 1], [1, 1, 2, 5, 0, 1])'), bignumber('2.3204774044612855517320588018918'));
+    assert.deepEqual(bigmath.eval('distance({pointX: 2, pointY: 3, pointZ: 1}, {x0: 1, y0: 1, z0: 2, a: 5, b: 0, c: 1})'),
+      bignumber('2.3204774044612855517320588018918'));
+  });
 });
diff --git a/test/function/geometry/intersect.test.js b/test/function/geometry/intersect.test.js
index f1964cf4f..c31a8b744 100644
--- a/test/function/geometry/intersect.test.js
+++ b/test/function/geometry/intersect.test.js
@@ -27,7 +27,7 @@ describe('intersect', function() {
     assert.deepEqual(math.intersect(math.matrix([0, 30, 0]), [0, 21, 0], math.matrix([0, 9, 0, 0])), math.matrix([0, 0, 0]));
     assert.deepEqual(math.intersect(math.matrix([0, 30, 0]), math.matrix([0, 21, 0]), math.matrix([0, 9, 0, 0])), math.matrix([0, 0, 0]));
   });
-  
+
   it('should return null if the points do not intersect', function() {
     assert.deepEqual(math.intersect([0, 1, 0], [0, 0, 0], [1, 1, 0], [1, 0, 0]), null);
     assert.deepEqual(math.intersect([0, 1], [0, 0], [1, 1], [1, 0]), null);
@@ -37,7 +37,7 @@ describe('intersect', function() {
     assert.throws(function () {math.intersect([2, 0, 1], [1, 1, 1, 6])}, /TypeError: Too few arguments in function intersect/);
     assert.throws(function () {math.intersect([2, 0, 1], [1, 1, 6], [2, 0, 1], [1, 1, 6], [0, 8, 1])}, /TypeError: Too many arguments in function intersect/);
   });
-  
+
   it('should throw an error for incompatible parameter types', function() {
     assert.throws(function () {math.intersect(2, 3, 6)}, /TypeError: Unexpected type of argument in function intersect/);
     assert.throws(function () {math.intersect([2, 0, 1], [1, 1, 1], [5, 1, 10])}, /TypeError: Array with 4 numbers expected as third argument/);
@@ -45,4 +45,19 @@ describe('intersect', function() {
     assert.throws(function () {math.intersect([2, 8, 9], 3, 6)}, /TypeError: Unexpected type of argument in function intersect/);
     assert.throws(function () {math.intersect('a', 'b', 'c', 'd')}, /TypeError: Unexpected type of argument in function intersect/);
   });
+
+  it('should calculate the intersection point if coordinates are bignumbers', function() {
+      var bigmath = math.create({number: 'BigNumber', precision: 32});
+      var bigintersect = bigmath.intersect;
+      var bignumber = bigmath.bignumber;
+
+      assert.deepEqual(bigmath.eval('intersect([0, 0], [10, 10], [10, 0], [0, 10])'), math.matrix([bignumber(5), bignumber(5)]));
+      assert.deepEqual(bigintersect([bignumber(0), bignumber(0)], [bignumber(10), bignumber(10)], [bignumber(10), bignumber(0)], [bignumber(0), bignumber(10)]),
+        [bignumber(5), bignumber(5)]);
+      assert.deepEqual(bigintersect([bignumber(0), 0], [10, bignumber(10)], [10, bignumber(0)], [0, bignumber(10)]), [bignumber(5), bignumber(5)]);
+      assert.deepEqual(bigintersect([bignumber(0), bignumber(0), bignumber(0)], [bignumber(10), bignumber(10), bignumber(0)], [bignumber(10), bignumber(0), bignumber(0)], [bignumber(0), bignumber(10), bignumber(0)]),
+        [bignumber(5), bignumber(5), bignumber(0)]);
+      assert.deepEqual(bigintersect([bignumber(1), bignumber(0), bignumber(1)], [bignumber(4), bignumber(-2), bignumber(2)], [bignumber(1), bignumber(1), bignumber(1), bignumber(6)]),
+        [bignumber(7), bignumber(-4), bignumber(3)]);
+  });
 });