import java.util.*;

public class CircleOperations {

	static final double EPS = 1e-10;

	public static double fastHypot(double x, double y) {
		return Math.sqrt(x * x + y * y);
	}

	public static class Point {
		double x, y;

		public Point(double x, double y) {
			this.x = x;
			this.y = y;
		}
	}

	public static class Circle {
		double x, y, r;

		public Circle(double x, double y, double r) {
			this.x = x;
			this.y = y;
			this.r = r;
		}

		public boolean contains(Point p) {
			return fastHypot(p.x - x, p.y - y) < r + EPS;
		}
	}

	public static class Line {
		double a, b, c;

		public Line(double a, double b, double c) {
			this.a = a;
			this.b = b;
			this.c = c;
		}

		public Line(Point p1, Point p2) {
			a = +(p1.y - p2.y);
			b = -(p1.x - p2.x);
			c = p1.x * p2.y - p2.x * p1.y;
		}
	}

	// geometric solution
	public static Point[] circleLineIntersection(Circle circle, Line line) {
		double a = line.a;
		double b = line.b;
		double c = line.c + circle.x * a + circle.y * b;
		double r = circle.r;
		double aabb = a * a + b * b;
		double d = c * c / aabb - r * r;
		if (d > EPS)
			return new Point[0];
		double x0 = -a * c / aabb;
		double y0 = -b * c / aabb;
		if (d > -EPS)
			return new Point[]{new Point(x0 + circle.x, y0 + circle.y)};
		d /= -aabb;
		double k = Math.sqrt(d < 0 ? 0 : d);
		return new Point[]{
				new Point(x0 + k * b + circle.x, y0 - k * a + circle.y),
				new Point(x0 - k * b + circle.x, y0 + k * a + circle.y)};
	}

	// algebraic solution
	public static Point[] circleLineIntersection2(Circle circle, Line line) {
		return Math.abs(line.a) >= Math.abs(line.b)
				? intersection(line.a, line.b, line.c, circle.x, circle.y, circle.r, false)
				: intersection(line.b, line.a, line.c, circle.y, circle.x, circle.r, true);
	}

	static Point[] intersection(double a, double b, double c, double CX, double CY, double R, boolean swap) {
		// ax+by+c=0
		// (by+c+aCX)^2+(ay-aCY)^2=(aR)^2
		double A = a * a + b * b;
		double B = 2.0 * b * (c + a * CX) - 2.0 * a * a * CY;
		double C = (c + a * CX) * (c + a * CX) + a * a * (CY * CY - R * R);
		double d = B * B - 4 * A * C;
		if (d < -EPS)
			return new Point[0];
		d = Math.sqrt(d < 0 ? 0 : d);
		double y1 = (-B + d) / (2 * A);
		double x1 = (-c - b * y1) / a;
		double y2 = (-B - d) / (2 * A);
		double x2 = (-c - b * y2) / a;
		return swap ? d > EPS ? new Point[]{new Point(y1, x1), new Point(y2, x2)} : new Point[]{new Point(y1, x1)}
				: d > EPS ? new Point[]{new Point(x1, y1), new Point(x2, y2)} : new Point[]{new Point(x1, y1)};
	}

	public static Point[] circleCircleIntersection(Circle c1, Circle c2) {
		if (fastHypot(c1.x - c2.x, c1.y - c2.y) < EPS) {
			if (Math.abs(c1.r - c2.r) < EPS)
				return null; // infinity intersection points
			return new Point[0];
		}
		double dx = c2.x - c1.x;
		double dy = c2.y - c1.y;
		double A = -2 * dx;
		double B = -2 * dy;
		double C = dx * dx + dy * dy + c1.r * c1.r - c2.r * c2.r;
		Point[] res = circleLineIntersection(new Circle(0, 0, c1.r), new Line(A, B, C));
		for (Point point : res) {
			point.x += c1.x;
			point.y += c1.y;
		}
		return res;
	}

	public static double circleCircleIntersectionArea(Circle c1, Circle c2) {
		double r = Math.min(c1.r, c2.r);
		double R = Math.max(c1.r, c2.r);
		double d = fastHypot(c1.x - c2.x, c1.y - c2.y);
		if (d < R - r + EPS)
			return Math.PI * r * r;
		if (d > R + r - EPS)
			return 0;
		double area = r * r * Math.acos((d * d + r * r - R * R) / 2 / d / r) + R * R
				* Math.acos((d * d + R * R - r * r) / 2 / d / R) - 0.5
				* Math.sqrt((-d + r + R) * (d + r - R) * (d - r + R) * (d + r + R));
		return area;
	}

	public static Line[] tangents(Circle a, Circle b) {
		List<Line> lines = new ArrayList<>();
		for (int i = -1; i <= 1; i += 2)
			for (int j = -1; j <= 1; j += 2)
				tangents(new Point(b.x - a.x, b.y - a.y), a.r * i, b.r * j, lines);
		for (Line line : lines)
			line.c -= line.a * a.x + line.b * a.y;
		return lines.toArray(new Line[lines.size()]);
	}

	static void tangents(Point center2, double r1, double r2, List<Line> lines) {
		double r = r2 - r1;
		double z = center2.x * center2.x + center2.y * center2.y;
		double d = z - r * r;
		if (d < -EPS) return;
		d = Math.sqrt(d < 0 ? 0 : d);
		lines.add(new Line((center2.x * r + center2.y * d) / z, (center2.y * r - center2.x * d) / z, r1));
	}

	// min enclosing circle in O(n) on average
	public static Circle minEnclosingCircle(Point[] points) {
		if (points.length == 0)
			return new Circle(0, 0, 0);
		if (points.length == 1)
			return new Circle(points[0].x, points[0].y, 0);
		Collections.shuffle(Arrays.asList(points));
		Circle circle = getCircumCircle(points[0], points[1]);
		for (int i = 2; i < points.length; i++) {
			if (!circle.contains(points[i])) {
				circle = getCircumCircle(points[0], points[i]);
				for (int j = 1; j < i; j++) {
					if (!circle.contains(points[j])) {
						circle = getCircumCircle(points[j], points[i]);
						for (int k = 0; k < j; k++) {
							if (!circle.contains(points[k])) {
								circle = getCircumCircle(points[i], points[j], points[k]);
							}
						}
					}
				}
			}
		}
		return circle;
	}

	public static Circle getCircumCircle(Point a, Point b) {
		double x = (a.x + b.x) / 2.;
		double y = (a.y + b.y) / 2.;
		double r = fastHypot(a.x - x, a.y - y);
		return new Circle(x, y, r);
	}

	public static Circle getCircumCircle(Point a, Point b, Point c) {
		double Bx = b.x - a.x;
		double By = b.y - a.y;
		double Cx = c.x - a.x;
		double Cy = c.y - a.y;
		double d = 2 * (Bx * Cy - By * Cx);
		if (Math.abs(d) < EPS)
			return getCircumCircle(new Point(Math.min(a.x, Math.min(b.x, c.x)), Math.min(a.y, Math.min(b.y, c.y))),
					new Point(Math.max(a.x, Math.max(b.x, c.x)), Math.max(a.y, Math.max(b.y, c.y))));
		double z1 = Bx * Bx + By * By;
		double z2 = Cx * Cx + Cy * Cy;
		double cx = Cy * z1 - By * z2;
		double cy = Bx * z2 - Cx * z1;
		double x = cx / d;
		double y = cy / d;
		double r = fastHypot(x, y);
		return new Circle(x + a.x, y + a.y, r);
	}

	// Usage example
	public static void main(String[] args) {
		Random rnd = new Random(1);
		for (int step = 0; step < 100_000; step++) {
			int range = 10;
			int x = rnd.nextInt(range) - range / 2;
			int y = rnd.nextInt(range) - range / 2;
			int r = rnd.nextInt(range);

			int x1 = rnd.nextInt(range) - range / 2;
			int y1 = rnd.nextInt(range) - range / 2;
			int x2 = rnd.nextInt(range) - range / 2;
			int y2 = rnd.nextInt(range) - range / 2;
			if (x1 == x2 && y1 == y2)
				continue;

			Point[] p1 = circleLineIntersection(new Circle(x, y, r), new Line(new Point(x1, y1), new Point(x2, y2)));
			Point[] p2 = circleLineIntersection2(new Circle(x, y, r), new Line(new Point(x1, y1), new Point(x2, y2)));

			if (p1.length != p2.length || p1.length == 1 && !eq(p1[0], p2[0])
					|| p1.length == 2 && !(eq(p1[0], p2[0]) && eq(p1[1], p2[1]) || eq(p1[0], p2[1]) && eq(p1[1], p2[0])))
				throw new RuntimeException();
		}
	}

	static boolean eq(Point p1, Point p2) {
		return !(fastHypot(p1.x - p2.x, p1.y - p2.y) > 1e-9);
	}
}
