diff -urN ppl-0.9/demos/ppl_lcdd/ppl_lcdd.cc ppl-0.9-new/demos/ppl_lcdd/ppl_lcdd.cc
--- ppl-0.9/demos/ppl_lcdd/ppl_lcdd.cc	2006-02-11 10:56:08.000000000 +0100
+++ ppl-0.9-new/demos/ppl_lcdd/ppl_lcdd.cc	2008-05-06 13:02:22.000000000 +0200
@@ -88,7 +88,7 @@
 #endif
 
 #include "timings.hh"
-#include <gmpxx.h>
+#include "biginteger.hh"
 #include <vector>
 #include <set>
 #include <cstdarg>
@@ -442,7 +442,7 @@
 	    denominator.get_mpz_t(),
 	    source[i].get_den().get_mpz_t());
   for (unsigned i = 0; i < n; ++i)
-    dest[i] = denominator*source[i];
+	  dest[i] = mpz_class(denominator*source[i]);
 }
 
 template <typename T>
Files ppl-0.9/doc/fdl.pdf and ppl-0.9-new/doc/fdl.pdf differ
Files ppl-0.9/doc/fdl.ps.gz and ppl-0.9-new/doc/fdl.ps.gz differ
Files ppl-0.9/doc/gpl.pdf and ppl-0.9-new/doc/gpl.pdf differ
Files ppl-0.9/doc/gpl.ps.gz and ppl-0.9-new/doc/gpl.ps.gz differ
Files ppl-0.9/doc/ppl-user-0.9-html.tar.gz and ppl-0.9-new/doc/ppl-user-0.9-html.tar.gz differ
Files ppl-0.9/doc/ppl-user-0.9.pdf and ppl-0.9-new/doc/ppl-user-0.9.pdf differ
Files ppl-0.9/doc/ppl-user-0.9.ps.gz and ppl-0.9-new/doc/ppl-user-0.9.ps.gz differ
diff -urN ppl-0.9/src/GMP_Integer.inlines.hh ppl-0.9-new/src/GMP_Integer.inlines.hh
--- ppl-0.9/src/GMP_Integer.inlines.hh	2006-02-14 13:34:25.000000000 +0100
+++ ppl-0.9-new/src/GMP_Integer.inlines.hh	2008-05-06 12:53:36.000000000 +0200
@@ -75,11 +75,6 @@
   mpz_sqrt(x.get_mpz_t(), y.get_mpz_t());
 }
 
-inline int
-cmp(const GMP_Integer& x, const GMP_Integer& y) {
-  return mpz_cmp(x.get_mpz_t(), y.get_mpz_t());
-}
-
 inline const mpz_class&
 raw_value(const GMP_Integer& x) {
   return x;
diff -urN ppl-0.9/src/GMP_Integer.types.hh ppl-0.9-new/src/GMP_Integer.types.hh
--- ppl-0.9/src/GMP_Integer.types.hh	2006-01-17 12:31:16.000000000 +0100
+++ ppl-0.9-new/src/GMP_Integer.types.hh	2008-05-06 12:47:26.000000000 +0200
@@ -13,7 +13,7 @@
 #define PPL_GMP_Integer_types_hh 1
 
 #include "Coefficient_traits_template.hh"
-#include <gmpxx.h>
+#include "biginteger.hh"
 
 namespace Parma_Polyhedra_Library {
 
diff -urN ppl-0.9/src/Interval.defs.hh ppl-0.9-new/src/Interval.defs.hh
--- ppl-0.9/src/Interval.defs.hh	2006-01-17 12:31:16.000000000 +0100
+++ ppl-0.9-new/src/Interval.defs.hh	2008-05-06 12:48:06.000000000 +0200
@@ -26,7 +26,7 @@
 #include "Interval.types.hh"
 #include "Coefficient.defs.hh"
 #include "Checked_Number.defs.hh"
-#include <gmpxx.h>
+#include "biginteger.hh"
 #include <iosfwd>
 
 namespace Parma_Polyhedra_Library {
diff -urN ppl-0.9/src/biginteger.hh ppl-0.9-new/src/biginteger.hh
--- ppl-0.9/src/biginteger.hh	1970-01-01 01:00:00.000000000 +0100
+++ ppl-0.9-new/src/biginteger.hh	2008-05-06 12:53:18.000000000 +0200
@@ -0,0 +1,4806 @@
+//
+// biginteger.hh
+//
+// This file is copyright (C) 2008, Heiko Wundram. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+// 1. Redistributions of source code must retain the above copyright
+//    notice, this list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright
+//    notice, this list of conditions and the following disclaimer in the
+//    documentation and/or other materials provided with the distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+// SUCH DAMAGE.
+//
+
+
+#ifndef BIGINTEGER_HH
+#define BIGINTEGER_HH
+
+
+//
+// Includes
+//
+
+#include <algorithm>
+#include <climits>
+#include <cstddef>
+#include <gmp.h>
+#include <istream>
+#include <ostream>
+#include <stdexcept>
+#include <string>
+#include <typeinfo>
+
+
+//
+// Library namespace
+//
+
+namespace Parma_Polyhedra_Library
+{
+
+	class BigInteger;
+	class BigRational;
+
+	namespace detail
+	{
+
+		template < class Expr >
+		struct BIX;
+
+		namespace MPZ
+		{
+
+			template < class src1, class src2 >
+			struct Add;
+
+			template < class src1, class src2 >
+			struct Sub;
+
+			template < class src1, class src2 >
+			struct Mul;
+
+			template < class src1, class src2 >
+			struct Div;
+
+			template < class src1, class src2 >
+			struct Mod;
+
+			template < class src1, class src2 >
+			struct And;
+
+			template < class src1, class src2 >
+			struct Ior;
+
+			template < class src1, class src2>
+			struct Xor;
+
+			template < class src1, class src2 >
+			struct Lshift;
+
+			template < class src1, class src2 >
+			struct Rshift;
+
+			template < class src1, class src2 >
+			struct Cmp;
+
+			template < class src1, class src2 >
+			struct Equal;
+
+			template < class src >
+			struct Neg;
+
+			template < class src >
+			struct Inv;
+
+			template < class src >
+			struct Abs;
+
+			template < class src >
+			struct Sqrt;
+
+			struct Sgn;
+
+			template <>
+			struct Add<mpz_srcptr,long>
+			{
+
+				static inline void eval(mpz_ptr dst, mpz_srcptr val1, long val2)
+				{
+					if( val2 >= 0 )
+						mpz_add_ui(dst,val1,val2);
+					else
+						mpz_sub_ui(dst,val1,-val2);
+				}
+
+			};
+
+			template <>
+			struct Sub<mpz_srcptr,long>
+			{
+
+				static inline void eval(mpz_ptr dst, mpz_srcptr val1, long val2)
+				{
+					if( val2 >= 0 )
+						mpz_sub_ui(dst,val1,val2);
+					else
+						mpz_add_ui(dst,val1,-val2);
+				}
+
+			};
+
+			template <>
+			struct Mul<mpz_srcptr,long>
+			{
+
+				static inline void eval(mpz_ptr dst, mpz_srcptr val1, long val2)
+				{
+					mpz_mul_si(dst,val1,val2);
+				}
+
+			};
+
+			template <>
+			struct Div<mpz_srcptr,long>
+			{
+
+				static inline void eval(mpz_ptr dst, mpz_srcptr val1, long val2)
+				{
+					if( val2 >= 0 )
+						mpz_tdiv_q_ui(dst,val1,val2);
+					else {
+						mpz_tdiv_q_ui(dst,val1,-val2);
+						mpz_neg(dst,dst);
+					}
+				}
+
+			};
+
+			template <>
+			struct Mod<mpz_srcptr,long>
+			{
+
+				static inline void eval(mpz_ptr dst, mpz_srcptr val1, long val2)
+				{
+					if( val2 >= 0 )
+						mpz_tdiv_r_ui(dst,val1,val2);
+					else
+						mpz_tdiv_r_ui(dst,val1,-val2);
+				}
+
+			};
+
+			template <>
+			struct And<mpz_srcptr,long>
+			{
+
+				static inline void eval(mpz_ptr dst, mpz_srcptr val1, long val2)
+				{
+					mpz_set_si(dst,mpz_get_si(val1)&val2);
+				}
+
+			};
+
+			template <>
+			struct Ior<mpz_srcptr,long>
+			{
+
+				static inline void eval(mpz_ptr dst, mpz_srcptr val1, long val2)
+				{
+					if( dst != val1 ) {
+						mpz_set_si(dst,val2);
+						mpz_ior(dst,val1,dst);
+					} else {
+						mpz_t tmp;
+						mpz_init_set_si(tmp,val2);
+						mpz_ior(dst,val1,tmp);
+						mpz_clear(tmp);
+					}
+				}
+
+			};
+
+			template <>
+			struct Xor<mpz_srcptr,long>
+			{
+
+				static inline void eval(mpz_ptr dst, mpz_srcptr val1, long val2)
+				{
+					if( dst != val1 ) {
+						mpz_set_si(dst,val2);
+						mpz_xor(dst,val1,dst);
+					} else {
+						mpz_t tmp;
+						mpz_init_set_si(tmp,val2);
+						mpz_xor(dst,val1,tmp);
+						mpz_clear(tmp);
+					}
+				}
+
+			};
+
+			template <>
+			struct Lshift<mpz_srcptr,long>
+			{
+
+				static inline void eval(mpz_ptr dst, mpz_srcptr val1, long val2)
+				{
+					if( val2 >= 0 )
+						mpz_mul_2exp(dst,val1,val2);
+					else
+						mpz_tdiv_q_2exp(dst,val1,-val2);
+				}
+
+			};
+
+			template <>
+			struct Rshift<mpz_srcptr,long>
+			{
+
+				static inline void eval(mpz_ptr dst, mpz_srcptr val1, long val2)
+				{
+					if( val2 >= 0 )
+						mpz_tdiv_q_2exp(dst,val1,val2);
+					else
+						mpz_mul_2exp(dst,val1,-val2);
+				}
+
+			};
+
+			template <>
+			struct Cmp<mpz_srcptr,long>
+			{
+
+				static inline int eval(mpz_srcptr val1, long val2)
+				{
+					return mpz_cmp_si(val1,val2);
+				}
+
+			};
+
+			template <>
+			struct Equal<mpz_srcptr,long> :
+				Cmp<mpz_srcptr,long>
+			{
+
+				static inline bool eval(mpz_srcptr val1, long val2)
+				{
+					return !Cmp<mpz_srcptr,long>::eval(val1,val2);
+				}
+
+			};
+
+			template <>
+			struct Add<long,mpz_srcptr>
+			{
+
+				static inline void eval(mpz_ptr dst, long val1, mpz_srcptr val2)
+				{
+					if( val1 >= 0 )
+						mpz_add_ui(dst,val2,val1);
+					else
+						mpz_sub_ui(dst,val2,-val1);
+				}
+
+			};
+
+			template <>
+			struct Sub<long,mpz_srcptr>
+			{
+
+				static inline void eval(mpz_ptr dst, long val1, mpz_srcptr val2)
+				{
+					if( val1 >= 0 )
+						mpz_ui_sub(dst,val1,val2);
+					else {
+						mpz_add_ui(dst,val2,-val1);
+						mpz_neg(dst,dst);
+					}
+				}
+
+			};
+
+			template <>
+			struct Mul<long,mpz_srcptr>
+			{
+
+				static inline void eval(mpz_ptr dst, long val1, mpz_srcptr val2)
+				{
+					mpz_mul_si(dst,val2,val1);
+				}
+
+			};
+
+			template <>
+			struct Div<long,mpz_srcptr>
+			{
+
+				static inline void eval(mpz_ptr dst, long val1, mpz_srcptr val2)
+				{
+					if( mpz_fits_slong_p(val2) )
+						mpz_set_si(dst,val1/mpz_get_si(val2));
+					else
+						mpz_set_si(dst,!mpz_cmpabs_ui(val2,val1>=0?val1:-val1)?
+								   -1:0);
+				}
+
+			};
+
+			template <>
+			struct Mod<long,mpz_srcptr>
+			{
+
+				static inline void eval(mpz_ptr dst, long val1, mpz_srcptr val2)
+				{
+					if( mpz_fits_slong_p(val2) )
+						mpz_set_si(dst,val1%mpz_get_si(val2));
+					else
+						mpz_set_si(dst,!mpz_cmpabs_ui(val2,val1>=0?val1:-val1)?
+								   0:val1);
+				}
+
+			};
+
+			template <>
+			struct And<long,mpz_srcptr>
+			{
+
+				static inline void eval(mpz_ptr dst, long val1, mpz_srcptr val2)
+				{
+					mpz_set_si(dst,val1&mpz_get_si(val2));
+				}
+
+			};
+
+			template <>
+			struct Ior<long,mpz_srcptr>
+			{
+
+				static inline void eval(mpz_ptr dst, long val1, mpz_srcptr val2)
+				{
+					if( dst != val2 ) {
+						mpz_set_si(dst,val1);
+						mpz_ior(dst,dst,val2);
+					} else {
+						mpz_t tmp;
+						mpz_init_set_si(tmp,val1);
+						mpz_ior(dst,tmp,val2);
+						mpz_clear(tmp);
+					}
+				}
+
+			};
+
+			template <>
+			struct Xor<long,mpz_srcptr>
+			{
+
+				static inline void eval(mpz_ptr dst, long val1, mpz_srcptr val2)
+				{
+					if( dst != val2 ) {
+						mpz_set_si(dst,val1);
+						mpz_xor(dst,dst,val2);
+					} else {
+						mpz_t tmp;
+						mpz_init_set_si(tmp,val1);
+						mpz_xor(dst,tmp,val2);
+						mpz_clear(tmp);
+					}
+				}
+
+			};
+
+			template <>
+			struct Lshift<long,mpz_srcptr>
+			{
+
+				static inline void eval(mpz_ptr dst, long val1, mpz_srcptr val2)
+				{
+					if( mpz_sgn(val2) >= 0 ) {
+						unsigned long shift = mpz_get_ui(val2);
+						mpz_set_si(dst,val1);
+						mpz_mul_2exp(dst,dst,shift);
+					} else
+						mpz_set_si(dst,val1>>std::max(mpz_get_ui(val2),
+													  sizeof(long)*8ul));
+				}
+
+			};
+
+			template <>
+			struct Rshift<long,mpz_srcptr>
+			{
+
+				static inline void eval(mpz_ptr dst, long val1, mpz_srcptr val2)
+				{
+					if( mpz_sgn(val2) >= 0 )
+						mpz_set_si(dst,val1>>std::max(mpz_get_ui(val2),
+													  sizeof(long)*8ul));
+					else {
+						unsigned long shift = mpz_get_ui(val2);
+						mpz_set_si(dst,val1);
+						mpz_mul_2exp(dst,dst,shift);
+					}
+				}
+				
+			};
+
+			template <>
+			struct Cmp<long,mpz_srcptr>
+			{
+
+				static inline int eval(long val1, mpz_srcptr val2)
+				{
+					return -mpz_cmp_si(val2,val1);
+				}
+
+			};
+
+			template <>
+			struct Equal<long,mpz_srcptr> :
+				Cmp<long,mpz_srcptr>
+			{
+
+				static inline bool eval(long val1, mpz_srcptr val2)
+				{
+					return !Cmp<long,mpz_srcptr>::eval(val1,val2);
+				}
+
+			};
+
+			template <>
+			struct Add<mpz_srcptr,unsigned long>
+			{
+
+				static inline void eval(mpz_ptr dst, mpz_srcptr val1,
+										unsigned long val2)
+				{
+					mpz_add_ui(dst,val1,val2);
+				}
+
+			};
+
+			template <>
+			struct Sub<mpz_srcptr,unsigned long>
+			{
+
+				static inline void eval(mpz_ptr dst, mpz_srcptr val1,
+										unsigned long val2)
+				{
+					mpz_sub_ui(dst,val1,val2);
+				}
+
+			};
+
+			template <>
+			struct Mul<mpz_srcptr,unsigned long>
+			{
+
+				static inline void eval(mpz_ptr dst, mpz_srcptr val1,
+										unsigned long val2)
+				{
+					mpz_mul_ui(dst,val1,val2);
+				}
+
+			};
+
+			template <>
+			struct Div<mpz_srcptr,unsigned long>
+			{
+
+				static inline void eval(mpz_ptr dst, mpz_srcptr val1,
+										unsigned long val2)
+				{
+					mpz_tdiv_q_ui(dst,val1,val2);
+				}
+
+			};
+
+			template <>
+			struct Mod<mpz_srcptr,unsigned long>
+			{
+
+				static inline void eval(mpz_ptr dst, mpz_srcptr val1,
+										unsigned long val2)
+				{
+					mpz_tdiv_r_ui(dst,val1,val2);
+				}
+
+			};
+
+			template <>
+			struct And<mpz_srcptr,unsigned long>
+			{
+
+				static inline void eval(mpz_ptr dst, mpz_srcptr val1,
+										unsigned long val2)
+				{
+					mpz_set_ui(dst,mpz_get_ui(val1)&val2);
+				}
+
+			};
+
+			template <>
+			struct Ior<mpz_srcptr,unsigned long>
+			{
+
+				static inline void eval(mpz_ptr dst, mpz_srcptr val1,
+										unsigned long val2)
+				{
+					if( dst != val1 ) {
+						mpz_set_ui(dst,val2);
+						mpz_ior(dst,val1,dst);
+					} else {
+						mpz_t tmp;
+						mpz_init_set_ui(tmp,val2);
+						mpz_ior(dst,val1,tmp);
+						mpz_clear(tmp);
+					}
+				}
+
+			};
+
+			template <>
+			struct Xor<mpz_srcptr,unsigned long>
+			{
+
+				static inline void eval(mpz_ptr dst, mpz_srcptr val1,
+										unsigned long val2)
+				{
+					if( dst != val1 ) {
+						mpz_set_ui(dst,val2);
+						mpz_xor(dst,val1,dst);
+					} else {
+						mpz_t tmp;
+						mpz_init_set_ui(tmp,val2);
+						mpz_xor(dst,val1,tmp);
+						mpz_clear(tmp);
+					}
+				}
+
+			};
+
+			template <>
+			struct Lshift<mpz_srcptr,unsigned long>
+			{
+
+				static inline void eval(mpz_ptr dst, mpz_srcptr val1,
+										unsigned long val2)
+				{
+					mpz_mul_2exp(dst,val1,val2);
+				}
+
+			};
+
+			template <>
+			struct Rshift<mpz_srcptr,unsigned long>
+			{
+
+				static inline void eval(mpz_ptr dst, mpz_srcptr val1,
+										unsigned long val2)
+				{
+					mpz_tdiv_q_2exp(dst,val1,val2);
+				}
+
+			};
+
+			template <>
+			struct Cmp<mpz_srcptr,unsigned long>
+			{
+
+				static inline int eval(mpz_srcptr val1, unsigned long val2)
+				{
+					return mpz_cmp_ui(val1,val2);
+				}
+
+			};
+
+			template <>
+			struct Equal<mpz_srcptr,unsigned long> :
+				Cmp<mpz_srcptr,unsigned long>
+			{
+
+				static inline bool eval(mpz_srcptr val1, unsigned long val2)
+				{
+					return !Cmp<mpz_srcptr,unsigned long>::eval(val1,val2);
+				}
+
+			};
+
+			template <>
+			struct Add<unsigned long,mpz_srcptr>
+			{
+
+				static inline void eval(mpz_ptr dst, unsigned long val1,
+										mpz_srcptr val2)
+				{
+					mpz_add_ui(dst,val2,val1);
+				}
+
+			};
+
+			template <>
+			struct Sub<unsigned long,mpz_srcptr>
+			{
+
+				static inline void eval(mpz_ptr dst, unsigned long val1,
+										mpz_srcptr val2)
+				{
+					mpz_ui_sub(dst,val1,val2);
+				}
+
+			};
+
+			template <>
+			struct Mul<unsigned long,mpz_srcptr>
+			{
+
+				static inline void eval(mpz_ptr dst, unsigned long val1,
+										mpz_srcptr val2)
+				{
+					mpz_mul_ui(dst,val2,val1);
+				}
+
+			};
+
+			template <>
+			struct Div<unsigned long,mpz_srcptr>
+			{
+
+				static inline void eval(mpz_ptr dst, unsigned long val1,
+										mpz_srcptr val2)
+				{
+					if( mpz_cmpabs_ui(val2,ULONG_MAX) <= 0 ) {
+						if( mpz_sgn(val2) >= 0 )
+							mpz_set_ui(dst,val1/mpz_get_ui(val2));
+						else {
+							mpz_set_ui(dst,val1/mpz_get_ui(val2));
+							mpz_neg(dst,dst);
+						}
+					} else
+						mpz_set_ui(dst,0);
+				}
+
+			};
+
+			template <>
+			struct Mod<unsigned long,mpz_srcptr>
+			{
+
+				static inline void eval(mpz_ptr dst, unsigned long val1,
+										mpz_srcptr val2)
+				{
+					if( mpz_cmpabs_ui(val2,ULONG_MAX) <= 0 )
+						mpz_set_ui(dst,val1%mpz_get_ui(val2));
+					else
+						mpz_set_ui(dst,val1);
+				}
+
+			};
+
+			template <>
+			struct And<unsigned long,mpz_srcptr>
+			{
+
+				static inline void eval(mpz_ptr dst, unsigned long val1,
+										mpz_srcptr val2)
+				{
+					mpz_set_ui(dst,val1&mpz_get_ui(val2));
+				}
+
+			};
+
+			template <>
+			struct Ior<unsigned long,mpz_srcptr>
+			{
+
+				static inline void eval(mpz_ptr dst, unsigned long val1,
+										mpz_srcptr val2)
+				{
+					if( dst != val2 ) {
+						mpz_set_ui(dst,val1);
+						mpz_ior(dst,dst,val2);
+					} else {
+						mpz_t tmp;
+						mpz_init_set_ui(tmp,val1);
+						mpz_ior(dst,tmp,val2);
+						mpz_clear(tmp);
+					}
+				}
+
+			};
+
+			template <>
+			struct Xor<unsigned long,mpz_srcptr>
+			{
+
+				static inline void eval(mpz_ptr dst, unsigned long val1,
+										mpz_srcptr val2)
+				{
+					if( dst != val2 ) {
+						mpz_set_ui(dst,val1);
+						mpz_xor(dst,dst,val2);
+					} else {
+						mpz_t tmp;
+						mpz_init_set_ui(tmp,val1);
+						mpz_xor(dst,tmp,val2);
+						mpz_clear(tmp);
+					}
+				}
+
+			};
+
+			template <>
+			struct Lshift<unsigned long,mpz_srcptr>
+			{
+
+				static inline void eval(mpz_ptr dst, unsigned long val1,
+										mpz_srcptr val2)
+				{
+					if( mpz_sgn(val2) >= 0 ) {
+						unsigned long shift = mpz_get_ui(val2);
+						mpz_set_ui(dst,val1);
+						mpz_mul_2exp(dst,dst,shift);
+					} else
+						mpz_set_ui(dst,val1>>
+								   std::max(mpz_get_ui(val2),
+											sizeof(unsigned long)*8ul));
+				}
+
+			};
+
+			template <>
+			struct Rshift<unsigned long,mpz_srcptr>
+			{
+
+				static inline void eval(mpz_ptr dst, unsigned long val1,
+										mpz_srcptr val2)
+				{
+					if( mpz_sgn(val2) >= 0 )
+						mpz_set_ui(dst,val1>>
+								   std::max(mpz_get_ui(val2),
+											sizeof(unsigned long)*8ul));
+					else {
+						unsigned long shift = mpz_get_ui(val2);
+						mpz_set_ui(dst,val1);
+						mpz_mul_2exp(dst,dst,shift);
+					}
+				}
+
+			};
+
+			template <>
+			struct Cmp<unsigned long,mpz_srcptr>
+			{
+
+				static inline int eval(unsigned long val1, mpz_srcptr val2)
+				{
+					return -mpz_cmp_ui(val2,val1);
+				}
+
+			};
+
+			template <>
+			struct Equal<unsigned long,mpz_srcptr> :
+				Cmp<unsigned long,mpz_srcptr>
+			{
+
+				static inline bool eval(unsigned long val1, mpz_srcptr val2)
+				{
+					return !Cmp<unsigned long,mpz_srcptr>::eval(val1,val2);
+				}
+
+			};
+
+			template <>
+			struct Add<mpz_srcptr,double>
+			{
+
+				static inline void eval(mpz_ptr dst, mpz_srcptr val1,
+										double val2)
+				{
+					if( dst != val1 ) {
+						mpz_set_d(dst,val2);
+						mpz_add(dst,val1,dst);
+					} else {
+						mpz_t tmp;
+						mpz_init_set_d(tmp,val2);
+						mpz_add(dst,val1,tmp);
+						mpz_clear(tmp);
+					}
+				}
+
+			};
+
+			template <>
+			struct Sub<mpz_srcptr,double>
+			{
+
+				static inline void eval(mpz_ptr dst, mpz_srcptr val1,
+										double val2)
+				{
+					if( dst != val1 ) {
+						mpz_set_d(dst,val2);
+						mpz_sub(dst,val1,dst);
+					} else {
+						mpz_t tmp;
+						mpz_init_set_d(tmp,val2);
+						mpz_sub(dst,val1,tmp);
+						mpz_clear(tmp);
+					}
+				}
+
+			};
+
+			template <>
+			struct Mul<mpz_srcptr,double>
+			{
+
+				static inline void eval(mpz_ptr dst, mpz_srcptr val1,
+										double val2)
+				{
+					if( dst != val1 ) {
+						mpz_set_d(dst,val2);
+						mpz_mul(dst,val1,dst);
+					} else {
+						mpz_t tmp;
+						mpz_init_set_d(tmp,val2);
+						mpz_mul(dst,val1,tmp);
+						mpz_clear(tmp);
+					}
+				}
+
+			};
+
+			template <>
+			struct Div<mpz_srcptr,double>
+			{
+
+				static inline void eval(mpz_ptr dst, mpz_srcptr val1,
+										double val2)
+				{
+					if( dst != val1 ) {
+						mpz_set_d(dst,val2);
+						mpz_tdiv_q(dst,val1,dst);
+					} else {
+						mpz_t tmp;
+						mpz_init_set_d(tmp,val2);
+						mpz_tdiv_q(dst,val1,tmp);
+						mpz_clear(tmp);
+					}
+				}
+
+			};
+
+			template <>
+			struct Mod<mpz_srcptr,double>
+			{
+
+				static inline void eval(mpz_ptr dst, mpz_srcptr val1,
+										double val2)
+				{
+					if( dst != val1 ) {
+						mpz_set_d(dst,val2);
+						mpz_tdiv_r(dst,val1,dst);
+					} else {
+						mpz_t tmp;
+						mpz_init_set_d(tmp,val2);
+						mpz_tdiv_r(dst,val1,tmp);
+						mpz_clear(tmp);
+					}
+				}
+
+			};
+
+			template <>
+			struct Cmp<mpz_srcptr,double>
+			{
+
+				static inline int eval(mpz_srcptr val1, double val2)
+				{
+					return mpz_cmp_d(val1,val2);
+				}
+			};
+
+			template <>
+			struct Equal<mpz_srcptr,double> :
+				Cmp<mpz_srcptr,double>
+			{
+
+				static inline bool eval(mpz_srcptr val1, double val2)
+				{
+					return !Cmp<mpz_srcptr,double>::eval(val1,val2);
+				}
+
+			};
+
+			template <>
+			struct Add<double,mpz_srcptr>
+			{
+
+				static inline void eval(mpz_ptr dst, double val1,
+										mpz_srcptr val2)
+				{
+					if( dst != val2 ) {
+						mpz_set_d(dst,val1);
+						mpz_add(dst,dst,val2);
+					} else {
+						mpz_t tmp;
+						mpz_init_set_d(tmp,val1);
+						mpz_add(dst,tmp,val2);
+						mpz_clear(tmp);
+					}
+				}
+
+			};
+
+			template <>
+			struct Sub<double,mpz_srcptr>
+			{
+
+				static inline void eval(mpz_ptr dst, double val1,
+										mpz_srcptr val2)
+				{
+					if( dst != val2 ) {
+						mpz_set_d(dst,val1);
+						mpz_sub(dst,dst,val2);
+					} else {
+						mpz_t tmp;
+						mpz_init_set_d(tmp,val1);
+						mpz_sub(dst,tmp,val2);
+						mpz_clear(tmp);
+					}
+				}
+
+			};
+
+			template <>
+			struct Mul<double,mpz_srcptr>
+			{
+
+				static inline void eval(mpz_ptr dst, double val1,
+										mpz_srcptr val2)
+				{
+					if( dst != val2 ) {
+						mpz_set_d(dst,val1);
+						mpz_mul(dst,dst,val2);
+					} else {
+						mpz_t tmp;
+						mpz_init_set_d(tmp,val1);
+						mpz_mul(dst,tmp,val2);
+						mpz_clear(tmp);
+					}
+				}
+
+			};
+
+			template <>
+			struct Div<double,mpz_srcptr>
+			{
+
+				static inline void eval(mpz_ptr dst, double val1,
+										mpz_srcptr val2)
+				{
+					if( dst != val2 ) {
+						mpz_set_d(dst,val1);
+						mpz_tdiv_q(dst,dst,val2);
+					} else {
+						mpz_t tmp;
+						mpz_init_set_d(tmp,val1);
+						mpz_tdiv_q(dst,tmp,val2);
+						mpz_clear(tmp);
+					}
+				}
+
+			};
+
+			template <>
+			struct Mod<double,mpz_srcptr>
+			{
+
+				static inline void eval(mpz_ptr dst, double val1,
+										mpz_srcptr val2)
+				{
+					if( dst != val2 ) {
+						mpz_set_d(dst,val1);
+						mpz_tdiv_r(dst,dst,val2);
+					} else {
+						mpz_t tmp;
+						mpz_init_set_d(tmp,val1);
+						mpz_tdiv_r(dst,tmp,val2);
+						mpz_clear(tmp);
+					}
+				}
+
+			};
+
+			template <>
+			struct Cmp<double,mpz_srcptr>
+			{
+
+				static inline int eval(double val1, mpz_srcptr val2)
+				{
+					return -mpz_cmp_d(val2,val1);
+				}
+			};
+
+			template <>
+			struct Equal<double,mpz_srcptr> :
+				Cmp<double,mpz_srcptr>
+			{
+
+				static inline bool eval(double val1, mpz_srcptr val2)
+				{
+					return !Cmp<double,mpz_srcptr>::eval(val1,val2);
+				}
+
+			};
+
+			template <>
+			struct Add<mpz_srcptr,mpz_srcptr>
+			{
+
+				static inline void eval(mpz_ptr dst, mpz_srcptr val1,
+										mpz_srcptr val2)
+				{
+					mpz_add(dst,val1,val2);
+				}
+
+			};
+
+			template <>
+			struct Sub<mpz_srcptr,mpz_srcptr>
+			{
+
+				static inline void eval(mpz_ptr dst, mpz_srcptr val1,
+										mpz_srcptr val2)
+				{
+					mpz_sub(dst,val1,val2);
+				}
+
+			};
+
+			template <>
+			struct Mul<mpz_srcptr,mpz_srcptr>
+			{
+
+				static inline void eval(mpz_ptr dst, mpz_srcptr val1,
+										mpz_srcptr val2)
+				{
+					mpz_mul(dst,val1,val2);
+				}
+
+			};
+
+			template <>
+			struct Div<mpz_srcptr,mpz_srcptr>
+			{
+
+				static inline void eval(mpz_ptr dst, mpz_srcptr val1,
+										mpz_srcptr val2)
+				{
+					mpz_tdiv_q(dst,val1,val2);
+				}
+
+			};
+
+			template <>
+			struct Mod<mpz_srcptr,mpz_srcptr>
+			{
+
+				static inline void eval(mpz_ptr dst, mpz_srcptr val1,
+										mpz_srcptr val2)
+				{
+					mpz_tdiv_r(dst,val1,val2);
+				}
+
+			};
+
+			template <>
+			struct And<mpz_srcptr,mpz_srcptr>
+			{
+
+				static inline void eval(mpz_ptr dst, mpz_srcptr val1,
+										mpz_srcptr val2)
+				{
+					mpz_and(dst,val1,val2);
+				}
+
+			};
+
+			template <>
+			struct Ior<mpz_srcptr,mpz_srcptr>
+			{
+
+				static inline void eval(mpz_ptr dst, mpz_srcptr val1,
+										mpz_srcptr val2)
+				{
+					mpz_ior(dst,val1,val2);
+				}
+
+			};
+
+			template <>
+			struct Xor<mpz_srcptr,mpz_srcptr>
+			{
+
+				static inline void eval(mpz_ptr dst, mpz_srcptr val1,
+										mpz_srcptr val2)
+				{
+					mpz_xor(dst,val1,val2);
+				}
+
+			};
+
+			template <>
+			struct Lshift<mpz_srcptr,mpz_srcptr>
+			{
+
+				static inline void eval(mpz_ptr dst, mpz_srcptr val1,
+										mpz_srcptr val2)
+				{
+					if( mpz_sgn(val2) >= 0 )
+						mpz_mul_2exp(dst,val1,mpz_get_ui(val2));
+					else
+						mpz_tdiv_q_2exp(dst,val1,mpz_get_ui(val2));
+				}
+
+			};
+
+			template <>
+			struct Rshift<mpz_srcptr,mpz_srcptr>
+			{
+
+				static inline void eval(mpz_ptr dst, mpz_srcptr val1,
+										mpz_srcptr val2)
+				{
+					if( mpz_sgn(val2) >= 0 )
+						mpz_tdiv_q_2exp(dst,val1,mpz_get_ui(val2));
+					else
+						mpz_mul_2exp(dst,val1,mpz_get_ui(val2));
+				}
+
+			};
+
+			template <>
+			struct Cmp<mpz_srcptr,mpz_srcptr>
+			{
+
+				static inline int eval(mpz_srcptr val1, mpz_srcptr val2)
+				{
+					return mpz_cmp(val1,val2);
+				}
+
+			};
+
+			template <>
+			struct Equal<mpz_srcptr,mpz_srcptr> :
+				Cmp<mpz_srcptr,mpz_srcptr>
+			{
+
+				static inline bool eval(mpz_srcptr val1, mpz_srcptr val2)
+				{
+					return !Cmp<mpz_srcptr,mpz_srcptr>::eval(val1,val2);
+				}
+
+			};
+
+			template <>
+			struct Neg<mpz_srcptr>
+			{
+
+				static inline void eval(mpz_ptr dst, mpz_srcptr val)
+				{
+					mpz_neg(dst,val);
+				}
+
+			};
+
+			template <>
+			struct Inv<mpz_srcptr>
+			{
+
+				static inline void eval(mpz_ptr dst, mpz_srcptr val)
+				{
+					mpz_com(dst,val);
+				}
+
+			};
+
+			template <>
+			struct Abs<mpz_srcptr>
+			{
+
+				static inline void eval(mpz_ptr dst, mpz_srcptr val)
+				{
+					mpz_abs(dst,val);
+				}
+
+			};
+
+			template <>
+			struct Sqrt<mpz_srcptr>
+			{
+
+				static inline void eval(mpz_ptr dst, mpz_srcptr val)
+				{
+					mpz_sqrt(dst,val);
+				}
+
+			};
+
+			struct Sgn
+			{
+
+				static inline int eval(mpz_srcptr val)
+				{
+					return mpz_sgn(val);
+				}
+
+			};
+
+		}
+
+		template < class Expr >
+		struct BRX;
+
+		namespace MPQ
+		{
+
+			template < class src1, class src2, bool inputCanonical >
+			struct Add;
+
+			template < class src1, class src2, bool inputCanonical >
+			struct Sub;
+
+			template < class src1, class src2, bool inputCanonical >
+			struct Mul;
+
+			template < class src1, class src2, bool inputCanonical >
+			struct Div;
+
+			template < class src1, class src2, bool inputCanonical >
+			struct Lshift;
+
+			template < class src1, class src2, bool inputCanonical >
+			struct Rshift;
+
+			template < class src, bool inputCanonical >
+			struct Neg;
+
+			template < class src, bool inputCanonical >
+			struct Inv;
+
+			template < class src, bool inputCanonical >
+			struct Abs;
+
+			template < class src1, class src2, bool inputCanonical >
+			struct Cmp;
+
+			template < class src1, class src2, bool inputCanonical >
+			struct Equal;
+
+			template < bool inputCanonical >
+			struct Sgn;
+
+			template < bool inputCanonical >
+			struct Add<mpq_srcptr,long,inputCanonical>
+			{
+
+				static const bool needCanonical = false;
+				static const bool isCanonical = inputCanonical;
+
+				static inline void eval(mpq_ptr dst, mpq_srcptr val1, long val2)
+				{
+					if( dst != val1 ) {
+						if( inputCanonical )
+							mpq_set(dst,val1);
+						else {
+							mpz_set(mpq_numref(dst),mpq_numref(val1));
+							mpz_set(mpq_denref(dst),mpq_denref(val1));
+						}
+					}
+					if( val2 >= 0 )
+						mpz_addmul_ui(mpq_numref(dst),mpq_denref(dst),val2);
+					else
+						mpz_submul_ui(mpq_numref(dst),mpq_denref(dst),-val2);
+				}
+
+			};
+
+			template < bool inputCanonical >
+			struct Sub<mpq_srcptr,long,inputCanonical>
+			{
+
+				static const bool needCanonical = false;
+				static const bool isCanonical = inputCanonical;
+
+				static inline void eval(mpq_ptr dst, mpq_srcptr val1, long val2)
+				{
+					if( dst != val1 ) {
+						if( inputCanonical )
+							mpq_set(dst,val1);
+						else {
+							mpz_set(mpq_numref(dst),mpq_numref(val1));
+							mpz_set(mpq_denref(dst),mpq_denref(val1));
+						}
+					}
+					if( val2 >= 0 )
+						mpz_submul_ui(mpq_numref(dst),mpq_denref(dst),val2);
+					else
+						mpz_addmul_ui(mpq_numref(dst),mpq_denref(dst),-val2);
+				}
+
+			};
+
+			template < bool inputCanonical >
+			struct Mul<mpq_srcptr,long,inputCanonical>
+			{
+
+				static const bool needCanonical = false;
+				static const bool isCanonical = false;
+
+				static inline void eval(mpq_ptr dst, mpq_srcptr val1, long val2)
+				{
+					mpz_mul_si(mpq_numref(dst),mpq_numref(val1),val2);
+					if( dst != val1 )
+						mpz_set(mpq_denref(dst),mpq_denref(val1));
+				}
+
+			};
+
+			template < bool inputCanonical >
+			struct Div<mpq_srcptr,long,inputCanonical>
+			{
+
+				static const bool needCanonical = false;
+				static const bool isCanonical = false;
+
+				static inline void eval(mpq_ptr dst, mpq_srcptr val1, long val2)
+				{
+					// FIXME: handle division by zero here, getting it to raise
+					// SIGFPE.
+					mpz_mul_si(mpq_denref(dst),mpq_denref(val1),val2);
+					if( dst != val1 )
+						mpz_set(mpq_numref(dst),mpq_numref(val1));
+				}
+
+			};
+
+			template < bool inputCanonical >
+			struct Lshift<mpq_srcptr,long,inputCanonical>
+			{
+
+				static const bool needCanonical = !inputCanonical;
+				static const bool isCanonical = true;
+
+				static inline void eval(mpq_ptr dst, mpq_srcptr val1, long val2)
+				{
+					if( val2 >= 0 )
+						mpq_mul_2exp(dst,val1,val2);
+					else
+						mpq_div_2exp(dst,val1,-val2);
+				}
+
+			};
+
+			template < bool inputCanonical >
+			struct Rshift<mpq_srcptr,long,inputCanonical>
+			{
+
+				static const bool needCanonical = !inputCanonical;
+				static const bool isCanonical = true;
+
+				static inline void eval(mpq_ptr dst, mpq_srcptr val1, long val2)
+				{
+					if( val2 >= 0 )
+						mpq_div_2exp(dst,val1,val2);
+					else
+						mpq_mul_2exp(dst,val1,-val2);
+				}
+
+			};
+
+			template < bool inputCanonical >
+			struct Cmp<mpq_srcptr,long,inputCanonical>
+			{
+
+				static const bool needCanonical = !inputCanonical;
+
+				static inline int eval(mpq_srcptr val1, long val2)
+				{
+					return mpq_cmp_si(val1,val2,1);
+				}
+
+			};
+
+			template < bool inputCanonical >
+			struct Equal<mpq_srcptr,long,inputCanonical> :
+				Cmp<mpq_srcptr,long,inputCanonical>
+			{
+
+				static inline bool eval(mpq_srcptr val1, long val2)
+				{
+					return !Cmp<mpq_srcptr,long,inputCanonical>::
+						eval(val1,val2);
+				}
+
+			};
+
+			template < bool inputCanonical >
+			struct Add<long,mpq_srcptr,inputCanonical>
+			{
+
+				static const bool needCanonical = false;
+				static const bool isCanonical = inputCanonical;
+
+				static inline void eval(mpq_ptr dst, long val1, mpq_srcptr val2)
+				{
+					if( dst != val2 ) {
+						if( inputCanonical )
+							mpq_set(dst,val2);
+						else {
+							mpz_set(mpq_numref(dst),mpq_numref(val2));
+							mpz_set(mpq_denref(dst),mpq_denref(val2));
+						}
+					}
+					if( val1 >= 0 )
+						mpz_addmul_ui(mpq_numref(dst),mpq_denref(dst),val1);
+					else
+						mpz_submul_ui(mpq_numref(dst),mpq_denref(dst),-val1);
+				}
+
+			};
+
+			template < bool inputCanonical >
+			struct Sub<long,mpq_srcptr,inputCanonical>
+			{
+
+				static const bool needCanonical = !inputCanonical;
+				static const bool isCanonical = true;
+
+				static inline void eval(mpq_ptr dst, long val1, mpq_srcptr val2)
+				{
+					mpq_neg(dst,val2);
+					if( val1 >= 0 )
+						mpz_addmul_ui(mpq_numref(dst),mpq_denref(dst),val1);
+					else
+						mpz_submul_ui(mpq_numref(dst),mpq_denref(dst),-val1);
+				}
+
+			};
+
+			template < bool inputCanonical >
+			struct Mul<long,mpq_srcptr,inputCanonical>
+			{
+
+				static const bool needCanonical = false;
+				static const bool isCanonical = false;
+
+				static inline void eval(mpq_ptr dst, long val1, mpq_srcptr val2)
+				{
+					mpz_mul_si(mpq_numref(dst),mpq_numref(val2),val1);
+					if( dst != val2 )
+						mpz_set(mpq_denref(dst),mpq_denref(val2));
+				}
+
+			};
+
+			template < bool inputCanonical >
+			struct Div<long,mpq_srcptr,inputCanonical>
+			{
+
+				static const bool needCanonical = false;
+				static const bool isCanonical = false;
+
+				static inline void eval(mpq_ptr dst, long val1, mpq_srcptr val2)
+				{
+					mpq_inv(dst,val2);
+					mpz_mul_si(mpq_numref(dst),mpq_numref(dst),val1);
+				}
+
+			};
+
+			template < bool inputCanonical >
+			struct Cmp<long,mpq_srcptr,inputCanonical>
+			{
+
+				static const bool needCanonical = !inputCanonical;
+
+				static inline int eval(long val1, mpq_srcptr val2)
+				{
+					return -mpq_cmp_si(val2,val1,1);
+				}
+
+			};
+
+			template < bool inputCanonical >
+			struct Equal<long,mpq_srcptr,inputCanonical> :
+				Cmp<long,mpq_srcptr,inputCanonical>
+			{
+
+				static inline bool eval(long val1, mpq_srcptr val2)
+				{
+					return !Cmp<long,mpq_srcptr,inputCanonical>::
+						eval(val1,val2);
+				}
+
+			};
+
+			template < bool inputCanonical >
+			struct Add<mpq_srcptr,unsigned long,inputCanonical>
+			{
+
+				static const bool needCanonical = false;
+				static const bool isCanonical = inputCanonical;
+
+				static inline void eval(mpq_ptr dst, mpq_srcptr val1,
+										unsigned long val2)
+				{
+					if( dst != val1 ) {
+						if( inputCanonical )
+							mpq_set(dst,val1);
+						else {
+							mpz_set(mpq_numref(dst),mpq_numref(val1));
+							mpz_set(mpq_denref(dst),mpq_denref(val1));
+						}
+					}
+					mpz_addmul_ui(mpq_numref(dst),mpq_denref(dst),val2);
+				}
+
+			};
+
+			template < bool inputCanonical >
+			struct Sub<mpq_srcptr,unsigned long,inputCanonical>
+			{
+
+				static const bool needCanonical = false;
+				static const bool isCanonical = inputCanonical;
+
+				static inline void eval(mpq_ptr dst, mpq_srcptr val1,
+										unsigned long val2)
+				{
+					if( dst != val1 ) {
+						if( inputCanonical )
+							mpq_set(dst,val1);
+						else {
+							mpz_set(mpq_numref(dst),mpq_numref(val1));
+							mpz_set(mpq_denref(dst),mpq_denref(val1));
+						}
+					}
+					mpz_submul_ui(mpq_numref(dst),mpq_denref(dst),val2);
+				}
+
+			};
+
+			template < bool inputCanonical >
+			struct Mul<mpq_srcptr,unsigned long,inputCanonical>
+			{
+
+				static const bool needCanonical = false;
+				static const bool isCanonical = false;
+
+				static inline void eval(mpq_ptr dst, mpq_srcptr val1,
+										unsigned long val2)
+				{
+					mpz_mul_ui(mpq_numref(dst),mpq_numref(val1),val2);
+					if( dst != val1 )
+						mpz_set(mpq_denref(dst),mpq_denref(val1));
+				}
+
+			};
+
+			template < bool inputCanonical >
+			struct Div<mpq_srcptr,unsigned long,inputCanonical>
+			{
+
+				static const bool needCanonical = false;
+				static const bool isCanonical = false;
+
+				static inline void eval(mpq_ptr dst, mpq_srcptr val1,
+										unsigned long val2)
+				{
+					// FIXME: handle division by zero here, getting it to raise
+					// SIGFPE.
+					mpz_mul_ui(mpq_denref(dst),mpq_denref(val1),val2);
+					if( dst != val1 )
+						mpz_set(mpq_numref(dst),mpq_numref(val1));
+				}
+
+			};
+
+			template < bool inputCanonical >
+			struct Lshift<mpq_srcptr,unsigned long,inputCanonical>
+			{
+
+				static const bool needCanonical = !inputCanonical;
+				static const bool isCanonical = true;
+
+				static inline void eval(mpq_ptr dst, mpq_srcptr val1,
+										unsigned long val2)
+				{
+					mpq_mul_2exp(dst,val1,val2);
+				}
+
+			};
+
+			template < bool inputCanonical >
+			struct Rshift<mpq_srcptr,unsigned long,inputCanonical>
+			{
+
+				static const bool needCanonical = !inputCanonical;
+				static const bool isCanonical = true;
+
+				static inline void eval(mpq_ptr dst, mpq_srcptr val1,
+										unsigned long val2)
+				{
+					mpq_div_2exp(dst,val1,val2);
+				}
+
+			};
+
+			template < bool inputCanonical >
+			struct Cmp<mpq_srcptr,unsigned long,inputCanonical>
+			{
+
+				static const bool needCanonical = !inputCanonical;
+
+				static inline int eval(mpq_srcptr val1, unsigned long val2)
+				{
+					return mpq_cmp_ui(val1,val2,1);
+				}
+
+			};
+
+			template < bool inputCanonical >
+			struct Equal<mpq_srcptr,unsigned long,inputCanonical> :
+				Cmp<mpq_srcptr,unsigned long,inputCanonical>
+			{
+
+				static inline bool eval(mpq_srcptr val1, unsigned long val2)
+				{
+					return !Cmp<mpq_srcptr,unsigned long,inputCanonical>::
+						eval(val1,val2);
+				}
+
+			};
+
+			template < bool inputCanonical >
+			struct Add<unsigned long,mpq_srcptr,inputCanonical>
+			{
+
+				static const bool needCanonical = false;
+				static const bool isCanonical = inputCanonical;
+
+				static inline void eval(mpq_ptr dst, unsigned long val1,
+										mpq_srcptr val2)
+				{
+					if( dst != val2 ) {
+						if( inputCanonical )
+							mpq_set(dst,val2);
+						else {
+							mpz_set(mpq_numref(dst),mpq_numref(val2));
+							mpz_set(mpq_denref(dst),mpq_denref(val2));
+						}
+					}
+					mpz_addmul_ui(mpq_numref(dst),mpq_denref(dst),val1);
+				}
+
+			};
+
+			template < bool inputCanonical >
+			struct Sub<unsigned long,mpq_srcptr,inputCanonical>
+			{
+
+				static const bool needCanonical = !inputCanonical;
+				static const bool isCanonical = true;
+
+				static inline void eval(mpq_ptr dst, unsigned long val1,
+										mpq_srcptr val2)
+				{
+					mpq_neg(dst,val2);
+					mpz_addmul_ui(mpq_numref(dst),mpq_denref(dst),val1);
+				}
+
+			};
+
+			template < bool inputCanonical >
+			struct Mul<unsigned long,mpq_srcptr,inputCanonical>
+			{
+
+				static const bool needCanonical = false;
+				static const bool isCanonical = false;
+
+				static inline void eval(mpq_ptr dst, unsigned long val1,
+										mpq_srcptr val2)
+				{
+					mpz_mul_ui(mpq_numref(dst),mpq_numref(val2),val1);
+					if( dst != val2 )
+						mpz_set(mpq_denref(dst),mpq_denref(val2));
+				}
+
+			};
+
+			template < bool inputCanonical >
+			struct Div<unsigned long,mpq_srcptr,inputCanonical>
+			{
+
+				static const bool needCanonical = false;
+				static const bool isCanonical = false;
+
+				static inline void eval(mpq_ptr dst, unsigned long val1,
+										mpq_srcptr val2)
+				{
+					mpq_inv(dst,val2);
+					mpz_mul_ui(mpq_numref(dst),mpq_numref(dst),val1);
+				}
+
+			};
+
+			template < bool inputCanonical >
+			struct Cmp<unsigned long,mpq_srcptr,inputCanonical>
+			{
+
+				static const bool needCanonical = !inputCanonical;
+
+				static inline int eval(unsigned long val1, mpq_srcptr val2)
+				{
+					return -mpq_cmp_ui(val2,val1,1);
+				}
+
+			};
+
+			template < bool inputCanonical >
+			struct Equal<unsigned long,mpq_srcptr,inputCanonical> :
+				Cmp<unsigned long,mpq_srcptr,inputCanonical>
+			{
+
+				static inline bool eval(unsigned long val1, mpq_srcptr val2)
+				{
+					return !Cmp<unsigned long,mpq_srcptr,inputCanonical>::
+						eval(val1,val2);
+				}
+
+			};
+
+			template < bool inputCanonical >
+			struct Add<mpq_srcptr,double,inputCanonical>
+			{
+
+				static const bool needCanonical = !inputCanonical;
+				static const bool isCanonical = true;
+
+				static inline void eval(mpq_ptr dst, mpq_srcptr val1,
+										double val2)
+				{
+					if( dst != val1 ) {
+						mpq_set_d(dst,val2);
+						mpq_add(dst,val1,dst);
+					} else {
+						mpq_t tmp;
+						mpq_init(tmp);
+						mpq_set_d(tmp,val2);
+						mpq_add(dst,dst,tmp);
+						mpq_clear(tmp);
+					}
+				}
+
+			};
+
+			template < bool inputCanonical >
+			struct Sub<mpq_srcptr,double,inputCanonical>
+			{
+
+				static const bool needCanonical = !inputCanonical;
+				static const bool isCanonical = true;
+
+				static inline void eval(mpq_ptr dst, mpq_srcptr val1,
+										double val2)
+				{
+					if( dst != val1 ) {
+						mpq_set_d(dst,val2);
+						mpq_sub(dst,val1,dst);
+					} else {
+						mpq_t tmp;
+						mpq_init(tmp);
+						mpq_set_d(tmp,val2);
+						mpq_sub(dst,val1,tmp);
+						mpq_clear(tmp);
+					}
+				}
+
+			};
+
+			template < bool inputCanonical >
+			struct Mul<mpq_srcptr,double,inputCanonical>
+			{
+
+				static const bool needCanonical = !inputCanonical;
+				static const bool isCanonical = true;
+
+				static inline void eval(mpq_ptr dst, mpq_srcptr val1,
+										double val2)
+				{
+					if( dst != val1 ) {
+						mpq_set_d(dst,val2);
+						mpq_mul(dst,val1,dst);
+					} else {
+						mpq_t tmp;
+						mpq_init(tmp);
+						mpq_set_d(tmp,val2);
+						mpq_mul(dst,val1,tmp);
+						mpq_clear(tmp);
+					}
+				}
+
+			};
+
+			template < bool inputCanonical >
+			struct Div<mpq_srcptr,double,inputCanonical>
+			{
+
+				static const bool needCanonical = !inputCanonical;
+				static const bool isCanonical = true;
+
+				static inline void eval(mpq_ptr dst, mpq_srcptr val1,
+										double val2)
+				{
+					if( dst != val1 ) {
+						mpq_set_d(dst,val2);
+						mpq_div(dst,val1,dst);
+					} else {
+						mpq_t tmp;
+						mpq_init(tmp);
+						mpq_set_d(tmp,val2);
+						mpq_div(dst,val1,tmp);
+						mpq_clear(tmp);
+					}
+				}
+
+			};
+
+			template < bool inputCanonical >
+			struct Cmp<mpq_srcptr,double,inputCanonical>
+			{
+
+				static const bool needCanonical = !inputCanonical;
+
+				static inline int eval(mpq_srcptr val1, double val2)
+				{
+					mpq_t tmp;
+					mpq_init(tmp);
+					mpq_set_d(tmp,val2);
+					int rv = mpq_cmp(val1,tmp);
+					mpq_clear(tmp);
+					return rv;
+				}
+
+			};
+
+			template < bool inputCanonical >
+			struct Equal<mpq_srcptr,double,inputCanonical>
+			{
+
+				static const bool needCanonical = !inputCanonical;
+
+				static inline bool eval(mpq_srcptr val1, double val2)
+				{
+					mpq_t tmp;
+					mpq_init(tmp);
+					mpq_set_d(tmp,val2);
+					bool rv = mpq_equal(val1,tmp);
+					mpq_clear(tmp);
+					return rv;
+				}
+
+			};
+
+			template < bool inputCanonical >
+			struct Add<double,mpq_srcptr,inputCanonical>
+			{
+
+				static const bool needCanonical = !inputCanonical;
+				static const bool isCanonical = true;
+
+				static inline void eval(mpq_ptr dst, double val1,
+										mpq_srcptr val2)
+				{
+					if( dst != val2 ) {
+						mpq_set_d(dst,val1);
+						mpq_add(dst,dst,val2);
+					} else {
+						mpq_t tmp;
+						mpq_init(tmp);
+						mpq_set_d(tmp,val1);
+						mpq_add(dst,tmp,val2);
+						mpq_clear(tmp);
+					}
+				}
+
+			};
+
+			template < bool inputCanonical >
+			struct Sub<double,mpq_srcptr,inputCanonical>
+			{
+
+				static const bool needCanonical = !inputCanonical;
+				static const bool isCanonical = true;
+
+				static inline void eval(mpq_ptr dst, double val1,
+										mpq_srcptr val2)
+				{
+					if( dst != val2 ) {
+						mpq_set_d(dst,val1);
+						mpq_sub(dst,dst,val2);
+					} else {
+						mpq_t tmp;
+						mpq_init(tmp);
+						mpq_set_d(tmp,val1);
+						mpq_sub(dst,tmp,val2);
+						mpq_clear(tmp);
+					}
+				}
+
+			};
+
+			template < bool inputCanonical >
+			struct Mul<double,mpq_srcptr,inputCanonical>
+			{
+
+				static const bool needCanonical = !inputCanonical;
+				static const bool isCanonical = true;
+
+				static inline void eval(mpq_ptr dst, double val1,
+										mpq_srcptr val2)
+				{
+					if( dst != val2 ) {
+						mpq_set_d(dst,val1);
+						mpq_mul(dst,dst,val2);
+					} else {
+						mpq_t tmp;
+						mpq_init(tmp);
+						mpq_set_d(tmp,val1);
+						mpq_mul(dst,tmp,val2);
+						mpq_clear(tmp);
+					}
+				}
+
+			};
+
+			template < bool inputCanonical >
+			struct Div<double,mpq_srcptr,inputCanonical>
+			{
+
+				static const bool needCanonical = !inputCanonical;
+				static const bool isCanonical = true;
+
+				static inline void eval(mpq_ptr dst, double val1,
+										mpq_srcptr val2)
+				{
+					if( dst != val2 ) {
+						mpq_set_d(dst,val1);
+						mpq_div(dst,dst,val2);
+					} else {
+						mpq_t tmp;
+						mpq_init(tmp);
+						mpq_set_d(tmp,val1);
+						mpq_div(dst,tmp,val2);
+						mpq_clear(tmp);
+					}
+				}
+
+			};
+
+			template < bool inputCanonical >
+			struct Cmp<double,mpq_srcptr,inputCanonical>
+			{
+
+				static const bool needCanonical = !inputCanonical;
+
+				static inline int eval(double val1, mpq_srcptr val2)
+				{
+					mpq_t tmp;
+					mpq_init(tmp);
+					mpq_set_d(tmp,val1);
+					int rv = mpq_cmp(tmp,val2);
+					mpq_clear(tmp);
+					return rv;
+				}
+
+			};
+
+			template < bool inputCanonical >
+			struct Equal<double,mpq_srcptr,inputCanonical>
+			{
+
+				static const bool needCanonical = !inputCanonical;
+
+				static inline bool eval(double val1, mpq_srcptr val2)
+				{
+					mpq_t tmp;
+					mpq_init(tmp);
+					mpq_set_d(tmp,val1);
+					bool rv = mpq_equal(tmp,val2);
+					mpq_clear(tmp);
+					return rv;
+				}
+
+			};
+
+			template < bool inputCanonical >
+			struct Add<mpq_srcptr,mpz_srcptr,inputCanonical>
+			{
+
+				static const bool needCanonical = false;
+				static const bool isCanonical = inputCanonical;
+
+				static inline void eval(mpq_ptr dst, mpq_srcptr val1,
+										mpz_srcptr val2)
+				{
+					if( dst != val1 ) {
+						mpz_mul(mpq_numref(dst),mpq_denref(val1),val2);
+						mpz_add(mpq_numref(dst),mpq_numref(val1),
+								mpq_numref(dst));
+						mpz_set(mpq_denref(dst),mpq_denref(val1));
+					} else
+						mpz_addmul(mpq_numref(dst),mpq_denref(dst),val2);
+				}
+
+			};
+
+			template < bool inputCanonical >
+			struct Sub<mpq_srcptr,mpz_srcptr,inputCanonical>
+			{
+
+				static const bool needCanonical = false;
+				static const bool isCanonical = inputCanonical;
+
+				static inline void eval(mpq_ptr dst, mpq_srcptr val1,
+										mpz_srcptr val2)
+				{
+					if( dst != val1 ) {
+						mpz_mul(mpq_numref(dst),mpq_denref(val1),val2);
+						mpz_sub(mpq_numref(dst),mpq_numref(val1),
+								mpq_numref(dst));
+						mpz_set(mpq_denref(dst),mpq_denref(val1));
+					} else
+						mpz_submul(mpq_numref(dst),mpq_denref(dst),val2);
+				}
+
+			};
+
+			template < bool inputCanonical >
+			struct Mul<mpq_srcptr,mpz_srcptr,inputCanonical>
+			{
+
+				static const bool needCanonical = false;
+				static const bool isCanonical = false;
+
+				static inline void eval(mpq_ptr dst, mpq_srcptr val1,
+										mpz_srcptr val2)
+				{
+					mpz_mul(mpq_numref(dst),mpq_numref(val1),val2);
+					if( dst != val1 )
+						mpz_set(mpq_denref(dst),mpq_denref(val1));
+				}
+
+			};
+
+			template < bool inputCanonical >
+			struct Div<mpq_srcptr,mpz_srcptr,inputCanonical>
+			{
+
+				static const bool needCanonical = false;
+				static const bool isCanonical = false;
+
+				static inline void eval(mpq_ptr dst, mpq_srcptr val1,
+										mpz_srcptr val2)
+				{
+					// FIXME: handle division by zero here, getting it to raise
+					// SIGFPE.
+					mpz_mul(mpq_denref(dst),mpq_denref(val1),val2);
+					if( dst != val1 )
+						mpz_set(mpq_numref(dst),mpq_numref(val1));
+				}
+
+			};
+
+			template < bool inputCanonical >
+			struct Lshift<mpq_srcptr,mpz_srcptr,inputCanonical>
+			{
+
+				static const bool needCanonical = !inputCanonical;
+				static const bool isCanonical = true;
+
+				static inline void eval(mpq_ptr dst, mpq_srcptr val1,
+										mpz_srcptr val2)
+				{
+					if( mpz_sgn(val2) >= 0 )
+						mpq_mul_2exp(dst,val1,mpz_get_ui(val2));
+					else
+						mpq_div_2exp(dst,val1,mpz_get_ui(val2));
+				}
+
+			};
+
+			template < bool inputCanonical >
+			struct Rshift<mpq_srcptr,mpz_srcptr,inputCanonical>
+			{
+
+				static const bool needCanonical = !inputCanonical;
+				static const bool isCanonical = true;
+
+				static inline void eval(mpq_ptr dst, mpq_srcptr val1,
+										mpz_srcptr val2)
+				{
+					if( mpz_sgn(val2) >= 0 )
+						mpq_div_2exp(dst,val1,mpz_get_ui(val2));
+					else
+						mpq_mul_2exp(dst,val1,mpz_get_ui(val2));
+				}
+
+			};
+
+			template < bool inputCanonical >
+			struct Cmp<mpq_srcptr,mpz_srcptr,inputCanonical>
+			{
+
+				static const bool needCanonical = false;
+
+				static inline int eval(mpq_srcptr val1, mpz_srcptr val2)
+				{
+					mpz_t tmp;
+					mpz_init(tmp);
+					mpz_mul(tmp,mpq_denref(val1),val2);
+					int rv = mpz_cmp(mpq_numref(val1),tmp);
+					mpz_clear(tmp);
+					return rv;
+				}
+
+			};
+
+			template < bool inputCanonical >
+			struct Equal<mpq_srcptr,mpz_srcptr,inputCanonical>
+			{
+
+				static const bool needCanonical = !inputCanonical;
+
+				static inline bool eval(mpq_srcptr val1, mpz_srcptr val2)
+				{
+					return !mpz_cmp_ui(mpq_denref(val1),1) &&
+						!mpz_cmp(mpq_numref(val1),val2);
+				}
+
+			};
+
+			template < bool inputCanonical >
+			struct Add<mpz_srcptr,mpq_srcptr,inputCanonical>
+			{
+
+				static const bool needCanonical = false;
+				static const bool isCanonical = inputCanonical;
+
+				static inline void eval(mpq_ptr dst, mpz_srcptr val1,
+										mpq_srcptr val2)
+				{
+					if( dst != val2 ) {
+						mpz_mul(mpq_numref(dst),val1,mpq_denref(val2));
+						mpz_add(mpq_numref(dst),mpq_numref(dst),
+								mpq_numref(val2));
+						mpz_set(mpq_denref(dst),mpq_denref(val2));
+					} else
+						mpz_addmul(mpq_numref(dst),val1,mpq_denref(dst));
+				}
+
+			};
+
+			template < bool inputCanonical >
+			struct Sub<mpz_srcptr,mpq_srcptr,inputCanonical>
+			{
+
+				static const bool needCanonical = !inputCanonical;
+				static const bool isCanonical = true;
+
+				static inline void eval(mpq_ptr dst, mpz_srcptr val1,
+										mpq_srcptr val2)
+				{
+					if( dst != val2 ) {
+						mpz_mul(mpq_numref(dst),val1,mpq_denref(val2));
+						mpz_sub(mpq_numref(dst),mpq_numref(dst),
+								mpq_numref(val2));
+						mpz_set(mpq_denref(dst),mpq_denref(val2));
+					} else {
+						mpz_submul(mpq_numref(dst),val1,mpq_denref(dst));
+						mpq_neg(dst,dst);
+					}
+				}
+
+			};
+
+			template < bool inputCanonical >
+			struct Mul<mpz_srcptr,mpq_srcptr,inputCanonical>
+			{
+
+				static const bool needCanonical = false;
+				static const bool isCanonical = false;
+
+				static inline void eval(mpq_ptr dst, mpz_srcptr val1,
+										mpq_srcptr val2)
+				{
+					mpz_mul(mpq_numref(dst),val1,mpq_numref(val2));
+					if( dst != val2 )
+						mpz_set(mpq_denref(dst),mpq_denref(val2));
+				}
+
+			};
+
+			template < bool inputCanonical >
+			struct Div<mpz_srcptr,mpq_srcptr,inputCanonical>
+			{
+
+				static const bool needCanonical = false;
+				static const bool isCanonical = false;
+
+				static inline void eval(mpq_ptr dst, mpz_srcptr val1,
+										mpq_srcptr val2)
+				{
+					mpz_mul(mpq_denref(dst),val1,mpq_denref(val2));
+					if( dst != val2 )
+						mpz_set(mpq_numref(dst),mpq_numref(val2));
+					mpq_inv(dst,dst);
+				}
+
+			};
+
+			template < bool inputCanonical >
+			struct Cmp<mpz_srcptr,mpq_srcptr,inputCanonical>
+			{
+
+				static const bool needCanonical = false;
+
+				static inline int eval(mpz_srcptr val1, mpq_srcptr val2)
+				{
+					mpz_t tmp;
+					mpz_init(tmp);
+					mpz_mul(tmp,val1,mpq_denref(val2));
+					int rv = mpz_cmp(tmp,mpq_numref(val2));
+					mpz_clear(tmp);
+					return rv;
+				}
+
+			};
+
+			template < bool inputCanonical >
+			struct Equal<mpz_srcptr,mpq_srcptr,inputCanonical>
+			{
+
+				static const bool needCanonical = !inputCanonical;
+
+				static inline bool eval(mpz_srcptr val1, mpq_srcptr val2)
+				{
+					return !mpz_cmp_ui(mpq_denref(val2),1) &&
+						!mpz_cmp(val1,mpq_numref(val2));
+				}
+
+			};
+
+			template < bool inputCanonical >
+			struct Add<mpq_srcptr,mpq_srcptr,inputCanonical>
+			{
+
+				static const bool needCanonical = !inputCanonical;
+				static const bool isCanonical = true;
+
+				static inline void eval(mpq_ptr dst, mpq_srcptr val1,
+										mpq_srcptr val2)
+				{
+					mpq_add(dst,val1,val2);
+				}
+
+			};
+
+			template < bool inputCanonical >
+			struct Sub<mpq_srcptr,mpq_srcptr,inputCanonical>
+			{
+
+				static const bool needCanonical = !inputCanonical;
+				static const bool isCanonical = true;
+
+				static inline void eval(mpq_ptr dst, mpq_srcptr val1,
+										mpq_srcptr val2)
+				{
+					mpq_sub(dst,val1,val2);
+				}
+
+			};
+
+			template < bool inputCanonical >
+			struct Mul<mpq_srcptr,mpq_srcptr,inputCanonical>
+			{
+
+				static const bool needCanonical = !inputCanonical;
+				static const bool isCanonical = true;
+
+				static inline void eval(mpq_ptr dst, mpq_srcptr val1,
+										mpq_srcptr val2)
+				{
+					mpq_mul(dst,val1,val2);
+				}
+
+			};
+
+			template < bool inputCanonical >
+			struct Div<mpq_srcptr,mpq_srcptr,inputCanonical>
+			{
+
+				static const bool needCanonical = !inputCanonical;
+				static const bool isCanonical = true;
+
+				static inline void eval(mpq_ptr dst, mpq_srcptr val1,
+										mpq_srcptr val2)
+				{
+					mpq_div(dst,val1,val2);
+				}
+
+			};
+
+			template < bool inputCanonical >
+			struct Cmp<mpq_srcptr,mpq_srcptr,inputCanonical>
+			{
+
+				static const bool needCanonical = !inputCanonical;
+
+				static inline int eval(mpq_srcptr val1, mpq_srcptr val2)
+				{
+					return mpq_cmp(val1,val2);
+				}
+
+			};
+
+			template < bool inputCanonical >
+			struct Equal<mpq_srcptr,mpq_srcptr,inputCanonical>
+			{
+
+				static const bool needCanonical = !inputCanonical;
+
+				static inline bool eval(mpq_srcptr val1, mpq_srcptr val2)
+				{
+					return mpq_equal(val1,val2);
+				}
+
+			};
+
+			template < bool inputCanonical >
+			struct Neg<mpq_srcptr,inputCanonical>
+			{
+
+				static const bool needCanonical = !inputCanonical;
+				static const bool isCanonical = true;
+
+				static inline void eval(mpq_ptr dst, mpq_srcptr val)
+				{
+					mpq_neg(dst,val);
+				}
+
+			};
+
+			template < bool inputCanonical >
+			struct Inv<mpq_srcptr,inputCanonical>
+			{
+
+				static const bool needCanonical = false;
+				static const bool isCanonical = inputCanonical;
+
+				static inline void eval(mpq_ptr dst, mpq_srcptr val)
+				{
+					mpq_inv(dst,val);
+				}
+
+			};
+
+			template < bool inputCanonical >
+			struct Abs<mpq_srcptr,inputCanonical>
+			{
+
+				static const bool needCanonical = !inputCanonical;
+				static const bool isCanonical = true;
+
+				static inline void eval(mpq_ptr dst, mpq_srcptr val)
+				{
+					mpq_abs(dst,val);
+				}
+
+			};
+
+			template < bool inputCanonical >
+			struct Sgn
+			{
+
+				static const bool needCanonical = !inputCanonical;
+
+				static inline int eval(mpq_srcptr val)
+				{
+					return mpq_sgn(val);
+				}
+
+			};
+
+		}
+
+	}
+
+	class BigInteger
+	{
+
+	private:
+
+		mpz_t m_val;
+
+	public:
+
+		inline BigInteger()
+		{
+			mpz_init(m_val);
+		}
+
+#define BIGINT_INIT(type,suffix)										\
+		inline BigInteger(type val)										\
+		{																\
+			mpz_init_set##suffix(m_val,val);							\
+		}
+
+		BIGINT_INIT(bool,_ui)
+		BIGINT_INIT(char,_si)
+		BIGINT_INIT(signed char,_si)
+		BIGINT_INIT(unsigned char,_ui)
+		BIGINT_INIT(short,_si)
+		BIGINT_INIT(unsigned short,_ui)
+		BIGINT_INIT(int,_si)
+		BIGINT_INIT(unsigned int,_ui)
+		BIGINT_INIT(long,_si)
+		BIGINT_INIT(unsigned long,_ui)
+		BIGINT_INIT(float,_d)
+		BIGINT_INIT(double,_d)
+		BIGINT_INIT(mpz_srcptr,)
+		BIGINT_INIT(const BigInteger&,)
+
+#undef BIGINT_INIT
+
+		explicit inline BigInteger(mpq_srcptr val)
+		{
+			mpz_init(m_val);
+			mpz_tdiv_q(m_val,mpq_numref(val),mpq_denref(val));
+		}
+
+		explicit inline BigInteger(const BigRational& val);
+
+		explicit inline BigInteger(const char* val, int base = 0)
+		{
+			if( mpz_init_set_str(m_val,val,base) ) {
+				mpz_clear(m_val);
+				throw std::runtime_error("Invalid string value for BigInt");
+			}
+		}
+
+		explicit inline BigInteger(const std::string& val, int base = 0)
+		{
+			if( mpz_init_set_str(m_val,val.c_str(),base) ) {
+				mpz_clear(m_val);
+				throw std::runtime_error("Invalid string value for BigInt");
+			}
+		}
+
+		template < class Expr >
+		inline BigInteger(const detail::BIX<Expr>& expr)
+		{
+			mpz_init(m_val);
+			expr.evalTmp(m_val);
+		}
+
+		template < class Expr >
+		explicit inline BigInteger(const detail::BRX<Expr>& expr)
+		{
+			mpz_init(m_val);
+			mpq_t tmp;
+			mpq_init(tmp);
+			expr.evalTmp(tmp);
+			mpz_tdiv_q(m_val,mpq_numref(tmp),mpq_denref(tmp));
+			mpq_clear(tmp);
+		}
+
+		inline void set(const char* val, int base = 0)
+		{
+			if( mpz_set_str(m_val,val,base) )
+				throw std::runtime_error("Invalid string value for BigInt");
+		}
+
+		inline void set(const std::string& val, int base = 0)
+		{
+			if( mpz_set_str(m_val,val.c_str(),base) )
+				throw std::runtime_error("Invalid string value for BigInt");
+		}
+
+#define BIGINT_ASSIGN(type,suffix)										\
+		inline BigInteger& operator =(type val)							\
+		{																\
+			mpz_set##suffix(m_val,val);									\
+			return *this;												\
+		}
+
+		BIGINT_ASSIGN(bool,_ui)
+		BIGINT_ASSIGN(char,_si)
+		BIGINT_ASSIGN(signed char,_si)
+		BIGINT_ASSIGN(unsigned char,_ui)
+		BIGINT_ASSIGN(short,_si)
+		BIGINT_ASSIGN(unsigned short,_ui)
+		BIGINT_ASSIGN(int,_si)
+		BIGINT_ASSIGN(unsigned int,_ui)
+		BIGINT_ASSIGN(long,_si)
+		BIGINT_ASSIGN(unsigned long,_ui)
+		BIGINT_ASSIGN(float,_d)
+		BIGINT_ASSIGN(double,_d)
+
+#undef BIGINT_ASSIGN
+
+		inline BigInteger& operator =(mpz_srcptr val)
+		{
+			if( m_val != val )
+				mpz_set(m_val,val);
+			return *this;
+		}
+
+		inline BigInteger& operator =(const BigInteger& val)
+		{
+			if( m_val != val.m_val )
+				mpz_set(m_val,val.m_val);
+			return *this;
+		}
+
+		inline BigInteger& operator =(const char* val)
+		{
+			set(val);
+			return *this;
+		}
+
+		inline BigInteger& operator =(const std::string& val)
+		{
+			set(val);
+			return *this;
+		}
+
+		template < class Expr >
+		inline BigInteger& operator =(const detail::BIX<Expr>& expr)
+		{
+			expr.eval(m_val);
+			return *this;
+		}
+
+		inline BigInteger& operator ++()
+		{
+			mpz_add_ui(m_val,m_val,1);
+			return *this;
+		}
+
+		inline BigInteger& operator --()
+		{
+			mpz_sub_ui(m_val,m_val,1);
+			return *this;
+		}
+
+#define BIGINT_IPOPER(fun,type,argtype,impl)							\
+		inline BigInteger& fun(type val)								\
+		{																\
+			typedef detail::MPZ::impl<mpz_srcptr,argtype> impl_t;		\
+			impl_t::eval(m_val,m_val,val);								\
+			return *this;												\
+		}
+
+#define BIGINT_INTIPOPER(fun,impl)										\
+		BIGINT_IPOPER(fun,bool,unsigned long,impl)						\
+		BIGINT_IPOPER(fun,char,long,impl)								\
+		BIGINT_IPOPER(fun,signed char,long,impl)						\
+		BIGINT_IPOPER(fun,unsigned char,unsigned long,impl)				\
+		BIGINT_IPOPER(fun,short,long,impl)								\
+		BIGINT_IPOPER(fun,unsigned short,unsigned long,impl)			\
+		BIGINT_IPOPER(fun,int,long,impl)								\
+		BIGINT_IPOPER(fun,unsigned int,unsigned long,impl)				\
+		BIGINT_IPOPER(fun,long,long,impl)								\
+		BIGINT_IPOPER(fun,unsigned long,unsigned long,impl)
+
+#define BIGINT_FLOATIPOPER(fun,impl)									\
+		BIGINT_IPOPER(fun,float,double,impl)							\
+		BIGINT_IPOPER(fun,double,double,impl)
+
+#define BIGINT_MPZIPOPER(fun,impl)										\
+		BIGINT_IPOPER(fun,mpz_srcptr,mpz_srcptr,impl)					\
+		BIGINT_IPOPER(fun,const BigInteger&,mpz_srcptr,impl)
+
+#define BIGINT_EXPRIPOPER(fun,impl)										\
+		template < class Expr >											\
+		inline BigInteger& fun(const detail::BIX<Expr>& val)			\
+		{																\
+			typedef detail::MPZ::impl<mpz_srcptr,						\
+									  mpz_srcptr> impl_t;				\
+			BigInteger tmp(val);										\
+			impl_t::eval(m_val,m_val,tmp);								\
+			return *this;												\
+		}
+
+#define BIGINT_BASEIPOPER(fun,impl)										\
+		BIGINT_INTIPOPER(fun,impl)										\
+		BIGINT_MPZIPOPER(fun,impl)										\
+		BIGINT_EXPRIPOPER(fun,impl)
+
+#define BIGINT_ALLIPOPER(fun,impl)										\
+		BIGINT_BASEIPOPER(fun,impl)										\
+		BIGINT_FLOATIPOPER(fun,impl)
+
+		BIGINT_ALLIPOPER(operator +=,Add)
+		BIGINT_ALLIPOPER(operator -=,Sub)
+		BIGINT_ALLIPOPER(operator *=,Mul)
+		BIGINT_ALLIPOPER(operator /=,Div)
+		BIGINT_ALLIPOPER(operator %=,Mod)
+		BIGINT_BASEIPOPER(operator &=,And)
+		BIGINT_BASEIPOPER(operator |=,Ior)
+		BIGINT_BASEIPOPER(operator ^=,Xor)
+		BIGINT_BASEIPOPER(operator <<=,Lshift)
+		BIGINT_BASEIPOPER(operator >>=,Rshift)
+
+#undef BIGINT_ALLIPOPER
+#undef BIGINT_BASEIPOPER
+#undef BIGINT_EXPRIPOPER
+#undef BIGINT_MPZIPOPER
+#undef BIGINT_FLOATIPOPER
+#undef BIGINT_INTIPOPER
+#undef BIGINT_IPOPER
+
+		inline operator bool() const
+		{
+			return mpz_sgn(m_val);
+		}
+
+#define BIGINT_CONV(type,suffix)										\
+		inline operator type() const									\
+		{																\
+			return mpz_get##suffix(m_val);								\
+		}
+
+#define BIGINT_FITSCONV(type,suffix,testsuffix)							\
+		BIGINT_CONV(type,suffix)										\
+		inline bool fits##testsuffix##_p() const						\
+		{																\
+			return mpz_fits##testsuffix##_p(m_val);						\
+		}
+
+		BIGINT_CONV(char,_si)
+		BIGINT_CONV(signed char,_si)
+		BIGINT_CONV(unsigned char,_ui)
+		BIGINT_FITSCONV(short,_si,_sshort)
+		BIGINT_FITSCONV(unsigned short,_ui,_ushort)
+		BIGINT_FITSCONV(int,_si,_sint)
+		BIGINT_FITSCONV(unsigned int,_ui,_uint)
+		BIGINT_FITSCONV(long,_si,_slong)
+		BIGINT_FITSCONV(unsigned long,_ui,_ulong)
+		BIGINT_CONV(float,_d)
+		BIGINT_CONV(double,_d)
+
+#undef BIGINT_FITSCONV
+#undef BIGINT_CONV
+
+		inline long get_si() const
+		{
+			return mpz_get_si(m_val);
+		}
+
+		inline unsigned long get_ui() const
+		{
+			return mpz_get_ui(m_val);
+		}
+
+		inline operator mpz_ptr()
+		{
+			return m_val;
+		}
+
+		inline mpz_ptr get_mpz_t()
+		{
+			return m_val;
+		}
+
+		inline mpz_ptr operator ->()
+		{
+			return m_val;
+		}
+
+		inline operator mpz_srcptr() const
+		{
+			return m_val;
+		}
+
+		inline mpz_srcptr get_mpz_t() const
+		{
+			return m_val;
+		}
+
+		inline mpz_srcptr operator ->() const
+		{
+			return m_val;
+		}
+
+		inline double get_double(long& exp) const
+		{
+			return mpz_get_d_2exp(&exp,m_val);
+		}
+
+		inline void get_string(char* val, int base = 10) const
+		{
+			mpz_get_str(val,base,m_val);
+		}
+
+		inline void get_string(std::string& val, int base = 10) const
+		{
+			char* buf = new char[mpz_sizeinbase(m_val,base)+2];
+			val = mpz_get_str(buf,base,m_val);
+			delete [] buf;
+		}
+
+		inline std::string get_string(int base = 10) const
+		{
+			std::string rv;
+			get_string(rv,base);
+			return rv;
+		}
+
+		inline operator std::string() const
+		{
+			return get_string();
+		}
+
+	};
+
+	class BigRational
+	{
+
+	private:
+
+		mpq_t m_val;
+
+	public:
+
+		inline BigRational()
+		{
+			mpq_init(m_val);
+		}
+
+#define BIGRAT_INIT(type,suffix)										\
+		inline BigRational(type num, unsigned long den = 1)				\
+		{																\
+			mpq_init(m_val);											\
+			mpq_set##suffix(m_val,num,den);								\
+			if( den != 1 )												\
+				mpq_canonicalize(m_val);								\
+		}
+
+#define BIGRAT_INIT2(type,suffix)										\
+		inline BigRational(type val)									\
+		{																\
+			mpq_init(m_val);											\
+			mpq_set##suffix(m_val,val);									\
+		}
+
+		BIGRAT_INIT(bool,_ui)
+		BIGRAT_INIT(char,_si)
+		BIGRAT_INIT(signed char,_si)
+		BIGRAT_INIT(unsigned char,_ui)
+		BIGRAT_INIT(short,_si)
+		BIGRAT_INIT(unsigned short,_ui)
+		BIGRAT_INIT(int,_si)
+		BIGRAT_INIT(unsigned int,_ui)
+		BIGRAT_INIT(long,_si)
+		BIGRAT_INIT(unsigned long,_ui)
+		BIGRAT_INIT2(float,_d)
+		BIGRAT_INIT2(double,_d)
+		BIGRAT_INIT2(mpz_srcptr,_z)
+		BIGRAT_INIT2(const BigInteger&,_z)
+		BIGRAT_INIT2(mpq_srcptr,)
+		BIGRAT_INIT2(const BigRational&,)
+
+#undef BIGRAT_INIT2
+#undef BIGRAT_INIT
+
+		inline BigRational(const BigInteger& num, const BigInteger& den)
+		{
+			mpq_init(m_val);
+			mpz_set(mpq_numref(m_val),num);
+			mpz_set(mpq_denref(m_val),den);
+			if( mpz_cmp_ui(den,1) )
+				mpq_canonicalize(m_val);
+		}
+
+		explicit inline BigRational(const char* val, int base = 0)
+		{
+			mpq_init(m_val);
+			if( mpq_set_str(m_val,val,base) ) {
+				mpq_clear(m_val);
+				throw std::runtime_error("Invalid string value for BigRat");
+			}
+			mpq_canonicalize(m_val);
+		}
+
+		explicit inline BigRational(const std::string& val, int base = 0)
+		{
+			mpq_init(m_val);
+			if( mpq_set_str(m_val,val.c_str(),base) ) {
+				mpq_clear(m_val);
+				throw std::runtime_error("Invalid string value for BigRat");
+			}
+			mpq_canonicalize(m_val);
+		}
+
+		template < class Expr >
+		inline BigRational(const detail::BIX<Expr>& expr)
+		{
+			mpq_init(m_val);
+			expr.evalTmp(mpq_numref(m_val));
+			mpz_set_ui(mpq_denref(m_val),1);
+		}
+
+		template < class Expr >
+		inline BigRational(const detail::BRX<Expr>& expr)
+		{
+			mpq_init(m_val);
+			expr.evalTmp(m_val);
+			if( !Expr::isCanonical )
+				mpq_canonicalize(m_val);
+		}
+
+		inline ~BigRational()
+		{
+			mpq_clear(m_val);
+		}
+
+		inline void set(const char* val, int base = 0)
+		{
+			if( mpq_set_str(m_val,val,base) )
+				throw std::runtime_error("Invalid string value for BigRat");
+			mpq_canonicalize(m_val);
+		}
+
+		inline void set(const std::string& val, int base = 0)
+		{
+			if( mpq_set_str(m_val,val.c_str(),base) )
+				throw std::runtime_error("Invalid string value for BigRat");
+			mpq_canonicalize(m_val);
+		}
+
+#define BIGRAT_ASSIGN(type,suffix)										\
+		inline void set(type num, unsigned long den = 1)				\
+		{																\
+			mpq_set##suffix(m_val,num,den);								\
+			if( den != 1 )												\
+				mpq_canonicalize(m_val);								\
+		}																\
+		inline BigRational& operator =(type num)						\
+		{																\
+			set(num);													\
+			return *this;												\
+		}
+
+#define BIGRAT_ASSIGN2(type,suffix)										\
+		inline BigRational& operator =(type val)						\
+		{																\
+			mpq_set##suffix(m_val,val);									\
+			return *this;												\
+		}
+
+		BIGRAT_ASSIGN(bool,_ui)
+		BIGRAT_ASSIGN(char,_si)
+		BIGRAT_ASSIGN(signed char,_si)
+		BIGRAT_ASSIGN(unsigned char,_ui)
+		BIGRAT_ASSIGN(short,_si)
+		BIGRAT_ASSIGN(unsigned short,_ui)
+		BIGRAT_ASSIGN(int,_si)
+		BIGRAT_ASSIGN(unsigned int,_ui)
+		BIGRAT_ASSIGN(long,_si)
+		BIGRAT_ASSIGN(unsigned long,_ui)
+		BIGRAT_ASSIGN2(float,_d)
+		BIGRAT_ASSIGN2(double,_d)
+		BIGRAT_ASSIGN2(mpz_srcptr,_z)
+		BIGRAT_ASSIGN2(const BigInteger&,_z)
+
+#undef BIGRAT_ASSIGN2
+#undef BIGRAT_ASSIGN
+
+		inline BigRational& operator =(mpq_srcptr val)
+		{
+			if( m_val != val )
+				mpq_set(m_val,val);
+			return *this;
+		}
+
+		inline BigRational& operator =(const BigRational& val)
+		{
+			if( m_val != val.m_val )
+				mpq_set(m_val,val.m_val);
+			return *this;
+		}
+
+		inline BigRational& operator =(const char* val)
+		{
+			set(val);
+			return *this;
+		}
+
+		inline BigRational& operator =(const std::string& val)
+		{
+			set(val);
+			return *this;
+		}
+
+		template < class Expr >
+		inline BigRational& operator =(const detail::BIX<Expr>& expr)
+		{
+			expr.eval(mpq_numref(m_val));
+			mpz_set_ui(mpq_denref(m_val),1);
+			return *this;
+		}
+
+		template < class Expr >
+		inline BigRational& operator =(const detail::BRX<Expr>& expr)
+		{
+			expr.eval(m_val);
+			if( !Expr::isCanonical )
+				mpq_canonicalize(m_val);
+			return *this;
+		}
+
+		inline BigRational& operator ++()
+		{
+			mpz_add(mpq_numref(m_val),mpq_numref(m_val),mpq_denref(m_val));
+			return *this;
+		}
+
+		inline BigRational& operator --()
+		{
+			mpz_sub(mpq_numref(m_val),mpq_numref(m_val),mpq_denref(m_val));
+			return *this;
+		}
+
+#define BIGRAT_IPOPER(fun,type,argtype,impl)							\
+		inline BigRational& fun(type val)								\
+		{																\
+			typedef detail::MPQ::impl<mpq_srcptr,argtype,true> impl_t;	\
+			impl_t::eval(m_val,m_val,val);								\
+			if( !impl_t::isCanonical )									\
+				mpq_canonicalize(m_val);								\
+			return *this;												\
+		}
+
+#define BIGRAT_INTIPOPER(fun,impl)										\
+		BIGRAT_IPOPER(fun,bool,unsigned long,impl)						\
+		BIGRAT_IPOPER(fun,char,long,impl)								\
+		BIGRAT_IPOPER(fun,signed char,long,impl)						\
+		BIGRAT_IPOPER(fun,unsigned char,unsigned long,impl)				\
+		BIGRAT_IPOPER(fun,short,long,impl)								\
+		BIGRAT_IPOPER(fun,unsigned short,unsigned long,impl)			\
+		BIGRAT_IPOPER(fun,int,long,impl)								\
+		BIGRAT_IPOPER(fun,unsigned int,unsigned long,impl)				\
+		BIGRAT_IPOPER(fun,long,long,impl)								\
+		BIGRAT_IPOPER(fun,unsigned long,unsigned long,impl)
+
+#define BIGRAT_FLOATIPOPER(fun,impl)									\
+		BIGRAT_IPOPER(fun,float,double,impl)							\
+		BIGRAT_IPOPER(fun,double,double,impl)
+
+#define BIGRAT_MPZIPOPER(fun,impl)										\
+		BIGRAT_IPOPER(fun,mpz_srcptr,mpz_srcptr,impl)					\
+		BIGRAT_IPOPER(fun,const BigInteger&,mpz_srcptr,impl)
+
+#define BIGRAT_MPQIPOPER(fun,impl)										\
+		BIGRAT_IPOPER(fun,mpq_srcptr,mpq_srcptr,impl)					\
+		BIGRAT_IPOPER(fun,const BigRational&,mpq_srcptr,impl)
+
+#define BIGRAT_BIEXPRIPOPER(fun,impl)									\
+		template < class Expr >											\
+		inline BigRational& fun(const detail::BIX<Expr>& val)			\
+		{																\
+			typedef detail::MPQ::impl<mpq_srcptr,mpz_srcptr,			\
+									  true> impl_t;						\
+			BigInteger tmp(val);										\
+			impl_t::eval(m_val,m_val,tmp);								\
+			if( !impl_t::isCanonical )									\
+				mpq_canonicalize(m_val);								\
+			return *this;												\
+		}
+
+#define BIGRAT_BREXPRIPOPER(fun,impl)									\
+		template < class Expr >											\
+		inline BigRational& fun(const detail::BRX<Expr>& val)			\
+		{																\
+			typedef detail::MPQ::impl<mpq_srcptr,mpq_srcptr,			\
+									  Expr::isCanonical> impl_t;		\
+			mpq_t tmp;													\
+			mpq_init(tmp);												\
+			val.evalTmp(tmp);											\
+			if( impl_t::needCanonical )									\
+				mpq_canonicalize(tmp);									\
+			impl_t::eval(m_val,m_val,tmp);								\
+			mpq_clear(tmp);												\
+			if( !impl_t::isCanonical )									\
+				mpq_canonicalize(m_val);								\
+			return *this;												\
+		}
+
+#define BIGRAT_BASEIPOPER(fun,impl)										\
+		BIGRAT_INTIPOPER(fun,impl)										\
+		BIGRAT_MPZIPOPER(fun,impl)										\
+		BIGRAT_BIEXPRIPOPER(fun,impl)
+
+#define BIGRAT_ALLIPOPER(fun,impl)										\
+		BIGRAT_BASEIPOPER(fun,impl)										\
+		BIGRAT_FLOATIPOPER(fun,impl)									\
+		BIGRAT_MPQIPOPER(fun,impl)										\
+		BIGRAT_BREXPRIPOPER(fun,impl)
+
+		BIGRAT_ALLIPOPER(operator +=,Add)
+		BIGRAT_ALLIPOPER(operator -=,Sub)
+		BIGRAT_ALLIPOPER(operator *=,Mul)
+		BIGRAT_ALLIPOPER(operator /=,Div)
+		BIGRAT_BASEIPOPER(operator <<=,Lshift)
+		BIGRAT_BASEIPOPER(operator >>=,Rshift)
+
+#undef BIGRAT_ALLIPOPER
+#undef BIGRAT_BASEIPOPER
+#undef BIGRAT_BREXPRIPOPER
+#undef BIGRAT_BIEXPRIPOPER
+#undef BIGRAT_MPQIPOPER
+#undef BIGRAT_MPZIPOPER
+#undef BIGRAT_FLOATIPOPER
+#undef BIGRAT_INTIPOPER
+#undef BIGRAT_IPOPER
+
+		inline operator bool() const
+		{
+			return mpq_sgn(m_val);
+		}
+
+#define BIGRAT_CONV(type,suffix)										\
+		inline operator type() const									\
+		{																\
+			return mpq_get##suffix(m_val);								\
+		}
+
+		BIGRAT_CONV(float,_d)
+		BIGRAT_CONV(double,_d)
+
+#undef BIGRAT_CONV
+
+		inline operator mpq_ptr()
+		{
+			return m_val;
+		}
+
+		inline mpq_ptr get_mpq_t()
+		{
+			return m_val;
+		}
+
+		inline mpq_ptr operator ->()
+		{
+			return m_val;
+		}
+
+		inline operator mpq_srcptr() const
+		{
+			return m_val;
+		}
+
+		inline mpq_srcptr get_mpq_t() const
+		{
+			return m_val;
+		}
+
+		inline mpq_srcptr operator ->() const
+		{
+			return m_val;
+		}
+
+		inline BigInteger& get_num()
+		{
+			return reinterpret_cast<BigInteger&>(*mpq_numref(m_val));
+		}
+
+		inline const BigInteger& get_num() const
+		{
+			return reinterpret_cast<const BigInteger&>(*mpq_numref(m_val));
+		}
+
+		inline BigInteger& get_den()
+		{
+			return reinterpret_cast<BigInteger&>(*mpq_denref(m_val));
+		}
+
+		inline const BigInteger& get_den() const
+		{
+			return reinterpret_cast<const BigInteger&>(*mpq_denref(m_val));
+		}
+
+		inline void get_string(char* val, int base = 10) const
+		{
+			mpq_get_str(val,base,m_val);
+		}
+
+		inline void get_string(std::string& val, int base = 10) const
+		{
+			char* buf = new char[mpz_sizeinbase(mpq_numref(m_val),base)+
+								 mpz_sizeinbase(mpq_denref(m_val),base)+3];
+			val = mpq_get_str(buf,base,m_val);
+			delete [] buf;
+		}
+
+		inline std::string get_string(int base = 10) const
+		{
+			std::string rv;
+			get_string(rv,base);
+			return rv;
+		}
+
+		inline operator std::string() const
+		{
+			return get_string();
+		}
+
+		inline void canonicalize()
+		{
+			mpq_canonicalize(m_val);
+		}
+
+	};
+
+	inline BigInteger::BigInteger(const BigRational& val)
+	{
+		mpz_init(m_val);
+		mpz_tdiv_q(m_val,val.get_num(),val.get_den());
+	}
+
+	namespace detail
+	{
+
+		template < class Expr >
+		class BIX
+		{
+
+		private:
+
+			Expr m_expr;
+
+		public:
+
+			inline BIX(const Expr& expr) :
+				m_expr(expr)
+			{
+			}
+
+			inline operator BigInteger() const
+			{
+				return BigInteger(*this);
+			}
+
+			inline operator BigRational() const
+			{
+				return BigRational(*this);
+			}
+
+			inline void eval(mpz_ptr dst) const
+			{
+				m_expr.eval(dst);
+			}
+
+			inline void evalTmp(mpz_ptr tmp) const
+			{
+				m_expr.evalTmp(tmp);
+			}
+
+#define BIX_CONV(type)													\
+			inline operator type() const								\
+			{															\
+				return BigInteger(*this);								\
+			}
+
+			BIX_CONV(bool)
+			BIX_CONV(char)
+			BIX_CONV(signed char)
+			BIX_CONV(unsigned char)
+			BIX_CONV(short)
+			BIX_CONV(unsigned short)
+			BIX_CONV(int)
+			BIX_CONV(unsigned int)
+			BIX_CONV(long)
+			BIX_CONV(unsigned long)
+			BIX_CONV(float)
+			BIX_CONV(double)
+			BIX_CONV(std::string)
+
+#undef BIX_CONV
+
+		};
+
+		template < class Expr >
+		class BRX
+		{
+
+		private:
+
+			Expr m_expr;
+
+		public:
+
+			inline BRX(const Expr& expr) :
+				m_expr(expr)
+			{
+			}
+
+			inline operator BigRational() const
+			{
+				return BigRational(*this);
+			}
+
+			inline void eval(mpq_ptr dst) const
+			{
+				m_expr.eval(dst);
+			}
+
+			inline void evalTmp(mpq_ptr tmp) const
+			{
+				m_expr.evalTmp(tmp);
+			}
+
+#define BRX_CONV(type)													\
+			inline operator type() const								\
+			{															\
+				return BigRational(*this);								\
+			}
+
+			BRX_CONV(float)
+			BRX_CONV(double)
+			BRX_CONV(std::string)
+
+#undef BRX_CONV
+
+		};
+
+	}
+
+#define BIX_FWDBICLASSDEF(name,type,impl)								\
+	namespace detail													\
+	{																	\
+		class BIX_Fwd_##name											\
+		{																\
+		private:														\
+			mpz_srcptr m_val1;											\
+			type m_val2;												\
+			typedef MPZ::impl<mpz_srcptr,type> impl_t;					\
+		public:															\
+			inline BIX_Fwd_##name(mpz_srcptr val1, type val2) :			\
+				m_val1(val1), m_val2(val2)								\
+			{															\
+			}															\
+			inline void eval(mpz_ptr dst) const							\
+			{															\
+				impl_t::eval(dst,m_val1,m_val2);						\
+			}															\
+			inline void evalTmp(mpz_ptr tmp) const						\
+			{															\
+				impl_t::eval(tmp,m_val1,m_val2);						\
+			}															\
+		};																\
+	}
+
+#define BIX_FWDEXCLASSDEF(name,type,impl)								\
+	namespace detail													\
+	{																	\
+		template < class Expr >											\
+		class BIX_Fwd_##name##_Expr										\
+		{																\
+		private:														\
+			BIX<Expr> m_val1;											\
+			type m_val2;												\
+			typedef MPZ::impl<mpz_srcptr,type> impl_t;					\
+		public:															\
+			inline BIX_Fwd_##name##_Expr(const BIX<Expr>& val1,			\
+										 type val2) :					\
+				m_val1(val1), m_val2(val2)								\
+			{															\
+			}															\
+			inline void	eval(mpz_ptr dst) const							\
+			{															\
+				BigInteger tmp(m_val1);									\
+				impl_t::eval(dst,tmp,m_val2);							\
+			}															\
+			inline void evalTmp(mpz_ptr tmp) const						\
+			{															\
+				m_val1.evalTmp(tmp);									\
+				impl_t::eval(tmp,tmp,m_val2);							\
+			}															\
+		};																\
+	}
+
+#define BIX_FWDCLASSDEF(name,type,impl)									\
+	BIX_FWDBICLASSDEF(name,type,impl)									\
+	BIX_FWDEXCLASSDEF(name,type,impl)
+
+#define BIX_REVBICLASSDEF(name,type,impl)								\
+	namespace detail													\
+	{																	\
+		class BIX_Rev_##name											\
+		{																\
+		private:														\
+			type m_val1;												\
+			mpz_srcptr m_val2;											\
+			typedef MPZ::impl<type,mpz_srcptr> impl_t;					\
+		public:															\
+			inline BIX_Rev_##name(type val1, mpz_srcptr val2) :			\
+				m_val1(val1), m_val2(val2)								\
+			{															\
+			}															\
+			inline void eval(mpz_ptr dst) const							\
+			{															\
+				impl_t::eval(dst,m_val1,m_val2);						\
+			}															\
+			inline void evalTmp(mpz_ptr tmp) const						\
+			{															\
+				impl_t::eval(tmp,m_val1,m_val2);						\
+			}															\
+		};																\
+	}
+
+#define BIX_REVEXCLASSDEF(name,type,impl)								\
+	namespace detail													\
+	{																	\
+		template < class Expr >											\
+		class BIX_Rev_##name##_Expr										\
+		{																\
+		private:														\
+			type m_val1;												\
+			BIX<Expr> m_val2;											\
+			typedef MPZ::impl<type,mpz_srcptr> impl_t;					\
+		public:															\
+			inline BIX_Rev_##name##_Expr(type val1,						\
+										 const BIX<Expr>& val2) :		\
+				m_val1(val1), m_val2(val2)								\
+			{															\
+			}															\
+			inline void eval(mpz_ptr dst) const							\
+			{															\
+				BigInteger tmp(m_val2);									\
+				impl_t::eval(dst,m_val1,tmp);							\
+			}															\
+			inline void evalTmp(mpz_ptr tmp) const						\
+			{															\
+				m_val2.evalTmp(tmp);									\
+				impl_t::eval(tmp,m_val1,tmp);							\
+			}															\
+		};																\
+	}
+
+#define BIX_REVCLASSDEF(name,type,impl)									\
+	BIX_REVBICLASSDEF(name,type,impl)									\
+	BIX_REVEXCLASSDEF(name,type,impl)
+
+#define BIX_EXPRCLASSDEF(name,impl)										\
+	namespace detail													\
+	{																	\
+		template < class Expr1, class Expr2 >							\
+		class BIX_##name##_Exprs										\
+		{																\
+		private:														\
+			BIX<Expr1> m_val1;											\
+			BIX<Expr2> m_val2;											\
+			typedef MPZ::impl<mpz_srcptr,mpz_srcptr> impl_t;			\
+		public:															\
+			inline BIX_##name##_Exprs(const BIX<Expr1>& val1,			\
+									  const BIX<Expr2>& val2) :			\
+				m_val1(val1), m_val2(val2)								\
+			{															\
+			}															\
+			inline void eval(mpz_ptr dst) const							\
+			{															\
+				BigInteger tmp(m_val1), tmp2(m_val2);					\
+				impl_t::eval(dst,tmp,tmp2);								\
+			}															\
+			inline void evalTmp(mpz_ptr tmp) const						\
+			{															\
+				m_val1.evalTmp(tmp);									\
+				BigInteger tmp2(m_val2);								\
+				impl_t::eval(tmp,tmp,tmp2);								\
+			}															\
+		};																\
+	}
+
+#define BIX_FWDBIFUNDEF(name,type,fun)									\
+	inline detail::BIX<detail::BIX_Fwd_##name>							\
+	fun(const BigInteger& val1, type val2)								\
+	{																	\
+		return detail::BIX<detail::BIX_Fwd_##name>						\
+			(detail::BIX_Fwd_##name(val1,val2));						\
+	}
+
+#define BIX_FWDEXFUNDEF(name,type,fun)									\
+	template < class SubExpr >											\
+	inline detail::BIX< detail::BIX_Fwd_##name##_Expr<SubExpr> >		\
+	fun(const detail::BIX<SubExpr>& val1, type val2)					\
+	{																	\
+		return detail::BIX< detail::BIX_Fwd_##name##_Expr<SubExpr> >	\
+			(detail::BIX_Fwd_##name##_Expr<SubExpr>(val1,val2));		\
+	}
+
+#define BIX_FWDFUNDEF(name,type,fun)									\
+	BIX_FWDBIFUNDEF(name,type,fun)										\
+	BIX_FWDEXFUNDEF(name,type,fun)
+
+#define BIX_REVBIFUNDEF(name,type,fun)									\
+	inline detail::BIX<detail::BIX_Rev_##name>							\
+	fun(type val1, const BigInteger& val2)								\
+	{																	\
+		return detail::BIX<detail::BIX_Rev_##name>						\
+			(detail::BIX_Rev_##name(val1,val2));						\
+	}
+
+#define BIX_REVEXFUNDEF(name,type,fun)									\
+	template < class SubExpr >											\
+	inline detail::BIX< detail::BIX_Rev_##name##_Expr<SubExpr> >		\
+	fun(type val1, const detail::BIX<SubExpr>& val2)					\
+	{																	\
+		return detail::BIX< detail::BIX_Rev_##name##_Expr<SubExpr> >	\
+			(detail::BIX_Rev_##name##_Expr<SubExpr>(val1,val2));		\
+	}
+
+#define BIX_REVFUNDEF(name,type,fun)									\
+	BIX_REVBIFUNDEF(name,type,fun)										\
+	BIX_REVEXFUNDEF(name,type,fun)
+
+#define BIX_EXPRFUNDEF(name,fun)										\
+	template < class SubExpr1, class SubExpr2 >							\
+	inline detail::BIX< detail::BIX_##name##_Exprs<SubExpr1,SubExpr2> >	\
+	fun(const detail::BIX<SubExpr1>& val1,								\
+		const detail::BIX<SubExpr2>& val2)								\
+	{																	\
+		return detail::BIX<												\
+				detail::BIX_##name##_Exprs<SubExpr1,SubExpr2>			\
+			>															\
+			(detail::BIX_##name##_Exprs<SubExpr1,SubExpr2>(val1,val2));	\
+	}
+
+#define BIX_FWDINTDEFS(name,fun,impl)									\
+	BIX_FWDCLASSDEF(Signed_##name,long,impl)							\
+	BIX_FWDCLASSDEF(Unsigned_##name,unsigned long,impl)					\
+	BIX_FWDFUNDEF(Unsigned_##name,bool,fun)								\
+	BIX_FWDFUNDEF(Signed_##name,char,fun)								\
+	BIX_FWDFUNDEF(Signed_##name,signed char,fun)						\
+	BIX_FWDFUNDEF(Unsigned_##name,unsigned char,fun)					\
+	BIX_FWDFUNDEF(Signed_##name,short,fun)								\
+	BIX_FWDFUNDEF(Unsigned_##name,unsigned short,fun)					\
+	BIX_FWDFUNDEF(Signed_##name,int,fun)								\
+	BIX_FWDFUNDEF(Unsigned_##name,unsigned int,fun)						\
+	BIX_FWDFUNDEF(Signed_##name,long,fun)								\
+	BIX_FWDFUNDEF(Unsigned_##name,unsigned long,fun)
+
+#define BIX_REVINTDEFS(name,fun,impl)									\
+	BIX_REVCLASSDEF(Signed_##name,long,impl)							\
+	BIX_REVCLASSDEF(Unsigned_##name,unsigned long,impl)					\
+	BIX_REVFUNDEF(Unsigned_##name,bool,fun)								\
+	BIX_REVFUNDEF(Signed_##name,char,fun)								\
+	BIX_REVFUNDEF(Signed_##name,signed char,fun)						\
+	BIX_REVFUNDEF(Unsigned_##name,unsigned char,fun)					\
+	BIX_REVFUNDEF(Signed_##name,short,fun)								\
+	BIX_REVFUNDEF(Unsigned_##name,unsigned short,fun)					\
+	BIX_REVFUNDEF(Signed_##name,int,fun)								\
+	BIX_REVFUNDEF(Unsigned_##name,unsigned int,fun)						\
+	BIX_REVFUNDEF(Signed_##name,long,fun)								\
+	BIX_REVFUNDEF(Unsigned_##name,unsigned long,fun)
+
+#define BIX_FWDFLOATDEFS(name,fun,impl)									\
+	BIX_FWDCLASSDEF(Float_##name,double,impl)							\
+	BIX_FWDFUNDEF(Float_##name,float,fun)								\
+	BIX_FWDFUNDEF(Float_##name,double,fun)
+
+#define BIX_REVFLOATDEFS(name,fun,impl)									\
+	BIX_REVCLASSDEF(Float_##name,double,impl)							\
+	BIX_REVFUNDEF(Float_##name,float,fun)								\
+	BIX_REVFUNDEF(Float_##name,double,fun)
+
+#define BIX_FWDMPZDEFS(name,fun,impl)									\
+	BIX_FWDCLASSDEF(MPZ_##name,mpz_srcptr,impl)							\
+	BIX_FWDFUNDEF(MPZ_##name,mpz_srcptr,fun)							\
+	BIX_FWDFUNDEF(MPZ_##name,const BigInteger&,fun)
+
+#define BIX_REVMPZDEFS(name,fun,impl)									\
+	BIX_REVCLASSDEF(MPZ_##name,mpz_srcptr,impl)							\
+	BIX_REVFUNDEF(MPZ_##name,mpz_srcptr,fun)							\
+	BIX_REVEXFUNDEF(MPZ_##name,const BigInteger&,fun)
+
+#define BIX_EXPRDEFS(name,fun,impl)										\
+	BIX_EXPRCLASSDEF(name,impl)											\
+	BIX_EXPRFUNDEF(name,fun)
+
+#define BIX_BASEDEFS(name,fun,impl)										\
+	BIX_FWDINTDEFS(name,fun,impl)										\
+	BIX_REVINTDEFS(name,fun,impl)										\
+	BIX_FWDMPZDEFS(name,fun,impl)										\
+	BIX_REVMPZDEFS(name,fun,impl)										\
+	BIX_EXPRDEFS(name,fun,impl)
+
+#define BIX_ALLDEFS(name,fun,impl)										\
+	BIX_BASEDEFS(name,fun,impl)											\
+	BIX_FWDFLOATDEFS(name,fun,impl)										\
+	BIX_REVFLOATDEFS(name,fun,impl)
+
+	BIX_ALLDEFS(Add,operator +,Add)
+	BIX_ALLDEFS(Sub,operator -,Sub)
+	BIX_ALLDEFS(Mul,operator *,Mul)
+	BIX_ALLDEFS(Div,operator /,Div)
+	BIX_ALLDEFS(Mod,operator %,Mod)
+	BIX_BASEDEFS(And,operator &,And)
+	BIX_BASEDEFS(Ior,operator |,Ior)
+	BIX_BASEDEFS(Xor,operator ^,Xor)
+	BIX_BASEDEFS(Lshift,operator <<,Lshift)
+	BIX_BASEDEFS(Rshift,operator >>,Rshift)
+
+#undef BIX_ALLDEFS
+#undef BIX_BASEDEFS
+#undef BIX_EXPRDEFS
+#undef BIX_REVMPZDEFS
+#undef BIX_FWDMPZDEFS
+#undef BIX_REVFLOATDEFS
+#undef BIX_FWDFLOATDEFS
+#undef BIX_REVINTDEFS
+#undef BIX_FWDINTDEFS
+#undef BIX_EXPRFUNDEF
+#undef BIX_REVFUNDEF
+#undef BIX_REVEXFUNDEF
+#undef BIX_REVBIFUNDEF
+#undef BIX_FWDFUNDEF
+#undef BIX_FWDEXFUNDEF
+#undef BIX_FWDBIFUNDEF
+#undef BIX_EXPRCLASSDEF
+#undef BIX_REVCLASSDEF
+#undef BIX_REVEXCLASSDEF
+#undef BIX_REVBICLASSDEF
+#undef BIX_FWDCLASSDEF
+#undef BIX_FWDEXCLASSDEF
+#undef BIX_FWDBICLASSDEF
+
+#define BRX_FWDBRCLASSDEF(name,type,impl)								\
+	namespace detail													\
+	{																	\
+		class BRX_Fwd_##name											\
+		{																\
+		private:														\
+			mpq_srcptr m_val1;											\
+			type m_val2;												\
+			typedef MPQ::impl<mpq_srcptr,type,true> impl_t;				\
+		public:															\
+			static const bool isCanonical = impl_t::isCanonical;		\
+			inline BRX_Fwd_##name(mpq_srcptr val1, type val2) :			\
+				m_val1(val1), m_val2(val2)								\
+			{															\
+			}															\
+			inline void eval(mpq_ptr dst) const							\
+			{															\
+				impl_t::eval(dst,m_val1,m_val2);						\
+			}															\
+			inline void evalTmp(mpq_ptr tmp) const						\
+			{															\
+				impl_t::eval(tmp,m_val1,m_val2);						\
+			}															\
+		};																\
+	}
+
+#define BRX_FWDEXCLASSDEF(name,type,impl)								\
+	namespace detail													\
+	{																	\
+		template < class Expr >											\
+		class BRX_Fwd_##name##_Expr										\
+		{																\
+		private:														\
+			BRX<Expr> m_val1;											\
+			type m_val2;												\
+			typedef MPQ::impl<mpq_srcptr,type,							\
+							  Expr::isCanonical> impl_t;				\
+		public:															\
+			static const bool isCanonical = impl_t::isCanonical;		\
+			inline BRX_Fwd_##name##_Expr(const BRX<Expr>& val1,			\
+										 type val2) :					\
+				m_val1(val1), m_val2(val2)								\
+			{															\
+			}															\
+			inline void eval(mpq_ptr dst) const							\
+			{															\
+				mpq_t tmp;												\
+				mpq_init(tmp);											\
+				m_val1.evalTmp(tmp);									\
+				if( impl_t::needCanonical )								\
+					mpq_canonicalize(tmp);								\
+				impl_t::eval(dst,tmp,m_val2);							\
+				mpq_clear(tmp);											\
+			}															\
+			inline void evalTmp(mpq_ptr tmp) const						\
+			{															\
+				m_val1.evalTmp(tmp);									\
+				if( impl_t::needCanonical )								\
+					mpq_canonicalize(tmp);								\
+				impl_t::eval(tmp,tmp,m_val2);							\
+			}															\
+		};																\
+	}
+
+#define BRX_FWDCLASSDEF(name,type,impl)									\
+	BRX_FWDBRCLASSDEF(name,type,impl)									\
+	BRX_FWDEXCLASSDEF(name,type,impl)
+
+#define BRX_REVBRCLASSDEF(name,type,impl)								\
+	namespace detail													\
+	{																	\
+		class BRX_Rev_##name											\
+		{																\
+		private:														\
+			type m_val1;												\
+			mpq_srcptr m_val2;											\
+			typedef MPQ::impl<type,mpq_srcptr,true> impl_t;				\
+		public:															\
+			static const bool isCanonical = impl_t::isCanonical;		\
+			inline BRX_Rev_##name(type val1, mpq_srcptr val2) :			\
+				m_val1(val1), m_val2(val2)								\
+			{															\
+			}															\
+			inline void eval(mpq_ptr dst) const							\
+			{															\
+				impl_t::eval(dst,m_val1,m_val2);						\
+			}															\
+			inline void evalTmp(mpq_ptr tmp) const						\
+			{															\
+				impl_t::eval(tmp,m_val1,m_val2);						\
+			}															\
+		};																\
+	}
+
+#define BRX_REVEXCLASSDEF(name,type,impl)								\
+	namespace detail													\
+	{																	\
+		template < class Expr >											\
+		class BRX_Rev_##name##_Expr										\
+		{																\
+		private:														\
+			type m_val1;												\
+			BRX<Expr> m_val2;											\
+			typedef MPQ::impl<type,mpq_srcptr,							\
+							  Expr::isCanonical> impl_t;				\
+		public:															\
+			static const bool isCanonical = impl_t::isCanonical;		\
+			inline BRX_Rev_##name##_Expr(type val1,						\
+										 const BRX<Expr>& val2) :		\
+				m_val1(val1), m_val2(val2)								\
+			{															\
+			}															\
+			inline void eval(mpq_ptr dst) const							\
+			{															\
+				mpq_t tmp;												\
+				mpq_init(tmp);											\
+				m_val2.evalTmp(tmp);									\
+				if( impl_t::needCanonical )								\
+					mpq_canonicalize(tmp);								\
+				impl_t::eval(dst,m_val1,tmp);							\
+				mpq_clear(tmp);											\
+			}															\
+			inline void evalTmp(mpq_ptr tmp) const						\
+			{															\
+				m_val2.evalTmp(tmp);									\
+				if( impl_t::needCanonical )								\
+					mpq_canonicalize(tmp);								\
+				impl_t::eval(tmp,m_val1,tmp);							\
+			}															\
+		};																\
+	}
+
+#define BRX_REVCLASSDEF(name,type,impl)									\
+	BRX_REVBRCLASSDEF(name,type,impl)									\
+	BRX_REVEXCLASSDEF(name,type,impl)
+
+#define BRX_FWDBRBIEXCLASSDEF(name,impl)								\
+	namespace detail													\
+	{																	\
+		template < class Expr >											\
+		class BRX_Fwd_##name											\
+		{																\
+		private:														\
+			mpq_srcptr m_val1;											\
+			BIX<Expr> m_val2;											\
+			typedef MPQ::impl<mpq_srcptr,mpz_srcptr,true> impl_t;		\
+		public:															\
+			static const bool isCanonical = impl_t::isCanonical;		\
+			inline BRX_Fwd_##name(mpq_srcptr val1,						\
+								  const BIX<Expr>& val2) :				\
+				m_val1(val1), m_val2(val2)								\
+			{															\
+			}															\
+			inline void eval(mpq_ptr dst) const							\
+			{															\
+				BigInteger tmp(m_val2);									\
+				impl_t::eval(dst,m_val1,tmp);							\
+			}															\
+			inline void evalTmp(mpq_ptr tmp) const						\
+			{															\
+				m_val2.evalTmp(mpq_numref(tmp));						\
+				impl_t::eval(tmp,m_val1,mpq_numref(tmp));				\
+			}															\
+		};																\
+	}
+
+#define BRX_FWDEXBIEXCLASSDEF(name,impl)								\
+	namespace detail													\
+	{																	\
+		template < class Expr1, class Expr2 >							\
+		class BRX_Fwd_##name##_Expr										\
+		{																\
+		private:														\
+			BRX<Expr1> m_val1;											\
+			BIX<Expr2> m_val2;											\
+			typedef MPQ::impl<mpq_srcptr,mpz_srcptr,					\
+							  Expr1::isCanonical> impl_t;				\
+		public:															\
+			static const bool isCanonical = impl_t::isCanonical;		\
+			inline BRX_Fwd_##name##_Expr(const BRX<Expr1>& val1,		\
+										 const BIX<Expr2>& val2) :		\
+				m_val1(val1), m_val2(val2)								\
+			{															\
+			}															\
+			inline void eval(mpq_ptr dst) const							\
+			{															\
+				mpq_t tmp;												\
+				mpq_init(tmp);											\
+				m_val1.evalTmp(tmp);									\
+				if( impl_t::needCanonical )								\
+					mpq_canonicalize(tmp);								\
+				BigInteger tmp2(m_val2);								\
+				impl_t::eval(dst,tmp,tmp2);								\
+				mpq_clear(tmp);											\
+			}															\
+			inline void evalTmp(mpq_ptr tmp) const						\
+			{															\
+				m_val1.evalTmp(tmp);									\
+				if( impl_t::needCanonical )								\
+					mpq_canonicalize(tmp);								\
+				BigInteger tmp2(m_val2);								\
+				impl_t::eval(tmp,tmp,tmp2);								\
+			}															\
+		};																\
+	}
+
+#define BRX_FWDBIEXCLASSDEF(name,impl)									\
+	BRX_FWDBRBIEXCLASSDEF(name,impl)									\
+	BRX_FWDEXBIEXCLASSDEF(name,impl)
+
+#define BRX_REVBRBIEXCLASSDEF(name,impl)								\
+	namespace detail													\
+	{																	\
+		template < class Expr >											\
+		class BRX_Rev_##name											\
+		{																\
+		private:														\
+			BIX<Expr> m_val1;											\
+			mpq_srcptr m_val2;											\
+			typedef MPQ::impl<mpz_srcptr,mpq_srcptr,true> impl_t;		\
+		public:															\
+			static const bool isCanonical = impl_t::isCanonical;		\
+			inline BRX_Rev_##name(const BIX<Expr>& val1,				\
+								  mpq_srcptr val2) :					\
+				m_val1(val1), m_val2(val2)								\
+			{															\
+			}															\
+			inline void eval(mpq_ptr dst) const							\
+			{															\
+				BigInteger tmp(m_val1);									\
+				impl_t::eval(dst,tmp,m_val2);							\
+			}															\
+			inline void evalTmp(mpq_ptr tmp) const						\
+			{															\
+				m_val1.evalTmp(mpq_numref(tmp));						\
+				impl_t::eval(tmp,mpq_numref(tmp),m_val2);				\
+			}															\
+		};																\
+	}
+
+#define BRX_REVEXBIEXCLASSDEF(name,impl)								\
+	namespace detail													\
+	{																	\
+		template < class Expr1, class Expr2 >							\
+		class BRX_Rev_##name##_Expr										\
+		{																\
+		private:														\
+			BIX<Expr1> m_val1;											\
+			BRX<Expr2> m_val2;											\
+			typedef MPQ::impl<mpz_srcptr,mpq_srcptr,					\
+							  Expr2::isCanonical> impl_t;				\
+		public:															\
+			static const bool isCanonical = impl_t::isCanonical;		\
+			inline BRX_Rev_##name##_Expr(const BIX<Expr1>& val1,		\
+										 const BRX<Expr2>& val2) :		\
+				m_val1(val1), m_val2(val2)								\
+			{															\
+			}															\
+			inline void eval(mpq_ptr dst) const							\
+			{															\
+				BigInteger tmp(m_val1);									\
+				mpq_t tmp2;												\
+				mpq_init(tmp2);											\
+				m_val2.evalTmp(tmp2);									\
+				if( impl_t::needCanonical )								\
+					mpq_canonicalize(tmp2);								\
+				impl_t::eval(dst,tmp,tmp2);								\
+				mpq_clear(tmp2);										\
+			}															\
+			inline void evalTmp(mpq_ptr tmp) const						\
+			{															\
+				BigInteger tmp2(m_val1);								\
+				m_val2.evalTmp(tmp);									\
+				if( impl_t::needCanonical )								\
+					mpq_canonicalize(tmp);								\
+				impl_t::eval(tmp,tmp2,tmp);								\
+			}															\
+		};																\
+	}
+
+#define BRX_REVBIEXCLASSDEF(name,impl)									\
+	BRX_REVBRBIEXCLASSDEF(name,impl)									\
+	BRX_REVEXBIEXCLASSDEF(name,impl)
+
+#define BRX_EXPRCLASSDEF(name,impl)										\
+	namespace detail													\
+	{																	\
+		template < class Expr1, class Expr2 >							\
+		class BRX_##name##_Exprs										\
+		{																\
+		private:														\
+			BRX<Expr1> m_val1;											\
+			BRX<Expr2> m_val2;											\
+			typedef MPQ::impl<mpq_srcptr,mpq_srcptr,					\
+							  Expr1::isCanonical&&						\
+							  Expr2::isCanonical> impl_t;				\
+		public:															\
+			static const bool isCanonical = impl_t::isCanonical;		\
+			inline BRX_##name##_Exprs(const BRX<Expr1>& val1,			\
+									  const BRX<Expr2>& val2) :			\
+				m_val1(val1), m_val2(val2)								\
+			{															\
+			}															\
+			inline void eval(mpq_ptr dst) const							\
+			{															\
+				mpq_t tmp;												\
+				mpq_init(tmp);											\
+				m_val1.evalTmp(tmp);									\
+				if( impl_t::needCanonical && !Expr1::isCanonical )		\
+					mpq_canonicalize(tmp);								\
+				mpq_t tmp2;												\
+				mpq_init(tmp2);											\
+				m_val2.evalTmp(tmp2);									\
+				if( impl_t::needCanonical && !Expr2::isCanonical )		\
+					mpq_canonicalize(tmp2);								\
+				impl_t::eval(dst,tmp,tmp2);								\
+				mpq_clear(tmp2);										\
+				mpq_clear(tmp);											\
+			}															\
+			inline void evalTmp(mpq_ptr tmp) const						\
+			{															\
+				m_val1.evalTmp(tmp);									\
+				if( impl_t::needCanonical && !Expr1::isCanonical )		\
+					mpq_canonicalize(tmp);								\
+				mpq_t tmp2;												\
+				mpq_init(tmp2);											\
+				m_val2.evalTmp(tmp2);									\
+				if( impl_t::needCanonical && !Expr2::isCanonical )		\
+					mpq_canonicalize(tmp2);								\
+				impl_t::eval(tmp,tmp,tmp2);								\
+				mpq_clear(tmp2);										\
+			}															\
+		};																\
+	}
+
+#define BRX_FWDBRFUNDEF(name,type,fun)									\
+	inline detail::BRX<detail::BRX_Fwd_##name>							\
+	fun(const BigRational& val1, type val2)								\
+	{																	\
+		return detail::BRX<detail::BRX_Fwd_##name>						\
+			(detail::BRX_Fwd_##name(val1,val2));						\
+	}
+
+#define BRX_FWDEXFUNDEF(name,type,fun)									\
+	template < class SubExpr >											\
+	inline detail::BRX< detail::BRX_Fwd_##name##_Expr<SubExpr> >		\
+	fun(const detail::BRX<SubExpr>& val1, type val2)					\
+	{																	\
+		return detail::BRX< detail::BRX_Fwd_##name##_Expr<SubExpr> >	\
+			(detail::BRX_Fwd_##name##_Expr<SubExpr>(val1,val2));		\
+	}
+
+#define BRX_FWDFUNDEF(name,type,fun)									\
+	BRX_FWDBRFUNDEF(name,type,fun)										\
+	BRX_FWDEXFUNDEF(name,type,fun)
+
+#define BRX_REVBRFUNDEF(name,type,fun)									\
+	inline detail::BRX<detail::BRX_Rev_##name>							\
+	fun(type val1, const BigRational& val2)								\
+	{																	\
+		return detail::BRX<detail::BRX_Rev_##name>						\
+			(detail::BRX_Rev_##name(val1,val2));						\
+	}
+
+#define BRX_REVEXFUNDEF(name,type,fun)									\
+	template < class SubExpr >											\
+	inline detail::BRX< detail::BRX_Rev_##name##_Expr<SubExpr> >		\
+	fun(type val1, const detail::BRX<SubExpr>& val2)					\
+	{																	\
+		return detail::BRX< detail::BRX_Rev_##name##_Expr<SubExpr> >	\
+			(detail::BRX_Rev_##name##_Expr<SubExpr>(val1,val2));		\
+	}
+
+#define BRX_REVFUNDEF(name,type,fun)									\
+	BRX_REVBRFUNDEF(name,type,fun)										\
+	BRX_REVEXFUNDEF(name,type,fun)
+
+#define BRX_FWDBRBIEXFUNDEF(name,fun)									\
+	template < class SubExpr >											\
+	inline detail::BRX< detail::BRX_Fwd_##name<SubExpr> >				\
+	fun(const BigRational& val1, const detail::BIX<SubExpr>& val2)		\
+	{																	\
+		return detail::BRX< detail::BRX_Fwd_##name<SubExpr> >			\
+			(detail::BRX_Fwd_##name<SubExpr>(val1,val2));				\
+	}
+
+#define BRX_FWDEXBIEXFUNDEF(name,fun)									\
+	template < class SubExpr1, class SubExpr2 >							\
+	inline detail::BRX<													\
+		detail::BRX_Fwd_##name##_Expr<SubExpr1,SubExpr2>				\
+	>																	\
+	fun(const detail::BRX<SubExpr1>& val1,								\
+		const detail::BIX<SubExpr2>& val2)								\
+	{																	\
+		return detail::BRX<												\
+				detail::BRX_Fwd_##name##_Expr<SubExpr1,SubExpr2>		\
+			>															\
+			(detail::BRX_Fwd_##name##_Expr<SubExpr1,SubExpr2>			\
+			 (val1,val2));												\
+	}
+
+#define BRX_FWDBIEXFUNDEF(name,fun)										\
+	BRX_FWDBRBIEXFUNDEF(name,fun)										\
+	BRX_FWDEXBIEXFUNDEF(name,fun)
+
+#define BRX_REVBRBIEXFUNDEF(name,fun)									\
+	template < class SubExpr >											\
+	inline detail::BRX< detail::BRX_Rev_##name<SubExpr> >				\
+	fun(const detail::BIX<SubExpr>& val1, const BigRational& val2)		\
+	{																	\
+		return detail::BRX< detail::BRX_Rev_##name<SubExpr> >			\
+			(detail::BRX_Rev_##name<SubExpr>(val1,val2));				\
+	}
+
+#define BRX_REVEXBIEXFUNDEF(name,fun)									\
+	template < class SubExpr1, class SubExpr2 >							\
+	inline detail::BRX<													\
+		detail::BRX_Rev_##name##_Expr<SubExpr1,SubExpr2>				\
+	>																	\
+	fun(const detail::BIX<SubExpr1>& val1,								\
+		const detail::BRX<SubExpr2>& val2)								\
+	{																	\
+		return detail::BRX<												\
+				detail::BRX_Rev_##name##_Expr<SubExpr1,SubExpr2>		\
+			>															\
+			(detail::BRX_Rev_##name##_Expr<SubExpr1,SubExpr2>			\
+			 (val1,val2));												\
+	}
+
+#define BRX_REVBIEXFUNDEF(name,fun)										\
+	BRX_REVBRBIEXFUNDEF(name,fun)										\
+	BRX_REVEXBIEXFUNDEF(name,fun)
+
+#define BRX_EXPRFUNDEF(name,fun)										\
+	template < class SubExpr1, class SubExpr2 >							\
+	inline detail::BRX< detail::BRX_##name##_Exprs<SubExpr1,SubExpr2> >	\
+	fun(const detail::BRX<SubExpr1>& val1,								\
+		const detail::BRX<SubExpr2>& val2)								\
+	{																	\
+		return detail::BRX<												\
+				detail::BRX_##name##_Exprs<SubExpr1,SubExpr2>			\
+			>															\
+			(detail::BRX_##name##_Exprs<SubExpr1,SubExpr2>(val1,val2));	\
+	}
+
+#define BRX_FWDINTDEFS(name,fun,impl)									\
+	BRX_FWDCLASSDEF(Signed_##name,long,impl)							\
+	BRX_FWDCLASSDEF(Unsigned_##name,unsigned long,impl)					\
+	BRX_FWDFUNDEF(Unsigned_##name,bool,fun)								\
+	BRX_FWDFUNDEF(Signed_##name,char,fun)								\
+	BRX_FWDFUNDEF(Signed_##name,signed char,fun)						\
+	BRX_FWDFUNDEF(Unsigned_##name,unsigned char,fun)					\
+	BRX_FWDFUNDEF(Signed_##name,short,fun)								\
+	BRX_FWDFUNDEF(Unsigned_##name,unsigned short,fun)					\
+	BRX_FWDFUNDEF(Signed_##name,int,fun)								\
+	BRX_FWDFUNDEF(Unsigned_##name,unsigned int,fun)						\
+	BRX_FWDFUNDEF(Signed_##name,long,fun)								\
+	BRX_FWDFUNDEF(Unsigned_##name,unsigned long,fun)
+
+#define BRX_REVINTDEFS(name,fun,impl)									\
+	BRX_REVCLASSDEF(Signed_##name,long,impl)							\
+	BRX_REVCLASSDEF(Unsigned_##name,unsigned long,impl)					\
+	BRX_REVFUNDEF(Unsigned_##name,bool,fun)								\
+	BRX_REVFUNDEF(Signed_##name,char,fun)								\
+	BRX_REVFUNDEF(Signed_##name,signed char,fun)						\
+	BRX_REVFUNDEF(Unsigned_##name,unsigned char,fun)					\
+	BRX_REVFUNDEF(Signed_##name,short,fun)								\
+	BRX_REVFUNDEF(Unsigned_##name,unsigned short,fun)					\
+	BRX_REVFUNDEF(Signed_##name,int,fun)								\
+	BRX_REVFUNDEF(Unsigned_##name,unsigned int,fun)						\
+	BRX_REVFUNDEF(Signed_##name,long,fun)								\
+	BRX_REVFUNDEF(Unsigned_##name,unsigned long,fun)
+
+#define BRX_FWDFLOATDEFS(name,fun,impl)									\
+	BRX_FWDCLASSDEF(Float_##name,double,impl)							\
+	BRX_FWDFUNDEF(Float_##name,float,fun)								\
+	BRX_FWDFUNDEF(Float_##name,double,fun)
+
+#define BRX_REVFLOATDEFS(name,fun,impl)									\
+	BRX_REVCLASSDEF(Float_##name,double,impl)							\
+	BRX_REVFUNDEF(Float_##name,float,fun)								\
+	BRX_REVFUNDEF(Float_##name,double,fun)
+
+#define BRX_FWDMPZDEFS(name,fun,impl)									\
+	BRX_FWDCLASSDEF(MPZ_##name,mpz_srcptr,impl)							\
+	BRX_FWDBIEXCLASSDEF(BIEX_##name,impl)								\
+	BRX_FWDFUNDEF(MPZ_##name,mpz_srcptr,fun)							\
+	BRX_FWDFUNDEF(MPZ_##name,const BigInteger&,fun)						\
+	BRX_FWDBIEXFUNDEF(BIEX_##name,fun)
+
+#define BRX_REVMPZDEFS(name,fun,impl)									\
+	BRX_REVCLASSDEF(MPZ_##name,mpz_srcptr,impl)							\
+	BRX_REVBIEXCLASSDEF(BIEX_##name,impl)								\
+	BRX_REVFUNDEF(MPZ_##name,mpz_srcptr,fun)							\
+	BRX_REVFUNDEF(MPZ_##name,const BigInteger&,fun)						\
+	BRX_REVBIEXFUNDEF(BIEX_##name,fun)
+
+#define BRX_FWDMPQDEFS(name,fun,impl)									\
+	BRX_FWDCLASSDEF(MPQ_##name,mpq_srcptr,impl)							\
+	BRX_FWDFUNDEF(MPQ_##name,mpq_srcptr,fun)							\
+	BRX_FWDFUNDEF(MPQ_##name,const BigRational&,fun)
+
+#define BRX_REVMPQDEFS(name,fun,impl)									\
+	BRX_REVCLASSDEF(MPQ_##name,mpq_srcptr,impl)							\
+	BRX_REVFUNDEF(MPQ_##name,mpq_srcptr,fun)							\
+	BRX_REVEXFUNDEF(MPQ_##name,const BigRational&,fun)
+
+#define BRX_EXPRDEFS(name,fun,impl)										\
+	BRX_EXPRCLASSDEF(name,impl)											\
+	BRX_EXPRFUNDEF(name,fun)
+
+#define BRX_BASEDEFS(name,fun,impl)										\
+	BRX_FWDINTDEFS(name,fun,impl)										\
+	BRX_FWDMPZDEFS(name,fun,impl)
+
+#define BRX_ALLDEFS(name,fun,impl)										\
+	BRX_BASEDEFS(name,fun,impl)											\
+	BRX_REVINTDEFS(name,fun,impl)										\
+	BRX_FWDFLOATDEFS(name,fun,impl)										\
+	BRX_REVFLOATDEFS(name,fun,impl)										\
+	BRX_REVMPZDEFS(name,fun,impl)										\
+	BRX_FWDMPQDEFS(name,fun,impl)										\
+	BRX_REVMPQDEFS(name,fun,impl)										\
+	BRX_EXPRDEFS(name,fun,impl)
+
+	BRX_ALLDEFS(Add,operator +,Add)
+	BRX_ALLDEFS(Sub,operator -,Sub)
+	BRX_ALLDEFS(Mul,operator *,Mul)
+	BRX_ALLDEFS(Div,operator /,Div)
+	BRX_BASEDEFS(Lshift,operator <<,Lshift)
+	BRX_BASEDEFS(Rshift,operator >>,Rshift)
+
+#undef BRX_ALLDEFS
+#undef BRX_BASEDEFS
+#undef BRX_EXPRDEFS
+#undef BRX_REVMPQDEFS
+#undef BRX_FWDMPQDEFS
+#undef BRX_REVMPZDEFS
+#undef BRX_FWDMPZDEFS
+#undef BRX_REVFLOATDEFS
+#undef BRX_FWDFLOATDEFS
+#undef BRX_REVINTDEFS
+#undef BRX_FWDINTDEFS
+#undef BRX_EXPRFUNDEF
+#undef BRX_REVBIEXFUNDEF
+#undef BRX_REVEXBIEXFUNDEF
+#undef BRX_REVBRBIEXFUNDEF
+#undef BRX_FWDBIEXFUNDEF
+#undef BRX_FWDEXBIEXFUNDEF
+#undef BRX_FWDBRBIEXFUNDEF
+#undef BRX_REVFUNDEF
+#undef BRX_REVEXFUNDEF
+#undef BRX_REVBRFUNDEF
+#undef BRX_FWDFUNDEF
+#undef BRX_FWDEXFUNDEF
+#undef BRX_FWDBRFUNDEF
+#undef BRX_EXPRCLASSDEF
+#undef BRX_REVBIEXCLASSDEF
+#undef BRX_REVEXBIEXCLASSDEF
+#undef BRX_REVBRBIEXCLASSDEF
+#undef BRX_FWDBIEXCLASSDEF
+#undef BRX_FWDEXBIEXCLASSDEF
+#undef BRX_FWDBRBIEXCLASSDEF
+#undef BRX_REVCLASSDEF
+#undef BRX_REVEXCLASSDEF
+#undef BRX_REVBRCLASSDEF
+#undef BRX_FWDCLASSDEF
+#undef BRX_FWDEXCLASSDEF
+#undef BRX_FWDBRCLASSDEF
+
+#define BIX_UNARYCLASSDEF(name,impl)									\
+	namespace detail													\
+	{																	\
+		class BIX_Unary_##name											\
+		{																\
+		private:														\
+			mpz_srcptr m_val;											\
+			typedef MPZ::impl<mpz_srcptr> impl_t;						\
+		public:															\
+			inline BIX_Unary_##name(mpz_srcptr val) :					\
+				m_val(val)												\
+			{															\
+			}															\
+			inline void eval(mpz_ptr dst) const							\
+			{															\
+				impl_t::eval(dst,m_val);								\
+			}															\
+			inline void evalTmp(mpz_ptr tmp) const						\
+			{															\
+				impl_t::eval(tmp,m_val);								\
+			}															\
+		};																\
+		template < class Expr >											\
+		class BIX_Unary_##name##_Expr									\
+		{																\
+		private:														\
+			BIX<Expr> m_val;											\
+			typedef MPZ::impl<mpz_srcptr> impl_t;						\
+		public:															\
+			inline BIX_Unary_##name##_Expr(const BIX<Expr>& val) :		\
+				m_val(val)												\
+			{															\
+			}															\
+			inline void eval(mpz_ptr dst) const							\
+			{															\
+				m_val.eval(dst);										\
+				impl_t::eval(dst,dst);									\
+			}															\
+			inline void evalTmp(mpz_ptr tmp) const						\
+			{															\
+				m_val.evalTmp(tmp);										\
+				impl_t::eval(tmp,tmp);									\
+			}															\
+		};																\
+	}
+
+#define BIX_UNARYFUNDEF(name,type,fun)									\
+	inline detail::BIX<detail::BIX_Unary_##name>						\
+	fun(type val)														\
+	{																	\
+		return detail::BIX<detail::BIX_Unary_##name>					\
+			(detail::BIX_Unary_##name(val));							\
+	}
+
+#define BIX_UNARYEXFUNDEF(name,fun)										\
+	template < class SubExpr >											\
+	inline detail::BIX< detail::BIX_Unary_##name##_Expr<SubExpr> >		\
+	fun(const detail::BIX<SubExpr>& val)								\
+	{																	\
+		return detail::BIX< detail::BIX_Unary_##name##_Expr<SubExpr> >	\
+			(detail::BIX_Unary_##name##_Expr<SubExpr>(val));			\
+	}
+
+#define BIX_UNARYBASEDEFS(name,fun,impl)								\
+	BIX_UNARYCLASSDEF(name,impl)										\
+	BIX_UNARYFUNDEF(name,const BigInteger&,fun)							\
+	BIX_UNARYEXFUNDEF(name,fun)
+
+#define BIX_UNARYALLDEFS(name,fun,impl)									\
+	BIX_UNARYBASEDEFS(name,fun,impl)									\
+	BIX_UNARYFUNDEF(name,mpz_srcptr,fun)
+
+	BIX_UNARYBASEDEFS(Neg,operator -,Neg)
+	BIX_UNARYBASEDEFS(Inv,operator ~,Inv)
+	BIX_UNARYALLDEFS(Abs,abs,Abs)
+	BIX_UNARYALLDEFS(Sqrt,sqrt,Sqrt)
+
+#undef BIX_UNARYALLDEFS
+#undef BIX_UNARYBASEDEFS
+#undef BIX_UNARYEXFUNDEF
+#undef BIX_UNARYFUNDEF
+#undef BIX_UNARYCLASSDEF
+
+#define BRX_UNARYCLASSDEF(name,impl)									\
+	namespace detail													\
+	{																	\
+		class BRX_Unary_##name											\
+		{																\
+		private:														\
+			mpq_srcptr m_val;											\
+			typedef MPQ::impl<mpq_srcptr,true> impl_t;					\
+		public:															\
+			static const bool isCanonical = impl_t::isCanonical;		\
+			inline BRX_Unary_##name(mpq_srcptr val) :					\
+				m_val(val)												\
+			{															\
+			}															\
+			inline void eval(mpq_ptr dst) const							\
+			{															\
+				impl_t::eval(dst,m_val);								\
+			}															\
+			inline void evalTmp(mpq_ptr tmp) const						\
+			{															\
+				impl_t::eval(tmp,m_val);								\
+			}															\
+		};																\
+		template < class Expr >											\
+		class BRX_Unary_##name##_Expr									\
+		{																\
+		private:														\
+			BRX<Expr> m_val;											\
+			typedef MPQ::impl<mpq_srcptr,Expr::isCanonical> impl_t;		\
+		public:															\
+			static const bool isCanonical = impl_t::isCanonical;		\
+			inline BRX_Unary_##name##_Expr(const BRX<Expr>& val) :		\
+				m_val(val)												\
+			{															\
+			}															\
+			inline void eval(mpq_ptr dst) const							\
+			{															\
+				m_val.eval(dst);										\
+				if( impl_t::needCanonical )								\
+					mpq_canonicalize(dst);								\
+				impl_t::eval(dst,dst);									\
+			}															\
+			inline void evalTmp(mpq_ptr tmp) const						\
+			{															\
+				m_val.evalTmp(tmp);										\
+				if( impl_t::needCanonical )								\
+					mpq_canonicalize(tmp);								\
+				impl_t::eval(tmp,tmp);									\
+			}															\
+		};																\
+	}
+
+#define BRX_UNARYFUNDEF(name,type,fun)									\
+	inline detail::BRX<detail::BRX_Unary_##name>						\
+	fun(type val)														\
+	{																	\
+		return detail::BRX<detail::BRX_Unary_##name>					\
+			(detail::BRX_Unary_##name(val));							\
+	}
+
+#define BRX_UNARYEXFUNDEF(name,fun)										\
+	template < class SubExpr >											\
+	inline detail::BRX< detail::BRX_Unary_##name##_Expr<SubExpr> >		\
+	fun(const detail::BRX<SubExpr>& val)								\
+	{																	\
+		return detail::BRX< detail::BRX_Unary_##name##_Expr<SubExpr> >	\
+			(detail::BRX_Unary_##name##_Expr<SubExpr>(val));			\
+	}
+
+#define BRX_UNARYBASEDEFS(name,fun,impl)								\
+	BRX_UNARYCLASSDEF(name,impl)										\
+	BRX_UNARYFUNDEF(name,const BigRational&,fun)						\
+	BRX_UNARYEXFUNDEF(name,fun)
+
+#define BRX_UNARYALLDEFS(name,fun,impl)									\
+	BRX_UNARYBASEDEFS(name,fun,impl)									\
+	BRX_UNARYFUNDEF(name,mpq_srcptr,fun)
+
+	BRX_UNARYBASEDEFS(Neg,operator -,Neg)
+	BRX_UNARYBASEDEFS(Inv,operator ~,Inv)
+	BRX_UNARYALLDEFS(Abs,abs,Abs)
+
+#undef BRX_UNARYALLDEFS
+#undef BRX_UNARYBASEDEFS
+#undef BRX_UNARYEXFUNDEF
+#undef BRX_UNARYFUNDEF
+#undef BRX_UNARYCLASSDEF
+
+#define BIX_UNARYFUNDEF(rvtype,name,impl)								\
+	inline rvtype name(const BigInteger& val)							\
+	{																	\
+		typedef detail::MPZ::impl impl_t;								\
+		return impl_t::eval(val);										\
+	}																	\
+	template < class Expr >												\
+	inline rvtype name(const detail::BIX<Expr>& val)					\
+	{																	\
+		typedef detail::MPZ::impl impl_t;								\
+		BigInteger tmp(val);											\
+		return impl_t::eval(tmp);										\
+	}
+
+	BIX_UNARYFUNDEF(int,sgn,Sgn)
+
+#undef BIX_UNARYFUNDEF
+		
+#define BRX_UNARYFUNDEF(rvtype,name,impl)								\
+	inline rvtype name(const BigRational& val)							\
+	{																	\
+		typedef detail::MPQ::impl<true> impl_t;							\
+		return impl_t::eval(val);										\
+	}																	\
+	template < class Expr >												\
+	inline rvtype name(const detail::BRX<Expr>& val)					\
+	{																	\
+		typedef detail::MPQ::impl<Expr::isCanonical> impl_t;			\
+		mpq_t tmp;														\
+		mpq_init(tmp);													\
+		val.evalTmp(tmp);												\
+		if( impl_t::needCanonical )										\
+			mpq_canonicalize(tmp);										\
+		rvtype rv = impl_t::eval(tmp);									\
+		mpq_clear(tmp);													\
+		return rv;														\
+	}
+
+	BRX_UNARYFUNDEF(int,sgn,Sgn)
+
+#undef BRX_UNARYFUNDEF
+		
+	inline const BigInteger&
+	operator +(const BigInteger& val)
+	{
+		return val;
+	}
+
+	template < class Expr >
+	inline detail::BIX<Expr>
+	operator +(const detail::BIX<Expr>& val)
+	{
+		return val;
+	}
+
+	inline const BigRational&
+	operator +(const BigRational& val)
+	{
+		return val;
+	}
+
+	template < class Expr >
+	inline detail::BRX<Expr>
+	operator +(const detail::BRX<Expr>& val)
+	{
+		return val;
+	}
+
+	inline detail::BIX<detail::BIX_Fwd_Unsigned_Sub>
+	operator ++(BigInteger& val, int)
+	{
+		++val;
+		return detail::BIX<detail::BIX_Fwd_Unsigned_Sub>
+			(detail::BIX_Fwd_Unsigned_Sub(val,1));
+	}
+
+	inline detail::BIX<detail::BIX_Fwd_Unsigned_Add>
+	operator --(BigInteger& val, int)
+	{
+		--val;
+		return detail::BIX<detail::BIX_Fwd_Unsigned_Add>
+			(detail::BIX_Fwd_Unsigned_Add(val,1));
+	}
+
+	inline detail::BRX<detail::BRX_Fwd_Unsigned_Sub>
+	operator ++(BigRational& val, int)
+	{
+		++val;
+		return detail::BRX<detail::BRX_Fwd_Unsigned_Sub>
+			(detail::BRX_Fwd_Unsigned_Sub(val,1));
+	}
+
+	inline detail::BRX<detail::BRX_Fwd_Unsigned_Add>
+	operator --(BigRational& val, int)
+	{
+		--val;
+		return detail::BRX<detail::BRX_Fwd_Unsigned_Add>
+			(detail::BRX_Fwd_Unsigned_Add(val,1));
+	}
+
+#define BIX_FWDBICMPDEF(type,argtype,rvtype,name,impl,cmparg)			\
+	inline rvtype name(const BigInteger& val1, type val2)				\
+	{																	\
+		typedef detail::MPZ::impl<mpz_srcptr,argtype> impl_t;			\
+		return impl_t::eval(val1,val2) cmparg;							\
+	}
+
+#define BIX_FWDEXCMPDEF(type,argtype,rvtype,name,impl,cmparg)			\
+	template < class Expr >												\
+	inline rvtype name(const detail::BIX<Expr>& val1, type val2)		\
+	{																	\
+		typedef detail::MPZ::impl<mpz_srcptr,argtype> impl_t;			\
+		BigInteger tmp(val1);											\
+		return impl_t::eval(tmp,val2) cmparg;							\
+	}
+
+#define BIX_FWDCMPDEF(type,argtype,rvtype,name,impl,cmparg)				\
+	BIX_FWDBICMPDEF(type,argtype,rvtype,name,impl,cmparg)				\
+	BIX_FWDEXCMPDEF(type,argtype,rvtype,name,impl,cmparg)
+
+#define BIX_REVBICMPDEF(type,argtype,rvtype,name,impl,cmparg)			\
+	inline rvtype name(type val1, const BigInteger& val2)				\
+	{																	\
+		typedef detail::MPZ::impl<argtype,mpz_srcptr> impl_t;			\
+		return impl_t::eval(val1,val2) cmparg;							\
+	}
+
+#define BIX_REVEXCMPDEF(type,argtype,rvtype,name,impl,cmparg)			\
+	template < class Expr >												\
+	inline rvtype name(type val1, const detail::BIX<Expr>& val2)		\
+	{																	\
+		typedef detail::MPZ::impl<argtype,mpz_srcptr> impl_t;			\
+		BigInteger tmp(val2);											\
+		return impl_t::eval(val1,tmp) cmparg;							\
+	}
+
+#define BIX_REVCMPDEF(type,argtype,rvtype,name,impl,cmparg)				\
+	BIX_REVBICMPDEF(type,argtype,rvtype,name,impl,cmparg)				\
+	BIX_REVEXCMPDEF(type,argtype,rvtype,name,impl,cmparg)
+
+#define BIX_INTCMPDEF(rvtype,name,impl,cmparg)							\
+	BIX_FWDCMPDEF(bool,unsigned long,rvtype,name,impl,cmparg)			\
+	BIX_FWDCMPDEF(char,long,rvtype,name,impl,cmparg)					\
+	BIX_FWDCMPDEF(signed char,long,rvtype,name,impl,cmparg)				\
+	BIX_FWDCMPDEF(unsigned char,unsigned long,rvtype,name,impl,cmparg)	\
+	BIX_FWDCMPDEF(short,long,rvtype,name,impl,cmparg)					\
+	BIX_FWDCMPDEF(unsigned short,unsigned long,rvtype,name,impl,cmparg)	\
+	BIX_FWDCMPDEF(int,long,rvtype,name,impl,cmparg)						\
+	BIX_FWDCMPDEF(unsigned int,unsigned long,rvtype,name,impl,cmparg)	\
+	BIX_FWDCMPDEF(long,long,rvtype,name,impl,cmparg)					\
+	BIX_FWDCMPDEF(unsigned long,unsigned long,rvtype,name,impl,cmparg)	\
+	BIX_REVCMPDEF(bool,unsigned long,rvtype,name,impl,cmparg)			\
+	BIX_REVCMPDEF(char,long,rvtype,name,impl,cmparg)					\
+	BIX_REVCMPDEF(signed char,long,rvtype,name,impl,cmparg)				\
+	BIX_REVCMPDEF(unsigned char,unsigned long,rvtype,name,impl,cmparg)	\
+	BIX_REVCMPDEF(short,long,rvtype,name,impl,cmparg)					\
+	BIX_REVCMPDEF(unsigned short,unsigned long,rvtype,name,impl,cmparg)	\
+	BIX_REVCMPDEF(int,long,rvtype,name,impl,cmparg)						\
+	BIX_REVCMPDEF(unsigned int,unsigned long,rvtype,name,impl,cmparg)	\
+	BIX_REVCMPDEF(long,long,rvtype,name,impl,cmparg)					\
+	BIX_REVCMPDEF(unsigned long,unsigned long,rvtype,name,impl,cmparg)
+
+#define BIX_FLOATCMPDEF(rvtype,name,impl,cmparg)						\
+	BIX_FWDCMPDEF(float,double,rvtype,name,impl,cmparg)					\
+	BIX_FWDCMPDEF(double,double,rvtype,name,impl,cmparg)				\
+	BIX_REVCMPDEF(float,double,rvtype,name,impl,cmparg)					\
+	BIX_REVCMPDEF(double,double,rvtype,name,impl,cmparg)
+
+#define BIX_MPZCMPDEF(rvtype,name,impl,cmparg)							\
+	BIX_FWDCMPDEF(mpz_srcptr,mpz_srcptr,rvtype,name,impl,cmparg)		\
+	BIX_FWDCMPDEF(const BigInteger&,mpz_srcptr,rvtype,name,impl,cmparg)	\
+	BIX_REVCMPDEF(mpz_srcptr,mpz_srcptr,rvtype,name,impl,cmparg)		\
+	BIX_REVEXCMPDEF(const BigInteger&,mpz_srcptr,rvtype,name,impl,cmparg)
+
+#define BIX_ALLCMPDEF(rvtype,name,impl,cmparg)							\
+	BIX_INTCMPDEF(rvtype,name,impl,cmparg)								\
+	BIX_FLOATCMPDEF(rvtype,name,impl,cmparg)							\
+	BIX_MPZCMPDEF(rvtype,name,impl,cmparg)								\
+	template < class SubExpr1, class SubExpr2 >							\
+	inline rvtype name(const detail::BIX<SubExpr1>& val1,				\
+					   const detail::BIX<SubExpr2>& val2)				\
+	{																	\
+		typedef detail::MPZ::impl<mpz_srcptr,mpz_srcptr> impl_t;		\
+		BigInteger tmp(val1), tmp2(val2);								\
+		return impl_t::eval(tmp,tmp2) cmparg;							\
+	}
+
+	BIX_ALLCMPDEF(bool,operator <,Cmp,<0)
+	BIX_ALLCMPDEF(bool,operator <=,Cmp,<=0)
+	BIX_ALLCMPDEF(bool,operator ==,Equal,)
+	BIX_ALLCMPDEF(bool,operator !=,Equal,==false)
+	BIX_ALLCMPDEF(bool,operator >=,Cmp,>=0)
+	BIX_ALLCMPDEF(bool,operator >,Cmp,>0)
+	BIX_ALLCMPDEF(int,cmp,Cmp,)
+
+#undef BIX_ALLCMPDEF
+#undef BIX_MPZCMPDEF
+#undef BIX_FLOATCMPDEF
+#undef BIX_INTCMPDEF
+#undef BIX_REVCMPDEF
+#undef BIX_REVEXCMPDEF
+#undef BIX_REVBICMPDEF
+#undef BIX_FWDCMPDEF
+#undef BIX_FWDEXCMPDEF
+#undef BIX_FWDBICMPDEF
+
+#define BRX_FWDBRCMPDEF(type,argtype,rvtype,name,impl,cmparg)			\
+	inline rvtype name(const BigRational& val1, type val2)				\
+	{																	\
+		typedef detail::MPQ::impl<mpq_srcptr,argtype,true> impl_t;		\
+		return impl_t::eval(val1,val2) cmparg;							\
+	}
+
+#define BRX_FWDEXCMPDEF(type,argtype,rvtype,name,impl,cmparg)			\
+	template < class Expr >												\
+	inline rvtype name(const detail::BRX<Expr>& val1, type val2)		\
+	{																	\
+		typedef detail::MPQ::impl<mpq_srcptr,argtype,					\
+								  Expr::isCanonical> impl_t;			\
+		mpq_t tmp;														\
+		mpq_init(tmp);													\
+		val1.evalTmp(tmp);												\
+		if( impl_t::needCanonical )										\
+			mpq_canonicalize(tmp);										\
+		rvtype rv = impl_t::eval(tmp,val2) cmparg;						\
+		mpq_clear(tmp);													\
+		return rv;														\
+	}
+
+#define BRX_FWDCMPDEF(type,argtype,rvtype,name,impl,cmparg)				\
+	BRX_FWDBRCMPDEF(type,argtype,rvtype,name,impl,cmparg)				\
+	BRX_FWDEXCMPDEF(type,argtype,rvtype,name,impl,cmparg)
+
+#define BRX_REVBRCMPDEF(type,argtype,rvtype,name,impl,cmparg)			\
+	inline rvtype name(type val1, const BigRational& val2)				\
+	{																	\
+		typedef detail::MPQ::impl<argtype,mpq_srcptr,true> impl_t;		\
+		return impl_t::eval(val1,val2) cmparg;							\
+	}
+
+#define BRX_REVEXCMPDEF(type,argtype,rvtype,name,impl,cmparg)			\
+	template < class Expr >												\
+	inline rvtype name(type val1, const detail::BRX<Expr>& val2)		\
+	{																	\
+		typedef detail::MPQ::impl<argtype,mpq_srcptr,					\
+								  Expr::isCanonical> impl_t;			\
+		mpq_t tmp;														\
+		mpq_init(tmp);													\
+		val2.evalTmp(tmp);												\
+		if( impl_t::needCanonical )										\
+			mpq_canonicalize(tmp);										\
+		rvtype rv = impl_t::eval(val1,tmp) cmparg;						\
+		mpq_clear(tmp);													\
+		return rv;														\
+	}
+
+#define BRX_REVCMPDEF(type,argtype,rvtype,name,impl,cmparg)				\
+	BRX_REVBRCMPDEF(type,argtype,rvtype,name,impl,cmparg)				\
+	BRX_REVEXCMPDEF(type,argtype,rvtype,name,impl,cmparg)
+
+#define BRX_FWDBRBIEXCMPDEF(rvtype,name,impl,cmparg)					\
+	template < class Expr >												\
+	inline rvtype name(const BigRational& val1,							\
+					   const detail::BIX<Expr>& val2)					\
+	{																	\
+		typedef detail::MPQ::impl<mpq_srcptr,mpz_srcptr,true> impl_t;	\
+		BigInteger tmp(val2);											\
+		return impl_t::eval(val1,tmp) cmparg;							\
+	}
+
+#define BRX_FWDEXBIEXCMPDEF(rvtype,name,impl,cmparg)					\
+	template < class SubExpr1, class SubExpr2 >							\
+	inline rvtype name(const detail::BRX<SubExpr1>& val1,				\
+					   const detail::BIX<SubExpr2>& val2)				\
+	{																	\
+		typedef detail::MPQ::impl<mpq_srcptr,mpz_srcptr,				\
+								  SubExpr1::isCanonical> impl_t;		\
+		mpq_t tmp;														\
+		mpq_init(tmp);													\
+		val1.evalTmp(tmp);												\
+		if( impl_t::needCanonical )										\
+			mpq_canonicalize(tmp);										\
+		BigInteger tmp2(val2);											\
+		rvtype rv = impl_t::eval(tmp,tmp2) cmparg;						\
+		mpq_clear(tmp);													\
+		return rv;														\
+	}
+
+#define BRX_FWDBIEXCMPDEF(rvtype,name,impl,cmparg)						\
+	BRX_FWDBRBIEXCMPDEF(rvtype,name,impl,cmparg)						\
+	BRX_FWDEXBIEXCMPDEF(rvtype,name,impl,cmparg)
+
+#define BRX_REVBRBIEXCMPDEF(rvtype,name,impl,cmparg)					\
+	template < class Expr >												\
+	inline rvtype name(const detail::BIX<Expr>& val1,					\
+					   const BigRational& val2)							\
+	{																	\
+		typedef detail::MPQ::impl<mpz_srcptr,mpq_srcptr,true> impl_t;	\
+		BigInteger tmp(val1);											\
+		return impl_t::eval(tmp,val2) cmparg;							\
+	}
+	
+#define BRX_REVEXBIEXCMPDEF(rvtype,name,impl,cmparg)					\
+	template < class SubExpr1, class SubExpr2 >							\
+	inline rvtype name(const detail::BIX<SubExpr1>& val1,				\
+					   const detail::BRX<SubExpr2>& val2)				\
+	{																	\
+		typedef detail::MPQ::impl<mpz_srcptr,mpq_srcptr,				\
+								  SubExpr2::isCanonical> impl_t;		\
+		BigInteger tmp(val1);											\
+		mpq_t tmp2;														\
+		mpq_init(tmp2);													\
+		val2.evalTmp(tmp2);												\
+		if( impl_t::needCanonical )										\
+			mpq_canonicalize(tmp2);										\
+		rvtype rv = impl_t::eval(tmp,tmp2) cmparg;						\
+		mpq_clear(tmp2);												\
+		return rv;														\
+	}
+
+#define BRX_REVBIEXCMPDEF(rvtype,name,impl,cmparg)						\
+	BRX_REVBRBIEXCMPDEF(rvtype,name,impl,cmparg)						\
+	BRX_REVEXBIEXCMPDEF(rvtype,name,impl,cmparg)
+
+#define BRX_INTCMPDEF(rvtype,name,impl,cmparg)							\
+	BRX_FWDCMPDEF(bool,unsigned long,rvtype,name,impl,cmparg)			\
+	BRX_FWDCMPDEF(char,long,rvtype,name,impl,cmparg)					\
+	BRX_FWDCMPDEF(signed char,long,rvtype,name,impl,cmparg)				\
+	BRX_FWDCMPDEF(unsigned char,unsigned long,rvtype,name,impl,cmparg)	\
+	BRX_FWDCMPDEF(short,long,rvtype,name,impl,cmparg)					\
+	BRX_FWDCMPDEF(unsigned short,unsigned long,rvtype,name,impl,cmparg)	\
+	BRX_FWDCMPDEF(int,long,rvtype,name,impl,cmparg)						\
+	BRX_FWDCMPDEF(unsigned int,unsigned long,rvtype,name,impl,cmparg)	\
+	BRX_FWDCMPDEF(long,long,rvtype,name,impl,cmparg)					\
+	BRX_FWDCMPDEF(unsigned long,unsigned long,rvtype,name,impl,cmparg)	\
+	BRX_REVCMPDEF(bool,unsigned long,rvtype,name,impl,cmparg)			\
+	BRX_REVCMPDEF(char,long,rvtype,name,impl,cmparg)					\
+	BRX_REVCMPDEF(signed char,long,rvtype,name,impl,cmparg)				\
+	BRX_REVCMPDEF(unsigned char,unsigned long,rvtype,name,impl,cmparg)	\
+	BRX_REVCMPDEF(short,long,rvtype,name,impl,cmparg)					\
+	BRX_REVCMPDEF(unsigned short,unsigned long,rvtype,name,impl,cmparg)	\
+	BRX_REVCMPDEF(int,long,rvtype,name,impl,cmparg)						\
+	BRX_REVCMPDEF(unsigned int,unsigned long,rvtype,name,impl,cmparg)	\
+	BRX_REVCMPDEF(long,long,rvtype,name,impl,cmparg)					\
+	BRX_REVCMPDEF(unsigned long,unsigned long,rvtype,name,impl,cmparg)
+
+#define BRX_FLOATCMPDEF(rvtype,name,impl,cmparg)						\
+	BRX_FWDCMPDEF(float,double,rvtype,name,impl,cmparg)					\
+	BRX_FWDCMPDEF(double,double,rvtype,name,impl,cmparg)				\
+	BRX_REVCMPDEF(float,double,rvtype,name,impl,cmparg)					\
+	BRX_REVCMPDEF(double,double,rvtype,name,impl,cmparg)
+
+#define BRX_MPZCMPDEF(rvtype,name,impl,cmparg)							\
+	BRX_FWDCMPDEF(mpz_srcptr,mpz_srcptr,rvtype,name,impl,cmparg)		\
+	BRX_FWDCMPDEF(const BigInteger&,mpz_srcptr,rvtype,name,impl,cmparg)	\
+	BRX_FWDBIEXCMPDEF(rvtype,name,impl,cmparg)							\
+	BRX_REVCMPDEF(mpz_srcptr,mpz_srcptr,rvtype,name,impl,cmparg)		\
+	BRX_REVCMPDEF(const BigInteger&,mpz_srcptr,rvtype,name,impl,cmparg)	\
+	BRX_REVBIEXCMPDEF(rvtype,name,impl,cmparg)
+
+#define BRX_MPQCMPDEF(rvtype,name,impl,cmparg)							\
+	BRX_FWDCMPDEF(mpq_srcptr,mpq_srcptr,rvtype,name,impl,cmparg)		\
+	BRX_FWDCMPDEF(const BigRational&,mpq_srcptr,rvtype,name,impl,cmparg) \
+	BRX_REVCMPDEF(mpq_srcptr,mpq_srcptr,rvtype,name,impl,cmparg)		\
+	BRX_REVEXCMPDEF(const BigRational&,mpq_srcptr,rvtype,name,impl,cmparg)
+
+#define BRX_ALLCMPDEF(rvtype,name,impl,cmparg)							\
+	BRX_INTCMPDEF(rvtype,name,impl,cmparg)								\
+	BRX_FLOATCMPDEF(rvtype,name,impl,cmparg)							\
+	BRX_MPZCMPDEF(rvtype,name,impl,cmparg)								\
+	BRX_MPQCMPDEF(rvtype,name,impl,cmparg)								\
+	template < class SubExpr1, class SubExpr2 >							\
+	inline rvtype name(const detail::BRX<SubExpr1>& val1,				\
+					   const detail::BRX<SubExpr2>& val2)				\
+	{																	\
+		typedef detail::MPQ::impl<mpq_srcptr,mpq_srcptr,				\
+								  SubExpr1::isCanonical&&				\
+								  SubExpr2::isCanonical> impl_t;		\
+		mpq_t tmp;														\
+		mpq_init(tmp);													\
+		val1.evalTmp(tmp);												\
+		if( impl_t::needCanonical && !SubExpr1::isCanonical )			\
+			mpq_canonicalize(tmp);										\
+		mpq_t tmp2;														\
+		mpq_init(tmp2);													\
+		val2.evalTmp(tmp2);												\
+		if( impl_t::needCanonical && !SubExpr2::isCanonical )			\
+			mpq_canonicalize(tmp2);										\
+		rvtype rv = impl_t::eval(tmp,tmp2) cmparg;						\
+		mpq_clear(tmp2);												\
+		mpq_clear(tmp);													\
+		return rv;														\
+	}
+
+	BRX_ALLCMPDEF(bool,operator <,Cmp,<0)
+	BRX_ALLCMPDEF(bool,operator <=,Cmp,<=0)
+	BRX_ALLCMPDEF(bool,operator ==,Equal,)
+	BRX_ALLCMPDEF(bool,operator !=,Equal,==false)
+	BRX_ALLCMPDEF(bool,operator >=,Cmp,>=0)
+	BRX_ALLCMPDEF(bool,operator >,Cmp,>0)
+	BRX_ALLCMPDEF(int,cmp,Cmp,)
+
+#undef BRX_ALLCMPDEF
+#undef BRX_MPQCMPDEF
+#undef BRX_MPZCMPDEF
+#undef BRX_FLOATCMPDEF
+#undef BRX_INTCMPDEF
+#undef BRX_REVBIEXCMPDEF
+#undef BRX_REVEXBIEXCMPDEF
+#undef BRX_REVBRBIEXCMPDEF
+#undef BRX_FWDBIEXCMPDEF
+#undef BRX_FWDEXBIEXCMPDEF
+#undef BRX_FWDBRBIEXCMPDEF
+#undef BRX_REVCMPDEF
+#undef BRX_REVEXCMPDEF
+#undef BRX_REVBRCMPDEF
+#undef BRX_FWDCMPDEF
+#undef BRX_FWDEXCMPDEF
+#undef BRX_FWDBRCMPDEF
+
+	typedef BigInteger mpz_class;
+	typedef BigRational mpq_class;
+
+}
+
+namespace std
+{
+
+	inline std::ostream& operator <<(std::ostream& o, const Parma_Polyhedra_Library::BigInteger& val)
+	{
+		o << static_cast<mpz_srcptr>(val);
+		return o;
+	}
+
+	template < class Expr >
+	inline std::ostream& operator <<(std::ostream& o,
+									 const Parma_Polyhedra_Library::detail::BIX<Expr>& val)
+	{
+		Parma_Polyhedra_Library::BigInteger tmp(val);
+		o << tmp;
+		return o;
+	}
+
+	inline std::istream& operator >>(std::istream& i, Parma_Polyhedra_Library::BigInteger& val)
+	{
+		i >> static_cast<mpz_ptr>(val);
+		return i;
+	}
+
+	inline std::ostream& operator <<(std::ostream& o, const Parma_Polyhedra_Library::BigRational& val)
+	{
+		o << static_cast<mpq_srcptr>(val);
+		return o;
+	}
+
+	template < class Expr >
+	inline std::ostream& operator <<(std::ostream& o,
+									 const Parma_Polyhedra_Library::detail::BRX<Expr>& val)
+	{
+		Parma_Polyhedra_Library::BigRational tmp(val);
+		o << tmp;
+		return o;
+	}
+
+	inline std::istream& operator >>(std::istream& i, Parma_Polyhedra_Library::BigRational& val)
+	{
+		i >> static_cast<mpq_ptr>(val);
+		return i;
+	}
+
+}
+
+
+using Parma_Polyhedra_Library::mpz_class;
+using Parma_Polyhedra_Library::mpq_class;
+using Parma_Polyhedra_Library::sgn;
+using Parma_Polyhedra_Library::cmp;
+
+
+#endif // BIGINTEGER_HH
diff -urN ppl-0.9/src/checked.defs.hh ppl-0.9-new/src/checked.defs.hh
--- ppl-0.9/src/checked.defs.hh	2006-02-25 09:28:56.000000000 +0100
+++ ppl-0.9-new/src/checked.defs.hh	2008-05-06 12:47:39.000000000 +0200
@@ -24,7 +24,7 @@
 #define PPL_checked_defs_hh 1
 
 #include <iostream>
-#include <gmpxx.h>
+#include "biginteger.hh"
 #include "Rounding_Dir.defs.hh"
 #include "Numeric_Format.defs.hh"
 
diff -urN ppl-0.9/src/mp_numeric_limits.hh ppl-0.9-new/src/mp_numeric_limits.hh
--- ppl-0.9/src/mp_numeric_limits.hh	2006-01-16 12:10:10.000000000 +0100
+++ ppl-0.9-new/src/mp_numeric_limits.hh	2008-05-06 12:47:52.000000000 +0200
@@ -25,7 +25,7 @@
 #ifndef PPL_mp_numeric_limits_hh
 #define PPL_mp_numeric_limits_hh 1
 
-#include <gmpxx.h>
+#include "biginteger.hh"
 #include <limits>
 
 namespace std {
diff -urN ppl-0.9/src/ppl.hh.dist ppl-0.9-new/src/ppl.hh.dist
--- ppl-0.9/src/ppl.hh.dist	2006-03-12 09:14:05.000000000 +0100
+++ ppl-0.9-new/src/ppl.hh.dist	2008-05-06 12:48:34.000000000 +0200
@@ -517,7 +517,7 @@
 
 
 // Automatically generated from PPL source file ../src/GMP_Integer.types.hh line 16
-#include <gmpxx.h>
+#include "biginteger.hh"
 
 namespace Parma_Polyhedra_Library {
 
@@ -558,7 +558,7 @@
 
 
 #include <iostream>
-#include <gmpxx.h>
+#include "biginteger.hh"
 // Automatically generated from PPL source file ../src/Rounding_Dir.defs.hh line 1
 /* Declaration of Rounding_Dir and related functions.
 */
@@ -8268,7 +8268,7 @@
 */
 
 
-#include <gmpxx.h>
+#include "biginteger.hh"
 #include <limits>
 
 namespace std {
@@ -9534,7 +9534,7 @@
 
 
 // Automatically generated from PPL source file ../src/Interval.defs.hh line 29
-#include <gmpxx.h>
+#include "biginteger.hh"
 #include <iosfwd>
 
 namespace Parma_Polyhedra_Library {

