Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Determining the quadrant of a point

I need to determine the quadrant of point, in a faster way. I am only aware of "determine using the signs" method. I am looking for a good approach, if any. If not any fixes to my code would help. Assume there are 4 quads on the plane. My code-

        int x = scan.nextInt() > 0 ? 1 : 0;
        int y = scan.nextInt() > 0 ? 1 : 0;
        switch (x) {
        case 1:
            switch (y) {
            case 1:
                quad = 1;
                break;
            case 0:
                quad = 4;
                break;
            }
            break;

        case 0:
            switch (y) {
            case 1:
                quad = 2;
                break;
            case 0:
                quad = 3;
                break;
            }
            break;
        }
like image 406
sgowd Avatar asked Mar 15 '12 10:03

sgowd


2 Answers

Branching and memory look ups are the things to avoid when doing micro optimizations on a snippet of code. With inline assembly you could just use the CMOV (Conditional MOV) to get a speedup on x86 systems. Java's hotspot compiler can be coaxed into using this instruction as well. But since the snippet is so simple, doing too many operations to avoid the branching or memory look ups might (in the end) be defeatist.

static int[] QUAD_LUT = new int[]{1, 2, 4, 3};
...
// use the sign bit on the integers
return QUAD_LUT[ (x >>> 31) | ((y >>> 30) & 0x2) ]

When you think about the result you're after

x.sign y.sign Quad
0      0      1
0      1      4
1      0      2
1      1      3

You can get to the formula

(x.sign XOR y.sign + y.sign + y.sign) + 1

So in Java

y = (y>>>31);
return ((x>>>31) ^ y) + y + y + 1;

EDIT Just for people curious about inline assembly...

;; NASM/FASM syntax
;; GetQuadrant(int x, int y)
;; RETURN [1|2|3|4] in EAX register
GetQuadrant:
    MOV     eax, [esp+4] ;; = x
    MOV     ecx, [esp+8] ;; = y
    SHR     eax, 31 ;; = >> 31
    SHR     ecx, 31 ;; = >> 31 
    XOR     eax, ecx ;; = x XOR y
    LEA     eax, [eax + ecx * 2 + 1] ;; = x + y*2 + 1
    RET     8 ;; correct stack and return
like image 174
Louis Ricci Avatar answered Oct 05 '22 08:10

Louis Ricci


Here is the method for you. Looks simple...

getQuadrant(int x, int y) {
    if (x >= 0) {
        return y >= 0 ? 1 : 4;
    } else {
        return y >= 0 ? 2 : 3;
    }
}
like image 25
AlexR Avatar answered Oct 05 '22 10:10

AlexR