Fast cos tests

Fast cos tests

by Csaba Hellinger

HTML

<div>
  <canvas id="canvas1" width="2000" height="2000"></canvas>
  <canvas id="canvas2" width="2000" height="2000"></canvas>
  <canvas id="canvas3" width="2000" height="2000"></canvas>
</div>

CSS

div {
  display:grid;
  grid-template-columns: 1fr 1fr 1fr;
  gap: 0.5rem;
}

canvas {
  width: 100%;
  background: pink;
}

body {
  background: #222;
}

JavaScript

const PI = Math.PI;

const draw = (canvasId, cos, name) => {
  const canvas = document.getElementById(canvasId);
  const context = canvas.getContext('2d');
  const imageData = context.getImageData(0,0,canvas.width, canvas.height);
  const data = imageData.data;
  const S = Math.max(canvas.width, canvas.height);
  const start = performance.now();
  for (let y=0; y<S; y+=1) {
    for (let x=0; x<S; x+=1) {
      const i = (y * S + x) * 4;
      data[i + 0] = Math.trunc((cos(2*PI/S*x*3+PI) + cos(2*PI/S*y+PI))    * 128);
      data[i + 1] = Math.trunc((cos(2*PI/S*x*2   ) + cos(2*PI/S*y*2 ))    * 128);
      data[i + 2] = Math.trunc((cos(2*PI/S*x  +PI) + cos(2*PI/S*y    )*2) * 128);
      data[i + 3] = 255;
    }
  }
  console.log(name, performance.now()-start);
  context.putImageData(imageData, 0, 0);
};

draw('canvas1', Math.cos, 'Math.cos');

const lookup = Array(360).fill(0).map((_,i) => Math.cos(PI/180*i));
const fastCos2 = rad => lookup[Math.trunc(rad / PI * 180) % 360];
const fastCos3 = rad => lookup[~~(rad / PI * 180) % 360];
const fastCos4 = rad => lookup[~~(rad / radToDeg) % 360];
const radToDeg = PI / 180;

draw('canvas2', fastCos4, 'fastCos4');

//const lookup2 = Array(629).fill(0).map((_,i) => Math.cos(i*0.01));
//const fastCos5 = rad => lookup2[~~((rad % (2*PI)) * 100)];

const TABLE_SIZE = 256; // power of two
const INDEX_FACTOR = TABLE_SIZE / (2 * PI); // scale radians to table index
const lookup2 = Array(TABLE_SIZE).fill(0).map((_, i) => Math.cos(i / INDEX_FACTOR));
const fastCos5 = rad => lookup2[(rad * INDEX_FACTOR) & (TABLE_SIZE - 1)];

draw('canvas3', fastCos5, 'fastCos5');