#include <bits/stdc++.h>
using namespace std;

template<class T> inline void chmin(T &a, const T &b) { if(a > b) a = b; }
template<class T> inline void chmax(T &a, const T &b) { if(a < b) a = b; }

typedef double Real;
constexpr Real EPS = 1e-8;
inline int sign(Real d) { return d > EPS ? 1 : d < -EPS ? -1 : 0; }

struct Point {
	Real x, y;
	explicit Point(Real x_ = 0, Real y_ = 0):x(x_), y(y_) {}
	Point operator+(const Point &p) const { return Point(x + p.x, y + p.y); }
	Point operator-(const Point &p) const { return Point(x - p.x, y - p.y); }
	Point operator*(Real s) const { return Point(x * s, y * s); }
	bool operator<(const Point &p) const { return sign(x - p.x) == -1 || (sign(x - p.x) == 0 && sign(y - p.y) == -1); }
	bool operator==(const Point &p) const { return sign(x - p.x) == 0 && sign(y - p.y) == 0; }
};

inline istream &operator>>(istream &is, Point &p) {
	return is >> p.x >> p.y;
}

struct Segment : public array<Point, 2> {
	Segment(const Point &a, const Point &b) { at(0) = a; at(1) = b; }
};

typedef vector<Point> Polygon;

inline Real norm(const Point &p) {
	return p.x * p.x + p.y * p.y;
}

inline Real abs(const Point &p) {
	return sqrt(norm(p));
}

inline Real dot(const Point &a, const Point &b) {
	return a.x * b.x + a.y * b.y;
}

inline Real cross(const Point &a, const Point &b) {
	return a.x * b.y - a.y * b.x;
}

enum { CCW = 1, CW = -1, BACK = 2, FRONT = -2, ON = 0};
inline int ccw(const Point &a, const Point &b, const Point &c) {
	const Point p = b - a;
	const Point q = c - a;
	const int sign_cross = sign(cross(p, q));

	if(sign_cross == 1) return CCW;
	if(sign_cross == -1) return CW;
	if(sign(dot(p, q)) == -1) return BACK;
	if(sign(norm(p) - norm(q)) == -1) return FRONT;
	return ON;
}

inline bool intersect(const Segment &s, const Point &p) {
	return ccw(s[0], s[1], p) == ON;
}

inline bool intersect(const Segment &a, const Segment &b) {
	return ccw(a[0], a[1], b[0]) * ccw(a[0], a[1], b[1]) <= 0
		&& ccw(b[0], b[1], a[0]) * ccw(b[0], b[1], a[1]) <= 0;
}

inline Real dist(const Point &a, const Point &b) {
	return abs(a - b);
}

inline Point crosspoint(const Segment &a, const Segment &b) {
	const Real crs = cross(a[1] - a[0], b[1] - b[0]);
	if(sign(crs) == 0) {
		if(intersect(a, b[0])) return b[0];
		if(intersect(a, b[1])) return b[1];
		if(intersect(b, a[0])) return a[0];
		return a[1];
	}
	return b[0] + (b[1] - b[0]) * (cross(a[1] - a[0], a[1] - b[0]) / crs);
}

// *solve

int main() {
	cin.tie(nullptr);
	ios::sync_with_stdio(false);
	cout.setf(ios::fixed);
	cout.precision(10);

	constexpr Real INF = 1e6;

	for(int m, n; cin >> m >> n && m;) {
		vector<Real> xs;
		Polygon c1(m), c2(n);
		Real L1 = INF, R1 = -INF, L2 = INF, R2 = -INF;

		for(auto &e : c1) {
			cin >> e;
			xs.emplace_back(e.x);
			chmin(L1, e.x);
			chmax(R1, e.x);
		}
		for(auto &e : c2) {
			cin >> e;
			xs.emplace_back(e.x);
			chmin(L2, e.x);
			chmax(R2, e.x);
		}

		const Real L = max(L1, L2), R = min(R1, R2);

		sort(begin(xs), end(xs));
		xs.erase(unique(begin(xs), end(xs)), end(xs));

		const auto width = [](const Polygon &p, Real x) {
			Segment cut(Point(x, INF), Point(x, -INF));
			Real low = INF, high = -INF;
			Point prev = p.back();

			for(const auto &curr : p) {
				const Segment edge(prev, curr);
				if(intersect(edge, cut)) {
					const auto cp = crosspoint(edge, cut);
					chmin(low, cp.y);
					chmax(high, cp.y);
				}
				prev = curr;
			}
			return max(0.0, high - low);
		};
		const auto f = [&](Real x) { return width(c1, x) * width(c2, x); };
		const auto simpson = [&](Real a, Real b) {
			const Real c = (a + b) / 2;
			return L < c && c < R ? (b - a) / 6 * (f(a) + 4 * f(c) + f(b)) : 0;
		};

		Real ans = 0.0;
		for(int i = 1; i < xs.size(); ++i) {
			ans += simpson(xs[i - 1], xs[i]);
		}
		cout << ans << endl;
	}

	return EXIT_SUCCESS;
}

Measured memory_bytes: 1332