Merge pull request #47 from sebpiq/random

Merged randomMatrix and random
This commit is contained in:
Jos de Jong 2013-08-04 04:34:48 -07:00
commit 3be2a6e68c
3 changed files with 143 additions and 123 deletions

69
math.js
View File

@ -7,7 +7,7 @@
* mathematical functions, and a flexible expression parser.
*
* @version 0.11.2-SNAPSHOT
* @date 2013-08-02
* @date 2013-08-04
*
* @license
* Copyright (C) 2013 Jos de Jong <wjosdejong@gmail.com>
@ -439,28 +439,6 @@ var util = (function () {
return res;
};
/**
* For each method for objects and arrays.
* In case of an object, the method loops over all properties of the object.
* In case of an array, the method loops over all indexes of the array.
* @param {Object | Array} object The object
* @param {function} callback Callback method, called for each item in
* the object or array with three parameters:
* callback(value, index, object)
*/
util.forEach = function forEach (object, callback) {
if (object instanceof Array) {
object.forEach(callback);
}
else {
for (var key in object) {
if (object.hasOwnProperty(key)) {
callback(object[key], key, object);
}
}
}
};
/**
* Creates a new object with the results of calling a provided function on
* every prop in the object.
@ -7540,6 +7518,15 @@ var distributions = {
}
};
/**
* Create a distribution object.
* @param {String} name Name of a distribution.
* Choose from 'uniform', 'normal'.
* @return {Object} distribution A distribution object containing functions:
* random([size, min, max])
* randomInt([min, max])
* pickRandom(array)
*/
math.distribution = function(name) {
if (!distributions.hasOwnProperty(name))
throw new Error('unknown distribution ' + name);
@ -7552,12 +7539,27 @@ math.distribution = function(name) {
var randFunctions = {
random: function(min, max) {
if (arguments.length > 2)
newArgumentsError('random', arguments.length, 0, 2);
if (max === undefined) max = 1
if (min === undefined) min = 0
return min + distribution() * (max - min);
random: function(arg1, arg2, arg3) {
if (arguments.length > 3)
newArgumentsError('random', arguments.length, 0, 3);
// Random matrix
else if (Object.prototype.toString.call(arg1) === '[object Array]') {
var min = arg2, max = arg3;
if (max === undefined) max = 1;
if (min === undefined) min = 0;
return new Matrix(_randomDataForMatrix(arg1, min, max));
// Random float
} else {
// TODO: more precise error message?
if (arguments.length > 2)
newArgumentsError('random', arguments.length, 0, 2);
var min = arg1, max = arg2;
if (max === undefined) max = 1;
if (min === undefined) min = 0;
return min + distribution() * (max - min);
}
},
randomInt: function(min, max) {
@ -7570,13 +7572,6 @@ math.distribution = function(name) {
if (arguments.length !== 1)
newArgumentsError('pickRandom', arguments.length, 1);
return possibles[Math.floor(Math.random() * possibles.length)];
},
randomMatrix: function(size, min, max) {
if (arguments.length > 3 || arguments.length < 1)
newArgumentsError('pickRandom', arguments.length, 1, 3);
debugger
return new Matrix(_randomDataForMatrix(size, min, max));
}
};
@ -9463,7 +9458,7 @@ function isSupportedType(object) {
name = token;
fn = math.unary;
getToken();
params = [parse_pow(scope)];
params = [parse_unary(scope)];
return new OperatorNode(name, fn, params);
}

View File

@ -39,7 +39,7 @@ var distributions = {
* @param {String} name Name of a distribution.
* Choose from 'uniform', 'normal'.
* @return {Object} distribution A distribution object containing functions:
* random([min, max])
* random([size, min, max])
* randomInt([min, max])
* pickRandom(array)
*/
@ -55,12 +55,27 @@ math.distribution = function(name) {
var randFunctions = {
random: function(min, max) {
if (arguments.length > 2)
newArgumentsError('random', arguments.length, 0, 2);
if (max === undefined) max = 1;
if (min === undefined) min = 0;
return min + distribution() * (max - min);
random: function(arg1, arg2, arg3) {
if (arguments.length > 3)
newArgumentsError('random', arguments.length, 0, 3);
// Random matrix
else if (Object.prototype.toString.call(arg1) === '[object Array]') {
var min = arg2, max = arg3;
if (max === undefined) max = 1;
if (min === undefined) min = 0;
return new Matrix(_randomDataForMatrix(arg1, min, max));
// Random float
} else {
// TODO: more precise error message?
if (arguments.length > 2)
newArgumentsError('random', arguments.length, 0, 2);
var min = arg1, max = arg2;
if (max === undefined) max = 1;
if (min === undefined) min = 0;
return min + distribution() * (max - min);
}
},
randomInt: function(min, max) {
@ -73,12 +88,6 @@ math.distribution = function(name) {
if (arguments.length !== 1)
newArgumentsError('pickRandom', arguments.length, 1);
return possibles[Math.floor(Math.random() * possibles.length)];
},
randomMatrix: function(size, min, max) {
if (arguments.length > 3 || arguments.length < 1)
newArgumentsError('pickRandom', arguments.length, 1, 3);
return new Matrix(_randomDataForMatrix(size, min, max));
}
};

View File

@ -8,38 +8,96 @@ var assertApproxEqual = function(testVal, val, tolerance) {
else assert.ok(diff <= tolerance)
}
var testRandom = function() {
var assertUniformDistribution = function(values, min, max) {
var interval = (max - min) / 10
count = _.filter(values, function(val) { return val < min }).length
assert.equal(count, 0)
count = _.filter(values, function(val) { return val > max }).length
assert.equal(count, 0)
count = _.filter(values, function(val) { return val < (min + interval) }).length
assert.equal(math.round(count/values.length, 1), 0.1)
count = _.filter(values, function(val) { return val >= (min + interval) && val < (min + 2 * interval) }).length
assert.equal(math.round(count/values.length, 1), 0.1)
count = _.filter(values, function(val) { return val >= (min + 2 * interval) && val < (min + 3 * interval) }).length
assert.equal(math.round(count/values.length, 1), 0.1)
count = _.filter(values, function(val) { return val >= (min + 3 * interval) && val < (min + 4 * interval) }).length
assert.equal(math.round(count/values.length, 1), 0.1)
count = _.filter(values, function(val) { return val >= (min + 4 * interval) && val < (min + 5 * interval) }).length
assert.equal(math.round(count/values.length, 1), 0.1)
count = _.filter(values, function(val) { return val >= (min + 5 * interval) && val < (min + 6 * interval) }).length
assert.equal(math.round(count/values.length, 1), 0.1)
count = _.filter(values, function(val) { return val >= (min + 6 * interval) && val < (min + 7 * interval) }).length
assert.equal(math.round(count/values.length, 1), 0.1)
count = _.filter(values, function(val) { return val >= (min + 7 * interval) && val < (min + 8 * interval) }).length
assert.equal(math.round(count/values.length, 1), 0.1)
count = _.filter(values, function(val) { return val >= (min + 8 * interval) && val < (min + 9 * interval) }).length
assert.equal(math.round(count/values.length, 1), 0.1)
count = _.filter(values, function(val) { return val >= (min + 9 * interval) }).length
assert.equal(math.round(count/values.length, 1), 0.1)
}
var testRandomFloat = function() {
var picked = [], count
_.times(1000, function() {
picked.push(math.random())
})
assertUniformDistribution(picked, 0, 1)
}
var testRandomFloatMinMax = function() {
var picked = [], count
_.times(1000, function() {
picked.push(math.random(-10, 10))
})
assertUniformDistribution(picked, -10, 10)
}
count = _.filter(picked, function(val) { return val < -10 }).length
assert.equal(count, 0)
count = _.filter(picked, function(val) { return val > 10 }).length
assert.equal(count, 0)
var testRandomMatrix = function() {
var picked = [],
matrices = [],
size = [2, 3, 4],
count, matrix
count = _.filter(picked, function(val) { return val < -8 }).length
assert.equal(math.round(count/picked.length, 1), 0.1)
count = _.filter(picked, function(val) { return val >= -8 && val < -6 }).length
assert.equal(math.round(count/picked.length, 1), 0.1)
count = _.filter(picked, function(val) { return val >= -6 && val < -4 }).length
assert.equal(math.round(count/picked.length, 1), 0.1)
count = _.filter(picked, function(val) { return val >= -4 && val < -2 }).length
assert.equal(math.round(count/picked.length, 1), 0.1)
count = _.filter(picked, function(val) { return val >= -2 && val < 0 }).length
assert.equal(math.round(count/picked.length, 1), 0.1)
count = _.filter(picked, function(val) { return val >= 0 && val < 2 }).length
assert.equal(math.round(count/picked.length, 1), 0.1)
count = _.filter(picked, function(val) { return val >= 2 && val < 4 }).length
assert.equal(math.round(count/picked.length, 1), 0.1)
count = _.filter(picked, function(val) { return val >= 4 && val < 6 }).length
assert.equal(math.round(count/picked.length, 1), 0.1)
count = _.filter(picked, function(val) { return val >= 6 && val < 8 }).length
assert.equal(math.round(count/picked.length, 1), 0.1)
count = _.filter(picked, function(val) { return val >= 8 }).length
assert.equal(math.round(count/picked.length, 1), 0.1)
_.times(100, function() {
matrices.push(math.random(size))
})
// Collect all values in one array
matrices.forEach(function(matrix) {
assert.deepEqual(matrix.size(), size)
matrix.forEach(function(val) {
picked.push(val)
})
})
assert.equal(picked.length, 2 * 3 * 4 * 100)
assertUniformDistribution(picked, 0, 1)
}
var testRandomMatrixMinMax = function() {
var picked = [],
matrices = [],
size = [2, 3, 4],
count, matrix
_.times(100, function() {
matrices.push(math.random(size, -103, 8))
})
// Collect all values in one array
matrices.forEach(function(matrix) {
assert.deepEqual(matrix.size(), size)
matrix.forEach(function(val) {
picked.push(val)
})
})
assert.equal(picked.length, 2 * 3 * 4 * 100)
assertUniformDistribution(picked, -103, 8)
}
var testRandomInt = function() {
@ -102,52 +160,6 @@ var testPickRandom = function() {
assert.equal(math.round(count/picked.length, 1), 0.2)
}
var testRandomMatrix = function(size, min, max) {
var picked = [],
matrices = [],
size = [2, 3, 4],
count, matrix
_.times(100, function() {
matrices.push(math.randomMatrix(size, -10, 10))
})
// Collect all values in one array
matrices.forEach(function(matrix) {
assert.deepEqual(matrix.size(), size)
matrix.forEach(function(val) {
picked.push(val)
})
})
assert.equal(picked.length, 2 * 3 * 4 * 100)
count = _.filter(picked, function(val) { return val < -10 }).length
assert.equal(count, 0)
count = _.filter(picked, function(val) { return val > 10 }).length
assert.equal(count, 0)
count = _.filter(picked, function(val) { return val < -8 }).length
assert.equal(math.round(count/picked.length, 1), 0.1)
count = _.filter(picked, function(val) { return val >= -8 && val < -6 }).length
assert.equal(math.round(count/picked.length, 1), 0.1)
count = _.filter(picked, function(val) { return val >= -6 && val < -4 }).length
assert.equal(math.round(count/picked.length, 1), 0.1)
count = _.filter(picked, function(val) { return val >= -4 && val < -2 }).length
assert.equal(math.round(count/picked.length, 1), 0.1)
count = _.filter(picked, function(val) { return val >= -2 && val < 0 }).length
assert.equal(math.round(count/picked.length, 1), 0.1)
count = _.filter(picked, function(val) { return val >= 0 && val < 2 }).length
assert.equal(math.round(count/picked.length, 1), 0.1)
count = _.filter(picked, function(val) { return val >= 2 && val < 4 }).length
assert.equal(math.round(count/picked.length, 1), 0.1)
count = _.filter(picked, function(val) { return val >= 4 && val < 6 }).length
assert.equal(math.round(count/picked.length, 1), 0.1)
count = _.filter(picked, function(val) { return val >= 6 && val < 8 }).length
assert.equal(math.round(count/picked.length, 1), 0.1)
count = _.filter(picked, function(val) { return val >= 8 }).length
assert.equal(math.round(count/picked.length, 1), 0.1)
}
var testRandomNormal = function() {
var picked = [], count, distribution = math.distribution('normal')
@ -171,9 +183,13 @@ var testRandomNormal = function() {
assertApproxEqual(count/picked.length, 0.93, 0.01)
}
testRandom()
testRandomFloat()
testRandomFloatMinMax()
testRandomMatrix()
testRandomMatrixMinMax()
testRandomInt()
testPickRandom()
testRandomMatrix()
testRandomNormal()