* Returns a low part of a float value that can be encoded to Float32 without recision loss
* @param {number} float Number in float64 precision
* @return {number} Low part of the float value
*/
export function getLowPart(float) {
return float - getHighPart(float);
}
* Returns a high part of a float value that can be encoded to Float32 without precision loss
* @param {number} float Number in float64 precision
* @return {number} High part of the float value
*/
export function getHighPart(float) {
return Math.fround(float);
}
* These arithmetic functions are mostly inspired the ones in luma.gl: https://github.com/visgl/luma.gl/blob/master/modules/shadertools/src/modules/math/fp64/fp64-arithmetic-glsl.ts
* and https://blog.cyclemap.link/2011-06-09-glsl-part2-emu/
* Note that we use the `u_one` uniform here to ensure that the compiler doesn't simplify the calculations; otherwise these will have no effect at all
* @type {string}
*/
export const FLOAT64_ARITHMETIC_FN = `
vec2 df_from(float value) {
return vec2(value, 0.);
}
float df_float(vec2 df) {
return df.x;
}
vec2 df_add(vec2 dfa, vec2 dfb) {
vec2 dfc;
float t1, t2, e;
t1 = dfa.x * u_one + dfb.x * u_one;
e = t1 * u_one - dfa.x * u_one;
t2 = ((dfb.x - e) + (dfa.x - (t1 - e))) * u_one + dfa.y + dfb.y * u_one;
dfc.x = t1 * u_one + t2 * u_one;
dfc.y = t2 - (dfc.x - t1) * u_one;
return dfc;
}
vec2 df_sub(vec2 dfa, vec2 dfb) {
vec2 dfc;
float e, t1, t2;
t1 = dfa.x - dfb.x;
e = t1 - dfa.x;
t2 = ((-dfb.x - e) + (dfa.x - (t1 - e))) + dfa.y - dfb.y;
dfc.x = t1 + t2;
dfc.y = t2 - (dfc.x - t1);
return dfc;
}
vec2 df_mul(vec2 dfa, vec2 dfb) {
vec2 dfc;
float c11, c21, c2, e, t1, t2;
float a1, a2, b1, b2, cona, conb, split = 4097.;
cona = dfa.x * split * u_one;
conb = dfb.x * split * u_one;
a1 = cona * u_one - (cona - dfa.x);
b1 = conb * u_one - (conb - dfb.x);
a2 = dfa.x * u_one - a1;
b2 = dfb.x * u_one - b1 * u_one;
c11 = dfa.x * u_one * dfb.x * u_one;
c21 = a2 * b2 * u_one + (a2 * b1 + (a1 * b2 + (a1 * b1 - c11))) * u_one;
c2 = dfa.x * dfb.y * u_one + dfa.y * dfb.x * u_one;
t1 = c11 + c2 * u_one;
e = t1 - c11 * u_one;
t2 = dfa.y * dfb.y * u_one + ((c2 - e) + (c11 - (t1 - e))) + c21 * u_one;
dfc.x = t1 * u_one + t2 * u_one;
dfc.y = t2 - (dfc.x - t1) * u_one;
return dfc;
}
vec2 df_div(vec2 dfa, vec2 dfb) {
vec2 dfc;
float c11, c21, c2, e, t1, t2, t11, t12, t21, t22;
float a1, a2, b1, b2, cona, conb, split = 4097.;
float s1, s2;
s1 = dfa.x / dfb.x * u_one;
cona = s1 * split * u_one;
conb = dfb.x * split * u_one;
a1 = cona - (cona - s1) * u_one;
b1 = conb - (conb - dfb.x) * u_one;
a2 = s1 - a1 * u_one;
b2 = dfb.x - b1 * u_one;
c11 = s1 * dfb.x * u_one;
c21 = (((a1 * b1 - c11) + a1 * b2) + a2 * b1) + a2 * b2 * u_one;
c2 = s1 * dfb.y * u_one;
t1 = c11 + c2 * u_one;
e = t1 - c11 * u_one;
t2 = ((c2 - e) + (c11 - (t1 - e))) + c21 * u_one;
t12 = t1 + t2 * u_one;
t22 = t2 - (t12 - t1) * u_one;
t11 = dfa.x - t12 * u_one;
e = t11 - dfa.x * u_one;
t21 = ((-t12 - e) + (dfa.x - (t11 - e))) + dfa.y - t22 * u_one;
s2 = (t11 + t21) / dfb.x * u_one;
dfc.x = s1 + s2 * u_one;
dfc.y = s2 - (dfc.x - s1) * u_one;
return dfc;
}
float df_mod(vec2 df, vec2 m) {
vec2 q = df_div(df, m) * u_one;
float qf = floor(q.x);
float frac = q.x - qf + q.y * u_one;
if (frac < 0.0) qf -= 1.0;
if (frac >= 1.0) qf += 1.0;
vec2 prod = df_mul(df_from(qf), m);
vec2 rem = df_add(df_from(df.x), df_from(-prod.x)) * u_one;
rem.y += df.y - prod.y;
return rem.x + rem.y * u_one;
}
`;