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 java.io.*;
import java.math.BigInteger;
import java.util.*;




public class A {
    private static final int mod = (int)1e9+7;
    
    public void run() throws IOException {
        long w = IOFast.nextLong();
        long h = IOFast.nextLong();
        final int a = IOFast.nextInt();
        
        if(a == 0) {
            IOFast.out.printf("%.10f\n", w * 1.0 * h);
            return;
        }
        
        final double r = a * Math.PI / 180.0;
        
        Point p1 = new Point(-w/2.0, h/2.0);
        Point p2 = new Point( w/2.0, h/2.0);
        Point p3 = new Point( w/2.0,-h/2.0);
        Point p4 = new Point(-w/2.0,-h/2.0);
        Segment[] segs = new Segment[] {
                new Segment(p1, p2),
                new Segment(p2, p3),
                new Segment(p3, p4),
                new Segment(p4, p1),
        };
        Segment[] segs2 = new Segment[] {
                new Segment(p1, p2),
                new Segment(p2, p3),
                new Segment(p3, p4),
                new Segment(p4, p1),
        };
        for(int i = 0; i < segs2.length; i++) {
//          System.err.println(i + ": " + segs2[i]);
            segs2[i].rotM(new Point(0, 0), r);
//          System.err.println(i + ": " + segs2[i]);
        }
        
        List<Point> c = new ArrayList<Point>();
        for(int i = 0; i < segs2.length; i++) {
            for(int j = 0; j < segs.length; j++) {
                if(segs2[i].intersect(segs[j])) {
                    Line l1 = Line.from2Point(segs[j].s, segs[j].t);
                    Line l2 = Line.from2Point(segs2[i].s, segs2[i].t);
//                  System.err.println(segs[j] + " " + segs2[i]);
//                  System.err.println(l1 + ": " + l2);
                    if(l1.crossLL(l2) != null) {
                        c.add(l1.crossLL(l2));
                    }
                    /*
                    if(l1.crossLL(l2) != null) {
                        c.add(l1.crossLL(l2));
                    }*/
                }
            }
        }
        
        Collections.sort(c, new Comparator<Point>() {
            @Override
            public int compare(Point o1, Point o2) {
                // TODO Auto-generated method stub
                return Double.compare(Math.atan2(o1.y, o1.x), Math.atan2(o2.y, o2.x));
            }
        });
        
        IOFast.out.printf("%.10f\n", area(c));
    }
    
    double area(List<Point> ps) {
        double res = 0;
        for(int i = 0; i < ps.size(); i++) {
            final int j = (i + 1) % ps.size();
            res += (ps.get(i).x - ps.get(j).x) * (ps.get(i).y + ps.get(j).y);
        }
        return res / 2;
    }
    
    static int ccw(Point a, Point b_, Point c_) {
        Point b = b_.sub(a);
        Point c = c_.sub(a);
        if(b.cross(c) > 0) return 1;
        if(b.cross(c) < 0) return -1;
        if(b.dot(c) < 0) return 2;
        if(b.norm() < c.norm()) return -2;
        return 0;
    }
    
    static
    class Point {
        public double x, y;
        public Point() { }
        public Point(double xx, double yy) { x = xx; y = yy; }
        public Point(Point p) { this(p.x, p.y); }
        public Point rot(final double theta) {
            return new Point(this).rotM(theta);
        }
        public Point rotM(final double theta) {
            final double a = x, b = y;
            x = a * Math.cos(theta) - b * Math.sin(theta);
            y = a * Math.sin(theta) + b * Math.cos(theta);
            return this;
        }
        double cross(Point p) {
            return x * p.y - p.x * y;
        }
        public Point addM(Point p) { return addM(p.x, p.y); }
        public Point addM(double x, double y) {
            this.x += x;
            this.y += y;
            return this;
        }
        public Point add(Point p) { return add(p.x, p.y); }
        public Point add(double x, double y) {
            return new Point(this).addM(x, y);
        }
        public Point subM(Point p) { return subM(p.x, p.y); }
        public Point subM(double x, double y) {
            this.x -= x;
            this.y -= y;
            return this;
        }
        public Point sub(Point p) { return sub(p.x, p.y); }
        public Point sub(double x, double y) {
            return new Point(this).subM(x, y);
        }
        public Point mulM(double d) {
            x *= d;
            y *= d;
            return this;
        }
        public Point mul(double d) {
            return new Point(this).mulM(d);
        }
        public Point divM(double v) {
            this.x /= v;
            this.y /= v;
            return this;
        }
        public Point div(double v) {
            return new Point(this).divM(v);
        }

        public double dot(Point p) { return dot(p.x, p.y); }
        public double dot(double x, double y) {
            return x*this.x + y*this.y;
        }

        public double norm() {
            return x*x+y*y;
        }
        public double abs() {
            return Math.sqrt(norm());
        }

        public String toString() {
            return "(" + x + "," + y + ")";
        }
    }

    static
    public class Segment {
        private static final double eps = 1e-9;

        public Point s, t;

        public Segment(Point a, Point b) { s = new Point(a); t = new Point(b); }
        public Segment(Segment seg) { s = new Point(seg.s); t = new Point(seg.t); }

        public double cross(Point p) {
            final double x1 = p.x - s.x, y1 = p.y - s.y;
            final double x2 = t.x - s.x, y2 = t.y - s.y;
            return x1 * y2 - x2 * y1;
        }

        public boolean intersect(Segment seg) {
            return ccw(s, t, seg.s) * ccw(s, t, seg.t) <= 0 &&
                    ccw(seg.s, seg.t, s) * ccw(seg.s, seg.t, t) <= 0;
        }

        public Point projection(Point p) {
            final Point d = s.sub(t);
            final double t = p.sub(s).dot(d) / d.norm();
            return d.mulM(t).addM(s);
        }
        
        public Segment rot(Point c, double rad) {
            return new Segment(this).rotM(c, rad);
        }
        
        public Segment rotM(Point c, double rad) {
            s.subM(c).rotM(rad).addM(c);
            t.subM(c).rotM(rad).addM(c);
            return this;
        }

        public double dist(Segment seg) {
            if(intersect(seg)) return 0;
            return Math.min(
                    Math.min(dist(seg.s), dist(seg.t)),
                    Math.min(seg.dist(s), seg.dist(t)));
        }

        boolean intersect(Point p) {
            return s.sub(p).abs() + t.sub(p).abs() - t.sub(s).abs() < eps;
        }

        public double dist(final Point pt) {
            final Point p = projection(pt);
            if(intersect(p)) return p.subM(pt).abs();
            return Math.min(s.sub(pt).abs(), t.sub(pt).abs());
        }

        public String toString() {
            return "[" + s + ";" + t + "]";
        }
    }

    static
    public class Line {
        private static final boolean DEBUG = false;
        private static final double eps = 1e-9;
        double a, b, c;

        public static Line fromLine(double a, double b, double c) {
            Line l = new Line();
            l.a = a;
            l.b = b;
            l.c = c;
            return l;
        }

        public static Line fromVec(Point p, Point vec) {
            return from2Point(p, p.add(vec));
        }

        public static Line from2Point(Point p, Point q) {
            final double dx = q.x - p.x;
            final double dy = q.y - p.y;
            final Point mid = p.add(q).divM(2);
            if(Math.abs(dx) < eps) {
                return fromLine(1, 0, -mid.x);
            }
            final double m = dy / dx;
            final Line ret = fromLine(-m, 1, m * mid.x - mid.y);
            ret.checkPassedPoint(p);
            ret.checkPassedPoint(q);
            return ret;
        }

        double GetY(double x) {
            return -(c + a * x)/ b;
        }

        double GetX(double y) {
            return -(c + b * y)/ a;
        }

        void checkPassedPoint(Point p) {
            if(DEBUG) {
                if(Math.abs(a * p.x + b * p.y + c) >= eps) {
                    throw new AssertionError("checkPassedPoint");
                }
            }
        }

        boolean isParallel(Line l) {
            return Math.abs(a * l.b - l.a * b) < eps;
        }

        double dist(Point d) {
            return Math.sqrt(dist2(d));
        }

        double dist2(Point d) {
            return d.x*d.x + d.y*d.y;
        }

        double distP(Point p) {
            if(Math.abs(a) < eps) {
                return dist(new Point(0, -(c / b + p.y)));
            }
            if(Math.abs(b) < eps) {
                return dist(new Point(-(c / a + p.x), 0));
            }

            final double c_ = -b * p.x + a * p.y;
            double x = -(a * c + b * c_) / (a * a + b * b);
            double y = (a * c_ - b * c) / (a * a + b * b);
            return dist(new Point(x - p.x, y - p.y));
        }

        Point crossLL(Line l) {
            final double a1 = a;
            final double b1 = b;
            final double c1 = c;

            final double a2 = l.a;
            final double b2 = l.b;
            final double c2 = l.c;

            final double d = a1 * b2 - a2 * b1;

            if(Math.abs(d) < 1e-9) {
                return null;
            }

            //      System.err.println(d + " " + (a1*c2 - a2*c1));
            final Point p = new Point(-(b2*c1 - b1*c2) / d, -(a1*c2 - a2*c1) / d);
//          final double x = -(b2*c1 - b1*c2) / d;
//          final Point p = new Point(x, -(a*x + c) / b);
//          System.err.println(p);
            checkPassedPoint(p);
            l.checkPassedPoint(p);
            return p;
        }

        // 二等分線
        Line binAngleLine(Line l) {
            final double[] res = new double[3];
            Point p;

            if(isParallel(l)) {
                if(Math.abs(a) < Math.abs(b)) {
                    res[0] = (a * 1.0 / b + l.a * 1.0 / l.b) / 2.0;
                    res[1] = 1;
                    res[2] = (c * 1.0 / b + l.c * 1.0 / l.b) / 2.0;
                    p = new Point(0, res[2] / res[1]);
                }
                else {
                    res[0] = 1;
                    res[1] = (b * 1.0 / a + l.b * 1.0 / l.a) / 2.0;
                    res[2] = (c * 1.0 / a + l.c * 1.0 / l.a) / 2.0;
                    p = new Point(res[2] / res[0], 0);
                }

                //          System.err.println(Arrays.toString(p1) + " " + Arrays.toString(p2) + " " + Arrays.toString(res));
            }
            else {
                p = crossLL(l);

                res[0] = a * 1.0 * l.b + b * 1.0 * l.a;
                res[1] = 2 * b * 1.0 * l.b;
                res[2] = -(p.x * res[0] + p.y * res[1]);

                //          System.err.println(Arrays.toString(p1) + " " + Arrays.toString(p2) + " " + Arrays.toString(p)  + " " + distLP(p1, p[0], p[1]) + " " + distLP(p2, p[0], p[1]));
            }

            final Line ret = fromLine(res[0], res[1], res[2]);
            this.checkPassedPoint(p);
            l.checkPassedPoint(p);
            ret.checkPassedPoint(p);
            return ret;
        }

        Line binLine(Point p1, Point p2) {
            final Point mid = p1.add(p2).divM(2);
            final Point m = p1.sub(p2);
            m.rot(Math.PI / 2);
            return fromVec(mid, m);
        }

        public String toString() {
            return "[" + a + ";" + b + ";" + c + "]";
        }
    }

    
    public static void main(String[] args) throws IOException {
//      IOFast.setFileIO("input.txt", "output.txt");
        new A().run();
        IOFast.out.flush();
    }


    static public class IOFast {
        private static BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
        private static PrintWriter out = new PrintWriter(System.out);

        static void setFileIO(String ins, String outs) throws IOException {
            try {
                in = new BufferedReader(new FileReader(ins));
                out = new PrintWriter(new FileWriter(outs));
            }
            catch(IOException e) {
                System.err.println(e);
                throw e;
            }
        }

        //      private static final int BUFFER_SIZE = 50 * 200000;
        private static int pos, readLen;
        private static final char[] buffer = new char[1024 * 8];
        private static final StringBuilder buf = new StringBuilder();
        private static boolean[] isDigit = new boolean[256];
        private static boolean[] isSpace = new boolean[256];

        static {
            for(int i = 0; i < 10; i++) {
                isDigit['0' + i] = true;
            }
            isDigit['-'] = true;
            isSpace[' '] = isSpace['\r'] = isSpace['\n'] = isSpace['\t'] = true;
        }

        static boolean endInput;

        private static int read() throws IOException {
            if(readLen == -1) {
                return -1;
            }

            if(pos >= readLen) {
                readLen = in.read(buffer);
                pos = 0;

                if(readLen <= 0) {
                    return -1;
                }
            }

            return buffer[pos++];
        }

        private static int nextInt() throws IOException {
            boolean plus = false;
            int ret = 0;
            while(true) {
                final int c = read();

                if(c == -1) {
                    endInput = true;
                    return Integer.MIN_VALUE;
                }

                if(isDigit[c]) {
                    if(c != '-') {
                        plus = true;
                        ret = c - '0';
                    }
                    break;
                }
            }

            while(true) {
                final int c = read();
                if(c == -1 || !isDigit[c]) {
                    break;
                }
                ret = ret * 10 + c - '0';
            }

            return plus ? ret : -ret;
        }

        private static long nextLong() throws IOException {
            boolean plus = false;
            long ret = 0;
            while(true) {
                final int c = read();

                if(c == -1) {
                    endInput = true;
                    return Integer.MIN_VALUE;
                }

                if(isDigit[c]) {
                    if(c != '-') {
                        plus = true;
                        ret = c - '0';
                    }
                    break;
                }
            }

            while(true) {
                final int c = read();
                if(c == -1 || !isDigit[c]) {
                    break;
                }
                ret = ret * 10 + c - '0';
            }

            return plus ? ret : -ret;
        }

        private static char nextChar() throws IOException {
            while(true) {
                final int c = read();

                if(c == -1) {
                    endInput = true;
                    return '\0';
                }

                if(!isSpace[c]) {
                    return (char)c;
                }
            }
        }

        private static String next() throws IOException {
            buf.setLength(0);

            while(true) {
                final int c = read();

                if(c == -1) {
                    endInput = true;
                    return "-1";
                }

                if(!isSpace[c]) {
                    buf.append((char)c);
                    break;
                }
            }

            while(true) {
                final int c = read();

                if(c == -1 || isSpace[c]) {
                    break;
                }
                buf.append((char)c);
            }

            return buf.toString();
        }

        private static double nextDouble() throws IOException {
            return Double.parseDouble(next());
        }

    }

}