atan2 function

double atan2(
  1. double y,
  2. double x
)

Two arguments arctangent function

y ordinate. x abscissa. Returns phase angle of point (x,y) between -PI and PI.

Implementation

double atan2(double y, double x) {
  if (x != x || y != y) {
    return double.nan;
  }

  if (y == 0) {
    final result = x * y;
    final invx = 1.0 / x;
    final invy = 1.0 / y;

    if (invx == 0) {
      // X is infinite
      if (x > 0) {
        return y; // return +/- 0.0
      } else {
        return copySign(math.pi, y);
      }
    }

    if (x < 0 || invx < 0) {
      if (y < 0 || invy < 0) {
        return -math.pi;
      } else {
        return math.pi;
      }
    } else {
      return result;
    }
  }

  // y cannot now be zero

  if (y == double.infinity) {
    if (x == double.infinity) {
      return math.pi * _f1_4;
    }

    if (x == double.negativeInfinity) {
      return math.pi * _f3_4;
    }

    return math.pi * _f1_2;
  }

  if (y == double.negativeInfinity) {
    if (x == double.infinity) {
      return -math.pi * _f1_4;
    }

    if (x == double.negativeInfinity) {
      return -math.pi * _f3_4;
    }

    return -math.pi * _f1_2;
  }

  if (x == double.infinity) {
    if (y > 0 || 1 / y > 0) {
      return 0.0;
    }

    if (y < 0 || 1 / y < 0) {
      return -0.0;
    }
  }

  if (x == double.negativeInfinity) {
    if (y > 0.0 || 1 / y > 0.0) {
      return math.pi;
    }

    if (y < 0 || 1 / y < 0) {
      return -math.pi;
    }
  }

  // Neither y nor x can be infinite or NAN here

  if (x == 0) {
    if (y > 0 || 1 / y > 0) {
      return math.pi * _f1_2;
    }

    if (y < 0 || 1 / y < 0) {
      return -math.pi * _f1_2;
    }
  }

  // Compute ratio r = y/x
  final r = y / x;
  if (r.isInfinite) {
    // bypass calculations that can create NaN
    return atan(r, 0.0, x < 0);
  }

  var ra = r; // TODO(rwl): doubleHighPart(r);
  var rb = r - ra;

  // Split x
  final xa = x; // TODO(rwl): doubleHighPart(x);
  final xb = x - xa;

  rb += (y - ra * xa - ra * xb - rb * xa - rb * xb) / x;

  final temp = ra + rb;
  rb = -(temp - ra - rb);
  ra = temp;

  if (ra == 0) {
    // Fix up the sign so atan works correctly
    ra = copySign(0.0, y);
  }

  // Call atan
  return atan(ra, rb, x < 0);
}