# vec4.random() in gl-matrix

## JavaScript performance comparison

Revision 7 of this test case created by

## Preparation code

``````<script src="https://rawgithub.com/toji/gl-matrix/master/dist/gl-matrix-min.js"></script>

<script>
Benchmark.prototype.setup = function() {
var length = Math.PI;

var out = vec4.create();

var GLMAT_RANDOM = Math.random;

// original
vec4.random = function (out, scale) {
scale = scale || 1.0;

//TODO: This is a pretty awful way of doing this. Find something better.
out[0] = GLMAT_RANDOM();
out[1] = GLMAT_RANDOM();
out[2] = GLMAT_RANDOM();
out[3] = GLMAT_RANDOM();
vec4.normalize(out, out);
vec4.scale(out, out, scale);
return out;
};

// allows negative components, but is still biased
vec4.random2 = function(out, len) {
len = len || 1;
out[0] = .5 - Math.random();
out[1] = .5 - Math.random();
out[2] = .5 - Math.random();
out[3] = .5 - Math.random();
var adjust = len / vec4.length(out);
return out;
};

// return a random float in (-1, 1]
var random_float_small = function() {
return 1 - 2 * Math.random();
};

// discards some results to remove bias
vec4.random3 = function(out, len) {
len = len || 1;
var m = 0;
while (m===0||m>1) {
out[0] = random_float_small();
out[1] = random_float_small();
out[2] = random_float_small();
out[3] = random_float_small();
m = vec4.length(out);
}
var adjust = len / m;
//out[3] = Math.sqrt(len*len - vec3.squaredLength(out)); // better approximation of len
return out;
};

/**
* Random Limitless Float
*
* @returns {Number} out random float in (-Infinity, Infinity)
*/
function randomLimitlessFloat() {

// random number in (-1, 1]
var r = 1 - 2 * (Math.random());

// 50% chance to get the reciprocal, which is in [1, Infinity] or (-Infinity, -1)
if (Math.random() < .5) {

// replace Infinity with -1, so the result is in (-Infinity, Infinity)
if (r===0) return -1;

return 1 / r;
}

return r;
}

vec4.random4 = function(out, len) {
len = len || 1;

var h = randomLimitlessFloat();

var h2 = h*h;
var h2p1 = h2 + 1;

var sin_h = 2*h / h2p1;
var cos_h = (1-h2) / h2p1;

var j = randomLimitlessFloat();

var j2 = j*j;
var j2p1 = j2 + 1;

var sin_j = 2*j / j2p1;
var cos_j = (1-j2) / j2p1;

var k = randomLimitlessFloat();

var k2 = k*k;
var k2p1 = k2 + 1;

var sin_k = 2*k / k2p1;
var cos_k = (1-k2) / k2p1;

out[0] = len * cos_h;
out[1] = len * sin_h * cos_j;
out[2] = len * sin_h * sin_j * cos_k;
out[3] = len * sin_h * sin_j * sin_k;

return out;
};

// return a random float in (0, PI]
var random_2PI = function() {
return Math.random() * Math.PI * 2;
};

function shuffleArray(array) {
for (var i = array.length - 1; i > 0; i--) {
var j = Math.floor(Math.random() * (i + 1));
var temp = array[i];
array[i] = array[j];
array[j] = temp;
}
return array;
}

vec4.random5 = function(out, len) {
len = len || 1;

var h = random_2PI();

var sin_h = Math.sin(h);
var cos_h = Math.cos(h);

var j = random_2PI();

var sin_j = Math.sin(j);
var cos_j = Math.cos(j);

var k = random_2PI();

var sin_k = Math.sin(k);
var cos_k = Math.cos(k);

out[0] = len * cos_h;
out[1] = len * sin_h * cos_j;
out[2] = len * sin_h * sin_j * cos_k;
out[3] = len * sin_h * sin_j * sin_k;

shuffleArray(out);

return out;
};

};

</script>
``````

## Test runner

Warning! For accurate results, please disable Firebug before running the tests. (Why?)

Java applet disabled.

Testing in CCBot 2.0.0 / Other 0.0.0
Test Ops/sec
vec4.random - original version
``vec4.random(out, length);``
pending…
vec4.random2 - allows negative components, but still biased towards cube corners
``vec4.random2(out, length);``
pending…
vec4.random3 - rejects vectors with length > 1 to avoid bias
``vec4.random3(out, length);``
pending…
vec4.random4 - uses rational trigonometry to rotate a random amount around 3 axis
``vec4.random4(out, length);``
pending…
vec4.random5 - same idea but with classical trigonometry
``vec4.random5(out, length);``
pending…

## Revisions

You can edit these tests or add even more tests to this page by appending `/edit` to the URL.