2021年3月30日星期二

Is there an easy function from a pair of 32-bit ints to a single 64-bit int that preserves rotational order?

This is a question that came up in the context of sorting points with integer coordinates into clockwise order, but this question is not about how to do that sorting.

This question is about the observation that 2-d vectors have a natural cyclic ordering. Unsigned integers with usual overflow behavior (or signed integers using twos-complement) also have a natural cyclic ordering. Can you easily map from the first ordering to the second?

So, the exact question is whether there is a map from pairs of twos-complement signed 32-bit integers to unsigned (or twos-complement signed) 64-bit integers such that any list of vectors that is in clockwise order maps to integers that are in decreasing (modulo overflow) order?

Some technical cases that people will likely ask about:

  • Yes, vectors that are multiples of each other should map to the same thing
  • No, I don't care which vector (if any) maps to 0
  • No, the images of antipodal vectors don't have to differ by 2^63 (although that is a nice-to-have)

The obvious answer is that since there are only around 0.6*2^64 distinct slopes, the answer is yes, such a map exists, but I'm looking for one that is easily computable. I understand that "easily" is subjective, but I'm really looking for something reasonably efficient and not terrible to implement. So, in particular, no counting every lattice point between the ray and the positive x-axis (unless you know a clever way to do that without enumerating them all).

An important thing to note is that it can be done by mapping to 65-bit integers. Simply project the vector out to where it hits the box bounded by x,y=+/-2^62 and round toward negative infinity. You need 63 bits to represent that integer and two more to encode which side of the box you hit. The implementation needs a little care to make sure you don't overflow, but only has one branch and two divides and is otherwise quite cheap. It doesn't work if you project out to 2^61 because you don't get enough resolution to separate some slopes.

Also, before you suggest "just use atan2", compute atan2(1073741821,2147483643) and atan2(1073741820,2147483642)

https://stackoverflow.com/questions/66880696/is-there-an-easy-function-from-a-pair-of-32-bit-ints-to-a-single-64-bit-int-that March 31, 2021 at 10:06AM

没有评论:

发表评论