GAP 4.8.9 installation with standard packages -- copy to your CoCalc project to get it
/* gmpxx.h -- C++ class wrapper for GMP types. -*- C++ -*-12Copyright 2001-2003, 2006, 2008, 2011, 2012 Free Software Foundation, Inc.34This file is part of the GNU MP Library.56The GNU MP Library is free software; you can redistribute it and/or modify7it under the terms of either:89* the GNU Lesser General Public License as published by the Free10Software Foundation; either version 3 of the License, or (at your11option) any later version.1213or1415* the GNU General Public License as published by the Free Software16Foundation; either version 2 of the License, or (at your option) any17later version.1819or both in parallel, as here.2021The GNU MP Library is distributed in the hope that it will be useful, but22WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY23or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License24for more details.2526You should have received copies of the GNU General Public License and the27GNU Lesser General Public License along with the GNU MP Library. If not,28see https://www.gnu.org/licenses/. */2930#ifndef __GMP_PLUSPLUS__31#define __GMP_PLUSPLUS__3233#include <iosfwd>3435#include <cstring> /* for strlen */36#include <limits> /* numeric_limits */37#include <utility>38#include <algorithm> /* swap */39#include <string>40#include <stdexcept>41#include <cfloat>42#include <gmp.h>4344// wrapper for gcc's __builtin_constant_p45// __builtin_constant_p has been in gcc since forever,46// but g++-3.4 miscompiles it.47#if __GMP_GNUC_PREREQ(4, 2)48#define __GMPXX_CONSTANT(X) __builtin_constant_p(X)49#else50#define __GMPXX_CONSTANT(X) false51#endif52#define __GMPXX_CONSTANT_TRUE(X) (__GMPXX_CONSTANT(X) && (X))5354// Use C++11 features55#ifndef __GMPXX_USE_CXX1156#if __cplusplus >= 201103L57#define __GMPXX_USE_CXX11 158#else59#define __GMPXX_USE_CXX11 060#endif61#endif6263#if __GMPXX_USE_CXX1164#define __GMPXX_NOEXCEPT noexcept65#include <type_traits> // for common_type66#else67#define __GMPXX_NOEXCEPT68#endif6970// Max allocations for plain types when converted to GMP types71#if GMP_NAIL_BITS != 0 && ! defined _LONG_LONG_LIMB72#define __GMPZ_ULI_LIMBS 273#else74#define __GMPZ_ULI_LIMBS 175#endif7677#define __GMPXX_BITS_TO_LIMBS(n) (((n) + (GMP_NUMB_BITS - 1)) / GMP_NUMB_BITS)78#define __GMPZ_DBL_LIMBS __GMPXX_BITS_TO_LIMBS(DBL_MAX_EXP)+179#define __GMPQ_NUM_DBL_LIMBS __GMPZ_DBL_LIMBS80#define __GMPQ_DEN_DBL_LIMBS __GMPXX_BITS_TO_LIMBS(DBL_MANT_DIG+1-DBL_MIN_EXP)+181// The final +1s are a security margin. The current implementation of82// mpq_set_d seems to need it for the denominator.8384inline void __mpz_set_ui_safe(mpz_ptr p, unsigned long l)85{86p->_mp_size = (l != 0);87p->_mp_d[0] = l & GMP_NUMB_MASK;88#if __GMPZ_ULI_LIMBS > 189l >>= GMP_NUMB_BITS;90p->_mp_d[1] = l;91p->_mp_size += (l != 0);92#endif93}9495inline void __mpz_set_si_safe(mpz_ptr p, long l)96{97if(l < 0)98{99__mpz_set_ui_safe(p, -static_cast<unsigned long>(l));100mpz_neg(p, p);101}102else103__mpz_set_ui_safe(p, l);104// Note: we know the high bit of l is 0 so we could do slightly better105}106107// Fake temporary variables108#define __GMPXX_TMPZ_UI \109mpz_t temp; \110mp_limb_t limbs[__GMPZ_ULI_LIMBS]; \111temp->_mp_d = limbs; \112__mpz_set_ui_safe (temp, l)113#define __GMPXX_TMPZ_SI \114mpz_t temp; \115mp_limb_t limbs[__GMPZ_ULI_LIMBS]; \116temp->_mp_d = limbs; \117__mpz_set_si_safe (temp, l)118#define __GMPXX_TMPZ_D \119mpz_t temp; \120mp_limb_t limbs[__GMPZ_DBL_LIMBS]; \121temp->_mp_d = limbs; \122temp->_mp_alloc = __GMPZ_DBL_LIMBS; \123mpz_set_d (temp, d)124125#define __GMPXX_TMPQ_UI \126mpq_t temp; \127mp_limb_t limbs[__GMPZ_ULI_LIMBS+1]; \128mpq_numref(temp)->_mp_d = limbs; \129__mpz_set_ui_safe (mpq_numref(temp), l); \130mpq_denref(temp)->_mp_d = limbs + __GMPZ_ULI_LIMBS; \131mpq_denref(temp)->_mp_size = 1; \132mpq_denref(temp)->_mp_d[0] = 1133#define __GMPXX_TMPQ_SI \134mpq_t temp; \135mp_limb_t limbs[__GMPZ_ULI_LIMBS+1]; \136mpq_numref(temp)->_mp_d = limbs; \137__mpz_set_si_safe (mpq_numref(temp), l); \138mpq_denref(temp)->_mp_d = limbs + __GMPZ_ULI_LIMBS; \139mpq_denref(temp)->_mp_size = 1; \140mpq_denref(temp)->_mp_d[0] = 1141#define __GMPXX_TMPQ_D \142mpq_t temp; \143mp_limb_t limbs[__GMPQ_NUM_DBL_LIMBS + __GMPQ_DEN_DBL_LIMBS]; \144mpq_numref(temp)->_mp_d = limbs; \145mpq_numref(temp)->_mp_alloc = __GMPQ_NUM_DBL_LIMBS; \146mpq_denref(temp)->_mp_d = limbs + __GMPQ_NUM_DBL_LIMBS; \147mpq_denref(temp)->_mp_alloc = __GMPQ_DEN_DBL_LIMBS; \148mpq_set_d (temp, d)149150inline unsigned long __gmpxx_abs_ui (signed long l)151{152return l >= 0 ? static_cast<unsigned long>(l)153: -static_cast<unsigned long>(l);154}155156/**************** Function objects ****************/157/* Any evaluation of a __gmp_expr ends up calling one of these functions158all intermediate functions being inline, the evaluation should optimize159to a direct call to the relevant function, thus yielding no overhead160over the C interface. */161162struct __gmp_unary_plus163{164static void eval(mpz_ptr z, mpz_srcptr w) { mpz_set(z, w); }165static void eval(mpq_ptr q, mpq_srcptr r) { mpq_set(q, r); }166static void eval(mpf_ptr f, mpf_srcptr g) { mpf_set(f, g); }167};168169struct __gmp_unary_minus170{171static void eval(mpz_ptr z, mpz_srcptr w) { mpz_neg(z, w); }172static void eval(mpq_ptr q, mpq_srcptr r) { mpq_neg(q, r); }173static void eval(mpf_ptr f, mpf_srcptr g) { mpf_neg(f, g); }174};175176struct __gmp_unary_com177{178static void eval(mpz_ptr z, mpz_srcptr w) { mpz_com(z, w); }179};180181struct __gmp_binary_plus182{183static void eval(mpz_ptr z, mpz_srcptr w, mpz_srcptr v)184{ mpz_add(z, w, v); }185186static void eval(mpz_ptr z, mpz_srcptr w, unsigned long int l)187{188// Ideally, those checks should happen earlier so that the tree189// generated for a+0+b would just be sum(a,b).190if (__GMPXX_CONSTANT(l) && l == 0)191{192if (z != w) mpz_set(z, w);193}194else195mpz_add_ui(z, w, l);196}197static void eval(mpz_ptr z, unsigned long int l, mpz_srcptr w)198{ eval(z, w, l); }199static void eval(mpz_ptr z, mpz_srcptr w, signed long int l)200{201if (l >= 0)202eval(z, w, static_cast<unsigned long>(l));203else204mpz_sub_ui(z, w, -static_cast<unsigned long>(l));205}206static void eval(mpz_ptr z, signed long int l, mpz_srcptr w)207{ eval(z, w, l); }208static void eval(mpz_ptr z, mpz_srcptr w, double d)209{ __GMPXX_TMPZ_D; mpz_add (z, w, temp); }210static void eval(mpz_ptr z, double d, mpz_srcptr w)211{ eval(z, w, d); }212213static void eval(mpq_ptr q, mpq_srcptr r, mpq_srcptr s)214{ mpq_add(q, r, s); }215216static void eval(mpq_ptr q, mpq_srcptr r, unsigned long int l)217{218if (__GMPXX_CONSTANT(l) && l == 0)219{220if (q != r) mpq_set(q, r);221}222else223{224if (q == r)225mpz_addmul_ui(mpq_numref(q), mpq_denref(q), l);226else227{228mpz_mul_ui(mpq_numref(q), mpq_denref(r), l);229mpz_add(mpq_numref(q), mpq_numref(q), mpq_numref(r));230mpz_set(mpq_denref(q), mpq_denref(r));231}232}233}234static void eval(mpq_ptr q, unsigned long int l, mpq_srcptr r)235{ eval(q, r, l); }236static inline void eval(mpq_ptr q, mpq_srcptr r, signed long int l);237// defined after __gmp_binary_minus238static void eval(mpq_ptr q, signed long int l, mpq_srcptr r)239{ eval(q, r, l); }240static void eval(mpq_ptr q, mpq_srcptr r, double d)241{ __GMPXX_TMPQ_D; mpq_add (q, r, temp); }242static void eval(mpq_ptr q, double d, mpq_srcptr r)243{ eval(q, r, d); }244245static void eval(mpq_ptr q, mpq_srcptr r, mpz_srcptr z)246{247if (q == r)248mpz_addmul(mpq_numref(q), mpq_denref(q), z);249else250{251mpz_mul(mpq_numref(q), mpq_denref(r), z);252mpz_add(mpq_numref(q), mpq_numref(q), mpq_numref(r));253mpz_set(mpq_denref(q), mpq_denref(r));254}255}256static void eval(mpq_ptr q, mpz_srcptr z, mpq_srcptr r)257{ eval(q, r, z); }258259static void eval(mpf_ptr f, mpf_srcptr g, mpf_srcptr h)260{ mpf_add(f, g, h); }261262static void eval(mpf_ptr f, mpf_srcptr g, unsigned long int l)263{ mpf_add_ui(f, g, l); }264static void eval(mpf_ptr f, unsigned long int l, mpf_srcptr g)265{ mpf_add_ui(f, g, l); }266static void eval(mpf_ptr f, mpf_srcptr g, signed long int l)267{268if (l >= 0)269mpf_add_ui(f, g, l);270else271mpf_sub_ui(f, g, -static_cast<unsigned long>(l));272}273static void eval(mpf_ptr f, signed long int l, mpf_srcptr g)274{ eval(f, g, l); }275static void eval(mpf_ptr f, mpf_srcptr g, double d)276{277mpf_t temp;278mpf_init2(temp, 8*sizeof(double));279mpf_set_d(temp, d);280mpf_add(f, g, temp);281mpf_clear(temp);282}283static void eval(mpf_ptr f, double d, mpf_srcptr g)284{ eval(f, g, d); }285};286287struct __gmp_binary_minus288{289static void eval(mpz_ptr z, mpz_srcptr w, mpz_srcptr v)290{ mpz_sub(z, w, v); }291292static void eval(mpz_ptr z, mpz_srcptr w, unsigned long int l)293{294if (__GMPXX_CONSTANT(l) && l == 0)295{296if (z != w) mpz_set(z, w);297}298else299mpz_sub_ui(z, w, l);300}301static void eval(mpz_ptr z, unsigned long int l, mpz_srcptr w)302{303if (__GMPXX_CONSTANT(l) && l == 0)304{305mpz_neg(z, w);306}307else308mpz_ui_sub(z, l, w);309}310static void eval(mpz_ptr z, mpz_srcptr w, signed long int l)311{312if (l >= 0)313eval(z, w, static_cast<unsigned long>(l));314else315mpz_add_ui(z, w, -static_cast<unsigned long>(l));316}317static void eval(mpz_ptr z, signed long int l, mpz_srcptr w)318{319if (l >= 0)320eval(z, static_cast<unsigned long>(l), w);321else322{323mpz_add_ui(z, w, -static_cast<unsigned long>(l));324mpz_neg(z, z);325}326}327static void eval(mpz_ptr z, mpz_srcptr w, double d)328{ __GMPXX_TMPZ_D; mpz_sub (z, w, temp); }329static void eval(mpz_ptr z, double d, mpz_srcptr w)330{ __GMPXX_TMPZ_D; mpz_sub (z, temp, w); }331332static void eval(mpq_ptr q, mpq_srcptr r, mpq_srcptr s)333{ mpq_sub(q, r, s); }334335static void eval(mpq_ptr q, mpq_srcptr r, unsigned long int l)336{337if (__GMPXX_CONSTANT(l) && l == 0)338{339if (q != r) mpq_set(q, r);340}341else342{343if (q == r)344mpz_submul_ui(mpq_numref(q), mpq_denref(q), l);345else346{347mpz_mul_ui(mpq_numref(q), mpq_denref(r), l);348mpz_sub(mpq_numref(q), mpq_numref(r), mpq_numref(q));349mpz_set(mpq_denref(q), mpq_denref(r));350}351}352}353static void eval(mpq_ptr q, unsigned long int l, mpq_srcptr r)354{ eval(q, r, l); mpq_neg(q, q); }355static void eval(mpq_ptr q, mpq_srcptr r, signed long int l)356{357if (l >= 0)358eval(q, r, static_cast<unsigned long>(l));359else360__gmp_binary_plus::eval(q, r, -static_cast<unsigned long>(l));361}362static void eval(mpq_ptr q, signed long int l, mpq_srcptr r)363{ eval(q, r, l); mpq_neg(q, q); }364static void eval(mpq_ptr q, mpq_srcptr r, double d)365{ __GMPXX_TMPQ_D; mpq_sub (q, r, temp); }366static void eval(mpq_ptr q, double d, mpq_srcptr r)367{ __GMPXX_TMPQ_D; mpq_sub (q, temp, r); }368369static void eval(mpq_ptr q, mpq_srcptr r, mpz_srcptr z)370{371if (q == r)372mpz_submul(mpq_numref(q), mpq_denref(q), z);373else374{375mpz_mul(mpq_numref(q), mpq_denref(r), z);376mpz_sub(mpq_numref(q), mpq_numref(r), mpq_numref(q));377mpz_set(mpq_denref(q), mpq_denref(r));378}379}380static void eval(mpq_ptr q, mpz_srcptr z, mpq_srcptr r)381{ eval(q, r, z); mpq_neg(q, q); }382383static void eval(mpf_ptr f, mpf_srcptr g, mpf_srcptr h)384{ mpf_sub(f, g, h); }385386static void eval(mpf_ptr f, mpf_srcptr g, unsigned long int l)387{ mpf_sub_ui(f, g, l); }388static void eval(mpf_ptr f, unsigned long int l, mpf_srcptr g)389{ mpf_ui_sub(f, l, g); }390static void eval(mpf_ptr f, mpf_srcptr g, signed long int l)391{392if (l >= 0)393mpf_sub_ui(f, g, l);394else395mpf_add_ui(f, g, -static_cast<unsigned long>(l));396}397static void eval(mpf_ptr f, signed long int l, mpf_srcptr g)398{399if (l >= 0)400mpf_sub_ui(f, g, l);401else402mpf_add_ui(f, g, -static_cast<unsigned long>(l));403mpf_neg(f, f);404}405static void eval(mpf_ptr f, mpf_srcptr g, double d)406{407mpf_t temp;408mpf_init2(temp, 8*sizeof(double));409mpf_set_d(temp, d);410mpf_sub(f, g, temp);411mpf_clear(temp);412}413static void eval(mpf_ptr f, double d, mpf_srcptr g)414{415mpf_t temp;416mpf_init2(temp, 8*sizeof(double));417mpf_set_d(temp, d);418mpf_sub(f, temp, g);419mpf_clear(temp);420}421};422423// defined here so it can reference __gmp_binary_minus424inline void425__gmp_binary_plus::eval(mpq_ptr q, mpq_srcptr r, signed long int l)426{427if (l >= 0)428eval(q, r, static_cast<unsigned long>(l));429else430__gmp_binary_minus::eval(q, r, -static_cast<unsigned long>(l));431}432433struct __gmp_binary_lshift434{435static void eval(mpz_ptr z, mpz_srcptr w, mp_bitcnt_t l)436{437if (__GMPXX_CONSTANT(l) && (l == 0))438{439if (z != w) mpz_set(z, w);440}441else442mpz_mul_2exp(z, w, l);443}444static void eval(mpq_ptr q, mpq_srcptr r, mp_bitcnt_t l)445{446if (__GMPXX_CONSTANT(l) && (l == 0))447{448if (q != r) mpq_set(q, r);449}450else451mpq_mul_2exp(q, r, l);452}453static void eval(mpf_ptr f, mpf_srcptr g, mp_bitcnt_t l)454{ mpf_mul_2exp(f, g, l); }455};456457struct __gmp_binary_rshift458{459static void eval(mpz_ptr z, mpz_srcptr w, mp_bitcnt_t l)460{461if (__GMPXX_CONSTANT(l) && (l == 0))462{463if (z != w) mpz_set(z, w);464}465else466mpz_fdiv_q_2exp(z, w, l);467}468static void eval(mpq_ptr q, mpq_srcptr r, mp_bitcnt_t l)469{470if (__GMPXX_CONSTANT(l) && (l == 0))471{472if (q != r) mpq_set(q, r);473}474else475mpq_div_2exp(q, r, l);476}477static void eval(mpf_ptr f, mpf_srcptr g, mp_bitcnt_t l)478{ mpf_div_2exp(f, g, l); }479};480481struct __gmp_binary_multiplies482{483static void eval(mpz_ptr z, mpz_srcptr w, mpz_srcptr v)484{ mpz_mul(z, w, v); }485486static void eval(mpz_ptr z, mpz_srcptr w, unsigned long int l)487{488// gcc-3.3 doesn't have __builtin_ctzl. Don't bother optimizing for old gcc.489#if __GMP_GNUC_PREREQ(3, 4)490if (__GMPXX_CONSTANT(l) && (l & (l-1)) == 0)491{492if (l == 0)493{494z->_mp_size = 0;495}496else497{498__gmp_binary_lshift::eval(z, w, __builtin_ctzl(l));499}500}501else502#endif503mpz_mul_ui(z, w, l);504}505static void eval(mpz_ptr z, unsigned long int l, mpz_srcptr w)506{ eval(z, w, l); }507static void eval(mpz_ptr z, mpz_srcptr w, signed long int l)508{509if (__GMPXX_CONSTANT_TRUE(l >= 0))510eval(z, w, static_cast<unsigned long>(l));511else if (__GMPXX_CONSTANT_TRUE(l <= 0))512{513eval(z, w, -static_cast<unsigned long>(l));514mpz_neg(z, z);515}516else517mpz_mul_si (z, w, l);518}519static void eval(mpz_ptr z, signed long int l, mpz_srcptr w)520{ eval(z, w, l); }521static void eval(mpz_ptr z, mpz_srcptr w, double d)522{ __GMPXX_TMPZ_D; mpz_mul (z, w, temp); }523static void eval(mpz_ptr z, double d, mpz_srcptr w)524{ eval(z, w, d); }525526static void eval(mpq_ptr q, mpq_srcptr r, mpq_srcptr s)527{ mpq_mul(q, r, s); }528529static void eval(mpq_ptr q, mpq_srcptr r, unsigned long int l)530{531#if __GMP_GNUC_PREREQ(3, 4)532if (__GMPXX_CONSTANT(l) && (l & (l-1)) == 0)533{534if (l == 0)535{536mpq_set_ui(q, 0, 1);537}538else539{540__gmp_binary_lshift::eval(q, r, __builtin_ctzl(l));541}542}543else544#endif545{546__GMPXX_TMPQ_UI;547mpq_mul (q, r, temp);548}549}550static void eval(mpq_ptr q, unsigned long int l, mpq_srcptr r)551{ eval(q, r, l); }552static void eval(mpq_ptr q, mpq_srcptr r, signed long int l)553{554if (__GMPXX_CONSTANT_TRUE(l >= 0))555eval(q, r, static_cast<unsigned long>(l));556else if (__GMPXX_CONSTANT_TRUE(l <= 0))557{558eval(q, r, -static_cast<unsigned long>(l));559mpq_neg(q, q);560}561else562{563__GMPXX_TMPQ_SI;564mpq_mul (q, r, temp);565}566}567static void eval(mpq_ptr q, signed long int l, mpq_srcptr r)568{ eval(q, r, l); }569static void eval(mpq_ptr q, mpq_srcptr r, double d)570{ __GMPXX_TMPQ_D; mpq_mul (q, r, temp); }571static void eval(mpq_ptr q, double d, mpq_srcptr r)572{ eval(q, r, d); }573574static void eval(mpf_ptr f, mpf_srcptr g, mpf_srcptr h)575{ mpf_mul(f, g, h); }576577static void eval(mpf_ptr f, mpf_srcptr g, unsigned long int l)578{ mpf_mul_ui(f, g, l); }579static void eval(mpf_ptr f, unsigned long int l, mpf_srcptr g)580{ mpf_mul_ui(f, g, l); }581static void eval(mpf_ptr f, mpf_srcptr g, signed long int l)582{583if (l >= 0)584mpf_mul_ui(f, g, l);585else586{587mpf_mul_ui(f, g, -static_cast<unsigned long>(l));588mpf_neg(f, f);589}590}591static void eval(mpf_ptr f, signed long int l, mpf_srcptr g)592{ eval(f, g, l); }593static void eval(mpf_ptr f, mpf_srcptr g, double d)594{595mpf_t temp;596mpf_init2(temp, 8*sizeof(double));597mpf_set_d(temp, d);598mpf_mul(f, g, temp);599mpf_clear(temp);600}601static void eval(mpf_ptr f, double d, mpf_srcptr g)602{ eval(f, g, d); }603};604605struct __gmp_binary_divides606{607static void eval(mpz_ptr z, mpz_srcptr w, mpz_srcptr v)608{ mpz_tdiv_q(z, w, v); }609610static void eval(mpz_ptr z, mpz_srcptr w, unsigned long int l)611{612#if __GMP_GNUC_PREREQ(3, 4)613// Don't optimize division by 0...614if (__GMPXX_CONSTANT(l) && (l & (l-1)) == 0 && l != 0)615{616if (l == 1)617{618if (z != w) mpz_set(z, w);619}620else621mpz_tdiv_q_2exp(z, w, __builtin_ctzl(l));622// warning: do not use rshift (fdiv)623}624else625#endif626mpz_tdiv_q_ui(z, w, l);627}628static void eval(mpz_ptr z, unsigned long int l, mpz_srcptr w)629{630if (mpz_sgn(w) >= 0)631{632if (mpz_fits_ulong_p(w))633mpz_set_ui(z, l / mpz_get_ui(w));634else635mpz_set_ui(z, 0);636}637else638{639mpz_neg(z, w);640if (mpz_fits_ulong_p(z))641{642mpz_set_ui(z, l / mpz_get_ui(z));643mpz_neg(z, z);644}645else646mpz_set_ui(z, 0);647}648}649static void eval(mpz_ptr z, mpz_srcptr w, signed long int l)650{651if (l >= 0)652eval(z, w, static_cast<unsigned long>(l));653else654{655eval(z, w, -static_cast<unsigned long>(l));656mpz_neg(z, z);657}658}659static void eval(mpz_ptr z, signed long int l, mpz_srcptr w)660{661if (mpz_fits_slong_p(w))662mpz_set_si(z, l / mpz_get_si(w));663else664{665/* if w is bigger than a long then the quotient must be zero, unless666l==LONG_MIN and w==-LONG_MIN in which case the quotient is -1 */667mpz_set_si (z, (mpz_cmpabs_ui (w, __gmpxx_abs_ui(l)) == 0 ? -1 : 0));668}669}670static void eval(mpz_ptr z, mpz_srcptr w, double d)671{ __GMPXX_TMPZ_D; mpz_tdiv_q (z, w, temp); }672static void eval(mpz_ptr z, double d, mpz_srcptr w)673{ __GMPXX_TMPZ_D; mpz_tdiv_q (z, temp, w); }674675static void eval(mpq_ptr q, mpq_srcptr r, mpq_srcptr s)676{ mpq_div(q, r, s); }677678static void eval(mpq_ptr q, mpq_srcptr r, unsigned long int l)679{680#if __GMP_GNUC_PREREQ(3, 4)681if (__GMPXX_CONSTANT(l) && (l & (l-1)) == 0 && l != 0)682__gmp_binary_rshift::eval(q, r, __builtin_ctzl(l));683else684#endif685{686__GMPXX_TMPQ_UI;687mpq_div (q, r, temp);688}689}690static void eval(mpq_ptr q, unsigned long int l, mpq_srcptr r)691{ __GMPXX_TMPQ_UI; mpq_div (q, temp, r); }692static void eval(mpq_ptr q, mpq_srcptr r, signed long int l)693{694if (__GMPXX_CONSTANT_TRUE(l >= 0))695eval(q, r, static_cast<unsigned long>(l));696else if (__GMPXX_CONSTANT_TRUE(l <= 0))697{698eval(q, r, -static_cast<unsigned long>(l));699mpq_neg(q, q);700}701else702{703__GMPXX_TMPQ_SI;704mpq_div (q, r, temp);705}706}707static void eval(mpq_ptr q, signed long int l, mpq_srcptr r)708{ __GMPXX_TMPQ_SI; mpq_div (q, temp, r); }709static void eval(mpq_ptr q, mpq_srcptr r, double d)710{ __GMPXX_TMPQ_D; mpq_div (q, r, temp); }711static void eval(mpq_ptr q, double d, mpq_srcptr r)712{ __GMPXX_TMPQ_D; mpq_div (q, temp, r); }713714static void eval(mpf_ptr f, mpf_srcptr g, mpf_srcptr h)715{ mpf_div(f, g, h); }716717static void eval(mpf_ptr f, mpf_srcptr g, unsigned long int l)718{ mpf_div_ui(f, g, l); }719static void eval(mpf_ptr f, unsigned long int l, mpf_srcptr g)720{ mpf_ui_div(f, l, g); }721static void eval(mpf_ptr f, mpf_srcptr g, signed long int l)722{723if (l >= 0)724mpf_div_ui(f, g, l);725else726{727mpf_div_ui(f, g, -static_cast<unsigned long>(l));728mpf_neg(f, f);729}730}731static void eval(mpf_ptr f, signed long int l, mpf_srcptr g)732{733if (l >= 0)734mpf_ui_div(f, l, g);735else736{737mpf_ui_div(f, -static_cast<unsigned long>(l), g);738mpf_neg(f, f);739}740}741static void eval(mpf_ptr f, mpf_srcptr g, double d)742{743mpf_t temp;744mpf_init2(temp, 8*sizeof(double));745mpf_set_d(temp, d);746mpf_div(f, g, temp);747mpf_clear(temp);748}749static void eval(mpf_ptr f, double d, mpf_srcptr g)750{751mpf_t temp;752mpf_init2(temp, 8*sizeof(double));753mpf_set_d(temp, d);754mpf_div(f, temp, g);755mpf_clear(temp);756}757};758759struct __gmp_binary_modulus760{761static void eval(mpz_ptr z, mpz_srcptr w, mpz_srcptr v)762{ mpz_tdiv_r(z, w, v); }763764static void eval(mpz_ptr z, mpz_srcptr w, unsigned long int l)765{ mpz_tdiv_r_ui(z, w, l); }766static void eval(mpz_ptr z, unsigned long int l, mpz_srcptr w)767{768if (mpz_sgn(w) >= 0)769{770if (mpz_fits_ulong_p(w))771mpz_set_ui(z, l % mpz_get_ui(w));772else773mpz_set_ui(z, l);774}775else776{777mpz_neg(z, w);778if (mpz_fits_ulong_p(z))779mpz_set_ui(z, l % mpz_get_ui(z));780else781mpz_set_ui(z, l);782}783}784static void eval(mpz_ptr z, mpz_srcptr w, signed long int l)785{786mpz_tdiv_r_ui (z, w, __gmpxx_abs_ui(l));787}788static void eval(mpz_ptr z, signed long int l, mpz_srcptr w)789{790if (mpz_fits_slong_p(w))791mpz_set_si(z, l % mpz_get_si(w));792else793{794/* if w is bigger than a long then the remainder is l unchanged,795unless l==LONG_MIN and w==-LONG_MIN in which case it's 0 */796mpz_set_si (z, mpz_cmpabs_ui (w, __gmpxx_abs_ui(l)) == 0 ? 0 : l);797}798}799static void eval(mpz_ptr z, mpz_srcptr w, double d)800{ __GMPXX_TMPZ_D; mpz_tdiv_r (z, w, temp); }801static void eval(mpz_ptr z, double d, mpz_srcptr w)802{ __GMPXX_TMPZ_D; mpz_tdiv_r (z, temp, w); }803};804805struct __gmp_binary_and806{807static void eval(mpz_ptr z, mpz_srcptr w, mpz_srcptr v)808{ mpz_and(z, w, v); }809810static void eval(mpz_ptr z, mpz_srcptr w, unsigned long int l)811{ __GMPXX_TMPZ_UI; mpz_and (z, w, temp); }812static void eval(mpz_ptr z, unsigned long int l, mpz_srcptr w)813{ eval(z, w, l); }814static void eval(mpz_ptr z, mpz_srcptr w, signed long int l)815{ __GMPXX_TMPZ_SI; mpz_and (z, w, temp); }816static void eval(mpz_ptr z, signed long int l, mpz_srcptr w)817{ eval(z, w, l); }818static void eval(mpz_ptr z, mpz_srcptr w, double d)819{ __GMPXX_TMPZ_D; mpz_and (z, w, temp); }820static void eval(mpz_ptr z, double d, mpz_srcptr w)821{ eval(z, w, d); }822};823824struct __gmp_binary_ior825{826static void eval(mpz_ptr z, mpz_srcptr w, mpz_srcptr v)827{ mpz_ior(z, w, v); }828static void eval(mpz_ptr z, mpz_srcptr w, unsigned long int l)829{ __GMPXX_TMPZ_UI; mpz_ior (z, w, temp); }830static void eval(mpz_ptr z, unsigned long int l, mpz_srcptr w)831{ eval(z, w, l); }832static void eval(mpz_ptr z, mpz_srcptr w, signed long int l)833{ __GMPXX_TMPZ_SI; mpz_ior (z, w, temp); }834static void eval(mpz_ptr z, signed long int l, mpz_srcptr w)835{ eval(z, w, l); }836static void eval(mpz_ptr z, mpz_srcptr w, double d)837{ __GMPXX_TMPZ_D; mpz_ior (z, w, temp); }838static void eval(mpz_ptr z, double d, mpz_srcptr w)839{ eval(z, w, d); }840};841842struct __gmp_binary_xor843{844static void eval(mpz_ptr z, mpz_srcptr w, mpz_srcptr v)845{ mpz_xor(z, w, v); }846static void eval(mpz_ptr z, mpz_srcptr w, unsigned long int l)847{ __GMPXX_TMPZ_UI; mpz_xor (z, w, temp); }848static void eval(mpz_ptr z, unsigned long int l, mpz_srcptr w)849{ eval(z, w, l); }850static void eval(mpz_ptr z, mpz_srcptr w, signed long int l)851{ __GMPXX_TMPZ_SI; mpz_xor (z, w, temp); }852static void eval(mpz_ptr z, signed long int l, mpz_srcptr w)853{ eval(z, w, l); }854static void eval(mpz_ptr z, mpz_srcptr w, double d)855{ __GMPXX_TMPZ_D; mpz_xor (z, w, temp); }856static void eval(mpz_ptr z, double d, mpz_srcptr w)857{ eval(z, w, d); }858};859860struct __gmp_binary_equal861{862static bool eval(mpz_srcptr z, mpz_srcptr w) { return mpz_cmp(z, w) == 0; }863864static bool eval(mpz_srcptr z, unsigned long int l)865{ return mpz_cmp_ui(z, l) == 0; }866static bool eval(unsigned long int l, mpz_srcptr z)867{ return eval(z, l); }868static bool eval(mpz_srcptr z, signed long int l)869{ return mpz_cmp_si(z, l) == 0; }870static bool eval(signed long int l, mpz_srcptr z)871{ return eval(z, l); }872static bool eval(mpz_srcptr z, double d)873{ return mpz_cmp_d(z, d) == 0; }874static bool eval(double d, mpz_srcptr z)875{ return eval(z, d); }876877static bool eval(mpq_srcptr q, mpq_srcptr r)878{ return mpq_equal(q, r) != 0; }879880static bool eval(mpq_srcptr q, unsigned long int l)881{ return mpq_cmp_ui(q, l, 1) == 0; }882static bool eval(unsigned long int l, mpq_srcptr q)883{ return eval(q, l); }884static bool eval(mpq_srcptr q, signed long int l)885{ return mpq_cmp_si(q, l, 1) == 0; }886static bool eval(signed long int l, mpq_srcptr q)887{ return eval(q, l); }888static bool eval(mpq_srcptr q, double d)889{ __GMPXX_TMPQ_D; return mpq_equal (q, temp) != 0; }890static bool eval(double d, mpq_srcptr q)891{ return eval(q, d); }892893static bool eval(mpf_srcptr f, mpf_srcptr g) { return mpf_cmp(f, g) == 0; }894895static bool eval(mpf_srcptr f, unsigned long int l)896{ return mpf_cmp_ui(f, l) == 0; }897static bool eval(unsigned long int l, mpf_srcptr f)898{ return eval(f, l); }899static bool eval(mpf_srcptr f, signed long int l)900{ return mpf_cmp_si(f, l) == 0; }901static bool eval(signed long int l, mpf_srcptr f)902{ return eval(f, l); }903static bool eval(mpf_srcptr f, double d)904{ return mpf_cmp_d(f, d) == 0; }905static bool eval(double d, mpf_srcptr f)906{ return eval(f, d); }907};908909struct __gmp_binary_less910{911static bool eval(mpz_srcptr z, mpz_srcptr w) { return mpz_cmp(z, w) < 0; }912913static bool eval(mpz_srcptr z, unsigned long int l)914{ return mpz_cmp_ui(z, l) < 0; }915static bool eval(unsigned long int l, mpz_srcptr z)916{ return mpz_cmp_ui(z, l) > 0; }917static bool eval(mpz_srcptr z, signed long int l)918{ return mpz_cmp_si(z, l) < 0; }919static bool eval(signed long int l, mpz_srcptr z)920{ return mpz_cmp_si(z, l) > 0; }921static bool eval(mpz_srcptr z, double d)922{ return mpz_cmp_d(z, d) < 0; }923static bool eval(double d, mpz_srcptr z)924{ return mpz_cmp_d(z, d) > 0; }925926static bool eval(mpq_srcptr q, mpq_srcptr r) { return mpq_cmp(q, r) < 0; }927928static bool eval(mpq_srcptr q, unsigned long int l)929{ return mpq_cmp_ui(q, l, 1) < 0; }930static bool eval(unsigned long int l, mpq_srcptr q)931{ return mpq_cmp_ui(q, l, 1) > 0; }932static bool eval(mpq_srcptr q, signed long int l)933{ return mpq_cmp_si(q, l, 1) < 0; }934static bool eval(signed long int l, mpq_srcptr q)935{ return mpq_cmp_si(q, l, 1) > 0; }936static bool eval(mpq_srcptr q, double d)937{ __GMPXX_TMPQ_D; return mpq_cmp (q, temp) < 0; }938static bool eval(double d, mpq_srcptr q)939{ __GMPXX_TMPQ_D; return mpq_cmp (temp, q) < 0; }940941static bool eval(mpf_srcptr f, mpf_srcptr g) { return mpf_cmp(f, g) < 0; }942943static bool eval(mpf_srcptr f, unsigned long int l)944{ return mpf_cmp_ui(f, l) < 0; }945static bool eval(unsigned long int l, mpf_srcptr f)946{ return mpf_cmp_ui(f, l) > 0; }947static bool eval(mpf_srcptr f, signed long int l)948{ return mpf_cmp_si(f, l) < 0; }949static bool eval(signed long int l, mpf_srcptr f)950{ return mpf_cmp_si(f, l) > 0; }951static bool eval(mpf_srcptr f, double d)952{ return mpf_cmp_d(f, d) < 0; }953static bool eval(double d, mpf_srcptr f)954{ return mpf_cmp_d(f, d) > 0; }955};956957struct __gmp_binary_greater958{959template <class T, class U>960static inline bool eval(T t, U u) { return __gmp_binary_less::eval(u, t); }961};962963struct __gmp_unary_increment964{965static void eval(mpz_ptr z) { mpz_add_ui(z, z, 1); }966static void eval(mpq_ptr q)967{ mpz_add(mpq_numref(q), mpq_numref(q), mpq_denref(q)); }968static void eval(mpf_ptr f) { mpf_add_ui(f, f, 1); }969};970971struct __gmp_unary_decrement972{973static void eval(mpz_ptr z) { mpz_sub_ui(z, z, 1); }974static void eval(mpq_ptr q)975{ mpz_sub(mpq_numref(q), mpq_numref(q), mpq_denref(q)); }976static void eval(mpf_ptr f) { mpf_sub_ui(f, f, 1); }977};978979struct __gmp_abs_function980{981static void eval(mpz_ptr z, mpz_srcptr w) { mpz_abs(z, w); }982static void eval(mpq_ptr q, mpq_srcptr r) { mpq_abs(q, r); }983static void eval(mpf_ptr f, mpf_srcptr g) { mpf_abs(f, g); }984};985986struct __gmp_trunc_function987{988static void eval(mpf_ptr f, mpf_srcptr g) { mpf_trunc(f, g); }989};990991struct __gmp_floor_function992{993static void eval(mpf_ptr f, mpf_srcptr g) { mpf_floor(f, g); }994};995996struct __gmp_ceil_function997{998static void eval(mpf_ptr f, mpf_srcptr g) { mpf_ceil(f, g); }999};10001001struct __gmp_sqrt_function1002{1003static void eval(mpz_ptr z, mpz_srcptr w) { mpz_sqrt(z, w); }1004static void eval(mpf_ptr f, mpf_srcptr g) { mpf_sqrt(f, g); }1005};10061007struct __gmp_hypot_function1008{1009static void eval(mpf_ptr f, mpf_srcptr g, mpf_srcptr h)1010{1011mpf_t temp;1012mpf_init2(temp, mpf_get_prec(f));1013mpf_mul(temp, g, g);1014mpf_mul(f, h, h);1015mpf_add(f, f, temp);1016mpf_sqrt(f, f);1017mpf_clear(temp);1018}10191020static void eval(mpf_ptr f, mpf_srcptr g, unsigned long int l)1021{1022mpf_t temp;1023mpf_init2(temp, mpf_get_prec(f));1024mpf_mul(temp, g, g);1025mpf_set_ui(f, l);1026mpf_mul_ui(f, f, l);1027mpf_add(f, f, temp);1028mpf_clear(temp);1029mpf_sqrt(f, f);1030}1031static void eval(mpf_ptr f, unsigned long int l, mpf_srcptr g)1032{ eval(f, g, l); }1033static void eval(mpf_ptr f, mpf_srcptr g, signed long int l)1034{ eval(f, g, __gmpxx_abs_ui(l)); }1035static void eval(mpf_ptr f, signed long int l, mpf_srcptr g)1036{ eval(f, g, l); }1037static void eval(mpf_ptr f, mpf_srcptr g, double d)1038{1039mpf_t temp;1040mpf_init2(temp, mpf_get_prec(f));1041mpf_mul(temp, g, g);1042mpf_set_d(f, d);1043mpf_mul(f, f, f);1044mpf_add(f, f, temp);1045mpf_sqrt(f, f);1046mpf_clear(temp);1047}1048static void eval(mpf_ptr f, double d, mpf_srcptr g)1049{ eval(f, g, d); }1050};10511052struct __gmp_sgn_function1053{1054static int eval(mpz_srcptr z) { return mpz_sgn(z); }1055static int eval(mpq_srcptr q) { return mpq_sgn(q); }1056static int eval(mpf_srcptr f) { return mpf_sgn(f); }1057};10581059struct __gmp_cmp_function1060{1061static int eval(mpz_srcptr z, mpz_srcptr w) { return mpz_cmp(z, w); }10621063static int eval(mpz_srcptr z, unsigned long int l)1064{ return mpz_cmp_ui(z, l); }1065static int eval(unsigned long int l, mpz_srcptr z)1066{ return -mpz_cmp_ui(z, l); }1067static int eval(mpz_srcptr z, signed long int l)1068{ return mpz_cmp_si(z, l); }1069static int eval(signed long int l, mpz_srcptr z)1070{ return -mpz_cmp_si(z, l); }1071static int eval(mpz_srcptr z, double d)1072{ return mpz_cmp_d(z, d); }1073static int eval(double d, mpz_srcptr z)1074{ return -mpz_cmp_d(z, d); }10751076static int eval(mpq_srcptr q, mpq_srcptr r) { return mpq_cmp(q, r); }10771078static int eval(mpq_srcptr q, unsigned long int l)1079{ return mpq_cmp_ui(q, l, 1); }1080static int eval(unsigned long int l, mpq_srcptr q)1081{ return -mpq_cmp_ui(q, l, 1); }1082static int eval(mpq_srcptr q, signed long int l)1083{ return mpq_cmp_si(q, l, 1); }1084static int eval(signed long int l, mpq_srcptr q)1085{ return -mpq_cmp_si(q, l, 1); }1086static int eval(mpq_srcptr q, double d)1087{ __GMPXX_TMPQ_D; return mpq_cmp (q, temp); }1088static int eval(double d, mpq_srcptr q)1089{ __GMPXX_TMPQ_D; return mpq_cmp (temp, q); }10901091static int eval(mpf_srcptr f, mpf_srcptr g) { return mpf_cmp(f, g); }10921093static int eval(mpf_srcptr f, unsigned long int l)1094{ return mpf_cmp_ui(f, l); }1095static int eval(unsigned long int l, mpf_srcptr f)1096{ return -mpf_cmp_ui(f, l); }1097static int eval(mpf_srcptr f, signed long int l)1098{ return mpf_cmp_si(f, l); }1099static int eval(signed long int l, mpf_srcptr f)1100{ return -mpf_cmp_si(f, l); }1101static int eval(mpf_srcptr f, double d)1102{ return mpf_cmp_d(f, d); }1103static int eval(double d, mpf_srcptr f)1104{ return -mpf_cmp_d(f, d); }1105};11061107struct __gmp_rand_function1108{1109static void eval(mpz_ptr z, gmp_randstate_t s, mp_bitcnt_t l)1110{ mpz_urandomb(z, s, l); }1111static void eval(mpz_ptr z, gmp_randstate_t s, mpz_srcptr w)1112{ mpz_urandomm(z, s, w); }1113static void eval(mpf_ptr f, gmp_randstate_t s, mp_bitcnt_t prec)1114{ mpf_urandomb(f, s, prec); }1115};111611171118/**************** Auxiliary classes ****************/11191120/* this is much the same as gmp_allocated_string in gmp-impl.h1121since gmp-impl.h is not publicly available, I redefine it here1122I use a different name to avoid possible clashes */11231124extern "C" {1125typedef void (*__gmp_freefunc_t) (void *, size_t);1126}1127struct __gmp_alloc_cstring1128{1129char *str;1130__gmp_alloc_cstring(char *s) { str = s; }1131~__gmp_alloc_cstring()1132{1133__gmp_freefunc_t freefunc;1134mp_get_memory_functions (NULL, NULL, &freefunc);1135(*freefunc) (str, std::strlen(str)+1);1136}1137};113811391140// general expression template class1141template <class T, class U>1142class __gmp_expr;114311441145// templates for resolving expression types1146template <class T>1147struct __gmp_resolve_ref1148{1149typedef T ref_type;1150};11511152template <class T, class U>1153struct __gmp_resolve_ref<__gmp_expr<T, U> >1154{1155typedef const __gmp_expr<T, U> & ref_type;1156};115711581159template <class T, class U = T>1160struct __gmp_resolve_expr;11611162template <>1163struct __gmp_resolve_expr<mpz_t>1164{1165typedef mpz_t value_type;1166typedef mpz_ptr ptr_type;1167typedef mpz_srcptr srcptr_type;1168};11691170template <>1171struct __gmp_resolve_expr<mpq_t>1172{1173typedef mpq_t value_type;1174typedef mpq_ptr ptr_type;1175typedef mpq_srcptr srcptr_type;1176};11771178template <>1179struct __gmp_resolve_expr<mpf_t>1180{1181typedef mpf_t value_type;1182typedef mpf_ptr ptr_type;1183typedef mpf_srcptr srcptr_type;1184};11851186template <>1187struct __gmp_resolve_expr<mpz_t, mpq_t>1188{1189typedef mpq_t value_type;1190};11911192template <>1193struct __gmp_resolve_expr<mpq_t, mpz_t>1194{1195typedef mpq_t value_type;1196};11971198template <>1199struct __gmp_resolve_expr<mpz_t, mpf_t>1200{1201typedef mpf_t value_type;1202};12031204template <>1205struct __gmp_resolve_expr<mpf_t, mpz_t>1206{1207typedef mpf_t value_type;1208};12091210template <>1211struct __gmp_resolve_expr<mpq_t, mpf_t>1212{1213typedef mpf_t value_type;1214};12151216template <>1217struct __gmp_resolve_expr<mpf_t, mpq_t>1218{1219typedef mpf_t value_type;1220};12211222#if __GMPXX_USE_CXX111223namespace std {1224template <class T, class U, class V, class W>1225struct common_type <__gmp_expr<T, U>, __gmp_expr<V, W> >1226{1227private:1228typedef typename __gmp_resolve_expr<T, V>::value_type X;1229public:1230typedef __gmp_expr<X, X> type;1231};12321233template <class T, class U>1234struct common_type <__gmp_expr<T, U>, __gmp_expr<T, U> >1235{1236typedef __gmp_expr<T, U> type;1237};12381239#define __GMPXX_DECLARE_COMMON_TYPE(typ) \1240template <class T, class U> \1241struct common_type <__gmp_expr<T, U>, typ > \1242{ \1243typedef __gmp_expr<T, T> type; \1244}; \1245\1246template <class T, class U> \1247struct common_type <typ, __gmp_expr<T, U> > \1248{ \1249typedef __gmp_expr<T, T> type; \1250}12511252__GMPXX_DECLARE_COMMON_TYPE(signed char);1253__GMPXX_DECLARE_COMMON_TYPE(unsigned char);1254__GMPXX_DECLARE_COMMON_TYPE(signed int);1255__GMPXX_DECLARE_COMMON_TYPE(unsigned int);1256__GMPXX_DECLARE_COMMON_TYPE(signed short int);1257__GMPXX_DECLARE_COMMON_TYPE(unsigned short int);1258__GMPXX_DECLARE_COMMON_TYPE(signed long int);1259__GMPXX_DECLARE_COMMON_TYPE(unsigned long int);1260__GMPXX_DECLARE_COMMON_TYPE(float);1261__GMPXX_DECLARE_COMMON_TYPE(double);1262#undef __GMPXX_DECLARE_COMMON_TYPE1263}1264#endif12651266// classes for evaluating unary and binary expressions1267template <class T, class Op>1268struct __gmp_unary_expr1269{1270const T &val;12711272__gmp_unary_expr(const T &v) : val(v) { }1273private:1274__gmp_unary_expr();1275};12761277template <class T, class U, class Op>1278struct __gmp_binary_expr1279{1280typename __gmp_resolve_ref<T>::ref_type val1;1281typename __gmp_resolve_ref<U>::ref_type val2;12821283__gmp_binary_expr(const T &v1, const U &v2) : val1(v1), val2(v2) { }1284private:1285__gmp_binary_expr();1286};1287128812891290/**************** Macros for in-class declarations ****************/1291/* This is just repetitive code that is easier to maintain if it's written1292only once */12931294#define __GMPP_DECLARE_COMPOUND_OPERATOR(fun) \1295template <class T, class U> \1296__gmp_expr<value_type, value_type> & fun(const __gmp_expr<T, U> &);12971298#define __GMPN_DECLARE_COMPOUND_OPERATOR(fun) \1299__gmp_expr & fun(signed char); \1300__gmp_expr & fun(unsigned char); \1301__gmp_expr & fun(signed int); \1302__gmp_expr & fun(unsigned int); \1303__gmp_expr & fun(signed short int); \1304__gmp_expr & fun(unsigned short int); \1305__gmp_expr & fun(signed long int); \1306__gmp_expr & fun(unsigned long int); \1307__gmp_expr & fun(float); \1308__gmp_expr & fun(double); \1309/* __gmp_expr & fun(long double); */13101311#define __GMP_DECLARE_COMPOUND_OPERATOR(fun) \1312__GMPP_DECLARE_COMPOUND_OPERATOR(fun) \1313__GMPN_DECLARE_COMPOUND_OPERATOR(fun)13141315#define __GMP_DECLARE_COMPOUND_OPERATOR_UI(fun) \1316__gmp_expr & fun(mp_bitcnt_t);13171318#define __GMP_DECLARE_INCREMENT_OPERATOR(fun) \1319inline __gmp_expr & fun(); \1320inline __gmp_expr fun(int);13211322#define __GMPXX_DEFINE_ARITHMETIC_CONSTRUCTORS \1323__gmp_expr(signed char c) { init_si(c); } \1324__gmp_expr(unsigned char c) { init_ui(c); } \1325__gmp_expr(signed int i) { init_si(i); } \1326__gmp_expr(unsigned int i) { init_ui(i); } \1327__gmp_expr(signed short int s) { init_si(s); } \1328__gmp_expr(unsigned short int s) { init_ui(s); } \1329__gmp_expr(signed long int l) { init_si(l); } \1330__gmp_expr(unsigned long int l) { init_ui(l); } \1331__gmp_expr(float f) { init_d(f); } \1332__gmp_expr(double d) { init_d(d); }13331334#define __GMPXX_DEFINE_ARITHMETIC_ASSIGNMENTS \1335__gmp_expr & operator=(signed char c) { assign_si(c); return *this; } \1336__gmp_expr & operator=(unsigned char c) { assign_ui(c); return *this; } \1337__gmp_expr & operator=(signed int i) { assign_si(i); return *this; } \1338__gmp_expr & operator=(unsigned int i) { assign_ui(i); return *this; } \1339__gmp_expr & operator=(signed short int s) { assign_si(s); return *this; } \1340__gmp_expr & operator=(unsigned short int s) { assign_ui(s); return *this; } \1341__gmp_expr & operator=(signed long int l) { assign_si(l); return *this; } \1342__gmp_expr & operator=(unsigned long int l) { assign_ui(l); return *this; } \1343__gmp_expr & operator=(float f) { assign_d(f); return *this; } \1344__gmp_expr & operator=(double d) { assign_d(d); return *this; }13451346/**************** mpz_class -- wrapper for mpz_t ****************/13471348template <>1349class __gmp_expr<mpz_t, mpz_t>1350{1351private:1352typedef mpz_t value_type;1353value_type mp;13541355// Helper functions used for all arithmetic types1356void assign_ui(unsigned long l)1357{1358if (__GMPXX_CONSTANT_TRUE(l == 0))1359mp->_mp_size = 0;1360else1361mpz_set_ui(mp, l);1362}1363void assign_si(signed long l)1364{1365if (__GMPXX_CONSTANT_TRUE(l >= 0))1366assign_ui(l);1367else if (__GMPXX_CONSTANT_TRUE(l <= 0))1368{1369assign_ui(-static_cast<unsigned long>(l));1370mpz_neg(mp, mp);1371}1372else1373mpz_set_si(mp, l);1374}1375void assign_d (double d)1376{1377mpz_set_d (mp, d);1378}13791380void init_ui(unsigned long l)1381{1382if (__GMPXX_CONSTANT_TRUE(l == 0))1383mpz_init(mp);1384else1385mpz_init_set_ui(mp, l);1386}1387void init_si(signed long l)1388{1389if (__GMPXX_CONSTANT_TRUE(l >= 0))1390init_ui(l);1391else if (__GMPXX_CONSTANT_TRUE(l <= 0))1392{1393init_ui(-static_cast<unsigned long>(l));1394mpz_neg(mp, mp);1395}1396else1397mpz_init_set_si(mp, l);1398}1399void init_d (double d)1400{1401mpz_init_set_d (mp, d);1402}14031404public:1405mp_bitcnt_t get_prec() const { return mpf_get_default_prec(); }14061407// constructors and destructor1408__gmp_expr() { mpz_init(mp); }14091410__gmp_expr(const __gmp_expr &z) { mpz_init_set(mp, z.mp); }1411#if __GMPXX_USE_CXX111412__gmp_expr(__gmp_expr &&z)1413{ *mp = *z.mp; mpz_init(z.mp); }1414#endif1415template <class T>1416__gmp_expr(const __gmp_expr<mpz_t, T> &expr)1417{ mpz_init(mp); __gmp_set_expr(mp, expr); }1418template <class T, class U>1419explicit __gmp_expr(const __gmp_expr<T, U> &expr)1420{ mpz_init(mp); __gmp_set_expr(mp, expr); }14211422__GMPXX_DEFINE_ARITHMETIC_CONSTRUCTORS14231424explicit __gmp_expr(const char *s, int base = 0)1425{1426if (mpz_init_set_str (mp, s, base) != 0)1427{1428mpz_clear (mp);1429throw std::invalid_argument ("mpz_set_str");1430}1431}1432explicit __gmp_expr(const std::string &s, int base = 0)1433{1434if (mpz_init_set_str(mp, s.c_str(), base) != 0)1435{1436mpz_clear (mp);1437throw std::invalid_argument ("mpz_set_str");1438}1439}14401441explicit __gmp_expr(mpz_srcptr z) { mpz_init_set(mp, z); }14421443~__gmp_expr() { mpz_clear(mp); }14441445void swap(__gmp_expr& z) __GMPXX_NOEXCEPT { std::swap(*mp, *z.mp); }14461447// assignment operators1448__gmp_expr & operator=(const __gmp_expr &z)1449{ mpz_set(mp, z.mp); return *this; }1450#if __GMPXX_USE_CXX111451__gmp_expr & operator=(__gmp_expr &&z) noexcept1452{ swap(z); return *this; }1453#endif1454template <class T, class U>1455__gmp_expr<value_type, value_type> & operator=(const __gmp_expr<T, U> &expr)1456{ __gmp_set_expr(mp, expr); return *this; }14571458__GMPXX_DEFINE_ARITHMETIC_ASSIGNMENTS14591460__gmp_expr & operator=(const char *s)1461{1462if (mpz_set_str (mp, s, 0) != 0)1463throw std::invalid_argument ("mpz_set_str");1464return *this;1465}1466__gmp_expr & operator=(const std::string &s)1467{1468if (mpz_set_str(mp, s.c_str(), 0) != 0)1469throw std::invalid_argument ("mpz_set_str");1470return *this;1471}14721473// string input/output functions1474int set_str(const char *s, int base)1475{ return mpz_set_str(mp, s, base); }1476int set_str(const std::string &s, int base)1477{ return mpz_set_str(mp, s.c_str(), base); }1478std::string get_str(int base = 10) const1479{1480__gmp_alloc_cstring temp(mpz_get_str(0, base, mp));1481return std::string(temp.str);1482}14831484// conversion functions1485mpz_srcptr __get_mp() const { return mp; }1486mpz_ptr __get_mp() { return mp; }1487mpz_srcptr get_mpz_t() const { return mp; }1488mpz_ptr get_mpz_t() { return mp; }14891490signed long int get_si() const { return mpz_get_si(mp); }1491unsigned long int get_ui() const { return mpz_get_ui(mp); }1492double get_d() const { return mpz_get_d(mp); }14931494// bool fits_schar_p() const { return mpz_fits_schar_p(mp); }1495// bool fits_uchar_p() const { return mpz_fits_uchar_p(mp); }1496bool fits_sint_p() const { return mpz_fits_sint_p(mp); }1497bool fits_uint_p() const { return mpz_fits_uint_p(mp); }1498bool fits_sshort_p() const { return mpz_fits_sshort_p(mp); }1499bool fits_ushort_p() const { return mpz_fits_ushort_p(mp); }1500bool fits_slong_p() const { return mpz_fits_slong_p(mp); }1501bool fits_ulong_p() const { return mpz_fits_ulong_p(mp); }1502// bool fits_float_p() const { return mpz_fits_float_p(mp); }1503// bool fits_double_p() const { return mpz_fits_double_p(mp); }1504// bool fits_ldouble_p() const { return mpz_fits_ldouble_p(mp); }15051506#if __GMPXX_USE_CXX111507explicit operator bool() const { return mp->_mp_size != 0; }1508#endif15091510// member operators1511__GMP_DECLARE_COMPOUND_OPERATOR(operator+=)1512__GMP_DECLARE_COMPOUND_OPERATOR(operator-=)1513__GMP_DECLARE_COMPOUND_OPERATOR(operator*=)1514__GMP_DECLARE_COMPOUND_OPERATOR(operator/=)1515__GMP_DECLARE_COMPOUND_OPERATOR(operator%=)15161517__GMP_DECLARE_COMPOUND_OPERATOR(operator&=)1518__GMP_DECLARE_COMPOUND_OPERATOR(operator|=)1519__GMP_DECLARE_COMPOUND_OPERATOR(operator^=)15201521__GMP_DECLARE_COMPOUND_OPERATOR_UI(operator<<=)1522__GMP_DECLARE_COMPOUND_OPERATOR_UI(operator>>=)15231524__GMP_DECLARE_INCREMENT_OPERATOR(operator++)1525__GMP_DECLARE_INCREMENT_OPERATOR(operator--)1526};15271528typedef __gmp_expr<mpz_t, mpz_t> mpz_class;152915301531/**************** mpq_class -- wrapper for mpq_t ****************/15321533template <>1534class __gmp_expr<mpq_t, mpq_t>1535{1536private:1537typedef mpq_t value_type;1538value_type mp;15391540// Helper functions used for all arithmetic types1541void assign_ui(unsigned long l) { mpq_set_ui(mp, l, 1); }1542void assign_si(signed long l)1543{1544if (__GMPXX_CONSTANT_TRUE(l >= 0))1545assign_ui(l);1546else1547mpq_set_si(mp, l, 1);1548}1549void assign_d (double d) { mpq_set_d (mp, d); }15501551void init_ui(unsigned long l) { mpq_init(mp); get_num() = l; }1552void init_si(signed long l) { mpq_init(mp); get_num() = l; }1553void init_d (double d) { mpq_init(mp); assign_d (d); }15541555public:1556mp_bitcnt_t get_prec() const { return mpf_get_default_prec(); }1557void canonicalize() { mpq_canonicalize(mp); }15581559// constructors and destructor1560__gmp_expr() { mpq_init(mp); }15611562__gmp_expr(const __gmp_expr &q)1563{1564mpz_init_set(mpq_numref(mp), mpq_numref(q.mp));1565mpz_init_set(mpq_denref(mp), mpq_denref(q.mp));1566}1567#if __GMPXX_USE_CXX111568__gmp_expr(__gmp_expr &&q)1569{ *mp = *q.mp; mpq_init(q.mp); }1570#endif1571template <class T>1572__gmp_expr(const __gmp_expr<mpz_t, T> &expr)1573{ mpq_init(mp); __gmp_set_expr(mp, expr); }1574template <class T>1575__gmp_expr(const __gmp_expr<mpq_t, T> &expr)1576{ mpq_init(mp); __gmp_set_expr(mp, expr); }1577template <class T, class U>1578explicit __gmp_expr(const __gmp_expr<T, U> &expr)1579{ mpq_init(mp); __gmp_set_expr(mp, expr); }15801581__GMPXX_DEFINE_ARITHMETIC_CONSTRUCTORS15821583explicit __gmp_expr(const char *s, int base = 0)1584{1585mpq_init (mp);1586// If s is the literal 0, we meant to call another constructor.1587// If s just happens to evaluate to 0, we would crash, so whatever.1588if (s == 0)1589{1590// Don't turn mpq_class(0,0) into 01591mpz_set_si(mpq_denref(mp), base);1592}1593else if (mpq_set_str(mp, s, base) != 0)1594{1595mpq_clear (mp);1596throw std::invalid_argument ("mpq_set_str");1597}1598}1599explicit __gmp_expr(const std::string &s, int base = 0)1600{1601mpq_init(mp);1602if (mpq_set_str (mp, s.c_str(), base) != 0)1603{1604mpq_clear (mp);1605throw std::invalid_argument ("mpq_set_str");1606}1607}1608explicit __gmp_expr(mpq_srcptr q)1609{1610mpz_init_set(mpq_numref(mp), mpq_numref(q));1611mpz_init_set(mpq_denref(mp), mpq_denref(q));1612}16131614__gmp_expr(const mpz_class &num, const mpz_class &den)1615{1616mpz_init_set(mpq_numref(mp), num.get_mpz_t());1617mpz_init_set(mpq_denref(mp), den.get_mpz_t());1618}16191620~__gmp_expr() { mpq_clear(mp); }16211622void swap(__gmp_expr& q) __GMPXX_NOEXCEPT { std::swap(*mp, *q.mp); }16231624// assignment operators1625__gmp_expr & operator=(const __gmp_expr &q)1626{ mpq_set(mp, q.mp); return *this; }1627#if __GMPXX_USE_CXX111628__gmp_expr & operator=(__gmp_expr &&q) noexcept1629{ swap(q); return *this; }1630__gmp_expr & operator=(mpz_class &&z) noexcept1631{ get_num() = std::move(z); get_den() = 1u; return *this; }1632#endif1633template <class T, class U>1634__gmp_expr<value_type, value_type> & operator=(const __gmp_expr<T, U> &expr)1635{ __gmp_set_expr(mp, expr); return *this; }16361637__GMPXX_DEFINE_ARITHMETIC_ASSIGNMENTS16381639__gmp_expr & operator=(const char *s)1640{1641if (mpq_set_str (mp, s, 0) != 0)1642throw std::invalid_argument ("mpq_set_str");1643return *this;1644}1645__gmp_expr & operator=(const std::string &s)1646{1647if (mpq_set_str(mp, s.c_str(), 0) != 0)1648throw std::invalid_argument ("mpq_set_str");1649return *this;1650}16511652// string input/output functions1653int set_str(const char *s, int base)1654{ return mpq_set_str(mp, s, base); }1655int set_str(const std::string &s, int base)1656{ return mpq_set_str(mp, s.c_str(), base); }1657std::string get_str(int base = 10) const1658{1659__gmp_alloc_cstring temp(mpq_get_str(0, base, mp));1660return std::string(temp.str);1661}16621663// conversion functions16641665// casting a reference to an mpz_t to mpz_class & is a dirty hack,1666// but works because the internal representation of mpz_class is1667// exactly an mpz_t1668const mpz_class & get_num() const1669{ return reinterpret_cast<const mpz_class &>(*mpq_numref(mp)); }1670mpz_class & get_num()1671{ return reinterpret_cast<mpz_class &>(*mpq_numref(mp)); }1672const mpz_class & get_den() const1673{ return reinterpret_cast<const mpz_class &>(*mpq_denref(mp)); }1674mpz_class & get_den()1675{ return reinterpret_cast<mpz_class &>(*mpq_denref(mp)); }16761677mpq_srcptr __get_mp() const { return mp; }1678mpq_ptr __get_mp() { return mp; }1679mpq_srcptr get_mpq_t() const { return mp; }1680mpq_ptr get_mpq_t() { return mp; }16811682mpz_srcptr get_num_mpz_t() const { return mpq_numref(mp); }1683mpz_ptr get_num_mpz_t() { return mpq_numref(mp); }1684mpz_srcptr get_den_mpz_t() const { return mpq_denref(mp); }1685mpz_ptr get_den_mpz_t() { return mpq_denref(mp); }16861687double get_d() const { return mpq_get_d(mp); }16881689#if __GMPXX_USE_CXX111690explicit operator bool() const { return mpq_numref(mp)->_mp_size != 0; }1691#endif16921693// compound assignments1694__GMP_DECLARE_COMPOUND_OPERATOR(operator+=)1695__GMP_DECLARE_COMPOUND_OPERATOR(operator-=)1696__GMP_DECLARE_COMPOUND_OPERATOR(operator*=)1697__GMP_DECLARE_COMPOUND_OPERATOR(operator/=)16981699__GMP_DECLARE_COMPOUND_OPERATOR_UI(operator<<=)1700__GMP_DECLARE_COMPOUND_OPERATOR_UI(operator>>=)17011702__GMP_DECLARE_INCREMENT_OPERATOR(operator++)1703__GMP_DECLARE_INCREMENT_OPERATOR(operator--)1704};17051706typedef __gmp_expr<mpq_t, mpq_t> mpq_class;170717081709/**************** mpf_class -- wrapper for mpf_t ****************/17101711template <>1712class __gmp_expr<mpf_t, mpf_t>1713{1714private:1715typedef mpf_t value_type;1716value_type mp;17171718// Helper functions used for all arithmetic types1719void assign_ui(unsigned long l) { mpf_set_ui(mp, l); }1720void assign_si(signed long l)1721{1722if (__GMPXX_CONSTANT_TRUE(l >= 0))1723assign_ui(l);1724else1725mpf_set_si(mp, l);1726}1727void assign_d (double d) { mpf_set_d (mp, d); }17281729void init_ui(unsigned long l)1730{1731if (__GMPXX_CONSTANT_TRUE(l == 0))1732mpf_init(mp);1733else1734mpf_init_set_ui(mp, l);1735}1736void init_si(signed long l)1737{1738if (__GMPXX_CONSTANT_TRUE(l >= 0))1739init_ui(l);1740else1741mpf_init_set_si(mp, l);1742}1743void init_d (double d) { mpf_init_set_d (mp, d); }17441745public:1746mp_bitcnt_t get_prec() const { return mpf_get_prec(mp); }17471748void set_prec(mp_bitcnt_t prec) { mpf_set_prec(mp, prec); }1749void set_prec_raw(mp_bitcnt_t prec) { mpf_set_prec_raw(mp, prec); }17501751// constructors and destructor1752__gmp_expr() { mpf_init(mp); }17531754__gmp_expr(const __gmp_expr &f)1755{ mpf_init2(mp, f.get_prec()); mpf_set(mp, f.mp); }1756#if __GMPXX_USE_CXX111757__gmp_expr(__gmp_expr &&f)1758{ *mp = *f.mp; mpf_init2(f.mp, get_prec()); }1759#endif1760__gmp_expr(const __gmp_expr &f, mp_bitcnt_t prec)1761{ mpf_init2(mp, prec); mpf_set(mp, f.mp); }1762template <class T, class U>1763__gmp_expr(const __gmp_expr<T, U> &expr)1764{ mpf_init2(mp, expr.get_prec()); __gmp_set_expr(mp, expr); }1765template <class T, class U>1766__gmp_expr(const __gmp_expr<T, U> &expr, mp_bitcnt_t prec)1767{ mpf_init2(mp, prec); __gmp_set_expr(mp, expr); }17681769__GMPXX_DEFINE_ARITHMETIC_CONSTRUCTORS17701771__gmp_expr(signed char c, mp_bitcnt_t prec)1772{ mpf_init2(mp, prec); mpf_set_si(mp, c); }1773__gmp_expr(unsigned char c, mp_bitcnt_t prec)1774{ mpf_init2(mp, prec); mpf_set_ui(mp, c); }17751776__gmp_expr(signed int i, mp_bitcnt_t prec)1777{ mpf_init2(mp, prec); mpf_set_si(mp, i); }1778__gmp_expr(unsigned int i, mp_bitcnt_t prec)1779{ mpf_init2(mp, prec); mpf_set_ui(mp, i); }17801781__gmp_expr(signed short int s, mp_bitcnt_t prec)1782{ mpf_init2(mp, prec); mpf_set_si(mp, s); }1783__gmp_expr(unsigned short int s, mp_bitcnt_t prec)1784{ mpf_init2(mp, prec); mpf_set_ui(mp, s); }17851786__gmp_expr(signed long int l, mp_bitcnt_t prec)1787{ mpf_init2(mp, prec); mpf_set_si(mp, l); }1788__gmp_expr(unsigned long int l, mp_bitcnt_t prec)1789{ mpf_init2(mp, prec); mpf_set_ui(mp, l); }17901791__gmp_expr(float f, mp_bitcnt_t prec)1792{ mpf_init2(mp, prec); mpf_set_d(mp, f); }1793__gmp_expr(double d, mp_bitcnt_t prec)1794{ mpf_init2(mp, prec); mpf_set_d(mp, d); }1795// __gmp_expr(long double ld) { mpf_init_set_d(mp, ld); }1796// __gmp_expr(long double ld, mp_bitcnt_t prec)1797// { mpf_init2(mp, prec); mpf_set_d(mp, ld); }17981799explicit __gmp_expr(const char *s)1800{1801if (mpf_init_set_str (mp, s, 0) != 0)1802{1803mpf_clear (mp);1804throw std::invalid_argument ("mpf_set_str");1805}1806}1807__gmp_expr(const char *s, mp_bitcnt_t prec, int base = 0)1808{1809mpf_init2(mp, prec);1810if (mpf_set_str(mp, s, base) != 0)1811{1812mpf_clear (mp);1813throw std::invalid_argument ("mpf_set_str");1814}1815}1816explicit __gmp_expr(const std::string &s)1817{1818if (mpf_init_set_str(mp, s.c_str(), 0) != 0)1819{1820mpf_clear (mp);1821throw std::invalid_argument ("mpf_set_str");1822}1823}1824__gmp_expr(const std::string &s, mp_bitcnt_t prec, int base = 0)1825{1826mpf_init2(mp, prec);1827if (mpf_set_str(mp, s.c_str(), base) != 0)1828{1829mpf_clear (mp);1830throw std::invalid_argument ("mpf_set_str");1831}1832}18331834explicit __gmp_expr(mpf_srcptr f)1835{ mpf_init2(mp, mpf_get_prec(f)); mpf_set(mp, f); }1836__gmp_expr(mpf_srcptr f, mp_bitcnt_t prec)1837{ mpf_init2(mp, prec); mpf_set(mp, f); }18381839~__gmp_expr() { mpf_clear(mp); }18401841void swap(__gmp_expr& f) __GMPXX_NOEXCEPT { std::swap(*mp, *f.mp); }18421843// assignment operators1844__gmp_expr & operator=(const __gmp_expr &f)1845{ mpf_set(mp, f.mp); return *this; }1846#if __GMPXX_USE_CXX111847__gmp_expr & operator=(__gmp_expr &&f) noexcept1848{ swap(f); return *this; }1849#endif1850template <class T, class U>1851__gmp_expr<value_type, value_type> & operator=(const __gmp_expr<T, U> &expr)1852{ __gmp_set_expr(mp, expr); return *this; }18531854__GMPXX_DEFINE_ARITHMETIC_ASSIGNMENTS18551856__gmp_expr & operator=(const char *s)1857{1858if (mpf_set_str (mp, s, 0) != 0)1859throw std::invalid_argument ("mpf_set_str");1860return *this;1861}1862__gmp_expr & operator=(const std::string &s)1863{1864if (mpf_set_str(mp, s.c_str(), 0) != 0)1865throw std::invalid_argument ("mpf_set_str");1866return *this;1867}18681869// string input/output functions1870int set_str(const char *s, int base)1871{ return mpf_set_str(mp, s, base); }1872int set_str(const std::string &s, int base)1873{ return mpf_set_str(mp, s.c_str(), base); }1874std::string get_str(mp_exp_t &expo, int base = 10, size_t size = 0) const1875{1876__gmp_alloc_cstring temp(mpf_get_str(0, &expo, base, size, mp));1877return std::string(temp.str);1878}18791880// conversion functions1881mpf_srcptr __get_mp() const { return mp; }1882mpf_ptr __get_mp() { return mp; }1883mpf_srcptr get_mpf_t() const { return mp; }1884mpf_ptr get_mpf_t() { return mp; }18851886signed long int get_si() const { return mpf_get_si(mp); }1887unsigned long int get_ui() const { return mpf_get_ui(mp); }1888double get_d() const { return mpf_get_d(mp); }18891890// bool fits_schar_p() const { return mpf_fits_schar_p(mp); }1891// bool fits_uchar_p() const { return mpf_fits_uchar_p(mp); }1892bool fits_sint_p() const { return mpf_fits_sint_p(mp); }1893bool fits_uint_p() const { return mpf_fits_uint_p(mp); }1894bool fits_sshort_p() const { return mpf_fits_sshort_p(mp); }1895bool fits_ushort_p() const { return mpf_fits_ushort_p(mp); }1896bool fits_slong_p() const { return mpf_fits_slong_p(mp); }1897bool fits_ulong_p() const { return mpf_fits_ulong_p(mp); }1898// bool fits_float_p() const { return mpf_fits_float_p(mp); }1899// bool fits_double_p() const { return mpf_fits_double_p(mp); }1900// bool fits_ldouble_p() const { return mpf_fits_ldouble_p(mp); }19011902#if __GMPXX_USE_CXX111903explicit operator bool() const { return mp->_mp_size != 0; }1904#endif19051906// compound assignments1907__GMP_DECLARE_COMPOUND_OPERATOR(operator+=)1908__GMP_DECLARE_COMPOUND_OPERATOR(operator-=)1909__GMP_DECLARE_COMPOUND_OPERATOR(operator*=)1910__GMP_DECLARE_COMPOUND_OPERATOR(operator/=)19111912__GMP_DECLARE_COMPOUND_OPERATOR_UI(operator<<=)1913__GMP_DECLARE_COMPOUND_OPERATOR_UI(operator>>=)19141915__GMP_DECLARE_INCREMENT_OPERATOR(operator++)1916__GMP_DECLARE_INCREMENT_OPERATOR(operator--)1917};19181919typedef __gmp_expr<mpf_t, mpf_t> mpf_class;1920192119221923/**************** User-defined literals ****************/19241925#if __GMPXX_USE_CXX111926inline mpz_class operator"" _mpz(const char* s)1927{1928return mpz_class(s);1929}19301931inline mpq_class operator"" _mpq(const char* s)1932{1933mpq_class q;1934q.get_num() = s;1935return q;1936}19371938inline mpf_class operator"" _mpf(const char* s)1939{1940return mpf_class(s);1941}1942#endif19431944/**************** I/O operators ****************/19451946// these should (and will) be provided separately19471948template <class T, class U>1949inline std::ostream & operator<<1950(std::ostream &o, const __gmp_expr<T, U> &expr)1951{1952__gmp_expr<T, T> const& temp(expr);1953return o << temp.__get_mp();1954}19551956template <class T>1957inline std::istream & operator>>(std::istream &i, __gmp_expr<T, T> &expr)1958{1959return i >> expr.__get_mp();1960}19611962/*1963// you might want to uncomment this1964inline std::istream & operator>>(std::istream &i, mpq_class &q)1965{1966i >> q.get_mpq_t();1967q.canonicalize();1968return i;1969}1970*/197119721973/**************** Functions for type conversion ****************/19741975inline void __gmp_set_expr(mpz_ptr z, const mpz_class &w)1976{1977mpz_set(z, w.get_mpz_t());1978}19791980template <class T>1981inline void __gmp_set_expr(mpz_ptr z, const __gmp_expr<mpz_t, T> &expr)1982{1983expr.eval(z);1984}19851986template <class T>1987inline void __gmp_set_expr(mpz_ptr z, const __gmp_expr<mpq_t, T> &expr)1988{1989mpq_class const& temp(expr);1990mpz_set_q(z, temp.get_mpq_t());1991}19921993template <class T>1994inline void __gmp_set_expr(mpz_ptr z, const __gmp_expr<mpf_t, T> &expr)1995{1996mpf_class const& temp(expr);1997mpz_set_f(z, temp.get_mpf_t());1998}19992000inline void __gmp_set_expr(mpq_ptr q, const mpz_class &z)2001{2002mpq_set_z(q, z.get_mpz_t());2003}20042005template <class T>2006inline void __gmp_set_expr(mpq_ptr q, const __gmp_expr<mpz_t, T> &expr)2007{2008__gmp_set_expr(mpq_numref(q), expr);2009mpz_set_ui(mpq_denref(q), 1);2010}20112012inline void __gmp_set_expr(mpq_ptr q, const mpq_class &r)2013{2014mpq_set(q, r.get_mpq_t());2015}20162017template <class T>2018inline void __gmp_set_expr(mpq_ptr q, const __gmp_expr<mpq_t, T> &expr)2019{2020expr.eval(q);2021}20222023template <class T>2024inline void __gmp_set_expr(mpq_ptr q, const __gmp_expr<mpf_t, T> &expr)2025{2026mpf_class const& temp(expr);2027mpq_set_f(q, temp.get_mpf_t());2028}20292030template <class T>2031inline void __gmp_set_expr(mpf_ptr f, const __gmp_expr<mpz_t, T> &expr)2032{2033mpz_class const& temp(expr);2034mpf_set_z(f, temp.get_mpz_t());2035}20362037template <class T>2038inline void __gmp_set_expr(mpf_ptr f, const __gmp_expr<mpq_t, T> &expr)2039{2040mpq_class const& temp(expr);2041mpf_set_q(f, temp.get_mpq_t());2042}20432044inline void __gmp_set_expr(mpf_ptr f, const mpf_class &g)2045{2046mpf_set(f, g.get_mpf_t());2047}20482049template <class T>2050inline void __gmp_set_expr(mpf_ptr f, const __gmp_expr<mpf_t, T> &expr)2051{2052expr.eval(f);2053}205420552056/* Temporary objects */20572058template <class T>2059class __gmp_temp2060{2061__gmp_expr<T, T> val;2062public:2063template<class U, class V>2064__gmp_temp(U const& u, V) : val (u) {}2065typename __gmp_resolve_expr<T>::srcptr_type2066__get_mp() const { return val.__get_mp(); }2067};20682069template <>2070class __gmp_temp <mpf_t>2071{2072mpf_class val;2073public:2074template<class U>2075__gmp_temp(U const& u, mpf_ptr res) : val (u, mpf_get_prec(res)) {}2076mpf_srcptr __get_mp() const { return val.__get_mp(); }2077};20782079/**************** Specializations of __gmp_expr ****************/2080/* The eval() method of __gmp_expr<T, U> evaluates the corresponding2081expression and assigns the result to its argument, which is either an2082mpz_t, mpq_t, or mpf_t as specified by the T argument.2083Compound expressions are evaluated recursively (temporaries are created2084to hold intermediate values), while for simple expressions the eval()2085method of the appropriate function object (available as the Op argument2086of either __gmp_unary_expr<T, Op> or __gmp_binary_expr<T, U, Op>) is2087called. */208820892090/**************** Unary expressions ****************/2091/* cases:2092- simple: argument is mp*_class, that is, __gmp_expr<T, T>2093- compound: argument is __gmp_expr<T, U> (with U not equal to T) */209420952096// simple expressions20972098template <class T, class Op>2099class __gmp_expr<T, __gmp_unary_expr<__gmp_expr<T, T>, Op> >2100{2101private:2102typedef __gmp_expr<T, T> val_type;21032104__gmp_unary_expr<val_type, Op> expr;2105public:2106explicit __gmp_expr(const val_type &val) : expr(val) { }2107void eval(typename __gmp_resolve_expr<T>::ptr_type p) const2108{ Op::eval(p, expr.val.__get_mp()); }2109const val_type & get_val() const { return expr.val; }2110mp_bitcnt_t get_prec() const { return expr.val.get_prec(); }2111};211221132114// compound expressions21152116template <class T, class U, class Op>2117class __gmp_expr<T, __gmp_unary_expr<__gmp_expr<T, U>, Op> >2118{2119private:2120typedef __gmp_expr<T, U> val_type;21212122__gmp_unary_expr<val_type, Op> expr;2123public:2124explicit __gmp_expr(const val_type &val) : expr(val) { }2125void eval(typename __gmp_resolve_expr<T>::ptr_type p) const2126{ expr.val.eval(p); Op::eval(p, p); }2127const val_type & get_val() const { return expr.val; }2128mp_bitcnt_t get_prec() const { return expr.val.get_prec(); }2129};213021312132/**************** Binary expressions ****************/2133/* simple:2134- arguments are both mp*_class2135- one argument is mp*_class, one is a built-in type2136compound:2137- one is mp*_class, one is __gmp_expr<T, U>2138- one is __gmp_expr<T, U>, one is built-in2139- both arguments are __gmp_expr<...> */214021412142// simple expressions21432144template <class T, class Op>2145class __gmp_expr2146<T, __gmp_binary_expr<__gmp_expr<T, T>, __gmp_expr<T, T>, Op> >2147{2148private:2149typedef __gmp_expr<T, T> val1_type;2150typedef __gmp_expr<T, T> val2_type;21512152__gmp_binary_expr<val1_type, val2_type, Op> expr;2153public:2154__gmp_expr(const val1_type &val1, const val2_type &val2)2155: expr(val1, val2) { }2156void eval(typename __gmp_resolve_expr<T>::ptr_type p) const2157{ Op::eval(p, expr.val1.__get_mp(), expr.val2.__get_mp()); }2158const val1_type & get_val1() const { return expr.val1; }2159const val2_type & get_val2() const { return expr.val2; }2160mp_bitcnt_t get_prec() const2161{2162mp_bitcnt_t prec1 = expr.val1.get_prec(),2163prec2 = expr.val2.get_prec();2164return (prec1 > prec2) ? prec1 : prec2;2165}2166};216721682169// simple expressions, T is a built-in numerical type21702171template <class T, class U, class Op>2172class __gmp_expr<T, __gmp_binary_expr<__gmp_expr<T, T>, U, Op> >2173{2174private:2175typedef __gmp_expr<T, T> val1_type;2176typedef U val2_type;21772178__gmp_binary_expr<val1_type, val2_type, Op> expr;2179public:2180__gmp_expr(const val1_type &val1, const val2_type &val2)2181: expr(val1, val2) { }2182void eval(typename __gmp_resolve_expr<T>::ptr_type p) const2183{ Op::eval(p, expr.val1.__get_mp(), expr.val2); }2184const val1_type & get_val1() const { return expr.val1; }2185const val2_type & get_val2() const { return expr.val2; }2186mp_bitcnt_t get_prec() const { return expr.val1.get_prec(); }2187};21882189template <class T, class U, class Op>2190class __gmp_expr<T, __gmp_binary_expr<U, __gmp_expr<T, T>, Op> >2191{2192private:2193typedef U val1_type;2194typedef __gmp_expr<T, T> val2_type;21952196__gmp_binary_expr<val1_type, val2_type, Op> expr;2197public:2198__gmp_expr(const val1_type &val1, const val2_type &val2)2199: expr(val1, val2) { }2200void eval(typename __gmp_resolve_expr<T>::ptr_type p) const2201{ Op::eval(p, expr.val1, expr.val2.__get_mp()); }2202const val1_type & get_val1() const { return expr.val1; }2203const val2_type & get_val2() const { return expr.val2; }2204mp_bitcnt_t get_prec() const { return expr.val2.get_prec(); }2205};220622072208// compound expressions, one argument is a subexpression22092210template <class T, class U, class V, class Op>2211class __gmp_expr2212<T, __gmp_binary_expr<__gmp_expr<T, T>, __gmp_expr<U, V>, Op> >2213{2214private:2215typedef __gmp_expr<T, T> val1_type;2216typedef __gmp_expr<U, V> val2_type;22172218__gmp_binary_expr<val1_type, val2_type, Op> expr;2219public:2220__gmp_expr(const val1_type &val1, const val2_type &val2)2221: expr(val1, val2) { }2222void eval(typename __gmp_resolve_expr<T>::ptr_type p) const2223{2224if(p != expr.val1.__get_mp())2225{2226__gmp_set_expr(p, expr.val2);2227Op::eval(p, expr.val1.__get_mp(), p);2228}2229else2230{2231__gmp_temp<T> temp(expr.val2, p);2232Op::eval(p, expr.val1.__get_mp(), temp.__get_mp());2233}2234}2235const val1_type & get_val1() const { return expr.val1; }2236const val2_type & get_val2() const { return expr.val2; }2237mp_bitcnt_t get_prec() const2238{2239mp_bitcnt_t prec1 = expr.val1.get_prec(),2240prec2 = expr.val2.get_prec();2241return (prec1 > prec2) ? prec1 : prec2;2242}2243};22442245template <class T, class U, class V, class Op>2246class __gmp_expr2247<T, __gmp_binary_expr<__gmp_expr<U, V>, __gmp_expr<T, T>, Op> >2248{2249private:2250typedef __gmp_expr<U, V> val1_type;2251typedef __gmp_expr<T, T> val2_type;22522253__gmp_binary_expr<val1_type, val2_type, Op> expr;2254public:2255__gmp_expr(const val1_type &val1, const val2_type &val2)2256: expr(val1, val2) { }2257void eval(typename __gmp_resolve_expr<T>::ptr_type p) const2258{2259if(p != expr.val2.__get_mp())2260{2261__gmp_set_expr(p, expr.val1);2262Op::eval(p, p, expr.val2.__get_mp());2263}2264else2265{2266__gmp_temp<T> temp(expr.val1, p);2267Op::eval(p, temp.__get_mp(), expr.val2.__get_mp());2268}2269}2270const val1_type & get_val1() const { return expr.val1; }2271const val2_type & get_val2() const { return expr.val2; }2272mp_bitcnt_t get_prec() const2273{2274mp_bitcnt_t prec1 = expr.val1.get_prec(),2275prec2 = expr.val2.get_prec();2276return (prec1 > prec2) ? prec1 : prec2;2277}2278};22792280template <class T, class U, class Op>2281class __gmp_expr2282<T, __gmp_binary_expr<__gmp_expr<T, T>, __gmp_expr<T, U>, Op> >2283{2284private:2285typedef __gmp_expr<T, T> val1_type;2286typedef __gmp_expr<T, U> val2_type;22872288__gmp_binary_expr<val1_type, val2_type, Op> expr;2289public:2290__gmp_expr(const val1_type &val1, const val2_type &val2)2291: expr(val1, val2) { }2292void eval(typename __gmp_resolve_expr<T>::ptr_type p) const2293{2294if(p != expr.val1.__get_mp())2295{2296__gmp_set_expr(p, expr.val2);2297Op::eval(p, expr.val1.__get_mp(), p);2298}2299else2300{2301__gmp_temp<T> temp(expr.val2, p);2302Op::eval(p, expr.val1.__get_mp(), temp.__get_mp());2303}2304}2305const val1_type & get_val1() const { return expr.val1; }2306const val2_type & get_val2() const { return expr.val2; }2307mp_bitcnt_t get_prec() const2308{2309mp_bitcnt_t prec1 = expr.val1.get_prec(),2310prec2 = expr.val2.get_prec();2311return (prec1 > prec2) ? prec1 : prec2;2312}2313};23142315template <class T, class U, class Op>2316class __gmp_expr2317<T, __gmp_binary_expr<__gmp_expr<T, U>, __gmp_expr<T, T>, Op> >2318{2319private:2320typedef __gmp_expr<T, U> val1_type;2321typedef __gmp_expr<T, T> val2_type;23222323__gmp_binary_expr<val1_type, val2_type, Op> expr;2324public:2325__gmp_expr(const val1_type &val1, const val2_type &val2)2326: expr(val1, val2) { }2327void eval(typename __gmp_resolve_expr<T>::ptr_type p) const2328{2329if(p != expr.val2.__get_mp())2330{2331__gmp_set_expr(p, expr.val1);2332Op::eval(p, p, expr.val2.__get_mp());2333}2334else2335{2336__gmp_temp<T> temp(expr.val1, p);2337Op::eval(p, temp.__get_mp(), expr.val2.__get_mp());2338}2339}2340const val1_type & get_val1() const { return expr.val1; }2341const val2_type & get_val2() const { return expr.val2; }2342mp_bitcnt_t get_prec() const2343{2344mp_bitcnt_t prec1 = expr.val1.get_prec(),2345prec2 = expr.val2.get_prec();2346return (prec1 > prec2) ? prec1 : prec2;2347}2348};234923502351// one argument is a subexpression, one is a built-in23522353template <class T, class U, class V, class Op>2354class __gmp_expr<T, __gmp_binary_expr<__gmp_expr<T, U>, V, Op> >2355{2356private:2357typedef __gmp_expr<T, U> val1_type;2358typedef V val2_type;23592360__gmp_binary_expr<val1_type, val2_type, Op> expr;2361public:2362__gmp_expr(const val1_type &val1, const val2_type &val2)2363: expr(val1, val2) { }2364void eval(typename __gmp_resolve_expr<T>::ptr_type p) const2365{2366expr.val1.eval(p);2367Op::eval(p, p, expr.val2);2368}2369const val1_type & get_val1() const { return expr.val1; }2370const val2_type & get_val2() const { return expr.val2; }2371mp_bitcnt_t get_prec() const { return expr.val1.get_prec(); }2372};23732374template <class T, class U, class V, class Op>2375class __gmp_expr<T, __gmp_binary_expr<U, __gmp_expr<T, V>, Op> >2376{2377private:2378typedef U val1_type;2379typedef __gmp_expr<T, V> val2_type;23802381__gmp_binary_expr<val1_type, val2_type, Op> expr;2382public:2383__gmp_expr(const val1_type &val1, const val2_type &val2)2384: expr(val1, val2) { }2385void eval(typename __gmp_resolve_expr<T>::ptr_type p) const2386{2387expr.val2.eval(p);2388Op::eval(p, expr.val1, p);2389}2390const val1_type & get_val1() const { return expr.val1; }2391const val2_type & get_val2() const { return expr.val2; }2392mp_bitcnt_t get_prec() const { return expr.val2.get_prec(); }2393};239423952396// both arguments are subexpressions23972398template <class T, class U, class V, class W, class Op>2399class __gmp_expr2400<T, __gmp_binary_expr<__gmp_expr<T, U>, __gmp_expr<V, W>, Op> >2401{2402private:2403typedef __gmp_expr<T, U> val1_type;2404typedef __gmp_expr<V, W> val2_type;24052406__gmp_binary_expr<val1_type, val2_type, Op> expr;2407public:2408__gmp_expr(const val1_type &val1, const val2_type &val2)2409: expr(val1, val2) { }2410void eval(typename __gmp_resolve_expr<T>::ptr_type p) const2411{2412__gmp_temp<T> temp2(expr.val2, p);2413expr.val1.eval(p);2414Op::eval(p, p, temp2.__get_mp());2415}2416const val1_type & get_val1() const { return expr.val1; }2417const val2_type & get_val2() const { return expr.val2; }2418mp_bitcnt_t get_prec() const2419{2420mp_bitcnt_t prec1 = expr.val1.get_prec(),2421prec2 = expr.val2.get_prec();2422return (prec1 > prec2) ? prec1 : prec2;2423}2424};24252426template <class T, class U, class V, class W, class Op>2427class __gmp_expr2428<T, __gmp_binary_expr<__gmp_expr<U, V>, __gmp_expr<T, W>, Op> >2429{2430private:2431typedef __gmp_expr<U, V> val1_type;2432typedef __gmp_expr<T, W> val2_type;24332434__gmp_binary_expr<val1_type, val2_type, Op> expr;2435public:2436__gmp_expr(const val1_type &val1, const val2_type &val2)2437: expr(val1, val2) { }2438void eval(typename __gmp_resolve_expr<T>::ptr_type p) const2439{2440__gmp_temp<T> temp1(expr.val1, p);2441expr.val2.eval(p);2442Op::eval(p, temp1.__get_mp(), p);2443}2444const val1_type & get_val1() const { return expr.val1; }2445const val2_type & get_val2() const { return expr.val2; }2446mp_bitcnt_t get_prec() const2447{2448mp_bitcnt_t prec1 = expr.val1.get_prec(),2449prec2 = expr.val2.get_prec();2450return (prec1 > prec2) ? prec1 : prec2;2451}2452};24532454template <class T, class U, class V, class Op>2455class __gmp_expr2456<T, __gmp_binary_expr<__gmp_expr<T, U>, __gmp_expr<T, V>, Op> >2457{2458private:2459typedef __gmp_expr<T, U> val1_type;2460typedef __gmp_expr<T, V> val2_type;24612462__gmp_binary_expr<val1_type, val2_type, Op> expr;2463public:2464__gmp_expr(const val1_type &val1, const val2_type &val2)2465: expr(val1, val2) { }2466void eval(typename __gmp_resolve_expr<T>::ptr_type p) const2467{2468__gmp_temp<T> temp2(expr.val2, p);2469expr.val1.eval(p);2470Op::eval(p, p, temp2.__get_mp());2471}2472const val1_type & get_val1() const { return expr.val1; }2473const val2_type & get_val2() const { return expr.val2; }2474mp_bitcnt_t get_prec() const2475{2476mp_bitcnt_t prec1 = expr.val1.get_prec(),2477prec2 = expr.val2.get_prec();2478return (prec1 > prec2) ? prec1 : prec2;2479}2480};248124822483/**************** Special cases ****************/24842485/* Some operations (i.e., add and subtract) with mixed mpz/mpq arguments2486can be done directly without first converting the mpz to mpq.2487Appropriate specializations of __gmp_expr are required. */248824892490#define __GMPZQ_DEFINE_EXPR(eval_fun) \2491\2492template <> \2493class __gmp_expr<mpq_t, __gmp_binary_expr<mpz_class, mpq_class, eval_fun> > \2494{ \2495private: \2496typedef mpz_class val1_type; \2497typedef mpq_class val2_type; \2498\2499__gmp_binary_expr<val1_type, val2_type, eval_fun> expr; \2500public: \2501__gmp_expr(const val1_type &val1, const val2_type &val2) \2502: expr(val1, val2) { } \2503void eval(mpq_ptr q) const \2504{ eval_fun::eval(q, expr.val1.get_mpz_t(), expr.val2.get_mpq_t()); } \2505const val1_type & get_val1() const { return expr.val1; } \2506const val2_type & get_val2() const { return expr.val2; } \2507mp_bitcnt_t get_prec() const { return mpf_get_default_prec(); } \2508}; \2509\2510template <> \2511class __gmp_expr<mpq_t, __gmp_binary_expr<mpq_class, mpz_class, eval_fun> > \2512{ \2513private: \2514typedef mpq_class val1_type; \2515typedef mpz_class val2_type; \2516\2517__gmp_binary_expr<val1_type, val2_type, eval_fun> expr; \2518public: \2519__gmp_expr(const val1_type &val1, const val2_type &val2) \2520: expr(val1, val2) { } \2521void eval(mpq_ptr q) const \2522{ eval_fun::eval(q, expr.val1.get_mpq_t(), expr.val2.get_mpz_t()); } \2523const val1_type & get_val1() const { return expr.val1; } \2524const val2_type & get_val2() const { return expr.val2; } \2525mp_bitcnt_t get_prec() const { return mpf_get_default_prec(); } \2526}; \2527\2528template <class T> \2529class __gmp_expr \2530<mpq_t, __gmp_binary_expr<mpz_class, __gmp_expr<mpq_t, T>, eval_fun> > \2531{ \2532private: \2533typedef mpz_class val1_type; \2534typedef __gmp_expr<mpq_t, T> val2_type; \2535\2536__gmp_binary_expr<val1_type, val2_type, eval_fun> expr; \2537public: \2538__gmp_expr(const val1_type &val1, const val2_type &val2) \2539: expr(val1, val2) { } \2540void eval(mpq_ptr q) const \2541{ \2542mpq_class temp(expr.val2); \2543eval_fun::eval(q, expr.val1.get_mpz_t(), temp.get_mpq_t()); \2544} \2545const val1_type & get_val1() const { return expr.val1; } \2546const val2_type & get_val2() const { return expr.val2; } \2547mp_bitcnt_t get_prec() const { return mpf_get_default_prec(); } \2548}; \2549\2550template <class T> \2551class __gmp_expr \2552<mpq_t, __gmp_binary_expr<mpq_class, __gmp_expr<mpz_t, T>, eval_fun> > \2553{ \2554private: \2555typedef mpq_class val1_type; \2556typedef __gmp_expr<mpz_t, T> val2_type; \2557\2558__gmp_binary_expr<val1_type, val2_type, eval_fun> expr; \2559public: \2560__gmp_expr(const val1_type &val1, const val2_type &val2) \2561: expr(val1, val2) { } \2562void eval(mpq_ptr q) const \2563{ \2564mpz_class temp(expr.val2); \2565eval_fun::eval(q, expr.val1.get_mpq_t(), temp.get_mpz_t()); \2566} \2567const val1_type & get_val1() const { return expr.val1; } \2568const val2_type & get_val2() const { return expr.val2; } \2569mp_bitcnt_t get_prec() const { return mpf_get_default_prec(); } \2570}; \2571\2572template <class T> \2573class __gmp_expr \2574<mpq_t, __gmp_binary_expr<__gmp_expr<mpz_t, T>, mpq_class, eval_fun> > \2575{ \2576private: \2577typedef __gmp_expr<mpz_t, T> val1_type; \2578typedef mpq_class val2_type; \2579\2580__gmp_binary_expr<val1_type, val2_type, eval_fun> expr; \2581public: \2582__gmp_expr(const val1_type &val1, const val2_type &val2) \2583: expr(val1, val2) { } \2584void eval(mpq_ptr q) const \2585{ \2586mpz_class temp(expr.val1); \2587eval_fun::eval(q, temp.get_mpz_t(), expr.val2.get_mpq_t()); \2588} \2589const val1_type & get_val1() const { return expr.val1; } \2590const val2_type & get_val2() const { return expr.val2; } \2591mp_bitcnt_t get_prec() const { return mpf_get_default_prec(); } \2592}; \2593\2594template <class T> \2595class __gmp_expr \2596<mpq_t, __gmp_binary_expr<__gmp_expr<mpq_t, T>, mpz_class, eval_fun> > \2597{ \2598private: \2599typedef __gmp_expr<mpq_t, T> val1_type; \2600typedef mpz_class val2_type; \2601\2602__gmp_binary_expr<val1_type, val2_type, eval_fun> expr; \2603public: \2604__gmp_expr(const val1_type &val1, const val2_type &val2) \2605: expr(val1, val2) { } \2606void eval(mpq_ptr q) const \2607{ \2608mpq_class temp(expr.val1); \2609eval_fun::eval(q, temp.get_mpq_t(), expr.val2.get_mpz_t()); \2610} \2611const val1_type & get_val1() const { return expr.val1; } \2612const val2_type & get_val2() const { return expr.val2; } \2613mp_bitcnt_t get_prec() const { return mpf_get_default_prec(); } \2614}; \2615\2616template <class T, class U> \2617class __gmp_expr<mpq_t, __gmp_binary_expr \2618<__gmp_expr<mpz_t, T>, __gmp_expr<mpq_t, U>, eval_fun> > \2619{ \2620private: \2621typedef __gmp_expr<mpz_t, T> val1_type; \2622typedef __gmp_expr<mpq_t, U> val2_type; \2623\2624__gmp_binary_expr<val1_type, val2_type, eval_fun> expr; \2625public: \2626__gmp_expr(const val1_type &val1, const val2_type &val2) \2627: expr(val1, val2) { } \2628void eval(mpq_ptr q) const \2629{ \2630mpz_class temp1(expr.val1); \2631expr.val2.eval(q); \2632eval_fun::eval(q, temp1.get_mpz_t(), q); \2633} \2634const val1_type & get_val1() const { return expr.val1; } \2635const val2_type & get_val2() const { return expr.val2; } \2636mp_bitcnt_t get_prec() const { return mpf_get_default_prec(); } \2637}; \2638\2639template <class T, class U> \2640class __gmp_expr<mpq_t, __gmp_binary_expr \2641<__gmp_expr<mpq_t, T>, __gmp_expr<mpz_t, U>, eval_fun> > \2642{ \2643private: \2644typedef __gmp_expr<mpq_t, T> val1_type; \2645typedef __gmp_expr<mpz_t, U> val2_type; \2646\2647__gmp_binary_expr<val1_type, val2_type, eval_fun> expr; \2648public: \2649__gmp_expr(const val1_type &val1, const val2_type &val2) \2650: expr(val1, val2) { } \2651void eval(mpq_ptr q) const \2652{ \2653mpz_class temp2(expr.val2); \2654expr.val1.eval(q); \2655eval_fun::eval(q, q, temp2.get_mpz_t()); \2656} \2657const val1_type & get_val1() const { return expr.val1; } \2658const val2_type & get_val2() const { return expr.val2; } \2659mp_bitcnt_t get_prec() const { return mpf_get_default_prec(); } \2660};266126622663__GMPZQ_DEFINE_EXPR(__gmp_binary_plus)2664__GMPZQ_DEFINE_EXPR(__gmp_binary_minus)2665266626672668/**************** Macros for defining functions ****************/2669/* Results of operators and functions are instances of __gmp_expr<T, U>.2670T determines the numerical type of the expression: it can be either2671mpz_t, mpq_t, or mpf_t. When the arguments of a binary2672expression have different numerical types, __gmp_resolve_expr is used2673to determine the "larger" type.2674U is either __gmp_unary_expr<V, Op> or __gmp_binary_expr<V, W, Op>,2675where V and W are the arguments' types -- they can in turn be2676expressions, thus allowing to build compound expressions to any2677degree of complexity.2678Op is a function object that must have an eval() method accepting2679appropriate arguments.2680Actual evaluation of a __gmp_expr<T, U> object is done when it gets2681assigned to an mp*_class ("lazy" evaluation): this is done by calling2682its eval() method. */268326842685// non-member unary operators and functions26862687#define __GMP_DEFINE_UNARY_FUNCTION(fun, eval_fun) \2688\2689template <class T, class U> \2690inline __gmp_expr<T, __gmp_unary_expr<__gmp_expr<T, U>, eval_fun> > \2691fun(const __gmp_expr<T, U> &expr) \2692{ \2693return __gmp_expr<T, __gmp_unary_expr<__gmp_expr<T, U>, eval_fun> >(expr); \2694}26952696#define __GMP_DEFINE_UNARY_TYPE_FUNCTION(type, fun, eval_fun) \2697\2698template <class T, class U> \2699inline type fun(const __gmp_expr<T, U> &expr) \2700{ \2701__gmp_expr<T, T> const& temp(expr); \2702return eval_fun::eval(temp.__get_mp()); \2703}270427052706// non-member binary operators and functions27072708#define __GMPP_DEFINE_BINARY_FUNCTION(fun, eval_fun) \2709\2710template <class T, class U, class V, class W> \2711inline __gmp_expr<typename __gmp_resolve_expr<T, V>::value_type, \2712__gmp_binary_expr<__gmp_expr<T, U>, __gmp_expr<V, W>, eval_fun> > \2713fun(const __gmp_expr<T, U> &expr1, const __gmp_expr<V, W> &expr2) \2714{ \2715return __gmp_expr<typename __gmp_resolve_expr<T, V>::value_type, \2716__gmp_binary_expr<__gmp_expr<T, U>, __gmp_expr<V, W>, eval_fun> > \2717(expr1, expr2); \2718}27192720#define __GMPNN_DEFINE_BINARY_FUNCTION(fun, eval_fun, type, bigtype) \2721\2722template <class T, class U> \2723inline __gmp_expr \2724<T, __gmp_binary_expr<__gmp_expr<T, U>, bigtype, eval_fun> > \2725fun(const __gmp_expr<T, U> &expr, type t) \2726{ \2727return __gmp_expr \2728<T, __gmp_binary_expr<__gmp_expr<T, U>, bigtype, eval_fun> >(expr, t); \2729} \2730\2731template <class T, class U> \2732inline __gmp_expr \2733<T, __gmp_binary_expr<bigtype, __gmp_expr<T, U>, eval_fun> > \2734fun(type t, const __gmp_expr<T, U> &expr) \2735{ \2736return __gmp_expr \2737<T, __gmp_binary_expr<bigtype, __gmp_expr<T, U>, eval_fun> >(t, expr); \2738}27392740#define __GMPNS_DEFINE_BINARY_FUNCTION(fun, eval_fun, type) \2741__GMPNN_DEFINE_BINARY_FUNCTION(fun, eval_fun, type, signed long int)27422743#define __GMPNU_DEFINE_BINARY_FUNCTION(fun, eval_fun, type) \2744__GMPNN_DEFINE_BINARY_FUNCTION(fun, eval_fun, type, unsigned long int)27452746#define __GMPND_DEFINE_BINARY_FUNCTION(fun, eval_fun, type) \2747__GMPNN_DEFINE_BINARY_FUNCTION(fun, eval_fun, type, double)27482749#define __GMPNLD_DEFINE_BINARY_FUNCTION(fun, eval_fun, type) \2750__GMPNN_DEFINE_BINARY_FUNCTION(fun, eval_fun, type, long double)27512752#define __GMPN_DEFINE_BINARY_FUNCTION(fun, eval_fun) \2753__GMPNS_DEFINE_BINARY_FUNCTION(fun, eval_fun, signed char) \2754__GMPNU_DEFINE_BINARY_FUNCTION(fun, eval_fun, unsigned char) \2755__GMPNS_DEFINE_BINARY_FUNCTION(fun, eval_fun, signed int) \2756__GMPNU_DEFINE_BINARY_FUNCTION(fun, eval_fun, unsigned int) \2757__GMPNS_DEFINE_BINARY_FUNCTION(fun, eval_fun, signed short int) \2758__GMPNU_DEFINE_BINARY_FUNCTION(fun, eval_fun, unsigned short int) \2759__GMPNS_DEFINE_BINARY_FUNCTION(fun, eval_fun, signed long int) \2760__GMPNU_DEFINE_BINARY_FUNCTION(fun, eval_fun, unsigned long int) \2761__GMPND_DEFINE_BINARY_FUNCTION(fun, eval_fun, float) \2762__GMPND_DEFINE_BINARY_FUNCTION(fun, eval_fun, double) \2763/* __GMPNLD_DEFINE_BINARY_FUNCTION(fun, eval_fun, long double) */27642765#define __GMP_DEFINE_BINARY_FUNCTION(fun, eval_fun) \2766__GMPP_DEFINE_BINARY_FUNCTION(fun, eval_fun) \2767__GMPN_DEFINE_BINARY_FUNCTION(fun, eval_fun)276827692770#define __GMP_DEFINE_BINARY_FUNCTION_UI(fun, eval_fun) \2771\2772template <class T, class U> \2773inline __gmp_expr \2774<T, __gmp_binary_expr<__gmp_expr<T, U>, mp_bitcnt_t, eval_fun> > \2775fun(const __gmp_expr<T, U> &expr, mp_bitcnt_t l) \2776{ \2777return __gmp_expr<T, __gmp_binary_expr \2778<__gmp_expr<T, U>, mp_bitcnt_t, eval_fun> >(expr, l); \2779}278027812782#define __GMPP_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun) \2783\2784template <class T, class U, class V, class W> \2785inline type fun(const __gmp_expr<T, U> &expr1, \2786const __gmp_expr<V, W> &expr2) \2787{ \2788typedef typename __gmp_resolve_expr<T, V>::value_type eval_type; \2789__gmp_expr<eval_type, eval_type> const& temp1(expr1); \2790__gmp_expr<eval_type, eval_type> const& temp2(expr2); \2791return eval_fun::eval(temp1.__get_mp(), temp2.__get_mp()); \2792}27932794#define __GMPNN_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun, \2795type2, bigtype) \2796\2797template <class T, class U> \2798inline type fun(const __gmp_expr<T, U> &expr, type2 t) \2799{ \2800__gmp_expr<T, T> const& temp(expr); \2801return eval_fun::eval(temp.__get_mp(), static_cast<bigtype>(t)); \2802} \2803\2804template <class T, class U> \2805inline type fun(type2 t, const __gmp_expr<T, U> &expr) \2806{ \2807__gmp_expr<T, T> const& temp(expr); \2808return eval_fun::eval(static_cast<bigtype>(t), temp.__get_mp()); \2809}28102811#define __GMPNS_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun, type2) \2812__GMPNN_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun, \2813type2, signed long int)28142815#define __GMPNU_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun, type2) \2816__GMPNN_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun, \2817type2, unsigned long int)28182819#define __GMPND_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun, type2) \2820__GMPNN_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun, type2, double)28212822#define __GMPNLD_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun, type2) \2823__GMPNN_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun, type2, long double)28242825#define __GMPN_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun) \2826__GMPNS_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun, signed char) \2827__GMPNU_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun, unsigned char) \2828__GMPNS_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun, signed int) \2829__GMPNU_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun, unsigned int) \2830__GMPNS_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun, signed short int) \2831__GMPNU_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun, unsigned short int) \2832__GMPNS_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun, signed long int) \2833__GMPNU_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun, unsigned long int) \2834__GMPND_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun, float) \2835__GMPND_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun, double) \2836/* __GMPNLD_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun, long double) */28372838#define __GMP_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun) \2839__GMPP_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun) \2840__GMPN_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun)284128422843// member operators28442845#define __GMPP_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun) \2846\2847template <class T, class U> \2848inline type##_class & type##_class::fun(const __gmp_expr<T, U> &expr) \2849{ \2850__gmp_set_expr(mp, __gmp_expr<type##_t, __gmp_binary_expr \2851<type##_class, __gmp_expr<T, U>, eval_fun> >(*this, expr)); \2852return *this; \2853}28542855#define __GMPNN_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun, \2856type2, bigtype) \2857\2858inline type##_class & type##_class::fun(type2 t) \2859{ \2860__gmp_set_expr(mp, __gmp_expr<type##_t, __gmp_binary_expr \2861<type##_class, bigtype, eval_fun> >(*this, t)); \2862return *this; \2863}28642865#define __GMPNS_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun, type2) \2866__GMPNN_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun, \2867type2, signed long int)28682869#define __GMPNU_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun, type2) \2870__GMPNN_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun, \2871type2, unsigned long int)28722873#define __GMPND_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun, type2) \2874__GMPNN_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun, type2, double)28752876#define __GMPNLD_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun, type2) \2877__GMPNN_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun, type2, long double)28782879#define __GMPN_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun) \2880__GMPNS_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun, signed char) \2881__GMPNU_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun, unsigned char) \2882__GMPNS_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun, signed int) \2883__GMPNU_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun, unsigned int) \2884__GMPNS_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun, signed short int) \2885__GMPNU_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun, unsigned short int) \2886__GMPNS_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun, signed long int) \2887__GMPNU_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun, unsigned long int) \2888__GMPND_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun, float) \2889__GMPND_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun, double) \2890/* __GMPNLD_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun, long double) */28912892#define __GMP_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun) \2893__GMPP_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun) \2894__GMPN_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun)28952896#define __GMPZ_DEFINE_COMPOUND_OPERATOR(fun, eval_fun) \2897__GMP_DEFINE_COMPOUND_OPERATOR(mpz, fun, eval_fun)28982899#define __GMPQ_DEFINE_COMPOUND_OPERATOR(fun, eval_fun) \2900__GMP_DEFINE_COMPOUND_OPERATOR(mpq, fun, eval_fun)29012902#define __GMPF_DEFINE_COMPOUND_OPERATOR(fun, eval_fun) \2903__GMP_DEFINE_COMPOUND_OPERATOR(mpf, fun, eval_fun)2904290529062907#define __GMP_DEFINE_COMPOUND_OPERATOR_UI(type, fun, eval_fun) \2908\2909inline type##_class & type##_class::fun(mp_bitcnt_t l) \2910{ \2911__gmp_set_expr(mp, __gmp_expr<type##_t, __gmp_binary_expr \2912<type##_class, mp_bitcnt_t, eval_fun> >(*this, l)); \2913return *this; \2914}29152916#define __GMPZ_DEFINE_COMPOUND_OPERATOR_UI(fun, eval_fun) \2917__GMP_DEFINE_COMPOUND_OPERATOR_UI(mpz, fun, eval_fun)29182919#define __GMPQ_DEFINE_COMPOUND_OPERATOR_UI(fun, eval_fun) \2920__GMP_DEFINE_COMPOUND_OPERATOR_UI(mpq, fun, eval_fun)29212922#define __GMPF_DEFINE_COMPOUND_OPERATOR_UI(fun, eval_fun) \2923__GMP_DEFINE_COMPOUND_OPERATOR_UI(mpf, fun, eval_fun)2924292529262927#define __GMP_DEFINE_INCREMENT_OPERATOR(type, fun, eval_fun) \2928\2929inline type##_class & type##_class::fun() \2930{ \2931eval_fun::eval(mp); \2932return *this; \2933} \2934\2935inline type##_class type##_class::fun(int) \2936{ \2937type##_class temp(*this); \2938eval_fun::eval(mp); \2939return temp; \2940}29412942#define __GMPZ_DEFINE_INCREMENT_OPERATOR(fun, eval_fun) \2943__GMP_DEFINE_INCREMENT_OPERATOR(mpz, fun, eval_fun)29442945#define __GMPQ_DEFINE_INCREMENT_OPERATOR(fun, eval_fun) \2946__GMP_DEFINE_INCREMENT_OPERATOR(mpq, fun, eval_fun)29472948#define __GMPF_DEFINE_INCREMENT_OPERATOR(fun, eval_fun) \2949__GMP_DEFINE_INCREMENT_OPERATOR(mpf, fun, eval_fun)2950295129522953/**************** Arithmetic operators and functions ****************/29542955// non-member operators and functions29562957__GMP_DEFINE_UNARY_FUNCTION(operator+, __gmp_unary_plus)2958__GMP_DEFINE_UNARY_FUNCTION(operator-, __gmp_unary_minus)2959__GMP_DEFINE_UNARY_FUNCTION(operator~, __gmp_unary_com)29602961__GMP_DEFINE_BINARY_FUNCTION(operator+, __gmp_binary_plus)2962__GMP_DEFINE_BINARY_FUNCTION(operator-, __gmp_binary_minus)2963__GMP_DEFINE_BINARY_FUNCTION(operator*, __gmp_binary_multiplies)2964__GMP_DEFINE_BINARY_FUNCTION(operator/, __gmp_binary_divides)2965__GMP_DEFINE_BINARY_FUNCTION(operator%, __gmp_binary_modulus)2966__GMP_DEFINE_BINARY_FUNCTION(operator&, __gmp_binary_and)2967__GMP_DEFINE_BINARY_FUNCTION(operator|, __gmp_binary_ior)2968__GMP_DEFINE_BINARY_FUNCTION(operator^, __gmp_binary_xor)29692970__GMP_DEFINE_BINARY_FUNCTION_UI(operator<<, __gmp_binary_lshift)2971__GMP_DEFINE_BINARY_FUNCTION_UI(operator>>, __gmp_binary_rshift)29722973__GMP_DEFINE_BINARY_TYPE_FUNCTION(bool, operator==, __gmp_binary_equal)2974__GMP_DEFINE_BINARY_TYPE_FUNCTION(bool, operator!=, ! __gmp_binary_equal)2975__GMP_DEFINE_BINARY_TYPE_FUNCTION(bool, operator<, __gmp_binary_less)2976__GMP_DEFINE_BINARY_TYPE_FUNCTION(bool, operator<=, ! __gmp_binary_greater)2977__GMP_DEFINE_BINARY_TYPE_FUNCTION(bool, operator>, __gmp_binary_greater)2978__GMP_DEFINE_BINARY_TYPE_FUNCTION(bool, operator>=, ! __gmp_binary_less)29792980__GMP_DEFINE_UNARY_FUNCTION(abs, __gmp_abs_function)2981__GMP_DEFINE_UNARY_FUNCTION(trunc, __gmp_trunc_function)2982__GMP_DEFINE_UNARY_FUNCTION(floor, __gmp_floor_function)2983__GMP_DEFINE_UNARY_FUNCTION(ceil, __gmp_ceil_function)2984__GMP_DEFINE_UNARY_FUNCTION(sqrt, __gmp_sqrt_function)2985__GMP_DEFINE_BINARY_FUNCTION(hypot, __gmp_hypot_function)29862987__GMP_DEFINE_UNARY_TYPE_FUNCTION(int, sgn, __gmp_sgn_function)2988__GMP_DEFINE_BINARY_TYPE_FUNCTION(int, cmp, __gmp_cmp_function)29892990template <class T>2991void swap(__gmp_expr<T, T>& x, __gmp_expr<T, T>& y) __GMPXX_NOEXCEPT2992{ x.swap(y); }29932994// member operators for mpz_class29952996__GMPZ_DEFINE_COMPOUND_OPERATOR(operator+=, __gmp_binary_plus)2997__GMPZ_DEFINE_COMPOUND_OPERATOR(operator-=, __gmp_binary_minus)2998__GMPZ_DEFINE_COMPOUND_OPERATOR(operator*=, __gmp_binary_multiplies)2999__GMPZ_DEFINE_COMPOUND_OPERATOR(operator/=, __gmp_binary_divides)3000__GMPZ_DEFINE_COMPOUND_OPERATOR(operator%=, __gmp_binary_modulus)30013002__GMPZ_DEFINE_COMPOUND_OPERATOR(operator&=, __gmp_binary_and)3003__GMPZ_DEFINE_COMPOUND_OPERATOR(operator|=, __gmp_binary_ior)3004__GMPZ_DEFINE_COMPOUND_OPERATOR(operator^=, __gmp_binary_xor)30053006__GMPZ_DEFINE_COMPOUND_OPERATOR_UI(operator<<=, __gmp_binary_lshift)3007__GMPZ_DEFINE_COMPOUND_OPERATOR_UI(operator>>=, __gmp_binary_rshift)30083009__GMPZ_DEFINE_INCREMENT_OPERATOR(operator++, __gmp_unary_increment)3010__GMPZ_DEFINE_INCREMENT_OPERATOR(operator--, __gmp_unary_decrement)30113012// member operators for mpq_class30133014__GMPQ_DEFINE_COMPOUND_OPERATOR(operator+=, __gmp_binary_plus)3015__GMPQ_DEFINE_COMPOUND_OPERATOR(operator-=, __gmp_binary_minus)3016__GMPQ_DEFINE_COMPOUND_OPERATOR(operator*=, __gmp_binary_multiplies)3017__GMPQ_DEFINE_COMPOUND_OPERATOR(operator/=, __gmp_binary_divides)30183019__GMPQ_DEFINE_COMPOUND_OPERATOR_UI(operator<<=, __gmp_binary_lshift)3020__GMPQ_DEFINE_COMPOUND_OPERATOR_UI(operator>>=, __gmp_binary_rshift)30213022__GMPQ_DEFINE_INCREMENT_OPERATOR(operator++, __gmp_unary_increment)3023__GMPQ_DEFINE_INCREMENT_OPERATOR(operator--, __gmp_unary_decrement)30243025// member operators for mpf_class30263027__GMPF_DEFINE_COMPOUND_OPERATOR(operator+=, __gmp_binary_plus)3028__GMPF_DEFINE_COMPOUND_OPERATOR(operator-=, __gmp_binary_minus)3029__GMPF_DEFINE_COMPOUND_OPERATOR(operator*=, __gmp_binary_multiplies)3030__GMPF_DEFINE_COMPOUND_OPERATOR(operator/=, __gmp_binary_divides)30313032__GMPF_DEFINE_COMPOUND_OPERATOR_UI(operator<<=, __gmp_binary_lshift)3033__GMPF_DEFINE_COMPOUND_OPERATOR_UI(operator>>=, __gmp_binary_rshift)30343035__GMPF_DEFINE_INCREMENT_OPERATOR(operator++, __gmp_unary_increment)3036__GMPF_DEFINE_INCREMENT_OPERATOR(operator--, __gmp_unary_decrement)3037303830393040/**************** Class wrapper for gmp_randstate_t ****************/30413042class __gmp_urandomb_value { };3043class __gmp_urandomm_value { };30443045template <>3046class __gmp_expr<mpz_t, __gmp_urandomb_value>3047{3048private:3049__gmp_randstate_struct *state;3050mp_bitcnt_t bits;3051public:3052__gmp_expr(gmp_randstate_t s, mp_bitcnt_t l) : state(s), bits(l) { }3053void eval(mpz_ptr z) const { __gmp_rand_function::eval(z, state, bits); }3054mp_bitcnt_t get_prec() const { return mpf_get_default_prec(); }3055};30563057template <>3058class __gmp_expr<mpz_t, __gmp_urandomm_value>3059{3060private:3061__gmp_randstate_struct *state;3062mpz_class range;3063public:3064__gmp_expr(gmp_randstate_t s, const mpz_class &z) : state(s), range(z) { }3065void eval(mpz_ptr z) const3066{ __gmp_rand_function::eval(z, state, range.get_mpz_t()); }3067mp_bitcnt_t get_prec() const { return mpf_get_default_prec(); }3068};30693070template <>3071class __gmp_expr<mpf_t, __gmp_urandomb_value>3072{3073private:3074__gmp_randstate_struct *state;3075mp_bitcnt_t bits;3076public:3077__gmp_expr(gmp_randstate_t s, mp_bitcnt_t l) : state(s), bits(l) { }3078void eval(mpf_ptr f) const3079{3080__gmp_rand_function::eval(f, state,3081(bits>0) ? bits : mpf_get_prec(f));3082}3083mp_bitcnt_t get_prec() const3084{3085if (bits == 0)3086return mpf_get_default_prec();3087else3088return bits;3089}3090};30913092extern "C" {3093typedef void __gmp_randinit_default_t (gmp_randstate_t);3094typedef void __gmp_randinit_lc_2exp_t (gmp_randstate_t, mpz_srcptr, unsigned long int, mp_bitcnt_t);3095typedef int __gmp_randinit_lc_2exp_size_t (gmp_randstate_t, mp_bitcnt_t);3096}30973098class gmp_randclass3099{3100private:3101gmp_randstate_t state;31023103// copy construction and assignment not allowed3104gmp_randclass(const gmp_randclass &);3105void operator=(const gmp_randclass &);3106public:3107// constructors and destructor3108gmp_randclass(gmp_randalg_t alg, unsigned long int size)3109{3110switch (alg)3111{3112case GMP_RAND_ALG_LC: // no other cases for now3113default:3114gmp_randinit(state, alg, size);3115break;3116}3117}31183119// gmp_randinit_default3120gmp_randclass(__gmp_randinit_default_t* f) { f(state); }31213122// gmp_randinit_lc_2exp3123gmp_randclass(__gmp_randinit_lc_2exp_t* f,3124mpz_class z, unsigned long int l1, mp_bitcnt_t l2)3125{ f(state, z.get_mpz_t(), l1, l2); }31263127// gmp_randinit_lc_2exp_size3128gmp_randclass(__gmp_randinit_lc_2exp_size_t* f,3129mp_bitcnt_t size)3130{3131if (f (state, size) == 0)3132throw std::length_error ("gmp_randinit_lc_2exp_size");3133}31343135~gmp_randclass() { gmp_randclear(state); }31363137// initialize3138void seed(); // choose a random seed some way (?)3139void seed(unsigned long int s) { gmp_randseed_ui(state, s); }3140void seed(const mpz_class &z) { gmp_randseed(state, z.get_mpz_t()); }31413142// get random number3143__gmp_expr<mpz_t, __gmp_urandomb_value> get_z_bits(mp_bitcnt_t l)3144{ return __gmp_expr<mpz_t, __gmp_urandomb_value>(state, l); }3145__gmp_expr<mpz_t, __gmp_urandomb_value> get_z_bits(const mpz_class &z)3146{ return get_z_bits(z.get_ui()); }3147// FIXME: z.get_bitcnt_t() ?31483149__gmp_expr<mpz_t, __gmp_urandomm_value> get_z_range(const mpz_class &z)3150{ return __gmp_expr<mpz_t, __gmp_urandomm_value>(state, z); }31513152__gmp_expr<mpf_t, __gmp_urandomb_value> get_f(mp_bitcnt_t prec = 0)3153{ return __gmp_expr<mpf_t, __gmp_urandomb_value>(state, prec); }3154};315531563157/**************** Specialize std::numeric_limits ****************/31583159namespace std {3160template <> class numeric_limits<mpz_class>3161{3162public:3163static const bool is_specialized = true;3164static mpz_class min() { return mpz_class(); }3165static mpz_class max() { return mpz_class(); }3166static mpz_class lowest() { return mpz_class(); }3167static const int digits = 0;3168static const int digits10 = 0;3169static const int max_digits10 = 0;3170static const bool is_signed = true;3171static const bool is_integer = true;3172static const bool is_exact = true;3173static const int radix = 2;3174static mpz_class epsilon() { return mpz_class(); }3175static mpz_class round_error() { return mpz_class(); }3176static const int min_exponent = 0;3177static const int min_exponent10 = 0;3178static const int max_exponent = 0;3179static const int max_exponent10 = 0;3180static const bool has_infinity = false;3181static const bool has_quiet_NaN = false;3182static const bool has_signaling_NaN = false;3183static const float_denorm_style has_denorm = denorm_absent;3184static const bool has_denorm_loss = false;3185static mpz_class infinity() { return mpz_class(); }3186static mpz_class quiet_NaN() { return mpz_class(); }3187static mpz_class signaling_NaN() { return mpz_class(); }3188static mpz_class denorm_min() { return mpz_class(); }3189static const bool is_iec559 = false;3190static const bool is_bounded = false;3191static const bool is_modulo = false;3192static const bool traps = false;3193static const bool tinyness_before = false;3194static const float_round_style round_style = round_toward_zero;3195};31963197template <> class numeric_limits<mpq_class>3198{3199public:3200static const bool is_specialized = true;3201static mpq_class min() { return mpq_class(); }3202static mpq_class max() { return mpq_class(); }3203static mpq_class lowest() { return mpq_class(); }3204static const int digits = 0;3205static const int digits10 = 0;3206static const int max_digits10 = 0;3207static const bool is_signed = true;3208static const bool is_integer = false;3209static const bool is_exact = true;3210static const int radix = 2;3211static mpq_class epsilon() { return mpq_class(); }3212static mpq_class round_error() { return mpq_class(); }3213static const int min_exponent = 0;3214static const int min_exponent10 = 0;3215static const int max_exponent = 0;3216static const int max_exponent10 = 0;3217static const bool has_infinity = false;3218static const bool has_quiet_NaN = false;3219static const bool has_signaling_NaN = false;3220static const float_denorm_style has_denorm = denorm_absent;3221static const bool has_denorm_loss = false;3222static mpq_class infinity() { return mpq_class(); }3223static mpq_class quiet_NaN() { return mpq_class(); }3224static mpq_class signaling_NaN() { return mpq_class(); }3225static mpq_class denorm_min() { return mpq_class(); }3226static const bool is_iec559 = false;3227static const bool is_bounded = false;3228static const bool is_modulo = false;3229static const bool traps = false;3230static const bool tinyness_before = false;3231static const float_round_style round_style = round_toward_zero;3232};32333234template <> class numeric_limits<mpf_class>3235{3236public:3237static const bool is_specialized = true;3238static mpf_class min() { return mpf_class(); }3239static mpf_class max() { return mpf_class(); }3240static mpf_class lowest() { return mpf_class(); }3241static const int digits = 0;3242static const int digits10 = 0;3243static const int max_digits10 = 0;3244static const bool is_signed = true;3245static const bool is_integer = false;3246static const bool is_exact = false;3247static const int radix = 2;3248static mpf_class epsilon() { return mpf_class(); }3249static mpf_class round_error() { return mpf_class(); }3250static const int min_exponent = 0;3251static const int min_exponent10 = 0;3252static const int max_exponent = 0;3253static const int max_exponent10 = 0;3254static const bool has_infinity = false;3255static const bool has_quiet_NaN = false;3256static const bool has_signaling_NaN = false;3257static const float_denorm_style has_denorm = denorm_absent;3258static const bool has_denorm_loss = false;3259static mpf_class infinity() { return mpf_class(); }3260static mpf_class quiet_NaN() { return mpf_class(); }3261static mpf_class signaling_NaN() { return mpf_class(); }3262static mpf_class denorm_min() { return mpf_class(); }3263static const bool is_iec559 = false;3264static const bool is_bounded = false;3265static const bool is_modulo = false;3266static const bool traps = false;3267static const bool tinyness_before = false;3268static const float_round_style round_style = round_indeterminate;3269};3270}327132723273/**************** #undef all private macros ****************/32743275#undef __GMPP_DECLARE_COMPOUND_OPERATOR3276#undef __GMPN_DECLARE_COMPOUND_OPERATOR3277#undef __GMP_DECLARE_COMPOUND_OPERATOR3278#undef __GMP_DECLARE_COMPOUND_OPERATOR_UI3279#undef __GMP_DECLARE_INCREMENT_OPERATOR3280#undef __GMPXX_DEFINE_ARITHMETIC_CONSTRUCTORS3281#undef __GMPXX_DEFINE_ARITHMETIC_ASSIGNMENTS32823283#undef __GMPZQ_DEFINE_EXPR32843285#undef __GMP_DEFINE_UNARY_FUNCTION3286#undef __GMP_DEFINE_UNARY_TYPE_FUNCTION32873288#undef __GMPP_DEFINE_BINARY_FUNCTION3289#undef __GMPNN_DEFINE_BINARY_FUNCTION3290#undef __GMPNS_DEFINE_BINARY_FUNCTION3291#undef __GMPNU_DEFINE_BINARY_FUNCTION3292#undef __GMPND_DEFINE_BINARY_FUNCTION3293#undef __GMPNLD_DEFINE_BINARY_FUNCTION3294#undef __GMPN_DEFINE_BINARY_FUNCTION3295#undef __GMP_DEFINE_BINARY_FUNCTION32963297#undef __GMP_DEFINE_BINARY_FUNCTION_UI32983299#undef __GMPP_DEFINE_BINARY_TYPE_FUNCTION3300#undef __GMPNN_DEFINE_BINARY_TYPE_FUNCTION3301#undef __GMPNS_DEFINE_BINARY_TYPE_FUNCTION3302#undef __GMPNU_DEFINE_BINARY_TYPE_FUNCTION3303#undef __GMPND_DEFINE_BINARY_TYPE_FUNCTION3304#undef __GMPNLD_DEFINE_BINARY_TYPE_FUNCTION3305#undef __GMPN_DEFINE_BINARY_TYPE_FUNCTION3306#undef __GMP_DEFINE_BINARY_TYPE_FUNCTION33073308#undef __GMPZ_DEFINE_COMPOUND_OPERATOR33093310#undef __GMPP_DEFINE_COMPOUND_OPERATOR3311#undef __GMPNN_DEFINE_COMPOUND_OPERATOR3312#undef __GMPNS_DEFINE_COMPOUND_OPERATOR3313#undef __GMPNU_DEFINE_COMPOUND_OPERATOR3314#undef __GMPND_DEFINE_COMPOUND_OPERATOR3315#undef __GMPNLD_DEFINE_COMPOUND_OPERATOR3316#undef __GMPN_DEFINE_COMPOUND_OPERATOR3317#undef __GMP_DEFINE_COMPOUND_OPERATOR33183319#undef __GMPQ_DEFINE_COMPOUND_OPERATOR3320#undef __GMPF_DEFINE_COMPOUND_OPERATOR33213322#undef __GMP_DEFINE_COMPOUND_OPERATOR_UI3323#undef __GMPZ_DEFINE_COMPOUND_OPERATOR_UI3324#undef __GMPQ_DEFINE_COMPOUND_OPERATOR_UI3325#undef __GMPF_DEFINE_COMPOUND_OPERATOR_UI33263327#undef __GMP_DEFINE_INCREMENT_OPERATOR3328#undef __GMPZ_DEFINE_INCREMENT_OPERATOR3329#undef __GMPQ_DEFINE_INCREMENT_OPERATOR3330#undef __GMPF_DEFINE_INCREMENT_OPERATOR33313332#undef __GMPXX_CONSTANT_TRUE3333#undef __GMPXX_CONSTANT33343335#endif /* __GMP_PLUSPLUS__ */333633373338