Fastest way to sort vectors by angle without actually computing that angle

后端 未结 7 1354
长情又很酷
长情又很酷 2020-12-09 04:19

Many algorithms (e.g. Graham scan) require points or vectors to be sorted by their angle (perhaps as seen from some other point, i.e. using difference vectors). This order i

7条回答
  •  忘掉有多难
    2020-12-09 04:45

    If you can feed the original vectors instead of angles into a comparison function when sorting, you can make it work with:

    • Just a single branch.
    • Only floating point comparisons and multiplications.

    Avoiding addition and subtraction makes it numerically much more robust. A double can actually always exactly represent the product of two floats, but not necessarily their sum. This means for single precision input you can guarantee a perfect flawless result with little effort.

    This is basically Cimbali's solution repeated for both vectors, with branches eliminated and divisions multiplied away. It returns an integer, with sign matching the comparison result (positive, negative or zero):

    signed int compare(double x1, double y1, double x2, double y2) {
        unsigned int d1 = x1 > y1;
        unsigned int d2 = x2 > y2;
        unsigned int a1 = x1 > -y1;
        unsigned int a2 = x2 > -y2;
    
        // Quotients of both angles.
        unsigned int qa = d1 * 2 + a1;
        unsigned int qb = d2 * 2 + a2;
    
        if(qa != qb) return((0x6c >> qa * 2 & 6) - (0x6c >> qb * 2 & 6));
    
        d1 ^= a1;
    
        double p = x1 * y2;
        double q = x2 * y1;
    
        // Numerator of each remainder, multiplied by denominator of the other.
        double na = q * (1 - d1) - p * d1;
        double nb = p * (1 - d1) - q * d1;
    
        // Return signum(na - nb)
        return((na > nb) - (na < nb));
    }
    

提交回复
热议问题