Published
Edited
Apr 6, 2020
1 star
Insert cell
Insert cell
Insert cell
{
const concatNumbersCPU = (a, b) => a * Math.pow(10, Math.floor(Math.log(b) / Math.log(10)) + 1) + b;
return concatNumbersCPU(12345, 67890); // => 1234567890
}
Insert cell
Insert cell
{
const gpu = new GPU();

const concatNumbersGPU = gpu.createKernel(function (a, b) {
return a * Math.pow(10, Math.floor(Math.log(b) / Math.log(10)) + 1) + b;
}, { output: [1] });

return concatNumbersGPU(12345, 67890)[0]; // => 1234567552
}
Insert cell
md`## Raw precision`
Insert cell
{
const gpu = new GPU();

const concatNumbersGPU = gpu.createKernel(function (a, b) {
return 1234567890;
}, { output: [1] });

return concatNumbersGPU(12345, 67890)[0]; // => 1234567936
}
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
{
function Kernel(settings) {
const { context, constants } = settings;

const gl = context;

const glVariables0 = gl.getExtension('OES_texture_float');
const glVariables1 = gl.getExtension('OES_texture_float_linear');
const glVariables2 = gl.getExtension('OES_element_index_uint');
const glVariables3 = gl.getExtension('WEBGL_draw_buffers');
const glVariables4 = gl.getExtension('WEBGL_color_buffer_float');
gl.enable(gl.SCISSOR_TEST);
gl.viewport(0, 0, 1, 1);
const glVariable5 = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(glVariable5, `precision highp float;
precision highp int;
precision highp sampler2D;

attribute vec2 aPos;
attribute vec2 aTexCoord;

varying vec2 vTexCoord;
uniform vec2 ratio;

void main(void) {
gl_Position = vec4((aPos + vec2(1)) * ratio + vec2(-1), 0, 1);
vTexCoord = aTexCoord;
}`);
gl.compileShader(glVariable5);
const glVariable6 = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(glVariable6, `precision highp float;
precision highp int;
precision highp sampler2D;

const int LOOP_MAX = 1000;

ivec3 uOutputDim = ivec3(1, 1, 1);
ivec2 uTexSize = ivec2(1, 1);

varying vec2 vTexCoord;

float acosh(float x) {
return log(x + sqrt(x * x - 1.0));
}

float sinh(float x) {
return (pow(2.718281828459045, x) - pow(2.718281828459045, -x)) / 2.0;
}

float asinh(float x) {
return log(x + sqrt(x * x + 1.0));
}

float atan2(float v1, float v2) {
if (v1 == 0.0 || v2 == 0.0) return 0.0;
return atan(v1 / v2);
}

float atanh(float x) {
x = (x + 1.0) / (x - 1.0);
if (x < 0.0) {
return 0.5 * log(-x);
}
return 0.5 * log(x);
}

float cbrt(float x) {
if (x >= 0.0) {
return pow(x, 1.0 / 3.0);
} else {
return -pow(x, 1.0 / 3.0);
}
}

float cosh(float x) {
return (pow(2.718281828459045, x) + pow(2.718281828459045, -x)) / 2.0;
}

float expm1(float x) {
return pow(2.718281828459045, x) - 1.0;
}

float fround(highp float x) {
return x;
}

float imul(float v1, float v2) {
return float(int(v1) * int(v2));
}

float log10(float x) {
return log2(x) * (1.0 / log2(10.0));
}

float log1p(float x) {
return log(1.0 + x);
}

float _pow(float v1, float v2) {
if (v2 == 0.0) return 1.0;
return pow(v1, v2);
}

float tanh(float x) {
float e = exp(2.0 * x);
return (e - 1.0) / (e + 1.0);
}

float trunc(float x) {
if (x >= 0.0) {
return floor(x);
} else {
return ceil(x);
}
}

vec4 _round(vec4 x) {
return floor(x + 0.5);
}

float _round(float x) {
return floor(x + 0.5);
}

const int BIT_COUNT = 32;
int modi(int x, int y) {
return x - y * (x / y);
}

int bitwiseOr(int a, int b) {
int result = 0;
int n = 1;

for (int i = 0; i < BIT_COUNT; i++) {
if ((modi(a, 2) == 1) || (modi(b, 2) == 1)) {
result += n;
}
a = a / 2;
b = b / 2;
n = n * 2;
if(!(a > 0 || b > 0)) {
break;
}
}
return result;
}
int bitwiseXOR(int a, int b) {
int result = 0;
int n = 1;

for (int i = 0; i < BIT_COUNT; i++) {
if ((modi(a, 2) == 1) != (modi(b, 2) == 1)) {
result += n;
}
a = a / 2;
b = b / 2;
n = n * 2;
if(!(a > 0 || b > 0)) {
break;
}
}
return result;
}
int bitwiseAnd(int a, int b) {
int result = 0;
int n = 1;
for (int i = 0; i < BIT_COUNT; i++) {
if ((modi(a, 2) == 1) && (modi(b, 2) == 1)) {
result += n;
}
a = a / 2;
b = b / 2;
n = n * 2;
if(!(a > 0 && b > 0)) {
break;
}
}
return result;
}
int bitwiseNot(int a) {
int result = 0;
int n = 1;

for (int i = 0; i < BIT_COUNT; i++) {
if (modi(a, 2) == 0) {
result += n;
}
a = a / 2;
n = n * 2;
}
return result;
}
int bitwiseZeroFillLeftShift(int n, int shift) {
int maxBytes = BIT_COUNT;
for (int i = 0; i < BIT_COUNT; i++) {
if (maxBytes >= n) {
break;
}
maxBytes *= 2;
}
for (int i = 0; i < BIT_COUNT; i++) {
if (i >= shift) {
break;
}
n *= 2;
}

int result = 0;
int byteVal = 1;
for (int i = 0; i < BIT_COUNT; i++) {
if (i >= maxBytes) break;
if (modi(n, 2) > 0) { result += byteVal; }
n = int(n / 2);
byteVal *= 2;
}
return result;
}

int bitwiseSignedRightShift(int num, int shifts) {
return int(floor(float(num) / pow(2.0, float(shifts))));
}

int bitwiseZeroFillRightShift(int n, int shift) {
int maxBytes = BIT_COUNT;
for (int i = 0; i < BIT_COUNT; i++) {
if (maxBytes >= n) {
break;
}
maxBytes *= 2;
}
for (int i = 0; i < BIT_COUNT; i++) {
if (i >= shift) {
break;
}
n /= 2;
}
int result = 0;
int byteVal = 1;
for (int i = 0; i < BIT_COUNT; i++) {
if (i >= maxBytes) break;
if (modi(n, 2) > 0) { result += byteVal; }
n = int(n / 2);
byteVal *= 2;
}
return result;
}

vec2 integerMod(vec2 x, float y) {
vec2 res = floor(mod(x, y));
return res * step(1.0 - floor(y), -res);
}

vec3 integerMod(vec3 x, float y) {
vec3 res = floor(mod(x, y));
return res * step(1.0 - floor(y), -res);
}

vec4 integerMod(vec4 x, vec4 y) {
vec4 res = floor(mod(x, y));
return res * step(1.0 - floor(y), -res);
}

float integerMod(float x, float y) {
float res = floor(mod(x, y));
return res * (res > floor(y) - 1.0 ? 0.0 : 1.0);
}

int integerMod(int x, int y) {
return x - (y * int(x / y));
}

float divWithIntCheck(float x, float y) {
if (floor(x) == x && floor(y) == y && integerMod(x, y) == 0.0) {
return float(int(x) / int(y));
}
return x / y;
}

float integerCorrectionModulo(float number, float divisor) {
if (number < 0.0) {
number = abs(number);
if (divisor < 0.0) {
divisor = abs(divisor);
}
return -(number - (divisor * floor(divWithIntCheck(number, divisor))));
}
if (divisor < 0.0) {
divisor = abs(divisor);
}
return number - (divisor * floor(divWithIntCheck(number, divisor)));
}
// Here be dragons!
// DO NOT OPTIMIZE THIS CODE
// YOU WILL BREAK SOMETHING ON SOMEBODY'S MACHINE
// LEAVE IT AS IT IS, LEST YOU WASTE YOUR OWN TIME
const vec2 MAGIC_VEC = vec2(1.0, -256.0);
const vec4 SCALE_FACTOR = vec4(1.0, 256.0, 65536.0, 0.0);
const vec4 SCALE_FACTOR_INV = vec4(1.0, 0.00390625, 0.0000152587890625, 0.0); // 1, 1/256, 1/65536
float decode32(vec4 texel) {
texel *= 255.0;
vec2 gte128;
gte128.x = texel.b >= 128.0 ? 1.0 : 0.0;
gte128.y = texel.a >= 128.0 ? 1.0 : 0.0;
float exponent = 2.0 * texel.a - 127.0 + dot(gte128, MAGIC_VEC);
float res = exp2(_round(exponent));
texel.b = texel.b - 128.0 * gte128.x;
res = dot(texel, SCALE_FACTOR) * exp2(_round(exponent-23.0)) + res;
res *= gte128.y * -2.0 + 1.0;
return res;
}

float decode16(vec4 texel, int index) {
int channel = integerMod(index, 2);
if (channel == 0) return texel.r * 255.0 + texel.g * 65280.0;
if (channel == 1) return texel.b * 255.0 + texel.a * 65280.0;
return 0.0;
}

float decode8(vec4 texel, int index) {
int channel = integerMod(index, 4);
if (channel == 0) return texel.r * 255.0;
if (channel == 1) return texel.g * 255.0;
if (channel == 2) return texel.b * 255.0;
if (channel == 3) return texel.a * 255.0;
return 0.0;
}

vec4 legacyEncode32(float f) {
float F = abs(f);
float sign = f < 0.0 ? 1.0 : 0.0;
float exponent = floor(log2(F));
float mantissa = (exp2(-exponent) * F);
// exponent += floor(log2(mantissa));
vec4 texel = vec4(F * exp2(23.0-exponent)) * SCALE_FACTOR_INV;
texel.rg = integerMod(texel.rg, 256.0);
texel.b = integerMod(texel.b, 128.0);
texel.a = exponent*0.5 + 63.5;
texel.ba += vec2(integerMod(exponent+127.0, 2.0), sign) * 128.0;
texel = floor(texel);
texel *= 0.003921569; // 1/255
return texel;
}

// https://github.com/gpujs/gpu.js/wiki/Encoder-details
vec4 encode32(float value) {
if (value == 0.0) return vec4(0, 0, 0, 0);

float exponent;
float mantissa;
vec4 result;
float sgn;

sgn = step(0.0, -value);
value = abs(value);

exponent = floor(log2(value));

mantissa = value*pow(2.0, -exponent)-1.0;
exponent = exponent+127.0;
result = vec4(0,0,0,0);

result.a = floor(exponent/2.0);
exponent = exponent - result.a*2.0;
result.a = result.a + 128.0*sgn;

result.b = floor(mantissa * 128.0);
mantissa = mantissa - result.b / 128.0;
result.b = result.b + exponent*128.0;

result.g = floor(mantissa*32768.0);
mantissa = mantissa - result.g/32768.0;

result.r = floor(mantissa*8388608.0);
return result/255.0;
}
// Dragons end here

int index;
ivec3 threadId;

ivec3 indexTo3D(int idx, ivec3 texDim) {
int z = int(idx / (texDim.x * texDim.y));
idx -= z * int(texDim.x * texDim.y);
int y = int(idx / texDim.x);
int x = int(integerMod(idx, texDim.x));
return ivec3(x, y, z);
}

float get32(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) {
int index = x + texDim.x * (y + texDim.y * z);
int w = texSize.x;
vec2 st = vec2(float(integerMod(index, w)), float(index / w)) + 0.5;
vec4 texel = texture2D(tex, st / vec2(texSize));
return decode32(texel);
}

float get16(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) {
int index = x + texDim.x * (y + texDim.y * z);
int w = texSize.x * 2;
vec2 st = vec2(float(integerMod(index, w)), float(index / w)) + 0.5;
vec4 texel = texture2D(tex, st / vec2(texSize.x * 2, texSize.y));
return decode16(texel, index);
}

float get8(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) {
int index = x + texDim.x * (y + texDim.y * z);
int w = texSize.x * 4;
vec2 st = vec2(float(integerMod(index, w)), float(index / w)) + 0.5;
vec4 texel = texture2D(tex, st / vec2(texSize.x * 4, texSize.y));
return decode8(texel, index);
}

float getMemoryOptimized32(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) {
int index = x + texDim.x * (y + texDim.y * z);
int channel = integerMod(index, 4);
index = index / 4;
int w = texSize.x;
vec2 st = vec2(float(integerMod(index, w)), float(index / w)) + 0.5;
vec4 texel = texture2D(tex, st / vec2(texSize));
if (channel == 0) return texel.r;
if (channel == 1) return texel.g;
if (channel == 2) return texel.b;
if (channel == 3) return texel.a;
return 0.0;
}

vec4 getImage2D(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) {
int index = x + texDim.x * (y + texDim.y * z);
int w = texSize.x;
vec2 st = vec2(float(integerMod(index, w)), float(index / w)) + 0.5;
return texture2D(tex, st / vec2(texSize));
}

float getFloatFromSampler2D(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) {
vec4 result = getImage2D(tex, texSize, texDim, z, y, x);
return result[0];
}

vec2 getVec2FromSampler2D(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) {
vec4 result = getImage2D(tex, texSize, texDim, z, y, x);
return vec2(result[0], result[1]);
}

vec2 getMemoryOptimizedVec2(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) {
int index = x + (texDim.x * (y + (texDim.y * z)));
int channel = integerMod(index, 2);
index = index / 2;
int w = texSize.x;
vec2 st = vec2(float(integerMod(index, w)), float(index / w)) + 0.5;
vec4 texel = texture2D(tex, st / vec2(texSize));
if (channel == 0) return vec2(texel.r, texel.g);
if (channel == 1) return vec2(texel.b, texel.a);
return vec2(0.0, 0.0);
}

vec3 getVec3FromSampler2D(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) {
vec4 result = getImage2D(tex, texSize, texDim, z, y, x);
return vec3(result[0], result[1], result[2]);
}

vec3 getMemoryOptimizedVec3(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) {
int fieldIndex = 3 * (x + texDim.x * (y + texDim.y * z));
int vectorIndex = fieldIndex / 4;
int vectorOffset = fieldIndex - vectorIndex * 4;
int readY = vectorIndex / texSize.x;
int readX = vectorIndex - readY * texSize.x;
vec4 tex1 = texture2D(tex, (vec2(readX, readY) + 0.5) / vec2(texSize));

if (vectorOffset == 0) {
return tex1.xyz;
} else if (vectorOffset == 1) {
return tex1.yzw;
} else {
readX++;
if (readX >= texSize.x) {
readX = 0;
readY++;
}
vec4 tex2 = texture2D(tex, vec2(readX, readY) / vec2(texSize));
if (vectorOffset == 2) {
return vec3(tex1.z, tex1.w, tex2.x);
} else {
return vec3(tex1.w, tex2.x, tex2.y);
}
}
}

vec4 getVec4FromSampler2D(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) {
return getImage2D(tex, texSize, texDim, z, y, x);
}

vec4 getMemoryOptimizedVec4(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) {
int index = x + texDim.x * (y + texDim.y * z);
int channel = integerMod(index, 2);
int w = texSize.x;
vec2 st = vec2(float(integerMod(index, w)), float(index / w)) + 0.5;
vec4 texel = texture2D(tex, st / vec2(texSize));
return vec4(texel.r, texel.g, texel.b, texel.a);
}

vec4 actualColor;
void color(float r, float g, float b, float a) {
actualColor = vec4(r,g,b,a);
}

void color(float r, float g, float b) {
color(r,g,b,1.0);
}

void color(sampler2D image) {
actualColor = texture2D(image, vTexCoord);
}

float modulo(float number, float divisor) {
if (number < 0.0) {
number = abs(number);
if (divisor < 0.0) {
divisor = abs(divisor);
}
return -mod(number, divisor);
}
if (divisor < 0.0) {
divisor = abs(divisor);
}
return mod(number, divisor);
}

uniform float user_a;
uniform float user_b;
float kernelResult;
void kernel() {
kernelResult = ((user_a*_pow(10.0, (floor(divWithIntCheck(log(user_b), log(10.0)))+1.0)))+user_b);return;
}
void main(void) {
index = int(vTexCoord.s * float(uTexSize.x)) + int(vTexCoord.t * float(uTexSize.y)) * uTexSize.x;
threadId = indexTo3D(index, uOutputDim);
kernel();
gl_FragData[0][0] = kernelResult;

}`);
gl.compileShader(glVariable6);
const glVariable7 = gl.getShaderParameter(glVariable5, gl.COMPILE_STATUS);
const glVariable8 = gl.getShaderParameter(glVariable6, gl.COMPILE_STATUS);
const glVariable9 = gl.createProgram();
gl.attachShader(glVariable9, glVariable5);
gl.attachShader(glVariable9, glVariable6);
gl.linkProgram(glVariable9);
const glVariable10 = gl.createFramebuffer();
const glVariable11 = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, glVariable11);
gl.bufferData(gl.ARRAY_BUFFER, 64, gl.STATIC_DRAW);
const glVariable12 = new Float32Array([-1,-1,1,-1,-1,1,1,1]);
gl.bufferSubData(gl.ARRAY_BUFFER, 0, glVariable12);
const glVariable13 = new Float32Array([0,0,1,0,0,1,1,1]);
gl.bufferSubData(gl.ARRAY_BUFFER, 32, glVariable13);
const glVariable14 = gl.getAttribLocation(glVariable9, 'aPos');
gl.enableVertexAttribArray(glVariable14);
gl.vertexAttribPointer(glVariable14, 2, gl.FLOAT, false, 0, 0);
const glVariable15 = gl.getAttribLocation(glVariable9, 'aTexCoord');
gl.enableVertexAttribArray(glVariable15);
gl.vertexAttribPointer(glVariable15, 2, gl.FLOAT, false, 0, 32);
gl.bindFramebuffer(gl.FRAMEBUFFER, glVariable10);
gl.useProgram(glVariable9);
const glVariable16 = gl.createTexture();
gl.activeTexture(gl.TEXTURE0);
gl.bindTexture(gl.TEXTURE_2D, glVariable16);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.FLOAT, null);
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, glVariable16, 0);
/** start of injected functions **/
const renderOutput = function (e,t){const n=new Float32Array(t);let r=0;for(let i=0;i<t;i++)n[i]=e[r],r+=4;return n};
/** end of injected functions **/
const innerKernel = function (a, b) {
/** start setup uploads for kernel values **/
const uploadValue_a = a;

const uploadValue_b = b;

/** end setup uploads for kernel values **/
gl.useProgram(glVariable9);
gl.scissor(0, 0, 1, 1);
const glVariable17 = gl.getUniformLocation(glVariable9, 'ratio');
gl.uniform2f(glVariable17, 1, 1);
const glVariable18 = gl.getUniformLocation(glVariable9, 'user_a');
gl.uniform1f(glVariable18, uploadValue_a);
const glVariable19 = gl.getUniformLocation(glVariable9, 'user_b');
gl.uniform1f(glVariable19, uploadValue_b);
gl.bindFramebuffer(gl.FRAMEBUFFER, glVariable10);
gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
const glVariable20 = new Float32Array(4);
gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.FLOAT, glVariable20);

return renderOutput(glVariable20, 1);
};
return innerKernel;
}
const canvas = document.createElement('canvas');
const context = canvas.getContext('webgl');
const kernel = Kernel({ canvas, context });
return kernel(12345, 67890);
}
Insert cell
{
// const gpu = new GPU({ mode: 'webgl' });

// const concatNumbersGPU = gpu.createKernel(function (a, b) {
// return (a * Math.pow(10, Math.floor(Math.log(b) / Math.log(10)) + 1) + b);
// }, { output: [1] });

// return concatNumbersGPU.toString(12345, 67890); // => 1234567552
return '';
}
Insert cell
Insert cell

One platform to build and deploy the best data apps

Experiment and prototype by building visualizations in live JavaScript notebooks. Collaborate with your team and decide which concepts to build out.
Use Observable Framework to build data apps locally. Use data loaders to build in any language or library, including Python, SQL, and R.
Seamlessly deploy to Observable. Test before you ship, use automatic deploy-on-commit, and ensure your projects are always up-to-date.
Learn more