math/doubleToTwoFloats.tstypescript
/**
* Splits 64-bit values into two 32-bit floats, high and low, for the GPU. No dependencies, so the workers
* import it without the math classes.
* @module og/math/doubleToTwoFloats
*/
import type { NumberArray2 } from "./Vec2";
import type { NumberArray3 } from "./Vec3";
type XY = { x: number; y: number };
type XYZ = { x: number; y: number; z: number };
// The value rounded towards zero to a multiple of 65536, it is exact in 32 bits
function getHigh(value: number): number {
return Math.trunc(value / 65536.0) * 65536.0;
}
/**
* Separate 64 bit value to two 32-bit float values.
* @function
* @param {number} value - Double type value.
* @param {NumberArray2 | Float32Array} highLowArr - Reference output array.
* @returns {NumberArray2 | Float32Array} Encoded array. (exactly 2 entries)
*/
export function doubleToTwoFloats2(
value: number,
highLowArr: NumberArray2 | Float32Array
): NumberArray2 | Float32Array {
let h = getHigh(value);
highLowArr[0] = Math.fround(h);
highLowArr[1] = Math.fround(value - h);
return highLowArr;
}
/**
* Separate 64 bit value to two 32-bit float values.
* @function
* @param {number} value - Double type value.
* @param {Vec2} highLowVec - Reference out vector object.
* @returns {Vec2} Encoded array. (exactly 2 entries)
*/
export function doubleToTwoFloatsV2<T extends XY>(value: number, highLowVec: T): T {
let h = getHigh(value);
highLowVec.x = Math.fround(h);
highLowVec.y = Math.fround(value - h);
return highLowVec;
}
/**
* Splits a 64-bit 3d vector into two vectors with 32-bit float components.
* @function
* @param {XYZ} v - Double type value.
* @param {XYZ} high - Out vector high values.
* @param {XYZ} low - Out vector low values.
*/
export function doubleToTwoFloatsV3(v: XYZ, high: XYZ, low: XYZ) {
let x = v.x,
y = v.y,
z = v.z;
let h = getHigh(x);
high.x = Math.fround(h);
low.x = Math.fround(x - h);
h = getHigh(y);
high.y = Math.fround(h);
low.y = Math.fround(y - h);
h = getHigh(z);
high.z = Math.fround(h);
low.z = Math.fround(z - h);
}
/**
* Splits a 64-bit 3d vector into two arrays with 32-bit float components.
* @function
* @param {XYZ} v - Double type value.
* @param {Float32Array | NumberArray3} high - Out high values.
* @param {Float32Array | NumberArray3} low - Out low values.
*/
export function doubleToTwoFloat32Array(v: XYZ, high: Float32Array | NumberArray3, low: Float32Array | NumberArray3) {
let x = v.x,
y = v.y,
z = v.z;
let h = getHigh(x);
high[0] = Math.fround(h);
low[0] = Math.fround(x - h);
h = getHigh(y);
high[1] = Math.fround(h);
low[1] = Math.fround(y - h);
h = getHigh(z);
high[2] = Math.fround(h);
low[2] = Math.fround(z - h);
}