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<complex>
#include<vector>
#include<iostream>
#include<stack>
#include<cmath>
#include<map>

enum CCW{FRONT=0x01,RIGHT=0x02,BACK=0x04,LEFT=0x08,OVER=0x10};
enum CIRCLE_RELATION{CIRCLE_SAME=0x01,CIRCLE_CONTAIN=0x02,
		     CIRCLE_NO_CROSS=0x04,CIRCLE_ONE_CROSS=0x08,
		     CIRCLE_ONE_INSIDE_CROSS=0x10,CIRCLE_TWO_CROSS=0x20};
#define sc second
#define fr first

#define REP(i,n) for(int i = 0; i < (int)(n); ++i)

using namespace std;

typedef double elem;
typedef complex<elem> point, vec;
typedef pair<point, point> line, hline, seg, pp;

const double infty = 1e40;
const double eps = 1.0e-8;
const double pi = acos(-1.0);
point base(0,0);

// lZ
inline elem sq(elem a){ return a*a; }
inline elem cq(elem a){ return a*a*a; }

// pxÏ·
elem rad(elem deg){ return (deg/180)*pi; }
elem deg(elem rad){ return (rad*180)/pi; }

// ®¬_Ìô¢AÈÇ
bool eq(elem a, elem b){ return abs(a-b) < eps; }
bool eqv(vec a, vec b){ return eq( abs(b-a),0); }

// _Iy[^
bool far(point a, point b){ return abs(b-a)>0; }
bool near(point a, point b){ return abs(b-a)<=0; }
elem dot(vec a, vec b){ return (a.real() * b.real() + a.imag() * b.imag() ); }
elem cross(vec a, vec b){ return ( a.real() * b.imag() - a.imag() * b.real() ); }

// a©çbÜÅvñèÌpxAàpA]ñ]
elem varg(vec a, vec b){
  elem ret=arg(a)-arg(b);
  if(ret<0)ret+=2*pi;
  if(ret>2*pi)ret-=2*pi;
  if(eq(ret,2*pi))ret=0;
  return ret;
}
elem varg2(vec a, vec b){
  elem ret = varg(a,b);
  if(ret>pi)return 2*pi-ret;
  return ret;
}
elem arg(vec a, vec b){ return acos( dot(a,b) / ( abs(a) * abs(b) ) ); }
point rot(point p, elem theta){ return p * polar((elem)1.0, theta); }
point rotdeg(point p, elem deg){ return p * polar((elem)1.0, rad(deg)); }
point proj(line l, point p){
  double t=dot(p-l.first,l.first-l.second)/abs(l.first-l.second);
  return l.first + t*(l.first-l.second);
}
point reflect(line l, point p){ return p+2.0*(proj(l,p)-p); }

// ñ_Ô£A¼üÆ_ÌÅZ£AüªÆ_ÌÅZ£
elem dist(point a, point b){ return abs(a-b); }
elem dist_l(line l, point x){ return abs(cross(l.sc-l.fr,x-l.fr)) / abs(l.sc-l.fr); }
elem dist_seg(seg s, point x)
{
  if( dot(s.sc-s.fr,x-s.fr)<0 ) return abs(x-s.fr);
  if( dot(s.fr-s.sc,x-s.sc)<0 ) return abs(x-s.sc);
  return dist_l(s,x);
}

// PÊxNgA@üxNgAPÊ@üxNg
vec uvec(vec a){ return a / abs(a); }
vec nmr(vec a){ return a * vec(0,-1); }
vec nml(vec a){ return a * vec(0,1); }
vec unmr(vec a){ return uvec( nmr(a) ); }
vec unml(vec a){ return uvec( nml(a) ); }

// ¼ðA½s»è
bool orth(point a1, point a2, point b1, point b2){ return eq( dot( a2 - a1, b2 - b1 ), 0 ); }
bool orth(vec v1, vec v2){ return eq( dot(v1, v2), 0 ); }
bool prll(point a1, point a2, point b1, point b2){ return eq( cross( a2 - a1, b2 - b1 ), 0 ); }
bool prll(vec v1, vec v2){ return eq( cross(v1, v2), 0 ); }

// CCW oXg¾ªA¸xÉæé
inline int ccw(const point &a, point b, point x){
  b -= a;
  x -= a;
  if( eq(cross(b,x),0.0) && dot(b,x) < 0 ) return BACK;
  if( eq(cross(b,x),0.0) && abs(b) < abs(x) ) return FRONT;
  if( eq(cross(b,x),0.0) ) return OVER;
  if( cross(b,x) > 0 ) return LEFT;
  if( cross(b,x) < 0 ) return RIGHT;
}

// üªg£
line expandLine(line l, elem mag){
  line ret = l;
  vec vf(l.first - l.second);
  vec vs(l.second - l.first);
  ret.first = l.second + mag * vf;
  ret.second = l.first + mag * vs;
  return ret;
}

// üªÌð·»è
inline bool intersectedSS(const seg &a, const seg &b)
{
  int cwaf=ccw(a.fr,a.sc,b.fr);
  int cwbf=ccw(b.fr,b.sc,a.fr);
  int cwas=ccw(a.fr,a.sc,b.sc);
  int cwbs=ccw(b.fr,b.sc,a.sc);
  if( cwaf==OVER || cwas==OVER || cwbf==OVER || cwbs==OVER ) return true;
  return ( cwaf | cwas ) == (LEFT|RIGHT) && ( cwbf | cwbs ) == (LEFT|RIGHT);
}

// ¼üÌð·»è
bool intersectedLL(line a, line b){ return !eq( cross(a.sc-a.fr,b.sc-b.fr), 0.0 ); }

// ð_vZ
point intersectionSS(seg a, seg b)
{
  elem d1 = dist_l(b,a.fr);
  elem d2 = dist_l(b,a.sc);
  return a.fr + ( d1 / (d1 + d2 ) ) * (a.sc-a.fr);
}
point intersectionLL(line a, line b)
{
  vec va = a.sc - a.fr;
  vec vb = b.sc - b.fr;
  return a.fr + va * ( cross(vb, b.fr - a.fr) / cross(vb,va) );
}

// üªð_êÅ
bool intersectionLL(line a, line b, point &ret){
  return intersectedLL( a, b ) ? ret = intersectionLL( a, b ), true : false;
}
bool intersectionLH(line a, hline b, point &ret){
  point tmp;
  return intersectionLL(a,b,tmp) ? ( ccw(b.fr,b.sc,tmp)&(OVER|FRONT) ? ret=tmp, true : false ) : false;
}
bool intersectionLS(line l, seg s, point &ret){
  point tmp;
  return intersectionLL(l,s,tmp) ? ( ccw(s.fr,s.sc,tmp)&OVER ? ret=tmp, true : false ) : false;
}
bool intersectionHH(hline a, hline b, point &ret){
  point tmp;
  return intersectionLL(a,b,tmp) ? ( ccw(a.fr,a.sc,tmp)&(OVER|FRONT)&&ccw(b.fr,b.sc,tmp)&(OVER|FRONT) ? ret = tmp, true : false ) : false;
}
bool intersectionHS(hline a, seg s, point &ret){
  point tmp;
  return intersectionLS(a,s,tmp) ? ( ccw(a.fr,a.sc,tmp)&(OVER|FRONT) ? ret = tmp, true : false ) : false;
}
bool intersectionSS(seg a, seg b, point &ret){
  return intersectedSS(a,b) ? ret = intersectionSS(a,b), true : false;
}

pair<int, pair<double,double> > getLH(double x, const vector<point> &v)
{
  point a,b;
  int cnt=0;
  line l(point(x,0),point(x,1));
  for(int i = 0; i < (int)v.size(); ++i){
    point is;
    if( intersectionLS( l, seg(v[i],v[(i+1)%v.size()]), is ) ){
      if(cnt==0){
	a = is;
	++cnt;
      }else if( far(is,a) ){
	b = is;
	++cnt;
      }
    }
  }
  if(cnt==1)b=a;
  if( a.imag() > b.imag() ) swap( a, b );
  return make_pair( cnt, make_pair(a.imag(), b.imag() ) );
}

struct point3{
  double x,y,z;
  point3(double x, double y, double z):x(x),y(y),z(z){}
  point3 operator-(const point3 &t){
    return point3(x-t.x,y-t.y,z-t.z);
  }
  point3 operator+(const point3 &t){
    return point3(x+t.x,y+t.y,z+t.z);
  }
};

ostream &operator<<(ostream &oss, const point3 &t)
{
  oss << '('<<t.x <<','<< t.y<<','<<t.z<<')';
  return oss;
}

double dot3(point3 a, point3 b){
  return a.x*b.x + a.y*b.y + a.z*b.z;
}
point3 cross3(point3 a, point3 b){
  return point3(a.y*b.z-b.y*a.z, a.z*b.x-b.z*a.x, a.x*b.y-b.x*a.y);
}

double tetrahedronVolume(point3 a, point3 b, point3 c, point3 d)
{
  point3 A=b-a;
  point3 B=c-a;
  point3 C=d-a;
  return abs(dot3(A,cross3(B,C))/6);
}
double getVolume( const vector<point3> &V1, const vector<point3> &V2 )
{
  double ret=0;
  vector<point3> v1 = V1;
  vector<point3> v2 = V2;
  if( v2.size() < v1.size() ){
    swap( v1, v2 );
  }
  if(v1.size()==1){
    if(v2.size()==2){
      ret = 0;
    }else if(v2.size()==4){
      ret+=tetrahedronVolume(v1[0],v2[0],v2[1],v2[2]);
      ret+=tetrahedronVolume(v1[0],v2[2],v2[3],v2[0]);
    }
  }else if(v1.size()==2){
    if(v2.size()==2){
      ret = tetrahedronVolume(v1[0],v1[1],v2[0],v2[1]);
    }else{
      if(eq(v1[0].y,v1[1].y)){
	ret += tetrahedronVolume( v1[1],v1[0],v2[1],v2[2] );
	ret += tetrahedronVolume( v1[0],v2[0],v2[1],v2[2] );
	ret += tetrahedronVolume( v1[0],v2[2],v2[3],v2[0] );
      }else{
	ret += tetrahedronVolume( v1[1],v1[0],v2[2],v2[3] );
	ret += tetrahedronVolume( v1[0],v2[0],v2[1],v2[2] );
	ret += tetrahedronVolume( v1[0],v2[2],v2[3],v2[0] );
      }
    }
  }else{
    ret += tetrahedronVolume( v1[1],v1[0],v2[1],v1[2] );
    ret += tetrahedronVolume( v2[0],v1[0],v2[3],v2[1] );
    ret += tetrahedronVolume( v1[3],v1[0],v1[2],v2[3] );

    ret += tetrahedronVolume( v2[2],v2[3],v2[1],v1[2] );
    ret += tetrahedronVolume( v1[0],v1[2],v2[1],v2[3] );
  }
  return ret;
}

int main()
{
  int m,n;
  while(scanf("%d%d", &m, &n) && m && n){
    double x,y;
    double res = 0;
    vector<point> P1;
    vector<point> P2;
    int minx1=1000,maxx1=-1000;
    int minx2=1000,maxx2=-1000;
    map<int,pair<double,double> > vx;
    for(int i = 0; i < m; ++i){
      scanf("%lf%lf", &x, &y);
      P1.push_back(point(x,y));
      vx[(int)x]=make_pair(0,0);
      minx1 = min( (int)x, minx1 );
      maxx1 = max( (int)x, maxx1 );
    }
    for(int i = 0; i < n; ++i){
      scanf("%lf%lf", &x, &y);
      P2.push_back(point(x,y));
      minx2 = min( (int)x, minx2 );
      maxx2 = max( (int)x, maxx2 );
      vx[(int)x]=make_pair(0,0);
    }
  retry:;
    for(map<int,pair<double,double> >::iterator itm = vx.begin(); itm != vx.end(); ++itm){
      pair<int, pair<double,double > > LH = getLH( itm->first, P1);
      if( !(  minx1 <= itm->first && itm->first <= maxx1 &&
	      minx2 <= itm->first && itm->first <= maxx2 ) ){
	vx.erase(itm);
	goto retry;
      }
      if( LH.first == 0 ){
	vx.erase(itm);
	goto retry;
      }else{
	itm->second = LH.second;
      }
    }
    vector< vector<point3> > V;
    for(map<int,pair<double,double> >::iterator itm = vx.begin(); itm != vx.end(); ++itm){
      vector<point3> vpx;
      double x = itm->first;
      double y1 = itm->second.first;
      double y2 = itm->second.second;

      if( eq(y1,y2) ){
	pair<int,pair<double,double> > Z = getLH( x, P2 );
	double z1 = Z.second.first;
	double z2 = Z.second.second;
	if( eq(z1,z2) ){
	  vpx.push_back( point3( x,y1,z1 ) );
	}else{
	  vpx.push_back( point3( x,y1,z1 ) );
	  vpx.push_back( point3( x,y1,z2 ) );
	}
      }else{
	pair<int,pair<double,double> > Z = getLH( x, P2 );
	double z1 = Z.second.first;
	double z2 = Z.second.second;
	if( eq(z1,z2) ){
	  vpx.push_back( point3( x,y1,z1 ) );
	  vpx.push_back( point3( x,y2,z1 ) );
	}else{
	  vpx.push_back( point3( x,y1,z1 ) );
	  vpx.push_back( point3( x,y1,z2 ) );
	  vpx.push_back( point3( x,y2,z2 ) );
	  vpx.push_back( point3( x,y2,z1 ) );
	}
      }
      
      /*
      for(int i = 0; i < (int)vpx.size(); ++i){
	cout << vpx[i] << ' ';
      }
      cout << endl;
      */

      V.push_back( vpx );
    }
    for(int i = 0; i < (int)V.size()-1; ++i){
      //cout << i << ' ' << i+1 << endl;
      res += getVolume(V[i], V[i+1]);
    }
    printf("%.13lf\n", res);
    //return 0;
  }
  return 0;
}