Tesseral arithmetic/quadtree

99封情书 提交于 2020-01-02 17:41:31

问题


I did a project a while back on path finding with quadtrees and I would like to improve on its performance. It seems that using tesseral arithmetic to determine node adjacency (as per this page, courtesy of the Geography department of the University of British Columbia) would be much faster than the brute force method I'm using at the moment (I'm checking for shared edges, which works fine for a static quadtree but would be too much overhead if the map were changing).

I more or less understand what's said in the Adjacency Algorithm section, but I'm not really sure how to begin. I'm primarily interested in C#, but it'd be awesome if there's already some source floating around for working with tesseral arithmetic that I could look at, regardless of language. Otherwise, could anyone give me some pointers on dealing with the addition/subtraction carries?


回答1:


I think, the easiest way to deal with tesseral arithmetic is to "bit-unzip" numbers, perform any number of arithmetical operations normally, and "bit-zip" them back when tesseral form is needed:

z = bit_zip(bit_unzip(x) + bit_unzip(y));

(This example works for unsigned only. For signed integers, unpack each number into two variables and do normal arithmetic on both parts separately).

You can find fast implementations for "bit-unzip" and "bit-zip" in "Matters Computational ", chapter 1.15 "Bit-wise zip".




回答2:


Well, I don't know of any way to do this efficiently, but the usual "add with bitwise operations" algorithm suggests the following algorithm (not tested):

static int tesseral_add(int x, int y)
{
    int a, b;
    do
    {
        a = x & y;
        b = x ^ y;
        x = a << 2; // move carry up 2 places instead of the usual 1
        y = b;
    } while (b != 0);
    return b;
}

Which possibly loops quite a lot, if there are carry chains.


Actually, there's a much better way to do this.

Observe that for z = interleave(a, -1); w = interleave(b, 0);, adding z and w directly gives a partially correct result, because any carries are re-carried (all the "in-between" bits are 1). The only "problem" is that it destroys the y-coordinates.

So to add two tesseral numbers z = interleave(a, b); w = interleave(c, d);, there is a nice short way to do it:

int xsum = (z | 0xAAAAAAAA) + (w & 0x55555555);
int ysum = (z | 0x55555555) + (w & 0xAAAAAAAA);
int result = (xsum & 0x55555555) | (ysum & 0xAAAAAAAA);


来源:https://stackoverflow.com/questions/9339395/tesseral-arithmetic-quadtree

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!