Wymyśliłem metodę, która wygląda na to, że działa. To trochę brzydkie.
Pierwszym krokiem jest porównanie górnych 32 bitów, ponieważ 2 komplementy bitu znaku MSB pozostają, więc liczby zachowują prawidłowe relacje
-1 —> -1
0 —> 0
9223372036854775807 = 0x7fff ffff ffff ffff -> 0x7ffff ffff = 2147483647
Tak więc zwracanie wyników z pracy MSB, chyba że są one równe, wtedy LSB musi zostać sprawdzone.
Mam kilka przypadków, aby ustalić pewne wzorce:
-1 = 0xffff ffff ffff ffff
-2 = 0xffff ffff ffff fffe
32 bit is:
-1 -> 0xffff ffff = -1
-2 -> 0xffff fffe = -2
-1 > -2 would be like -1 > -2 : GOOD
I
8589934591 = 0x0000 0001 ffff ffff
8589934590 = 0x0000 0001 ffff fffe
32 bit is:
8589934591 -> ffff ffff = -1
8589934590 -> ffff fffe = -2
8589934591 > 8589934590 would be -1 > -2 : GOOD
Bit znaku na MSB nie ma znaczenia b/c liczby ujemne mają między sobą taki sam związek jak liczby dodatnie. np. niezależnie od bitu znaku, wartości lsb 0xff
> 0xfe
, zawsze.
A co, jeśli MSB na niższych 32 bitach jest inny?
0xff7f ffff 7fff ffff = -36,028,799,166,447,617
0xff7f ffff ffff ffff = -36,028,797,018,963,969
32 bit is:
-..799.. -> 0x7fff ffff = 2147483647
-..797.. -> 0xffff ffff = -1
-..799.. < -..797.. would be 2147483647 < -1 : BAD!
Musimy więc zignorować bit znaku na niższych 32 bitach. A ponieważ relacje są takie same dla LSB niezależnie od znaku, po prostu użycie najniższych 32 bitów bez znaku działa we wszystkich przypadkach.
Oznacza to, że chcę mieć podpisane dla MSB i niepodpisane dla LSB - więc zmieniam I4
do i4
dla LSB. Również oficjalny big endian i użycie '>' w wywołaniach struct.unpack:
-- ...
local comp_int64s = function (as0, au1, bs0, bu1)
if as0 > bs0 then
return 1
elseif as0 < bs0 then
return -1
else
-- msb's equal comparing lsbs - these are unsigned
if au1 > bu1 then
return 1
elseif au1 < bu1 then
return -1
else
return 0
end
end
end
local l, as0, au1, bs0, bu1
as0, l = bit.tobit(struct.unpack(">i4", ARGV[1]))
au1, l = bit.tobit(struct.unpack(">I4", ARGV[1], 5))
bs0, l = bit.tobit(struct.unpack(">i4", blob))
bu1, l = bit.tobit(struct.unpack(">I4", blob, 5))
print("Cmp result", comp_int64s(as0, au1, bs0, bu1))