atan2 in k

While q/k offers all the stan­dard trigono­met­ric func­tions, it does not include atan2. A recent project (cal­cu­lat­ing head­ings between air­ports) required atan2; there­fore I needed to imple­ment it.

Wikipedia was my guide and my first attempt was a pretty straight-for­ward imple­men­ta­tion in k:

atan2:{[y;x]
    p: $[y>0;pi;y<0;0-pi;0N];
    $[
        x>0; atan[y%x];
        x<0; atan[y%x]+p;
        x=0; p%2;
        0N;
    ]
}

This works but the excite­ment faded when I real­ized $[] only works with scalars.

Re-exam­in­ing the atan2 rules, we can cre­ate this chart:

  x > 0 x < 0 x = 0
y > 0 atan[y%x] atan[y%x] + pi +pi%2
y < 0 atan[y%x] atan[y%x] - pi -pi%2
y = 0 atan[y%x] atan[y%x] + pi undefined

The most dif­fi­cult case is x = 0. For­tu­nately, k’s atan gives the cor­rect result for +in­fin­ity, -infin­ity, and null, so it can ignore x = 0 and y = 0

  x >= 0 x < 0
y >= 0 atan[y%x] atan[y%x] + pi
y < 0 atan[y%x] atan[y%x] - pi

Our only con­cern is adding (or sub­stract­ing) pi when x < 0:

atan2:{[y;x]
    fudge: pi * (x<0) * (2*y>=0)-1;
    
    fudge + atan[y%x]
}