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 CPP):

Solution:
#include <bits/stdc++.h>
using data_Ty = double;
const data_Ty INF = 0x7fffffffffffffffLL;
const double PI = 2.0 * acos(0.0);
const double EPSILON = 1e-9;
using std::get;
using std::pair;
using std::vector;
struct point {
  data_Ty x;
  data_Ty y;
  bool operator==(point p) { return x == p.x && y == p.y; }
  point operator*(double p) const { return {x * p, y * p}; }
  point operator+(const point p) const { return {x + p.x, y + p.y}; }
  point operator-(const point p) const { return {x - p.x, y - p.y}; }
  double norm() const { return hypot(x, y); }
  point normalize() const { return {x / norm(), y / norm()}; }
  double polar() const { return fmod(atan2(y, x) + 2 * PI, 2 * PI); }
  double dot(const point& p) const { return x * p.x + y * p.y; }
  double cross(const point& p) const { return x * p.y - p.x * y; }
  point project(const point& p) const {
    point r = p.normalize();
    return r * r.dot(*this);
  }
  double toRadian(double degree) const { return PI / 180 * degree; }
  point func(const double degree) const {
    double radian = toRadian(degree);
    return {cos(radian) * x - sin(radian) * y,
            sin(radian) * x + cos(radian) * y};
  }
};
data_Ty abss(data_Ty a) {
  if (a < 0) return -a;
  return a;
}
data_Ty ccw(data_Ty ax, data_Ty ay, data_Ty bx, data_Ty by, data_Ty cx,
            data_Ty cy) {
  return bx * cy - ay * bx - ax * cy - by * cx + ax * by + ay * cx;
}
data_Ty ccw(point a, point b, point c) {
  return b.x * c.y - a.y * b.x - a.x * c.y - b.y * c.x + a.x * b.y + a.y * c.x;
}
struct line {
  data_Ty a, b, c;
  line();
  line(point A, point B) {
    a = B.y - A.y;
    b = -(B.x - A.x);
    c = A.y * (B.x - A.x) - A.x * (B.y - A.y);
  }
  line(data_Ty m_u, data_Ty m_d, data_Ty B) {
    a = m_u;
    b = -m_d;
    c = B;
  }
  data_Ty getX(data_Ty y) { return (-b * y - c) / a; }
  data_Ty getY(data_Ty x) { return (-a * x - c) / b; }
  double toPoint(point p) {
    return std::abs(a * p.x + b * p.y + c) / sqrt((double)(a * a + b * b));
  }
  bool getLineIntersectionPoint(line p, point& q) {
    point a = {0, getY(0)};
    point b = {1, getY(1)};
    if (this->b == 0) {
      a = {getX(0), 0};
      b = {getX(1), 1};
    }
    point c = {0, p.getY(0)};
    point d = {1, p.getY(1)};
    if (p.b == 0) {
      c = {p.getX(0), 0};
      d = {p.getX(1), 1};
    }
    double det = (b - a).cross(d - c);
    if (fabs(det) < EPSILON) return false;
    q = a + (b - a) * ((c - a).cross(d - c) / det);
    return true;
  }
  bool extend(line p) {
    if (b == 0 && p.b == 0) {
      return fabs(c / a - p.c / p.a) < EPSILON;
    }
    return fabs((a / b) - (p.a / p.b)) < EPSILON &&
           fabs(c / b - p.c / p.b) < EPSILON;
  }
};
struct segment {
  point a;
  point b;
  long long diffX() { return b.x - a.x; }
  long long diffY() { return b.y - a.y; }
  long long sign(long long a) {
    if (a > 0) return 1;
    if (a < 0) return -1;
    return 0;
  }
  bool intersect(segment p) {
    long long a1 = ccw(a, b, p.a);
    long long a2 = ccw(a, b, p.b);
    long long b1 = ccw(p.a, p.b, a);
    long long b2 = ccw(p.a, p.b, b);
    bool A = sign(a1) * sign(a2) < 0;
    bool B = sign(b1) * sign(b2) < 0;
    if (A && B) {
      return true;
    }
    return false;
  }
  bool inner(point p) {
    long long A = ccw(a, b, p);
    bool X = false;
    bool Y = false;
    if (std::min(a.x, b.x) <= p.x && p.x <= std::max(a.x, b.x)) {
      X = true;
    }
    if (std::min(a.y, b.y) <= p.y && p.y <= std::max(a.y, b.y)) {
      Y = true;
    }
    if (A == 0 && X && Y) {
      return true;
    }
    return false;
  }
  bool endpoint(point p) { return a == p || b == p; }
  bool overlap(segment p) {
    long long a1 = ccw(a, b, p.a);
    long long a2 = ccw(a, b, p.b);
    long long b1 = ccw(p.a, p.b, a);
    long long b2 = ccw(p.a, p.b, b);
    if (a1 == 0 && a2 == 0 && b1 == 0 && b2 == 0) {
      if ((inner(p.a) && inner(p.b)) || (p.inner(a) && p.inner(b))) {
        return true;
      }
      if (a == p.a && (sign(b.x - a.x) != sign(p.b.x - p.a.x) ||
                       sign(b.y - a.y) != sign(p.b.y - p.a.y))) {
        return false;
      }
      if (a == p.b && (sign(b.x - a.x) != sign(p.a.x - p.b.x) ||
                       sign(b.y - a.y) != sign(p.a.y - p.b.y))) {
        return false;
      }
      if (b == p.a && (sign(a.x - b.x) != sign(p.b.x - p.a.x) ||
                       sign(a.y - b.y) != sign(p.b.y - p.a.y))) {
        return false;
      }
      if (b == p.b && (sign(a.x - b.x) != sign(p.a.x - p.b.x) ||
                       sign(a.y - b.y) != sign(p.a.y - p.b.y))) {
        return false;
      }
      if (inner(p.a) || inner(p.b) || p.inner(a) || p.inner(b)) {
        return true;
      }
    }
    return false;
  }
};
struct polygon {
  vector<point> points;
  data_Ty ccw(data_Ty ax, data_Ty ay, data_Ty bx, data_Ty by, data_Ty cx,
              data_Ty cy) {
    return bx * cy - ay * bx - ax * cy - by * cx + ax * by + ay * cx;
  }
  data_Ty ccw(point a, point b, point c) {
    return b.x * c.y - a.y * b.x - a.x * c.y - b.y * c.x + a.x * b.y +
           a.y * c.x;
  }
  data_Ty ccw(int a, int b, int c) {
    return ccw(points[a], points[b], points[c]);
  }
  data_Ty length(point a, point b) {
    return (b.y - a.y) * (b.y - a.y) + (b.x - a.x) * (b.x - a.x);
  }
  bool isInsider(point p) {
    segment q = {p, {1000000007, 1000000007}};
    int size = points.size();
    int cnt = 0;
    for (int i = 0; i < size; i++) {
      segment k = {points[i], points[(i + 1) % size]};
      if (q.intersect(k)) {
        cnt++;
      }
      if (k.inner(p)) {
      }
    }
    return cnt % 2 == 1;
  }
  bool isInsider(polygon& p) {
    int size = p.points.size();
    for (int i = 0; i < size; i++) {
      if (!isInsider(p.points[i])) {
        return false;
      }
    }
    return true;
  }
  double getArea() {
    int size = points.size();
    double ret = 0;
    for (int i = 0; i < size; i++) {
      ret += ccw(points[0], points[i], points[(i + 1) % size]);
    }
    return fabs(ret / 2);
  }
  polygon getConvexHull() {
    using node = std::tuple<point, double, data_Ty>;
    point leftup = {INF / 2, -INF / 2}, leftdown = {INF / 2, INF / 2},
          rightup = {-INF / 2, -INF / 2}, rightdown = {-INF / 2, INF / 2};
    auto U = [](const point& p) { return p.y - p.x; };
    auto D = [](const point& p) { return p.y + p.x; };
    for (const point& p : this->points) {
      if (U(leftup) < U(p)) leftup = p;
      if (U(rightdown) > U(p)) rightdown = p;
      if (D(rightup) < D(p)) rightup = p;
      if (D(leftdown) > D(p)) leftdown = p;
    }
    vector<data_Ty> X;
    vector<data_Ty> Y;
    X.push_back(leftup.x);
    X.push_back(leftdown.x);
    X.push_back(rightup.x);
    X.push_back(rightdown.x);
    Y.push_back(leftup.y);
    Y.push_back(leftdown.y);
    Y.push_back(rightup.y);
    Y.push_back(rightdown.y);
    std::sort(X.begin(), X.end());
    std::sort(Y.begin(), Y.end());
    vector<node> np;
    point q = {INF, INF};
    for (const point& p : this->points) {
      if (p.y < q.y || (p.y == q.y && p.x < q.x)) {
        q = p;
      }
    }
    for (const point& p : points) {
      if ((p.x <= X[1] || p.x >= X[2]) || (p.y <= Y[1] || p.y >= Y[2])) {
        np.emplace_back(p, atan2(p.y - q.y, p.x - q.x), length(p, q));
      }
    }
    std::sort(np.begin(), np.end(), [&](const node& a, const node& b) {
      double a_radian = get<1>(a);
      data_Ty a_length = get<2>(a);
      double b_radian = get<1>(b);
      data_Ty b_length = get<2>(b);
      return a_radian < b_radian ||
             (a_radian == b_radian && a_length < b_length);
    });
    np.emplace_back(q, 0, 0);
    vector<point> stack;
    for (node& s : np) {
      point p = get<0>(s);
      while (stack.size() >= 2) {
        point one = *(stack.end() - 2);
        point two = *(stack.end() - 1);
        if (ccw(one, two, p) <= 0) {
          stack.pop_back();
          continue;
        }
        break;
      }
      stack.push_back(p);
    }
    stack.pop_back();
    return {stack};
  }
  polygon cutPolygontoSegment(const segment& p) {
    int size = points.size();
    vector<bool> inside;
    auto next = [&](int i) { return (i + 1) % size; };
    for (auto& q : points) inside.push_back(ccw(p.a, p.b, q) >= 0);
    polygon ret;
    for (int i = 0; i < size; i++) {
      int j = next(i);
      if (inside[i]) ret.points.push_back(points[i]);
      if (inside[i] != inside[j]) {
        line a(points[i], points[j]);
        line b(p.a, p.b);
        point q;
        a.getLineIntersectionPoint(b, q);
        ret.points.push_back(q);
      }
    }
    return ret;
  }
  polygon cutPolygontoConvexhull(polygon& p) {
    int size = p.points.size();
    if (isInsider(p)) {
      return p;
    }
    if (p.isInsider(*this)) {
      return *this;
    }
    polygon ret = *this;
    auto next = [&](int i) { return (i + 1) % size; };
    for (int i = 0; i < size; i++) {
      ret = ret.cutPolygontoSegment({p.points[i], p.points[next(i)]});
    }
    return ret;
  }
};
int main() {
  double w, h, a;
  scanf("%lf%lf%lf", &w, &h, &a);
  point lx = {w / 2, 0};
  point rx = {-w / 2, 0};
  point uy = {0, h / 2};
  point dy = {0, -h / 2};
  polygon one;
  one.points.push_back(lx + uy);
  one.points.push_back(rx + uy);
  one.points.push_back(rx + dy);
  one.points.push_back(lx + dy);
  one = one.getConvexHull();
  polygon two;
  lx = lx.func(a);
  rx = rx.func(a);
  uy = uy.func(a);
  dy = dy.func(a);
  two.points.push_back(lx + uy);
  two.points.push_back(rx + uy);
  two.points.push_back(rx + dy);
  two.points.push_back(lx + dy);
  two = two.getConvexHull();
  if (a == 0 || a == 180 || (w == h && a == 90)) {
    printf("%.9lf\n", one.getArea());
    return 0;
  }
  if (one.cutPolygontoConvexhull(two).points.size() <= 2) {
    while (1)
      ;
  }
  printf("%.9lf\n", one.cutPolygontoConvexhull(two).getArea());
}