Problem: You are given two rectangles on a plane. The centers of both rectangles are located in the origin of coordinates (meaning the center of the rectangle's symmetry). The first rectangle's sides are parallel to the coordinate axes: the length of the side that is parallel to the Ox axis, equals w, the length of the side that is parallel to the Oy axis, equals h. The second rectangle can be obtained by rotating the first rectangle relative to the origin of coordinates by angle α.

<image>

Your task is to find the area of the region which belongs to both given rectangles. This region is shaded in the picture.

Input

The first line contains three integers w, h, α (1 ≤ w, h ≤ 106; 0 ≤ α ≤ 180). Angle α is given in degrees.

Output

In a single line print a real number — the area of the region which belongs to both given rectangles.

The answer will be considered correct if its relative or absolute error doesn't exceed 10 - 6.

Examples

Input

1 1 45


Output

0.828427125


Input

6 4 30


Output

19.668384925

Note

The second sample has been drawn on the picture above.

Solution (in JAVA):

Solution:
import static java.lang.Math.*;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Locale;
import java.util.StringTokenizer;
public class Main {
	public static void main(String[] args) throws IOException {
		new Thread(null, new Runnable() {
			public void run() {
				try {
					long prevTime = System.currentTimeMillis();
					new Main().run();
					System.err.println("Total time: "
							+ (System.currentTimeMillis() - prevTime) + " ms");
					System.err.println("Memory status: " + memoryStatus());
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}, "1", 1L << 24).start();
	}

	void run() throws IOException {
		in = new BufferedReader(new InputStreamReader(System.in));
		out = new PrintWriter(System.out);
		Object o = solve();
		if (o != null)
			out.println(o);
		out.close();
		in.close();
	}

	private Object solve() throws IOException {
		double w = nd();
		double h = nd();
		int a = ni();
		
		if(a == 0 || a == 180)
			return w * h;
		if( a==90 )
			return Math.min(w, h) * Math.min(w, h);
		
		List<Point> list = new ArrayList<>();
		list.add(new Point(-w/2.0, -h/2.0));
		list.add(new Point(-w/2.0, h/2.0));
		list.add(new Point(w/2.0, h/2.0));
		list.add(new Point(w/2.0, -h/2.0));
		
		List<Point> rots = new ArrayList<>();
		for(Point p : list)
			rots.add(p.rot(Math.PI * ((double) a) / 180.0));
		List<Point> check = new ArrayList<>();
		for(int i =0;i<4;i++){
			Point p1 = list.get(i);
			Point p2 = list.get((i+1)%4);
			
			for(int j =0;j<4;j++){
				Point q1 = rots.get(j);
				Point q2 = rots.get((j+1)%4);
				if(crsSS(p1,p2,q1,q2)){
					check.add(isLL(p1, p2, q1, q2));
				}
			}
		}
		return area(convexHull(check.toArray(new Point[0])));
	}
	
	private double area(Point... ps) {
		int n = ps.length;
		double ret = 0.0;
		for(int i =0;i<n;i++){
			int j = (i + 1)%n;
			ret += ps[i].x * ps[j].y - ps[i].y * ps[j].x;
		}
		return Math.abs(ret/2.0);
	}
	
	double EPS = 1e-9;
	
	Point[] convexHull(Point[] ps) { 
		int n = ps.length, k = 0;
		if (n <= 1) return ps;
		Arrays.sort(ps); 
		Point[] qs = new Point[n * 2];
		for (int i = 0; i < n; qs[k++] = ps[i++]) { 
			while (k > 1 && qs[k - 1].sub(qs[k - 2]).det(ps[i].sub(qs[k - 1])) < EPS) k--;
		}
		for (int i = n - 2, t = k; i >= 0; qs[k++] = ps[i--]) { 
			while (k > t && qs[k - 1].sub(qs[k - 2]).det(ps[i].sub(qs[k - 1])) < EPS) k--;
		 }
		Point[] res = new Point[k - 1];
		System.arraycopy(qs, 0, res, 0, k - 1);
		return res;
	}

	boolean crsSS(Point p1, Point p2, Point q1, Point q2) {
		if (max(p1.x, p2.x) + EPS < min(q1.x, q2.x))
			return false;
		if (max(q1.x, q2.x) + EPS < min(p1.x, p2.x))
			return false;
		if (max(p1.y, p2.y) + EPS < min(q1.y, q2.y))
			return false;
		if (max(q1.y, q2.y) + EPS < min(p1.y, p2.y))
			return false;
		return sig(p2.sub(p1).det(q1.sub(p1)))
				* sig(p2.sub(p1).det(q2.sub(p1))) < EPS;
	}
	
	Point isLL(Point p1, Point p2, Point q1, Point q2) {
		double d = q2.sub(q1).det(p2.sub(p1));
		if (abs(d) < EPS)
			return null;
		return p1.add(p2.sub(p1).mul(q2.sub(q1).det(q1.sub(p1)) / d));
	}

	private int sig(double a) {
		if( a < EPS)
			return -1;
		if( a > EPS)
			return 1;
		return 0;
	}

	class Point implements Comparable<Point>{
		double x;
		double y;

		Point(double x, double y) {
			this.x = x;
			this.y = y;
		}
		
		Point add(Point o) {
			return new Point(x+o.x,y + o.y);
		}

		Point mul(double d) {
			return new Point(x * d, y * d);
		}
		
		double det(Point o) {
			return x * o.y - o.x * y;
		}
		
		Point sub(Point o) {
			return new Point(x - o.x, y - o.y);
		}

		Point rot(double a) {
			return new Point(Math.cos(a) * x - Math.sin(a) * y, Math.sin(a) * x + Math.cos(a) * y);
		}
		@Override
		public int compareTo(Point o) {
			if(Math.abs(x - o.x) > EPS)
				return Double.compare(x, o.x);
			if(Math.abs(y - o.y) > EPS)
				return Double.compare(y, o.y);
			return 0;
		}
		
		@Override
		public String toString() {
			return "Point [x=" + x + ", y=" + y + "]";
		}
	}

	BufferedReader in;
	PrintWriter out;
	StringTokenizer strTok = new StringTokenizer("");

	String nextToken() throws IOException {
		while (!strTok.hasMoreTokens())
			strTok = new StringTokenizer(in.readLine());
		return strTok.nextToken();
	}

	int ni() throws IOException {
		return Integer.parseInt(nextToken());
	}

	long nl() throws IOException {
		return Long.parseLong(nextToken());
	}

	double nd() throws IOException {
		return Double.parseDouble(nextToken());
	}

	int[] nia(int size) throws IOException {
		int[] ret = new int[size];
		for (int i = 0; i < size; i++)
			ret[i] = ni();
		return ret;
	}

	long[] nla(int size) throws IOException {
		long[] ret = new long[size];
		for (int i = 0; i < size; i++)
			ret[i] = nl();
		return ret;
	}

	double[] nda(int size) throws IOException {
		double[] ret = new double[size];
		for (int i = 0; i < size; i++)
			ret[i] = nd();
		return ret;
	}

	String nextLine() throws IOException {
		strTok = new StringTokenizer("");
		return in.readLine();
	}

	boolean EOF() throws IOException {
		while (!strTok.hasMoreTokens()) {
			String s = in.readLine();
			if (s == null)
				return true;
			strTok = new StringTokenizer(s);
		}
		return false;
	}

	void printRepeat(String s, int count) {
		for (int i = 0; i < count; i++)
			out.print(s);
	}

	void printArray(int[] array) {
		for (int i = 0; i < array.length; i++) {
			if (i > 0)
				out.print(' ');
			out.print(array[i]);
		}
		out.println();
	}

	void printArray(long[] array) {
		for (int i = 0; i < array.length; i++) {
			if (i > 0)
				out.print(' ');
			out.print(array[i]);
		}
		out.println();
	}

	void printArray(double[] array) {
		for (int i = 0; i < array.length; i++) {
			if (i > 0)
				out.print(' ');
			out.print(array[i]);
		}
		out.println();
	}

	void printArray(double[] array, String spec) {
		for (int i = 0; i < array.length; i++) {
			if (i > 0)
				out.print(' ');
			out.printf(Locale.US, spec, array[i]);
		}
		out.println();
	}

	void printArray(Object[] array) {
		boolean blank = false;
		for (Object x : array) {
			if (blank)
				out.print(' ');
			else
				blank = true;
			out.print(x);
		}
		out.println();
	}

	@SuppressWarnings("rawtypes")
	void printCollection(Collection collection) {
		boolean blank = false;
		for (Object x : collection) {
			if (blank)
				out.print(' ');
			else
				blank = true;
			out.print(x);
		}
		out.println();
	}

	static String memoryStatus() {
		return (Runtime.getRuntime().totalMemory()
				- Runtime.getRuntime().freeMemory() >> 20)
				+ "/" + (Runtime.getRuntime().totalMemory() >> 20) + " MB";
	}

	public void pln() {
		out.println();
	}

	public void pln(int arg) {
		out.println(arg);
	}

	public void pln(long arg) {
		out.println(arg);
	}

	public void pln(double arg) {
		out.println(arg);
	}

	public void pln(String arg) {
		out.println(arg);
	}

	public void pln(boolean arg) {
		out.println(arg);
	}

	public void pln(char arg) {
		out.println(arg);
	}

	public void pln(float arg) {
		out.println(arg);
	}

	public void pln(Object arg) {
		out.println(arg);
	}

	public void p(int arg) {
		out.print(arg);
	}

	public void p(long arg) {
		out.print(arg);
	}

	public void p(double arg) {
		out.print(arg);
	}

	public void p(String arg) {
		out.print(arg);
	}

	public void p(boolean arg) {
		out.print(arg);
	}

	public void p(char arg) {
		out.print(arg);
	}

	public void p(float arg) {
		out.print(arg);
	}

	public void p(Object arg) {
		out.print(arg);
	}

}