Repository: josdejong/mathjs
Pull request #679 (2016-06-30 00:26:28)

add pickMultipleRandom function
I added a pickMultipleRandom function modeled after pickRandom. I already wrote additional functions for weighted random picking, but since this is my first attempt at contributing to an open source project, I'd rather like to listen to your comments before putting it all out at once.


Patch:
diff --git a/.travis.yml b/.travis.yml
index ba2d30a38..d3a4bdc72 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -2,5 +2,5 @@ language: node_js
 node_js:
   - 0.10
   - 0.12
-  - 4
-  - 5
+  - 4.3
+  - 5.7
diff --git a/HISTORY.md b/HISTORY.md
index ed83a02d3..3b31eea7f 100644
--- a/HISTORY.md
+++ b/HISTORY.md
@@ -1,16 +1,6 @@
 # History
 
 
-## not yet released, version 3.2.2
-
-- Function `math.filter` now passes three arguments to the callback function:
-  value, index, and array.
-- Removed the check on the number of arguments from functions defined in the
-  expression parser (see #665).
-- Fixed #665: functions `map`, `forEach`, and `filter` now invoke callbacks
-  which are a typed-function with the correct number of arguments.
-
-
 ## 2016-04-26, version 3.2.1
 
 - Fixed #651: unable to perform calculations on "Unit-less" units.
diff --git a/docs/expressions/syntax.md b/docs/expressions/syntax.md
index 248284f96..15cab42ed 100644
--- a/docs/expressions/syntax.md
+++ b/docs/expressions/syntax.md
@@ -148,17 +148,6 @@ parser.eval('g(x, y) = x ^ y');
 parser.eval('g(2, 3)'); // 8
 ```
 
-Math.js itself heavily uses typed functions, which ensure correct inputs and
-throws meaningful errors when the input arguments are invalid. One can create
-a [typed-function](https://github.com/josdejong/typed-function) in the
-expression parser like:
-
-```js
-var parser = math.parser();
-
-parser.eval('f = typed({"number": f(x) = x ^ 2 - 5})');
-```
-
 
 ## Constants and variables
 
@@ -372,11 +361,10 @@ math.eval('9.81 m/s^2 * 5 s to mi/h')   // Unit, 109.72172512527 mi / h
 
 ### Strings
 
-Strings are enclosed by double quotes ". Strings can be concatenated using the
-function `concat` (not by adding them using `+` like in JavaScript). Parts of
-a string can be retrieved or replaced by using indexes. Strings can be converted
-to a number using function `number`, and numbers can be converted to a string
-using function `string`.
+Strings are enclosed by double quotes ". Strings can be concatenated by adding
+them. Parts of a string can be retrieved or replaced by using indexes. Strings
+can be converted to a number using function `number`, and numbers can be
+converted to a string using function `string`.
 
 ```js
 var parser = math.parser();
diff --git a/lib/expression/docs/function/probability/distribution.js b/lib/expression/docs/function/probability/distribution.js
index 97494f3a3..3beeb4a8b 100644
--- a/lib/expression/docs/function/probability/distribution.js
+++ b/lib/expression/docs/function/probability/distribution.js
@@ -8,7 +8,7 @@ module.exports = {
   'description':
       'Create a distribution object of a specific type. ' +
           'A distribution object contains functions `random([size,] [min,] [max])`, ' +
-          '`randomInt([size,] [min,] [max])`, and `pickRandom(array)`. ' +
+          '`randomInt([size,] [min,] [max])` and `pickRandom(array)`. ' +
           'Available types of distributions: "uniform", "normal". ' +
           'Note that the function distribution is currently not available via the expression parser.',
   'examples': [
diff --git a/lib/expression/docs/function/probability/pickRandom.js b/lib/expression/docs/function/probability/pickRandom.js
index 26d136dd3..8c18f7aae 100644
--- a/lib/expression/docs/function/probability/pickRandom.js
+++ b/lib/expression/docs/function/probability/pickRandom.js
@@ -2,13 +2,21 @@ module.exports = {
   'name': 'pickRandom',
   'category': 'Probability',
   'syntax': [
-    'pickRandom(array)'
+    'pickRandom(array)',
+    'pickRandom(array, number)',
+    'pickRandom(array, weights)',
+    'pickRandom(array, number, weights)',
+    'pickRandom(array, weights, number)'
   ],
   'description':
       'Pick a random entry from a given array.',
   'examples': [
     'pickRandom(0:10)',
-    'pickRandom([1, 3, 1, 6])'
+    'pickRandom([1, 3, 1, 6])',
+    'pickRandom([1, 3, 1, 6], 2)',
+    'pickRandom([1, 3, 1, 6], [2, 3, 2, 1])',
+    'pickRandom([1, 3, 1, 6], 2, [2, 3, 2, 1])',
+    'pickRandom([1, 3, 1, 6], [2, 3, 2, 1], 2)'
   ],
   'seealso': ['random', 'randomInt']
 };
diff --git a/lib/expression/node/FunctionAssignmentNode.js b/lib/expression/node/FunctionAssignmentNode.js
index 2fe3f20ed..559e6851e 100644
--- a/lib/expression/node/FunctionAssignmentNode.js
+++ b/lib/expression/node/FunctionAssignmentNode.js
@@ -17,10 +17,7 @@ function factory (type, config, load, typed) {
    * Function assignment
    *
    * @param {string} name           Function name
-   * @param {string[] | Array.<{name: string, type: string}>} params
-   *                                Array with function parameter names, or an
-   *                                array with objects containing the name
-   *                                and type of the parameter
+   * @param {string[]} params       Function parameter names
    * @param {Node} expr             The function expression
    */
   function FunctionAssignmentNode(name, params, expr) {
@@ -30,17 +27,12 @@ function factory (type, config, load, typed) {
 
     // validate input
     if (typeof name !== 'string') throw new TypeError('String expected for parameter "name"');
-    if (!Array.isArray(params))  throw new TypeError('Array containing strings or objects expected for parameter "params"');
+    if (!Array.isArray(params) || !params.every(isString))  throw new TypeError('Array containing strings expected for parameter "params"');
     if (!(expr && expr.isNode)) throw new TypeError('Node expected for parameter "expr"');
     if (name in keywords) throw new Error('Illegal function name, "' + name + '" is a reserved keyword');
 
     this.name = name;
-    this.params = params.map(function (param) {
-      return param && param.name || param;
-    });
-    this.types = params.map(function (param) {
-      return param && param.type || 'any'
-    });
+    this.params = params;
     this.expr = expr;
   }
 
@@ -63,8 +55,6 @@ function factory (type, config, load, typed) {
    * @private
    */
   FunctionAssignmentNode.prototype._compile = function (defs, args) {
-    defs.typed = typed;
-
     // we extend the original args and add the args to the child object
     var childArgs = Object.create(args);
     this.params.forEach(function (variable) {
@@ -76,11 +66,14 @@ function factory (type, config, load, typed) {
 
     return 'scope["' + this.name + '"] = ' +
         '  (function () {' +
-        '    var fn = typed("' + this.name + '", {' +
-        '      "' + this.types.join(',') + '": function (' + this.params.join(',') + ') {' +
-        '        return ' + jsExpr + '' +
+        '    var fn = function ' + this.name + '(' + this.params.join(',') + ') {' +
+        '      if (arguments.length != ' + this.params.length + ') {' +
+          // TODO: use util.error.ArgumentsError here?
+          // TODO: test arguments error
+        '        throw new SyntaxError("Wrong number of arguments in function ' + this.name + ' (" + arguments.length + " provided, ' + this.params.length + ' expected)");' +
         '      }' +
-        '    });' +
+        '      return ' + jsExpr + '' +
+        '    };' +
         '    fn.syntax = "' + this.name + '(' + this.params.join(', ') + ')";' +
         '    return fn;' +
         '  })()';
diff --git a/lib/expression/transform/filter.transform.js b/lib/expression/transform/filter.transform.js
index 062adc852..06c3aec6d 100644
--- a/lib/expression/transform/filter.transform.js
+++ b/lib/expression/transform/filter.transform.js
@@ -1,7 +1,5 @@
 'use strict';
 
-var maxArgumentCount = require('../../utils/function').maxArgumentCount;
-
 /**
  * Attach a transform function to math.filter
  * Adds a property transform containing the transform function.
diff --git a/lib/expression/transform/forEach.transform.js b/lib/expression/transform/forEach.transform.js
index 5ed90dca4..e785aa929 100644
--- a/lib/expression/transform/forEach.transform.js
+++ b/lib/expression/transform/forEach.transform.js
@@ -1,7 +1,5 @@
 'use strict';
 
-var maxArgumentCount = require('../../utils/function').maxArgumentCount;
-
 /**
  * Attach a transform function to math.forEach
  * Adds a property transform containing the transform function.
@@ -13,9 +11,6 @@ function factory (type, config, load, typed) {
 
   return typed('forEach', {
     'Array | Matrix, function': function (array, callback) {
-      // figure out what number of arguments the callback function expects
-      var args = maxArgumentCount(callback);
-
       var recurse = function (value, index) {
         if (Array.isArray(value)) {
           value.forEach(function (child, i) {
@@ -24,16 +19,7 @@ function factory (type, config, load, typed) {
           });
         }
         else {
-          // invoke the callback function with the right number of arguments
-          if (args === 1) {
-            callback(value);
-          }
-          else if (args === 2) {
-            callback(value, index);
-          }
-          else { // 3 or -1
-            callback(value, index, array);
-          }
+          callback(value, index, array);
         }
       };
       recurse(array.valueOf(), []); // pass Array
diff --git a/lib/expression/transform/map.transform.js b/lib/expression/transform/map.transform.js
index f8c6fe885..ba2b8dba6 100644
--- a/lib/expression/transform/map.transform.js
+++ b/lib/expression/transform/map.transform.js
@@ -1,7 +1,5 @@
 'use strict';
 
-var maxArgumentCount = require('../../utils/function').maxArgumentCount;
-
 /**
  * Attach a transform function to math.map
  * Adds a property transform containing the transform function.
@@ -32,9 +30,6 @@ function factory (type, config, load, typed) {
  * @private
  */
 function _map (array, callback, orig) {
-  // figure out what number of arguments the callback function expects
-  var args = maxArgumentCount(callback);
-
   function recurse(value, index) {
     if (Array.isArray(value)) {
       return value.map(function (child, i) {
@@ -43,16 +38,7 @@ function _map (array, callback, orig) {
       });
     }
     else {
-      // invoke the callback function with the right number of arguments
-      if (args === 1) {
-        return callback(value);
-      }
-      else if (args === 2) {
-        return callback(value, index);
-      }
-      else { // 3 or -1
-        return callback(value, index, orig);
-      }
+      return callback(value, index, orig);
     }
   }
 
diff --git a/lib/function/matrix/filter.js b/lib/function/matrix/filter.js
index 95c8364d2..edae3569f 100644
--- a/lib/function/matrix/filter.js
+++ b/lib/function/matrix/filter.js
@@ -1,7 +1,6 @@
 'use strict';
 
 var size = require('../../utils/array').size;
-var maxArgumentCount = require('../../utils/function').maxArgumentCount;
 
 function factory (type, config, load, typed) {
   var matrix = load(require('../../type/matrix/function/matrix'));
@@ -29,10 +28,8 @@ function factory (type, config, load, typed) {
    * @param {Matrix | Array} x    A one dimensional matrix or array to filter
    * @param {Function | RegExp} test
    *        A function or regular expression to test items.
+   *        When `test` is a function, it must return a boolean.
    *        All entries for which `test` returns true are returned.
-   *        When `test` is a function, it is invoked with three parameters:
-   *        the value of the element, the index of the element, and the
-   *        matrix/array being traversed. The function must return a boolean.
    * @return {Matrix | Array} Returns the filtered matrix.
    */
   var filter = typed('filter', {
@@ -66,20 +63,8 @@ function _filterCallback (x, callback) {
     throw new Error('Only one dimensional matrices supported');
   }
 
-  // figure out what number of arguments the callback function expects
-  var args = maxArgumentCount(callback);
-
-  return x.filter(function (value, index, array) {
-    // invoke the callback function with the right number of arguments
-    if (args === 1) {
-      return callback(value);
-    }
-    else if (args === 2) {
-      return callback(value, [index]);
-    }
-    else { // 3 or -1
-      return callback(value, [index], array);
-    }
+  return x.filter(function (entry) {
+    return callback(entry);
   });
 }
 
diff --git a/lib/function/matrix/forEach.js b/lib/function/matrix/forEach.js
index f061ce1bc..eac25ab8c 100644
--- a/lib/function/matrix/forEach.js
+++ b/lib/function/matrix/forEach.js
@@ -1,7 +1,5 @@
 'use strict';
 
-var maxArgumentCount = require('../../utils/function').maxArgumentCount;
-
 function factory (type, config, load, typed) {
   /**
    * Iterate over all elements of a matrix/array, and executes the given callback function.
@@ -46,9 +44,6 @@ function factory (type, config, load, typed) {
  * @private
  */
 function _forEach (array, callback) {
-  // figure out what number of arguments the callback function expects
-  var args = maxArgumentCount(callback);
-
   var recurse = function (value, index) {
     if (Array.isArray(value)) {
       value.forEach(function (child, i) {
@@ -57,16 +52,7 @@ function _forEach (array, callback) {
       });
     }
     else {
-      // invoke the callback function with the right number of arguments
-      if (args === 1) {
-        callback(value);
-      }
-      else if (args === 2) {
-        callback(value, index);
-      }
-      else { // 3 or -1
-        callback(value, index, array);
-      }
+      callback(value, index, array);
     }
   };
   recurse(array, []);
diff --git a/lib/function/matrix/map.js b/lib/function/matrix/map.js
index faa381f91..5204d8317 100644
--- a/lib/function/matrix/map.js
+++ b/lib/function/matrix/map.js
@@ -1,7 +1,5 @@
 'use strict';
 
-var maxArgumentCount = require('../../utils/function').maxArgumentCount;
-
 function factory (type, config, load, typed) {
   /**
    * Create a new matrix or array with the results of the callback function executed on
@@ -48,9 +46,6 @@ function factory (type, config, load, typed) {
  * @private
  */
 function _map (array, callback) {
-  // figure out what number of arguments the callback function expects
-  var args = maxArgumentCount(callback);
-
   var recurse = function (value, index) {
     if (Array.isArray(value)) {
       return value.map(function (child, i) {
@@ -59,16 +54,7 @@ function _map (array, callback) {
       });
     }
     else {
-      // invoke the callback function with the right number of arguments
-      if (args === 1) {
-        return callback(value);
-      }
-      else if (args === 2) {
-        return callback(value, index);
-      }
-      else { // 3 or -1
-        return callback(value, index, array);
-      }
+      return callback(value, index, array);
     }
   };
 
diff --git a/lib/function/probability/distribution.js b/lib/function/probability/distribution.js
index eae9c96b6..0c57155a5 100644
--- a/lib/function/probability/distribution.js
+++ b/lib/function/probability/distribution.js
@@ -2,6 +2,7 @@
 
 var ArgumentsError = require('../../error/ArgumentsError');
 var isCollection = require('../../utils/collection/isCollection');
+var isNumber = require('../../utils/number').isNumber;
 
 // TODO: rethink math.distribution
 // TODO: rework to a typed function
@@ -46,35 +47,36 @@ function factory (type, config, load, typed) {
 
         random: function(arg1, arg2, arg3) {
           var size, min, max;
+
           if (arguments.length > 3) {
             throw new ArgumentsError('random', arguments.length, 0, 3);
-
-          // `random(max)` or `random(size)`
           } else if (arguments.length === 1) {
+            // `random(max)` or `random(size)`
             if (isCollection(arg1)) {
               size = arg1;
-            }
-            else {
+            } else {
               max = arg1;
             }
-          // `random(min, max)` or `random(size, max)`
           } else if (arguments.length === 2) {
+            // `random(min, max)` or `random(size, max)`
             if (isCollection(arg1)) {
               size = arg1;
               max = arg2;
-            }
-            else {
+            } else {
               min = arg1;
               max = arg2;
             }
-          // `random(size, min, max)`
           } else {
+            // `random(size, min, max)`
             size = arg1;
             min = arg2;
             max = arg3;
           }
 
-          // TODO: validate type of min, max, and size
+          // TODO: validate type of size
+          if ((min !== undefined && !isNumber(min)) || (max !== undefined && !isNumber(max))) {
+            throw new TypeError('Invalid argument in function random');
+          }
 
           if (max === undefined) max = 1;
           if (min === undefined) min = 0;
@@ -82,69 +84,149 @@ function factory (type, config, load, typed) {
             var res = _randomDataForMatrix(size.valueOf(), min, max, _random);
             return (size && size.isMatrix === true) ? matrix(res) : res;
           }
-          else return _random(min, max);
+          return _random(min, max);
         },
 
-        randomInt: function(arg1, arg2, arg3) {
-          var size, min, max;
-          if (arguments.length > 3 || arguments.length < 1)
-            throw new ArgumentsError('randomInt', arguments.length, 1, 3);
+        randomInt: typed({
+          'number | Array': function(arg) {
+            var min = 0;
 
-          // `random(max)` or `random(size)`
-          else if (arguments.length === 1)
-            if (isCollection(arg1)) {
-              size = arg1;
-            }
-            else {
-              max = arg1;
+            if (isCollection(arg)) {
+              var size = arg;
+              var max = 1;
+              var res = _randomDataForMatrix(size.valueOf(), min, max, _randomInt);
+              return (size && size.isMatrix === true) ? matrix(res) : res;
+            } else {
+              var max = arg;
+              return _randomInt(min, max);
             }
-          // `randomInt(min, max)` or `randomInt(size, max)`
-          else if (arguments.length === 2) {
+          },
+          'number | Array, number': function(arg1, arg2) {
             if (isCollection(arg1)) {
-              size = arg1;
-              max = arg2;
+              var size = arg1;
+              var max = arg2;
+              var min = 0;
+              var res = _randomDataForMatrix(size.valueOf(), min, max, _randomInt);
+              return (size && size.isMatrix === true) ? matrix(res) : res;
             }
             else {
-              min = arg1;
-              max = arg2;
+              var min = arg1;
+              var max = arg2;
+              return _randomInt(min, max);
             }
-          // `randomInt(size, min, max)`
-          } else {
-            size = arg1;
-            min = arg2;
-            max = arg3;
-          }
-
-          // TODO: validate type of min, max, and size
-
-          if (min === undefined) min = 0;
-          if (size !== undefined) {
+          },
+          'Array, number, number': function(size, min, max) {
             var res = _randomDataForMatrix(size.valueOf(), min, max, _randomInt);
             return (size && size.isMatrix === true) ? matrix(res) : res;
           }
-          else return _randomInt(min, max);
-        },
+        }),
+
+        pickRandom: typed({
+          'Array': function(possibles) {
+            return _pickRandom(possibles);
+          },
+          'Array, number | Array': function(possibles, arg2) {
+            var number, weights;
 
-        pickRandom: function(possibles) {
-          if (arguments.length !== 1) {
-            throw new ArgumentsError('pickRandom', arguments.length, 1);
+            if (Array.isArray(arg2)) {
+              weights = arg2;
+            } else if (isNumber(arg2)) {
+              number = arg2;
+            } else {
+              throw new TypeError('Invalid argument in function pickRandom')
+            }
+
+            return _pickRandom(possibles, number, weights);
+          },
+          'Array, number | Array, Array | number': function(possibles, arg2, arg3) {
+            var number, weights;
+
+            if (Array.isArray(arg2)) {
+              weights = arg2;
+              number = arg3;
+            } else {
+              weights = arg3;
+              number = arg2;
+            }
+
+            if (!Array.isArray(weights) || !isNumber(number)) {
+              throw new TypeError('Invalid argument in function pickRandom');
+            }
+
+            return _pickRandom(possibles, number, weights);
           }
-          if (possibles && possibles.isMatrix === true) {
-            possibles = possibles.valueOf(); // get Array
+        })
+      }
+
+      var _pickRandom = function(possibles, number, weights) {
+        var single = (typeof number === 'undefined');
+
+        if (single) {
+          number = 1;
+        }
+
+        if (possibles && possibles.isMatrix === true) {
+          possibles = possibles.valueOf(); // get Array
+        } else if (!Array.isArray(possibles)) {
+          throw new TypeError('Unsupported type of value in function pickRandom');
+        }
+
+        if (array.size(possibles).length > 1) {
+          throw new Error('Only one dimensional vectors supported');
+        }
+
+        if (typeof weights !== 'undefined') {
+          if (weights.length != possibles.length) {
+            throw new Error('Weights must have the same length as possibles');
           }
-          else if (!Array.isArray(possibles)) {
-            throw new TypeError('Unsupported type of value in function pickRandom');
+
+          var totalWeights = 0;
+
+          for (var i = 0, len = weights.length; i < len; i++) {
+            if (!isNumber(weights[i]) || weights[i] < 0) {
+              throw new Error('Weights must be an array of positive numbers');
+            }
+
+            totalWeights += weights[i];
           }
+        }
+
+        var length = possibles.length;
+
+        if (length == 0) {
+          return [];
+        } else if (number >= length) {
+          return possibles;
+        }
+
+        var result = [];
+        var pick;
+
+        while (result.length < number) {
+          if (typeof weights === 'undefined') {
+            pick = possibles[Math.floor(Math.random() * length)];
+          } else {
+            var randKey = Math.random() * totalWeights;
+
+            for (var i = 0, len = possibles.length; i < len; i++) {
+              randKey -= weights[i];
 
-          if (array.size(possibles).length > 1) {
-            throw new Error('Only one dimensional vectors supported');
+              if (randKey < 0) {
+                pick = possibles[i];
+                break;
+              }
+            }
           }
 
-          // TODO: add support for multi dimensional matrices
-          return possibles[Math.floor(Math.random() * possibles.length)];
+          if (result.indexOf(pick) == -1) {
+            result.push(pick);
+          }
         }
 
-      };
+        return single ? result[0] : result;
+
+        // TODO: add support for multi dimensional matrices
+      }
 
       var _random = function(min, max) {
         return min + distribution() * (max - min);
@@ -160,11 +242,13 @@ function factory (type, config, load, typed) {
         size = size.slice(0);
 
         if (size.length > 1) {
-          for (i = 0, length = size.shift(); i < length; i++)
+          for (var i = 0, length = size.shift(); i < length; i++) {
             data.push(_randomDataForMatrix(size, min, max, randFunc));
+          }
         } else {
-          for (i = 0, length = size.shift(); i < length; i++)
+          for (var i = 0, length = size.shift(); i < length; i++) {
             data.push(randFunc(min, max));
+          }
         }
 
         return data;
diff --git a/lib/function/probability/pickRandom.js b/lib/function/probability/pickRandom.js
index f553c3127..1e4e92a5c 100644
--- a/lib/function/probability/pickRandom.js
+++ b/lib/function/probability/pickRandom.js
@@ -4,23 +4,34 @@ function factory (type, config, load, typed) {
   var distribution = load(require('./distribution'));
 
   /**
-   * Random pick a value from a one dimensional array.
-   * Array element is picked using a random function with uniform distribution.
+   * Random pick one or more values from a one dimensional array.
+   * Array elements are picked using a random function with uniform or weighted distribution.
    *
    * Syntax:
    *
    *     math.pickRandom(array)
+   *     math.pickRandom(array, number)
+   *     math.pickRandom(array, weights)
+   *     math.pickRandom(array, number, weights)
+   *     math.pickRandom(array, weights, number)
    *
    * Examples:
    *
-   *     math.pickRandom([3, 6, 12, 2]);       // returns one of the values in the array
+   *     math.pickRandom([3, 6, 12, 2]);                  // returns one of the values in the array
+   *     math.pickRandom([3, 6, 12, 2], 2);               // returns an array of two of the values in the array
+   *     math.pickRandom([3, 6, 12, 2], [1, 3, 2, 1]);    // returns one of the values in the array with weighted distribution
+   *     math.pickRandom([3, 6, 12, 2], 2, [1, 3, 2, 1]); // returns an array of two of the values in the array with weighted distribution
+   *     math.pickRandom([3, 6, 12, 2], [1, 3, 2, 1], 2); // returns an array of two of the values in the array with weighted distribution
    *
    * See also:
    *
    *     random, randomInt
    *
    * @param {Array} array     A one dimensional array
+   * @param {Int} number      An int or float
+   * @param {Array} weights   An array of ints or floats
    * @return {number} One of the elements of the provided input array
+   * @return {array} An array of elements of the provided input array
    */
   // TODO: rework pickRandom to a typed-function
   var pickRandom =  distribution('uniform').pickRandom;
diff --git a/lib/function/utils/index.js b/lib/function/utils/index.js
index 393bdf93a..b13e2b35e 100644
--- a/lib/function/utils/index.js
+++ b/lib/function/utils/index.js
@@ -5,6 +5,5 @@ module.exports = [
   require('./isNumeric'),
   require('./isPositive'),
   require('./isZero'),
-  require('./isNaN'),
   require('./typeof')
 ];
diff --git a/lib/function/utils/isNaN.js b/lib/function/utils/isNaN.js
deleted file mode 100644
index 87a712051..000000000
--- a/lib/function/utils/isNaN.js
+++ /dev/null
@@ -1,66 +0,0 @@
-'use strict';
-
-var deepMap = require('../../utils/collection/deepMap');
-var number = require('../../utils/number');
-
-function factory (type, config, load, typed) {
-  /**
-   * Test whether a value is NaN (not a number).
-   * The function supports types `number`, `BigNumber`, `Fraction`, `Unit` and `Complex`.
-   *
-   * The function is evaluated element-wise in case of Array or Matrix input.
-   *
-   * Syntax:
-   *
-   *     math.isNaN(x)
-   *
-   * Examples:
-   *
-   *    math.isNaN(3);                     // returns false
-   *    math.isNaN(NaN);                   // returns true
-   *    math.isNaN(0);                     // returns false
-   *    math.isNaN(math.bignumber(NaN));   // returns true
-   *    math.isNaN(math.bignumber(0));     // returns false
-   *    math.isNaN(math.fraction(-2, 5));  // returns false
-   *    math.isNaN('-2');                  // returns false
-   *    math.isNaN([2, 0, -3, NaN]');      // returns [false, false, false, true]
-   *
-   * See also:
-   *
-   *    isNumeric, isNegative, isPositive, isZero, isInteger
-   *
-   * @param {number | BigNumber | Fraction | Unit | Array | Matrix} x  Value to be tested
-   * @return {boolean}  Returns true when `x` is NaN.
-   *                    Throws an error in case of an unknown data type.
-   */
-  var isNaN = typed('isNaN', {
-    'number': function (x) {
-      return Number.isNaN(x);
-    },
-
-    'BigNumber': function (x) {
-      return x.isNaN();
-    },
-
-    'Fraction': function (x) {
-      return false;
-    },
-
-    'Complex': function (x) {
-      return Number.isNaN(x.re) && Number.isNaN(x.im);
-    },
-
-    'Unit': function (x) {
-      return Number.isNaN(x.value);
-    },
-
-    'Array | Matrix': function (x) {
-      return deepMap(x, Number.isNaN);
-    }
-  });
-
-  return isNaN;
-}
-
-exports.name = 'isNaN';
-exports.factory = factory;
diff --git a/lib/utils/function.js b/lib/utils/function.js
index c3b2efb43..613d1d369 100644
--- a/lib/utils/function.js
+++ b/lib/utils/function.js
@@ -29,17 +29,3 @@ exports.memoize = function(fn, hasher) {
     return memoize.cache[hash];
   };
 };
-
-/**
- * Find the maximum number of arguments expected by a typed function.
- * @param {function} fn   A typed function
- * @return {number} Returns the maximum number of expected arguments.
- *                  Returns -1 when no signatures where found on the function.
- */
-exports.maxArgumentCount = function (fn) {
-  return Object.keys(fn.signatures || {})
-      .reduce(function (args, signature) {
-        var count = (signature.match(/,/g) || []).length + 1;
-        return Math.max(args, count);
-      }, -1);
-};


Test patch:
diff --git a/test/expression/node/FunctionAssignmentNode.test.js b/test/expression/node/FunctionAssignmentNode.test.js
index 31cc129e3..6279cb854 100644
--- a/test/expression/node/FunctionAssignmentNode.test.js
+++ b/test/expression/node/FunctionAssignmentNode.test.js
@@ -34,6 +34,7 @@ describe('FunctionAssignmentNode', function() {
     assert.throws(function () {new FunctionAssignmentNode()}, TypeError);
     assert.throws(function () {new FunctionAssignmentNode('a')}, TypeError);
     assert.throws(function () {new FunctionAssignmentNode('a', ['x'])}, TypeError);
+    assert.throws(function () {new FunctionAssignmentNode('a', [2], new ConstantNode(2))}, TypeError);
     assert.throws(function () {new FunctionAssignmentNode(null, ['x'], new ConstantNode(2))}, TypeError);
   });
 
@@ -49,26 +50,11 @@ describe('FunctionAssignmentNode', function() {
     assert.equal(typeof scope.f, 'function');
     assert.equal(scope.f(3), 5);
     assert.equal(scope.f(5), 7);
+    assert.throws(function () {scope.f()}, SyntaxError);
+    assert.throws(function () {scope.f(2, 3)}, SyntaxError);
 
   });
 
-  it ('should compile a typed FunctionAssignmentNode', function () {
-    var a = new ConstantNode(2);
-    var x = new SymbolNode('x');
-    var o = new OperatorNode('+', 'add', [a, x]);
-    var n = new FunctionAssignmentNode('f', [{name: 'x', type: 'number' }], o);
-
-    var expr = n.compile();
-    var scope = {};
-    var f = expr.eval(scope);
-    assert.equal(typeof scope.f, 'function');
-    assert.equal(scope.f(3), 5);
-    assert.equal(scope.f(5), 7);
-    assert.throws(function () { scope.f(new Date())}, /Unexpected type of argument in function f/);
-    assert.throws(function () { scope.f(2, 2)}, /Too many arguments in function f/);
-    assert.throws(function () { scope.f()}, /Too few arguments in function f/);
-  });
-
   it ('should eval a recursive FunctionAssignmentNode', function () {
     var x = new SymbolNode('x');
     var one = new ConstantNode(1);
diff --git a/test/function/matrix/filter.test.js b/test/function/matrix/filter.test.js
index cf7652852..2226c45ee 100644
--- a/test/function/matrix/filter.test.js
+++ b/test/function/matrix/filter.test.js
@@ -18,53 +18,6 @@ describe('filter', function() {
     assert.deepEqual(math.filter(math.matrix([6, -2, -1, 4, 3]), isPositive), math.matrix([6, 4, 3]));
   });
 
-  it('should invoke callback with parameters value, index, obj', function() {
-    var arr = [1,2,3];
-    var log = [];
-
-    math.filter(arr, function (value, index, obj) {
-      log.push([value, index, obj === arr]);
-      return true;
-    }).valueOf();
-
-    assert.deepEqual(log, [
-      [1, [0], true ],
-      [2, [1], true ],
-      [3, [2], true ]
-    ]);
-
-  });
-
-  it('should invoke a typed function with correct number of arguments (1)', function() {
-    var output = [];
-    math.filter([1,2,3], math.typed('callback', {
-      'number': function (value) {
-        output.push(value + 2)
-      }
-    }));
-    assert.deepEqual(output, [3,4,5]);
-  });
-
-  it('should invoke a typed function with correct number of arguments (2)', function() {
-    var output = [];
-    math.filter([1,2,3], math.typed('callback', {
-      'number, Array': function (value, index) {
-        output.push(value + 2)
-      }
-    }));
-    assert.deepEqual(output, [3,4,5]);
-  });
-
-  it('should invoke a typed function with correct number of arguments (3)', function() {
-    var output = [];
-    math.filter([1,2,3], math.typed('callback', {
-      'number, Array, Array': function (value, index, array) {
-        output.push(value + 2)
-      }
-    }));
-    assert.deepEqual(output, [3,4,5]);
-  });
-
   it('should filter an array with a regexp', function() {
     assert.deepEqual(math.filter(["23", "foo", "100", "55", "bar"], /[0-9]+/), ["23", "100", "55"]);
   });
diff --git a/test/function/matrix/forEach.test.js b/test/function/matrix/forEach.test.js
index 18b459bd5..66bbb4c4d 100644
--- a/test/function/matrix/forEach.test.js
+++ b/test/function/matrix/forEach.test.js
@@ -18,36 +18,6 @@ describe('forEach', function() {
     assert.deepEqual(output, [1,2,3]);
   });
 
-  it('should invoke a typed function with correct number of arguments (1)', function() {
-    var output = [];
-    math.forEach([1,2,3], math.typed('callback', {
-      'number': function (value) {
-        output.push(value + 2)
-      }
-    }));
-    assert.deepEqual(output, [3,4,5]);
-  });
-
-  it('should invoke a typed function with correct number of arguments (2)', function() {
-    var output = [];
-    math.forEach([1,2,3], math.typed('callback', {
-      'number, Array': function (value, index) {
-        output.push(value + 2)
-      }
-    }));
-    assert.deepEqual(output, [3,4,5]);
-  });
-
-  it('should invoke a typed function with correct number of arguments (3)', function() {
-    var output = [];
-    math.forEach([1,2,3], math.typed('callback', {
-      'number, Array, Array': function (value, index, array) {
-        output.push(value + 2)
-      }
-    }));
-    assert.deepEqual(output, [3,4,5]);
-  });
-
   it('should invoke callback with parameters value, index, obj', function() {
     var arr = [[1,2,3], [4,5,6]];
     var output = [];
diff --git a/test/function/matrix/map.test.js b/test/function/matrix/map.test.js
index a51356801..bcf1c7f61 100644
--- a/test/function/matrix/map.test.js
+++ b/test/function/matrix/map.test.js
@@ -39,33 +39,6 @@ describe('map', function() {
 
   });
 
-  it('should invoke a typed function with correct number of arguments (1)', function() {
-    var output = math.map([1,2,3], math.typed('callback', {
-      'number': function (value) {
-        return value + 2
-      }
-    }));
-    assert.deepEqual(output, [3,4,5]);
-  });
-
-  it('should invoke a typed function with correct number of arguments (2)', function() {
-    var output = math.map([1,2,3], math.typed('callback', {
-      'number, Array': function (value, index) {
-        return value + 2
-      }
-    }));
-    assert.deepEqual(output, [3,4,5]);
-  });
-
-  it('should invoke a typed function with correct number of arguments (3)', function() {
-    var output = math.map([1,2,3], math.typed('callback', {
-      'number, Array, Array': function (value, index, array) {
-        return value + 2
-      }
-    }));
-    assert.deepEqual(output, [3,4,5]);
-  });
-
   it('should throw an error if called with unsupported type', function() {
     assert.throws(function() { math.map(1, function() {}) });
     assert.throws(function() { math.map('arr', function() {}) });
diff --git a/test/function/probability/distribution.test.js b/test/function/probability/distribution.test.js
index 9e0fa7186..10649899f 100644
--- a/test/function/probability/distribution.test.js
+++ b/test/function/probability/distribution.test.js
@@ -225,7 +225,109 @@ describe('distribution', function () {
 
   describe('pickRandom', function() {
 
-    it('should pick numbers from the given array following an uniform distribution', function() {
+    it('should throw an error when providing a multi dimensional matrix', function() {
+      assert.throws(function () {
+        uniformDistrib.pickRandom(math.matrix([[1,2], [3,4]]));
+      }, /Only one dimensional vectors supported/);
+    });
+
+    it('should throw an error if the length of the weights does not match the length of the possibles', function() {
+      var possibles = [11, 22, 33, 44, 55],
+          weights = [1, 5, 2, 4],
+          number = 2;
+
+      assert.throws(function() {
+        uniformDistrib.pickRandom(possibles, weights);
+      }, /Weights must have the same length as possibles/);
+
+      assert.throws(function() {
+        uniformDistrib.pickRandom(possibles, number, weights);
+      }, /Weights must have the same length as possibles/);
+
+      assert.throws(function() {
+        uniformDistrib.pickRandom(possibles, weights, number);
+      }, /Weights must have the same length as possibles/);
+    });
+
+    it('should throw an error if the weights array contains a non number or negative value', function() {
+      var possibles = [11, 22, 33, 44, 55],
+          weights = [1, 5, 2, -1, 6],
+          number = 2;
+
+      assert.throws(function() {
+        uniformDistrib.pickRandom(possibles, weights);
+      }, /Weights must be an array of positive numbers/);
+
+      weights = [1, 5, 2, "stinky", 6];
+
+      assert.throws(function() {
+        uniformDistrib.pickRandom(possibles, weights);
+      }, /Weights must be an array of positive numbers/);
+    });
+
+    it('should return a single value if no number argument was passed', function() {
+      var possibles = [11, 22, 33, 44, 55],
+          weights = [1, 5, 2, 4, 6];
+
+      assert.notEqual(possibles.indexOf(uniformDistrib.pickRandom(possibles)), -1);
+      assert.notEqual(possibles.indexOf(uniformDistrib.pickRandom(possibles, weights)), -1);
+    });
+
+    it('should return the given array if the given number is equal its length', function() {
+      var possibles = [11, 22, 33, 44, 55],
+          weights = [1, 5, 2, 4, 6],
+          number = 5;
+
+      assert.equal(uniformDistrib.pickRandom(possibles, number), possibles);
+      assert.equal(uniformDistrib.pickRandom(possibles, number, weights), possibles);
+      assert.equal(uniformDistrib.pickRandom(possibles, weights, number), possibles);
+    });
+
+    it('should return the given array if the given number is greater than its length', function() {
+      var possibles = [11, 22, 33, 44, 55],
+          weights = [1, 5, 2, 4, 6],
+          number = 6;
+
+      assert.equal(uniformDistrib.pickRandom(possibles, number), possibles);
+      assert.equal(uniformDistrib.pickRandom(possibles, number, weights), possibles);
+      assert.equal(uniformDistrib.pickRandom(possibles, weights, number), possibles);
+    });
+
+    it('should return an empty array if the given number is 0', function() {
+      var possibles = [11, 22, 33, 44, 55],
+          weights = [1, 5, 2, 4, 6],
+          number = 0;
+
+      assert.equal(uniformDistrib.pickRandom(possibles, number).length, 0);
+      assert.equal(uniformDistrib.pickRandom(possibles, number, weights).length, 0);
+      assert.equal(uniformDistrib.pickRandom(possibles, weights, number).length, 0);
+    });
+
+    it('should return an array of length 1 if the number passed is 1', function() {
+      var possibles = [11, 22, 33, 44, 55],
+          weights = [1, 5, 2, 4, 6],
+          number = 1;
+
+      assert(Array.isArray(uniformDistrib.pickRandom(possibles, number)));
+      assert(Array.isArray(uniformDistrib.pickRandom(possibles, number, weights)));
+      assert(Array.isArray(uniformDistrib.pickRandom(possibles, weights, number)));
+
+      assert.equal(uniformDistrib.pickRandom(possibles, number).length, 1);
+      assert.equal(uniformDistrib.pickRandom(possibles, number, weights).length, 1);
+      assert.equal(uniformDistrib.pickRandom(possibles, weights, number).length, 1);
+    });
+
+    it('should pick the given number of values from the given array', function() {
+      var possibles = [11, 22, 33, 44, 55],
+          weights = [1, 5, 2, 4, 6],
+          number = 3;
+
+      assert.equal(uniformDistrib.pickRandom(possibles, number).length, number);
+      assert.equal(uniformDistrib.pickRandom(possibles, number, weights).length, number);
+      assert.equal(uniformDistrib.pickRandom(possibles, weights, number).length, number);
+    });
+
+    it('should pick a value from the given array following an uniform distribution if only possibles are passed', function() {
       var possibles = [11, 22, 33, 44, 55],
           picked = [],
           count;
@@ -250,7 +352,7 @@ describe('distribution', function () {
       assert.equal(math.round(count/picked.length, 1), 0.2);
     });
 
-    it('should pick numbers from the given matrix following an uniform distribution', function() {
+    it('should pick a value from the given matrix following an uniform distribution', function() {
       var possibles = math.matrix([11, 22, 33, 44, 55]),
           picked = [],
           count;
@@ -275,10 +377,204 @@ describe('distribution', function () {
       assert.equal(math.round(count/picked.length, 1), 0.2);
     });
 
-    it('should throw an error when providing a multi dimensional matrix', function() {
-      assert.throws(function () {
-        uniformDistrib.pickRandom(math.matrix([[1,2], [3,4]]));
-      }, /Only one dimensional vectors supported/);
+    it('should pick a given number of values from the given array following an uniform distribution if no weights were passed', function() {
+      var possibles = [11, 22, 33, 44, 55],
+          number = 2,
+          picked = [],
+          count;
+
+      _.times(1000, function() {
+        picked.push.apply(picked, uniformDistrib.pickRandom(possibles, number));
+      });
+
+      assert.equal(picked.length, 2000);
+
+      count = _.filter(picked, function(val) { return val === 11 }).length;
+      assert.equal(math.round(count/picked.length, 1), 0.2);
+
+      count = _.filter(picked, function(val) { return val === 22 }).length;
+      assert.equal(math.round(count/picked.length, 1), 0.2);
+
+      count = _.filter(picked, function(val) { return val === 33 }).length;
+      assert.equal(math.round(count/picked.length, 1), 0.2);
+
+      count = _.filter(picked, function(val) { return val === 44 }).length;
+      assert.equal(math.round(count/picked.length, 1), 0.2);
+
+      count = _.filter(picked, function(val) { return val === 55 }).length;
+      assert.equal(math.round(count/picked.length, 1), 0.2);
+    });
+
+    it('should pick numbers from the given matrix following an uniform distribution', function() {
+      var possibles = math.matrix([11, 22, 33, 44, 55]),
+          number = 3,
+          picked = [],
+          count;
+
+      _.times(1000, function() {
+        picked.push.apply(picked, uniformDistrib.pickRandom(possibles, number));
+      });
+
+      assert.equal(picked.length, 3000);
+
+      count = _.filter(picked, function(val) { return val === 11 }).length;
+      assert.equal(math.round(count/picked.length, 1), 0.2);
+
+      count = _.filter(picked, function(val) { return val === 22 }).length;
+      assert.equal(math.round(count/picked.length, 1), 0.2);
+
+      count = _.filter(picked, function(val) { return val === 33 }).length;
+      assert.equal(math.round(count/picked.length, 1), 0.2);
+
+      count = _.filter(picked, function(val) { return val === 44 }).length;
+      assert.equal(math.round(count/picked.length, 1), 0.2);
+
+      count = _.filter(picked, function(val) { return val === 55 }).length;
+      assert.equal(math.round(count/picked.length, 1), 0.2);
+    });
+
+    it('should pick a value from the given array following a weighted distribution', function() {
+      var possibles = [11, 22, 33, 44, 55],
+        weights = [1, 4, 0, 2, 3],
+        picked = [],
+        count;
+
+      _.times(1000, function() {
+        picked.push(uniformDistrib.pickRandom(possibles, weights));
+      });
+
+      count = _.filter(picked, function(val) { return val === 11 }).length;
+      assert.equal(math.round(count/picked.length, 1), 0.1);
+
+      count = _.filter(picked, function(val) { return val === 22 }).length;
+      assert.equal(math.round((count)/picked.length, 1), 0.4);
+
+      count = _.filter(picked, function(val) { return val === 33 }).length;
+      assert.equal(math.round(count/picked.length, 1), 0);
+
+      count = _.filter(picked, function(val) { return val === 44 }).length;
+      assert.equal(math.round(count/picked.length, 1), 0.2);
+
+      count = _.filter(picked, function(val) { return val === 55 }).length;
+      assert.equal(math.round(count/picked.length, 1), 0.3);
+    });
+
+    it('should pick a value from the given matrix following a weighted distribution', function() {
+      var possibles = math.matrix([11, 22, 33, 44, 55]),
+          weights = [1, 4, 0, 2, 3],
+          picked = [],
+          count;
+
+      _.times(1000, function() {
+        picked.push(uniformDistrib.pickRandom(possibles, weights));
+      });
+
+      count = _.filter(picked, function(val) { return val === 11 }).length;
+      assert.equal(math.round(count/picked.length, 1), 0.1);
+
+      count = _.filter(picked, function(val) { return val === 22 }).length;
+      assert.equal(math.round((count)/picked.length, 1), 0.4);
+
+      count = _.filter(picked, function(val) { return val === 33 }).length;
+      assert.equal(math.round(count/picked.length, 1), 0);
+
+      count = _.filter(picked, function(val) { return val === 44 }).length;
+      assert.equal(math.round(count/picked.length, 1), 0.2);
+
+      count = _.filter(picked, function(val) { return val === 55 }).length;
+      assert.equal(math.round(count/picked.length, 1), 0.3);
+    });
+
+    it('should return an array of values from the given array following a weighted distribution', function() {
+      var possibles = [11, 22, 33, 44, 55],
+          weights = [1, 4, 0, 2, 3],
+          number = 2,
+          picked = [],
+          count;
+
+      _.times(1000, function() {
+        picked.push.apply(picked, uniformDistrib.pickRandom(possibles, number, weights));
+      });
+
+      count = _.filter(picked, function(val) { return val === 11 }).length;
+      assert.equal(math.round(count/picked.length, 1), 0.1);
+
+      count = _.filter(picked, function(val) { return val === 22 }).length;
+      assert.equal(math.round((count)/picked.length, 1), 0.4);
+
+      count = _.filter(picked, function(val) { return val === 33 }).length;
+      assert.equal(math.round(count/picked.length, 1), 0);
+
+      count = _.filter(picked, function(val) { return val === 44 }).length;
+      assert.equal(math.round(count/picked.length, 1), 0.2);
+
+      count = _.filter(picked, function(val) { return val === 55 }).length;
+      assert.equal(math.round(count/picked.length, 1), 0.3);
+
+      _.times(1000, function() {
+        picked.push.apply(picked, uniformDistrib.pickRandom(possibles, weights, number));
+      });
+
+      count = _.filter(picked, function(val) { return val === 11 }).length;
+      assert.equal(math.round(count/picked.length, 1), 0.1);
+
+      count = _.filter(picked, function(val) { return val === 22 }).length;
+      assert.equal(math.round((count)/picked.length, 1), 0.4);
+
+      count = _.filter(picked, function(val) { return val === 33 }).length;
+      assert.equal(math.round(count/picked.length, 1), 0);
+
+      count = _.filter(picked, function(val) { return val === 44 }).length;
+      assert.equal(math.round(count/picked.length, 1), 0.2);
+
+      count = _.filter(picked, function(val) { return val === 55 }).length;
+      assert.equal(math.round(count/picked.length, 1), 0.3);
+    });
+
+    it('should return an array of values from the given matrix following a weighted distribution', function() {
+      var possibles = math.matrix([11, 22, 33, 44, 55]),
+          weights = [1, 4, 0, 2, 3],
+          number = 2,
+          picked = [],
+          count;
+
+      _.times(1000, function() {
+        picked.push.apply(picked, uniformDistrib.pickRandom(possibles, number, weights));
+      });
+
+      count = _.filter(picked, function(val) { return val === 11 }).length;
+      assert.equal(math.round(count/picked.length, 1), 0.1);
+
+      count = _.filter(picked, function(val) { return val === 22 }).length;
+      assert.equal(math.round((count)/picked.length, 1), 0.4);
+
+      count = _.filter(picked, function(val) { return val === 33 }).length;
+      assert.equal(math.round(count/picked.length, 1), 0);
+
+      count = _.filter(picked, function(val) { return val === 44 }).length;
+      assert.equal(math.round(count/picked.length, 1), 0.2);
+
+      count = _.filter(picked, function(val) { return val === 55 }).length;
+      assert.equal(math.round(count/picked.length, 1), 0.3);
+
+      _.times(1000, function() {
+        picked.push.apply(picked, uniformDistrib.pickRandom(possibles, weights, number));
+      });
+
+      count = _.filter(picked, function(val) { return val === 11 }).length;
+      assert.equal(math.round(count/picked.length, 1), 0.1);
+
+      count = _.filter(picked, function(val) { return val === 22 }).length;
+      assert.equal(math.round((count)/picked.length, 1), 0.4);
+
+      count = _.filter(picked, function(val) { return val === 33 }).length;
+      assert.equal(math.round(count/picked.length, 1), 0);
+
+      count = _.filter(picked, function(val) { return val === 44 }).length;
+      assert.equal(math.round(count/picked.length, 1), 0.2);
+
+      count = _.filter(picked, function(val) { return val === 55 }).length;
+      assert.equal(math.round(count/picked.length, 1), 0.3);
     });
   });
 
@@ -320,7 +616,7 @@ describe('distribution', function () {
     assert.throws(function () {dist.random([2,3], 10, 100, 12); }, error.ArgumentsError);
     assert.throws(function () {dist.randomInt([2,3], 10, 100, 12); }, error.ArgumentsError);
     assert.throws(function () {dist.pickRandom(); }, error.ArgumentsError);
-    assert.throws(function () {dist.pickRandom([], 23); }, error.ArgumentsError);
+    assert.throws(function () {dist.pickRandom([], 23, [], 9); }, error.ArgumentsError);
   });
 
   it('created random functions should throw an error in case of wrong type of arguments', function() {
diff --git a/test/function/utils/isNaN.test.js b/test/function/utils/isNaN.test.js
deleted file mode 100644
index 72cf5724e..000000000
--- a/test/function/utils/isNaN.test.js
+++ /dev/null
@@ -1,77 +0,0 @@
-var assert = require('assert');
-var math = require('../../../index');
-var isNaN = math.isNaN;
-var bignumber = math.bignumber;
-var fraction = math.fraction;
-var complex = math.complex;
-var Unit = math.type.Unit;
-var Fraction = math.type.Fraction;
-
-describe('isNegative', function() {
-
-  it('should test whether a number is NaN', function() {
-    assert.strictEqual(isNaN(0), false);
-    assert.strictEqual(isNaN(2), false);
-    assert.strictEqual(isNaN(-3), false);
-    assert.strictEqual(isNaN(Infinity), false);
-    assert.strictEqual(isNaN(-Infinity), false);
-    assert.strictEqual(isNaN(NaN), true);
-  });
-
-  it('should test whether a boolean is NaN', function() {
-    assert.strictEqual(isNaN(true), false);
-    assert.strictEqual(isNaN(false), false);
-  });
-
-  it('should test whether a BigNumber is NaN', function() {
-    assert.strictEqual(isNaN(bignumber(0)), false);
-    assert.strictEqual(isNaN(bignumber(2)), false);
-    assert.strictEqual(isNaN(bignumber(-3)), false);
-    assert.strictEqual(isNaN(bignumber(Infinity)), false);
-    assert.strictEqual(isNaN(bignumber(-Infinity)), false);
-    assert.strictEqual(isNaN(bignumber(NaN)), true);
-  });
-
-  it('should test whether a Fraction is NaN', function() {
-    assert.strictEqual(isNaN(fraction(2)), false);
-    assert.strictEqual(isNaN(fraction(-3)), false);
-    assert.strictEqual(isNaN(fraction(0)), false);
-  });
-
-  it('should test whether a unit is NaN', function() {
-    assert.strictEqual(isNaN(new Unit(0, 'm')), false);
-    assert.strictEqual(isNaN(new Unit(0, 'kB')), false);
-    assert.strictEqual(isNaN(new Unit(5, 'cm')), false);
-    assert.strictEqual(isNaN(new Unit(-3, 'inch')), false);
-    assert.strictEqual(isNaN(new Unit(NaN, 'inch')), true);
-  });
-
-  it('should test whether a complex number contains NaN', function () {
-    assert.strictEqual(isNaN(complex(0, 0)), false);
-    assert.strictEqual(isNaN(complex(NaN, 0)), false);
-    assert.strictEqual(isNaN(complex(0, NaN)), false);
-    assert.strictEqual(isNaN(complex(NaN, NaN)), true);
-  });
-
-  it('should test whether a string contains a NaN', function() {
-    assert.strictEqual(isNaN('2'), false);
-    assert.strictEqual(isNaN('-2'), false);
-    assert.strictEqual(isNaN('0'), false);
-    assert.throws(function () {isNaN('NaN')}, /Error: Cannot convert "NaN" to a number/);
-    assert.strictEqual(isNaN(''), false);
-  });
-
-  it('should test isNegative element wise on an Array', function() {
-    assert.deepEqual(isNaN([0, 5, -2, NaN]), [false, false, false, true]);
-  });
-
-  it('should test isNegative element wise on a Matrix', function() {
-    assert.deepEqual(isNaN(math.matrix([0, 5, -2, NaN])), math.matrix([false, false, false, true]));
-  });
-
-  it('should throw an error in case of unsupported data types', function() {
-    assert.throws(function () {isNaN(new Date())}, /TypeError: Unexpected type of argument/);
-    assert.throws(function () {isNaN({})}, /TypeError: Unexpected type of argument/);
-  });
-
-});
diff --git a/test/utils/function.test.js b/test/utils/function.test.js
index 613a3117b..a87ec1cee 100644
--- a/test/utils/function.test.js
+++ b/test/utils/function.test.js
@@ -62,43 +62,4 @@ describe('util.function', function() {
 
   });
 
-  describe ('maxArgumentCount', function () {
-
-    it('should calculate the max argument count of a typed function', function() {
-      var a = function () {};
-      a.signatures = {
-        'number, number': function () {},
-        'number': function () {}
-      };
-      assert.equal(functionUtils.maxArgumentCount(a), 2);
-
-      var b = function () {};
-      b.signatures = {
-        'number': function () {},
-        'number, number': function () {}
-      };
-      assert.equal(functionUtils.maxArgumentCount(b), 2);
-
-      var c = function () {};
-      c.signatures = {
-        'number': function () {},
-        'BigNumber': function () {}
-      };
-      assert.equal(functionUtils.maxArgumentCount(c), 1);
-
-      var d = function () {};
-      d.signatures = {
-        'number,number': function () {},
-        'number': function () {},
-        'number,any,number': function () {}
-      };
-      assert.equal(functionUtils.maxArgumentCount(d), 3);
-    });
-
-    it('should return -1 for regular functions', function() {
-      assert.equal(functionUtils.maxArgumentCount(function () {}), -1);
-    });
-
-  });
-
 });