"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.bround = exports.btof = exports.ftob = exports.spherePoint = exports.spherePointTrig = exports.cryptoInt32 = exports.djb2 = exports.lqrandomSync = exports.lqrandom = exports.lqrandomSeed = exports.setSeed = exports.xorshift32 = exports.xorshift = exports.u32toF = exports.copySeed = exports.lqrandomsync = exports.lqrandomstore = exports.generateSeed = exports.quatFromRadians = exports.surfaceNormal = exports.dot = exports.preciseAngle = exports.computeRadians = exports.computeAngle = exports.angleY = exports.angleX = exports.radian = exports.rad = exports.degree = exports.addClamp = exports.addWrap = void 0;
const crypto = require("crypto");
const gl_matrix_1 = require("gl-matrix");
const addWrap = (a, b) => a + b > 1 ? a + b - 1 : a + b < 0 ? a + b + 1 : a + b;
exports.addWrap = addWrap;
const addClamp = (a, b) => a + b > 1 ? 1 : a + b < 0 ? 0 : a + b;
exports.addClamp = addClamp;
const pi = Math.PI;
exports.degree = pi / 180;
exports.rad = 180 / pi;
const radian = (n) => n * exports.rad;
exports.radian = radian;
const angleX = (n) => Math.cos(n * exports.degree);
exports.angleX = angleX;
const angleY = (n) => Math.sin(n * exports.degree);
exports.angleY = angleY;
const computeAngle = (dx, dy) => (pi + Math.atan2(dy, dx)) * exports.rad;
exports.computeAngle = computeAngle;
const computeRadians = (dx, dy) => pi + Math.atan2(dy, dx);
exports.computeRadians = computeRadians;
const container = [0, 0, 0];
const preciseAngle = (dx, dy) => {
    const radians = pi + Math.atan2(dy, dx);
    container[0] = Math.cos(radians);
    container[1] = Math.sin(radians);
    container[2] = radians;
    return container;
};
exports.preciseAngle = preciseAngle;
const dot = (a1, a2, b1, b2) => a1 * b1 + a2 * b2;
exports.dot = dot;
const snV1 = gl_matrix_1.vec3.create();
const snV2 = gl_matrix_1.vec3.create();
const surfaceNormal = (out, a, b, c) => {
    const u = gl_matrix_1.vec3.subtract(snV1, b, a);
    const v = gl_matrix_1.vec3.subtract(snV2, c, a);
    out[0] = u[1] * v[2] - u[2] * v[1];
    out[1] = u[2] * v[0] - u[0] * v[2];
    out[2] = u[0] * v[1] - u[1] * v[0];
    return out;
};
exports.surfaceNormal = surfaceNormal;
const quatFromRadians = (p, y, r) => {
    const q = gl_matrix_1.quat.create();
    gl_matrix_1.quat.rotateX(q, q, p * pi);
    gl_matrix_1.quat.rotateY(q, q, y * pi);
    gl_matrix_1.quat.rotateZ(q, q, r * pi);
    return q;
};
exports.quatFromRadians = quatFromRadians;
const generateSeed = (out = null, rand = () => exports.xorshift(exports.lqrandomsync)) => {
    if (out === null) {
        out = new Uint32Array(4);
    }
    for (let i = 0; i < 128; i++) {
        const row = (i / 32) >>> 0;
        const col = i % 32 >>> 0;
        out[row] = (out[row] | ((rand() < 0.5 ? 1 : 0) << col)) >>> 0;
    }
    return out;
};
exports.generateSeed = generateSeed;
exports.lqrandomstore = new Uint32Array(4);
exports.lqrandomsync = new Uint32Array(4);
exports.generateSeed(exports.lqrandomstore, Math.random);
exports.generateSeed(exports.lqrandomsync, Math.random);
const lqrandomseed = new Uint32Array(4);
const copySeed = (out, seed) => {
    out[0] = seed[0];
    out[1] = seed[1];
    out[2] = seed[2];
    out[3] = seed[3];
};
exports.copySeed = copySeed;
const dv = new DataView(new ArrayBuffer(4));
const u32toF = (n) => {
    dv.setUint32(0, (n >>> 9) | 0x3f800000);
    return dv.getFloat32(0) - 1;
};
exports.u32toF = u32toF;
const xorshift = (state) => {
    let t = state[3] >>> 0;
    t = (t ^ (t << 11)) >>> 0;
    t = (t ^ (t >>> 8)) >>> 0;
    state[3] = state[2] >>> 0;
    state[2] = state[1] >>> 0;
    state[1] = state[0] >>> 0;
    t = (t ^ state[0]) >>> 0;
    t = (t ^ (state[0] >>> 19)) >>> 0;
    state[0] = t >>> 0;
    return t >>> 0;
};
exports.xorshift = xorshift;
const xorshift32 = (seed, rounds = 1) => {
    for (let i = 0; i < rounds; i++) {
        seed = (seed ^ (seed << 13)) >>> 0;
        seed = (seed ^ (seed >> 17)) >>> 0;
        seed = (seed ^ (seed << 5)) >>> 0;
    }
    return seed >>> 0;
};
exports.xorshift32 = xorshift32;
const setSeed = (seed) => exports.copySeed(lqrandomseed, seed);
exports.setSeed = setSeed;
const lqrandomSeed = () => exports.xorshift(lqrandomseed) / 0xffffffff;
exports.lqrandomSeed = lqrandomSeed;
const lqrandom = () => exports.xorshift(exports.lqrandomstore) / 0xffffffff;
exports.lqrandom = lqrandom;
const lqrandomSync = () => exports.xorshift(exports.lqrandomsync) / 0xffffffff;
exports.lqrandomSync = lqrandomSync;
const djb2 = (str) => {
    let hash = 5381 >>> 0;
    for (let i = 0; i < str.length; i++) {
        const c = str.charCodeAt(i) & (0xff >>> 0);
        hash = ((hash << 5) + hash + c) >>> 0;
    }
    return hash;
};
exports.djb2 = djb2;
const poolByteLength = 32 * 4;
let cryptoStorage = crypto.randomBytes(poolByteLength);
let cryptoCursor = 0;
const cryptoInt32 = () => {
    let val = 0;
    if (cryptoCursor + 4 > poolByteLength) {
        cryptoStorage = crypto.randomBytes(poolByteLength);
        cryptoCursor = 0;
    }
    val = cryptoStorage.readInt32LE(cryptoCursor);
    cryptoCursor = cryptoCursor + 4;
    return val;
};
exports.cryptoInt32 = cryptoInt32;
const spherePointTrig = (out) => {
    const v = exports.lqrandom();
    const u = exports.lqrandom();
    const theta = u * 2.0 * Math.PI;
    const phi = Math.acos(2.0 * v - 1.0);
    const r = Math.cbrt(exports.lqrandom());
    const sinTheta = Math.sin(theta);
    const cosTheta = Math.cos(theta);
    const sinPhi = Math.sin(phi);
    const cosPhi = Math.cos(phi);
    out[0] = r * sinPhi * cosTheta;
    out[1] = r * sinPhi * sinTheta;
    out[2] = r * cosPhi;
};
exports.spherePointTrig = spherePointTrig;
const spherePoint = (out) => {
    do {
        out[0] = exports.lqrandom() * 2.0 - 1.0;
        out[1] = exports.lqrandom() * 2.0 - 1.0;
        out[2] = exports.lqrandom() * 2.0 - 1.0;
    } while (out[0] ** 2 + out[1] ** 2 + out[2] ** 2 > 1);
    return out;
};
exports.spherePoint = spherePoint;
const ftob = (n) => n * 127.0 | 0;
exports.ftob = ftob;
const btof = (n) => n / 127.0;
exports.btof = btof;
const bround = (n) => exports.btof(exports.ftob(n));
exports.bround = bround;
//# sourceMappingURL=math.js.map