Es ist möglich, Vektormathematik mit zwei Zahlen in einer zu machen. Lassen Sie mich zunächst ein Beispiel zeigen, bevor ich erkläre, wie es funktioniert:
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");
Ich benutze die Tatsache, dass Sie das gleiche Ergebnis erhalten, wenn Sie zwei Zahlen X-mal verschieben und sie dann addieren oder subtrahieren, bevor Sie sie zurückschieben, als hätten Sie sie zunächst nicht verschoben. In ähnlicher Weise funktioniert die skalare Multiplikation und Division für verschobene Werte symmetrisch.
Eine JavaScript-Zahl hat eine Ganzzahlgenauigkeit von 52 Bit (64-Bit-Gleitkommazahlen), daher packe ich eine Zahl in die höheren verfügbaren 26 Bits und eine in die niedrigeren. Der Code ist etwas chaotischer, weil ich signierte Nummern unterstützen wollte.
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;
}
}
Der einzige Nachteil, den ich dabei sehen kann, ist, dass x und y im Bereich von + -33 Millionen liegen müssen, da sie jeweils in 26 Bit passen müssen.