Blame gmpxx.h

Packit 5c3484
/* gmpxx.h -- C++ class wrapper for GMP types.  -*- C++ -*-
Packit 5c3484
Packit 5c3484
Copyright 2001-2003, 2006, 2008, 2011, 2012 Free Software Foundation, Inc.
Packit 5c3484
Packit 5c3484
This file is part of the GNU MP Library.
Packit 5c3484
Packit 5c3484
The GNU MP Library is free software; you can redistribute it and/or modify
Packit 5c3484
it under the terms of either:
Packit 5c3484
Packit 5c3484
  * the GNU Lesser General Public License as published by the Free
Packit 5c3484
    Software Foundation; either version 3 of the License, or (at your
Packit 5c3484
    option) any later version.
Packit 5c3484
Packit 5c3484
or
Packit 5c3484
Packit 5c3484
  * the GNU General Public License as published by the Free Software
Packit 5c3484
    Foundation; either version 2 of the License, or (at your option) any
Packit 5c3484
    later version.
Packit 5c3484
Packit 5c3484
or both in parallel, as here.
Packit 5c3484
Packit 5c3484
The GNU MP Library is distributed in the hope that it will be useful, but
Packit 5c3484
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
Packit 5c3484
or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
Packit 5c3484
for more details.
Packit 5c3484
Packit 5c3484
You should have received copies of the GNU General Public License and the
Packit 5c3484
GNU Lesser General Public License along with the GNU MP Library.  If not,
Packit 5c3484
see https://www.gnu.org/licenses/.  */
Packit 5c3484
Packit 5c3484
#ifndef __GMP_PLUSPLUS__
Packit 5c3484
#define __GMP_PLUSPLUS__
Packit 5c3484
Packit 5c3484
#include <iosfwd>
Packit 5c3484
Packit 5c3484
#include <cstring>  /* for strlen */
Packit 5c3484
#include <limits>  /* numeric_limits */
Packit 5c3484
#include <utility>
Packit 5c3484
#include <algorithm>  /* swap */
Packit 5c3484
#include <string>
Packit 5c3484
#include <stdexcept>
Packit 5c3484
#include <cfloat>
Packit 5c3484
#include <gmp.h>
Packit 5c3484
Packit 5c3484
// wrapper for gcc's __builtin_constant_p
Packit 5c3484
// __builtin_constant_p has been in gcc since forever,
Packit 5c3484
// but g++-3.4 miscompiles it.
Packit 5c3484
#if __GMP_GNUC_PREREQ(4, 2)
Packit 5c3484
#define __GMPXX_CONSTANT(X) __builtin_constant_p(X)
Packit 5c3484
#else
Packit 5c3484
#define __GMPXX_CONSTANT(X) false
Packit 5c3484
#endif
Packit 5c3484
#define __GMPXX_CONSTANT_TRUE(X) (__GMPXX_CONSTANT(X) && (X))
Packit 5c3484
Packit 5c3484
// Use C++11 features
Packit 5c3484
#ifndef __GMPXX_USE_CXX11
Packit 5c3484
#if __cplusplus >= 201103L
Packit 5c3484
#define __GMPXX_USE_CXX11 1
Packit 5c3484
#else
Packit 5c3484
#define __GMPXX_USE_CXX11 0
Packit 5c3484
#endif
Packit 5c3484
#endif
Packit 5c3484
Packit 5c3484
#if __GMPXX_USE_CXX11
Packit 5c3484
#define __GMPXX_NOEXCEPT noexcept
Packit 5c3484
#include <type_traits> // for common_type
Packit 5c3484
#else
Packit 5c3484
#define __GMPXX_NOEXCEPT
Packit 5c3484
#endif
Packit 5c3484
Packit 5c3484
// Max allocations for plain types when converted to GMP types
Packit 5c3484
#if GMP_NAIL_BITS != 0 && ! defined _LONG_LONG_LIMB
Packit 5c3484
#define __GMPZ_ULI_LIMBS 2
Packit 5c3484
#else
Packit 5c3484
#define __GMPZ_ULI_LIMBS 1
Packit 5c3484
#endif
Packit 5c3484
Packit 5c3484
#define __GMPXX_BITS_TO_LIMBS(n)  (((n) + (GMP_NUMB_BITS - 1)) / GMP_NUMB_BITS)
Packit 5c3484
#define __GMPZ_DBL_LIMBS __GMPXX_BITS_TO_LIMBS(DBL_MAX_EXP)+1
Packit 5c3484
#define __GMPQ_NUM_DBL_LIMBS __GMPZ_DBL_LIMBS
Packit 5c3484
#define __GMPQ_DEN_DBL_LIMBS __GMPXX_BITS_TO_LIMBS(DBL_MANT_DIG+1-DBL_MIN_EXP)+1
Packit 5c3484
// The final +1s are a security margin. The current implementation of
Packit 5c3484
// mpq_set_d seems to need it for the denominator.
Packit 5c3484
Packit 5c3484
inline void __mpz_set_ui_safe(mpz_ptr p, unsigned long l)
Packit 5c3484
{
Packit 5c3484
  p->_mp_size = (l != 0);
Packit 5c3484
  p->_mp_d[0] = l & GMP_NUMB_MASK;
Packit 5c3484
#if __GMPZ_ULI_LIMBS > 1
Packit 5c3484
  l >>= GMP_NUMB_BITS;
Packit 5c3484
  p->_mp_d[1] = l;
Packit 5c3484
  p->_mp_size += (l != 0);
Packit 5c3484
#endif
Packit 5c3484
}
Packit 5c3484
Packit 5c3484
inline void __mpz_set_si_safe(mpz_ptr p, long l)
Packit 5c3484
{
Packit 5c3484
  if(l < 0)
Packit 5c3484
  {
Packit 5c3484
    __mpz_set_ui_safe(p, -static_cast<unsigned long>(l));
Packit 5c3484
    mpz_neg(p, p);
Packit 5c3484
  }
Packit 5c3484
  else
Packit 5c3484
    __mpz_set_ui_safe(p, l);
Packit 5c3484
    // Note: we know the high bit of l is 0 so we could do slightly better
Packit 5c3484
}
Packit 5c3484
Packit 5c3484
// Fake temporary variables
Packit 5c3484
#define __GMPXX_TMPZ_UI							\
Packit 5c3484
  mpz_t temp;								\
Packit 5c3484
  mp_limb_t limbs[__GMPZ_ULI_LIMBS];					\
Packit 5c3484
  temp->_mp_d = limbs;							\
Packit 5c3484
  __mpz_set_ui_safe (temp, l)
Packit 5c3484
#define __GMPXX_TMPZ_SI							\
Packit 5c3484
  mpz_t temp;								\
Packit 5c3484
  mp_limb_t limbs[__GMPZ_ULI_LIMBS];					\
Packit 5c3484
  temp->_mp_d = limbs;							\
Packit 5c3484
  __mpz_set_si_safe (temp, l)
Packit 5c3484
#define __GMPXX_TMPZ_D							\
Packit 5c3484
  mpz_t temp;								\
Packit 5c3484
  mp_limb_t limbs[__GMPZ_DBL_LIMBS];					\
Packit 5c3484
  temp->_mp_d = limbs;							\
Packit 5c3484
  temp->_mp_alloc = __GMPZ_DBL_LIMBS;					\
Packit 5c3484
  mpz_set_d (temp, d)
Packit 5c3484
Packit 5c3484
#define __GMPXX_TMPQ_UI							\
Packit 5c3484
  mpq_t temp;								\
Packit 5c3484
  mp_limb_t limbs[__GMPZ_ULI_LIMBS+1];					\
Packit 5c3484
  mpq_numref(temp)->_mp_d = limbs;					\
Packit 5c3484
  __mpz_set_ui_safe (mpq_numref(temp), l);				\
Packit 5c3484
  mpq_denref(temp)->_mp_d = limbs + __GMPZ_ULI_LIMBS;			\
Packit 5c3484
  mpq_denref(temp)->_mp_size = 1;					\
Packit 5c3484
  mpq_denref(temp)->_mp_d[0] = 1
Packit 5c3484
#define __GMPXX_TMPQ_SI							\
Packit 5c3484
  mpq_t temp;								\
Packit 5c3484
  mp_limb_t limbs[__GMPZ_ULI_LIMBS+1];					\
Packit 5c3484
  mpq_numref(temp)->_mp_d = limbs;					\
Packit 5c3484
  __mpz_set_si_safe (mpq_numref(temp), l);				\
Packit 5c3484
  mpq_denref(temp)->_mp_d = limbs + __GMPZ_ULI_LIMBS;			\
Packit 5c3484
  mpq_denref(temp)->_mp_size = 1;					\
Packit 5c3484
  mpq_denref(temp)->_mp_d[0] = 1
Packit 5c3484
#define __GMPXX_TMPQ_D							\
Packit 5c3484
  mpq_t temp;								\
Packit 5c3484
  mp_limb_t limbs[__GMPQ_NUM_DBL_LIMBS + __GMPQ_DEN_DBL_LIMBS];		\
Packit 5c3484
  mpq_numref(temp)->_mp_d = limbs;					\
Packit 5c3484
  mpq_numref(temp)->_mp_alloc = __GMPQ_NUM_DBL_LIMBS;			\
Packit 5c3484
  mpq_denref(temp)->_mp_d = limbs + __GMPQ_NUM_DBL_LIMBS;		\
Packit 5c3484
  mpq_denref(temp)->_mp_alloc = __GMPQ_DEN_DBL_LIMBS;			\
Packit 5c3484
  mpq_set_d (temp, d)
Packit 5c3484
Packit 5c3484
inline unsigned long __gmpxx_abs_ui (signed long l)
Packit 5c3484
{
Packit 5c3484
  return l >= 0 ? static_cast<unsigned long>(l)
Packit 5c3484
	  : -static_cast<unsigned long>(l);
Packit 5c3484
}
Packit 5c3484
Packit 5c3484
/**************** Function objects ****************/
Packit 5c3484
/* Any evaluation of a __gmp_expr ends up calling one of these functions
Packit 5c3484
   all intermediate functions being inline, the evaluation should optimize
Packit 5c3484
   to a direct call to the relevant function, thus yielding no overhead
Packit 5c3484
   over the C interface. */
Packit 5c3484
Packit 5c3484
struct __gmp_unary_plus
Packit 5c3484
{
Packit 5c3484
  static void eval(mpz_ptr z, mpz_srcptr w) { mpz_set(z, w); }
Packit 5c3484
  static void eval(mpq_ptr q, mpq_srcptr r) { mpq_set(q, r); }
Packit 5c3484
  static void eval(mpf_ptr f, mpf_srcptr g) { mpf_set(f, g); }
Packit 5c3484
};
Packit 5c3484
Packit 5c3484
struct __gmp_unary_minus
Packit 5c3484
{
Packit 5c3484
  static void eval(mpz_ptr z, mpz_srcptr w) { mpz_neg(z, w); }
Packit 5c3484
  static void eval(mpq_ptr q, mpq_srcptr r) { mpq_neg(q, r); }
Packit 5c3484
  static void eval(mpf_ptr f, mpf_srcptr g) { mpf_neg(f, g); }
Packit 5c3484
};
Packit 5c3484
Packit 5c3484
struct __gmp_unary_com
Packit 5c3484
{
Packit 5c3484
  static void eval(mpz_ptr z, mpz_srcptr w) { mpz_com(z, w); }
Packit 5c3484
};
Packit 5c3484
Packit 5c3484
struct __gmp_binary_plus
Packit 5c3484
{
Packit 5c3484
  static void eval(mpz_ptr z, mpz_srcptr w, mpz_srcptr v)
Packit 5c3484
  { mpz_add(z, w, v); }
Packit 5c3484
Packit 5c3484
  static void eval(mpz_ptr z, mpz_srcptr w, unsigned long int l)
Packit 5c3484
  {
Packit 5c3484
    // Ideally, those checks should happen earlier so that the tree
Packit 5c3484
    // generated for a+0+b would just be sum(a,b).
Packit 5c3484
    if (__GMPXX_CONSTANT(l) && l == 0)
Packit 5c3484
    {
Packit 5c3484
      if (z != w) mpz_set(z, w);
Packit 5c3484
    }
Packit 5c3484
    else
Packit 5c3484
      mpz_add_ui(z, w, l);
Packit 5c3484
  }
Packit 5c3484
  static void eval(mpz_ptr z, unsigned long int l, mpz_srcptr w)
Packit 5c3484
  { eval(z, w, l); }
Packit 5c3484
  static void eval(mpz_ptr z, mpz_srcptr w, signed long int l)
Packit 5c3484
  {
Packit 5c3484
    if (l >= 0)
Packit 5c3484
      eval(z, w, static_cast<unsigned long>(l));
Packit 5c3484
    else
Packit 5c3484
      mpz_sub_ui(z, w, -static_cast<unsigned long>(l));
Packit 5c3484
  }
Packit 5c3484
  static void eval(mpz_ptr z, signed long int l, mpz_srcptr w)
Packit 5c3484
  { eval(z, w, l); }
Packit 5c3484
  static void eval(mpz_ptr z, mpz_srcptr w, double d)
Packit 5c3484
  {  __GMPXX_TMPZ_D;    mpz_add (z, w, temp); }
Packit 5c3484
  static void eval(mpz_ptr z, double d, mpz_srcptr w)
Packit 5c3484
  { eval(z, w, d); }
Packit 5c3484
Packit 5c3484
  static void eval(mpq_ptr q, mpq_srcptr r, mpq_srcptr s)
Packit 5c3484
  { mpq_add(q, r, s); }
Packit 5c3484
Packit 5c3484
  static void eval(mpq_ptr q, mpq_srcptr r, unsigned long int l)
Packit 5c3484
  {
Packit 5c3484
    if (__GMPXX_CONSTANT(l) && l == 0)
Packit 5c3484
    {
Packit 5c3484
      if (q != r) mpq_set(q, r);
Packit 5c3484
    }
Packit 5c3484
    else
Packit 5c3484
    {
Packit 5c3484
      if (q == r)
Packit 5c3484
        mpz_addmul_ui(mpq_numref(q), mpq_denref(q), l);
Packit 5c3484
      else
Packit 5c3484
      {
Packit 5c3484
        mpz_mul_ui(mpq_numref(q), mpq_denref(r), l);
Packit 5c3484
        mpz_add(mpq_numref(q), mpq_numref(q), mpq_numref(r));
Packit 5c3484
        mpz_set(mpq_denref(q), mpq_denref(r));
Packit 5c3484
      }
Packit 5c3484
    }
Packit 5c3484
  }
Packit 5c3484
  static void eval(mpq_ptr q, unsigned long int l, mpq_srcptr r)
Packit 5c3484
  { eval(q, r, l); }
Packit 5c3484
  static inline void eval(mpq_ptr q, mpq_srcptr r, signed long int l);
Packit 5c3484
  // defined after __gmp_binary_minus
Packit 5c3484
  static void eval(mpq_ptr q, signed long int l, mpq_srcptr r)
Packit 5c3484
  { eval(q, r, l); }
Packit 5c3484
  static void eval(mpq_ptr q, mpq_srcptr r, double d)
Packit 5c3484
  {  __GMPXX_TMPQ_D;    mpq_add (q, r, temp); }
Packit 5c3484
  static void eval(mpq_ptr q, double d, mpq_srcptr r)
Packit 5c3484
  { eval(q, r, d); }
Packit 5c3484
Packit 5c3484
  static void eval(mpq_ptr q, mpq_srcptr r, mpz_srcptr z)
Packit 5c3484
  {
Packit 5c3484
    if (q == r)
Packit 5c3484
      mpz_addmul(mpq_numref(q), mpq_denref(q), z);
Packit 5c3484
    else
Packit 5c3484
    {
Packit 5c3484
      mpz_mul(mpq_numref(q), mpq_denref(r), z);
Packit 5c3484
      mpz_add(mpq_numref(q), mpq_numref(q), mpq_numref(r));
Packit 5c3484
      mpz_set(mpq_denref(q), mpq_denref(r));
Packit 5c3484
    }
Packit 5c3484
  }
Packit 5c3484
  static void eval(mpq_ptr q, mpz_srcptr z, mpq_srcptr r)
Packit 5c3484
  { eval(q, r, z); }
Packit 5c3484
Packit 5c3484
  static void eval(mpf_ptr f, mpf_srcptr g, mpf_srcptr h)
Packit 5c3484
  { mpf_add(f, g, h); }
Packit 5c3484
Packit 5c3484
  static void eval(mpf_ptr f, mpf_srcptr g, unsigned long int l)
Packit 5c3484
  { mpf_add_ui(f, g, l); }
Packit 5c3484
  static void eval(mpf_ptr f, unsigned long int l, mpf_srcptr g)
Packit 5c3484
  { mpf_add_ui(f, g, l); }
Packit 5c3484
  static void eval(mpf_ptr f, mpf_srcptr g, signed long int l)
Packit 5c3484
  {
Packit 5c3484
    if (l >= 0)
Packit 5c3484
      mpf_add_ui(f, g, l);
Packit 5c3484
    else
Packit 5c3484
      mpf_sub_ui(f, g, -static_cast<unsigned long>(l));
Packit 5c3484
  }
Packit 5c3484
  static void eval(mpf_ptr f, signed long int l, mpf_srcptr g)
Packit 5c3484
  { eval(f, g, l); }
Packit 5c3484
  static void eval(mpf_ptr f, mpf_srcptr g, double d)
Packit 5c3484
  {
Packit 5c3484
    mpf_t temp;
Packit 5c3484
    mpf_init2(temp, 8*sizeof(double));
Packit 5c3484
    mpf_set_d(temp, d);
Packit 5c3484
    mpf_add(f, g, temp);
Packit 5c3484
    mpf_clear(temp);
Packit 5c3484
  }
Packit 5c3484
  static void eval(mpf_ptr f, double d, mpf_srcptr g)
Packit 5c3484
  { eval(f, g, d); }
Packit 5c3484
};
Packit 5c3484
Packit 5c3484
struct __gmp_binary_minus
Packit 5c3484
{
Packit 5c3484
  static void eval(mpz_ptr z, mpz_srcptr w, mpz_srcptr v)
Packit 5c3484
  { mpz_sub(z, w, v); }
Packit 5c3484
Packit 5c3484
  static void eval(mpz_ptr z, mpz_srcptr w, unsigned long int l)
Packit 5c3484
  {
Packit 5c3484
    if (__GMPXX_CONSTANT(l) && l == 0)
Packit 5c3484
    {
Packit 5c3484
      if (z != w) mpz_set(z, w);
Packit 5c3484
    }
Packit 5c3484
    else
Packit 5c3484
      mpz_sub_ui(z, w, l);
Packit 5c3484
  }
Packit 5c3484
  static void eval(mpz_ptr z, unsigned long int l, mpz_srcptr w)
Packit 5c3484
  {
Packit 5c3484
    if (__GMPXX_CONSTANT(l) && l == 0)
Packit 5c3484
    {
Packit 5c3484
      mpz_neg(z, w);
Packit 5c3484
    }
Packit 5c3484
    else
Packit 5c3484
      mpz_ui_sub(z, l, w);
Packit 5c3484
  }
Packit 5c3484
  static void eval(mpz_ptr z, mpz_srcptr w, signed long int l)
Packit 5c3484
  {
Packit 5c3484
    if (l >= 0)
Packit 5c3484
      eval(z, w, static_cast<unsigned long>(l));
Packit 5c3484
    else
Packit 5c3484
      mpz_add_ui(z, w, -static_cast<unsigned long>(l));
Packit 5c3484
  }
Packit 5c3484
  static void eval(mpz_ptr z, signed long int l, mpz_srcptr w)
Packit 5c3484
  {
Packit 5c3484
    if (l >= 0)
Packit 5c3484
      eval(z, static_cast<unsigned long>(l), w);
Packit 5c3484
    else
Packit 5c3484
      {
Packit 5c3484
        mpz_add_ui(z, w, -static_cast<unsigned long>(l));
Packit 5c3484
        mpz_neg(z, z);
Packit 5c3484
      }
Packit 5c3484
  }
Packit 5c3484
  static void eval(mpz_ptr z, mpz_srcptr w, double d)
Packit 5c3484
  {  __GMPXX_TMPZ_D;    mpz_sub (z, w, temp); }
Packit 5c3484
  static void eval(mpz_ptr z, double d, mpz_srcptr w)
Packit 5c3484
  {  __GMPXX_TMPZ_D;    mpz_sub (z, temp, w); }
Packit 5c3484
Packit 5c3484
  static void eval(mpq_ptr q, mpq_srcptr r, mpq_srcptr s)
Packit 5c3484
  { mpq_sub(q, r, s); }
Packit 5c3484
Packit 5c3484
  static void eval(mpq_ptr q, mpq_srcptr r, unsigned long int l)
Packit 5c3484
  {
Packit 5c3484
    if (__GMPXX_CONSTANT(l) && l == 0)
Packit 5c3484
    {
Packit 5c3484
      if (q != r) mpq_set(q, r);
Packit 5c3484
    }
Packit 5c3484
    else
Packit 5c3484
    {
Packit 5c3484
      if (q == r)
Packit 5c3484
        mpz_submul_ui(mpq_numref(q), mpq_denref(q), l);
Packit 5c3484
      else
Packit 5c3484
      {
Packit 5c3484
        mpz_mul_ui(mpq_numref(q), mpq_denref(r), l);
Packit 5c3484
        mpz_sub(mpq_numref(q), mpq_numref(r), mpq_numref(q));
Packit 5c3484
        mpz_set(mpq_denref(q), mpq_denref(r));
Packit 5c3484
      }
Packit 5c3484
    }
Packit 5c3484
  }
Packit 5c3484
  static void eval(mpq_ptr q, unsigned long int l, mpq_srcptr r)
Packit 5c3484
  { eval(q, r, l); mpq_neg(q, q); }
Packit 5c3484
  static void eval(mpq_ptr q, mpq_srcptr r, signed long int l)
Packit 5c3484
  {
Packit 5c3484
    if (l >= 0)
Packit 5c3484
      eval(q, r, static_cast<unsigned long>(l));
Packit 5c3484
    else
Packit 5c3484
      __gmp_binary_plus::eval(q, r, -static_cast<unsigned long>(l));
Packit 5c3484
  }
Packit 5c3484
  static void eval(mpq_ptr q, signed long int l, mpq_srcptr r)
Packit 5c3484
  { eval(q, r, l); mpq_neg(q, q); }
Packit 5c3484
  static void eval(mpq_ptr q, mpq_srcptr r, double d)
Packit 5c3484
  {  __GMPXX_TMPQ_D;    mpq_sub (q, r, temp); }
Packit 5c3484
  static void eval(mpq_ptr q, double d, mpq_srcptr r)
Packit 5c3484
  {  __GMPXX_TMPQ_D;    mpq_sub (q, temp, r); }
Packit 5c3484
Packit 5c3484
  static void eval(mpq_ptr q, mpq_srcptr r, mpz_srcptr z)
Packit 5c3484
  {
Packit 5c3484
    if (q == r)
Packit 5c3484
      mpz_submul(mpq_numref(q), mpq_denref(q), z);
Packit 5c3484
    else
Packit 5c3484
    {
Packit 5c3484
      mpz_mul(mpq_numref(q), mpq_denref(r), z);
Packit 5c3484
      mpz_sub(mpq_numref(q), mpq_numref(r), mpq_numref(q));
Packit 5c3484
      mpz_set(mpq_denref(q), mpq_denref(r));
Packit 5c3484
    }
Packit 5c3484
  }
Packit 5c3484
  static void eval(mpq_ptr q, mpz_srcptr z, mpq_srcptr r)
Packit 5c3484
  { eval(q, r, z); mpq_neg(q, q); }
Packit 5c3484
Packit 5c3484
  static void eval(mpf_ptr f, mpf_srcptr g, mpf_srcptr h)
Packit 5c3484
  { mpf_sub(f, g, h); }
Packit 5c3484
Packit 5c3484
  static void eval(mpf_ptr f, mpf_srcptr g, unsigned long int l)
Packit 5c3484
  { mpf_sub_ui(f, g, l); }
Packit 5c3484
  static void eval(mpf_ptr f, unsigned long int l, mpf_srcptr g)
Packit 5c3484
  { mpf_ui_sub(f, l, g); }
Packit 5c3484
  static void eval(mpf_ptr f, mpf_srcptr g, signed long int l)
Packit 5c3484
  {
Packit 5c3484
    if (l >= 0)
Packit 5c3484
      mpf_sub_ui(f, g, l);
Packit 5c3484
    else
Packit 5c3484
      mpf_add_ui(f, g, -static_cast<unsigned long>(l));
Packit 5c3484
  }
Packit 5c3484
  static void eval(mpf_ptr f, signed long int l, mpf_srcptr g)
Packit 5c3484
  {
Packit 5c3484
    if (l >= 0)
Packit 5c3484
      mpf_sub_ui(f, g, l);
Packit 5c3484
    else
Packit 5c3484
      mpf_add_ui(f, g, -static_cast<unsigned long>(l));
Packit 5c3484
    mpf_neg(f, f);
Packit 5c3484
  }
Packit 5c3484
  static void eval(mpf_ptr f, mpf_srcptr g, double d)
Packit 5c3484
  {
Packit 5c3484
    mpf_t temp;
Packit 5c3484
    mpf_init2(temp, 8*sizeof(double));
Packit 5c3484
    mpf_set_d(temp, d);
Packit 5c3484
    mpf_sub(f, g, temp);
Packit 5c3484
    mpf_clear(temp);
Packit 5c3484
  }
Packit 5c3484
  static void eval(mpf_ptr f, double d, mpf_srcptr g)
Packit 5c3484
  {
Packit 5c3484
    mpf_t temp;
Packit 5c3484
    mpf_init2(temp, 8*sizeof(double));
Packit 5c3484
    mpf_set_d(temp, d);
Packit 5c3484
    mpf_sub(f, temp, g);
Packit 5c3484
    mpf_clear(temp);
Packit 5c3484
  }
Packit 5c3484
};
Packit 5c3484
Packit 5c3484
// defined here so it can reference __gmp_binary_minus
Packit 5c3484
inline void
Packit 5c3484
__gmp_binary_plus::eval(mpq_ptr q, mpq_srcptr r, signed long int l)
Packit 5c3484
{
Packit 5c3484
  if (l >= 0)
Packit 5c3484
    eval(q, r, static_cast<unsigned long>(l));
Packit 5c3484
  else
Packit 5c3484
    __gmp_binary_minus::eval(q, r, -static_cast<unsigned long>(l));
Packit 5c3484
}
Packit 5c3484
Packit 5c3484
struct __gmp_binary_lshift
Packit 5c3484
{
Packit 5c3484
  static void eval(mpz_ptr z, mpz_srcptr w, mp_bitcnt_t l)
Packit 5c3484
  {
Packit 5c3484
    if (__GMPXX_CONSTANT(l) && (l == 0))
Packit 5c3484
    {
Packit 5c3484
      if (z != w) mpz_set(z, w);
Packit 5c3484
    }
Packit 5c3484
    else
Packit 5c3484
      mpz_mul_2exp(z, w, l);
Packit 5c3484
  }
Packit 5c3484
  static void eval(mpq_ptr q, mpq_srcptr r, mp_bitcnt_t l)
Packit 5c3484
  {
Packit 5c3484
    if (__GMPXX_CONSTANT(l) && (l == 0))
Packit 5c3484
    {
Packit 5c3484
      if (q != r) mpq_set(q, r);
Packit 5c3484
    }
Packit 5c3484
    else
Packit 5c3484
      mpq_mul_2exp(q, r, l);
Packit 5c3484
  }
Packit 5c3484
  static void eval(mpf_ptr f, mpf_srcptr g, mp_bitcnt_t l)
Packit 5c3484
  { mpf_mul_2exp(f, g, l); }
Packit 5c3484
};
Packit 5c3484
Packit 5c3484
struct __gmp_binary_rshift
Packit 5c3484
{
Packit 5c3484
  static void eval(mpz_ptr z, mpz_srcptr w, mp_bitcnt_t l)
Packit 5c3484
  {
Packit 5c3484
    if (__GMPXX_CONSTANT(l) && (l == 0))
Packit 5c3484
    {
Packit 5c3484
      if (z != w) mpz_set(z, w);
Packit 5c3484
    }
Packit 5c3484
    else
Packit 5c3484
      mpz_fdiv_q_2exp(z, w, l);
Packit 5c3484
  }
Packit 5c3484
  static void eval(mpq_ptr q, mpq_srcptr r, mp_bitcnt_t l)
Packit 5c3484
  {
Packit 5c3484
    if (__GMPXX_CONSTANT(l) && (l == 0))
Packit 5c3484
    {
Packit 5c3484
      if (q != r) mpq_set(q, r);
Packit 5c3484
    }
Packit 5c3484
    else
Packit 5c3484
      mpq_div_2exp(q, r, l);
Packit 5c3484
  }
Packit 5c3484
  static void eval(mpf_ptr f, mpf_srcptr g, mp_bitcnt_t l)
Packit 5c3484
  { mpf_div_2exp(f, g, l); }
Packit 5c3484
};
Packit 5c3484
Packit 5c3484
struct __gmp_binary_multiplies
Packit 5c3484
{
Packit 5c3484
  static void eval(mpz_ptr z, mpz_srcptr w, mpz_srcptr v)
Packit 5c3484
  { mpz_mul(z, w, v); }
Packit 5c3484
Packit 5c3484
  static void eval(mpz_ptr z, mpz_srcptr w, unsigned long int l)
Packit 5c3484
  {
Packit 5c3484
// gcc-3.3 doesn't have __builtin_ctzl. Don't bother optimizing for old gcc.
Packit 5c3484
#if __GMP_GNUC_PREREQ(3, 4)
Packit 5c3484
    if (__GMPXX_CONSTANT(l) && (l & (l-1)) == 0)
Packit 5c3484
    {
Packit 5c3484
      if (l == 0)
Packit 5c3484
      {
Packit 5c3484
        z->_mp_size = 0;
Packit 5c3484
      }
Packit 5c3484
      else
Packit 5c3484
      {
Packit 5c3484
        __gmp_binary_lshift::eval(z, w, __builtin_ctzl(l));
Packit 5c3484
      }
Packit 5c3484
    }
Packit 5c3484
    else
Packit 5c3484
#endif
Packit 5c3484
      mpz_mul_ui(z, w, l);
Packit 5c3484
  }
Packit 5c3484
  static void eval(mpz_ptr z, unsigned long int l, mpz_srcptr w)
Packit 5c3484
  { eval(z, w, l); }
Packit 5c3484
  static void eval(mpz_ptr z, mpz_srcptr w, signed long int l)
Packit 5c3484
  {
Packit 5c3484
    if (__GMPXX_CONSTANT_TRUE(l >= 0))
Packit 5c3484
      eval(z, w, static_cast<unsigned long>(l));
Packit 5c3484
    else if (__GMPXX_CONSTANT_TRUE(l <= 0))
Packit 5c3484
      {
Packit 5c3484
        eval(z, w, -static_cast<unsigned long>(l));
Packit 5c3484
	mpz_neg(z, z);
Packit 5c3484
      }
Packit 5c3484
    else
Packit 5c3484
      mpz_mul_si (z, w, l);
Packit 5c3484
  }
Packit 5c3484
  static void eval(mpz_ptr z, signed long int l, mpz_srcptr w)
Packit 5c3484
  { eval(z, w, l); }
Packit 5c3484
  static void eval(mpz_ptr z, mpz_srcptr w, double d)
Packit 5c3484
  {  __GMPXX_TMPZ_D;    mpz_mul (z, w, temp); }
Packit 5c3484
  static void eval(mpz_ptr z, double d, mpz_srcptr w)
Packit 5c3484
  { eval(z, w, d); }
Packit 5c3484
Packit 5c3484
  static void eval(mpq_ptr q, mpq_srcptr r, mpq_srcptr s)
Packit 5c3484
  { mpq_mul(q, r, s); }
Packit 5c3484
Packit 5c3484
  static void eval(mpq_ptr q, mpq_srcptr r, unsigned long int l)
Packit 5c3484
  {
Packit 5c3484
#if __GMP_GNUC_PREREQ(3, 4)
Packit 5c3484
    if (__GMPXX_CONSTANT(l) && (l & (l-1)) == 0)
Packit 5c3484
    {
Packit 5c3484
      if (l == 0)
Packit 5c3484
      {
Packit 5c3484
	mpq_set_ui(q, 0, 1);
Packit 5c3484
      }
Packit 5c3484
      else
Packit 5c3484
      {
Packit 5c3484
        __gmp_binary_lshift::eval(q, r, __builtin_ctzl(l));
Packit 5c3484
      }
Packit 5c3484
    }
Packit 5c3484
    else
Packit 5c3484
#endif
Packit 5c3484
    {
Packit 5c3484
      __GMPXX_TMPQ_UI;
Packit 5c3484
      mpq_mul (q, r, temp);
Packit 5c3484
    }
Packit 5c3484
  }
Packit 5c3484
  static void eval(mpq_ptr q, unsigned long int l, mpq_srcptr r)
Packit 5c3484
  { eval(q, r, l); }
Packit 5c3484
  static void eval(mpq_ptr q, mpq_srcptr r, signed long int l)
Packit 5c3484
  {
Packit 5c3484
    if (__GMPXX_CONSTANT_TRUE(l >= 0))
Packit 5c3484
      eval(q, r, static_cast<unsigned long>(l));
Packit 5c3484
    else if (__GMPXX_CONSTANT_TRUE(l <= 0))
Packit 5c3484
      {
Packit 5c3484
        eval(q, r, -static_cast<unsigned long>(l));
Packit 5c3484
	mpq_neg(q, q);
Packit 5c3484
      }
Packit 5c3484
    else
Packit 5c3484
      {
Packit 5c3484
	__GMPXX_TMPQ_SI;
Packit 5c3484
	mpq_mul (q, r, temp);
Packit 5c3484
      }
Packit 5c3484
  }
Packit 5c3484
  static void eval(mpq_ptr q, signed long int l, mpq_srcptr r)
Packit 5c3484
  { eval(q, r, l); }
Packit 5c3484
  static void eval(mpq_ptr q, mpq_srcptr r, double d)
Packit 5c3484
  {  __GMPXX_TMPQ_D;    mpq_mul (q, r, temp); }
Packit 5c3484
  static void eval(mpq_ptr q, double d, mpq_srcptr r)
Packit 5c3484
  { eval(q, r, d); }
Packit 5c3484
Packit 5c3484
  static void eval(mpf_ptr f, mpf_srcptr g, mpf_srcptr h)
Packit 5c3484
  { mpf_mul(f, g, h); }
Packit 5c3484
Packit 5c3484
  static void eval(mpf_ptr f, mpf_srcptr g, unsigned long int l)
Packit 5c3484
  { mpf_mul_ui(f, g, l); }
Packit 5c3484
  static void eval(mpf_ptr f, unsigned long int l, mpf_srcptr g)
Packit 5c3484
  { mpf_mul_ui(f, g, l); }
Packit 5c3484
  static void eval(mpf_ptr f, mpf_srcptr g, signed long int l)
Packit 5c3484
  {
Packit 5c3484
    if (l >= 0)
Packit 5c3484
      mpf_mul_ui(f, g, l);
Packit 5c3484
    else
Packit 5c3484
      {
Packit 5c3484
	mpf_mul_ui(f, g, -static_cast<unsigned long>(l));
Packit 5c3484
	mpf_neg(f, f);
Packit 5c3484
      }
Packit 5c3484
  }
Packit 5c3484
  static void eval(mpf_ptr f, signed long int l, mpf_srcptr g)
Packit 5c3484
  { eval(f, g, l); }
Packit 5c3484
  static void eval(mpf_ptr f, mpf_srcptr g, double d)
Packit 5c3484
  {
Packit 5c3484
    mpf_t temp;
Packit 5c3484
    mpf_init2(temp, 8*sizeof(double));
Packit 5c3484
    mpf_set_d(temp, d);
Packit 5c3484
    mpf_mul(f, g, temp);
Packit 5c3484
    mpf_clear(temp);
Packit 5c3484
  }
Packit 5c3484
  static void eval(mpf_ptr f, double d, mpf_srcptr g)
Packit 5c3484
  { eval(f, g, d); }
Packit 5c3484
};
Packit 5c3484
Packit 5c3484
struct __gmp_binary_divides
Packit 5c3484
{
Packit 5c3484
  static void eval(mpz_ptr z, mpz_srcptr w, mpz_srcptr v)
Packit 5c3484
  { mpz_tdiv_q(z, w, v); }
Packit 5c3484
Packit 5c3484
  static void eval(mpz_ptr z, mpz_srcptr w, unsigned long int l)
Packit 5c3484
  {
Packit 5c3484
#if __GMP_GNUC_PREREQ(3, 4)
Packit 5c3484
    // Don't optimize division by 0...
Packit 5c3484
    if (__GMPXX_CONSTANT(l) && (l & (l-1)) == 0 && l != 0)
Packit 5c3484
    {
Packit 5c3484
      if (l == 1)
Packit 5c3484
      {
Packit 5c3484
        if (z != w) mpz_set(z, w);
Packit 5c3484
      }
Packit 5c3484
      else
Packit 5c3484
        mpz_tdiv_q_2exp(z, w, __builtin_ctzl(l));
Packit 5c3484
        // warning: do not use rshift (fdiv)
Packit 5c3484
    }
Packit 5c3484
    else
Packit 5c3484
#endif
Packit 5c3484
      mpz_tdiv_q_ui(z, w, l);
Packit 5c3484
  }
Packit 5c3484
  static void eval(mpz_ptr z, unsigned long int l, mpz_srcptr w)
Packit 5c3484
  {
Packit 5c3484
    if (mpz_sgn(w) >= 0)
Packit 5c3484
      {
Packit 5c3484
	if (mpz_fits_ulong_p(w))
Packit 5c3484
	  mpz_set_ui(z, l / mpz_get_ui(w));
Packit 5c3484
	else
Packit 5c3484
	  mpz_set_ui(z, 0);
Packit 5c3484
      }
Packit 5c3484
    else
Packit 5c3484
      {
Packit 5c3484
	mpz_neg(z, w);
Packit 5c3484
	if (mpz_fits_ulong_p(z))
Packit 5c3484
	  {
Packit 5c3484
	    mpz_set_ui(z, l / mpz_get_ui(z));
Packit 5c3484
	    mpz_neg(z, z);
Packit 5c3484
	  }
Packit 5c3484
	else
Packit 5c3484
	  mpz_set_ui(z, 0);
Packit 5c3484
      }
Packit 5c3484
  }
Packit 5c3484
  static void eval(mpz_ptr z, mpz_srcptr w, signed long int l)
Packit 5c3484
  {
Packit 5c3484
    if (l >= 0)
Packit 5c3484
      eval(z, w, static_cast<unsigned long>(l));
Packit 5c3484
    else
Packit 5c3484
      {
Packit 5c3484
	eval(z, w, -static_cast<unsigned long>(l));
Packit 5c3484
	mpz_neg(z, z);
Packit 5c3484
      }
Packit 5c3484
  }
Packit 5c3484
  static void eval(mpz_ptr z, signed long int l, mpz_srcptr w)
Packit 5c3484
  {
Packit 5c3484
    if (mpz_fits_slong_p(w))
Packit 5c3484
      mpz_set_si(z, l / mpz_get_si(w));
Packit 5c3484
    else
Packit 5c3484
      {
Packit 5c3484
        /* if w is bigger than a long then the quotient must be zero, unless
Packit 5c3484
           l==LONG_MIN and w==-LONG_MIN in which case the quotient is -1 */
Packit 5c3484
        mpz_set_si (z, (mpz_cmpabs_ui (w, __gmpxx_abs_ui(l)) == 0 ? -1 : 0));
Packit 5c3484
      }
Packit 5c3484
  }
Packit 5c3484
  static void eval(mpz_ptr z, mpz_srcptr w, double d)
Packit 5c3484
  {  __GMPXX_TMPZ_D;    mpz_tdiv_q (z, w, temp); }
Packit 5c3484
  static void eval(mpz_ptr z, double d, mpz_srcptr w)
Packit 5c3484
  {  __GMPXX_TMPZ_D;    mpz_tdiv_q (z, temp, w); }
Packit 5c3484
Packit 5c3484
  static void eval(mpq_ptr q, mpq_srcptr r, mpq_srcptr s)
Packit 5c3484
  { mpq_div(q, r, s); }
Packit 5c3484
Packit 5c3484
  static void eval(mpq_ptr q, mpq_srcptr r, unsigned long int l)
Packit 5c3484
  {
Packit 5c3484
#if __GMP_GNUC_PREREQ(3, 4)
Packit 5c3484
    if (__GMPXX_CONSTANT(l) && (l & (l-1)) == 0 && l != 0)
Packit 5c3484
      __gmp_binary_rshift::eval(q, r, __builtin_ctzl(l));
Packit 5c3484
    else
Packit 5c3484
#endif
Packit 5c3484
    {
Packit 5c3484
      __GMPXX_TMPQ_UI;
Packit 5c3484
      mpq_div (q, r, temp);
Packit 5c3484
    }
Packit 5c3484
  }
Packit 5c3484
  static void eval(mpq_ptr q, unsigned long int l, mpq_srcptr r)
Packit 5c3484
  {  __GMPXX_TMPQ_UI;   mpq_div (q, temp, r); }
Packit 5c3484
  static void eval(mpq_ptr q, mpq_srcptr r, signed long int l)
Packit 5c3484
  {
Packit 5c3484
    if (__GMPXX_CONSTANT_TRUE(l >= 0))
Packit 5c3484
      eval(q, r, static_cast<unsigned long>(l));
Packit 5c3484
    else if (__GMPXX_CONSTANT_TRUE(l <= 0))
Packit 5c3484
      {
Packit 5c3484
        eval(q, r, -static_cast<unsigned long>(l));
Packit 5c3484
	mpq_neg(q, q);
Packit 5c3484
      }
Packit 5c3484
    else
Packit 5c3484
      {
Packit 5c3484
	__GMPXX_TMPQ_SI;
Packit 5c3484
	mpq_div (q, r, temp);
Packit 5c3484
      }
Packit 5c3484
  }
Packit 5c3484
  static void eval(mpq_ptr q, signed long int l, mpq_srcptr r)
Packit 5c3484
  {  __GMPXX_TMPQ_SI;   mpq_div (q, temp, r); }
Packit 5c3484
  static void eval(mpq_ptr q, mpq_srcptr r, double d)
Packit 5c3484
  {  __GMPXX_TMPQ_D;    mpq_div (q, r, temp); }
Packit 5c3484
  static void eval(mpq_ptr q, double d, mpq_srcptr r)
Packit 5c3484
  {  __GMPXX_TMPQ_D;    mpq_div (q, temp, r); }
Packit 5c3484
Packit 5c3484
  static void eval(mpf_ptr f, mpf_srcptr g, mpf_srcptr h)
Packit 5c3484
  { mpf_div(f, g, h); }
Packit 5c3484
Packit 5c3484
  static void eval(mpf_ptr f, mpf_srcptr g, unsigned long int l)
Packit 5c3484
  { mpf_div_ui(f, g, l); }
Packit 5c3484
  static void eval(mpf_ptr f, unsigned long int l, mpf_srcptr g)
Packit 5c3484
  { mpf_ui_div(f, l, g); }
Packit 5c3484
  static void eval(mpf_ptr f, mpf_srcptr g, signed long int l)
Packit 5c3484
  {
Packit 5c3484
    if (l >= 0)
Packit 5c3484
      mpf_div_ui(f, g, l);
Packit 5c3484
    else
Packit 5c3484
      {
Packit 5c3484
	mpf_div_ui(f, g, -static_cast<unsigned long>(l));
Packit 5c3484
	mpf_neg(f, f);
Packit 5c3484
      }
Packit 5c3484
  }
Packit 5c3484
  static void eval(mpf_ptr f, signed long int l, mpf_srcptr g)
Packit 5c3484
  {
Packit 5c3484
    if (l >= 0)
Packit 5c3484
      mpf_ui_div(f, l, g);
Packit 5c3484
    else
Packit 5c3484
      {
Packit 5c3484
	mpf_ui_div(f, -static_cast<unsigned long>(l), g);
Packit 5c3484
	mpf_neg(f, f);
Packit 5c3484
      }
Packit 5c3484
  }
Packit 5c3484
  static void eval(mpf_ptr f, mpf_srcptr g, double d)
Packit 5c3484
  {
Packit 5c3484
    mpf_t temp;
Packit 5c3484
    mpf_init2(temp, 8*sizeof(double));
Packit 5c3484
    mpf_set_d(temp, d);
Packit 5c3484
    mpf_div(f, g, temp);
Packit 5c3484
    mpf_clear(temp);
Packit 5c3484
  }
Packit 5c3484
  static void eval(mpf_ptr f, double d, mpf_srcptr g)
Packit 5c3484
  {
Packit 5c3484
    mpf_t temp;
Packit 5c3484
    mpf_init2(temp, 8*sizeof(double));
Packit 5c3484
    mpf_set_d(temp, d);
Packit 5c3484
    mpf_div(f, temp, g);
Packit 5c3484
    mpf_clear(temp);
Packit 5c3484
  }
Packit 5c3484
};
Packit 5c3484
Packit 5c3484
struct __gmp_binary_modulus
Packit 5c3484
{
Packit 5c3484
  static void eval(mpz_ptr z, mpz_srcptr w, mpz_srcptr v)
Packit 5c3484
  { mpz_tdiv_r(z, w, v); }
Packit 5c3484
Packit 5c3484
  static void eval(mpz_ptr z, mpz_srcptr w, unsigned long int l)
Packit 5c3484
  { mpz_tdiv_r_ui(z, w, l); }
Packit 5c3484
  static void eval(mpz_ptr z, unsigned long int l, mpz_srcptr w)
Packit 5c3484
  {
Packit 5c3484
    if (mpz_sgn(w) >= 0)
Packit 5c3484
      {
Packit 5c3484
	if (mpz_fits_ulong_p(w))
Packit 5c3484
	  mpz_set_ui(z, l % mpz_get_ui(w));
Packit 5c3484
	else
Packit 5c3484
	  mpz_set_ui(z, l);
Packit 5c3484
      }
Packit 5c3484
    else
Packit 5c3484
      {
Packit 5c3484
	mpz_neg(z, w);
Packit 5c3484
	if (mpz_fits_ulong_p(z))
Packit 5c3484
	  mpz_set_ui(z, l % mpz_get_ui(z));
Packit 5c3484
	else
Packit 5c3484
	  mpz_set_ui(z, l);
Packit 5c3484
      }
Packit 5c3484
  }
Packit 5c3484
  static void eval(mpz_ptr z, mpz_srcptr w, signed long int l)
Packit 5c3484
  {
Packit 5c3484
    mpz_tdiv_r_ui (z, w, __gmpxx_abs_ui(l));
Packit 5c3484
  }
Packit 5c3484
  static void eval(mpz_ptr z, signed long int l, mpz_srcptr w)
Packit 5c3484
  {
Packit 5c3484
    if (mpz_fits_slong_p(w))
Packit 5c3484
      mpz_set_si(z, l % mpz_get_si(w));
Packit 5c3484
    else
Packit 5c3484
      {
Packit 5c3484
        /* if w is bigger than a long then the remainder is l unchanged,
Packit 5c3484
           unless l==LONG_MIN and w==-LONG_MIN in which case it's 0 */
Packit 5c3484
        mpz_set_si (z, mpz_cmpabs_ui (w, __gmpxx_abs_ui(l)) == 0 ? 0 : l);
Packit 5c3484
      }
Packit 5c3484
  }
Packit 5c3484
  static void eval(mpz_ptr z, mpz_srcptr w, double d)
Packit 5c3484
  {  __GMPXX_TMPZ_D;    mpz_tdiv_r (z, w, temp); }
Packit 5c3484
  static void eval(mpz_ptr z, double d, mpz_srcptr w)
Packit 5c3484
  {  __GMPXX_TMPZ_D;    mpz_tdiv_r (z, temp, w); }
Packit 5c3484
};
Packit 5c3484
Packit 5c3484
struct __gmp_binary_and
Packit 5c3484
{
Packit 5c3484
  static void eval(mpz_ptr z, mpz_srcptr w, mpz_srcptr v)
Packit 5c3484
  { mpz_and(z, w, v); }
Packit 5c3484
Packit 5c3484
  static void eval(mpz_ptr z, mpz_srcptr w, unsigned long int l)
Packit 5c3484
  {  __GMPXX_TMPZ_UI;   mpz_and (z, w, temp);  }
Packit 5c3484
  static void eval(mpz_ptr z, unsigned long int l, mpz_srcptr w)
Packit 5c3484
  { eval(z, w, l);  }
Packit 5c3484
  static void eval(mpz_ptr z, mpz_srcptr w, signed long int l)
Packit 5c3484
  {  __GMPXX_TMPZ_SI;   mpz_and (z, w, temp);  }
Packit 5c3484
  static void eval(mpz_ptr z, signed long int l, mpz_srcptr w)
Packit 5c3484
  { eval(z, w, l);  }
Packit 5c3484
  static void eval(mpz_ptr z, mpz_srcptr w, double d)
Packit 5c3484
  {  __GMPXX_TMPZ_D;    mpz_and (z, w, temp); }
Packit 5c3484
  static void eval(mpz_ptr z, double d, mpz_srcptr w)
Packit 5c3484
  { eval(z, w, d);  }
Packit 5c3484
};
Packit 5c3484
Packit 5c3484
struct __gmp_binary_ior
Packit 5c3484
{
Packit 5c3484
  static void eval(mpz_ptr z, mpz_srcptr w, mpz_srcptr v)
Packit 5c3484
  { mpz_ior(z, w, v); }
Packit 5c3484
  static void eval(mpz_ptr z, mpz_srcptr w, unsigned long int l)
Packit 5c3484
  {  __GMPXX_TMPZ_UI;   mpz_ior (z, w, temp);  }
Packit 5c3484
  static void eval(mpz_ptr z, unsigned long int l, mpz_srcptr w)
Packit 5c3484
  { eval(z, w, l);  }
Packit 5c3484
  static void eval(mpz_ptr z, mpz_srcptr w, signed long int l)
Packit 5c3484
  {  __GMPXX_TMPZ_SI;   mpz_ior (z, w, temp);  }
Packit 5c3484
  static void eval(mpz_ptr z, signed long int l, mpz_srcptr w)
Packit 5c3484
  { eval(z, w, l);  }
Packit 5c3484
  static void eval(mpz_ptr z, mpz_srcptr w, double d)
Packit 5c3484
  {  __GMPXX_TMPZ_D;    mpz_ior (z, w, temp); }
Packit 5c3484
  static void eval(mpz_ptr z, double d, mpz_srcptr w)
Packit 5c3484
  { eval(z, w, d);  }
Packit 5c3484
};
Packit 5c3484
Packit 5c3484
struct __gmp_binary_xor
Packit 5c3484
{
Packit 5c3484
  static void eval(mpz_ptr z, mpz_srcptr w, mpz_srcptr v)
Packit 5c3484
  { mpz_xor(z, w, v); }
Packit 5c3484
  static void eval(mpz_ptr z, mpz_srcptr w, unsigned long int l)
Packit 5c3484
  {  __GMPXX_TMPZ_UI;   mpz_xor (z, w, temp);  }
Packit 5c3484
  static void eval(mpz_ptr z, unsigned long int l, mpz_srcptr w)
Packit 5c3484
  { eval(z, w, l);  }
Packit 5c3484
  static void eval(mpz_ptr z, mpz_srcptr w, signed long int l)
Packit 5c3484
  {  __GMPXX_TMPZ_SI;   mpz_xor (z, w, temp);  }
Packit 5c3484
  static void eval(mpz_ptr z, signed long int l, mpz_srcptr w)
Packit 5c3484
  { eval(z, w, l);  }
Packit 5c3484
  static void eval(mpz_ptr z, mpz_srcptr w, double d)
Packit 5c3484
  {  __GMPXX_TMPZ_D;    mpz_xor (z, w, temp); }
Packit 5c3484
  static void eval(mpz_ptr z, double d, mpz_srcptr w)
Packit 5c3484
  { eval(z, w, d);  }
Packit 5c3484
};
Packit 5c3484
Packit 5c3484
struct __gmp_cmp_function
Packit 5c3484
{
Packit 5c3484
  static int eval(mpz_srcptr z, mpz_srcptr w) { return mpz_cmp(z, w); }
Packit 5c3484
Packit 5c3484
  static int eval(mpz_srcptr z, unsigned long int l)
Packit 5c3484
  { return mpz_cmp_ui(z, l); }
Packit 5c3484
  static int eval(unsigned long int l, mpz_srcptr z)
Packit 5c3484
  { return -mpz_cmp_ui(z, l); }
Packit 5c3484
  static int eval(mpz_srcptr z, signed long int l)
Packit 5c3484
  { return mpz_cmp_si(z, l); }
Packit 5c3484
  static int eval(signed long int l, mpz_srcptr z)
Packit 5c3484
  { return -mpz_cmp_si(z, l); }
Packit 5c3484
  static int eval(mpz_srcptr z, double d)
Packit 5c3484
  { return mpz_cmp_d(z, d); }
Packit 5c3484
  static int eval(double d, mpz_srcptr z)
Packit 5c3484
  { return -mpz_cmp_d(z, d); }
Packit 5c3484
Packit 5c3484
  static int eval(mpq_srcptr q, mpq_srcptr r) { return mpq_cmp(q, r); }
Packit 5c3484
Packit 5c3484
  static int eval(mpq_srcptr q, unsigned long int l)
Packit 5c3484
  { return mpq_cmp_ui(q, l, 1); }
Packit 5c3484
  static int eval(unsigned long int l, mpq_srcptr q)
Packit 5c3484
  { return -mpq_cmp_ui(q, l, 1); }
Packit 5c3484
  static int eval(mpq_srcptr q, signed long int l)
Packit 5c3484
  { return mpq_cmp_si(q, l, 1); }
Packit 5c3484
  static int eval(signed long int l, mpq_srcptr q)
Packit 5c3484
  { return -mpq_cmp_si(q, l, 1); }
Packit 5c3484
  static int eval(mpq_srcptr q, double d)
Packit 5c3484
  {  __GMPXX_TMPQ_D;    return mpq_cmp (q, temp); }
Packit 5c3484
  static int eval(double d, mpq_srcptr q)
Packit 5c3484
  {  __GMPXX_TMPQ_D;    return mpq_cmp (temp, q); }
Packit 5c3484
  static int eval(mpq_srcptr q, mpz_srcptr z)
Packit 5c3484
  { return mpq_cmp_z(q, z); }
Packit 5c3484
  static int eval(mpz_srcptr z, mpq_srcptr q)
Packit 5c3484
  { return -mpq_cmp_z(q, z); }
Packit 5c3484
Packit 5c3484
  static int eval(mpf_srcptr f, mpf_srcptr g) { return mpf_cmp(f, g); }
Packit 5c3484
Packit 5c3484
  static int eval(mpf_srcptr f, unsigned long int l)
Packit 5c3484
  { return mpf_cmp_ui(f, l); }
Packit 5c3484
  static int eval(unsigned long int l, mpf_srcptr f)
Packit 5c3484
  { return -mpf_cmp_ui(f, l); }
Packit 5c3484
  static int eval(mpf_srcptr f, signed long int l)
Packit 5c3484
  { return mpf_cmp_si(f, l); }
Packit 5c3484
  static int eval(signed long int l, mpf_srcptr f)
Packit 5c3484
  { return -mpf_cmp_si(f, l); }
Packit 5c3484
  static int eval(mpf_srcptr f, double d)
Packit 5c3484
  { return mpf_cmp_d(f, d); }
Packit 5c3484
  static int eval(double d, mpf_srcptr f)
Packit 5c3484
  { return -mpf_cmp_d(f, d); }
Packit 5c3484
  static int eval(mpf_srcptr f, mpz_srcptr z)
Packit 5c3484
  { return mpf_cmp_z(f, z); }
Packit 5c3484
  static int eval(mpz_srcptr z, mpf_srcptr f)
Packit 5c3484
  { return -mpf_cmp_z(f, z); }
Packit 5c3484
  static int eval(mpf_srcptr f, mpq_srcptr q)
Packit 5c3484
  {
Packit 5c3484
    mpf_t qf;
Packit 5c3484
    mpf_init(qf); /* Should we use the precision of f?  */
Packit 5c3484
    mpf_set_q(qf, q);
Packit 5c3484
    int ret = eval(f, qf);
Packit 5c3484
    mpf_clear(qf);
Packit 5c3484
    return ret;
Packit 5c3484
  }
Packit 5c3484
  static int eval(mpq_srcptr q, mpf_srcptr f)
Packit 5c3484
  { return -eval(f, q); }
Packit 5c3484
};
Packit 5c3484
Packit 5c3484
struct __gmp_binary_equal
Packit 5c3484
{
Packit 5c3484
  static bool eval(mpz_srcptr z, mpz_srcptr w) { return mpz_cmp(z, w) == 0; }
Packit 5c3484
Packit 5c3484
  static bool eval(mpz_srcptr z, unsigned long int l)
Packit 5c3484
  { return mpz_cmp_ui(z, l) == 0; }
Packit 5c3484
  static bool eval(unsigned long int l, mpz_srcptr z)
Packit 5c3484
  { return eval(z, l); }
Packit 5c3484
  static bool eval(mpz_srcptr z, signed long int l)
Packit 5c3484
  { return mpz_cmp_si(z, l) == 0; }
Packit 5c3484
  static bool eval(signed long int l, mpz_srcptr z)
Packit 5c3484
  { return eval(z, l); }
Packit 5c3484
  static bool eval(mpz_srcptr z, double d)
Packit 5c3484
  { return mpz_cmp_d(z, d) == 0; }
Packit 5c3484
  static bool eval(double d, mpz_srcptr z)
Packit 5c3484
  { return eval(z, d); }
Packit 5c3484
Packit 5c3484
  static bool eval(mpq_srcptr q, mpq_srcptr r)
Packit 5c3484
  { return mpq_equal(q, r) != 0; }
Packit 5c3484
Packit 5c3484
  static bool eval(mpq_srcptr q, unsigned long int l)
Packit 5c3484
  { return mpq_cmp_ui(q, l, 1) == 0; }
Packit 5c3484
  static bool eval(unsigned long int l, mpq_srcptr q)
Packit 5c3484
  { return eval(q, l); }
Packit 5c3484
  static bool eval(mpq_srcptr q, signed long int l)
Packit 5c3484
  { return mpq_cmp_si(q, l, 1) == 0; }
Packit 5c3484
  static bool eval(signed long int l, mpq_srcptr q)
Packit 5c3484
  { return eval(q, l); }
Packit 5c3484
  static bool eval(mpq_srcptr q, double d)
Packit 5c3484
  {  __GMPXX_TMPQ_D;    return mpq_equal (q, temp) != 0; }
Packit 5c3484
  static bool eval(double d, mpq_srcptr q)
Packit 5c3484
  { return eval(q, d); }
Packit 5c3484
  static bool eval(mpq_srcptr q, mpz_srcptr z)
Packit 5c3484
  { return mpq_cmp_z(q, z) == 0; }
Packit 5c3484
  static bool eval(mpz_srcptr z, mpq_srcptr q)
Packit 5c3484
  { return eval(q, z); }
Packit 5c3484
Packit 5c3484
  static bool eval(mpf_srcptr f, mpf_srcptr g) { return mpf_cmp(f, g) == 0; }
Packit 5c3484
Packit 5c3484
  static bool eval(mpf_srcptr f, unsigned long int l)
Packit 5c3484
  { return mpf_cmp_ui(f, l) == 0; }
Packit 5c3484
  static bool eval(unsigned long int l, mpf_srcptr f)
Packit 5c3484
  { return eval(f, l); }
Packit 5c3484
  static bool eval(mpf_srcptr f, signed long int l)
Packit 5c3484
  { return mpf_cmp_si(f, l) == 0; }
Packit 5c3484
  static bool eval(signed long int l, mpf_srcptr f)
Packit 5c3484
  { return eval(f, l); }
Packit 5c3484
  static bool eval(mpf_srcptr f, double d)
Packit 5c3484
  { return mpf_cmp_d(f, d) == 0; }
Packit 5c3484
  static bool eval(double d, mpf_srcptr f)
Packit 5c3484
  { return eval(f, d); }
Packit 5c3484
  static bool eval(mpf_srcptr f, mpz_srcptr z)
Packit 5c3484
  { return mpf_cmp_z(f, z) == 0; }
Packit 5c3484
  static bool eval(mpz_srcptr z, mpf_srcptr f)
Packit 5c3484
  { return eval(f, z); }
Packit 5c3484
  static bool eval(mpf_srcptr f, mpq_srcptr q)
Packit 5c3484
  { return __gmp_cmp_function::eval(f, q) == 0; }
Packit 5c3484
  static bool eval(mpq_srcptr q, mpf_srcptr f)
Packit 5c3484
  { return eval(f, q); }
Packit 5c3484
};
Packit 5c3484
Packit 5c3484
struct __gmp_binary_less
Packit 5c3484
{
Packit 5c3484
  static bool eval(mpz_srcptr z, mpz_srcptr w) { return mpz_cmp(z, w) < 0; }
Packit 5c3484
Packit 5c3484
  static bool eval(mpz_srcptr z, unsigned long int l)
Packit 5c3484
  { return mpz_cmp_ui(z, l) < 0; }
Packit 5c3484
  static bool eval(unsigned long int l, mpz_srcptr z)
Packit 5c3484
  { return mpz_cmp_ui(z, l) > 0; }
Packit 5c3484
  static bool eval(mpz_srcptr z, signed long int l)
Packit 5c3484
  { return mpz_cmp_si(z, l) < 0; }
Packit 5c3484
  static bool eval(signed long int l, mpz_srcptr z)
Packit 5c3484
  { return mpz_cmp_si(z, l) > 0; }
Packit 5c3484
  static bool eval(mpz_srcptr z, double d)
Packit 5c3484
  { return mpz_cmp_d(z, d) < 0; }
Packit 5c3484
  static bool eval(double d, mpz_srcptr z)
Packit 5c3484
  { return mpz_cmp_d(z, d) > 0; }
Packit 5c3484
Packit 5c3484
  static bool eval(mpq_srcptr q, mpq_srcptr r) { return mpq_cmp(q, r) < 0; }
Packit 5c3484
Packit 5c3484
  static bool eval(mpq_srcptr q, unsigned long int l)
Packit 5c3484
  { return mpq_cmp_ui(q, l, 1) < 0; }
Packit 5c3484
  static bool eval(unsigned long int l, mpq_srcptr q)
Packit 5c3484
  { return mpq_cmp_ui(q, l, 1) > 0; }
Packit 5c3484
  static bool eval(mpq_srcptr q, signed long int l)
Packit 5c3484
  { return mpq_cmp_si(q, l, 1) < 0; }
Packit 5c3484
  static bool eval(signed long int l, mpq_srcptr q)
Packit 5c3484
  { return mpq_cmp_si(q, l, 1) > 0; }
Packit 5c3484
  static bool eval(mpq_srcptr q, double d)
Packit 5c3484
  {  __GMPXX_TMPQ_D;    return mpq_cmp (q, temp) < 0; }
Packit 5c3484
  static bool eval(double d, mpq_srcptr q)
Packit 5c3484
  {  __GMPXX_TMPQ_D;    return mpq_cmp (temp, q) < 0; }
Packit 5c3484
  static bool eval(mpq_srcptr q, mpz_srcptr z)
Packit 5c3484
  { return mpq_cmp_z(q, z) < 0; }
Packit 5c3484
  static bool eval(mpz_srcptr z, mpq_srcptr q)
Packit 5c3484
  { return mpq_cmp_z(q, z) > 0; }
Packit 5c3484
Packit 5c3484
  static bool eval(mpf_srcptr f, mpf_srcptr g) { return mpf_cmp(f, g) < 0; }
Packit 5c3484
Packit 5c3484
  static bool eval(mpf_srcptr f, unsigned long int l)
Packit 5c3484
  { return mpf_cmp_ui(f, l) < 0; }
Packit 5c3484
  static bool eval(unsigned long int l, mpf_srcptr f)
Packit 5c3484
  { return mpf_cmp_ui(f, l) > 0; }
Packit 5c3484
  static bool eval(mpf_srcptr f, signed long int l)
Packit 5c3484
  { return mpf_cmp_si(f, l) < 0; }
Packit 5c3484
  static bool eval(signed long int l, mpf_srcptr f)
Packit 5c3484
  { return mpf_cmp_si(f, l) > 0; }
Packit 5c3484
  static bool eval(mpf_srcptr f, double d)
Packit 5c3484
  { return mpf_cmp_d(f, d) < 0; }
Packit 5c3484
  static bool eval(double d, mpf_srcptr f)
Packit 5c3484
  { return mpf_cmp_d(f, d) > 0; }
Packit 5c3484
  static bool eval(mpf_srcptr f, mpz_srcptr z)
Packit 5c3484
  { return mpf_cmp_z(f, z) < 0; }
Packit 5c3484
  static bool eval(mpz_srcptr z, mpf_srcptr f)
Packit 5c3484
  { return mpf_cmp_z(f, z) > 0; }
Packit 5c3484
  static bool eval(mpf_srcptr f, mpq_srcptr q)
Packit 5c3484
  { return __gmp_cmp_function::eval(f, q) < 0; }
Packit 5c3484
  static bool eval(mpq_srcptr q, mpf_srcptr f)
Packit 5c3484
  { return __gmp_cmp_function::eval(q, f) < 0; }
Packit 5c3484
};
Packit 5c3484
Packit 5c3484
struct __gmp_binary_greater
Packit 5c3484
{
Packit 5c3484
  template <class T, class U>
Packit 5c3484
  static inline bool eval(T t, U u) { return __gmp_binary_less::eval(u, t); }
Packit 5c3484
};
Packit 5c3484
Packit 5c3484
struct __gmp_unary_increment
Packit 5c3484
{
Packit 5c3484
  static void eval(mpz_ptr z) { mpz_add_ui(z, z, 1); }
Packit 5c3484
  static void eval(mpq_ptr q)
Packit 5c3484
  { mpz_add(mpq_numref(q), mpq_numref(q), mpq_denref(q)); }
Packit 5c3484
  static void eval(mpf_ptr f) { mpf_add_ui(f, f, 1); }
Packit 5c3484
};
Packit 5c3484
Packit 5c3484
struct __gmp_unary_decrement
Packit 5c3484
{
Packit 5c3484
  static void eval(mpz_ptr z) { mpz_sub_ui(z, z, 1); }
Packit 5c3484
  static void eval(mpq_ptr q)
Packit 5c3484
  { mpz_sub(mpq_numref(q), mpq_numref(q), mpq_denref(q)); }
Packit 5c3484
  static void eval(mpf_ptr f) { mpf_sub_ui(f, f, 1); }
Packit 5c3484
};
Packit 5c3484
Packit 5c3484
struct __gmp_abs_function
Packit 5c3484
{
Packit 5c3484
  static void eval(mpz_ptr z, mpz_srcptr w) { mpz_abs(z, w); }
Packit 5c3484
  static void eval(mpq_ptr q, mpq_srcptr r) { mpq_abs(q, r); }
Packit 5c3484
  static void eval(mpf_ptr f, mpf_srcptr g) { mpf_abs(f, g); }
Packit 5c3484
};
Packit 5c3484
Packit 5c3484
struct __gmp_trunc_function
Packit 5c3484
{
Packit 5c3484
  static void eval(mpf_ptr f, mpf_srcptr g) { mpf_trunc(f, g); }
Packit 5c3484
};
Packit 5c3484
Packit 5c3484
struct __gmp_floor_function
Packit 5c3484
{
Packit 5c3484
  static void eval(mpf_ptr f, mpf_srcptr g) { mpf_floor(f, g); }
Packit 5c3484
};
Packit 5c3484
Packit 5c3484
struct __gmp_ceil_function
Packit 5c3484
{
Packit 5c3484
  static void eval(mpf_ptr f, mpf_srcptr g) { mpf_ceil(f, g); }
Packit 5c3484
};
Packit 5c3484
Packit 5c3484
struct __gmp_sqrt_function
Packit 5c3484
{
Packit 5c3484
  static void eval(mpz_ptr z, mpz_srcptr w) { mpz_sqrt(z, w); }
Packit 5c3484
  static void eval(mpf_ptr f, mpf_srcptr g) { mpf_sqrt(f, g); }
Packit 5c3484
};
Packit 5c3484
Packit 5c3484
struct __gmp_hypot_function
Packit 5c3484
{
Packit 5c3484
  static void eval(mpf_ptr f, mpf_srcptr g, mpf_srcptr h)
Packit 5c3484
  {
Packit 5c3484
    mpf_t temp;
Packit 5c3484
    mpf_init2(temp, mpf_get_prec(f));
Packit 5c3484
    mpf_mul(temp, g, g);
Packit 5c3484
    mpf_mul(f, h, h);
Packit 5c3484
    mpf_add(f, f, temp);
Packit 5c3484
    mpf_sqrt(f, f);
Packit 5c3484
    mpf_clear(temp);
Packit 5c3484
  }
Packit 5c3484
Packit 5c3484
  static void eval(mpf_ptr f, mpf_srcptr g, unsigned long int l)
Packit 5c3484
  {
Packit 5c3484
    mpf_t temp;
Packit 5c3484
    mpf_init2(temp, mpf_get_prec(f));
Packit 5c3484
    mpf_mul(temp, g, g);
Packit 5c3484
    mpf_set_ui(f, l);
Packit 5c3484
    mpf_mul_ui(f, f, l);
Packit 5c3484
    mpf_add(f, f, temp);
Packit 5c3484
    mpf_clear(temp);
Packit 5c3484
    mpf_sqrt(f, f);
Packit 5c3484
  }
Packit 5c3484
  static void eval(mpf_ptr f, unsigned long int l, mpf_srcptr g)
Packit 5c3484
  { eval(f, g, l); }
Packit 5c3484
  static void eval(mpf_ptr f, mpf_srcptr g, signed long int l)
Packit 5c3484
  { eval(f, g, __gmpxx_abs_ui(l)); }
Packit 5c3484
  static void eval(mpf_ptr f, signed long int l, mpf_srcptr g)
Packit 5c3484
  { eval(f, g, l); }
Packit 5c3484
  static void eval(mpf_ptr f, mpf_srcptr g, double d)
Packit 5c3484
  {
Packit 5c3484
    mpf_t temp;
Packit 5c3484
    mpf_init2(temp, mpf_get_prec(f));
Packit 5c3484
    mpf_mul(temp, g, g);
Packit 5c3484
    mpf_set_d(f, d);
Packit 5c3484
    mpf_mul(f, f, f);
Packit 5c3484
    mpf_add(f, f, temp);
Packit 5c3484
    mpf_sqrt(f, f);
Packit 5c3484
    mpf_clear(temp);
Packit 5c3484
  }
Packit 5c3484
  static void eval(mpf_ptr f, double d, mpf_srcptr g)
Packit 5c3484
  { eval(f, g, d); }
Packit 5c3484
};
Packit 5c3484
Packit 5c3484
struct __gmp_sgn_function
Packit 5c3484
{
Packit 5c3484
  static int eval(mpz_srcptr z) { return mpz_sgn(z); }
Packit 5c3484
  static int eval(mpq_srcptr q) { return mpq_sgn(q); }
Packit 5c3484
  static int eval(mpf_srcptr f) { return mpf_sgn(f); }
Packit 5c3484
};
Packit 5c3484
Packit 5c3484
struct __gmp_gcd_function
Packit 5c3484
{
Packit 5c3484
  static void eval(mpz_ptr z, mpz_srcptr w, mpz_srcptr v)
Packit 5c3484
  { mpz_gcd(z, w, v); }
Packit 5c3484
  static void eval(mpz_ptr z, mpz_srcptr w, unsigned long int l)
Packit 5c3484
  { mpz_gcd_ui(z, w, l); }
Packit 5c3484
  static void eval(mpz_ptr z, unsigned long int l, mpz_srcptr w)
Packit 5c3484
  { eval(z, w, l); }
Packit 5c3484
  static void eval(mpz_ptr z, mpz_srcptr w, signed long int l)
Packit 5c3484
  { eval(z, w, __gmpxx_abs_ui(l)); }
Packit 5c3484
  static void eval(mpz_ptr z, signed long int l, mpz_srcptr w)
Packit 5c3484
  { eval(z, w, l); }
Packit 5c3484
  static void eval(mpz_ptr z, mpz_srcptr w, double d)
Packit 5c3484
  {  __GMPXX_TMPZ_D;    mpz_gcd (z, w, temp); }
Packit 5c3484
  static void eval(mpz_ptr z, double d, mpz_srcptr w)
Packit 5c3484
  { eval(z, w, d); }
Packit 5c3484
};
Packit 5c3484
Packit 5c3484
struct __gmp_lcm_function
Packit 5c3484
{
Packit 5c3484
  static void eval(mpz_ptr z, mpz_srcptr w, mpz_srcptr v)
Packit 5c3484
  { mpz_lcm(z, w, v); }
Packit 5c3484
  static void eval(mpz_ptr z, mpz_srcptr w, unsigned long int l)
Packit 5c3484
  { mpz_lcm_ui(z, w, l); }
Packit 5c3484
  static void eval(mpz_ptr z, unsigned long int l, mpz_srcptr w)
Packit 5c3484
  { eval(z, w, l); }
Packit 5c3484
  static void eval(mpz_ptr z, mpz_srcptr w, signed long int l)
Packit 5c3484
  { eval(z, w, __gmpxx_abs_ui(l)); }
Packit 5c3484
  static void eval(mpz_ptr z, signed long int l, mpz_srcptr w)
Packit 5c3484
  { eval(z, w, l); }
Packit 5c3484
  static void eval(mpz_ptr z, mpz_srcptr w, double d)
Packit 5c3484
  {  __GMPXX_TMPZ_D;    mpz_lcm (z, w, temp); }
Packit 5c3484
  static void eval(mpz_ptr z, double d, mpz_srcptr w)
Packit 5c3484
  { eval(z, w, d); }
Packit 5c3484
};
Packit 5c3484
Packit 5c3484
struct __gmp_rand_function
Packit 5c3484
{
Packit 5c3484
  static void eval(mpz_ptr z, gmp_randstate_t s, mp_bitcnt_t l)
Packit 5c3484
  { mpz_urandomb(z, s, l); }
Packit 5c3484
  static void eval(mpz_ptr z, gmp_randstate_t s, mpz_srcptr w)
Packit 5c3484
  { mpz_urandomm(z, s, w); }
Packit 5c3484
  static void eval(mpf_ptr f, gmp_randstate_t s, mp_bitcnt_t prec)
Packit 5c3484
  { mpf_urandomb(f, s, prec); }
Packit 5c3484
};
Packit 5c3484
Packit 5c3484
Packit 5c3484
/**************** Auxiliary classes ****************/
Packit 5c3484
Packit 5c3484
/* this is much the same as gmp_allocated_string in gmp-impl.h
Packit 5c3484
   since gmp-impl.h is not publicly available, I redefine it here
Packit 5c3484
   I use a different name to avoid possible clashes */
Packit 5c3484
Packit 5c3484
extern "C" {
Packit 5c3484
  typedef void (*__gmp_freefunc_t) (void *, size_t);
Packit 5c3484
}
Packit 5c3484
struct __gmp_alloc_cstring
Packit 5c3484
{
Packit 5c3484
  char *str;
Packit 5c3484
  __gmp_alloc_cstring(char *s) { str = s; }
Packit 5c3484
  ~__gmp_alloc_cstring()
Packit 5c3484
  {
Packit 5c3484
    __gmp_freefunc_t freefunc;
Packit 5c3484
    mp_get_memory_functions (NULL, NULL, &freefunc);
Packit 5c3484
    (*freefunc) (str, std::strlen(str)+1);
Packit 5c3484
  }
Packit 5c3484
};
Packit 5c3484
Packit 5c3484
Packit 5c3484
// general expression template class
Packit 5c3484
template <class T, class U>
Packit 5c3484
class __gmp_expr;
Packit 5c3484
Packit 5c3484
Packit 5c3484
// templates for resolving expression types
Packit 5c3484
template <class T>
Packit 5c3484
struct __gmp_resolve_ref
Packit 5c3484
{
Packit 5c3484
  typedef T ref_type;
Packit 5c3484
};
Packit 5c3484
Packit 5c3484
template <class T, class U>
Packit 5c3484
struct __gmp_resolve_ref<__gmp_expr<T, U> >
Packit 5c3484
{
Packit 5c3484
  typedef const __gmp_expr<T, U> & ref_type;
Packit 5c3484
};
Packit 5c3484
Packit 5c3484
Packit 5c3484
template <class T, class U = T>
Packit 5c3484
struct __gmp_resolve_expr;
Packit 5c3484
Packit 5c3484
template <>
Packit 5c3484
struct __gmp_resolve_expr<mpz_t>
Packit 5c3484
{
Packit 5c3484
  typedef mpz_t value_type;
Packit 5c3484
  typedef mpz_ptr ptr_type;
Packit 5c3484
  typedef mpz_srcptr srcptr_type;
Packit 5c3484
};
Packit 5c3484
Packit 5c3484
template <>
Packit 5c3484
struct __gmp_resolve_expr<mpq_t>
Packit 5c3484
{
Packit 5c3484
  typedef mpq_t value_type;
Packit 5c3484
  typedef mpq_ptr ptr_type;
Packit 5c3484
  typedef mpq_srcptr srcptr_type;
Packit 5c3484
};
Packit 5c3484
Packit 5c3484
template <>
Packit 5c3484
struct __gmp_resolve_expr<mpf_t>
Packit 5c3484
{
Packit 5c3484
  typedef mpf_t value_type;
Packit 5c3484
  typedef mpf_ptr ptr_type;
Packit 5c3484
  typedef mpf_srcptr srcptr_type;
Packit 5c3484
};
Packit 5c3484
Packit 5c3484
template <>
Packit 5c3484
struct __gmp_resolve_expr<mpz_t, mpq_t>
Packit 5c3484
{
Packit 5c3484
  typedef mpq_t value_type;
Packit 5c3484
};
Packit 5c3484
Packit 5c3484
template <>
Packit 5c3484
struct __gmp_resolve_expr<mpq_t, mpz_t>
Packit 5c3484
{
Packit 5c3484
  typedef mpq_t value_type;
Packit 5c3484
};
Packit 5c3484
Packit 5c3484
template <>
Packit 5c3484
struct __gmp_resolve_expr<mpz_t, mpf_t>
Packit 5c3484
{
Packit 5c3484
  typedef mpf_t value_type;
Packit 5c3484
};
Packit 5c3484
Packit 5c3484
template <>
Packit 5c3484
struct __gmp_resolve_expr<mpf_t, mpz_t>
Packit 5c3484
{
Packit 5c3484
  typedef mpf_t value_type;
Packit 5c3484
};
Packit 5c3484
Packit 5c3484
template <>
Packit 5c3484
struct __gmp_resolve_expr<mpq_t, mpf_t>
Packit 5c3484
{
Packit 5c3484
  typedef mpf_t value_type;
Packit 5c3484
};
Packit 5c3484
Packit 5c3484
template <>
Packit 5c3484
struct __gmp_resolve_expr<mpf_t, mpq_t>
Packit 5c3484
{
Packit 5c3484
  typedef mpf_t value_type;
Packit 5c3484
};
Packit 5c3484
Packit 5c3484
#if __GMPXX_USE_CXX11
Packit 5c3484
namespace std {
Packit 5c3484
  template <class T, class U, class V, class W>
Packit 5c3484
  struct common_type <__gmp_expr<T, U>, __gmp_expr<V, W> >
Packit 5c3484
  {
Packit 5c3484
  private:
Packit 5c3484
    typedef typename __gmp_resolve_expr<T, V>::value_type X;
Packit 5c3484
  public:
Packit 5c3484
    typedef __gmp_expr<X, X> type;
Packit 5c3484
  };
Packit 5c3484
Packit 5c3484
  template <class T, class U>
Packit 5c3484
  struct common_type <__gmp_expr<T, U> >
Packit 5c3484
  {
Packit 5c3484
    typedef __gmp_expr<T, T> type;
Packit 5c3484
  };
Packit 5c3484
Packit 5c3484
#define __GMPXX_DECLARE_COMMON_TYPE(typ)	\
Packit 5c3484
  template <class T, class U>			\
Packit 5c3484
  struct common_type <__gmp_expr<T, U>, typ >	\
Packit 5c3484
  {						\
Packit 5c3484
    typedef __gmp_expr<T, T> type;		\
Packit 5c3484
  };						\
Packit 5c3484
						\
Packit 5c3484
  template <class T, class U>			\
Packit 5c3484
  struct common_type <typ, __gmp_expr<T, U> >	\
Packit 5c3484
  {						\
Packit 5c3484
    typedef __gmp_expr<T, T> type;		\
Packit 5c3484
  }
Packit 5c3484
Packit 5c3484
  __GMPXX_DECLARE_COMMON_TYPE(signed char);
Packit 5c3484
  __GMPXX_DECLARE_COMMON_TYPE(unsigned char);
Packit 5c3484
  __GMPXX_DECLARE_COMMON_TYPE(signed int);
Packit 5c3484
  __GMPXX_DECLARE_COMMON_TYPE(unsigned int);
Packit 5c3484
  __GMPXX_DECLARE_COMMON_TYPE(signed short int);
Packit 5c3484
  __GMPXX_DECLARE_COMMON_TYPE(unsigned short int);
Packit 5c3484
  __GMPXX_DECLARE_COMMON_TYPE(signed long int);
Packit 5c3484
  __GMPXX_DECLARE_COMMON_TYPE(unsigned long int);
Packit 5c3484
  __GMPXX_DECLARE_COMMON_TYPE(float);
Packit 5c3484
  __GMPXX_DECLARE_COMMON_TYPE(double);
Packit 5c3484
#undef __GMPXX_DECLARE_COMMON_TYPE
Packit 5c3484
}
Packit 5c3484
#endif
Packit 5c3484
Packit 5c3484
// classes for evaluating unary and binary expressions
Packit 5c3484
template <class T, class Op>
Packit 5c3484
struct __gmp_unary_expr
Packit 5c3484
{
Packit 5c3484
  typename __gmp_resolve_ref<T>::ref_type val;
Packit 5c3484
Packit 5c3484
  __gmp_unary_expr(const T &v) : val(v) { }
Packit 5c3484
private:
Packit 5c3484
  __gmp_unary_expr();
Packit 5c3484
};
Packit 5c3484
Packit 5c3484
template <class T, class U, class Op>
Packit 5c3484
struct __gmp_binary_expr
Packit 5c3484
{
Packit 5c3484
  typename __gmp_resolve_ref<T>::ref_type val1;
Packit 5c3484
  typename __gmp_resolve_ref<U>::ref_type val2;
Packit 5c3484
Packit 5c3484
  __gmp_binary_expr(const T &v1, const U &v2) : val1(v1), val2(v2) { }
Packit 5c3484
private:
Packit 5c3484
  __gmp_binary_expr();
Packit 5c3484
};
Packit 5c3484
Packit 5c3484
Packit 5c3484
Packit 5c3484
/**************** Macros for in-class declarations ****************/
Packit 5c3484
/* This is just repetitive code that is easier to maintain if it's written
Packit 5c3484
   only once */
Packit 5c3484
Packit 5c3484
#define __GMPP_DECLARE_COMPOUND_OPERATOR(fun)                         \
Packit 5c3484
  template <class T, class U>                                         \
Packit 5c3484
  __gmp_expr<value_type, value_type> & fun(const __gmp_expr<T, U> &);
Packit 5c3484
Packit 5c3484
#define __GMPN_DECLARE_COMPOUND_OPERATOR(fun) \
Packit 5c3484
  __gmp_expr & fun(signed char);              \
Packit 5c3484
  __gmp_expr & fun(unsigned char);            \
Packit 5c3484
  __gmp_expr & fun(signed int);               \
Packit 5c3484
  __gmp_expr & fun(unsigned int);             \
Packit 5c3484
  __gmp_expr & fun(signed short int);         \
Packit 5c3484
  __gmp_expr & fun(unsigned short int);       \
Packit 5c3484
  __gmp_expr & fun(signed long int);          \
Packit 5c3484
  __gmp_expr & fun(unsigned long int);        \
Packit 5c3484
  __gmp_expr & fun(float);                    \
Packit 5c3484
  __gmp_expr & fun(double);                   \
Packit 5c3484
  /* __gmp_expr & fun(long double); */
Packit 5c3484
Packit 5c3484
#define __GMP_DECLARE_COMPOUND_OPERATOR(fun) \
Packit 5c3484
__GMPP_DECLARE_COMPOUND_OPERATOR(fun)        \
Packit 5c3484
__GMPN_DECLARE_COMPOUND_OPERATOR(fun)
Packit 5c3484
Packit 5c3484
#define __GMP_DECLARE_COMPOUND_OPERATOR_UI(fun) \
Packit 5c3484
  __gmp_expr & fun(mp_bitcnt_t);
Packit 5c3484
Packit 5c3484
#define __GMP_DECLARE_INCREMENT_OPERATOR(fun) \
Packit 5c3484
  inline __gmp_expr & fun();                  \
Packit 5c3484
  inline __gmp_expr fun(int);
Packit 5c3484
Packit 5c3484
#define __GMPXX_DEFINE_ARITHMETIC_CONSTRUCTORS		\
Packit 5c3484
  __gmp_expr(signed char c) { init_si(c); }		\
Packit 5c3484
  __gmp_expr(unsigned char c) { init_ui(c); }		\
Packit 5c3484
  __gmp_expr(signed int i) { init_si(i); }		\
Packit 5c3484
  __gmp_expr(unsigned int i) { init_ui(i); }		\
Packit 5c3484
  __gmp_expr(signed short int s) { init_si(s); }	\
Packit 5c3484
  __gmp_expr(unsigned short int s) { init_ui(s); }	\
Packit 5c3484
  __gmp_expr(signed long int l) { init_si(l); }		\
Packit 5c3484
  __gmp_expr(unsigned long int l) { init_ui(l); }	\
Packit 5c3484
  __gmp_expr(float f) { init_d(f); }			\
Packit 5c3484
  __gmp_expr(double d) { init_d(d); }
Packit 5c3484
Packit 5c3484
#define __GMPXX_DEFINE_ARITHMETIC_ASSIGNMENTS		\
Packit 5c3484
  __gmp_expr & operator=(signed char c) { assign_si(c); return *this; } \
Packit 5c3484
  __gmp_expr & operator=(unsigned char c) { assign_ui(c); return *this; } \
Packit 5c3484
  __gmp_expr & operator=(signed int i) { assign_si(i); return *this; } \
Packit 5c3484
  __gmp_expr & operator=(unsigned int i) { assign_ui(i); return *this; } \
Packit 5c3484
  __gmp_expr & operator=(signed short int s) { assign_si(s); return *this; } \
Packit 5c3484
  __gmp_expr & operator=(unsigned short int s) { assign_ui(s); return *this; } \
Packit 5c3484
  __gmp_expr & operator=(signed long int l) { assign_si(l); return *this; } \
Packit 5c3484
  __gmp_expr & operator=(unsigned long int l) { assign_ui(l); return *this; } \
Packit 5c3484
  __gmp_expr & operator=(float f) { assign_d(f); return *this; } \
Packit 5c3484
  __gmp_expr & operator=(double d) { assign_d(d); return *this; }
Packit 5c3484
Packit 5c3484
/**************** mpz_class -- wrapper for mpz_t ****************/
Packit 5c3484
Packit 5c3484
template <>
Packit 5c3484
class __gmp_expr<mpz_t, mpz_t>
Packit 5c3484
{
Packit 5c3484
private:
Packit 5c3484
  typedef mpz_t value_type;
Packit 5c3484
  value_type mp;
Packit 5c3484
Packit 5c3484
  // Helper functions used for all arithmetic types
Packit 5c3484
  void assign_ui(unsigned long l)
Packit 5c3484
  {
Packit 5c3484
    if (__GMPXX_CONSTANT_TRUE(l == 0))
Packit 5c3484
      mp->_mp_size = 0;
Packit 5c3484
    else
Packit 5c3484
      mpz_set_ui(mp, l);
Packit 5c3484
  }
Packit 5c3484
  void assign_si(signed long l)
Packit 5c3484
  {
Packit 5c3484
    if (__GMPXX_CONSTANT_TRUE(l >= 0))
Packit 5c3484
      assign_ui(l);
Packit 5c3484
    else if (__GMPXX_CONSTANT_TRUE(l <= 0))
Packit 5c3484
      {
Packit 5c3484
	assign_ui(-static_cast<unsigned long>(l));
Packit 5c3484
	mpz_neg(mp, mp);
Packit 5c3484
      }
Packit 5c3484
    else
Packit 5c3484
      mpz_set_si(mp, l);
Packit 5c3484
  }
Packit 5c3484
  void assign_d (double d)
Packit 5c3484
  {
Packit 5c3484
    mpz_set_d (mp, d);
Packit 5c3484
  }
Packit 5c3484
Packit 5c3484
  void init_ui(unsigned long l)
Packit 5c3484
  {
Packit 5c3484
    if (__GMPXX_CONSTANT_TRUE(l == 0))
Packit 5c3484
      mpz_init(mp);
Packit 5c3484
    else
Packit 5c3484
      mpz_init_set_ui(mp, l);
Packit 5c3484
  }
Packit 5c3484
  void init_si(signed long l)
Packit 5c3484
  {
Packit 5c3484
    if (__GMPXX_CONSTANT_TRUE(l >= 0))
Packit 5c3484
      init_ui(l);
Packit 5c3484
    else if (__GMPXX_CONSTANT_TRUE(l <= 0))
Packit 5c3484
      {
Packit 5c3484
	init_ui(-static_cast<unsigned long>(l));
Packit 5c3484
	mpz_neg(mp, mp);
Packit 5c3484
      }
Packit 5c3484
    else
Packit 5c3484
      mpz_init_set_si(mp, l);
Packit 5c3484
  }
Packit 5c3484
  void init_d (double d)
Packit 5c3484
  {
Packit 5c3484
    mpz_init_set_d (mp, d);
Packit 5c3484
  }
Packit 5c3484
Packit 5c3484
public:
Packit 5c3484
  mp_bitcnt_t get_prec() const { return mpf_get_default_prec(); }
Packit 5c3484
Packit 5c3484
  // constructors and destructor
Packit 5c3484
  __gmp_expr() { mpz_init(mp); }
Packit 5c3484
Packit 5c3484
  __gmp_expr(const __gmp_expr &z) { mpz_init_set(mp, z.mp); }
Packit 5c3484
#if __GMPXX_USE_CXX11
Packit 5c3484
  __gmp_expr(__gmp_expr &&z)
Packit 5c3484
  { *mp = *z.mp; mpz_init(z.mp); }
Packit 5c3484
#endif
Packit 5c3484
  template <class T>
Packit 5c3484
  __gmp_expr(const __gmp_expr<mpz_t, T> &expr)
Packit 5c3484
  { mpz_init(mp); __gmp_set_expr(mp, expr); }
Packit 5c3484
  template <class T, class U>
Packit 5c3484
  explicit __gmp_expr(const __gmp_expr<T, U> &expr)
Packit 5c3484
  { mpz_init(mp); __gmp_set_expr(mp, expr); }
Packit 5c3484
Packit 5c3484
  __GMPXX_DEFINE_ARITHMETIC_CONSTRUCTORS
Packit 5c3484
Packit 5c3484
  explicit __gmp_expr(const char *s, int base = 0)
Packit 5c3484
  {
Packit 5c3484
    if (mpz_init_set_str (mp, s, base) != 0)
Packit 5c3484
      {
Packit 5c3484
        mpz_clear (mp);
Packit 5c3484
        throw std::invalid_argument ("mpz_set_str");
Packit 5c3484
      }
Packit 5c3484
  }
Packit 5c3484
  explicit __gmp_expr(const std::string &s, int base = 0)
Packit 5c3484
  {
Packit 5c3484
    if (mpz_init_set_str(mp, s.c_str(), base) != 0)
Packit 5c3484
      {
Packit 5c3484
        mpz_clear (mp);
Packit 5c3484
        throw std::invalid_argument ("mpz_set_str");
Packit 5c3484
      }
Packit 5c3484
  }
Packit 5c3484
Packit 5c3484
  explicit __gmp_expr(mpz_srcptr z) { mpz_init_set(mp, z); }
Packit 5c3484
Packit 5c3484
  ~__gmp_expr() { mpz_clear(mp); }
Packit 5c3484
Packit 5c3484
  void swap(__gmp_expr& z) __GMPXX_NOEXCEPT { std::swap(*mp, *z.mp); }
Packit 5c3484
Packit 5c3484
  // assignment operators
Packit 5c3484
  __gmp_expr & operator=(const __gmp_expr &z)
Packit 5c3484
  { mpz_set(mp, z.mp); return *this; }
Packit 5c3484
#if __GMPXX_USE_CXX11
Packit 5c3484
  __gmp_expr & operator=(__gmp_expr &&z) noexcept
Packit 5c3484
  { swap(z); return *this; }
Packit 5c3484
#endif
Packit 5c3484
  template <class T, class U>
Packit 5c3484
  __gmp_expr<value_type, value_type> & operator=(const __gmp_expr<T, U> &expr)
Packit 5c3484
  { __gmp_set_expr(mp, expr); return *this; }
Packit 5c3484
Packit 5c3484
  __GMPXX_DEFINE_ARITHMETIC_ASSIGNMENTS
Packit 5c3484
Packit 5c3484
  __gmp_expr & operator=(const char *s)
Packit 5c3484
  {
Packit 5c3484
    if (mpz_set_str (mp, s, 0) != 0)
Packit 5c3484
      throw std::invalid_argument ("mpz_set_str");
Packit 5c3484
    return *this;
Packit 5c3484
  }
Packit 5c3484
  __gmp_expr & operator=(const std::string &s)
Packit 5c3484
  {
Packit 5c3484
    if (mpz_set_str(mp, s.c_str(), 0) != 0)
Packit 5c3484
      throw std::invalid_argument ("mpz_set_str");
Packit 5c3484
    return *this;
Packit 5c3484
  }
Packit 5c3484
Packit 5c3484
  // string input/output functions
Packit 5c3484
  int set_str(const char *s, int base)
Packit 5c3484
  { return mpz_set_str(mp, s, base); }
Packit 5c3484
  int set_str(const std::string &s, int base)
Packit 5c3484
  { return mpz_set_str(mp, s.c_str(), base); }
Packit 5c3484
  std::string get_str(int base = 10) const
Packit 5c3484
  {
Packit 5c3484
    __gmp_alloc_cstring temp(mpz_get_str(0, base, mp));
Packit 5c3484
    return std::string(temp.str);
Packit 5c3484
  }
Packit 5c3484
Packit 5c3484
  // conversion functions
Packit 5c3484
  mpz_srcptr __get_mp() const { return mp; }
Packit 5c3484
  mpz_ptr __get_mp() { return mp; }
Packit 5c3484
  mpz_srcptr get_mpz_t() const { return mp; }
Packit 5c3484
  mpz_ptr get_mpz_t() { return mp; }
Packit 5c3484
Packit 5c3484
  signed long int get_si() const { return mpz_get_si(mp); }
Packit 5c3484
  unsigned long int get_ui() const { return mpz_get_ui(mp); }
Packit 5c3484
  double get_d() const { return mpz_get_d(mp); }
Packit 5c3484
Packit 5c3484
  // bool fits_schar_p() const { return mpz_fits_schar_p(mp); }
Packit 5c3484
  // bool fits_uchar_p() const { return mpz_fits_uchar_p(mp); }
Packit 5c3484
  bool fits_sint_p() const { return mpz_fits_sint_p(mp); }
Packit 5c3484
  bool fits_uint_p() const { return mpz_fits_uint_p(mp); }
Packit 5c3484
  bool fits_sshort_p() const { return mpz_fits_sshort_p(mp); }
Packit 5c3484
  bool fits_ushort_p() const { return mpz_fits_ushort_p(mp); }
Packit 5c3484
  bool fits_slong_p() const { return mpz_fits_slong_p(mp); }
Packit 5c3484
  bool fits_ulong_p() const { return mpz_fits_ulong_p(mp); }
Packit 5c3484
  // bool fits_float_p() const { return mpz_fits_float_p(mp); }
Packit 5c3484
  // bool fits_double_p() const { return mpz_fits_double_p(mp); }
Packit 5c3484
  // bool fits_ldouble_p() const { return mpz_fits_ldouble_p(mp); }
Packit 5c3484
Packit 5c3484
#if __GMPXX_USE_CXX11
Packit 5c3484
  explicit operator bool() const { return mp->_mp_size != 0; }
Packit 5c3484
#endif
Packit 5c3484
Packit 5c3484
  // member operators
Packit 5c3484
  __GMP_DECLARE_COMPOUND_OPERATOR(operator+=)
Packit 5c3484
  __GMP_DECLARE_COMPOUND_OPERATOR(operator-=)
Packit 5c3484
  __GMP_DECLARE_COMPOUND_OPERATOR(operator*=)
Packit 5c3484
  __GMP_DECLARE_COMPOUND_OPERATOR(operator/=)
Packit 5c3484
  __GMP_DECLARE_COMPOUND_OPERATOR(operator%=)
Packit 5c3484
Packit 5c3484
  __GMP_DECLARE_COMPOUND_OPERATOR(operator&=)
Packit 5c3484
  __GMP_DECLARE_COMPOUND_OPERATOR(operator|=)
Packit 5c3484
  __GMP_DECLARE_COMPOUND_OPERATOR(operator^=)
Packit 5c3484
Packit 5c3484
  __GMP_DECLARE_COMPOUND_OPERATOR_UI(operator<<=)
Packit 5c3484
  __GMP_DECLARE_COMPOUND_OPERATOR_UI(operator>>=)
Packit 5c3484
Packit 5c3484
  __GMP_DECLARE_INCREMENT_OPERATOR(operator++)
Packit 5c3484
  __GMP_DECLARE_INCREMENT_OPERATOR(operator--)
Packit 5c3484
};
Packit 5c3484
Packit 5c3484
typedef __gmp_expr<mpz_t, mpz_t> mpz_class;
Packit 5c3484
Packit 5c3484
Packit 5c3484
/**************** mpq_class -- wrapper for mpq_t ****************/
Packit 5c3484
Packit 5c3484
template <>
Packit 5c3484
class __gmp_expr<mpq_t, mpq_t>
Packit 5c3484
{
Packit 5c3484
private:
Packit 5c3484
  typedef mpq_t value_type;
Packit 5c3484
  value_type mp;
Packit 5c3484
Packit 5c3484
  // Helper functions used for all arithmetic types
Packit 5c3484
  void assign_ui(unsigned long l) { mpq_set_ui(mp, l, 1); }
Packit 5c3484
  void assign_si(signed long l)
Packit 5c3484
  {
Packit 5c3484
    if (__GMPXX_CONSTANT_TRUE(l >= 0))
Packit 5c3484
      assign_ui(l);
Packit 5c3484
    else
Packit 5c3484
      mpq_set_si(mp, l, 1);
Packit 5c3484
  }
Packit 5c3484
  void assign_d (double d)        { mpq_set_d (mp, d); }
Packit 5c3484
Packit 5c3484
  void init_ui(unsigned long l)	{ mpq_init(mp); get_num() = l; }
Packit 5c3484
  void init_si(signed long l)	{ mpq_init(mp); get_num() = l; }
Packit 5c3484
  void init_d (double d)	{ mpq_init(mp); assign_d (d); }
Packit 5c3484
Packit 5c3484
public:
Packit 5c3484
  mp_bitcnt_t get_prec() const { return mpf_get_default_prec(); }
Packit 5c3484
  void canonicalize() { mpq_canonicalize(mp); }
Packit 5c3484
Packit 5c3484
  // constructors and destructor
Packit 5c3484
  __gmp_expr() { mpq_init(mp); }
Packit 5c3484
Packit 5c3484
  __gmp_expr(const __gmp_expr &q)
Packit 5c3484
  {
Packit 5c3484
    mpz_init_set(mpq_numref(mp), mpq_numref(q.mp));
Packit 5c3484
    mpz_init_set(mpq_denref(mp), mpq_denref(q.mp));
Packit 5c3484
  }
Packit 5c3484
#if __GMPXX_USE_CXX11
Packit 5c3484
  __gmp_expr(__gmp_expr &&q)
Packit 5c3484
  { *mp = *q.mp; mpq_init(q.mp); }
Packit 5c3484
#endif
Packit 5c3484
  template <class T>
Packit 5c3484
  __gmp_expr(const __gmp_expr<mpz_t, T> &expr)
Packit 5c3484
  { mpq_init(mp); __gmp_set_expr(mp, expr); }
Packit 5c3484
  template <class T>
Packit 5c3484
  __gmp_expr(const __gmp_expr<mpq_t, T> &expr)
Packit 5c3484
  { mpq_init(mp); __gmp_set_expr(mp, expr); }
Packit 5c3484
  template <class T, class U>
Packit 5c3484
  explicit __gmp_expr(const __gmp_expr<T, U> &expr)
Packit 5c3484
  { mpq_init(mp); __gmp_set_expr(mp, expr); }
Packit 5c3484
Packit 5c3484
  __GMPXX_DEFINE_ARITHMETIC_CONSTRUCTORS
Packit 5c3484
Packit 5c3484
  explicit __gmp_expr(const char *s, int base = 0)
Packit 5c3484
  {
Packit 5c3484
    mpq_init (mp);
Packit 5c3484
    // If s is the literal 0, we meant to call another constructor.
Packit 5c3484
    // If s just happens to evaluate to 0, we would crash, so whatever.
Packit 5c3484
    if (s == 0)
Packit 5c3484
      {
Packit 5c3484
	// Don't turn mpq_class(0,0) into 0
Packit 5c3484
	mpz_set_si(mpq_denref(mp), base);
Packit 5c3484
      }
Packit 5c3484
    else if (mpq_set_str(mp, s, base) != 0)
Packit 5c3484
      {
Packit 5c3484
        mpq_clear (mp);
Packit 5c3484
        throw std::invalid_argument ("mpq_set_str");
Packit 5c3484
      }
Packit 5c3484
  }
Packit 5c3484
  explicit __gmp_expr(const std::string &s, int base = 0)
Packit 5c3484
  {
Packit 5c3484
    mpq_init(mp);
Packit 5c3484
    if (mpq_set_str (mp, s.c_str(), base) != 0)
Packit 5c3484
      {
Packit 5c3484
        mpq_clear (mp);
Packit 5c3484
        throw std::invalid_argument ("mpq_set_str");
Packit 5c3484
      }
Packit 5c3484
  }
Packit 5c3484
  explicit __gmp_expr(mpq_srcptr q)
Packit 5c3484
  {
Packit 5c3484
    mpz_init_set(mpq_numref(mp), mpq_numref(q));
Packit 5c3484
    mpz_init_set(mpq_denref(mp), mpq_denref(q));
Packit 5c3484
  }
Packit 5c3484
Packit 5c3484
  __gmp_expr(const mpz_class &num, const mpz_class &den)
Packit 5c3484
  {
Packit 5c3484
    mpz_init_set(mpq_numref(mp), num.get_mpz_t());
Packit 5c3484
    mpz_init_set(mpq_denref(mp), den.get_mpz_t());
Packit 5c3484
  }
Packit 5c3484
Packit 5c3484
  ~__gmp_expr() { mpq_clear(mp); }
Packit 5c3484
Packit 5c3484
  void swap(__gmp_expr& q) __GMPXX_NOEXCEPT { std::swap(*mp, *q.mp); }
Packit 5c3484
Packit 5c3484
  // assignment operators
Packit 5c3484
  __gmp_expr & operator=(const __gmp_expr &q)
Packit 5c3484
  { mpq_set(mp, q.mp); return *this; }
Packit 5c3484
#if __GMPXX_USE_CXX11
Packit 5c3484
  __gmp_expr & operator=(__gmp_expr &&q) noexcept
Packit 5c3484
  { swap(q); return *this; }
Packit 5c3484
  __gmp_expr & operator=(mpz_class &&z) noexcept
Packit 5c3484
  { get_num() = std::move(z); get_den() = 1u; return *this; }
Packit 5c3484
#endif
Packit 5c3484
  template <class T, class U>
Packit 5c3484
  __gmp_expr<value_type, value_type> & operator=(const __gmp_expr<T, U> &expr)
Packit 5c3484
  { __gmp_set_expr(mp, expr); return *this; }
Packit 5c3484
Packit 5c3484
  __GMPXX_DEFINE_ARITHMETIC_ASSIGNMENTS
Packit 5c3484
Packit 5c3484
  __gmp_expr & operator=(const char *s)
Packit 5c3484
  {
Packit 5c3484
    if (mpq_set_str (mp, s, 0) != 0)
Packit 5c3484
      throw std::invalid_argument ("mpq_set_str");
Packit 5c3484
    return *this;
Packit 5c3484
  }
Packit 5c3484
  __gmp_expr & operator=(const std::string &s)
Packit 5c3484
  {
Packit 5c3484
    if (mpq_set_str(mp, s.c_str(), 0) != 0)
Packit 5c3484
      throw std::invalid_argument ("mpq_set_str");
Packit 5c3484
    return *this;
Packit 5c3484
  }
Packit 5c3484
Packit 5c3484
  // string input/output functions
Packit 5c3484
  int set_str(const char *s, int base)
Packit 5c3484
  { return mpq_set_str(mp, s, base); }
Packit 5c3484
  int set_str(const std::string &s, int base)
Packit 5c3484
  { return mpq_set_str(mp, s.c_str(), base); }
Packit 5c3484
  std::string get_str(int base = 10) const
Packit 5c3484
  {
Packit 5c3484
    __gmp_alloc_cstring temp(mpq_get_str(0, base, mp));
Packit 5c3484
    return std::string(temp.str);
Packit 5c3484
  }
Packit 5c3484
Packit 5c3484
  // conversion functions
Packit 5c3484
Packit 5c3484
  // casting a reference to an mpz_t to mpz_class & is a dirty hack,
Packit 5c3484
  // but works because the internal representation of mpz_class is
Packit 5c3484
  // exactly an mpz_t
Packit 5c3484
  const mpz_class & get_num() const
Packit 5c3484
  { return reinterpret_cast<const mpz_class &>(*mpq_numref(mp)); }
Packit 5c3484
  mpz_class & get_num()
Packit 5c3484
  { return reinterpret_cast<mpz_class &>(*mpq_numref(mp)); }
Packit 5c3484
  const mpz_class & get_den() const
Packit 5c3484
  { return reinterpret_cast<const mpz_class &>(*mpq_denref(mp)); }
Packit 5c3484
  mpz_class & get_den()
Packit 5c3484
  { return reinterpret_cast<mpz_class &>(*mpq_denref(mp)); }
Packit 5c3484
Packit 5c3484
  mpq_srcptr __get_mp() const { return mp; }
Packit 5c3484
  mpq_ptr __get_mp() { return mp; }
Packit 5c3484
  mpq_srcptr get_mpq_t() const { return mp; }
Packit 5c3484
  mpq_ptr get_mpq_t() { return mp; }
Packit 5c3484
Packit 5c3484
  mpz_srcptr get_num_mpz_t() const { return mpq_numref(mp); }
Packit 5c3484
  mpz_ptr get_num_mpz_t() { return mpq_numref(mp); }
Packit 5c3484
  mpz_srcptr get_den_mpz_t() const { return mpq_denref(mp); }
Packit 5c3484
  mpz_ptr get_den_mpz_t() { return mpq_denref(mp); }
Packit 5c3484
Packit 5c3484
  double get_d() const { return mpq_get_d(mp); }
Packit 5c3484
Packit 5c3484
#if __GMPXX_USE_CXX11
Packit 5c3484
  explicit operator bool() const { return mpq_numref(mp)->_mp_size != 0; }
Packit 5c3484
#endif
Packit 5c3484
Packit 5c3484
  // compound assignments
Packit 5c3484
  __GMP_DECLARE_COMPOUND_OPERATOR(operator+=)
Packit 5c3484
  __GMP_DECLARE_COMPOUND_OPERATOR(operator-=)
Packit 5c3484
  __GMP_DECLARE_COMPOUND_OPERATOR(operator*=)
Packit 5c3484
  __GMP_DECLARE_COMPOUND_OPERATOR(operator/=)
Packit 5c3484
Packit 5c3484
  __GMP_DECLARE_COMPOUND_OPERATOR_UI(operator<<=)
Packit 5c3484
  __GMP_DECLARE_COMPOUND_OPERATOR_UI(operator>>=)
Packit 5c3484
Packit 5c3484
  __GMP_DECLARE_INCREMENT_OPERATOR(operator++)
Packit 5c3484
  __GMP_DECLARE_INCREMENT_OPERATOR(operator--)
Packit 5c3484
};
Packit 5c3484
Packit 5c3484
typedef __gmp_expr<mpq_t, mpq_t> mpq_class;
Packit 5c3484
Packit 5c3484
Packit 5c3484
/**************** mpf_class -- wrapper for mpf_t ****************/
Packit 5c3484
Packit 5c3484
template <>
Packit 5c3484
class __gmp_expr<mpf_t, mpf_t>
Packit 5c3484
{
Packit 5c3484
private:
Packit 5c3484
  typedef mpf_t value_type;
Packit 5c3484
  value_type mp;
Packit 5c3484
Packit 5c3484
  // Helper functions used for all arithmetic types
Packit 5c3484
  void assign_ui(unsigned long l) { mpf_set_ui(mp, l); }
Packit 5c3484
  void assign_si(signed long l)
Packit 5c3484
  {
Packit 5c3484
    if (__GMPXX_CONSTANT_TRUE(l >= 0))
Packit 5c3484
      assign_ui(l);
Packit 5c3484
    else
Packit 5c3484
      mpf_set_si(mp, l);
Packit 5c3484
  }
Packit 5c3484
  void assign_d (double d)        { mpf_set_d (mp, d); }
Packit 5c3484
Packit 5c3484
  void init_ui(unsigned long l)
Packit 5c3484
  {
Packit 5c3484
    if (__GMPXX_CONSTANT_TRUE(l == 0))
Packit 5c3484
      mpf_init(mp);
Packit 5c3484
    else
Packit 5c3484
      mpf_init_set_ui(mp, l);
Packit 5c3484
  }
Packit 5c3484
  void init_si(signed long l)
Packit 5c3484
  {
Packit 5c3484
    if (__GMPXX_CONSTANT_TRUE(l >= 0))
Packit 5c3484
      init_ui(l);
Packit 5c3484
    else
Packit 5c3484
      mpf_init_set_si(mp, l);
Packit 5c3484
  }
Packit 5c3484
  void init_d (double d)	{ mpf_init_set_d (mp, d); }
Packit 5c3484
Packit 5c3484
public:
Packit 5c3484
  mp_bitcnt_t get_prec() const { return mpf_get_prec(mp); }
Packit 5c3484
Packit 5c3484
  void set_prec(mp_bitcnt_t prec) { mpf_set_prec(mp, prec); }
Packit 5c3484
  void set_prec_raw(mp_bitcnt_t prec) { mpf_set_prec_raw(mp, prec); }
Packit 5c3484
Packit 5c3484
  // constructors and destructor
Packit 5c3484
  __gmp_expr() { mpf_init(mp); }
Packit 5c3484
Packit 5c3484
  __gmp_expr(const __gmp_expr &f)
Packit 5c3484
  { mpf_init2(mp, f.get_prec()); mpf_set(mp, f.mp); }
Packit 5c3484
#if __GMPXX_USE_CXX11
Packit 5c3484
  __gmp_expr(__gmp_expr &&f)
Packit 5c3484
  { *mp = *f.mp; mpf_init2(f.mp, get_prec()); }
Packit 5c3484
#endif
Packit 5c3484
  __gmp_expr(const __gmp_expr &f, mp_bitcnt_t prec)
Packit 5c3484
  { mpf_init2(mp, prec); mpf_set(mp, f.mp); }
Packit 5c3484
  template <class T, class U>
Packit 5c3484
  __gmp_expr(const __gmp_expr<T, U> &expr)
Packit 5c3484
  { mpf_init2(mp, expr.get_prec()); __gmp_set_expr(mp, expr); }
Packit 5c3484
  template <class T, class U>
Packit 5c3484
  __gmp_expr(const __gmp_expr<T, U> &expr, mp_bitcnt_t prec)
Packit 5c3484
  { mpf_init2(mp, prec); __gmp_set_expr(mp, expr); }
Packit 5c3484
Packit 5c3484
  __GMPXX_DEFINE_ARITHMETIC_CONSTRUCTORS
Packit 5c3484
Packit 5c3484
  __gmp_expr(signed char c, mp_bitcnt_t prec)
Packit 5c3484
  { mpf_init2(mp, prec); mpf_set_si(mp, c); }
Packit 5c3484
  __gmp_expr(unsigned char c, mp_bitcnt_t prec)
Packit 5c3484
  { mpf_init2(mp, prec); mpf_set_ui(mp, c); }
Packit 5c3484
Packit 5c3484
  __gmp_expr(signed int i, mp_bitcnt_t prec)
Packit 5c3484
  { mpf_init2(mp, prec); mpf_set_si(mp, i); }
Packit 5c3484
  __gmp_expr(unsigned int i, mp_bitcnt_t prec)
Packit 5c3484
  { mpf_init2(mp, prec); mpf_set_ui(mp, i); }
Packit 5c3484
Packit 5c3484
  __gmp_expr(signed short int s, mp_bitcnt_t prec)
Packit 5c3484
  { mpf_init2(mp, prec); mpf_set_si(mp, s); }
Packit 5c3484
  __gmp_expr(unsigned short int s, mp_bitcnt_t prec)
Packit 5c3484
  { mpf_init2(mp, prec); mpf_set_ui(mp, s); }
Packit 5c3484
Packit 5c3484
  __gmp_expr(signed long int l, mp_bitcnt_t prec)
Packit 5c3484
  { mpf_init2(mp, prec); mpf_set_si(mp, l); }
Packit 5c3484
  __gmp_expr(unsigned long int l, mp_bitcnt_t prec)
Packit 5c3484
  { mpf_init2(mp, prec); mpf_set_ui(mp, l); }
Packit 5c3484
Packit 5c3484
  __gmp_expr(float f, mp_bitcnt_t prec)
Packit 5c3484
  { mpf_init2(mp, prec); mpf_set_d(mp, f); }
Packit 5c3484
  __gmp_expr(double d, mp_bitcnt_t prec)
Packit 5c3484
  { mpf_init2(mp, prec); mpf_set_d(mp, d); }
Packit 5c3484
  // __gmp_expr(long double ld) { mpf_init_set_d(mp, ld); }
Packit 5c3484
  // __gmp_expr(long double ld, mp_bitcnt_t prec)
Packit 5c3484
  // { mpf_init2(mp, prec); mpf_set_d(mp, ld); }
Packit 5c3484
Packit 5c3484
  explicit __gmp_expr(const char *s)
Packit 5c3484
  {
Packit 5c3484
    if (mpf_init_set_str (mp, s, 0) != 0)
Packit 5c3484
      {
Packit 5c3484
        mpf_clear (mp);
Packit 5c3484
        throw std::invalid_argument ("mpf_set_str");
Packit 5c3484
      }
Packit 5c3484
  }
Packit 5c3484
  __gmp_expr(const char *s, mp_bitcnt_t prec, int base = 0)
Packit 5c3484
  {
Packit 5c3484
    mpf_init2(mp, prec);
Packit 5c3484
    if (mpf_set_str(mp, s, base) != 0)
Packit 5c3484
      {
Packit 5c3484
        mpf_clear (mp);
Packit 5c3484
        throw std::invalid_argument ("mpf_set_str");
Packit 5c3484
      }
Packit 5c3484
  }
Packit 5c3484
  explicit __gmp_expr(const std::string &s)
Packit 5c3484
  {
Packit 5c3484
    if (mpf_init_set_str(mp, s.c_str(), 0) != 0)
Packit 5c3484
      {
Packit 5c3484
        mpf_clear (mp);
Packit 5c3484
        throw std::invalid_argument ("mpf_set_str");
Packit 5c3484
      }
Packit 5c3484
  }
Packit 5c3484
  __gmp_expr(const std::string &s, mp_bitcnt_t prec, int base = 0)
Packit 5c3484
  {
Packit 5c3484
    mpf_init2(mp, prec);
Packit 5c3484
    if (mpf_set_str(mp, s.c_str(), base) != 0)
Packit 5c3484
      {
Packit 5c3484
        mpf_clear (mp);
Packit 5c3484
        throw std::invalid_argument ("mpf_set_str");
Packit 5c3484
      }
Packit 5c3484
  }
Packit 5c3484
Packit 5c3484
  explicit __gmp_expr(mpf_srcptr f)
Packit 5c3484
  { mpf_init2(mp, mpf_get_prec(f)); mpf_set(mp, f); }
Packit 5c3484
  __gmp_expr(mpf_srcptr f, mp_bitcnt_t prec)
Packit 5c3484
  { mpf_init2(mp, prec); mpf_set(mp, f); }
Packit 5c3484
Packit 5c3484
  ~__gmp_expr() { mpf_clear(mp); }
Packit 5c3484
Packit 5c3484
  void swap(__gmp_expr& f) __GMPXX_NOEXCEPT { std::swap(*mp, *f.mp); }
Packit 5c3484
Packit 5c3484
  // assignment operators
Packit 5c3484
  __gmp_expr & operator=(const __gmp_expr &f)
Packit 5c3484
  { mpf_set(mp, f.mp); return *this; }
Packit 5c3484
#if __GMPXX_USE_CXX11
Packit 5c3484
  __gmp_expr & operator=(__gmp_expr &&f) noexcept
Packit 5c3484
  { swap(f); return *this; }
Packit 5c3484
#endif
Packit 5c3484
  template <class T, class U>
Packit 5c3484
  __gmp_expr<value_type, value_type> & operator=(const __gmp_expr<T, U> &expr)
Packit 5c3484
  { __gmp_set_expr(mp, expr); return *this; }
Packit 5c3484
Packit 5c3484
  __GMPXX_DEFINE_ARITHMETIC_ASSIGNMENTS
Packit 5c3484
Packit 5c3484
  __gmp_expr & operator=(const char *s)
Packit 5c3484
  {
Packit 5c3484
    if (mpf_set_str (mp, s, 0) != 0)
Packit 5c3484
      throw std::invalid_argument ("mpf_set_str");
Packit 5c3484
    return *this;
Packit 5c3484
  }
Packit 5c3484
  __gmp_expr & operator=(const std::string &s)
Packit 5c3484
  {
Packit 5c3484
    if (mpf_set_str(mp, s.c_str(), 0) != 0)
Packit 5c3484
      throw std::invalid_argument ("mpf_set_str");
Packit 5c3484
    return *this;
Packit 5c3484
  }
Packit 5c3484
Packit 5c3484
  // string input/output functions
Packit 5c3484
  int set_str(const char *s, int base)
Packit 5c3484
  { return mpf_set_str(mp, s, base); }
Packit 5c3484
  int set_str(const std::string &s, int base)
Packit 5c3484
  { return mpf_set_str(mp, s.c_str(), base); }
Packit 5c3484
  std::string get_str(mp_exp_t &expo, int base = 10, size_t size = 0) const
Packit 5c3484
  {
Packit 5c3484
    __gmp_alloc_cstring temp(mpf_get_str(0, &expo, base, size, mp));
Packit 5c3484
    return std::string(temp.str);
Packit 5c3484
  }
Packit 5c3484
Packit 5c3484
  // conversion functions
Packit 5c3484
  mpf_srcptr __get_mp() const { return mp; }
Packit 5c3484
  mpf_ptr __get_mp() { return mp; }
Packit 5c3484
  mpf_srcptr get_mpf_t() const { return mp; }
Packit 5c3484
  mpf_ptr get_mpf_t() { return mp; }
Packit 5c3484
Packit 5c3484
  signed long int get_si() const { return mpf_get_si(mp); }
Packit 5c3484
  unsigned long int get_ui() const { return mpf_get_ui(mp); }
Packit 5c3484
  double get_d() const { return mpf_get_d(mp); }
Packit 5c3484
Packit 5c3484
  // bool fits_schar_p() const { return mpf_fits_schar_p(mp); }
Packit 5c3484
  // bool fits_uchar_p() const { return mpf_fits_uchar_p(mp); }
Packit 5c3484
  bool fits_sint_p() const { return mpf_fits_sint_p(mp); }
Packit 5c3484
  bool fits_uint_p() const { return mpf_fits_uint_p(mp); }
Packit 5c3484
  bool fits_sshort_p() const { return mpf_fits_sshort_p(mp); }
Packit 5c3484
  bool fits_ushort_p() const { return mpf_fits_ushort_p(mp); }
Packit 5c3484
  bool fits_slong_p() const { return mpf_fits_slong_p(mp); }
Packit 5c3484
  bool fits_ulong_p() const { return mpf_fits_ulong_p(mp); }
Packit 5c3484
  // bool fits_float_p() const { return mpf_fits_float_p(mp); }
Packit 5c3484
  // bool fits_double_p() const { return mpf_fits_double_p(mp); }
Packit 5c3484
  // bool fits_ldouble_p() const { return mpf_fits_ldouble_p(mp); }
Packit 5c3484
Packit 5c3484
#if __GMPXX_USE_CXX11
Packit 5c3484
  explicit operator bool() const { return mp->_mp_size != 0; }
Packit 5c3484
#endif
Packit 5c3484
Packit 5c3484
  // compound assignments
Packit 5c3484
  __GMP_DECLARE_COMPOUND_OPERATOR(operator+=)
Packit 5c3484
  __GMP_DECLARE_COMPOUND_OPERATOR(operator-=)
Packit 5c3484
  __GMP_DECLARE_COMPOUND_OPERATOR(operator*=)
Packit 5c3484
  __GMP_DECLARE_COMPOUND_OPERATOR(operator/=)
Packit 5c3484
Packit 5c3484
  __GMP_DECLARE_COMPOUND_OPERATOR_UI(operator<<=)
Packit 5c3484
  __GMP_DECLARE_COMPOUND_OPERATOR_UI(operator>>=)
Packit 5c3484
Packit 5c3484
  __GMP_DECLARE_INCREMENT_OPERATOR(operator++)
Packit 5c3484
  __GMP_DECLARE_INCREMENT_OPERATOR(operator--)
Packit 5c3484
};
Packit 5c3484
Packit 5c3484
typedef __gmp_expr<mpf_t, mpf_t> mpf_class;
Packit 5c3484
Packit 5c3484
Packit 5c3484
Packit 5c3484
/**************** User-defined literals ****************/
Packit 5c3484
Packit 5c3484
#if __GMPXX_USE_CXX11
Packit 5c3484
inline mpz_class operator"" _mpz(const char* s)
Packit 5c3484
{
Packit 5c3484
  return mpz_class(s);
Packit 5c3484
}
Packit 5c3484
Packit 5c3484
inline mpq_class operator"" _mpq(const char* s)
Packit 5c3484
{
Packit 5c3484
  mpq_class q;
Packit 5c3484
  q.get_num() = s;
Packit 5c3484
  return q;
Packit 5c3484
}
Packit 5c3484
Packit 5c3484
inline mpf_class operator"" _mpf(const char* s)
Packit 5c3484
{
Packit 5c3484
  return mpf_class(s);
Packit 5c3484
}
Packit 5c3484
#endif
Packit 5c3484
Packit 5c3484
/**************** I/O operators ****************/
Packit 5c3484
Packit 5c3484
// these should (and will) be provided separately
Packit 5c3484
Packit 5c3484
template <class T, class U>
Packit 5c3484
inline std::ostream & operator<<
Packit 5c3484
(std::ostream &o, const __gmp_expr<T, U> &expr)
Packit 5c3484
{
Packit 5c3484
  __gmp_expr<T, T> const& temp(expr);
Packit 5c3484
  return o << temp.__get_mp();
Packit 5c3484
}
Packit 5c3484
Packit 5c3484
template <class T>
Packit 5c3484
inline std::istream & operator>>(std::istream &i, __gmp_expr<T, T> &expr)
Packit 5c3484
{
Packit 5c3484
  return i >> expr.__get_mp();
Packit 5c3484
}
Packit 5c3484
Packit 5c3484
/*
Packit 5c3484
// you might want to uncomment this
Packit 5c3484
inline std::istream & operator>>(std::istream &i, mpq_class &q)
Packit 5c3484
{
Packit 5c3484
  i >> q.get_mpq_t();
Packit 5c3484
  q.canonicalize();
Packit 5c3484
  return i;
Packit 5c3484
}
Packit 5c3484
*/
Packit 5c3484
Packit 5c3484
Packit 5c3484
/**************** Functions for type conversion ****************/
Packit 5c3484
Packit 5c3484
inline void __gmp_set_expr(mpz_ptr z, const mpz_class &w)
Packit 5c3484
{
Packit 5c3484
  mpz_set(z, w.get_mpz_t());
Packit 5c3484
}
Packit 5c3484
Packit 5c3484
template <class T>
Packit 5c3484
inline void __gmp_set_expr(mpz_ptr z, const __gmp_expr<mpz_t, T> &expr)
Packit 5c3484
{
Packit 5c3484
  expr.eval(z);
Packit 5c3484
}
Packit 5c3484
Packit 5c3484
template <class T>
Packit 5c3484
inline void __gmp_set_expr(mpz_ptr z, const __gmp_expr<mpq_t, T> &expr)
Packit 5c3484
{
Packit 5c3484
  mpq_class const& temp(expr);
Packit 5c3484
  mpz_set_q(z, temp.get_mpq_t());
Packit 5c3484
}
Packit 5c3484
Packit 5c3484
template <class T>
Packit 5c3484
inline void __gmp_set_expr(mpz_ptr z, const __gmp_expr<mpf_t, T> &expr)
Packit 5c3484
{
Packit 5c3484
  mpf_class const& temp(expr);
Packit 5c3484
  mpz_set_f(z, temp.get_mpf_t());
Packit 5c3484
}
Packit 5c3484
Packit 5c3484
inline void __gmp_set_expr(mpq_ptr q, const mpz_class &z)
Packit 5c3484
{
Packit 5c3484
  mpq_set_z(q, z.get_mpz_t());
Packit 5c3484
}
Packit 5c3484
Packit 5c3484
template <class T>
Packit 5c3484
inline void __gmp_set_expr(mpq_ptr q, const __gmp_expr<mpz_t, T> &expr)
Packit 5c3484
{
Packit 5c3484
  __gmp_set_expr(mpq_numref(q), expr);
Packit 5c3484
  mpz_set_ui(mpq_denref(q), 1);
Packit 5c3484
}
Packit 5c3484
Packit 5c3484
inline void __gmp_set_expr(mpq_ptr q, const mpq_class &r)
Packit 5c3484
{
Packit 5c3484
  mpq_set(q, r.get_mpq_t());
Packit 5c3484
}
Packit 5c3484
Packit 5c3484
template <class T>
Packit 5c3484
inline void __gmp_set_expr(mpq_ptr q, const __gmp_expr<mpq_t, T> &expr)
Packit 5c3484
{
Packit 5c3484
  expr.eval(q);
Packit 5c3484
}
Packit 5c3484
Packit 5c3484
template <class T>
Packit 5c3484
inline void __gmp_set_expr(mpq_ptr q, const __gmp_expr<mpf_t, T> &expr)
Packit 5c3484
{
Packit 5c3484
  mpf_class const& temp(expr);
Packit 5c3484
  mpq_set_f(q, temp.get_mpf_t());
Packit 5c3484
}
Packit 5c3484
Packit 5c3484
template <class T>
Packit 5c3484
inline void __gmp_set_expr(mpf_ptr f, const __gmp_expr<mpz_t, T> &expr)
Packit 5c3484
{
Packit 5c3484
  mpz_class const& temp(expr);
Packit 5c3484
  mpf_set_z(f, temp.get_mpz_t());
Packit 5c3484
}
Packit 5c3484
Packit 5c3484
template <class T>
Packit 5c3484
inline void __gmp_set_expr(mpf_ptr f, const __gmp_expr<mpq_t, T> &expr)
Packit 5c3484
{
Packit 5c3484
  mpq_class const& temp(expr);
Packit 5c3484
  mpf_set_q(f, temp.get_mpq_t());
Packit 5c3484
}
Packit 5c3484
Packit 5c3484
inline void __gmp_set_expr(mpf_ptr f, const mpf_class &g)
Packit 5c3484
{
Packit 5c3484
  mpf_set(f, g.get_mpf_t());
Packit 5c3484
}
Packit 5c3484
Packit 5c3484
template <class T>
Packit 5c3484
inline void __gmp_set_expr(mpf_ptr f, const __gmp_expr<mpf_t, T> &expr)
Packit 5c3484
{
Packit 5c3484
  expr.eval(f);
Packit 5c3484
}
Packit 5c3484
Packit 5c3484
Packit 5c3484
/* Temporary objects */
Packit 5c3484
Packit 5c3484
template <class T>
Packit 5c3484
class __gmp_temp
Packit 5c3484
{
Packit 5c3484
  __gmp_expr<T, T> val;
Packit 5c3484
  public:
Packit 5c3484
  template<class U, class V>
Packit 5c3484
  __gmp_temp(U const& u, V) : val (u) {}
Packit 5c3484
  typename __gmp_resolve_expr<T>::srcptr_type
Packit 5c3484
  __get_mp() const { return val.__get_mp(); }
Packit 5c3484
};
Packit 5c3484
Packit 5c3484
template <>
Packit 5c3484
class __gmp_temp <mpf_t>
Packit 5c3484
{
Packit 5c3484
  mpf_class val;
Packit 5c3484
  public:
Packit 5c3484
  template<class U>
Packit 5c3484
  __gmp_temp(U const& u, mpf_ptr res) : val (u, mpf_get_prec(res)) {}
Packit 5c3484
  mpf_srcptr __get_mp() const { return val.__get_mp(); }
Packit 5c3484
};
Packit 5c3484
Packit 5c3484
/**************** Specializations of __gmp_expr ****************/
Packit 5c3484
/* The eval() method of __gmp_expr<T, U> evaluates the corresponding
Packit 5c3484
   expression and assigns the result to its argument, which is either an
Packit 5c3484
   mpz_t, mpq_t, or mpf_t as specified by the T argument.
Packit 5c3484
   Compound expressions are evaluated recursively (temporaries are created
Packit 5c3484
   to hold intermediate values), while for simple expressions the eval()
Packit 5c3484
   method of the appropriate function object (available as the Op argument
Packit 5c3484
   of either __gmp_unary_expr<T, Op> or __gmp_binary_expr<T, U, Op>) is
Packit 5c3484
   called. */
Packit 5c3484
Packit 5c3484
Packit 5c3484
/**************** Unary expressions ****************/
Packit 5c3484
/* cases:
Packit 5c3484
   - simple:   argument is mp*_class, that is, __gmp_expr<T, T>
Packit 5c3484
   - compound: argument is __gmp_expr<T, U> (with U not equal to T) */
Packit 5c3484
Packit 5c3484
Packit 5c3484
// simple expressions
Packit 5c3484
Packit 5c3484
template <class T, class Op>
Packit 5c3484
class __gmp_expr<T, __gmp_unary_expr<__gmp_expr<T, T>, Op> >
Packit 5c3484
{
Packit 5c3484
private:
Packit 5c3484
  typedef __gmp_expr<T, T> val_type;
Packit 5c3484
Packit 5c3484
  __gmp_unary_expr<val_type, Op> expr;
Packit 5c3484
public:
Packit 5c3484
  explicit __gmp_expr(const val_type &val) : expr(val) { }
Packit 5c3484
  void eval(typename __gmp_resolve_expr<T>::ptr_type p) const
Packit 5c3484
  { Op::eval(p, expr.val.__get_mp()); }
Packit 5c3484
  const val_type & get_val() const { return expr.val; }
Packit 5c3484
  mp_bitcnt_t get_prec() const { return expr.val.get_prec(); }
Packit 5c3484
};
Packit 5c3484
Packit 5c3484
Packit 5c3484
// simple expressions, U is a built-in numerical type
Packit 5c3484
Packit 5c3484
template <class T, class U, class Op>
Packit 5c3484
class __gmp_expr<T, __gmp_unary_expr<U, Op> >
Packit 5c3484
{
Packit 5c3484
private:
Packit 5c3484
  typedef U val_type;
Packit 5c3484
Packit 5c3484
  __gmp_unary_expr<val_type, Op> expr;
Packit 5c3484
public:
Packit 5c3484
  explicit __gmp_expr(const val_type &val) : expr(val) { }
Packit 5c3484
  void eval(typename __gmp_resolve_expr<T>::ptr_type p) const
Packit 5c3484
  { Op::eval(p, expr.val); }
Packit 5c3484
  const val_type & get_val() const { return expr.val; }
Packit 5c3484
  mp_bitcnt_t get_prec() const { return mpf_get_default_prec(); }
Packit 5c3484
};
Packit 5c3484
Packit 5c3484
Packit 5c3484
// compound expressions
Packit 5c3484
Packit 5c3484
template <class T, class U, class Op>
Packit 5c3484
class __gmp_expr<T, __gmp_unary_expr<__gmp_expr<T, U>, Op> >
Packit 5c3484
{
Packit 5c3484
private:
Packit 5c3484
  typedef __gmp_expr<T, U> val_type;
Packit 5c3484
Packit 5c3484
  __gmp_unary_expr<val_type, Op> expr;
Packit 5c3484
public:
Packit 5c3484
  explicit __gmp_expr(const val_type &val) : expr(val) { }
Packit 5c3484
  void eval(typename __gmp_resolve_expr<T>::ptr_type p) const
Packit 5c3484
  { expr.val.eval(p); Op::eval(p, p); }
Packit 5c3484
  const val_type & get_val() const { return expr.val; }
Packit 5c3484
  mp_bitcnt_t get_prec() const { return expr.val.get_prec(); }
Packit 5c3484
};
Packit 5c3484
Packit 5c3484
Packit 5c3484
/**************** Binary expressions ****************/
Packit 5c3484
/* simple:
Packit 5c3484
   - arguments are both mp*_class
Packit 5c3484
   - one argument is mp*_class, one is a built-in type
Packit 5c3484
   compound:
Packit 5c3484
   - one is mp*_class, one is __gmp_expr<T, U>
Packit 5c3484
   - one is __gmp_expr<T, U>, one is built-in
Packit 5c3484
   - both arguments are __gmp_expr<...> */
Packit 5c3484
Packit 5c3484
Packit 5c3484
// simple expressions
Packit 5c3484
Packit 5c3484
template <class T, class Op>
Packit 5c3484
class __gmp_expr
Packit 5c3484
<T, __gmp_binary_expr<__gmp_expr<T, T>, __gmp_expr<T, T>, Op> >
Packit 5c3484
{
Packit 5c3484
private:
Packit 5c3484
  typedef __gmp_expr<T, T> val1_type;
Packit 5c3484
  typedef __gmp_expr<T, T> val2_type;
Packit 5c3484
Packit 5c3484
  __gmp_binary_expr<val1_type, val2_type, Op> expr;
Packit 5c3484
public:
Packit 5c3484
  __gmp_expr(const val1_type &val1, const val2_type &val2)
Packit 5c3484
    : expr(val1, val2) { }
Packit 5c3484
  void eval(typename __gmp_resolve_expr<T>::ptr_type p) const
Packit 5c3484
  { Op::eval(p, expr.val1.__get_mp(), expr.val2.__get_mp()); }
Packit 5c3484
  const val1_type & get_val1() const { return expr.val1; }
Packit 5c3484
  const val2_type & get_val2() const { return expr.val2; }
Packit 5c3484
  mp_bitcnt_t get_prec() const
Packit 5c3484
  {
Packit 5c3484
    mp_bitcnt_t prec1 = expr.val1.get_prec(),
Packit 5c3484
      prec2 = expr.val2.get_prec();
Packit 5c3484
    return (prec1 > prec2) ? prec1 : prec2;
Packit 5c3484
  }
Packit 5c3484
};
Packit 5c3484
Packit 5c3484
Packit 5c3484
// simple expressions, U is a built-in numerical type
Packit 5c3484
Packit 5c3484
template <class T, class U, class Op>
Packit 5c3484
class __gmp_expr<T, __gmp_binary_expr<__gmp_expr<T, T>, U, Op> >
Packit 5c3484
{
Packit 5c3484
private:
Packit 5c3484
  typedef __gmp_expr<T, T> val1_type;
Packit 5c3484
  typedef U val2_type;
Packit 5c3484
Packit 5c3484
  __gmp_binary_expr<val1_type, val2_type, Op> expr;
Packit 5c3484
public:
Packit 5c3484
  __gmp_expr(const val1_type &val1, const val2_type &val2)
Packit 5c3484
    : expr(val1, val2) { }
Packit 5c3484
  void eval(typename __gmp_resolve_expr<T>::ptr_type p) const
Packit 5c3484
  { Op::eval(p, expr.val1.__get_mp(), expr.val2); }
Packit 5c3484
  const val1_type & get_val1() const { return expr.val1; }
Packit 5c3484
  const val2_type & get_val2() const { return expr.val2; }
Packit 5c3484
  mp_bitcnt_t get_prec() const { return expr.val1.get_prec(); }
Packit 5c3484
};
Packit 5c3484
Packit 5c3484
template <class T, class U, class Op>
Packit 5c3484
class __gmp_expr<T, __gmp_binary_expr<U, __gmp_expr<T, T>, Op> >
Packit 5c3484
{
Packit 5c3484
private:
Packit 5c3484
  typedef U val1_type;
Packit 5c3484
  typedef __gmp_expr<T, T> val2_type;
Packit 5c3484
Packit 5c3484
  __gmp_binary_expr<val1_type, val2_type, Op> expr;
Packit 5c3484
public:
Packit 5c3484
  __gmp_expr(const val1_type &val1, const val2_type &val2)
Packit 5c3484
    : expr(val1, val2) { }
Packit 5c3484
  void eval(typename __gmp_resolve_expr<T>::ptr_type p) const
Packit 5c3484
  { Op::eval(p, expr.val1, expr.val2.__get_mp()); }
Packit 5c3484
  const val1_type & get_val1() const { return expr.val1; }
Packit 5c3484
  const val2_type & get_val2() const { return expr.val2; }
Packit 5c3484
  mp_bitcnt_t get_prec() const { return expr.val2.get_prec(); }
Packit 5c3484
};
Packit 5c3484
Packit 5c3484
Packit 5c3484
// compound expressions, one argument is a subexpression
Packit 5c3484
Packit 5c3484
template <class T, class U, class V, class Op>
Packit 5c3484
class __gmp_expr
Packit 5c3484
<T, __gmp_binary_expr<__gmp_expr<T, T>, __gmp_expr<U, V>, Op> >
Packit 5c3484
{
Packit 5c3484
private:
Packit 5c3484
  typedef __gmp_expr<T, T> val1_type;
Packit 5c3484
  typedef __gmp_expr<U, V> val2_type;
Packit 5c3484
Packit 5c3484
  __gmp_binary_expr<val1_type, val2_type, Op> expr;
Packit 5c3484
public:
Packit 5c3484
  __gmp_expr(const val1_type &val1, const val2_type &val2)
Packit 5c3484
    : expr(val1, val2) { }
Packit 5c3484
  void eval(typename __gmp_resolve_expr<T>::ptr_type p) const
Packit 5c3484
  {
Packit 5c3484
    if(p != expr.val1.__get_mp())
Packit 5c3484
    {
Packit 5c3484
      __gmp_set_expr(p, expr.val2);
Packit 5c3484
      Op::eval(p, expr.val1.__get_mp(), p);
Packit 5c3484
    }
Packit 5c3484
    else
Packit 5c3484
    {
Packit 5c3484
      __gmp_temp<T> temp(expr.val2, p);
Packit 5c3484
      Op::eval(p, expr.val1.__get_mp(), temp.__get_mp());
Packit 5c3484
    }
Packit 5c3484
  }
Packit 5c3484
  const val1_type & get_val1() const { return expr.val1; }
Packit 5c3484
  const val2_type & get_val2() const { return expr.val2; }
Packit 5c3484
  mp_bitcnt_t get_prec() const
Packit 5c3484
  {
Packit 5c3484
    mp_bitcnt_t prec1 = expr.val1.get_prec(),
Packit 5c3484
      prec2 = expr.val2.get_prec();
Packit 5c3484
    return (prec1 > prec2) ? prec1 : prec2;
Packit 5c3484
  }
Packit 5c3484
};
Packit 5c3484
Packit 5c3484
template <class T, class U, class V, class Op>
Packit 5c3484
class __gmp_expr
Packit 5c3484
<T, __gmp_binary_expr<__gmp_expr<U, V>, __gmp_expr<T, T>, Op> >
Packit 5c3484
{
Packit 5c3484
private:
Packit 5c3484
  typedef __gmp_expr<U, V> val1_type;
Packit 5c3484
  typedef __gmp_expr<T, T> val2_type;
Packit 5c3484
Packit 5c3484
  __gmp_binary_expr<val1_type, val2_type, Op> expr;
Packit 5c3484
public:
Packit 5c3484
  __gmp_expr(const val1_type &val1, const val2_type &val2)
Packit 5c3484
    : expr(val1, val2) { }
Packit 5c3484
  void eval(typename __gmp_resolve_expr<T>::ptr_type p) const
Packit 5c3484
  {
Packit 5c3484
    if(p != expr.val2.__get_mp())
Packit 5c3484
    {
Packit 5c3484
      __gmp_set_expr(p, expr.val1);
Packit 5c3484
      Op::eval(p, p, expr.val2.__get_mp());
Packit 5c3484
    }
Packit 5c3484
    else
Packit 5c3484
    {
Packit 5c3484
      __gmp_temp<T> temp(expr.val1, p);
Packit 5c3484
      Op::eval(p, temp.__get_mp(), expr.val2.__get_mp());
Packit 5c3484
    }
Packit 5c3484
  }
Packit 5c3484
  const val1_type & get_val1() const { return expr.val1; }
Packit 5c3484
  const val2_type & get_val2() const { return expr.val2; }
Packit 5c3484
  mp_bitcnt_t get_prec() const
Packit 5c3484
  {
Packit 5c3484
    mp_bitcnt_t prec1 = expr.val1.get_prec(),
Packit 5c3484
      prec2 = expr.val2.get_prec();
Packit 5c3484
    return (prec1 > prec2) ? prec1 : prec2;
Packit 5c3484
  }
Packit 5c3484
};
Packit 5c3484
Packit 5c3484
template <class T, class U, class Op>
Packit 5c3484
class __gmp_expr
Packit 5c3484
<T, __gmp_binary_expr<__gmp_expr<T, T>, __gmp_expr<T, U>, Op> >
Packit 5c3484
{
Packit 5c3484
private:
Packit 5c3484
  typedef __gmp_expr<T, T> val1_type;
Packit 5c3484
  typedef __gmp_expr<T, U> val2_type;
Packit 5c3484
Packit 5c3484
  __gmp_binary_expr<val1_type, val2_type, Op> expr;
Packit 5c3484
public:
Packit 5c3484
  __gmp_expr(const val1_type &val1, const val2_type &val2)
Packit 5c3484
    : expr(val1, val2) { }
Packit 5c3484
  void eval(typename __gmp_resolve_expr<T>::ptr_type p) const
Packit 5c3484
  {
Packit 5c3484
    if(p != expr.val1.__get_mp())
Packit 5c3484
    {
Packit 5c3484
      __gmp_set_expr(p, expr.val2);
Packit 5c3484
      Op::eval(p, expr.val1.__get_mp(), p);
Packit 5c3484
    }
Packit 5c3484
    else
Packit 5c3484
    {
Packit 5c3484
      __gmp_temp<T> temp(expr.val2, p);
Packit 5c3484
      Op::eval(p, expr.val1.__get_mp(), temp.__get_mp());
Packit 5c3484
    }
Packit 5c3484
  }
Packit 5c3484
  const val1_type & get_val1() const { return expr.val1; }
Packit 5c3484
  const val2_type & get_val2() const { return expr.val2; }
Packit 5c3484
  mp_bitcnt_t get_prec() const
Packit 5c3484
  {
Packit 5c3484
    mp_bitcnt_t prec1 = expr.val1.get_prec(),
Packit 5c3484
      prec2 = expr.val2.get_prec();
Packit 5c3484
    return (prec1 > prec2) ? prec1 : prec2;
Packit 5c3484
  }
Packit 5c3484
};
Packit 5c3484
Packit 5c3484
template <class T, class U, class Op>
Packit 5c3484
class __gmp_expr
Packit 5c3484
<T, __gmp_binary_expr<__gmp_expr<T, U>, __gmp_expr<T, T>, Op> >
Packit 5c3484
{
Packit 5c3484
private:
Packit 5c3484
  typedef __gmp_expr<T, U> val1_type;
Packit 5c3484
  typedef __gmp_expr<T, T> val2_type;
Packit 5c3484
Packit 5c3484
  __gmp_binary_expr<val1_type, val2_type, Op> expr;
Packit 5c3484
public:
Packit 5c3484
  __gmp_expr(const val1_type &val1, const val2_type &val2)
Packit 5c3484
    : expr(val1, val2) { }
Packit 5c3484
  void eval(typename __gmp_resolve_expr<T>::ptr_type p) const
Packit 5c3484
  {
Packit 5c3484
    if(p != expr.val2.__get_mp())
Packit 5c3484
    {
Packit 5c3484
      __gmp_set_expr(p, expr.val1);
Packit 5c3484
      Op::eval(p, p, expr.val2.__get_mp());
Packit 5c3484
    }
Packit 5c3484
    else
Packit 5c3484
    {
Packit 5c3484
      __gmp_temp<T> temp(expr.val1, p);
Packit 5c3484
      Op::eval(p, temp.__get_mp(), expr.val2.__get_mp());
Packit 5c3484
    }
Packit 5c3484
  }
Packit 5c3484
  const val1_type & get_val1() const { return expr.val1; }
Packit 5c3484
  const val2_type & get_val2() const { return expr.val2; }
Packit 5c3484
  mp_bitcnt_t get_prec() const
Packit 5c3484
  {
Packit 5c3484
    mp_bitcnt_t prec1 = expr.val1.get_prec(),
Packit 5c3484
      prec2 = expr.val2.get_prec();
Packit 5c3484
    return (prec1 > prec2) ? prec1 : prec2;
Packit 5c3484
  }
Packit 5c3484
};
Packit 5c3484
Packit 5c3484
Packit 5c3484
// one argument is a subexpression, one is a built-in
Packit 5c3484
Packit 5c3484
template <class T, class U, class V, class Op>
Packit 5c3484
class __gmp_expr<T, __gmp_binary_expr<__gmp_expr<T, U>, V, Op> >
Packit 5c3484
{
Packit 5c3484
private:
Packit 5c3484
  typedef __gmp_expr<T, U> val1_type;
Packit 5c3484
  typedef V val2_type;
Packit 5c3484
Packit 5c3484
  __gmp_binary_expr<val1_type, val2_type, Op> expr;
Packit 5c3484
public:
Packit 5c3484
  __gmp_expr(const val1_type &val1, const val2_type &val2)
Packit 5c3484
    : expr(val1, val2) { }
Packit 5c3484
  void eval(typename __gmp_resolve_expr<T>::ptr_type p) const
Packit 5c3484
  {
Packit 5c3484
    expr.val1.eval(p);
Packit 5c3484
    Op::eval(p, p, expr.val2);
Packit 5c3484
  }
Packit 5c3484
  const val1_type & get_val1() const { return expr.val1; }
Packit 5c3484
  const val2_type & get_val2() const { return expr.val2; }
Packit 5c3484
  mp_bitcnt_t get_prec() const { return expr.val1.get_prec(); }
Packit 5c3484
};
Packit 5c3484
Packit 5c3484
template <class T, class U, class V, class Op>
Packit 5c3484
class __gmp_expr<T, __gmp_binary_expr<U, __gmp_expr<T, V>, Op> >
Packit 5c3484
{
Packit 5c3484
private:
Packit 5c3484
  typedef U val1_type;
Packit 5c3484
  typedef __gmp_expr<T, V> val2_type;
Packit 5c3484
Packit 5c3484
  __gmp_binary_expr<val1_type, val2_type, Op> expr;
Packit 5c3484
public:
Packit 5c3484
  __gmp_expr(const val1_type &val1, const val2_type &val2)
Packit 5c3484
    : expr(val1, val2) { }
Packit 5c3484
  void eval(typename __gmp_resolve_expr<T>::ptr_type p) const
Packit 5c3484
  {
Packit 5c3484
    expr.val2.eval(p);
Packit 5c3484
    Op::eval(p, expr.val1, p);
Packit 5c3484
  }
Packit 5c3484
  const val1_type & get_val1() const { return expr.val1; }
Packit 5c3484
  const val2_type & get_val2() const { return expr.val2; }
Packit 5c3484
  mp_bitcnt_t get_prec() const { return expr.val2.get_prec(); }
Packit 5c3484
};
Packit 5c3484
Packit 5c3484
Packit 5c3484
// both arguments are subexpressions
Packit 5c3484
Packit 5c3484
template <class T, class U, class V, class W, class Op>
Packit 5c3484
class __gmp_expr
Packit 5c3484
<T, __gmp_binary_expr<__gmp_expr<T, U>, __gmp_expr<V, W>, Op> >
Packit 5c3484
{
Packit 5c3484
private:
Packit 5c3484
  typedef __gmp_expr<T, U> val1_type;
Packit 5c3484
  typedef __gmp_expr<V, W> val2_type;
Packit 5c3484
Packit 5c3484
  __gmp_binary_expr<val1_type, val2_type, Op> expr;
Packit 5c3484
public:
Packit 5c3484
  __gmp_expr(const val1_type &val1, const val2_type &val2)
Packit 5c3484
    : expr(val1, val2) { }
Packit 5c3484
  void eval(typename __gmp_resolve_expr<T>::ptr_type p) const
Packit 5c3484
  {
Packit 5c3484
    __gmp_temp<T> temp2(expr.val2, p);
Packit 5c3484
    expr.val1.eval(p);
Packit 5c3484
    Op::eval(p, p, temp2.__get_mp());
Packit 5c3484
  }
Packit 5c3484
  const val1_type & get_val1() const { return expr.val1; }
Packit 5c3484
  const val2_type & get_val2() const { return expr.val2; }
Packit 5c3484
  mp_bitcnt_t get_prec() const
Packit 5c3484
  {
Packit 5c3484
    mp_bitcnt_t prec1 = expr.val1.get_prec(),
Packit 5c3484
      prec2 = expr.val2.get_prec();
Packit 5c3484
    return (prec1 > prec2) ? prec1 : prec2;
Packit 5c3484
  }
Packit 5c3484
};
Packit 5c3484
Packit 5c3484
template <class T, class U, class V, class W, class Op>
Packit 5c3484
class __gmp_expr
Packit 5c3484
<T, __gmp_binary_expr<__gmp_expr<U, V>, __gmp_expr<T, W>, Op> >
Packit 5c3484
{
Packit 5c3484
private:
Packit 5c3484
  typedef __gmp_expr<U, V> val1_type;
Packit 5c3484
  typedef __gmp_expr<T, W> val2_type;
Packit 5c3484
Packit 5c3484
  __gmp_binary_expr<val1_type, val2_type, Op> expr;
Packit 5c3484
public:
Packit 5c3484
  __gmp_expr(const val1_type &val1, const val2_type &val2)
Packit 5c3484
    : expr(val1, val2) { }
Packit 5c3484
  void eval(typename __gmp_resolve_expr<T>::ptr_type p) const
Packit 5c3484
  {
Packit 5c3484
    __gmp_temp<T> temp1(expr.val1, p);
Packit 5c3484
    expr.val2.eval(p);
Packit 5c3484
    Op::eval(p, temp1.__get_mp(), p);
Packit 5c3484
  }
Packit 5c3484
  const val1_type & get_val1() const { return expr.val1; }
Packit 5c3484
  const val2_type & get_val2() const { return expr.val2; }
Packit 5c3484
  mp_bitcnt_t get_prec() const
Packit 5c3484
  {
Packit 5c3484
    mp_bitcnt_t prec1 = expr.val1.get_prec(),
Packit 5c3484
      prec2 = expr.val2.get_prec();
Packit 5c3484
    return (prec1 > prec2) ? prec1 : prec2;
Packit 5c3484
  }
Packit 5c3484
};
Packit 5c3484
Packit 5c3484
template <class T, class U, class V, class Op>
Packit 5c3484
class __gmp_expr
Packit 5c3484
<T, __gmp_binary_expr<__gmp_expr<T, U>, __gmp_expr<T, V>, Op> >
Packit 5c3484
{
Packit 5c3484
private:
Packit 5c3484
  typedef __gmp_expr<T, U> val1_type;
Packit 5c3484
  typedef __gmp_expr<T, V> val2_type;
Packit 5c3484
Packit 5c3484
  __gmp_binary_expr<val1_type, val2_type, Op> expr;
Packit 5c3484
public:
Packit 5c3484
  __gmp_expr(const val1_type &val1, const val2_type &val2)
Packit 5c3484
    : expr(val1, val2) { }
Packit 5c3484
  void eval(typename __gmp_resolve_expr<T>::ptr_type p) const
Packit 5c3484
  {
Packit 5c3484
    __gmp_temp<T> temp2(expr.val2, p);
Packit 5c3484
    expr.val1.eval(p);
Packit 5c3484
    Op::eval(p, p, temp2.__get_mp());
Packit 5c3484
  }
Packit 5c3484
  const val1_type & get_val1() const { return expr.val1; }
Packit 5c3484
  const val2_type & get_val2() const { return expr.val2; }
Packit 5c3484
  mp_bitcnt_t get_prec() const
Packit 5c3484
  {
Packit 5c3484
    mp_bitcnt_t prec1 = expr.val1.get_prec(),
Packit 5c3484
      prec2 = expr.val2.get_prec();
Packit 5c3484
    return (prec1 > prec2) ? prec1 : prec2;
Packit 5c3484
  }
Packit 5c3484
};
Packit 5c3484
Packit 5c3484
Packit 5c3484
/**************** Special cases ****************/
Packit 5c3484
Packit 5c3484
/* Some operations (i.e., add and subtract) with mixed mpz/mpq arguments
Packit 5c3484
   can be done directly without first converting the mpz to mpq.
Packit 5c3484
   Appropriate specializations of __gmp_expr are required. */
Packit 5c3484
Packit 5c3484
Packit 5c3484
#define __GMPZQ_DEFINE_EXPR(eval_fun)                                       \
Packit 5c3484
                                                                            \
Packit 5c3484
template <>                                                                 \
Packit 5c3484
class __gmp_expr<mpq_t, __gmp_binary_expr<mpz_class, mpq_class, eval_fun> > \
Packit 5c3484
{                                                                           \
Packit 5c3484
private:                                                                    \
Packit 5c3484
  typedef mpz_class val1_type;                                              \
Packit 5c3484
  typedef mpq_class val2_type;                                              \
Packit 5c3484
                                                                            \
Packit 5c3484
  __gmp_binary_expr<val1_type, val2_type, eval_fun> expr;                   \
Packit 5c3484
public:                                                                     \
Packit 5c3484
  __gmp_expr(const val1_type &val1, const val2_type &val2)                  \
Packit 5c3484
    : expr(val1, val2) { }                                                  \
Packit 5c3484
  void eval(mpq_ptr q) const                                                \
Packit 5c3484
  { eval_fun::eval(q, expr.val1.get_mpz_t(), expr.val2.get_mpq_t()); }      \
Packit 5c3484
  const val1_type & get_val1() const { return expr.val1; }                  \
Packit 5c3484
  const val2_type & get_val2() const { return expr.val2; }                  \
Packit 5c3484
  mp_bitcnt_t get_prec() const { return mpf_get_default_prec(); }           \
Packit 5c3484
};                                                                          \
Packit 5c3484
                                                                            \
Packit 5c3484
template <>                                                                 \
Packit 5c3484
class __gmp_expr<mpq_t, __gmp_binary_expr<mpq_class, mpz_class, eval_fun> > \
Packit 5c3484
{                                                                           \
Packit 5c3484
private:                                                                    \
Packit 5c3484
  typedef mpq_class val1_type;                                              \
Packit 5c3484
  typedef mpz_class val2_type;                                              \
Packit 5c3484
                                                                            \
Packit 5c3484
  __gmp_binary_expr<val1_type, val2_type, eval_fun> expr;                   \
Packit 5c3484
public:                                                                     \
Packit 5c3484
  __gmp_expr(const val1_type &val1, const val2_type &val2)                  \
Packit 5c3484
    : expr(val1, val2) { }                                                  \
Packit 5c3484
  void eval(mpq_ptr q) const                                                \
Packit 5c3484
  { eval_fun::eval(q, expr.val1.get_mpq_t(), expr.val2.get_mpz_t()); }      \
Packit 5c3484
  const val1_type & get_val1() const { return expr.val1; }                  \
Packit 5c3484
  const val2_type & get_val2() const { return expr.val2; }                  \
Packit 5c3484
  mp_bitcnt_t get_prec() const { return mpf_get_default_prec(); }           \
Packit 5c3484
};                                                                          \
Packit 5c3484
                                                                            \
Packit 5c3484
template <class T>                                                          \
Packit 5c3484
class __gmp_expr                                                            \
Packit 5c3484
<mpq_t, __gmp_binary_expr<mpz_class, __gmp_expr<mpq_t, T>, eval_fun> >      \
Packit 5c3484
{                                                                           \
Packit 5c3484
private:                                                                    \
Packit 5c3484
  typedef mpz_class val1_type;                                              \
Packit 5c3484
  typedef __gmp_expr<mpq_t, T> val2_type;                                   \
Packit 5c3484
                                                                            \
Packit 5c3484
  __gmp_binary_expr<val1_type, val2_type, eval_fun> expr;                   \
Packit 5c3484
public:                                                                     \
Packit 5c3484
  __gmp_expr(const val1_type &val1, const val2_type &val2)                  \
Packit 5c3484
    : expr(val1, val2) { }                                                  \
Packit 5c3484
  void eval(mpq_ptr q) const                                                \
Packit 5c3484
  {                                                                         \
Packit 5c3484
    mpq_class temp(expr.val2);                                              \
Packit 5c3484
    eval_fun::eval(q, expr.val1.get_mpz_t(), temp.get_mpq_t());             \
Packit 5c3484
  }                                                                         \
Packit 5c3484
  const val1_type & get_val1() const { return expr.val1; }                  \
Packit 5c3484
  const val2_type & get_val2() const { return expr.val2; }                  \
Packit 5c3484
  mp_bitcnt_t get_prec() const { return mpf_get_default_prec(); }           \
Packit 5c3484
};                                                                          \
Packit 5c3484
                                                                            \
Packit 5c3484
template <class T>                                                          \
Packit 5c3484
class __gmp_expr                                                            \
Packit 5c3484
<mpq_t, __gmp_binary_expr<mpq_class, __gmp_expr<mpz_t, T>, eval_fun> >      \
Packit 5c3484
{                                                                           \
Packit 5c3484
private:                                                                    \
Packit 5c3484
  typedef mpq_class val1_type;                                              \
Packit 5c3484
  typedef __gmp_expr<mpz_t, T> val2_type;                                   \
Packit 5c3484
                                                                            \
Packit 5c3484
  __gmp_binary_expr<val1_type, val2_type, eval_fun> expr;                   \
Packit 5c3484
public:                                                                     \
Packit 5c3484
  __gmp_expr(const val1_type &val1, const val2_type &val2)                  \
Packit 5c3484
    : expr(val1, val2) { }                                                  \
Packit 5c3484
  void eval(mpq_ptr q) const                                                \
Packit 5c3484
  {                                                                         \
Packit 5c3484
    mpz_class temp(expr.val2);                                              \
Packit 5c3484
    eval_fun::eval(q, expr.val1.get_mpq_t(), temp.get_mpz_t());             \
Packit 5c3484
  }                                                                         \
Packit 5c3484
  const val1_type & get_val1() const { return expr.val1; }                  \
Packit 5c3484
  const val2_type & get_val2() const { return expr.val2; }                  \
Packit 5c3484
  mp_bitcnt_t get_prec() const { return mpf_get_default_prec(); }           \
Packit 5c3484
};                                                                          \
Packit 5c3484
                                                                            \
Packit 5c3484
template <class T>                                                          \
Packit 5c3484
class __gmp_expr                                                            \
Packit 5c3484
<mpq_t, __gmp_binary_expr<__gmp_expr<mpz_t, T>, mpq_class, eval_fun> >      \
Packit 5c3484
{                                                                           \
Packit 5c3484
private:                                                                    \
Packit 5c3484
  typedef __gmp_expr<mpz_t, T> val1_type;                                   \
Packit 5c3484
  typedef mpq_class val2_type;                                              \
Packit 5c3484
                                                                            \
Packit 5c3484
  __gmp_binary_expr<val1_type, val2_type, eval_fun> expr;                   \
Packit 5c3484
public:                                                                     \
Packit 5c3484
  __gmp_expr(const val1_type &val1, const val2_type &val2)                  \
Packit 5c3484
    : expr(val1, val2) { }                                                  \
Packit 5c3484
  void eval(mpq_ptr q) const                                                \
Packit 5c3484
  {                                                                         \
Packit 5c3484
    mpz_class temp(expr.val1);                                              \
Packit 5c3484
    eval_fun::eval(q, temp.get_mpz_t(), expr.val2.get_mpq_t());             \
Packit 5c3484
  }                                                                         \
Packit 5c3484
  const val1_type & get_val1() const { return expr.val1; }                  \
Packit 5c3484
  const val2_type & get_val2() const { return expr.val2; }                  \
Packit 5c3484
  mp_bitcnt_t get_prec() const { return mpf_get_default_prec(); }           \
Packit 5c3484
};                                                                          \
Packit 5c3484
                                                                            \
Packit 5c3484
template <class T>                                                          \
Packit 5c3484
class __gmp_expr                                                            \
Packit 5c3484
<mpq_t, __gmp_binary_expr<__gmp_expr<mpq_t, T>, mpz_class, eval_fun> >      \
Packit 5c3484
{                                                                           \
Packit 5c3484
private:                                                                    \
Packit 5c3484
  typedef __gmp_expr<mpq_t, T> val1_type;                                   \
Packit 5c3484
  typedef mpz_class val2_type;                                              \
Packit 5c3484
                                                                            \
Packit 5c3484
  __gmp_binary_expr<val1_type, val2_type, eval_fun> expr;                   \
Packit 5c3484
public:                                                                     \
Packit 5c3484
  __gmp_expr(const val1_type &val1, const val2_type &val2)                  \
Packit 5c3484
    : expr(val1, val2) { }                                                  \
Packit 5c3484
  void eval(mpq_ptr q) const                                                \
Packit 5c3484
  {                                                                         \
Packit 5c3484
    mpq_class temp(expr.val1);                                              \
Packit 5c3484
    eval_fun::eval(q, temp.get_mpq_t(), expr.val2.get_mpz_t());             \
Packit 5c3484
  }                                                                         \
Packit 5c3484
  const val1_type & get_val1() const { return expr.val1; }                  \
Packit 5c3484
  const val2_type & get_val2() const { return expr.val2; }                  \
Packit 5c3484
  mp_bitcnt_t get_prec() const { return mpf_get_default_prec(); }           \
Packit 5c3484
};                                                                          \
Packit 5c3484
                                                                            \
Packit 5c3484
template <class T, class U>                                                 \
Packit 5c3484
class __gmp_expr
Packit 5c3484
<__gmp_expr<mpz_t, T>, __gmp_expr<mpq_t, U>, eval_fun> >                    \
Packit 5c3484
{                                                                           \
Packit 5c3484
private:                                                                    \
Packit 5c3484
  typedef __gmp_expr<mpz_t, T> val1_type;                                   \
Packit 5c3484
  typedef __gmp_expr<mpq_t, U> val2_type;                                   \
Packit 5c3484
                                                                            \
Packit 5c3484
  __gmp_binary_expr<val1_type, val2_type, eval_fun> expr;                   \
Packit 5c3484
public:                                                                     \
Packit 5c3484
  __gmp_expr(const val1_type &val1, const val2_type &val2)                  \
Packit 5c3484
    : expr(val1, val2) { }                                                  \
Packit 5c3484
  void eval(mpq_ptr q) const                                                \
Packit 5c3484
  {                                                                         \
Packit 5c3484
    mpz_class temp1(expr.val1);                                             \
Packit 5c3484
    expr.val2.eval(q);                                                      \
Packit 5c3484
    eval_fun::eval(q, temp1.get_mpz_t(), q);                                \
Packit 5c3484
  }                                                                         \
Packit 5c3484
  const val1_type & get_val1() const { return expr.val1; }                  \
Packit 5c3484
  const val2_type & get_val2() const { return expr.val2; }                  \
Packit 5c3484
  mp_bitcnt_t get_prec() const { return mpf_get_default_prec(); }           \
Packit 5c3484
};                                                                          \
Packit 5c3484
                                                                            \
Packit 5c3484
template <class T, class U>                                                 \
Packit 5c3484
class __gmp_expr
Packit 5c3484
<__gmp_expr<mpq_t, T>, __gmp_expr<mpz_t, U>, eval_fun> >                    \
Packit 5c3484
{                                                                           \
Packit 5c3484
private:                                                                    \
Packit 5c3484
  typedef __gmp_expr<mpq_t, T> val1_type;                                   \
Packit 5c3484
  typedef __gmp_expr<mpz_t, U> val2_type;                                   \
Packit 5c3484
                                                                            \
Packit 5c3484
  __gmp_binary_expr<val1_type, val2_type, eval_fun> expr;                   \
Packit 5c3484
public:                                                                     \
Packit 5c3484
  __gmp_expr(const val1_type &val1, const val2_type &val2)                  \
Packit 5c3484
    : expr(val1, val2) { }                                                  \
Packit 5c3484
  void eval(mpq_ptr q) const                                                \
Packit 5c3484
  {                                                                         \
Packit 5c3484
    mpz_class temp2(expr.val2);                                             \
Packit 5c3484
    expr.val1.eval(q);                                             \
Packit 5c3484
    eval_fun::eval(q, q, temp2.get_mpz_t());                \
Packit 5c3484
  }                                                                         \
Packit 5c3484
  const val1_type & get_val1() const { return expr.val1; }                  \
Packit 5c3484
  const val2_type & get_val2() const { return expr.val2; }                  \
Packit 5c3484
  mp_bitcnt_t get_prec() const { return mpf_get_default_prec(); }           \
Packit 5c3484
};
Packit 5c3484
Packit 5c3484
Packit 5c3484
__GMPZQ_DEFINE_EXPR(__gmp_binary_plus)
Packit 5c3484
__GMPZQ_DEFINE_EXPR(__gmp_binary_minus)
Packit 5c3484
Packit 5c3484
Packit 5c3484
Packit 5c3484
/**************** Macros for defining functions ****************/
Packit 5c3484
/* Results of operators and functions are instances of __gmp_expr<T, U>.
Packit 5c3484
   T determines the numerical type of the expression: it can be either
Packit 5c3484
   mpz_t, mpq_t, or mpf_t.  When the arguments of a binary
Packit 5c3484
   expression have different numerical types, __gmp_resolve_expr is used
Packit 5c3484
   to determine the "larger" type.
Packit 5c3484
   U is either __gmp_unary_expr<V, Op> or __gmp_binary_expr<V, W, Op>,
Packit 5c3484
   where V and W are the arguments' types -- they can in turn be
Packit 5c3484
   expressions, thus allowing to build compound expressions to any
Packit 5c3484
   degree of complexity.
Packit 5c3484
   Op is a function object that must have an eval() method accepting
Packit 5c3484
   appropriate arguments.
Packit 5c3484
   Actual evaluation of a __gmp_expr<T, U> object is done when it gets
Packit 5c3484
   assigned to an mp*_class ("lazy" evaluation): this is done by calling
Packit 5c3484
   its eval() method. */
Packit 5c3484
Packit 5c3484
Packit 5c3484
// non-member unary operators and functions
Packit 5c3484
Packit 5c3484
#define __GMP_DEFINE_UNARY_FUNCTION(fun, eval_fun)                           \
Packit 5c3484
                                                                             \
Packit 5c3484
template <class T, class U>                                                  \
Packit 5c3484
inline __gmp_expr<T, __gmp_unary_expr<__gmp_expr<T, U>, eval_fun> >          \
Packit 5c3484
fun(const __gmp_expr<T, U> &expr)                                            \
Packit 5c3484
{                                                                            \
Packit 5c3484
  return __gmp_expr<T, __gmp_unary_expr<__gmp_expr<T, U>, eval_fun> >(expr); \
Packit 5c3484
}
Packit 5c3484
Packit 5c3484
#define __GMP_DEFINE_UNARY_TYPE_FUNCTION(type, fun, eval_fun) \
Packit 5c3484
                                                              \
Packit 5c3484
template <class T, class U>                                   \
Packit 5c3484
inline type fun(const __gmp_expr<T, U> &expr)                 \
Packit 5c3484
{                                                             \
Packit 5c3484
  __gmp_expr<T, T> const& temp(expr); \
Packit 5c3484
  return eval_fun::eval(temp.__get_mp());                     \
Packit 5c3484
}
Packit 5c3484
Packit 5c3484
Packit 5c3484
// non-member binary operators and functions
Packit 5c3484
Packit 5c3484
#define __GMPP_DEFINE_BINARY_FUNCTION(fun, eval_fun)                   \
Packit 5c3484
                                                                       \
Packit 5c3484
template <class T, class U, class V, class W>                          \
Packit 5c3484
inline __gmp_expr<typename __gmp_resolve_expr<T, V>::value_type,       \
Packit 5c3484
__gmp_binary_expr<__gmp_expr<T, U>, __gmp_expr<V, W>, eval_fun> >      \
Packit 5c3484
fun(const __gmp_expr<T, U> &expr1, const __gmp_expr<V, W> &expr2)      \
Packit 5c3484
{                                                                      \
Packit 5c3484
  return __gmp_expr<typename __gmp_resolve_expr<T, V>::value_type,     \
Packit 5c3484
     __gmp_binary_expr<__gmp_expr<T, U>, __gmp_expr<V, W>, eval_fun> > \
Packit 5c3484
    (expr1, expr2);                                                    \
Packit 5c3484
}
Packit 5c3484
Packit 5c3484
#define __GMPNN_DEFINE_BINARY_FUNCTION(fun, eval_fun, type, bigtype)       \
Packit 5c3484
                                                                           \
Packit 5c3484
template <class T, class U>                                                \
Packit 5c3484
inline __gmp_expr                                                          \
Packit 5c3484
<T, __gmp_binary_expr<__gmp_expr<T, U>, bigtype, eval_fun> >               \
Packit 5c3484
fun(const __gmp_expr<T, U> &expr, type t)                                  \
Packit 5c3484
{                                                                          \
Packit 5c3484
  return __gmp_expr                                                        \
Packit 5c3484
    <T, __gmp_binary_expr<__gmp_expr<T, U>, bigtype, eval_fun> >(expr, t); \
Packit 5c3484
}                                                                          \
Packit 5c3484
                                                                           \
Packit 5c3484
template <class T, class U>                                                \
Packit 5c3484
inline __gmp_expr                                                          \
Packit 5c3484
<T, __gmp_binary_expr<bigtype, __gmp_expr<T, U>, eval_fun> >               \
Packit 5c3484
fun(type t, const __gmp_expr<T, U> &expr)                                  \
Packit 5c3484
{                                                                          \
Packit 5c3484
  return __gmp_expr                                                        \
Packit 5c3484
    <T, __gmp_binary_expr<bigtype, __gmp_expr<T, U>, eval_fun> >(t, expr); \
Packit 5c3484
}
Packit 5c3484
Packit 5c3484
#define __GMPNS_DEFINE_BINARY_FUNCTION(fun, eval_fun, type)          \
Packit 5c3484
__GMPNN_DEFINE_BINARY_FUNCTION(fun, eval_fun, type, signed long int)
Packit 5c3484
Packit 5c3484
#define __GMPNU_DEFINE_BINARY_FUNCTION(fun, eval_fun, type)            \
Packit 5c3484
__GMPNN_DEFINE_BINARY_FUNCTION(fun, eval_fun, type, unsigned long int)
Packit 5c3484
Packit 5c3484
#define __GMPND_DEFINE_BINARY_FUNCTION(fun, eval_fun, type) \
Packit 5c3484
__GMPNN_DEFINE_BINARY_FUNCTION(fun, eval_fun, type, double)
Packit 5c3484
Packit 5c3484
#define __GMPNLD_DEFINE_BINARY_FUNCTION(fun, eval_fun, type)     \
Packit 5c3484
__GMPNN_DEFINE_BINARY_FUNCTION(fun, eval_fun, type, long double)
Packit 5c3484
Packit 5c3484
#define __GMPN_DEFINE_BINARY_FUNCTION(fun, eval_fun)              \
Packit 5c3484
__GMPNS_DEFINE_BINARY_FUNCTION(fun, eval_fun, signed char)        \
Packit 5c3484
__GMPNU_DEFINE_BINARY_FUNCTION(fun, eval_fun, unsigned char)      \
Packit 5c3484
__GMPNS_DEFINE_BINARY_FUNCTION(fun, eval_fun, signed int)         \
Packit 5c3484
__GMPNU_DEFINE_BINARY_FUNCTION(fun, eval_fun, unsigned int)       \
Packit 5c3484
__GMPNS_DEFINE_BINARY_FUNCTION(fun, eval_fun, signed short int)   \
Packit 5c3484
__GMPNU_DEFINE_BINARY_FUNCTION(fun, eval_fun, unsigned short int) \
Packit 5c3484
__GMPNS_DEFINE_BINARY_FUNCTION(fun, eval_fun, signed long int)    \
Packit 5c3484
__GMPNU_DEFINE_BINARY_FUNCTION(fun, eval_fun, unsigned long int)  \
Packit 5c3484
__GMPND_DEFINE_BINARY_FUNCTION(fun, eval_fun, float)              \
Packit 5c3484
__GMPND_DEFINE_BINARY_FUNCTION(fun, eval_fun, double)             \
Packit 5c3484
/* __GMPNLD_DEFINE_BINARY_FUNCTION(fun, eval_fun, long double) */
Packit 5c3484
Packit 5c3484
#define __GMP_DEFINE_BINARY_FUNCTION(fun, eval_fun) \
Packit 5c3484
__GMPP_DEFINE_BINARY_FUNCTION(fun, eval_fun)        \
Packit 5c3484
__GMPN_DEFINE_BINARY_FUNCTION(fun, eval_fun)
Packit 5c3484
Packit 5c3484
Packit 5c3484
#define __GMP_DEFINE_BINARY_FUNCTION_UI(fun, eval_fun)                 \
Packit 5c3484
                                                                       \
Packit 5c3484
template <class T, class U>                                            \
Packit 5c3484
inline __gmp_expr                                                      \
Packit 5c3484
<T, __gmp_binary_expr<__gmp_expr<T, U>, mp_bitcnt_t, eval_fun> > \
Packit 5c3484
fun(const __gmp_expr<T, U> &expr, mp_bitcnt_t l)                 \
Packit 5c3484
{                                                                      \
Packit 5c3484
  return __gmp_expr
Packit 5c3484
    <__gmp_expr<T, U>, mp_bitcnt_t, eval_fun> >(expr, l);        \
Packit 5c3484
}
Packit 5c3484
Packit 5c3484
Packit 5c3484
#define __GMPP_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun)         \
Packit 5c3484
                                                                        \
Packit 5c3484
template <class T, class U, class V, class W>                           \
Packit 5c3484
inline type fun(const __gmp_expr<T, U> &expr1,                          \
Packit 5c3484
		const __gmp_expr<V, W> &expr2)                          \
Packit 5c3484
{                                                                       \
Packit 5c3484
  __gmp_expr<T, T> const& temp1(expr1);                                 \
Packit 5c3484
  __gmp_expr<V, V> const& temp2(expr2);                                 \
Packit 5c3484
  return eval_fun::eval(temp1.__get_mp(), temp2.__get_mp());            \
Packit 5c3484
}
Packit 5c3484
Packit 5c3484
#define __GMPNN_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun,   \
Packit 5c3484
					    type2, bigtype)        \
Packit 5c3484
                                                                   \
Packit 5c3484
template <class T, class U>                                        \
Packit 5c3484
inline type fun(const __gmp_expr<T, U> &expr, type2 t)             \
Packit 5c3484
{                                                                  \
Packit 5c3484
  __gmp_expr<T, T> const& temp(expr);      \
Packit 5c3484
  return eval_fun::eval(temp.__get_mp(), static_cast<bigtype>(t)); \
Packit 5c3484
}                                                                  \
Packit 5c3484
                                                                   \
Packit 5c3484
template <class T, class U>                                        \
Packit 5c3484
inline type fun(type2 t, const __gmp_expr<T, U> &expr)             \
Packit 5c3484
{                                                                  \
Packit 5c3484
  __gmp_expr<T, T> const& temp(expr);      \
Packit 5c3484
  return eval_fun::eval(static_cast<bigtype>(t), temp.__get_mp()); \
Packit 5c3484
}
Packit 5c3484
Packit 5c3484
#define __GMPNS_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun, type2) \
Packit 5c3484
__GMPNN_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun,                \
Packit 5c3484
				    type2, signed long int)
Packit 5c3484
Packit 5c3484
#define __GMPNU_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun, type2) \
Packit 5c3484
__GMPNN_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun,                \
Packit 5c3484
				    type2, unsigned long int)
Packit 5c3484
Packit 5c3484
#define __GMPND_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun, type2) \
Packit 5c3484
__GMPNN_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun, type2, double)
Packit 5c3484
Packit 5c3484
#define __GMPNLD_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun, type2)     \
Packit 5c3484
__GMPNN_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun, type2, long double)
Packit 5c3484
Packit 5c3484
#define __GMPN_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun)              \
Packit 5c3484
__GMPNS_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun, signed char)        \
Packit 5c3484
__GMPNU_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun, unsigned char)      \
Packit 5c3484
__GMPNS_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun, signed int)         \
Packit 5c3484
__GMPNU_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun, unsigned int)       \
Packit 5c3484
__GMPNS_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun, signed short int)   \
Packit 5c3484
__GMPNU_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun, unsigned short int) \
Packit 5c3484
__GMPNS_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun, signed long int)    \
Packit 5c3484
__GMPNU_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun, unsigned long int)  \
Packit 5c3484
__GMPND_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun, float)              \
Packit 5c3484
__GMPND_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun, double)             \
Packit 5c3484
/* __GMPNLD_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun, long double) */
Packit 5c3484
Packit 5c3484
#define __GMP_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun) \
Packit 5c3484
__GMPP_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun)        \
Packit 5c3484
__GMPN_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun)
Packit 5c3484
Packit 5c3484
Packit 5c3484
// member operators
Packit 5c3484
Packit 5c3484
#define __GMPP_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun)                 \
Packit 5c3484
                                                                             \
Packit 5c3484
template <class T, class U>                                                  \
Packit 5c3484
inline type##_class & type##_class::fun(const __gmp_expr<T, U> &expr)        \
Packit 5c3484
{                                                                            \
Packit 5c3484
  __gmp_set_expr(mp, __gmp_expr
Packit 5c3484
		 <type##_class, __gmp_expr<T, U>, eval_fun> >(*this, expr)); \
Packit 5c3484
  return *this;                                                              \
Packit 5c3484
}
Packit 5c3484
Packit 5c3484
#define __GMPNN_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun,    \
Packit 5c3484
					 type2, bigtype)         \
Packit 5c3484
                                                                 \
Packit 5c3484
inline type##_class & type##_class::fun(type2 t)                 \
Packit 5c3484
{                                                                \
Packit 5c3484
  __gmp_set_expr(mp, __gmp_expr
Packit 5c3484
		 <type##_class, bigtype, eval_fun> >(*this, t)); \
Packit 5c3484
  return *this;                                                  \
Packit 5c3484
}
Packit 5c3484
Packit 5c3484
#define __GMPNS_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun, type2) \
Packit 5c3484
__GMPNN_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun,                \
Packit 5c3484
				 type2, signed long int)
Packit 5c3484
Packit 5c3484
#define __GMPNU_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun, type2) \
Packit 5c3484
__GMPNN_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun,                \
Packit 5c3484
				 type2, unsigned long int)
Packit 5c3484
Packit 5c3484
#define __GMPND_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun, type2) \
Packit 5c3484
__GMPNN_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun, type2, double)
Packit 5c3484
Packit 5c3484
#define __GMPNLD_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun, type2)     \
Packit 5c3484
__GMPNN_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun, type2, long double)
Packit 5c3484
Packit 5c3484
#define __GMPN_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun)              \
Packit 5c3484
__GMPNS_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun, signed char)        \
Packit 5c3484
__GMPNU_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun, unsigned char)      \
Packit 5c3484
__GMPNS_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun, signed int)         \
Packit 5c3484
__GMPNU_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun, unsigned int)       \
Packit 5c3484
__GMPNS_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun, signed short int)   \
Packit 5c3484
__GMPNU_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun, unsigned short int) \
Packit 5c3484
__GMPNS_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun, signed long int)    \
Packit 5c3484
__GMPNU_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun, unsigned long int)  \
Packit 5c3484
__GMPND_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun, float)              \
Packit 5c3484
__GMPND_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun, double)             \
Packit 5c3484
/* __GMPNLD_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun, long double) */
Packit 5c3484
Packit 5c3484
#define __GMP_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun) \
Packit 5c3484
__GMPP_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun)        \
Packit 5c3484
__GMPN_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun)
Packit 5c3484
Packit 5c3484
#define __GMPZ_DEFINE_COMPOUND_OPERATOR(fun, eval_fun) \
Packit 5c3484
__GMP_DEFINE_COMPOUND_OPERATOR(mpz, fun, eval_fun)
Packit 5c3484
Packit 5c3484
#define __GMPQ_DEFINE_COMPOUND_OPERATOR(fun, eval_fun) \
Packit 5c3484
__GMP_DEFINE_COMPOUND_OPERATOR(mpq, fun, eval_fun)
Packit 5c3484
Packit 5c3484
#define __GMPF_DEFINE_COMPOUND_OPERATOR(fun, eval_fun) \
Packit 5c3484
__GMP_DEFINE_COMPOUND_OPERATOR(mpf, fun, eval_fun)
Packit 5c3484
Packit 5c3484
Packit 5c3484
Packit 5c3484
#define __GMP_DEFINE_COMPOUND_OPERATOR_UI(type, fun, eval_fun)  \
Packit 5c3484
                                                                \
Packit 5c3484
inline type##_class & type##_class::fun(mp_bitcnt_t l)    \
Packit 5c3484
{                                                               \
Packit 5c3484
  __gmp_set_expr(mp, __gmp_expr
Packit 5c3484
    <type##_class, mp_bitcnt_t, eval_fun> >(*this, l));   \
Packit 5c3484
  return *this;                                                 \
Packit 5c3484
}
Packit 5c3484
Packit 5c3484
#define __GMPZ_DEFINE_COMPOUND_OPERATOR_UI(fun, eval_fun) \
Packit 5c3484
__GMP_DEFINE_COMPOUND_OPERATOR_UI(mpz, fun, eval_fun)
Packit 5c3484
Packit 5c3484
#define __GMPQ_DEFINE_COMPOUND_OPERATOR_UI(fun, eval_fun) \
Packit 5c3484
__GMP_DEFINE_COMPOUND_OPERATOR_UI(mpq, fun, eval_fun)
Packit 5c3484
Packit 5c3484
#define __GMPF_DEFINE_COMPOUND_OPERATOR_UI(fun, eval_fun) \
Packit 5c3484
__GMP_DEFINE_COMPOUND_OPERATOR_UI(mpf, fun, eval_fun)
Packit 5c3484
Packit 5c3484
Packit 5c3484
Packit 5c3484
#define __GMP_DEFINE_INCREMENT_OPERATOR(type, fun, eval_fun) \
Packit 5c3484
                                                             \
Packit 5c3484
inline type##_class & type##_class::fun()                    \
Packit 5c3484
{                                                            \
Packit 5c3484
  eval_fun::eval(mp);                                        \
Packit 5c3484
  return *this;                                              \
Packit 5c3484
}                                                            \
Packit 5c3484
                                                             \
Packit 5c3484
inline type##_class type##_class::fun(int)                   \
Packit 5c3484
{                                                            \
Packit 5c3484
  type##_class temp(*this);                                  \
Packit 5c3484
  eval_fun::eval(mp);                                        \
Packit 5c3484
  return temp;                                               \
Packit 5c3484
}
Packit 5c3484
Packit 5c3484
#define __GMPZ_DEFINE_INCREMENT_OPERATOR(fun, eval_fun) \
Packit 5c3484
__GMP_DEFINE_INCREMENT_OPERATOR(mpz, fun, eval_fun)
Packit 5c3484
Packit 5c3484
#define __GMPQ_DEFINE_INCREMENT_OPERATOR(fun, eval_fun) \
Packit 5c3484
__GMP_DEFINE_INCREMENT_OPERATOR(mpq, fun, eval_fun)
Packit 5c3484
Packit 5c3484
#define __GMPF_DEFINE_INCREMENT_OPERATOR(fun, eval_fun) \
Packit 5c3484
__GMP_DEFINE_INCREMENT_OPERATOR(mpf, fun, eval_fun)
Packit 5c3484
Packit 5c3484
Packit 5c3484
Packit 5c3484
/**************** Arithmetic operators and functions ****************/
Packit 5c3484
Packit 5c3484
// non-member operators and functions
Packit 5c3484
Packit 5c3484
__GMP_DEFINE_UNARY_FUNCTION(operator+, __gmp_unary_plus)
Packit 5c3484
__GMP_DEFINE_UNARY_FUNCTION(operator-, __gmp_unary_minus)
Packit 5c3484
__GMP_DEFINE_UNARY_FUNCTION(operator~, __gmp_unary_com)
Packit 5c3484
Packit 5c3484
__GMP_DEFINE_BINARY_FUNCTION(operator+, __gmp_binary_plus)
Packit 5c3484
__GMP_DEFINE_BINARY_FUNCTION(operator-, __gmp_binary_minus)
Packit 5c3484
__GMP_DEFINE_BINARY_FUNCTION(operator*, __gmp_binary_multiplies)
Packit 5c3484
__GMP_DEFINE_BINARY_FUNCTION(operator/, __gmp_binary_divides)
Packit 5c3484
__GMP_DEFINE_BINARY_FUNCTION(operator%, __gmp_binary_modulus)
Packit 5c3484
__GMP_DEFINE_BINARY_FUNCTION(operator&, __gmp_binary_and)
Packit 5c3484
__GMP_DEFINE_BINARY_FUNCTION(operator|, __gmp_binary_ior)
Packit 5c3484
__GMP_DEFINE_BINARY_FUNCTION(operator^, __gmp_binary_xor)
Packit 5c3484
Packit 5c3484
__GMP_DEFINE_BINARY_FUNCTION_UI(operator<<, __gmp_binary_lshift)
Packit 5c3484
__GMP_DEFINE_BINARY_FUNCTION_UI(operator>>, __gmp_binary_rshift)
Packit 5c3484
Packit 5c3484
__GMP_DEFINE_BINARY_TYPE_FUNCTION(bool, operator==, __gmp_binary_equal)
Packit 5c3484
__GMP_DEFINE_BINARY_TYPE_FUNCTION(bool, operator!=, ! __gmp_binary_equal)
Packit 5c3484
__GMP_DEFINE_BINARY_TYPE_FUNCTION(bool, operator<, __gmp_binary_less)
Packit 5c3484
__GMP_DEFINE_BINARY_TYPE_FUNCTION(bool, operator<=, ! __gmp_binary_greater)
Packit 5c3484
__GMP_DEFINE_BINARY_TYPE_FUNCTION(bool, operator>, __gmp_binary_greater)
Packit 5c3484
__GMP_DEFINE_BINARY_TYPE_FUNCTION(bool, operator>=, ! __gmp_binary_less)
Packit 5c3484
Packit 5c3484
__GMP_DEFINE_UNARY_FUNCTION(abs, __gmp_abs_function)
Packit 5c3484
__GMP_DEFINE_UNARY_FUNCTION(trunc, __gmp_trunc_function)
Packit 5c3484
__GMP_DEFINE_UNARY_FUNCTION(floor, __gmp_floor_function)
Packit 5c3484
__GMP_DEFINE_UNARY_FUNCTION(ceil, __gmp_ceil_function)
Packit 5c3484
__GMP_DEFINE_UNARY_FUNCTION(sqrt, __gmp_sqrt_function)
Packit 5c3484
__GMP_DEFINE_BINARY_FUNCTION(hypot, __gmp_hypot_function)
Packit 5c3484
__GMP_DEFINE_BINARY_FUNCTION(gcd, __gmp_gcd_function)
Packit 5c3484
__GMP_DEFINE_BINARY_FUNCTION(lcm, __gmp_lcm_function)
Packit 5c3484
Packit 5c3484
__GMP_DEFINE_UNARY_TYPE_FUNCTION(int, sgn, __gmp_sgn_function)
Packit 5c3484
__GMP_DEFINE_BINARY_TYPE_FUNCTION(int, cmp, __gmp_cmp_function)
Packit 5c3484
Packit 5c3484
template <class T>
Packit 5c3484
void swap(__gmp_expr<T, T>& x, __gmp_expr<T, T>& y) __GMPXX_NOEXCEPT
Packit 5c3484
{ x.swap(y); }
Packit 5c3484
Packit 5c3484
// member operators for mpz_class
Packit 5c3484
Packit 5c3484
__GMPZ_DEFINE_COMPOUND_OPERATOR(operator+=, __gmp_binary_plus)
Packit 5c3484
__GMPZ_DEFINE_COMPOUND_OPERATOR(operator-=, __gmp_binary_minus)
Packit 5c3484
__GMPZ_DEFINE_COMPOUND_OPERATOR(operator*=, __gmp_binary_multiplies)
Packit 5c3484
__GMPZ_DEFINE_COMPOUND_OPERATOR(operator/=, __gmp_binary_divides)
Packit 5c3484
__GMPZ_DEFINE_COMPOUND_OPERATOR(operator%=, __gmp_binary_modulus)
Packit 5c3484
Packit 5c3484
__GMPZ_DEFINE_COMPOUND_OPERATOR(operator&=, __gmp_binary_and)
Packit 5c3484
__GMPZ_DEFINE_COMPOUND_OPERATOR(operator|=, __gmp_binary_ior)
Packit 5c3484
__GMPZ_DEFINE_COMPOUND_OPERATOR(operator^=, __gmp_binary_xor)
Packit 5c3484
Packit 5c3484
__GMPZ_DEFINE_COMPOUND_OPERATOR_UI(operator<<=, __gmp_binary_lshift)
Packit 5c3484
__GMPZ_DEFINE_COMPOUND_OPERATOR_UI(operator>>=, __gmp_binary_rshift)
Packit 5c3484
Packit 5c3484
__GMPZ_DEFINE_INCREMENT_OPERATOR(operator++, __gmp_unary_increment)
Packit 5c3484
__GMPZ_DEFINE_INCREMENT_OPERATOR(operator--, __gmp_unary_decrement)
Packit 5c3484
Packit 5c3484
// member operators for mpq_class
Packit 5c3484
Packit 5c3484
__GMPQ_DEFINE_COMPOUND_OPERATOR(operator+=, __gmp_binary_plus)
Packit 5c3484
__GMPQ_DEFINE_COMPOUND_OPERATOR(operator-=, __gmp_binary_minus)
Packit 5c3484
__GMPQ_DEFINE_COMPOUND_OPERATOR(operator*=, __gmp_binary_multiplies)
Packit 5c3484
__GMPQ_DEFINE_COMPOUND_OPERATOR(operator/=, __gmp_binary_divides)
Packit 5c3484
Packit 5c3484
__GMPQ_DEFINE_COMPOUND_OPERATOR_UI(operator<<=, __gmp_binary_lshift)
Packit 5c3484
__GMPQ_DEFINE_COMPOUND_OPERATOR_UI(operator>>=, __gmp_binary_rshift)
Packit 5c3484
Packit 5c3484
__GMPQ_DEFINE_INCREMENT_OPERATOR(operator++, __gmp_unary_increment)
Packit 5c3484
__GMPQ_DEFINE_INCREMENT_OPERATOR(operator--, __gmp_unary_decrement)
Packit 5c3484
Packit 5c3484
// member operators for mpf_class
Packit 5c3484
Packit 5c3484
__GMPF_DEFINE_COMPOUND_OPERATOR(operator+=, __gmp_binary_plus)
Packit 5c3484
__GMPF_DEFINE_COMPOUND_OPERATOR(operator-=, __gmp_binary_minus)
Packit 5c3484
__GMPF_DEFINE_COMPOUND_OPERATOR(operator*=, __gmp_binary_multiplies)
Packit 5c3484
__GMPF_DEFINE_COMPOUND_OPERATOR(operator/=, __gmp_binary_divides)
Packit 5c3484
Packit 5c3484
__GMPF_DEFINE_COMPOUND_OPERATOR_UI(operator<<=, __gmp_binary_lshift)
Packit 5c3484
__GMPF_DEFINE_COMPOUND_OPERATOR_UI(operator>>=, __gmp_binary_rshift)
Packit 5c3484
Packit 5c3484
__GMPF_DEFINE_INCREMENT_OPERATOR(operator++, __gmp_unary_increment)
Packit 5c3484
__GMPF_DEFINE_INCREMENT_OPERATOR(operator--, __gmp_unary_decrement)
Packit 5c3484
Packit 5c3484
Packit 5c3484
Packit 5c3484
/**************** Class wrapper for gmp_randstate_t ****************/
Packit 5c3484
Packit 5c3484
class __gmp_urandomb_value { };
Packit 5c3484
class __gmp_urandomm_value { };
Packit 5c3484
Packit 5c3484
template <>
Packit 5c3484
class __gmp_expr<mpz_t, __gmp_urandomb_value>
Packit 5c3484
{
Packit 5c3484
private:
Packit 5c3484
  __gmp_randstate_struct *state;
Packit 5c3484
  mp_bitcnt_t bits;
Packit 5c3484
public:
Packit 5c3484
  __gmp_expr(gmp_randstate_t s, mp_bitcnt_t l) : state(s), bits(l) { }
Packit 5c3484
  void eval(mpz_ptr z) const { __gmp_rand_function::eval(z, state, bits); }
Packit 5c3484
  mp_bitcnt_t get_prec() const { return mpf_get_default_prec(); }
Packit 5c3484
};
Packit 5c3484
Packit 5c3484
template <>
Packit 5c3484
class __gmp_expr<mpz_t, __gmp_urandomm_value>
Packit 5c3484
{
Packit 5c3484
private:
Packit 5c3484
  __gmp_randstate_struct *state;
Packit 5c3484
  mpz_class range;
Packit 5c3484
public:
Packit 5c3484
  __gmp_expr(gmp_randstate_t s, const mpz_class &z) : state(s), range(z) { }
Packit 5c3484
  void eval(mpz_ptr z) const
Packit 5c3484
  { __gmp_rand_function::eval(z, state, range.get_mpz_t()); }
Packit 5c3484
  mp_bitcnt_t get_prec() const { return mpf_get_default_prec(); }
Packit 5c3484
};
Packit 5c3484
Packit 5c3484
template <>
Packit 5c3484
class __gmp_expr<mpf_t, __gmp_urandomb_value>
Packit 5c3484
{
Packit 5c3484
private:
Packit 5c3484
  __gmp_randstate_struct *state;
Packit 5c3484
  mp_bitcnt_t bits;
Packit 5c3484
public:
Packit 5c3484
  __gmp_expr(gmp_randstate_t s, mp_bitcnt_t l) : state(s), bits(l) { }
Packit 5c3484
  void eval(mpf_ptr f) const
Packit 5c3484
  {
Packit 5c3484
    __gmp_rand_function::eval(f, state,
Packit 5c3484
	(bits>0) ? bits : mpf_get_prec(f));
Packit 5c3484
  }
Packit 5c3484
  mp_bitcnt_t get_prec() const
Packit 5c3484
  {
Packit 5c3484
    if (bits == 0)
Packit 5c3484
      return mpf_get_default_prec();
Packit 5c3484
    else
Packit 5c3484
      return bits;
Packit 5c3484
  }
Packit 5c3484
};
Packit 5c3484
Packit 5c3484
extern "C" {
Packit 5c3484
  typedef void __gmp_randinit_default_t (gmp_randstate_t);
Packit 5c3484
  typedef void __gmp_randinit_lc_2exp_t (gmp_randstate_t, mpz_srcptr, unsigned long int, mp_bitcnt_t);
Packit 5c3484
  typedef int __gmp_randinit_lc_2exp_size_t (gmp_randstate_t, mp_bitcnt_t);
Packit 5c3484
}
Packit 5c3484
Packit 5c3484
class gmp_randclass
Packit 5c3484
{
Packit 5c3484
private:
Packit 5c3484
  gmp_randstate_t state;
Packit 5c3484
Packit 5c3484
  // copy construction and assignment not allowed
Packit 5c3484
  gmp_randclass(const gmp_randclass &);
Packit 5c3484
  void operator=(const gmp_randclass &);
Packit 5c3484
public:
Packit 5c3484
  // constructors and destructor
Packit 5c3484
  gmp_randclass(gmp_randalg_t alg, unsigned long int size)
Packit 5c3484
  {
Packit 5c3484
    switch (alg)
Packit 5c3484
      {
Packit 5c3484
      case GMP_RAND_ALG_LC: // no other cases for now
Packit 5c3484
      default:
Packit 5c3484
	gmp_randinit(state, alg, size);
Packit 5c3484
	break;
Packit 5c3484
      }
Packit 5c3484
  }
Packit 5c3484
Packit 5c3484
  // gmp_randinit_default
Packit 5c3484
  gmp_randclass(__gmp_randinit_default_t* f) { f(state); }
Packit 5c3484
Packit 5c3484
  // gmp_randinit_lc_2exp
Packit 5c3484
  gmp_randclass(__gmp_randinit_lc_2exp_t* f,
Packit 5c3484
		mpz_class z, unsigned long int l1, mp_bitcnt_t l2)
Packit 5c3484
  { f(state, z.get_mpz_t(), l1, l2); }
Packit 5c3484
Packit 5c3484
  // gmp_randinit_lc_2exp_size
Packit 5c3484
  gmp_randclass(__gmp_randinit_lc_2exp_size_t* f,
Packit 5c3484
		mp_bitcnt_t size)
Packit 5c3484
  {
Packit 5c3484
    if (f (state, size) == 0)
Packit 5c3484
      throw std::length_error ("gmp_randinit_lc_2exp_size");
Packit 5c3484
  }
Packit 5c3484
Packit 5c3484
  ~gmp_randclass() { gmp_randclear(state); }
Packit 5c3484
Packit 5c3484
  // initialize
Packit 5c3484
  void seed(); // choose a random seed some way (?)
Packit 5c3484
  void seed(unsigned long int s) { gmp_randseed_ui(state, s); }
Packit 5c3484
  void seed(const mpz_class &z) { gmp_randseed(state, z.get_mpz_t()); }
Packit 5c3484
Packit 5c3484
  // get random number
Packit 5c3484
  __gmp_expr<mpz_t, __gmp_urandomb_value> get_z_bits(mp_bitcnt_t l)
Packit 5c3484
  { return __gmp_expr<mpz_t, __gmp_urandomb_value>(state, l); }
Packit 5c3484
  __gmp_expr<mpz_t, __gmp_urandomb_value> get_z_bits(const mpz_class &z)
Packit 5c3484
  { return get_z_bits(z.get_ui()); }
Packit 5c3484
  // FIXME: z.get_bitcnt_t() ?
Packit 5c3484
Packit 5c3484
  __gmp_expr<mpz_t, __gmp_urandomm_value> get_z_range(const mpz_class &z)
Packit 5c3484
  { return __gmp_expr<mpz_t, __gmp_urandomm_value>(state, z); }
Packit 5c3484
Packit 5c3484
  __gmp_expr<mpf_t, __gmp_urandomb_value> get_f(mp_bitcnt_t prec = 0)
Packit 5c3484
  { return __gmp_expr<mpf_t, __gmp_urandomb_value>(state, prec); }
Packit 5c3484
};
Packit 5c3484
Packit 5c3484
Packit 5c3484
/**************** Specialize std::numeric_limits ****************/
Packit 5c3484
Packit 5c3484
namespace std {
Packit 5c3484
  template <> class numeric_limits<mpz_class>
Packit 5c3484
  {
Packit 5c3484
  public:
Packit 5c3484
    static const bool is_specialized = true;
Packit 5c3484
    static mpz_class min() { return mpz_class(); }
Packit 5c3484
    static mpz_class max() { return mpz_class(); }
Packit 5c3484
    static mpz_class lowest() { return mpz_class(); }
Packit 5c3484
    static const int digits = 0;
Packit 5c3484
    static const int digits10 = 0;
Packit 5c3484
    static const int max_digits10 = 0;
Packit 5c3484
    static const bool is_signed = true;
Packit 5c3484
    static const bool is_integer = true;
Packit 5c3484
    static const bool is_exact = true;
Packit 5c3484
    static const int radix = 2;
Packit 5c3484
    static mpz_class epsilon() { return mpz_class(); }
Packit 5c3484
    static mpz_class round_error() { return mpz_class(); }
Packit 5c3484
    static const int min_exponent = 0;
Packit 5c3484
    static const int min_exponent10 = 0;
Packit 5c3484
    static const int max_exponent = 0;
Packit 5c3484
    static const int max_exponent10 = 0;
Packit 5c3484
    static const bool has_infinity = false;
Packit 5c3484
    static const bool has_quiet_NaN = false;
Packit 5c3484
    static const bool has_signaling_NaN = false;
Packit 5c3484
    static const float_denorm_style has_denorm = denorm_absent;
Packit 5c3484
    static const bool has_denorm_loss = false;
Packit 5c3484
    static mpz_class infinity() { return mpz_class(); }
Packit 5c3484
    static mpz_class quiet_NaN() { return mpz_class(); }
Packit 5c3484
    static mpz_class signaling_NaN() { return mpz_class(); }
Packit 5c3484
    static mpz_class denorm_min() { return mpz_class(); }
Packit 5c3484
    static const bool is_iec559 = false;
Packit 5c3484
    static const bool is_bounded = false;
Packit 5c3484
    static const bool is_modulo = false;
Packit 5c3484
    static const bool traps = false;
Packit 5c3484
    static const bool tinyness_before = false;
Packit 5c3484
    static const float_round_style round_style = round_toward_zero;
Packit 5c3484
  };
Packit 5c3484
Packit 5c3484
  template <> class numeric_limits<mpq_class>
Packit 5c3484
  {
Packit 5c3484
  public:
Packit 5c3484
    static const bool is_specialized = true;
Packit 5c3484
    static mpq_class min() { return mpq_class(); }
Packit 5c3484
    static mpq_class max() { return mpq_class(); }
Packit 5c3484
    static mpq_class lowest() { return mpq_class(); }
Packit 5c3484
    static const int digits = 0;
Packit 5c3484
    static const int digits10 = 0;
Packit 5c3484
    static const int max_digits10 = 0;
Packit 5c3484
    static const bool is_signed = true;
Packit 5c3484
    static const bool is_integer = false;
Packit 5c3484
    static const bool is_exact = true;
Packit 5c3484
    static const int radix = 2;
Packit 5c3484
    static mpq_class epsilon() { return mpq_class(); }
Packit 5c3484
    static mpq_class round_error() { return mpq_class(); }
Packit 5c3484
    static const int min_exponent = 0;
Packit 5c3484
    static const int min_exponent10 = 0;
Packit 5c3484
    static const int max_exponent = 0;
Packit 5c3484
    static const int max_exponent10 = 0;
Packit 5c3484
    static const bool has_infinity = false;
Packit 5c3484
    static const bool has_quiet_NaN = false;
Packit 5c3484
    static const bool has_signaling_NaN = false;
Packit 5c3484
    static const float_denorm_style has_denorm = denorm_absent;
Packit 5c3484
    static const bool has_denorm_loss = false;
Packit 5c3484
    static mpq_class infinity() { return mpq_class(); }
Packit 5c3484
    static mpq_class quiet_NaN() { return mpq_class(); }
Packit 5c3484
    static mpq_class signaling_NaN() { return mpq_class(); }
Packit 5c3484
    static mpq_class denorm_min() { return mpq_class(); }
Packit 5c3484
    static const bool is_iec559 = false;
Packit 5c3484
    static const bool is_bounded = false;
Packit 5c3484
    static const bool is_modulo = false;
Packit 5c3484
    static const bool traps = false;
Packit 5c3484
    static const bool tinyness_before = false;
Packit 5c3484
    static const float_round_style round_style = round_toward_zero;
Packit 5c3484
  };
Packit 5c3484
Packit 5c3484
  template <> class numeric_limits<mpf_class>
Packit 5c3484
  {
Packit 5c3484
  public:
Packit 5c3484
    static const bool is_specialized = true;
Packit 5c3484
    static mpf_class min() { return mpf_class(); }
Packit 5c3484
    static mpf_class max() { return mpf_class(); }
Packit 5c3484
    static mpf_class lowest() { return mpf_class(); }
Packit 5c3484
    static const int digits = 0;