Quellcodebibliothek Statistik Leitseite products/sources/formale Sprachen/GAP/extern/gmp/   (Algebra von RWTH Aachen Version 4.15.1©)  Datei vom 18.9.2025 mit Größe 126 kB image not shown  

Quelle  gmpxx.h   Sprache: C

 
/* gmpxx.h -- C++ class wrapper for GMP types.  -*- C++ -*-

Copyright 2001-2003, 2006, 2008, 2011-2015, 2018 Free Software
Foundation, Inc.

This file is part of the GNU MP Library.

The GNU MP Library is free software; you can redistribute it and/or modify
it under the terms of either:

  * the GNU Lesser General Public License as published by the Free
    Software Foundation; either version 3 of the License, or (at your
    option) any later version.

or

  * the GNU General Public License as published by the Free Software
    Foundation; either version 2 of the License, or (at your option) any
    later version.

or both in parallel, as here.

The GNU MP Library is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
for more details.

You should have received copies of the GNU General Public License and the
GNU Lesser General Public License along with the GNU MP Library.  If not,
see https://www.gnu.org/licenses/.  */


#ifndef __GMP_PLUSPLUS__
#define __GMP_PLUSPLUS__

#include <iosfwd>

#include <cstring>  /* for strlen */
#include <limits>  /* numeric_limits */
#include <utility>
#include <algorithm>  /* swap */
#include <string>
#include <stdexcept>
#include <cfloat>
#include <gmp.h>

// wrapper for gcc's __builtin_constant_p
// __builtin_constant_p has been in gcc since forever,
// but g++-3.4 miscompiles it.
#if __GMP_GNUC_PREREQ(4, 2)
#define __GMPXX_CONSTANT(X) __builtin_constant_p(X)
#else
#define __GMPXX_CONSTANT(X) false
#endif
#define __GMPXX_CONSTANT_TRUE(X) (__GMPXX_CONSTANT(X) && (X))

// Use C++11 features
#ifndef __GMPXX_USE_CXX11
#if __cplusplus >= 201103L
#define __GMPXX_USE_CXX11 1
#else
#define __GMPXX_USE_CXX11 0
#endif
#endif

#if __GMPXX_USE_CXX11
#define __GMPXX_NOEXCEPT noexcept
#include <type_traits> // for common_type
#else
#define __GMPXX_NOEXCEPT
#endif

// Max allocations for plain types when converted to GMP types
#if GMP_NAIL_BITS != 0 && ! defined _LONG_LONG_LIMB
#define __GMPZ_ULI_LIMBS 2
#else
#define __GMPZ_ULI_LIMBS 1
#endif

#define __GMPXX_BITS_TO_LIMBS(n)  (((n) + (GMP_NUMB_BITS - 1)) / GMP_NUMB_BITS)
#define __GMPZ_DBL_LIMBS __GMPXX_BITS_TO_LIMBS(DBL_MAX_EXP)+1
#define __GMPQ_NUM_DBL_LIMBS __GMPZ_DBL_LIMBS
#define __GMPQ_DEN_DBL_LIMBS __GMPXX_BITS_TO_LIMBS(DBL_MANT_DIG+1-DBL_MIN_EXP)+1
// The final +1s are a security margin. The current implementation of
// mpq_set_d seems to need it for the denominator.

inline void __mpz_set_ui_safe(mpz_ptr p, unsigned long l)
{
  p->_mp_size = (l != 0);
  p->_mp_d[0] = l & GMP_NUMB_MASK;
#if __GMPZ_ULI_LIMBS > 1
  l >>= GMP_NUMB_BITS;
  p->_mp_d[1] = l;
  p->_mp_size += (l != 0);
#endif
}

inline void __mpz_set_si_safe(mpz_ptr p, long l)
{
  if(l < 0)
  {
    __mpz_set_ui_safe(p, -static_cast<unsigned long>(l));
    mpz_neg(p, p);
  }
  else
    __mpz_set_ui_safe(p, l);
    // Note: we know the high bit of l is 0 so we could do slightly better
}

// Fake temporary variables
#define __GMPXX_TMPZ_UI       \
  mpz_t temp;        \
  mp_limb_t limbs[__GMPZ_ULI_LIMBS];     \
  temp->_mp_d = limbs;       \
  __mpz_set_ui_safe (temp, l)
#define __GMPXX_TMPZ_SI       \
  mpz_t temp;        \
  mp_limb_t limbs[__GMPZ_ULI_LIMBS];     \
  temp->_mp_d = limbs;       \
  __mpz_set_si_safe (temp, l)
#define __GMPXX_TMPZ_D       \
  mpz_t temp;        \
  mp_limb_t limbs[__GMPZ_DBL_LIMBS];     \
  temp->_mp_d = limbs;       \
  temp->_mp_alloc = __GMPZ_DBL_LIMBS;     \
  mpz_set_d (temp, d)

#define __GMPXX_TMPQ_UI       \
  mpq_t temp;        \
  mp_limb_t limbs[__GMPZ_ULI_LIMBS+1];     \
  mpq_numref(temp)->_mp_d = limbs;     \
  __mpz_set_ui_safe (mpq_numref(temp), l);    \
  mpq_denref(temp)->_mp_d = limbs + __GMPZ_ULI_LIMBS;   \
  mpq_denref(temp)->_mp_size = 1;     \
  mpq_denref(temp)->_mp_d[0] = 1
#define __GMPXX_TMPQ_SI       \
  mpq_t temp;        \
  mp_limb_t limbs[__GMPZ_ULI_LIMBS+1];     \
  mpq_numref(temp)->_mp_d = limbs;     \
  __mpz_set_si_safe (mpq_numref(temp), l);    \
  mpq_denref(temp)->_mp_d = limbs + __GMPZ_ULI_LIMBS;   \
  mpq_denref(temp)->_mp_size = 1;     \
  mpq_denref(temp)->_mp_d[0] = 1
#define __GMPXX_TMPQ_D       \
  mpq_t temp;        \
  mp_limb_t limbs[__GMPQ_NUM_DBL_LIMBS + __GMPQ_DEN_DBL_LIMBS];  \
  mpq_numref(temp)->_mp_d = limbs;     \
  mpq_numref(temp)->_mp_alloc = __GMPQ_NUM_DBL_LIMBS;   \
  mpq_denref(temp)->_mp_d = limbs + __GMPQ_NUM_DBL_LIMBS;  \
  mpq_denref(temp)->_mp_alloc = __GMPQ_DEN_DBL_LIMBS;   \
  mpq_set_d (temp, d)

inline unsigned long __gmpxx_abs_ui (signed long l)
{
  return l >= 0 ? static_cast<unsigned long>(l)
   : -static_cast<unsigned long>(l);
}

/**************** Function objects ****************/
/* Any evaluation of a __gmp_expr ends up calling one of these functions
   all intermediate functions being inline, the evaluation should optimize
   to a direct call to the relevant function, thus yielding no overhead
   over the C interface. */


struct __gmp_unary_plus
{
  static void eval(mpz_ptr z, mpz_srcptr w) { mpz_set(z, w); }
  static void eval(mpq_ptr q, mpq_srcptr r) { mpq_set(q, r); }
  static void eval(mpf_ptr f, mpf_srcptr g) { mpf_set(f, g); }
};

struct __gmp_unary_minus
{
  static void eval(mpz_ptr z, mpz_srcptr w) { mpz_neg(z, w); }
  static void eval(mpq_ptr q, mpq_srcptr r) { mpq_neg(q, r); }
  static void eval(mpf_ptr f, mpf_srcptr g) { mpf_neg(f, g); }
};

struct __gmp_unary_com
{
  static void eval(mpz_ptr z, mpz_srcptr w) { mpz_com(z, w); }
};

struct __gmp_binary_plus
{
  static void eval(mpz_ptr z, mpz_srcptr w, mpz_srcptr v)
  { mpz_add(z, w, v); }

  static void eval(mpz_ptr z, mpz_srcptr w, unsigned long int l)
  {
    // Ideally, those checks should happen earlier so that the tree
    // generated for a+0+b would just be sum(a,b).
    if (__GMPXX_CONSTANT(l) && l == 0)
    {
      if (z != w) mpz_set(z, w);
    }
    else
      mpz_add_ui(z, w, l);
  }
  static void eval(mpz_ptr z, unsigned long int l, mpz_srcptr w)
  { eval(z, w, l); }
  static void eval(mpz_ptr z, mpz_srcptr w, signed long int l)
  {
    if (l >= 0)
      eval(z, w, static_cast<unsigned long>(l));
    else
      mpz_sub_ui(z, w, -static_cast<unsigned long>(l));
  }
  static void eval(mpz_ptr z, signed long int l, mpz_srcptr w)
  { eval(z, w, l); }
  static void eval(mpz_ptr z, mpz_srcptr w, double d)
  {  __GMPXX_TMPZ_D;    mpz_add (z, w, temp); }
  static void eval(mpz_ptr z, double d, mpz_srcptr w)
  { eval(z, w, d); }

  static void eval(mpq_ptr q, mpq_srcptr r, mpq_srcptr s)
  { mpq_add(q, r, s); }

  static void eval(mpq_ptr q, mpq_srcptr r, unsigned long int l)
  {
    if (__GMPXX_CONSTANT(l) && l == 0)
    {
      if (q != r) mpq_set(q, r);
    }
    else if (__GMPXX_CONSTANT(l) && l == 1)
    {
      mpz_add (mpq_numref(q), mpq_numref(r), mpq_denref(r));
      if (q != r) mpz_set(mpq_denref(q), mpq_denref(r));
    }
    else
    {
      if (q == r)
        mpz_addmul_ui(mpq_numref(q), mpq_denref(q), l);
      else
      {
        mpz_mul_ui(mpq_numref(q), mpq_denref(r), l);
        mpz_add(mpq_numref(q), mpq_numref(q), mpq_numref(r));
        mpz_set(mpq_denref(q), mpq_denref(r));
      }
    }
  }
  static void eval(mpq_ptr q, unsigned long int l, mpq_srcptr r)
  { eval(q, r, l); }
  static inline void eval(mpq_ptr q, mpq_srcptr r, signed long int l);
  // defined after __gmp_binary_minus
  static void eval(mpq_ptr q, signed long int l, mpq_srcptr r)
  { eval(q, r, l); }
  static void eval(mpq_ptr q, mpq_srcptr r, double d)
  {  __GMPXX_TMPQ_D;    mpq_add (q, r, temp); }
  static void eval(mpq_ptr q, double d, mpq_srcptr r)
  { eval(q, r, d); }

  static void eval(mpq_ptr q, mpq_srcptr r, mpz_srcptr z)
  {
    if (q == r)
      mpz_addmul(mpq_numref(q), mpq_denref(q), z);
    else
    {
      mpz_mul(mpq_numref(q), mpq_denref(r), z);
      mpz_add(mpq_numref(q), mpq_numref(q), mpq_numref(r));
      mpz_set(mpq_denref(q), mpq_denref(r));
    }
  }
  static void eval(mpq_ptr q, mpz_srcptr z, mpq_srcptr r)
  { eval(q, r, z); }

  static void eval(mpf_ptr f, mpf_srcptr g, mpf_srcptr h)
  { mpf_add(f, g, h); }

  static void eval(mpf_ptr f, mpf_srcptr g, unsigned long int l)
  { mpf_add_ui(f, g, l); }
  static void eval(mpf_ptr f, unsigned long int l, mpf_srcptr g)
  { mpf_add_ui(f, g, l); }
  static void eval(mpf_ptr f, mpf_srcptr g, signed long int l)
  {
    if (l >= 0)
      mpf_add_ui(f, g, l);
    else
      mpf_sub_ui(f, g, -static_cast<unsigned long>(l));
  }
  static void eval(mpf_ptr f, signed long int l, mpf_srcptr g)
  { eval(f, g, l); }
  static void eval(mpf_ptr f, mpf_srcptr g, double d)
  {
    mpf_t temp;
    mpf_init2(temp, 8*sizeof(double));
    mpf_set_d(temp, d);
    mpf_add(f, g, temp);
    mpf_clear(temp);
  }
  static void eval(mpf_ptr f, double d, mpf_srcptr g)
  { eval(f, g, d); }
};

struct __gmp_binary_minus
{
  static void eval(mpz_ptr z, mpz_srcptr w, mpz_srcptr v)
  { mpz_sub(z, w, v); }

  static void eval(mpz_ptr z, mpz_srcptr w, unsigned long int l)
  {
    if (__GMPXX_CONSTANT(l) && l == 0)
    {
      if (z != w) mpz_set(z, w);
    }
    else
      mpz_sub_ui(z, w, l);
  }
  static void eval(mpz_ptr z, unsigned long int l, mpz_srcptr w)
  {
    if (__GMPXX_CONSTANT(l) && l == 0)
    {
      mpz_neg(z, w);
    }
    else
      mpz_ui_sub(z, l, w);
  }
  static void eval(mpz_ptr z, mpz_srcptr w, signed long int l)
  {
    if (l >= 0)
      eval(z, w, static_cast<unsigned long>(l));
    else
      mpz_add_ui(z, w, -static_cast<unsigned long>(l));
  }
  static void eval(mpz_ptr z, signed long int l, mpz_srcptr w)
  {
    if (l >= 0)
      eval(z, static_cast<unsigned long>(l), w);
    else
      {
        mpz_add_ui(z, w, -static_cast<unsigned long>(l));
        mpz_neg(z, z);
      }
  }
  static void eval(mpz_ptr z, mpz_srcptr w, double d)
  {  __GMPXX_TMPZ_D;    mpz_sub (z, w, temp); }
  static void eval(mpz_ptr z, double d, mpz_srcptr w)
  {  __GMPXX_TMPZ_D;    mpz_sub (z, temp, w); }

  static void eval(mpq_ptr q, mpq_srcptr r, mpq_srcptr s)
  { mpq_sub(q, r, s); }

  static void eval(mpq_ptr q, mpq_srcptr r, unsigned long int l)
  {
    if (__GMPXX_CONSTANT(l) && l == 0)
    {
      if (q != r) mpq_set(q, r);
    }
    else if (__GMPXX_CONSTANT(l) && l == 1)
    {
      mpz_sub (mpq_numref(q), mpq_numref(r), mpq_denref(r));
      if (q != r) mpz_set(mpq_denref(q), mpq_denref(r));
    }
    else
    {
      if (q == r)
        mpz_submul_ui(mpq_numref(q), mpq_denref(q), l);
      else
      {
        mpz_mul_ui(mpq_numref(q), mpq_denref(r), l);
        mpz_sub(mpq_numref(q), mpq_numref(r), mpq_numref(q));
        mpz_set(mpq_denref(q), mpq_denref(r));
      }
    }
  }
  static void eval(mpq_ptr q, unsigned long int l, mpq_srcptr r)
  { eval(q, r, l); mpq_neg(q, q); }
  static void eval(mpq_ptr q, mpq_srcptr r, signed long int l)
  {
    if (l >= 0)
      eval(q, r, static_cast<unsigned long>(l));
    else
      __gmp_binary_plus::eval(q, r, -static_cast<unsigned long>(l));
  }
  static void eval(mpq_ptr q, signed long int l, mpq_srcptr r)
  { eval(q, r, l); mpq_neg(q, q); }
  static void eval(mpq_ptr q, mpq_srcptr r, double d)
  {  __GMPXX_TMPQ_D;    mpq_sub (q, r, temp); }
  static void eval(mpq_ptr q, double d, mpq_srcptr r)
  {  __GMPXX_TMPQ_D;    mpq_sub (q, temp, r); }

  static void eval(mpq_ptr q, mpq_srcptr r, mpz_srcptr z)
  {
    if (q == r)
      mpz_submul(mpq_numref(q), mpq_denref(q), z);
    else
    {
      mpz_mul(mpq_numref(q), mpq_denref(r), z);
      mpz_sub(mpq_numref(q), mpq_numref(r), mpq_numref(q));
      mpz_set(mpq_denref(q), mpq_denref(r));
    }
  }
  static void eval(mpq_ptr q, mpz_srcptr z, mpq_srcptr r)
  { eval(q, r, z); mpq_neg(q, q); }

  static void eval(mpf_ptr f, mpf_srcptr g, mpf_srcptr h)
  { mpf_sub(f, g, h); }

  static void eval(mpf_ptr f, mpf_srcptr g, unsigned long int l)
  { mpf_sub_ui(f, g, l); }
  static void eval(mpf_ptr f, unsigned long int l, mpf_srcptr g)
  { mpf_ui_sub(f, l, g); }
  static void eval(mpf_ptr f, mpf_srcptr g, signed long int l)
  {
    if (l >= 0)
      mpf_sub_ui(f, g, l);
    else
      mpf_add_ui(f, g, -static_cast<unsigned long>(l));
  }
  static void eval(mpf_ptr f, signed long int l, mpf_srcptr g)
  {
    if (l >= 0)
      mpf_sub_ui(f, g, l);
    else
      mpf_add_ui(f, g, -static_cast<unsigned long>(l));
    mpf_neg(f, f);
  }
  static void eval(mpf_ptr f, mpf_srcptr g, double d)
  {
    mpf_t temp;
    mpf_init2(temp, 8*sizeof(double));
    mpf_set_d(temp, d);
    mpf_sub(f, g, temp);
    mpf_clear(temp);
  }
  static void eval(mpf_ptr f, double d, mpf_srcptr g)
  {
    mpf_t temp;
    mpf_init2(temp, 8*sizeof(double));
    mpf_set_d(temp, d);
    mpf_sub(f, temp, g);
    mpf_clear(temp);
  }
};

// defined here so it can reference __gmp_binary_minus
inline void
__gmp_binary_plus::eval(mpq_ptr q, mpq_srcptr r, signed long int l)
{
  if (l >= 0)
    eval(q, r, static_cast<unsigned long>(l));
  else
    __gmp_binary_minus::eval(q, r, -static_cast<unsigned long>(l));
}

struct __gmp_binary_lshift
{
  static void eval(mpz_ptr z, mpz_srcptr w, mp_bitcnt_t l)
  {
    if (__GMPXX_CONSTANT(l) && (l == 0))
    {
      if (z != w) mpz_set(z, w);
    }
    else
      mpz_mul_2exp(z, w, l);
  }
  static void eval(mpq_ptr q, mpq_srcptr r, mp_bitcnt_t l)
  {
    if (__GMPXX_CONSTANT(l) && (l == 0))
    {
      if (q != r) mpq_set(q, r);
    }
    else
      mpq_mul_2exp(q, r, l);
  }
  static void eval(mpf_ptr f, mpf_srcptr g, mp_bitcnt_t l)
  { mpf_mul_2exp(f, g, l); }
};

struct __gmp_binary_rshift
{
  static void eval(mpz_ptr z, mpz_srcptr w, mp_bitcnt_t l)
  {
    if (__GMPXX_CONSTANT(l) && (l == 0))
    {
      if (z != w) mpz_set(z, w);
    }
    else
      mpz_fdiv_q_2exp(z, w, l);
  }
  static void eval(mpq_ptr q, mpq_srcptr r, mp_bitcnt_t l)
  {
    if (__GMPXX_CONSTANT(l) && (l == 0))
    {
      if (q != r) mpq_set(q, r);
    }
    else
      mpq_div_2exp(q, r, l);
  }
  static void eval(mpf_ptr f, mpf_srcptr g, mp_bitcnt_t l)
  { mpf_div_2exp(f, g, l); }
};

struct __gmp_binary_multiplies
{
  static void eval(mpz_ptr z, mpz_srcptr w, mpz_srcptr v)
  { mpz_mul(z, w, v); }

  static void eval(mpz_ptr z, mpz_srcptr w, unsigned long int l)
  {
// gcc-3.3 doesn't have __builtin_ctzl. Don't bother optimizing for old gcc.
#if __GMP_GNUC_PREREQ(3, 4)
    if (__GMPXX_CONSTANT(l) && (l & (l-1)) == 0)
    {
      if (l == 0)
      {
        z->_mp_size = 0;
      }
      else
      {
        __gmp_binary_lshift::eval(z, w, __builtin_ctzl(l));
      }
    }
    else
#endif
      mpz_mul_ui(z, w, l);
  }
  static void eval(mpz_ptr z, unsigned long int l, mpz_srcptr w)
  { eval(z, w, l); }
  static void eval(mpz_ptr z, mpz_srcptr w, signed long int l)
  {
    if (__GMPXX_CONSTANT_TRUE(l >= 0))
      eval(z, w, static_cast<unsigned long>(l));
    else if (__GMPXX_CONSTANT_TRUE(l <= 0))
      {
        eval(z, w, -static_cast<unsigned long>(l));
 mpz_neg(z, z);
      }
    else
      mpz_mul_si (z, w, l);
  }
  static void eval(mpz_ptr z, signed long int l, mpz_srcptr w)
  { eval(z, w, l); }
  static void eval(mpz_ptr z, mpz_srcptr w, double d)
  {  __GMPXX_TMPZ_D;    mpz_mul (z, w, temp); }
  static void eval(mpz_ptr z, double d, mpz_srcptr w)
  { eval(z, w, d); }

  static void eval(mpq_ptr q, mpq_srcptr r, mpq_srcptr s)
  { mpq_mul(q, r, s); }

  static void eval(mpq_ptr q, mpq_srcptr r, unsigned long int l)
  {
#if __GMP_GNUC_PREREQ(3, 4)
    if (__GMPXX_CONSTANT(l) && (l & (l-1)) == 0)
    {
      if (l == 0)
      {
 mpq_set_ui(q, 0, 1);
      }
      else
      {
        __gmp_binary_lshift::eval(q, r, __builtin_ctzl(l));
      }
    }
    else
#endif
    {
      __GMPXX_TMPQ_UI;
      mpq_mul (q, r, temp);
    }
  }
  static void eval(mpq_ptr q, unsigned long int l, mpq_srcptr r)
  { eval(q, r, l); }
  static void eval(mpq_ptr q, mpq_srcptr r, signed long int l)
  {
    if (__GMPXX_CONSTANT_TRUE(l >= 0))
      eval(q, r, static_cast<unsigned long>(l));
    else if (__GMPXX_CONSTANT_TRUE(l <= 0))
      {
        eval(q, r, -static_cast<unsigned long>(l));
 mpq_neg(q, q);
      }
    else
      {
 __GMPXX_TMPQ_SI;
 mpq_mul (q, r, temp);
      }
  }
  static void eval(mpq_ptr q, signed long int l, mpq_srcptr r)
  { eval(q, r, l); }
  static void eval(mpq_ptr q, mpq_srcptr r, double d)
  {  __GMPXX_TMPQ_D;    mpq_mul (q, r, temp); }
  static void eval(mpq_ptr q, double d, mpq_srcptr r)
  { eval(q, r, d); }

  static void eval(mpf_ptr f, mpf_srcptr g, mpf_srcptr h)
  { mpf_mul(f, g, h); }

  static void eval(mpf_ptr f, mpf_srcptr g, unsigned long int l)
  { mpf_mul_ui(f, g, l); }
  static void eval(mpf_ptr f, unsigned long int l, mpf_srcptr g)
  { mpf_mul_ui(f, g, l); }
  static void eval(mpf_ptr f, mpf_srcptr g, signed long int l)
  {
    if (l >= 0)
      mpf_mul_ui(f, g, l);
    else
      {
 mpf_mul_ui(f, g, -static_cast<unsigned long>(l));
 mpf_neg(f, f);
      }
  }
  static void eval(mpf_ptr f, signed long int l, mpf_srcptr g)
  { eval(f, g, l); }
  static void eval(mpf_ptr f, mpf_srcptr g, double d)
  {
    mpf_t temp;
    mpf_init2(temp, 8*sizeof(double));
    mpf_set_d(temp, d);
    mpf_mul(f, g, temp);
    mpf_clear(temp);
  }
  static void eval(mpf_ptr f, double d, mpf_srcptr g)
  { eval(f, g, d); }
};

struct __gmp_binary_divides
{
  static void eval(mpz_ptr z, mpz_srcptr w, mpz_srcptr v)
  { mpz_tdiv_q(z, w, v); }

  static void eval(mpz_ptr z, mpz_srcptr w, unsigned long int l)
  {
#if __GMP_GNUC_PREREQ(3, 4)
    // Don't optimize division by 0...
    if (__GMPXX_CONSTANT(l) && (l & (l-1)) == 0 && l != 0)
    {
      if (l == 1)
      {
        if (z != w) mpz_set(z, w);
      }
      else
        mpz_tdiv_q_2exp(z, w, __builtin_ctzl(l));
        // warning: do not use rshift (fdiv)
    }
    else
#endif
      mpz_tdiv_q_ui(z, w, l);
  }
  static void eval(mpz_ptr z, unsigned long int l, mpz_srcptr w)
  {
    if (mpz_sgn(w) >= 0)
      {
 if (mpz_fits_ulong_p(w))
   mpz_set_ui(z, l / mpz_get_ui(w));
 else
   mpz_set_ui(z, 0);
      }
    else
      {
 mpz_neg(z, w);
 if (mpz_fits_ulong_p(z))
   {
     mpz_set_ui(z, l / mpz_get_ui(z));
     mpz_neg(z, z);
   }
 else
   mpz_set_ui(z, 0);
      }
  }
  static void eval(mpz_ptr z, mpz_srcptr w, signed long int l)
  {
    if (l >= 0)
      eval(z, w, static_cast<unsigned long>(l));
    else
      {
 eval(z, w, -static_cast<unsigned long>(l));
 mpz_neg(z, z);
      }
  }
  static void eval(mpz_ptr z, signed long int l, mpz_srcptr w)
  {
    if (mpz_fits_slong_p(w))
      mpz_set_si(z, l / mpz_get_si(w));
    else
      {
        /* if w is bigger than a long then the quotient must be zero, unless
           l==LONG_MIN and w==-LONG_MIN in which case the quotient is -1 */

        mpz_set_si (z, (mpz_cmpabs_ui (w, __gmpxx_abs_ui(l)) == 0 ? -1 : 0));
      }
  }
  static void eval(mpz_ptr z, mpz_srcptr w, double d)
  {  __GMPXX_TMPZ_D;    mpz_tdiv_q (z, w, temp); }
  static void eval(mpz_ptr z, double d, mpz_srcptr w)
  {  __GMPXX_TMPZ_D;    mpz_tdiv_q (z, temp, w); }

  static void eval(mpq_ptr q, mpq_srcptr r, mpq_srcptr s)
  { mpq_div(q, r, s); }

  static void eval(mpq_ptr q, mpq_srcptr r, unsigned long int l)
  {
#if __GMP_GNUC_PREREQ(3, 4)
    if (__GMPXX_CONSTANT(l) && (l & (l-1)) == 0 && l != 0)
      __gmp_binary_rshift::eval(q, r, __builtin_ctzl(l));
    else
#endif
    {
      __GMPXX_TMPQ_UI;
      mpq_div (q, r, temp);
    }
  }
  static void eval(mpq_ptr q, unsigned long int l, mpq_srcptr r)
  {
    if (__GMPXX_CONSTANT_TRUE(l == 0))
      mpq_set_ui(q, 0, 1);
    else if (__GMPXX_CONSTANT_TRUE(l == 1))
      mpq_inv(q, r);
    else
      {
 __GMPXX_TMPQ_UI;
 mpq_div (q, temp, r);
      }
  }
  static void eval(mpq_ptr q, mpq_srcptr r, signed long int l)
  {
    if (__GMPXX_CONSTANT_TRUE(l >= 0))
      eval(q, r, static_cast<unsigned long>(l));
    else if (__GMPXX_CONSTANT_TRUE(l <= 0))
      {
        eval(q, r, -static_cast<unsigned long>(l));
 mpq_neg(q, q);
      }
    else
      {
 __GMPXX_TMPQ_SI;
 mpq_div (q, r, temp);
      }
  }
  static void eval(mpq_ptr q, signed long int l, mpq_srcptr r)
  {
    if (__GMPXX_CONSTANT_TRUE(l == 0))
      mpq_set_ui(q, 0, 1);
    else if (__GMPXX_CONSTANT_TRUE(l == 1))
      mpq_inv(q, r);
    else if (__GMPXX_CONSTANT_TRUE(l == -1))
      {
 mpq_inv(q, r);
 mpq_neg(q, q);
      }
    else
      {
 __GMPXX_TMPQ_SI;
 mpq_div (q, temp, r);
      }
  }
  static void eval(mpq_ptr q, mpq_srcptr r, double d)
  {  __GMPXX_TMPQ_D;    mpq_div (q, r, temp); }
  static void eval(mpq_ptr q, double d, mpq_srcptr r)
  {  __GMPXX_TMPQ_D;    mpq_div (q, temp, r); }

  static void eval(mpf_ptr f, mpf_srcptr g, mpf_srcptr h)
  { mpf_div(f, g, h); }

  static void eval(mpf_ptr f, mpf_srcptr g, unsigned long int l)
  { mpf_div_ui(f, g, l); }
  static void eval(mpf_ptr f, unsigned long int l, mpf_srcptr g)
  { mpf_ui_div(f, l, g); }
  static void eval(mpf_ptr f, mpf_srcptr g, signed long int l)
  {
    if (l >= 0)
      mpf_div_ui(f, g, l);
    else
      {
 mpf_div_ui(f, g, -static_cast<unsigned long>(l));
 mpf_neg(f, f);
      }
  }
  static void eval(mpf_ptr f, signed long int l, mpf_srcptr g)
  {
    if (l >= 0)
      mpf_ui_div(f, l, g);
    else
      {
 mpf_ui_div(f, -static_cast<unsigned long>(l), g);
 mpf_neg(f, f);
      }
  }
  static void eval(mpf_ptr f, mpf_srcptr g, double d)
  {
    mpf_t temp;
    mpf_init2(temp, 8*sizeof(double));
    mpf_set_d(temp, d);
    mpf_div(f, g, temp);
    mpf_clear(temp);
  }
  static void eval(mpf_ptr f, double d, mpf_srcptr g)
  {
    mpf_t temp;
    mpf_init2(temp, 8*sizeof(double));
    mpf_set_d(temp, d);
    mpf_div(f, temp, g);
    mpf_clear(temp);
  }
};

struct __gmp_binary_modulus
{
  static void eval(mpz_ptr z, mpz_srcptr w, mpz_srcptr v)
  { mpz_tdiv_r(z, w, v); }

  static void eval(mpz_ptr z, mpz_srcptr w, unsigned long int l)
  { mpz_tdiv_r_ui(z, w, l); }
  static void eval(mpz_ptr z, unsigned long int l, mpz_srcptr w)
  {
    if (mpz_sgn(w) >= 0)
      {
 if (mpz_fits_ulong_p(w))
   mpz_set_ui(z, l % mpz_get_ui(w));
 else
   mpz_set_ui(z, l);
      }
    else
      {
 mpz_neg(z, w);
 if (mpz_fits_ulong_p(z))
   mpz_set_ui(z, l % mpz_get_ui(z));
 else
   mpz_set_ui(z, l);
      }
  }
  static void eval(mpz_ptr z, mpz_srcptr w, signed long int l)
  {
    mpz_tdiv_r_ui (z, w, __gmpxx_abs_ui(l));
  }
  static void eval(mpz_ptr z, signed long int l, mpz_srcptr w)
  {
    if (mpz_fits_slong_p(w))
      mpz_set_si(z, l % mpz_get_si(w));
    else
      {
        /* if w is bigger than a long then the remainder is l unchanged,
           unless l==LONG_MIN and w==-LONG_MIN in which case it's 0 */

        mpz_set_si (z, mpz_cmpabs_ui (w, __gmpxx_abs_ui(l)) == 0 ? 0 : l);
      }
  }
  static void eval(mpz_ptr z, mpz_srcptr w, double d)
  {  __GMPXX_TMPZ_D;    mpz_tdiv_r (z, w, temp); }
  static void eval(mpz_ptr z, double d, mpz_srcptr w)
  {  __GMPXX_TMPZ_D;    mpz_tdiv_r (z, temp, w); }
};

struct __gmp_binary_and
{
  static void eval(mpz_ptr z, mpz_srcptr w, mpz_srcptr v)
  { mpz_and(z, w, v); }

  static void eval(mpz_ptr z, mpz_srcptr w, unsigned long int l)
  {  __GMPXX_TMPZ_UI;   mpz_and (z, w, temp);  }
  static void eval(mpz_ptr z, unsigned long int l, mpz_srcptr w)
  { eval(z, w, l);  }
  static void eval(mpz_ptr z, mpz_srcptr w, signed long int l)
  {  __GMPXX_TMPZ_SI;   mpz_and (z, w, temp);  }
  static void eval(mpz_ptr z, signed long int l, mpz_srcptr w)
  { eval(z, w, l);  }
  static void eval(mpz_ptr z, mpz_srcptr w, double d)
  {  __GMPXX_TMPZ_D;    mpz_and (z, w, temp); }
  static void eval(mpz_ptr z, double d, mpz_srcptr w)
  { eval(z, w, d);  }
};

struct __gmp_binary_ior
{
  static void eval(mpz_ptr z, mpz_srcptr w, mpz_srcptr v)
  { mpz_ior(z, w, v); }
  static void eval(mpz_ptr z, mpz_srcptr w, unsigned long int l)
  {  __GMPXX_TMPZ_UI;   mpz_ior (z, w, temp);  }
  static void eval(mpz_ptr z, unsigned long int l, mpz_srcptr w)
  { eval(z, w, l);  }
  static void eval(mpz_ptr z, mpz_srcptr w, signed long int l)
  {  __GMPXX_TMPZ_SI;   mpz_ior (z, w, temp);  }
  static void eval(mpz_ptr z, signed long int l, mpz_srcptr w)
  { eval(z, w, l);  }
  static void eval(mpz_ptr z, mpz_srcptr w, double d)
  {  __GMPXX_TMPZ_D;    mpz_ior (z, w, temp); }
  static void eval(mpz_ptr z, double d, mpz_srcptr w)
  { eval(z, w, d);  }
};

struct __gmp_binary_xor
{
  static void eval(mpz_ptr z, mpz_srcptr w, mpz_srcptr v)
  { mpz_xor(z, w, v); }
  static void eval(mpz_ptr z, mpz_srcptr w, unsigned long int l)
  {  __GMPXX_TMPZ_UI;   mpz_xor (z, w, temp);  }
  static void eval(mpz_ptr z, unsigned long int l, mpz_srcptr w)
  { eval(z, w, l);  }
  static void eval(mpz_ptr z, mpz_srcptr w, signed long int l)
  {  __GMPXX_TMPZ_SI;   mpz_xor (z, w, temp);  }
  static void eval(mpz_ptr z, signed long int l, mpz_srcptr w)
  { eval(z, w, l);  }
  static void eval(mpz_ptr z, mpz_srcptr w, double d)
  {  __GMPXX_TMPZ_D;    mpz_xor (z, w, temp); }
  static void eval(mpz_ptr z, double d, mpz_srcptr w)
  { eval(z, w, d);  }
};

struct __gmp_cmp_function
{
  static int eval(mpz_srcptr z, mpz_srcptr w) { return mpz_cmp(z, w); }

  static int eval(mpz_srcptr z, unsigned long int l)
  { return mpz_cmp_ui(z, l); }
  static int eval(unsigned long int l, mpz_srcptr z)
  { return -mpz_cmp_ui(z, l); }
  static int eval(mpz_srcptr z, signed long int l)
  { return mpz_cmp_si(z, l); }
  static int eval(signed long int l, mpz_srcptr z)
  { return -mpz_cmp_si(z, l); }
  static int eval(mpz_srcptr z, double d)
  { return mpz_cmp_d(z, d); }
  static int eval(double d, mpz_srcptr z)
  { return -mpz_cmp_d(z, d); }

  static int eval(mpq_srcptr q, mpq_srcptr r) { return mpq_cmp(q, r); }

  static int eval(mpq_srcptr q, unsigned long int l)
  { return mpq_cmp_ui(q, l, 1); }
  static int eval(unsigned long int l, mpq_srcptr q)
  { return -mpq_cmp_ui(q, l, 1); }
  static int eval(mpq_srcptr q, signed long int l)
  { return mpq_cmp_si(q, l, 1); }
  static int eval(signed long int l, mpq_srcptr q)
  { return -mpq_cmp_si(q, l, 1); }
  static int eval(mpq_srcptr q, double d)
  {  __GMPXX_TMPQ_D;    return mpq_cmp (q, temp); }
  static int eval(double d, mpq_srcptr q)
  {  __GMPXX_TMPQ_D;    return mpq_cmp (temp, q); }
  static int eval(mpq_srcptr q, mpz_srcptr z)
  { return mpq_cmp_z(q, z); }
  static int eval(mpz_srcptr z, mpq_srcptr q)
  { return -mpq_cmp_z(q, z); }

  static int eval(mpf_srcptr f, mpf_srcptr g) { return mpf_cmp(f, g); }

  static int eval(mpf_srcptr f, unsigned long int l)
  { return mpf_cmp_ui(f, l); }
  static int eval(unsigned long int l, mpf_srcptr f)
  { return -mpf_cmp_ui(f, l); }
  static int eval(mpf_srcptr f, signed long int l)
  { return mpf_cmp_si(f, l); }
  static int eval(signed long int l, mpf_srcptr f)
  { return -mpf_cmp_si(f, l); }
  static int eval(mpf_srcptr f, double d)
  { return mpf_cmp_d(f, d); }
  static int eval(double d, mpf_srcptr f)
  { return -mpf_cmp_d(f, d); }
  static int eval(mpf_srcptr f, mpz_srcptr z)
  { return mpf_cmp_z(f, z); }
  static int eval(mpz_srcptr z, mpf_srcptr f)
  { return -mpf_cmp_z(f, z); }
  static int eval(mpf_srcptr f, mpq_srcptr q)
  {
    mpf_t qf;
    mpf_init(qf); /* Should we use the precision of f?  */
    mpf_set_q(qf, q);
    int ret = eval(f, qf);
    mpf_clear(qf);
    return ret;
  }
  static int eval(mpq_srcptr q, mpf_srcptr f)
  { return -eval(f, q); }
};

struct __gmp_binary_equal
{
  static bool eval(mpz_srcptr z, mpz_srcptr w) { return mpz_cmp(z, w) == 0; }

  static bool eval(mpz_srcptr z, unsigned long int l)
  { return mpz_cmp_ui(z, l) == 0; }
  static bool eval(unsigned long int l, mpz_srcptr z)
  { return eval(z, l); }
  static bool eval(mpz_srcptr z, signed long int l)
  { return mpz_cmp_si(z, l) == 0; }
  static bool eval(signed long int l, mpz_srcptr z)
  { return eval(z, l); }
  static bool eval(mpz_srcptr z, double d)
  { return mpz_cmp_d(z, d) == 0; }
  static bool eval(double d, mpz_srcptr z)
  { return eval(z, d); }

  static bool eval(mpq_srcptr q, mpq_srcptr r)
  { return mpq_equal(q, r) != 0; }

  static bool eval(mpq_srcptr q, unsigned long int l)
  { return ((__GMPXX_CONSTANT(l) && l == 0) ||
     mpz_cmp_ui(mpq_denref(q), 1) == 0) &&
      mpz_cmp_ui(mpq_numref(q), l) == 0; }
  static bool eval(unsigned long int l, mpq_srcptr q)
  { return eval(q, l); }
  static bool eval(mpq_srcptr q, signed long int l)
  { return ((__GMPXX_CONSTANT(l) && l == 0) ||
     mpz_cmp_ui(mpq_denref(q), 1) == 0) &&
      mpz_cmp_si(mpq_numref(q), l) == 0; }
  static bool eval(signed long int l, mpq_srcptr q)
  { return eval(q, l); }
  static bool eval(mpq_srcptr q, double d)
  {  __GMPXX_TMPQ_D;    return mpq_equal (q, temp) != 0; }
  static bool eval(double d, mpq_srcptr q)
  { return eval(q, d); }
  static bool eval(mpq_srcptr q, mpz_srcptr z)
  { return mpz_cmp_ui(mpq_denref(q), 1) == 0 && mpz_cmp(mpq_numref(q), z) == 0; }
  static bool eval(mpz_srcptr z, mpq_srcptr q)
  { return eval(q, z); }

  static bool eval(mpf_srcptr f, mpf_srcptr g) { return mpf_cmp(f, g) == 0; }

  static bool eval(mpf_srcptr f, unsigned long int l)
  { return mpf_cmp_ui(f, l) == 0; }
  static bool eval(unsigned long int l, mpf_srcptr f)
  { return eval(f, l); }
  static bool eval(mpf_srcptr f, signed long int l)
  { return mpf_cmp_si(f, l) == 0; }
  static bool eval(signed long int l, mpf_srcptr f)
  { return eval(f, l); }
  static bool eval(mpf_srcptr f, double d)
  { return mpf_cmp_d(f, d) == 0; }
  static bool eval(double d, mpf_srcptr f)
  { return eval(f, d); }
  static bool eval(mpf_srcptr f, mpz_srcptr z)
  { return mpf_cmp_z(f, z) == 0; }
  static bool eval(mpz_srcptr z, mpf_srcptr f)
  { return eval(f, z); }
  static bool eval(mpf_srcptr f, mpq_srcptr q)
  { return __gmp_cmp_function::eval(f, q) == 0; }
  static bool eval(mpq_srcptr q, mpf_srcptr f)
  { return eval(f, q); }
};

struct __gmp_binary_less
{
  static bool eval(mpz_srcptr z, mpz_srcptr w) { return mpz_cmp(z, w) < 0; }

  static bool eval(mpz_srcptr z, unsigned long int l)
  { return mpz_cmp_ui(z, l) < 0; }
  static bool eval(unsigned long int l, mpz_srcptr z)
  { return mpz_cmp_ui(z, l) > 0; }
  static bool eval(mpz_srcptr z, signed long int l)
  { return mpz_cmp_si(z, l) < 0; }
  static bool eval(signed long int l, mpz_srcptr z)
  { return mpz_cmp_si(z, l) > 0; }
  static bool eval(mpz_srcptr z, double d)
  { return mpz_cmp_d(z, d) < 0; }
  static bool eval(double d, mpz_srcptr z)
  { return mpz_cmp_d(z, d) > 0; }

  static bool eval(mpq_srcptr q, mpq_srcptr r) { return mpq_cmp(q, r) < 0; }

  static bool eval(mpq_srcptr q, unsigned long int l)
  { return mpq_cmp_ui(q, l, 1) < 0; }
  static bool eval(unsigned long int l, mpq_srcptr q)
  { return mpq_cmp_ui(q, l, 1) > 0; }
  static bool eval(mpq_srcptr q, signed long int l)
  { return mpq_cmp_si(q, l, 1) < 0; }
  static bool eval(signed long int l, mpq_srcptr q)
  { return mpq_cmp_si(q, l, 1) > 0; }
  static bool eval(mpq_srcptr q, double d)
  {  __GMPXX_TMPQ_D;    return mpq_cmp (q, temp) < 0; }
  static bool eval(double d, mpq_srcptr q)
  {  __GMPXX_TMPQ_D;    return mpq_cmp (temp, q) < 0; }
  static bool eval(mpq_srcptr q, mpz_srcptr z)
  { return mpq_cmp_z(q, z) < 0; }
  static bool eval(mpz_srcptr z, mpq_srcptr q)
  { return mpq_cmp_z(q, z) > 0; }

  static bool eval(mpf_srcptr f, mpf_srcptr g) { return mpf_cmp(f, g) < 0; }

  static bool eval(mpf_srcptr f, unsigned long int l)
  { return mpf_cmp_ui(f, l) < 0; }
  static bool eval(unsigned long int l, mpf_srcptr f)
  { return mpf_cmp_ui(f, l) > 0; }
  static bool eval(mpf_srcptr f, signed long int l)
  { return mpf_cmp_si(f, l) < 0; }
  static bool eval(signed long int l, mpf_srcptr f)
  { return mpf_cmp_si(f, l) > 0; }
  static bool eval(mpf_srcptr f, double d)
  { return mpf_cmp_d(f, d) < 0; }
  static bool eval(double d, mpf_srcptr f)
  { return mpf_cmp_d(f, d) > 0; }
  static bool eval(mpf_srcptr f, mpz_srcptr z)
  { return mpf_cmp_z(f, z) < 0; }
  static bool eval(mpz_srcptr z, mpf_srcptr f)
  { return mpf_cmp_z(f, z) > 0; }
  static bool eval(mpf_srcptr f, mpq_srcptr q)
  { return __gmp_cmp_function::eval(f, q) < 0; }
  static bool eval(mpq_srcptr q, mpf_srcptr f)
  { return __gmp_cmp_function::eval(q, f) < 0; }
};

struct __gmp_binary_greater
{
  template <class T, class U>
  static inline bool eval(T t, U u) { return __gmp_binary_less::eval(u, t); }
};

struct __gmp_unary_increment
{
  static void eval(mpz_ptr z) { mpz_add_ui(z, z, 1); }
  static void eval(mpq_ptr q)
  { mpz_add(mpq_numref(q), mpq_numref(q), mpq_denref(q)); }
  static void eval(mpf_ptr f) { mpf_add_ui(f, f, 1); }
};

struct __gmp_unary_decrement
{
  static void eval(mpz_ptr z) { mpz_sub_ui(z, z, 1); }
  static void eval(mpq_ptr q)
  { mpz_sub(mpq_numref(q), mpq_numref(q), mpq_denref(q)); }
  static void eval(mpf_ptr f) { mpf_sub_ui(f, f, 1); }
};

struct __gmp_abs_function
{
  static void eval(mpz_ptr z, mpz_srcptr w) { mpz_abs(z, w); }
  static void eval(mpq_ptr q, mpq_srcptr r) { mpq_abs(q, r); }
  static void eval(mpf_ptr f, mpf_srcptr g) { mpf_abs(f, g); }
};

struct __gmp_trunc_function
{
  static void eval(mpf_ptr f, mpf_srcptr g) { mpf_trunc(f, g); }
};

struct __gmp_floor_function
{
  static void eval(mpf_ptr f, mpf_srcptr g) { mpf_floor(f, g); }
};

struct __gmp_ceil_function
{
  static void eval(mpf_ptr f, mpf_srcptr g) { mpf_ceil(f, g); }
};

struct __gmp_sqrt_function
{
  static void eval(mpz_ptr z, mpz_srcptr w) { mpz_sqrt(z, w); }
  static void eval(mpf_ptr f, mpf_srcptr g) { mpf_sqrt(f, g); }
};

struct __gmp_hypot_function
{
  static void eval(mpf_ptr f, mpf_srcptr g, mpf_srcptr h)
  {
    mpf_t temp;
    mpf_init2(temp, mpf_get_prec(f));
    mpf_mul(temp, g, g);
    mpf_mul(f, h, h);
    mpf_add(f, f, temp);
    mpf_sqrt(f, f);
    mpf_clear(temp);
  }

  static void eval(mpf_ptr f, mpf_srcptr g, unsigned long int l)
  {
    mpf_t temp;
    mpf_init2(temp, mpf_get_prec(f));
    mpf_mul(temp, g, g);
    mpf_set_ui(f, l);
    mpf_mul_ui(f, f, l);
    mpf_add(f, f, temp);
    mpf_clear(temp);
    mpf_sqrt(f, f);
  }
  static void eval(mpf_ptr f, unsigned long int l, mpf_srcptr g)
  { eval(f, g, l); }
  static void eval(mpf_ptr f, mpf_srcptr g, signed long int l)
  { eval(f, g, __gmpxx_abs_ui(l)); }
  static void eval(mpf_ptr f, signed long int l, mpf_srcptr g)
  { eval(f, g, l); }
  static void eval(mpf_ptr f, mpf_srcptr g, double d)
  {
    mpf_t temp;
    mpf_init2(temp, mpf_get_prec(f));
    mpf_mul(temp, g, g);
    mpf_set_d(f, d);
    mpf_mul(f, f, f);
    mpf_add(f, f, temp);
    mpf_sqrt(f, f);
    mpf_clear(temp);
  }
  static void eval(mpf_ptr f, double d, mpf_srcptr g)
  { eval(f, g, d); }
};

struct __gmp_sgn_function
{
  static int eval(mpz_srcptr z) { return mpz_sgn(z); }
  static int eval(mpq_srcptr q) { return mpq_sgn(q); }
  static int eval(mpf_srcptr f) { return mpf_sgn(f); }
};

struct __gmp_gcd_function
{
  static void eval(mpz_ptr z, mpz_srcptr w, mpz_srcptr v)
  { mpz_gcd(z, w, v); }
  static void eval(mpz_ptr z, mpz_srcptr w, unsigned long int l)
  { mpz_gcd_ui(z, w, l); }
  static void eval(mpz_ptr z, unsigned long int l, mpz_srcptr w)
  { eval(z, w, l); }
  static void eval(mpz_ptr z, mpz_srcptr w, signed long int l)
  { eval(z, w, __gmpxx_abs_ui(l)); }
  static void eval(mpz_ptr z, signed long int l, mpz_srcptr w)
  { eval(z, w, l); }
  static void eval(mpz_ptr z, mpz_srcptr w, double d)
  {  __GMPXX_TMPZ_D;    mpz_gcd (z, w, temp); }
  static void eval(mpz_ptr z, double d, mpz_srcptr w)
  { eval(z, w, d); }
};

struct __gmp_lcm_function
{
  static void eval(mpz_ptr z, mpz_srcptr w, mpz_srcptr v)
  { mpz_lcm(z, w, v); }
  static void eval(mpz_ptr z, mpz_srcptr w, unsigned long int l)
  { mpz_lcm_ui(z, w, l); }
  static void eval(mpz_ptr z, unsigned long int l, mpz_srcptr w)
  { eval(z, w, l); }
  static void eval(mpz_ptr z, mpz_srcptr w, signed long int l)
  { eval(z, w, __gmpxx_abs_ui(l)); }
  static void eval(mpz_ptr z, signed long int l, mpz_srcptr w)
  { eval(z, w, l); }
  static void eval(mpz_ptr z, mpz_srcptr w, double d)
  {  __GMPXX_TMPZ_D;    mpz_lcm (z, w, temp); }
  static void eval(mpz_ptr z, double d, mpz_srcptr w)
  { eval(z, w, d); }
};

struct __gmp_rand_function
{
  static void eval(mpz_ptr z, gmp_randstate_t s, mp_bitcnt_t l)
  { mpz_urandomb(z, s, l); }
  static void eval(mpz_ptr z, gmp_randstate_t s, mpz_srcptr w)
  { mpz_urandomm(z, s, w); }
  static void eval(mpf_ptr f, gmp_randstate_t s, mp_bitcnt_t prec)
  { mpf_urandomb(f, s, prec); }
};

struct __gmp_fac_function
{
  static void eval(mpz_ptr z, unsigned long l) { mpz_fac_ui(z, l); }
  static void eval(mpz_ptr z, signed long l)
  {
    if (l < 0)
      throw std::domain_error ("factorial(negative)");
    eval(z, static_cast<unsigned long>(l));
  }
  static void eval(mpz_ptr z, mpz_srcptr w)
  {
    if (!mpz_fits_ulong_p(w))
      {
 if (mpz_sgn(w) < 0)
   throw std::domain_error ("factorial(negative)");
 else
   throw std::bad_alloc(); // or std::overflow_error ("factorial")?
      }
    eval(z, mpz_get_ui(w));
  }
  static void eval(mpz_ptr z, double d)
  {  __GMPXX_TMPZ_D;    eval (z, temp); }
};

struct __gmp_primorial_function
{
  static void eval(mpz_ptr z, unsigned long l) { mpz_primorial_ui(z, l); }
  static void eval(mpz_ptr z, signed long l)
  {
    if (l < 0)
      throw std::domain_error ("primorial(negative)");
    eval(z, static_cast<unsigned long>(l));
  }
  static void eval(mpz_ptr z, mpz_srcptr w)
  {
    if (!mpz_fits_ulong_p(w))
      {
 if (mpz_sgn(w) < 0)
   throw std::domain_error ("primorial(negative)");
 else
   throw std::bad_alloc(); // or std::overflow_error ("primorial")?
      }
    eval(z, mpz_get_ui(w));
  }
  static void eval(mpz_ptr z, double d)
  {  __GMPXX_TMPZ_D;    eval (z, temp); }
};

struct __gmp_fib_function
{
  static void eval(mpz_ptr z, unsigned long l) { mpz_fib_ui(z, l); }
  static void eval(mpz_ptr z, signed long l)
  {
    if (l < 0)
      {
 eval(z, -static_cast<unsigned long>(l));
 if ((l & 1) == 0)
   mpz_neg(z, z);
      }
    else
      eval(z, static_cast<unsigned long>(l));
  }
  static void eval(mpz_ptr z, mpz_srcptr w)
  {
    if (!mpz_fits_slong_p(w))
      throw std::bad_alloc(); // or std::overflow_error ("fibonacci")?
    eval(z, mpz_get_si(w));
  }
  static void eval(mpz_ptr z, double d)
  {  __GMPXX_TMPZ_D;    eval (z, temp); }
};


/**************** Auxiliary classes ****************/

/* this is much the same as gmp_allocated_string in gmp-impl.h
   since gmp-impl.h is not publicly available, I redefine it here
   I use a different name to avoid possible clashes */


extern "C" {
  typedef void (*__gmp_freefunc_t) (void *, size_t);
}
struct __gmp_alloc_cstring
{
  char *str;
  __gmp_alloc_cstring(char *s) { str = s; }
  ~__gmp_alloc_cstring()
  {
    __gmp_freefunc_t freefunc;
    mp_get_memory_functions (NULL, NULL, &freefunc);
    (*freefunc) (str, std::strlen(str)+1);
  }
};


// general expression template class
template <class T, class U>
class __gmp_expr;


// templates for resolving expression types
template <class T>
struct __gmp_resolve_ref
{
  typedef T ref_type;
};

template <class T, class U>
struct __gmp_resolve_ref<__gmp_expr<T, U> >
{
  typedef const __gmp_expr<T, U> & ref_type;
};


template <class T, class U = T>
struct __gmp_resolve_expr;

template <>
struct __gmp_resolve_expr<mpz_t>
{
  typedef mpz_t value_type;
  typedef mpz_ptr ptr_type;
  typedef mpz_srcptr srcptr_type;
};

template <>
struct __gmp_resolve_expr<mpq_t>
{
  typedef mpq_t value_type;
  typedef mpq_ptr ptr_type;
  typedef mpq_srcptr srcptr_type;
};

template <>
struct __gmp_resolve_expr<mpf_t>
{
  typedef mpf_t value_type;
  typedef mpf_ptr ptr_type;
  typedef mpf_srcptr srcptr_type;
};

template <>
struct __gmp_resolve_expr<mpz_t, mpq_t>
{
  typedef mpq_t value_type;
};

template <>
struct __gmp_resolve_expr<mpq_t, mpz_t>
{
  typedef mpq_t value_type;
};

template <>
struct __gmp_resolve_expr<mpz_t, mpf_t>
{
  typedef mpf_t value_type;
};

template <>
struct __gmp_resolve_expr<mpf_t, mpz_t>
{
  typedef mpf_t value_type;
};

template <>
struct __gmp_resolve_expr<mpq_t, mpf_t>
{
  typedef mpf_t value_type;
};

template <>
struct __gmp_resolve_expr<mpf_t, mpq_t>
{
  typedef mpf_t value_type;
};

#if __GMPXX_USE_CXX11
namespace std {
  template <class T, class U, class V, class W>
  struct common_type <__gmp_expr<T, U>, __gmp_expr<V, W> >
  {
  private:
    typedef typename __gmp_resolve_expr<T, V>::value_type X;
  public:
    typedef __gmp_expr<X, X> type;
  };

  template <class T, class U>
  struct common_type <__gmp_expr<T, U> >
  {
    typedef __gmp_expr<T, T> type;
  };

#define __GMPXX_DECLARE_COMMON_TYPE(typ) \
  template <class T, class U>   \
  struct common_type <__gmp_expr<T, U>, typ > \
  {      \
    typedef __gmp_expr<T, T> type;  \
  };      \
      \
  template <class T, class U>   \
  struct common_type <typ, __gmp_expr<T, U> > \
  {      \
    typedef __gmp_expr<T, T> type;  \
  }

  __GMPXX_DECLARE_COMMON_TYPE(signed char);
  __GMPXX_DECLARE_COMMON_TYPE(unsigned char);
  __GMPXX_DECLARE_COMMON_TYPE(signed int);
  __GMPXX_DECLARE_COMMON_TYPE(unsigned int);
  __GMPXX_DECLARE_COMMON_TYPE(signed short int);
  __GMPXX_DECLARE_COMMON_TYPE(unsigned short int);
  __GMPXX_DECLARE_COMMON_TYPE(signed long int);
  __GMPXX_DECLARE_COMMON_TYPE(unsigned long int);
  __GMPXX_DECLARE_COMMON_TYPE(float);
  __GMPXX_DECLARE_COMMON_TYPE(double);
#undef __GMPXX_DECLARE_COMMON_TYPE
}
#endif

// classes for evaluating unary and binary expressions
template <class T, class Op>
struct __gmp_unary_expr
{
  typename __gmp_resolve_ref<T>::ref_type val;

  __gmp_unary_expr(const T &v) : val(v) { }
private:
  __gmp_unary_expr();
};

template <class T, class U, class Op>
struct __gmp_binary_expr
{
  typename __gmp_resolve_ref<T>::ref_type val1;
  typename __gmp_resolve_ref<U>::ref_type val2;

  __gmp_binary_expr(const T &v1, const U &v2) : val1(v1), val2(v2) { }
private:
  __gmp_binary_expr();
};



/**************** Macros for in-class declarations ****************/
/* This is just repetitive code that is easier to maintain if it's written
   only once */


#define __GMPP_DECLARE_COMPOUND_OPERATOR(fun)                         \
  template <class T, class U>                                         \
  __gmp_expr<value_type, value_type> & fun(const __gmp_expr<T, U> &);

#define __GMPN_DECLARE_COMPOUND_OPERATOR(fun) \
  __gmp_expr & fun(signed char);              \
  __gmp_expr & fun(unsigned char);            \
  __gmp_expr & fun(signed int);               \
  __gmp_expr & fun(unsigned int);             \
  __gmp_expr & fun(signed short int);         \
  __gmp_expr & fun(unsigned short int);       \
  __gmp_expr & fun(signed long int);          \
  __gmp_expr & fun(unsigned long int);        \
  __gmp_expr & fun(float);                    \
  __gmp_expr & fun(double);                   \
  /* __gmp_expr & fun(long double); */

#define __GMP_DECLARE_COMPOUND_OPERATOR(fun) \
__GMPP_DECLARE_COMPOUND_OPERATOR(fun)        \
__GMPN_DECLARE_COMPOUND_OPERATOR(fun)

#define __GMP_DECLARE_COMPOUND_OPERATOR_UI(fun) \
  __gmp_expr & fun(mp_bitcnt_t);

#define __GMP_DECLARE_INCREMENT_OPERATOR(fun) \
  inline __gmp_expr & fun();                  \
  inline __gmp_expr fun(int);

#define __GMPXX_DEFINE_ARITHMETIC_CONSTRUCTORS  \
  __gmp_expr(signed char c) { init_si(c); }  \
  __gmp_expr(unsigned char c) { init_ui(c); }  \
  __gmp_expr(signed int i) { init_si(i); }  \
  __gmp_expr(unsigned int i) { init_ui(i); }  \
  __gmp_expr(signed short int s) { init_si(s); } \
  __gmp_expr(unsigned short int s) { init_ui(s); } \
  __gmp_expr(signed long int l) { init_si(l); }  \
  __gmp_expr(unsigned long int l) { init_ui(l); } \
  __gmp_expr(float f) { init_d(f); }   \
  __gmp_expr(double d) { init_d(d); }

#define __GMPXX_DEFINE_ARITHMETIC_ASSIGNMENTS  \
  __gmp_expr & operator=(signed char c) { assign_si(c); return *this; } \
  __gmp_expr & operator=(unsigned char c) { assign_ui(c); return *this; } \
  __gmp_expr & operator=(signed int i) { assign_si(i); return *this; } \
  __gmp_expr & operator=(unsigned int i) { assign_ui(i); return *this; } \
  __gmp_expr & operator=(signed short int s) { assign_si(s); return *this; } \
  __gmp_expr & operator=(unsigned short int s) { assign_ui(s); return *this; } \
  __gmp_expr & operator=(signed long int l) { assign_si(l); return *this; } \
  __gmp_expr & operator=(unsigned long int l) { assign_ui(l); return *this; } \
  __gmp_expr & operator=(float f) { assign_d(f); return *this; } \
  __gmp_expr & operator=(double d) { assign_d(d); return *this; }

#define __GMPP_DECLARE_UNARY_STATIC_MEMFUN(T, fun, eval_fun)                 \
template <class U>                                                           \
static __gmp_expr<T, __gmp_unary_expr<__gmp_expr<T, U>, eval_fun> >          \
fun(const __gmp_expr<T, U> &expr);

#define __GMPNN_DECLARE_UNARY_STATIC_MEMFUN(T, fun, eval_fun, type, bigtype) \
static inline __gmp_expr<T, __gmp_unary_expr<bigtype, eval_fun> >            \
fun(type expr);

#define __GMPNS_DECLARE_UNARY_STATIC_MEMFUN(T, fun, eval_fun, type)  \
__GMPNN_DECLARE_UNARY_STATIC_MEMFUN(T, fun, eval_fun, type, signed long)
#define __GMPNU_DECLARE_UNARY_STATIC_MEMFUN(T, fun, eval_fun, type)  \
__GMPNN_DECLARE_UNARY_STATIC_MEMFUN(T, fun, eval_fun, type, unsigned long)
#define __GMPND_DECLARE_UNARY_STATIC_MEMFUN(T, fun, eval_fun, type)  \
__GMPNN_DECLARE_UNARY_STATIC_MEMFUN(T, fun, eval_fun, type, double)

#define __GMPN_DECLARE_UNARY_STATIC_MEMFUN(T, fun, eval_fun)                 \
__GMPNS_DECLARE_UNARY_STATIC_MEMFUN(T, fun, eval_fun, signed char)           \
__GMPNU_DECLARE_UNARY_STATIC_MEMFUN(T, fun, eval_fun, unsigned char)         \
__GMPNS_DECLARE_UNARY_STATIC_MEMFUN(T, fun, eval_fun, signed int)            \
__GMPNU_DECLARE_UNARY_STATIC_MEMFUN(T, fun, eval_fun, unsigned int)          \
__GMPNS_DECLARE_UNARY_STATIC_MEMFUN(T, fun, eval_fun, signed short int)      \
__GMPNU_DECLARE_UNARY_STATIC_MEMFUN(T, fun, eval_fun, unsigned short int)    \
__GMPNS_DECLARE_UNARY_STATIC_MEMFUN(T, fun, eval_fun, signed long int)       \
__GMPNU_DECLARE_UNARY_STATIC_MEMFUN(T, fun, eval_fun, unsigned long int)     \
__GMPND_DECLARE_UNARY_STATIC_MEMFUN(T, fun, eval_fun, float)                 \
__GMPND_DECLARE_UNARY_STATIC_MEMFUN(T, fun, eval_fun, double)

#define __GMP_DECLARE_UNARY_STATIC_MEMFUN(T, fun, eval_fun)                  \
__GMPP_DECLARE_UNARY_STATIC_MEMFUN(T, fun, eval_fun)                         \
__GMPN_DECLARE_UNARY_STATIC_MEMFUN(T, fun, eval_fun)

/**************** mpz_class -- wrapper for mpz_t ****************/

template <>
class __gmp_expr<mpz_t, mpz_t>
{
private:
  typedef mpz_t value_type;
  value_type mp;

  // Helper functions used for all arithmetic types
  void assign_ui(unsigned long l)
  {
    if (__GMPXX_CONSTANT_TRUE(l == 0))
      __get_mp()->_mp_size = 0;
    else
      mpz_set_ui(mp, l);
  }
  void assign_si(signed long l)
  {
    if (__GMPXX_CONSTANT_TRUE(l >= 0))
      assign_ui(l);
    else if (__GMPXX_CONSTANT_TRUE(l <= 0))
      {
 assign_ui(-static_cast<unsigned long>(l));
 mpz_neg(mp, mp);
      }
    else
      mpz_set_si(mp, l);
  }
  void assign_d (double d)
  {
    mpz_set_d (mp, d);
  }

  void init_ui(unsigned long l)
  {
    if (__GMPXX_CONSTANT_TRUE(l == 0))
      mpz_init(mp);
    else
      mpz_init_set_ui(mp, l);
  }
  void init_si(signed long l)
  {
    if (__GMPXX_CONSTANT_TRUE(l >= 0))
      init_ui(l);
    else if (__GMPXX_CONSTANT_TRUE(l <= 0))
      {
 init_ui(-static_cast<unsigned long>(l));
 mpz_neg(mp, mp);
      }
    else
      mpz_init_set_si(mp, l);
  }
  void init_d (double d)
  {
    mpz_init_set_d (mp, d);
  }

public:
  mp_bitcnt_t get_prec() const { return mpf_get_default_prec(); }

  // constructors and destructor
  __gmp_expr() __GMPXX_NOEXCEPT { mpz_init(mp); }

  __gmp_expr(const __gmp_expr &z) { mpz_init_set(mp, z.mp); }
#if __GMPXX_USE_CXX11
  __gmp_expr(__gmp_expr &&z) noexcept
  { *__get_mp() = *z.__get_mp(); mpz_init(z.mp); }
#endif
  template <class T>
  __gmp_expr(const __gmp_expr<mpz_t, T> &expr)
  { mpz_init(mp); __gmp_set_expr(mp, expr); }
  template <class T, class U>
  explicit __gmp_expr(const __gmp_expr<T, U> &expr)
  { mpz_init(mp); __gmp_set_expr(mp, expr); }

  __GMPXX_DEFINE_ARITHMETIC_CONSTRUCTORS

  explicit __gmp_expr(const char *s, int base = 0)
  {
    if (mpz_init_set_str (mp, s, base) != 0)
      {
        mpz_clear (mp);
        throw std::invalid_argument ("mpz_set_str");
      }
  }
  explicit __gmp_expr(const std::string &s, int base = 0)
  {
    if (mpz_init_set_str(mp, s.c_str(), base) != 0)
      {
        mpz_clear (mp);
        throw std::invalid_argument ("mpz_set_str");
      }
  }

  explicit __gmp_expr(mpz_srcptr z) { mpz_init_set(mp, z); }

  ~__gmp_expr() { mpz_clear(mp); }

  void swap(__gmp_expr& z) __GMPXX_NOEXCEPT
  { std::swap(*__get_mp(), *z.__get_mp()); }

  // assignment operators
  __gmp_expr & operator=(const __gmp_expr &z)
  { mpz_set(mp, z.mp); return *this; }
#if __GMPXX_USE_CXX11
  __gmp_expr & operator=(__gmp_expr &&z) noexcept
  { swap(z); return *this; }
#endif
  template <class T, class U>
  __gmp_expr<value_type, value_type> & operator=(const __gmp_expr<T, U> &expr)
  { __gmp_set_expr(mp, expr); return *this; }

  __GMPXX_DEFINE_ARITHMETIC_ASSIGNMENTS

  __gmp_expr & operator=(const char *s)
  {
    if (mpz_set_str (mp, s, 0) != 0)
      throw std::invalid_argument ("mpz_set_str");
    return *this;
  }
  __gmp_expr & operator=(const std::string &s)
  {
    if (mpz_set_str(mp, s.c_str(), 0) != 0)
      throw std::invalid_argument ("mpz_set_str");
    return *this;
  }

  // string input/output functions
  int set_str(const char *s, int base)
  { return mpz_set_str(mp, s, base); }
  int set_str(const std::string &s, int base)
  { return mpz_set_str(mp, s.c_str(), base); }
  std::string get_str(int base = 10) const
  {
    __gmp_alloc_cstring temp(mpz_get_str(0, base, mp));
    return std::string(temp.str);
  }

  // conversion functions
  mpz_srcptr __get_mp() const { return mp; }
  mpz_ptr __get_mp() { return mp; }
  mpz_srcptr get_mpz_t() const { return mp; }
  mpz_ptr get_mpz_t() { return mp; }

  signed long int get_si() const { return mpz_get_si(mp); }
  unsigned long int get_ui() const { return mpz_get_ui(mp); }
  double get_d() const { return mpz_get_d(mp); }

  // bool fits_schar_p() const { return mpz_fits_schar_p(mp); }
  // bool fits_uchar_p() const { return mpz_fits_uchar_p(mp); }
  bool fits_sint_p() const { return mpz_fits_sint_p(mp); }
  bool fits_uint_p() const { return mpz_fits_uint_p(mp); }
  bool fits_sshort_p() const { return mpz_fits_sshort_p(mp); }
  bool fits_ushort_p() const { return mpz_fits_ushort_p(mp); }
  bool fits_slong_p() const { return mpz_fits_slong_p(mp); }
  bool fits_ulong_p() const { return mpz_fits_ulong_p(mp); }
  // bool fits_float_p() const { return mpz_fits_float_p(mp); }
  // bool fits_double_p() const { return mpz_fits_double_p(mp); }
  // bool fits_ldouble_p() const { return mpz_fits_ldouble_p(mp); }

#if __GMPXX_USE_CXX11
  explicit operator bool() const { return __get_mp()->_mp_size != 0; }
#endif

  // member operators
  __GMP_DECLARE_COMPOUND_OPERATOR(operator+=)
  __GMP_DECLARE_COMPOUND_OPERATOR(operator-=)
  __GMP_DECLARE_COMPOUND_OPERATOR(operator*=)
  __GMP_DECLARE_COMPOUND_OPERATOR(operator/=)
  __GMP_DECLARE_COMPOUND_OPERATOR(operator%=)

  __GMP_DECLARE_COMPOUND_OPERATOR(operator&=)
  __GMP_DECLARE_COMPOUND_OPERATOR(operator|=)
  __GMP_DECLARE_COMPOUND_OPERATOR(operator^=)

  __GMP_DECLARE_COMPOUND_OPERATOR_UI(operator<<=)
  __GMP_DECLARE_COMPOUND_OPERATOR_UI(operator>>=)

  __GMP_DECLARE_INCREMENT_OPERATOR(operator++)
  __GMP_DECLARE_INCREMENT_OPERATOR(operator--)

  __GMP_DECLARE_UNARY_STATIC_MEMFUN(mpz_t, factorial, __gmp_fac_function)
  __GMP_DECLARE_UNARY_STATIC_MEMFUN(mpz_t, primorial, __gmp_primorial_function)
  __GMP_DECLARE_UNARY_STATIC_MEMFUN(mpz_t, fibonacci, __gmp_fib_function)
};

typedef __gmp_expr<mpz_t, mpz_t> mpz_class;


/**************** mpq_class -- wrapper for mpq_t ****************/

template <>
class __gmp_expr<mpq_t, mpq_t>
{
private:
  typedef mpq_t value_type;
  value_type mp;

  // Helper functions used for all arithmetic types
  void assign_ui(unsigned long l) { mpq_set_ui(mp, l, 1); }
  void assign_si(signed long l)
  {
    if (__GMPXX_CONSTANT_TRUE(l >= 0))
      assign_ui(l);
    else
      mpq_set_si(mp, l, 1);
  }
  void assign_d (double d)        { mpq_set_d (mp, d); }

  void init_ui(unsigned long l) { mpq_init(mp); get_num() = l; }
  void init_si(signed long l) { mpq_init(mp); get_num() = l; }
  void init_d (double d) { mpq_init(mp); assign_d (d); }

public:
  mp_bitcnt_t get_prec() const { return mpf_get_default_prec(); }
  void canonicalize() { mpq_canonicalize(mp); }

  // constructors and destructor
  __gmp_expr() { mpq_init(mp); }

  __gmp_expr(const __gmp_expr &q)
  {
    mpz_init_set(mpq_numref(mp), mpq_numref(q.mp));
    mpz_init_set(mpq_denref(mp), mpq_denref(q.mp));
  }
#if __GMPXX_USE_CXX11
  __gmp_expr(__gmp_expr &&q)
  { *mp = *q.mp; mpq_init(q.mp); }
  __gmp_expr(mpz_class &&z)
  {
    *mpq_numref(mp) = *z.get_mpz_t();
    mpz_init_set_ui(mpq_denref(mp), 1);
    mpz_init(z.get_mpz_t());
  }
#endif
  template <class T>
  __gmp_expr(const __gmp_expr<mpz_t, T> &expr)
  { mpq_init(mp); __gmp_set_expr(mp, expr); }
  template <class T>
  __gmp_expr(const __gmp_expr<mpq_t, T> &expr)
  { mpq_init(mp); __gmp_set_expr(mp, expr); }
  template <class T, class U>
  explicit __gmp_expr(const __gmp_expr<T, U> &expr)
  { mpq_init(mp); __gmp_set_expr(mp, expr); }

  __GMPXX_DEFINE_ARITHMETIC_CONSTRUCTORS

  explicit __gmp_expr(const char *s, int base = 0)
  {
    mpq_init (mp);
    // If s is the literal 0, we meant to call another constructor.
    // If s just happens to evaluate to 0, we would crash, so whatever.
    if (s == 0)
      {
 // Don't turn mpq_class(0,0) into 0
 mpz_set_si(mpq_denref(mp), base);
      }
    else if (mpq_set_str(mp, s, base) != 0)
      {
        mpq_clear (mp);
        throw std::invalid_argument ("mpq_set_str");
      }
  }
  explicit __gmp_expr(const std::string &s, int base = 0)
  {
    mpq_init(mp);
    if (mpq_set_str (mp, s.c_str(), base) != 0)
      {
        mpq_clear (mp);
        throw std::invalid_argument ("mpq_set_str");
      }
  }
  explicit __gmp_expr(mpq_srcptr q)
  {
    mpz_init_set(mpq_numref(mp), mpq_numref(q));
    mpz_init_set(mpq_denref(mp), mpq_denref(q));
  }

  __gmp_expr(const mpz_class &num, const mpz_class &den)
  {
    mpz_init_set(mpq_numref(mp), num.get_mpz_t());
    mpz_init_set(mpq_denref(mp), den.get_mpz_t());
  }

  ~__gmp_expr() { mpq_clear(mp); }

  void swap(__gmp_expr& q) __GMPXX_NOEXCEPT { std::swap(*mp, *q.mp); }

  // assignment operators
  __gmp_expr & operator=(const __gmp_expr &q)
  { mpq_set(mp, q.mp); return *this; }
#if __GMPXX_USE_CXX11
  __gmp_expr & operator=(__gmp_expr &&q) noexcept
  { swap(q); return *this; }
  __gmp_expr & operator=(mpz_class &&z) noexcept
  { get_num() = std::move(z); get_den() = 1u; return *this; }
#endif
  template <class T, class U>
  __gmp_expr<value_type, value_type> & operator=(const __gmp_expr<T, U> &expr)
  { __gmp_set_expr(mp, expr); return *this; }

  __GMPXX_DEFINE_ARITHMETIC_ASSIGNMENTS

  __gmp_expr & operator=(const char *s)
  {
    if (mpq_set_str (mp, s, 0) != 0)
      throw std::invalid_argument ("mpq_set_str");
    return *this;
  }
  __gmp_expr & operator=(const std::string &s)
  {
    if (mpq_set_str(mp, s.c_str(), 0) != 0)
      throw std::invalid_argument ("mpq_set_str");
    return *this;
  }

  // string input/output functions
  int set_str(const char *s, int base)
  { return mpq_set_str(mp, s, base); }
  int set_str(const std::string &s, int base)
  { return mpq_set_str(mp, s.c_str(), base); }
  std::string get_str(int base = 10) const
  {
    __gmp_alloc_cstring temp(mpq_get_str(0, base, mp));
    return std::string(temp.str);
  }

  // conversion functions

  // casting a reference to an mpz_t to mpz_class & is a dirty hack.
  // It kind of works because the internal representation of mpz_class is
  // exactly an mpz_t, but compilers are allowed to assume that mpq_class
  // and mpz_class do not alias... In mpz_class, we avoid using mp directly,
  // to reduce the risks of such problematic optimizations.
  const mpz_class & get_num() const
  { return reinterpret_cast<const mpz_class &>(*mpq_numref(mp)); }
  mpz_class & get_num()
  { return reinterpret_cast<mpz_class &>(*mpq_numref(mp)); }
  const mpz_class & get_den() const
  { return reinterpret_cast<const mpz_class &>(*mpq_denref(mp)); }
  mpz_class & get_den()
  { return reinterpret_cast<mpz_class &>(*mpq_denref(mp)); }

  mpq_srcptr __get_mp() const { return mp; }
  mpq_ptr __get_mp() { return mp; }
  mpq_srcptr get_mpq_t() const { return mp; }
  mpq_ptr get_mpq_t() { return mp; }

  mpz_srcptr get_num_mpz_t() const { return mpq_numref(mp); }
  mpz_ptr get_num_mpz_t() { return mpq_numref(mp); }
  mpz_srcptr get_den_mpz_t() const { return mpq_denref(mp); }
  mpz_ptr get_den_mpz_t() { return mpq_denref(mp); }

  double get_d() const { return mpq_get_d(mp); }

#if __GMPXX_USE_CXX11
  explicit operator bool() const { return mpq_numref(mp)->_mp_size != 0; }
#endif

  // compound assignments
  __GMP_DECLARE_COMPOUND_OPERATOR(operator+=)
  __GMP_DECLARE_COMPOUND_OPERATOR(operator-=)
  __GMP_DECLARE_COMPOUND_OPERATOR(operator*=)
  __GMP_DECLARE_COMPOUND_OPERATOR(operator/=)

  __GMP_DECLARE_COMPOUND_OPERATOR_UI(operator<<=)
  __GMP_DECLARE_COMPOUND_OPERATOR_UI(operator>>=)

  __GMP_DECLARE_INCREMENT_OPERATOR(operator++)
  __GMP_DECLARE_INCREMENT_OPERATOR(operator--)
};

typedef __gmp_expr<mpq_t, mpq_t> mpq_class;


/**************** mpf_class -- wrapper for mpf_t ****************/

template <>
class __gmp_expr<mpf_t, mpf_t>
{
private:
  typedef mpf_t value_type;
  value_type mp;

  // Helper functions used for all arithmetic types
  void assign_ui(unsigned long l) { mpf_set_ui(mp, l); }
  void assign_si(signed long l)
  {
    if (__GMPXX_CONSTANT_TRUE(l >= 0))
      assign_ui(l);
    else
      mpf_set_si(mp, l);
  }
  void assign_d (double d)        { mpf_set_d (mp, d); }

  void init_ui(unsigned long l)
  {
    if (__GMPXX_CONSTANT_TRUE(l == 0))
      mpf_init(mp);
    else
      mpf_init_set_ui(mp, l);
  }
  void init_si(signed long l)
  {
    if (__GMPXX_CONSTANT_TRUE(l >= 0))
      init_ui(l);
    else
      mpf_init_set_si(mp, l);
  }
  void init_d (double d) { mpf_init_set_d (mp, d); }

public:
  mp_bitcnt_t get_prec() const { return mpf_get_prec(mp); }

  void set_prec(mp_bitcnt_t prec) { mpf_set_prec(mp, prec); }
  void set_prec_raw(mp_bitcnt_t prec) { mpf_set_prec_raw(mp, prec); }

  // constructors and destructor
  __gmp_expr() { mpf_init(mp); }

  __gmp_expr(const __gmp_expr &f)
  { mpf_init2(mp, f.get_prec()); mpf_set(mp, f.mp); }
#if __GMPXX_USE_CXX11
  __gmp_expr(__gmp_expr &&f)
  { *mp = *f.mp; mpf_init2(f.mp, get_prec()); }
#endif
  __gmp_expr(const __gmp_expr &f, mp_bitcnt_t prec)
  { mpf_init2(mp, prec); mpf_set(mp, f.mp); }
  template <class T, class U>
  __gmp_expr(const __gmp_expr<T, U> &expr)
  { mpf_init2(mp, expr.get_prec()); __gmp_set_expr(mp, expr); }
  template <class T, class U>
  __gmp_expr(const __gmp_expr<T, U> &expr, mp_bitcnt_t prec)
  { mpf_init2(mp, prec); __gmp_set_expr(mp, expr); }

  __GMPXX_DEFINE_ARITHMETIC_CONSTRUCTORS

  __gmp_expr(signed char c, mp_bitcnt_t prec)
  { mpf_init2(mp, prec); mpf_set_si(mp, c); }
  __gmp_expr(unsigned char c, mp_bitcnt_t prec)
  { mpf_init2(mp, prec); mpf_set_ui(mp, c); }

  __gmp_expr(signed int i, mp_bitcnt_t prec)
  { mpf_init2(mp, prec); mpf_set_si(mp, i); }
  __gmp_expr(unsigned int i, mp_bitcnt_t prec)
  { mpf_init2(mp, prec); mpf_set_ui(mp, i); }

  __gmp_expr(signed short int s, mp_bitcnt_t prec)
  { mpf_init2(mp, prec); mpf_set_si(mp, s); }
  __gmp_expr(unsigned short int s, mp_bitcnt_t prec)
  { mpf_init2(mp, prec); mpf_set_ui(mp, s); }

  __gmp_expr(signed long int l, mp_bitcnt_t prec)
  { mpf_init2(mp, prec); mpf_set_si(mp, l); }
  __gmp_expr(unsigned long int l, mp_bitcnt_t prec)
  { mpf_init2(mp, prec); mpf_set_ui(mp, l); }

  __gmp_expr(float f, mp_bitcnt_t prec)
  { mpf_init2(mp, prec); mpf_set_d(mp, f); }
  __gmp_expr(double d, mp_bitcnt_t prec)
  { mpf_init2(mp, prec); mpf_set_d(mp, d); }
  // __gmp_expr(long double ld) { mpf_init_set_d(mp, ld); }
  // __gmp_expr(long double ld, mp_bitcnt_t prec)
  // { mpf_init2(mp, prec); mpf_set_d(mp, ld); }

  explicit __gmp_expr(const char *s)
  {
    if (mpf_init_set_str (mp, s, 0) != 0)
      {
        mpf_clear (mp);
        throw std::invalid_argument ("mpf_set_str");
      }
  }
  __gmp_expr(const char *s, mp_bitcnt_t prec, int base = 0)
  {
    mpf_init2(mp, prec);
    if (mpf_set_str(mp, s, base) != 0)
      {
        mpf_clear (mp);
        throw std::invalid_argument ("mpf_set_str");
      }
  }
  explicit __gmp_expr(const std::string &s)
  {
    if (mpf_init_set_str(mp, s.c_str(), 0) != 0)
      {
        mpf_clear (mp);
        throw std::invalid_argument ("mpf_set_str");
      }
  }
  __gmp_expr(const std::string &s, mp_bitcnt_t prec, int base = 0)
  {
    mpf_init2(mp, prec);
    if (mpf_set_str(mp, s.c_str(), base) != 0)
      {
        mpf_clear (mp);
        throw std::invalid_argument ("mpf_set_str");
      }
  }

  explicit __gmp_expr(mpf_srcptr f)
  { mpf_init2(mp, mpf_get_prec(f)); mpf_set(mp, f); }
  __gmp_expr(mpf_srcptr f, mp_bitcnt_t prec)
  { mpf_init2(mp, prec); mpf_set(mp, f); }

  ~__gmp_expr() { mpf_clear(mp); }

  void swap(__gmp_expr& f) __GMPXX_NOEXCEPT { std::swap(*mp, *f.mp); }

  // assignment operators
  __gmp_expr & operator=(const __gmp_expr &f)
  { mpf_set(mp, f.mp); return *this; }
#if __GMPXX_USE_CXX11
  __gmp_expr & operator=(__gmp_expr &&f) noexcept
  { swap(f); return *this; }
#endif
  template <class T, class U>
  __gmp_expr<value_type, value_type> & operator=(const __gmp_expr<T, U> &expr)
  { __gmp_set_expr(mp, expr); return *this; }

  __GMPXX_DEFINE_ARITHMETIC_ASSIGNMENTS

  __gmp_expr & operator=(const char *s)
  {
    if (mpf_set_str (mp, s, 0) != 0)
      throw std::invalid_argument ("mpf_set_str");
    return *this;
  }
  __gmp_expr & operator=(const std::string &s)
  {
    if (mpf_set_str(mp, s.c_str(), 0) != 0)
      throw std::invalid_argument ("mpf_set_str");
    return *this;
  }

  // string input/output functions
  int set_str(const char *s, int base)
  { return mpf_set_str(mp, s, base); }
  int set_str(const std::string &s, int base)
  { return mpf_set_str(mp, s.c_str(), base); }
  std::string get_str(mp_exp_t &expo, int base = 10, size_t size = 0) const
  {
    __gmp_alloc_cstring temp(mpf_get_str(0, &expo, base, size, mp));
    return std::string(temp.str);
  }

  // conversion functions
  mpf_srcptr __get_mp() const { return mp; }
  mpf_ptr __get_mp() { return mp; }
  mpf_srcptr get_mpf_t() const { return mp; }
  mpf_ptr get_mpf_t() { return mp; }

  signed long int get_si() const { return mpf_get_si(mp); }
  unsigned long int get_ui() const { return mpf_get_ui(mp); }
  double get_d() const { return mpf_get_d(mp); }

  // bool fits_schar_p() const { return mpf_fits_schar_p(mp); }
  // bool fits_uchar_p() const { return mpf_fits_uchar_p(mp); }
  bool fits_sint_p() const { return mpf_fits_sint_p(mp); }
  bool fits_uint_p() const { return mpf_fits_uint_p(mp); }
  bool fits_sshort_p() const { return mpf_fits_sshort_p(mp); }
  bool fits_ushort_p() const { return mpf_fits_ushort_p(mp); }
  bool fits_slong_p() const { return mpf_fits_slong_p(mp); }
  bool fits_ulong_p() const { return mpf_fits_ulong_p(mp); }
  // bool fits_float_p() const { return mpf_fits_float_p(mp); }
  // bool fits_double_p() const { return mpf_fits_double_p(mp); }
  // bool fits_ldouble_p() const { return mpf_fits_ldouble_p(mp); }

#if __GMPXX_USE_CXX11
  explicit operator bool() const { return mpf_sgn(mp) != 0; }
#endif

  // compound assignments
  __GMP_DECLARE_COMPOUND_OPERATOR(operator+=)
  __GMP_DECLARE_COMPOUND_OPERATOR(operator-=)
  __GMP_DECLARE_COMPOUND_OPERATOR(operator*=)
  __GMP_DECLARE_COMPOUND_OPERATOR(operator/=)

  __GMP_DECLARE_COMPOUND_OPERATOR_UI(operator<<=)
  __GMP_DECLARE_COMPOUND_OPERATOR_UI(operator>>=)

  __GMP_DECLARE_INCREMENT_OPERATOR(operator++)
  __GMP_DECLARE_INCREMENT_OPERATOR(operator--)
};

typedef __gmp_expr<mpf_t, mpf_t> mpf_class;



/**************** User-defined literals ****************/

#if __GMPXX_USE_CXX11
inline mpz_class operator"" _mpz(const char* s)
{
  return mpz_class(s);
}

inline mpq_class operator"" _mpq(const char* s)
{
  mpq_class q;
  q.get_num() = s;
  return q;
}

inline mpf_class operator"" _mpf(const char* s)
{
  return mpf_class(s);
}
#endif

/**************** I/O operators ****************/

// these should (and will) be provided separately

template <class T, class U>
inline std::ostream & operator<<
(std::ostream &o, const __gmp_expr<T, U> &expr)
{
  __gmp_expr<T, T> const& temp(expr);
  return o << temp.__get_mp();
}

template <class T>
inline std::istream & operator>>(std::istream &i, __gmp_expr<T, T> &expr)
{
  return i >> expr.__get_mp();
}

/*
// you might want to uncomment this
inline std::istream & operator>>(std::istream &i, mpq_class &q)
{
  i >> q.get_mpq_t();
  q.canonicalize();
  return i;
}
*/



/**************** Functions for type conversion ****************/

inline void __gmp_set_expr(mpz_ptr z, const mpz_class &w)
{
  mpz_set(z, w.get_mpz_t());
}

template <class T>
inline void __gmp_set_expr(mpz_ptr z, const __gmp_expr<mpz_t, T> &expr)
{
  expr.eval(z);
}

template <class T>
inline void __gmp_set_expr(mpz_ptr z, const __gmp_expr<mpq_t, T> &expr)
{
  mpq_class const& temp(expr);
  mpz_set_q(z, temp.get_mpq_t());
}

template <class T>
--> --------------------

--> maximum size reached

--> --------------------

100%


¤ Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.0.83Bemerkung:  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung ist noch experimentell.