Il est possible de faire des mathématiques vectorielles avec deux nombres regroupés en un seul. Permettez-moi d'abord de montrer un exemple avant d'expliquer comment cela fonctionne:
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");
J'utilise le fait que si vous décalez un peu deux nombres X fois, puis ajoutez ou soustrayez-les avant de les recaler, vous obtiendrez le même résultat que si vous ne les aviez pas décalés au départ. De même, la multiplication et la division scalaires fonctionnent symétriquement pour les valeurs décalées.
Un nombre JavaScript a 52 bits de précision entière (flottants de 64 bits), donc je vais emballer un nombre dans les 26 bits disponibles les plus élevés, et un dans le plus bas. Le code est un peu plus compliqué car je voulais prendre en charge les nombres signés.
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;
}
}
Le seul inconvénient que je peux voir avec cela est que le x et le y doivent être compris entre + -33 millions, car ils doivent tenir dans 26 bits chacun.