RunMat
GitHub

View all functions

CategoryMath: Trigonometry
GPUYes

atan2 — Quadrant-aware inverse tangent atan2(y, x) with MATLAB-compatible broadcasting.

theta = atan2(y, x) computes the four-quadrant inverse tangent of the point (x, y). It returns angles in radians covering the range (-pi, pi], giving robust results even when x is zero.

How does the atan2 function behave in MATLAB / RunMat?

  • Inputs can be scalars, vectors, matrices, or N-D tensors of real numeric, logical, or character data. MATLAB-style implicit expansion (broadcasting) applies when shapes are compatible.
  • atan2 treats y as the numerator and x as the denominator: atan2(Y, X) equals atan(Y ./ X) but keeps the correct quadrant and handles zero denominators.
  • Logical inputs are cast to double, character arrays use their Unicode code points, and integer inputs are promoted to double, mirroring MATLAB promotion rules.
  • Complex inputs are **not** supported; MATLAB raises an error and RunMat matches that behaviour.
  • atan2(0, 0) returns 0. atan2(±0, -0) follows IEEE-754 semantics, matching MATLAB for signed zeros and infinities.
  • atan2(NaN, x) or atan2(y, NaN) returns NaN; inputs containing Inf combinations follow IEEE-754 quadrant semantics exactly like MATLAB.
  • The output always has double precision and the same size as the broadcasted inputs.

GPU behavior

When both operands already reside on the GPU and the active provider implements the elem_atan2 hook, RunMat executes the operation entirely on the device without reformatting buffers.

If shapes require implicit expansion or the provider lacks elem_atan2, RunMat transparently gathers both tensors to the host, computes the result with the reference CPU implementation, and continues execution.

When GPU work completes in single precision (because the provider only exposes 32-bit buffers), RunMat promotes the results to double precision whenever the data is materialised on the host so the observable behaviour still matches MATLAB.

Fusion-aware expressions (for example, sin(atan2(y, x))) can still emit a combined WGSL kernel; the fusion planner recognises atan2 as a binary elementwise primitive.

GPU residency

RunMat's planner keeps tensors on the GPU whenever profitable. Explicit gpuArray calls are optional—use them only when you need to control residency for interoperability. When elem_atan2 is unavailable, RunMat automatically gathers data to the CPU, performs the computation, and re-uploads results only when downstream consumers demand GPU residency.

Examples of using atan2 in MATLAB / RunMat

Computing the polar angle of a point

theta = atan2(4, 3)

Expected output:

theta = 0.9273

Determining quadrants for a vector of coordinates

Y = [-1 0 1];
X = [-1 -1 -1];
angles = atan2(Y, X)

Expected output:

angles = [-2.3562 3.1416 2.3562]

Broadcasting a scalar denominator across a matrix

A = [1 2 3; 4 5 6];
angles = atan2(A, 2)

Expected output:

angles =
    0.4636    0.7854    0.9828
    1.1071    1.1903    1.2490

Handling zero numerators and signed zeros

theta = atan2([0 -0], [-2 0])

Expected output:

theta = [pi 0]

Executing atan2 on the GPU

Gy = gpuArray([1 1; -1 -1]);
Gx = gpuArray([1 -1; 1 -1]);
angles_gpu = atan2(Gy, Gx);
angles = gather(angles_gpu)

Expected output:

angles =
    0.7854    2.3562
   -0.7854   -2.3562

Converting character data to angles

theta = atan2('A', 100)

Expected output:

theta = 0.5764

FAQ

What is the range of values returned by atan2?

Angles are given in radians and span the open/closed interval (-pi, pi]. Use rad2deg if you prefer degrees.

Can I supply complex inputs?

No. MATLAB raises an error for complex inputs, and so does RunMat. Convert complex data to magnitude/phase first if needed.

Does atan2 preserve the shape of the inputs?

Yes. After implicit expansion, the output shape matches the broadcasted size of Y and X.

How are logical or character inputs handled?

Logical values map to 0 and 1, and character arrays use their Unicode code point values (as doubles) before computing the angle.

What happens when x is zero?

atan2 still returns a finite result using the sign of y. For example, atan2(1, 0) returns pi/2, and atan2(-1, 0) returns -pi/2.

Are GPU and CPU results identical?

Double-precision providers match CPU results exactly. Single-precision providers can differ by routine IEEE rounding. RunMat automatically promotes to double when materialising host tensors to mirror MATLAB.

How can I compute angles in degrees?

Call rad2deg(atan2(y, x)) or multiply the result by 180/pi.

See also

atan, hypot, sin, tan, gpuArray, gather

Source & Feedback