JAVA (Japan Aerospace Voyage Agency) launched a spacecraft in 2003 as part of its space development project. One of the purposes of launching this spacecraft is to approach the asteroid Ishikawa and collect samples of its surface material. Despite various accidents, the spacecraft reached Ishikawa and finally returned to Earth in 2010 to successfully recover the capsule containing Ishikawa's sample.

Masa Kita, who graduated from the University of Tokyo and got a job at JAVA, is in charge of research on this sample. I'd like to analyze the sample as soon as possible, but Mr. Kitamasa, who is very careful, thought that it would be difficult if there were ferocious aliens in the capsule. Therefore, before opening the capsule, I decided to use X-rays to examine the shape of the substance inside and confirm that it did not contain aliens. When the capsule is exposed to X-rays, a photograph is obtained in which the substance is white where it is present and black where it is not present. By irradiating X-rays from various angles and obtaining photographs, the shape of the substance inside can be identified.

However, there was another problem here. The X-ray device broke down when I got three pictures from the front, from the right side, and from the top. Furthermore, it is possible that the development of the three photographs also failed, and the part that should have been black has turned white. Since the shape of the substance cannot be accurately specified as it is, it cannot be confirmed that there are no aliens inside, and the capsule cannot be opened.

The only way to continue research is to replace the X-ray equipment, but JAVA does not have the money to replace the X-ray equipment immediately due to the budget cuts due to business sorting. So Kitamasa asked him to increase his budget next year and thought about buying a new X-ray device with that money. Of course, the budget will not increase easily, so it is necessary to maximize the results of the spacecraft. The larger the substance contained in the capsule, the stronger the appeal of the result, so we decided to calculate the maximum volume that the substance can take.

Find the shape of the substance inside that is consistent with the three X-ray photographs and have the largest volume, and output that volume.

Notes on Test Cases

Multiple datasets are given in the above input format. Create a program that outputs each data set in the above output format.

When nx, ny, nz are all 0, it indicates the end of input.

<!-



Input

The white and black border of each radiograph consists of a single polygon. Polygons are not always convex and do not self-intersect. The inside of the polygon is white and the outside is black.

The input format is as follows.


nx
y1 z1
y2 z2
...
ynx znx
ny
z1 x1
z2 x2
...
zny xny
nz
x1 y1
x2 y2
...
xnz ynz

nx, ny, and nz are the number of vertices of the polygon corresponding to the X-ray photograph from the front, right side, and top, respectively. The number of each vertex is 3 or more and 20 or less. The following n lines are given the coordinates of the vertices of the polygon counterclockwise. The coordinates of the vertices are integers between 0 and 300.

The coordinate axes are the x-axis in the front direction from the center of the capsule, the y-axis in the right side direction, and the z-axis in the top surface direction.

<image>

Output

Output the maximum volume of the substance in one line that is consistent with the three X-ray photographs. The output value may contain an error of 10-3 or less. The value may be displayed in any number of digits after the decimal point.

Examples

Input

4
0 0
100 0
100 100
0 100
4
0 0
100 0
100 100
0 100
4
0 0
100 0
100 100
0 100
3
0 0
100 0
0 100
3
0 0
100 0
0 100
3
0 0
100 0
0 100
5
0 0
200 0
200 200
100 100
0 200
5
0 0
200 0
100 100
200 200
0 200
4
0 0
200 0
200 200
0 200
0
0
0


Output

1000000.0000
250000.0000
5333333.3333


Input

4
0 0
100 0
100 100
0 100
4
0 0
100 0
100 100
0 100
4
0 0
100 0
100 100
0 100


Output

1000000.0000


Input

3
0 0
100 0
0 100
3
0 0
100 0
0 100
3
0 0
100 0
0 100


Output

250000.0000


Input

5
0 0
200 0
200 200
100 100
0 200
5
0 0
200 0
100 100
200 200
0 200
4
0 0
200 0
200 200
0 200


Output

5333333.3333
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <vector>
#include <queue>
#include <utility>
#define EPS 1e-10

using namespace std;
typedef long long ll;

struct Point{
	double x,y;
	Point(double x = 0.0,double y = 0.0): x(x),y(y) {}
	Point operator + (Point p){
		return Point(x + p.x,y + p.y);
	}
	Point operator - (Point p){
		return Point(x - p.x,y - p.y);
	}
	Point operator * (double lambda){
		return Point(x * lambda,y * lambda);
	}
	Point operator / (double lambda){
		return Point(x / lambda,y / lambda);
	}
	double norm(){
		return x * x + y * y;
	}
	double abs_(){
		return sqrt(norm());
	}
	double pol(){
		return atan2(y,x);
	}
	bool operator == (const Point &p)const
	{
		return abs(x - p.x) < EPS && abs(y - p.y) < EPS;
	}
	bool operator < (const Point &p)const
	{
		if(abs(x - p.x) < EPS) return y < p.y;
		return x < p.x;
 	}
};
typedef Point Vector;
double dot(Vector a,Vector b){
	return a.x * b.x + a.y * b.y;
}
double det(Vector a,Vector b){
	return a.x * b.y - a.y * b.x;
}
typedef vector<Point> Polygon;
struct Segment{
	Point p1,p2;
	Segment(Point p1 = Point(),Point p2 = Point()): p1(p1),p2(p2) {}
};
typedef Segment Line;
Point crossPoint(Line a,Line b){
	double r = det(b.p2 - b.p1,a.p1 - b.p1) / det(a.p2 - a.p1,b.p2 - b.p1);
	return a.p1 + (a.p2 - a.p1) * r;
}
bool on_left(Point p,Line l){ return det(l.p2 - l.p1,p - l.p1) > EPS; }
bool para(Line a,Line b){ return abs(det(a.p2 - a.p1,b.p2 - b.p1)) < EPS; }
Line L[15],que[15];
int he,ta,n;
bool cmp(Line &a,Line &b){
	return (a.p2 - a.p1).pol() < (b.p2 - b.p1).pol();
}
double area(Polygon P){
	double ans = 0.0;
	int num = P.size();
	for(int i = 0;i < num;i++){
		ans += det(P[i],P[(i + 1) % num]);
	}
	return ans / 2.0;
}
double hp_intersect(){
	sort(L + 1,L + n + 1,cmp);
	he = ta = 0;
	for(int i=1;i<=n;i++){
		while(ta - he > 1 && !on_left(crossPoint(que[ta - 1],que[ta - 2]),L[i])) ta--;
		while(ta - he > 1 && !on_left(crossPoint(que[he],que[he + 1]),L[i])) he++;
		que[ta++] = L[i];
		while(ta - he > 1 && para(que[ta - 1],que[ta - 2])){
			ta--;
			if(on_left(L[i].p1,que[ta - 1])) que[ta - 1] = L[i];
		}
	}
	while(ta - he > 1 && !on_left(crossPoint(que[ta - 1],que[ta - 2]),que[he])) ta--;
	if(ta - he <= 2) return 0.0;
	int cnt = ta - he;
  Polygon po(cnt);
  for(int i=0;i<cnt;i++){
  	po[i] = crossPoint(que[he + i],que[he + (i + 1) % cnt]);
  }
  return area(po);
}
void cut(Polygon P,double x0,vector <double> &lis){
  lis.clear();
  int num = P.size();
  Line l = Line(Point(x0,-1.0),Point(x0,301.0));
  for(int i = 0;i < num;i++){
    if(P[i].x == P[(i + 1) % num].x) continue; // 取x0时应回避这个x
    if((P[i].x - x0) * (P[(i + 1) % num].x - x0) < 0){
      lis.push_back(crossPoint(Line(P[i],P[(i + 1) % num]),l).y);
    }
  }
  sort(lis.begin(),lis.end());
}
Polygon X,Y,Z;
int nx,ny,nz;
vector <double> ylis,zlis; // ylis's segments parallel to z-axis.
double calc(double x0){
  cut(Y,x0,ylis);
  cut(Z,x0,zlis);
  double ans = 0;
  for(int i = 0;i < (int)ylis.size();i += 2){
    for(int j = 0;j < (int)zlis.size();j += 2){
      for(int k = 0;k < nx;k++){
        n = 0;
        L[++n] = Line(Point(zlis[j],ylis[i]),Point(zlis[j + 1],ylis[i]));
        L[++n] = Line(Point(zlis[j + 1],ylis[i]),Point(zlis[j + 1],ylis[i + 1]));
        L[++n] = Line(Point(zlis[j + 1],ylis[i + 1]),Point(zlis[j],ylis[i + 1]));
        L[++n] = Line(Point(zlis[j],ylis[i + 1]),Point(zlis[j],ylis[i]));
        if(det(X[k] + Point(1,1),X[(k + 1) % nx] + Point(1,1)) > 0){
          L[++n] = Line(Point(-1,-1),X[k]);
          L[++n] = Line(X[k],X[(k + 1) % nx]);
          L[++n] = Line(X[(k + 1) % nx],Point(-1,-1));
          ans += hp_intersect();
        }else{
          L[++n] = Line(Point(-1,-1),X[(k + 1) % nx]);
          L[++n] = Line(X[(k + 1) % nx],X[k]);
          L[++n] = Line(X[k],Point(-1,-1));
          ans -= hp_intersect();
        }
      }
    }
  }
  return ans;
}
double work(double l,double r,double y_l,double y_mid,double y_r,double eps){
  double mid = (l + r) / 2;
  double y_lmid = calc((l + mid) / 2), y_rmid = calc((mid + r) / 2);
  double s = (r - l) * (y_l + 4 * y_mid + y_r) / 6;
  double s1 = (mid - l) * (y_l + 4 * y_lmid + y_mid) / 6;
  double s2 = (r - mid) * (y_mid + 4 * y_rmid + y_r) / 6;
  if(abs(s1 + s2 - s) < 15 * eps) return s1 + s2 + (s1 + s2 - s) / 15;
  return work(l,mid,y_l,y_lmid,y_mid,eps / 2) + work(mid,r,y_mid,y_rmid,y_r,eps / 2);
}
vector <double> xs;
int t;
void solve(){
  sort(xs.begin(),xs.end());
  if(t == 20){
    printf("%.6f\n",work(xs.front() + EPS,xs.back() - EPS,calc(xs.front() + EPS),calc((xs.front() + xs.back()) / 2),calc(xs.back() - EPS),1e-7));
    return;
  }
  double ans = 0;
  for(int i = 0;i < (int)xs.size() - 1;i++){
    if(xs[i] + 1e-11 < xs[i + 1] - 1e-11)
      ans += work(xs[i] + 1e-11,xs[i + 1] - 1e-11,calc(xs[i] + 1e-11),calc((xs[i] + xs[i + 1]) / 2),calc(xs[i + 1] - 1e-11),1e-9);
  }
  printf("%.6f\n",ans);
}
int main(){
  while(~scanf("%d",&nx) && nx){
    t++;
    X.resize(nx);
    for(int i = 0;i < nx;i++) scanf("%lf%lf",&X[i].x,&X[i].y);
    scanf("%d",&ny);
    Y.resize(ny);
    for(int i = 0;i < ny;i++){
      scanf("%lf%lf",&Y[i].y,&Y[i].x);
      xs.push_back(Y[i].x);
    }
    reverse(Y.begin(),Y.end());
    scanf("%d",&nz);
    Z.resize(nz);
    for(int i = 0;i < nz;i++){
      scanf("%lf%lf",&Z[i].x,&Z[i].y);
      xs.push_back(Z[i].x);
    }
    solve();
  }
  return 0;
}

