Problem: Suppose that P1 is an infinite-height prism whose axis is parallel to the z-axis, and P2 is also an infinite-height prism whose axis is parallel to the y-axis. P1 is defined by the polygon C1 which is the cross section of P1 and the xy-plane, and P2 is also defined by the polygon C2 which is the cross section of P2 and the xz-plane.

Figure I.1 shows two cross sections which appear as the first dataset in the sample input, and Figure I.2 shows the relationship between the prisms and their cross sections.

<image>


Figure I.1: Cross sections of Prisms

<image>


Figure I.2: Prisms and their cross sections

<image>


Figure I.3: Intersection of two prisms

Figure I.3 shows the intersection of two prisms in Figure I.2, namely, P1 and P2.

Write a program which calculates the volume of the intersection of two prisms.



Input

The input is a sequence of datasets. The number of datasets is less than 200.

Each dataset is formatted as follows.

m n
x11 y11
x12 y12
.
.
.
x1m y1m
x21 z21
x22 z22
.
.
.
x2n z2n


m and n are integers (3 ≤ m ≤ 100, 3 ≤ n ≤ 100) which represent the numbers of the vertices of the polygons, C1 and C2, respectively.

x1i, y1i, x2j and z2j are integers between -100 and 100, inclusive. (x1i, y1i) and (x2j , z2j) mean the i-th and j-th vertices' positions of C1 and C2 respectively.

The sequences of these vertex positions are given in the counterclockwise order either on the xy-plane or the xz-plane as in Figure I.1.

You may assume that all the polygons are convex, that is, all the interior angles of the polygons are less than 180 degrees. You may also assume that all the polygons are simple, that is, each polygon's boundary does not cross nor touch itself.

The end of the input is indicated by a line containing two zeros.

Output

For each dataset, output the volume of the intersection of the two prisms, P1 and P2, with a decimal representation in a line.

None of the output values may have an error greater than 0.001. The output should not contain any other extra characters.

Example

Input

4 3
7 2
3 3
0 2
3 1
4 2
0 1
8 1
4 4
30 2
30 12
2 12
2 2
15 2
30 8
13 14
2 8
8 5
13 5
21 7
21 9
18 15
11 15
6 10
6 8
8 5
10 12
5 9
15 6
20 10
18 12
3 3
5 5
10 3
10 10
20 8
10 15
10 8
4 4
-98 99
-99 -99
99 -98
99 97
-99 99
-98 -98
99 -99
96 99
0 0


Output

4.708333333333333
1680.0000000000005
491.1500000000007
0.0
7600258.4847715655

Solution (in CPP):

Solution:
#include <bits/stdc++.h>

using namespace std;

#define SZ(x) (int)(x.size())
#define REP(i, n) for(int i=0;i<n;++i)
#define FOR(i, a, b) for(int i=a;i<b;++i)
#define RREP(i, n) for(int i=n-1;i>=0;--i)
#define RFOR(i, a, b) for(int i=b-1;i>=a;--i)
#define ALL(a) a.begin(),a.end()
#define DUMP(x) cerr<<#x<<" = "<<(x)<<endl
#define DEBUG(x) cerr<<#x<<" = "<<(x)<<" (L"<<__LINE__<<")"<< endl;

using ll = long long;
using ld = double;
#define double ld
using vi = vector<int>;
using vvi = vector<vi>;
using vll = vector<ll>;
using vvll = vector<vll>;
using P = pair<int, int>;

const double eps = 1e-8;
const double EPS = eps;
const ll MOD = 1000000007;
const int INF = INT_MAX / 2;
const ll LINF = LLONG_MAX / 2;

template <typename T1, typename T2>
bool chmax(T1 &a, const T2 &b) {
  if(a < b) {a = b; return true;}
  return false;
}

template <typename T1, typename T2>
bool chmin(T1 &a, const T2 &b) {
  if(a > b) {a = b; return true;}
  return false;
}

template<typename T>
void printv(const vector<T>& s) {
  for(int i=0;i<(int)(s.size());++i) {
    cout << s[i];
    if(i != (int)(s.size())-1) cout << " ";
  }
  cout << "\n";
}

template<class T>
ostream &operator<<(ostream &os, const vector<T> &v) {
  os << "[";
  REP(i, SZ(v)) {
    if(i) os << ", ";
    os << v[i];
  }
  return os << "]";
}

template<typename T1, typename T2>
ostream& operator<<(ostream &os, const pair<T1, T2> p) {
  os << p.first << ":" << p.second;
  return os;
}

using Real = double;
const Real PI = acos(-1);

using Point = complex<Real>;
namespace std {
  bool operator<(const Point& a, const Point& b) {
    if (a.real() == b.real()) return a.imag() < b.imag();
    return a.real() < b.real();
  }
}
struct Line {
  Point a, b;
  Line() {}
  Line(const Point& a, const Point& b) : a(a), b(b) {}
  friend ostream& operator<<(ostream& os, const Line& l) {
    return os << "[" << l.a << "," << l.b << "]";
  }
};
struct Segment : Line {
  Segment() = default;

  Segment(const Point& a, const Point& b) : Line(a, b) {}
};

inline bool eq(Real a, Real b) { return abs(b - a) < EPS; }

Real radian_to_degree(Real r) {
  return r * 180.0 / PI;
}

Real degree_to_radian(Real d) {
  return d * PI / 180.0;
}

Point rotate(const Point &p, Real theta) {
  return p * polar((Real)1.0, theta);
}

Real cross(const Point& a, const Point& b) {
  return a.real() * b.imag() - a.imag() * b.real();
}

Real dot(const Point& a, const Point& b) {
  return a.real() * b.real() + a.imag() * b.imag();
}

Point projection(const Line& l, const Point& p) {
  Real A = dot(l.b - l.a, p - l.a),
          B = dot(l.a - l.b, p - l.b);
  return (A * l.b + B * l.a) / (A + B);
}

bool parallel(const Line& l1, const Line& l2) {
  return eq(cross(l1.a - l1.b, l2.a - l2.b), 0.0);
}

bool orthogonal(const Line& l1, const Line& l2) {
  return eq(dot(l1.a - l1.b, l2.a - l2.b), 0.0);
}

const int COUNTER_CLOCKWISE = 1,
        CLOCKWISE = -1,
        ONLINE_BACK = 2,
        ONLINE_FRONT = -2,
        ON_SEGMENT = 0;
int ccw(const Point& a, Point b, Point c) {
  b = b - a, c = c - a;
  if (cross(b, c) > EPS) return COUNTER_CLOCKWISE;
  if (cross(b, c) < -EPS) return CLOCKWISE;
  if (dot(b, c) < 0) return ONLINE_BACK;
  if (norm(b) < norm(c)) return ONLINE_FRONT;
  return ON_SEGMENT;
}

bool intersected(const Line& l, const Point& p) {
  return abs(ccw(l.a, l.b, p)) != 1;
}

bool intersected(const Segment& s, const Point& p) {
  return ccw(s.a, s.b, p) == 0;
}

bool intersected(const Line& l, const Segment& s) {
  return cross(l.b - l.a, s.a - l.a) * cross(l.b - l.a, s.b - l.a) < EPS;
}

bool intersected(const Segment& s1, const Segment& s2) {
  return ccw(s1.a, s1.b, s2.a) * ccw(s1.a, s1.b, s2.b) <= 0 and
         ccw(s2.a, s2.b, s1.a) * ccw(s2.a, s2.b, s1.b) <= 0;
}

Real distance(const Line& l, const Point& p) {
  return abs(p - projection(l, p));
}

Real distance(const Segment& s, const Point& p) {
  Point r = projection(s, p);
  if (intersected(s, r)) return abs(r - p);
  return min(abs(s.a - p), abs(s.b - p));
}

Real distance(const Line &l, const Segment &s) {
  if (intersected(l, s)) return 0;
  return min(distance(l, s.a), distance(l, s.b));
}

Real distance(const Segment& s1, const Segment& s2) {
  if (intersected(s1, s2)) return 0.0;
  return min({ distance(s1, s2.a), distance(s1, s2.b),
               distance(s2, s1.a), distance(s2, s1.b) });
}

Point crosspoint(const Line& l1, const Line& l2) {
  Real A = cross(l2.a - l1.a, l2.b - l1.a),
          B = cross(l2.b - l1.b, l2.a - l1.b);
  return (A * l1.b + B * l1.a) / (A + B);
}

struct Circle {
  Point p;
  Real r;
  Circle() {}
  Circle(const Point& p, Real r) : p(p), r(r) {}
};


int intersected(Circle c1, Circle c2) {
  if (c1.r < c2.r) swap(c1, c2);
  Real d = abs(c1.p - c2.p);
  if (c1.r + c2.r < d) return 4;
  if (eq(c1.r + c2.r, d)) return 3;
  if (c1.r - c2.r < d) return 2;
  if (eq(c1.r - c2.r, d)) return 1;
  return 0;
}

pair<Point,Point> crosspoint(const Circle& c, const Line& l) {
  Real h = distance(l, c.p);
  Point p = projection(l, c.p);
  if (eq(h, c.r)) return { p, p };
  Point u = l.a - l.b; u /= abs(u);
  Real d = sqrt(c.r * c.r - h * h);
  return { p + u * d, p - u * d };
}

pair<Point,Point> crosspoint(const Circle& c1, const Circle& c2) {
  Real d = abs(c2.p - c1.p), t = arg(c2.p - c1.p);
  Real a = acos((c1.r * c1.r + d * d - c2.r * c2.r) / (2 * c1.r * d));
  return { c1.p + polar(c1.r, t + a),
           c1.p + polar(c1.r, t - a) };
}

pair<Point,Point> tangent(const Point& p, const Circle& c) {
  return crosspoint(c, Circle(p, sqrt(norm(p - c.p) - c.r * c.r)));
};

vector<Line> common_tangent(const Circle& c1, const Circle& c2) {
  vector<Line> lines;
  Point u = c2.p - c1.p;
  Real d = abs(u);
  if (eq(d, 0.0)) return lines;
  u /= d;
  for (Real s : { -1, 1 }) {
    Real h = (c1.r + s * c2.r) / d;
    if (eq(abs(h), 1.0)) {
      lines.emplace_back(
              c1.p + u * h * c1.r,
              c1.p + u * h * c1.r + rotate(u, PI / 2.0));
    } else if (abs(h) < 1) {
      Real a = acos(h);
      lines.emplace_back(
              c1.p + u * polar(c1.r, a),
              c2.p - s * u * polar(c2.r, a));
      lines.emplace_back(
              c1.p + u * polar(c1.r, -a),
              c2.p - s * u * polar(c2.r, -a));
    }
  }
  return lines;
}

double width(const vector<Point> &p, double x) {
  int sz = SZ(p);
  double mi = INF, ma = -INF;
  REP(i, sz) {
    double x1 = p[i].real(), x2 = p[(i+1)%sz].real();
    double y1 = p[i].imag(), y2 = p[(i+1)%sz].imag();

    if((x1 - x) * (x2 - x) <= 0 && x1 != x2) {
      double tmp = y1 + (y2 - y1) / (x2 - x1) * (x - x1);
      chmin(mi, tmp);
      chmax(ma, tmp);
    }
  }

  return max(0.0, ma - mi);
}

bool solve() {
  int m, n; cin >> m >> n;
  if(m == 0 && n == 0) return false;

  vector<Point> p1(m), p2(n);
  vector<int> vx;

  int mi1 = INF, ma1 = -INF;
  REP(i, m) {
    int x, y; cin >> x >> y;
    p1[i] = Point(x, y);
    vx.push_back(x);
    chmin(mi1, x);
    chmax(ma1, x);
  }

  int mi2 = INF, ma2 = -INF;
  REP(i, n) {
    int x, z; cin >> x >> z;
    p2[i] = Point(x, z);
    vx.push_back(x);
    chmin(mi2, x);
    chmax(ma2, x);
  }

  sort(ALL(vx));

  vector<double> area(n+m);
  REP(i, n+m) {
    area[i] = width(p1, vx[i]) * width(p2, vx[i]);
  }

  double ans = 0.0;
  REP(i, n+m-1) {
    double dist = vx[i+1] - vx[i];
    double b = (vx[i] + vx[i+1]) / 2.0;
    if(!(mi1 <= b && b <= ma1 && mi2 <= b && b <= ma2)) continue;
    double s = width(p1, b) * width(p2, b);

    //if(abs(area[i] - area[i+1]) < eps) ans += area[i] * dist;
    //else ans += dist / 3.0 * (area[i] + area[i+1] + sqrt(area[i]) * sqrt(area[i+1]));
    ans += dist / 6 * (area[i] + 4 * s + area[i+1]);
  }
  cout << ans << endl;

  return true;
}

int main() {
  cin.tie(0);
  ios::sync_with_stdio(false);
  cout << fixed << setprecision(10);

  while(1) {
    if(!solve()) break;
  }

}