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);
      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;
  
      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…

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.

0 Comments