Es posible hacer matemáticas vectoriales con dos números empaquetados en uno. Permítanme mostrarles un ejemplo antes de explicar cómo funciona:
let a = vec_pack([2,4]);
let b = vec_pack([1,2]);
let c = a+b; // Vector addition
let d = c-b; // Vector subtraction
let e = d*2; // Scalar multiplication
let f = e/2; // Scalar division
console.log(vec_unpack(c)); // [3, 6]
console.log(vec_unpack(d)); // [2, 4]
console.log(vec_unpack(e)); // [4, 8]
console.log(vec_unpack(f)); // [2, 4]
if(a === f) console.log("Equality works");
if(a > b) console.log("Y value takes priority");
Estoy usando el hecho de que si cambias dos números X veces y luego los sumas o restas antes de cambiarlos, obtendrás el mismo resultado que si no los hubieras cambiado al principio. De manera similar, la multiplicación y división escalar funciona simétricamente para valores desplazados.
Un número de JavaScript tiene 52 bits de precisión entera (flotantes de 64 bits), por lo que empaquetaré un número en los 26 bits disponibles más altos y uno en los más bajos. El código se complica un poco más porque quería admitir números firmados.
function vec_pack(vec){
return vec[1] * 67108864 + (vec[0] < 0 ? 33554432 | vec[0] : vec[0]);
}
function vec_unpack(number){
switch(((number & 33554432) !== 0) * 1 + (number < 0) * 2){
case(0):
return [(number % 33554432),Math.trunc(number / 67108864)];
break;
case(1):
return [(number % 33554432)-33554432,Math.trunc(number / 67108864)+1];
break;
case(2):
return [(((number+33554432) % 33554432) + 33554432) % 33554432,Math.round(number / 67108864)];
break;
case(3):
return [(number % 33554432),Math.trunc(number / 67108864)];
break;
}
}
El único inconveniente que puedo ver con esto es que xey deben estar en el rango + -33 millones, ya que deben caber dentro de 26 bits cada uno.