vec4.random() in gl-matrix

JavaScript performance comparison

Revision 8 of this test case created

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);
        out[0] *= adjust;
        out[1] *= adjust;
        out[2] *= adjust;
        out[3] *= adjust;
        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[0] *= adjust;
        out[1] *= adjust;
        out[2] *= adjust;
        out[3] *= adjust;
        //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;
   
        //is the bias avoided by randomizing order of the axis?
        //shuffleArray(out);
   
        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 unknown unknown
Test Ops/sec
original
vec4.random(out, length);
pending…
allows negative components, but still biased towards cube corners
vec4.random2(out, length);
pending…
rejects vectors with length > 1 to avoid bias
vec4.random3(out, length);
pending…
uses rational trigonometry to rotate a random amount around 3 axis
vec4.random4(out, length);
pending…
same idea but with classical trigonometry
vec4.random5(out, length);
pending…

Compare results of other browsers

Revisions

You can edit these tests or add even more tests to this page by appending /edit to the URL. Here’s a list of current revisions for this page:

0 comments

Add a comment