[BACK]Return to gmpxx.h CVS log [TXT][DIR] Up to [local] / OpenXM_contrib2 / windows / mpir

Annotation of OpenXM_contrib2/windows/mpir/gmpxx.h, Revision 1.1

1.1     ! ohara       1: /* mpirxx.h -- C++ class wrapper for GMP types.  -*- C++ -*-
        !             2:
        !             3: Copyright 2001, 2002, 2003, 2006, 2008 Free Software Foundation, Inc.
        !             4:
        !             5: Copyright 2009 William Hart
        !             6:
        !             7: This file is part of the GNU MP Library.
        !             8:
        !             9: The GNU MP Library is free software; you can redistribute it and/or modify
        !            10: it under the terms of the GNU Lesser General Public License as published by
        !            11: the Free Software Foundation; either version 3 of the License, or (at your
        !            12: option) any later version.
        !            13:
        !            14: The GNU MP Library is distributed in the hope that it will be useful, but
        !            15: WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
        !            16: or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
        !            17: License for more details.
        !            18:
        !            19: You should have received a copy of the GNU Lesser General Public License
        !            20: along with the GNU MP Library.  If not, see http://www.gnu.org/licenses/.  */
        !            21:
        !            22: /* the C++ compiler must implement the following features:
        !            23:    - member templates
        !            24:    - partial specialization of templates
        !            25:    - namespace support
        !            26:    for g++, this means version 2.91 or higher
        !            27:    for other compilers, I don't know */
        !            28: #ifdef __GNUC__
        !            29: #if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 91)
        !            30: #error mpirxx.h requires g++ version 2.91 (egcs 1.1.2) or higher
        !            31: #endif
        !            32: #endif
        !            33:
        !            34: #ifndef __GMP_PLUSPLUS__
        !            35: #define __GMP_PLUSPLUS__
        !            36:
        !            37: #include <iosfwd>
        !            38:
        !            39: #include <cstring>  /* for strlen */
        !            40: #include <string>
        !            41: #include <stdexcept>
        !            42: #include <cfloat>
        !            43:
        !            44: #include <gmp.h>
        !            45:
        !            46: #include <climits>
        !            47:
        !            48: #ifdef LLONG_MAX
        !            49: #if LLONG_MAX != LONG_MAX
        !            50: #define MPIRXX_HAVE_LLONG 1
        !            51: #endif
        !            52: #endif
        !            53:
        !            54: /**************** Function objects ****************/
        !            55: /* Any evaluation of a __gmp_expr ends up calling one of these functions
        !            56:    all intermediate functions being inline, the evaluation should optimize
        !            57:    to a direct call to the relevant function, thus yielding no overhead
        !            58:    over the C interface. */
        !            59:
        !            60: struct __gmp_unary_plus
        !            61: {
        !            62:   static void eval(mpz_ptr z, mpz_srcptr w) { mpz_set(z, w); }
        !            63:   static void eval(mpq_ptr q, mpq_srcptr r) { mpq_set(q, r); }
        !            64:   static void eval(mpf_ptr f, mpf_srcptr g) { mpf_set(f, g); }
        !            65: };
        !            66:
        !            67: struct __gmp_unary_minus
        !            68: {
        !            69:   static void eval(mpz_ptr z, mpz_srcptr w) { mpz_neg(z, w); }
        !            70:   static void eval(mpq_ptr q, mpq_srcptr r) { mpq_neg(q, r); }
        !            71:   static void eval(mpf_ptr f, mpf_srcptr g) { mpf_neg(f, g); }
        !            72: };
        !            73:
        !            74: struct __gmp_unary_com
        !            75: {
        !            76:   static void eval(mpz_ptr z, mpz_srcptr w) { mpz_com(z, w); }
        !            77: };
        !            78:
        !            79: struct __gmp_binary_plus
        !            80: {
        !            81:   static void eval(mpz_ptr z, mpz_srcptr w, mpz_srcptr v)
        !            82:   { mpz_add(z, w, v); }
        !            83:
        !            84:   static void eval(mpz_ptr z, mpz_srcptr w, mpir_ui l)
        !            85:   { mpz_add_ui(z, w, l); }
        !            86:   static void eval(mpz_ptr z, mpir_ui l, mpz_srcptr w)
        !            87:   { mpz_add_ui(z, w, l); }
        !            88:   static void eval(mpz_ptr z, mpz_srcptr w, mpir_si l)
        !            89:   {
        !            90:     if (l >= 0)
        !            91:       mpz_add_ui(z, w, l);
        !            92:     else
        !            93:       mpz_sub_ui(z, w, -l);
        !            94:   }
        !            95:   static void eval(mpz_ptr z, mpir_si l, mpz_srcptr w)
        !            96:   {
        !            97:     if (l >= 0)
        !            98:       mpz_add_ui(z, w, l);
        !            99:     else
        !           100:       mpz_sub_ui(z, w, -l);
        !           101:   }
        !           102:   static void eval(mpz_ptr z, mpz_srcptr w, double d)
        !           103:   {
        !           104:     mpz_t temp;
        !           105:     mpz_init_set_d(temp, d);
        !           106:     mpz_add(z, w, temp);
        !           107:     mpz_clear(temp);
        !           108:   }
        !           109:   static void eval(mpz_ptr z, double d, mpz_srcptr w)
        !           110:   {
        !           111:     mpz_t temp;
        !           112:     mpz_init_set_d(temp, d);
        !           113:     mpz_add(z, temp, w);
        !           114:     mpz_clear(temp);
        !           115:   }
        !           116:
        !           117:   static void eval(mpq_ptr q, mpq_srcptr r, mpq_srcptr s)
        !           118:   { mpq_add(q, r, s); }
        !           119:
        !           120:   static void eval(mpq_ptr q, mpq_srcptr r, mpir_ui l)
        !           121:   { mpq_set(q, r); mpz_addmul_ui(mpq_numref(q), mpq_denref(q), l); }
        !           122:   static void eval(mpq_ptr q, mpir_ui l, mpq_srcptr r)
        !           123:   { mpq_set(q, r); mpz_addmul_ui(mpq_numref(q), mpq_denref(q), l); }
        !           124:   static void eval(mpq_ptr q, mpq_srcptr r, mpir_si l)
        !           125:   {
        !           126:     mpq_set(q, r);
        !           127:     if (l >= 0)
        !           128:       mpz_addmul_ui(mpq_numref(q), mpq_denref(q), l);
        !           129:     else
        !           130:       mpz_submul_ui(mpq_numref(q), mpq_denref(q), -l);
        !           131:   }
        !           132:   static void eval(mpq_ptr q, mpir_si l, mpq_srcptr r)
        !           133:   {
        !           134:     mpq_set(q, r);
        !           135:     if (l >= 0)
        !           136:       mpz_addmul_ui(mpq_numref(q), mpq_denref(q), l);
        !           137:     else
        !           138:       mpz_submul_ui(mpq_numref(q), mpq_denref(q), -l);
        !           139:   }
        !           140:   static void eval(mpq_ptr q, mpq_srcptr r, double d)
        !           141:   {
        !           142:     mpq_t temp;
        !           143:     mpq_init(temp);
        !           144:     mpq_set_d(temp, d);
        !           145:     mpq_add(q, r, temp);
        !           146:     mpq_clear(temp);
        !           147:   }
        !           148:   static void eval(mpq_ptr q, double d, mpq_srcptr r)
        !           149:   {
        !           150:     mpq_t temp;
        !           151:     mpq_init(temp);
        !           152:     mpq_set_d(temp, d);
        !           153:     mpq_add(q, temp, r);
        !           154:     mpq_clear(temp);
        !           155:   }
        !           156:
        !           157:   static void eval(mpq_ptr q, mpq_srcptr r, mpz_srcptr z)
        !           158:   { mpq_set(q, r); mpz_addmul(mpq_numref(q), mpq_denref(q), z); }
        !           159:   static void eval(mpq_ptr q, mpz_srcptr z, mpq_srcptr r)
        !           160:   { mpq_set(q, r); mpz_addmul(mpq_numref(q), mpq_denref(q), z); }
        !           161:
        !           162:   static void eval(mpf_ptr f, mpf_srcptr g, mpf_srcptr h)
        !           163:   { mpf_add(f, g, h); }
        !           164:
        !           165:   static void eval(mpf_ptr f, mpf_srcptr g, mpir_ui l)
        !           166:   { mpf_add_ui(f, g, l); }
        !           167:   static void eval(mpf_ptr f, mpir_ui l, mpf_srcptr g)
        !           168:   { mpf_add_ui(f, g, l); }
        !           169:   static void eval(mpf_ptr f, mpf_srcptr g, mpir_si l)
        !           170:   {
        !           171:     if (l >= 0)
        !           172:       mpf_add_ui(f, g, l);
        !           173:     else
        !           174:       mpf_sub_ui(f, g, -l);
        !           175:   }
        !           176:   static void eval(mpf_ptr f, mpir_si l, mpf_srcptr g)
        !           177:   {
        !           178:     if (l >= 0)
        !           179:       mpf_add_ui(f, g, l);
        !           180:     else
        !           181:       mpf_sub_ui(f, g, -l);
        !           182:   }
        !           183:   static void eval(mpf_ptr f, mpf_srcptr g, double d)
        !           184:   {
        !           185:     mpf_t temp;
        !           186:     mpf_init2(temp, 8*sizeof(double));
        !           187:     mpf_set_d(temp, d);
        !           188:     mpf_add(f, g, temp);
        !           189:     mpf_clear(temp);
        !           190:   }
        !           191:   static void eval(mpf_ptr f, double d, mpf_srcptr g)
        !           192:   {
        !           193:     mpf_t temp;
        !           194:     mpf_init2(temp, 8*sizeof(double));
        !           195:     mpf_set_d(temp, d);
        !           196:     mpf_add(f, temp, g);
        !           197:     mpf_clear(temp);
        !           198:   }
        !           199: };
        !           200:
        !           201: struct __gmp_binary_minus
        !           202: {
        !           203:   static void eval(mpz_ptr z, mpz_srcptr w, mpz_srcptr v)
        !           204:   { mpz_sub(z, w, v); }
        !           205:
        !           206:   static void eval(mpz_ptr z, mpz_srcptr w, mpir_ui l)
        !           207:   { mpz_sub_ui(z, w, l); }
        !           208:   static void eval(mpz_ptr z, mpir_ui l, mpz_srcptr w)
        !           209:   { mpz_ui_sub(z, l, w); }
        !           210:   static void eval(mpz_ptr z, mpz_srcptr w, mpir_si l)
        !           211:   {
        !           212:     if (l >= 0)
        !           213:       mpz_sub_ui(z, w, l);
        !           214:     else
        !           215:       mpz_add_ui(z, w, -l);
        !           216:   }
        !           217:   static void eval(mpz_ptr z, mpir_si l, mpz_srcptr w)
        !           218:   {
        !           219:     if (l >= 0)
        !           220:       mpz_ui_sub(z, l, w);
        !           221:     else
        !           222:       {
        !           223:         mpz_add_ui(z, w, -l);
        !           224:         mpz_neg(z, z);
        !           225:       }
        !           226:   }
        !           227:   static void eval(mpz_ptr z, mpz_srcptr w, double d)
        !           228:   {
        !           229:     mpz_t temp;
        !           230:     mpz_init_set_d(temp, d);
        !           231:     mpz_sub(z, w, temp);
        !           232:     mpz_clear(temp);
        !           233:   }
        !           234:   static void eval(mpz_ptr z, double d, mpz_srcptr w)
        !           235:   {
        !           236:     mpz_t temp;
        !           237:     mpz_init_set_d(temp, d);
        !           238:     mpz_sub(z, temp, w);
        !           239:     mpz_clear(temp);
        !           240:   }
        !           241:
        !           242:   static void eval(mpq_ptr q, mpq_srcptr r, mpq_srcptr s)
        !           243:   { mpq_sub(q, r, s); }
        !           244:
        !           245:   static void eval(mpq_ptr q, mpq_srcptr r, mpir_ui l)
        !           246:   { mpq_set(q, r); mpz_submul_ui(mpq_numref(q), mpq_denref(q), l); }
        !           247:   static void eval(mpq_ptr q, mpir_ui l, mpq_srcptr r)
        !           248:   { mpq_neg(q, r); mpz_addmul_ui(mpq_numref(q), mpq_denref(q), l); }
        !           249:   static void eval(mpq_ptr q, mpq_srcptr r, mpir_si l)
        !           250:   {
        !           251:     mpq_set(q, r);
        !           252:     if (l >= 0)
        !           253:       mpz_submul_ui(mpq_numref(q), mpq_denref(q), l);
        !           254:     else
        !           255:       mpz_addmul_ui(mpq_numref(q), mpq_denref(q), -l);
        !           256:   }
        !           257:   static void eval(mpq_ptr q, mpir_si l, mpq_srcptr r)
        !           258:   {
        !           259:     mpq_neg(q, r);
        !           260:     if (l >= 0)
        !           261:       mpz_addmul_ui(mpq_numref(q), mpq_denref(q), l);
        !           262:     else
        !           263:       mpz_submul_ui(mpq_numref(q), mpq_denref(q), -l);
        !           264:   }
        !           265:   static void eval(mpq_ptr q, mpq_srcptr r, double d)
        !           266:   {
        !           267:     mpq_t temp;
        !           268:     mpq_init(temp);
        !           269:     mpq_set_d(temp, d);
        !           270:     mpq_sub(q, r, temp);
        !           271:     mpq_clear(temp);
        !           272:   }
        !           273:   static void eval(mpq_ptr q, double d, mpq_srcptr r)
        !           274:   {
        !           275:     mpq_t temp;
        !           276:     mpq_init(temp);
        !           277:     mpq_set_d(temp, d);
        !           278:     mpq_sub(q, temp, r);
        !           279:     mpq_clear(temp);
        !           280:   }
        !           281:
        !           282:   static void eval(mpq_ptr q, mpq_srcptr r, mpz_srcptr z)
        !           283:   { mpq_set(q, r); mpz_submul(mpq_numref(q), mpq_denref(q), z); }
        !           284:   static void eval(mpq_ptr q, mpz_srcptr z, mpq_srcptr r)
        !           285:   { mpq_neg(q, r); mpz_addmul(mpq_numref(q), mpq_denref(q), z); }
        !           286:
        !           287:   static void eval(mpf_ptr f, mpf_srcptr g, mpf_srcptr h)
        !           288:   { mpf_sub(f, g, h); }
        !           289:
        !           290:   static void eval(mpf_ptr f, mpf_srcptr g, mpir_ui l)
        !           291:   { mpf_sub_ui(f, g, l); }
        !           292:   static void eval(mpf_ptr f, mpir_ui l, mpf_srcptr g)
        !           293:   { mpf_ui_sub(f, l, g); }
        !           294:   static void eval(mpf_ptr f, mpf_srcptr g, mpir_si l)
        !           295:   {
        !           296:     if (l >= 0)
        !           297:       mpf_sub_ui(f, g, l);
        !           298:     else
        !           299:       mpf_add_ui(f, g, -l);
        !           300:   }
        !           301:   static void eval(mpf_ptr f, mpir_si l, mpf_srcptr g)
        !           302:   {
        !           303:     if (l >= 0)
        !           304:       mpf_sub_ui(f, g, l);
        !           305:     else
        !           306:       mpf_add_ui(f, g, -l);
        !           307:     mpf_neg(f, f);
        !           308:   }
        !           309:   static void eval(mpf_ptr f, mpf_srcptr g, double d)
        !           310:   {
        !           311:     mpf_t temp;
        !           312:     mpf_init2(temp, 8*sizeof(double));
        !           313:     mpf_set_d(temp, d);
        !           314:     mpf_sub(f, g, temp);
        !           315:     mpf_clear(temp);
        !           316:   }
        !           317:   static void eval(mpf_ptr f, double d, mpf_srcptr g)
        !           318:   {
        !           319:     mpf_t temp;
        !           320:     mpf_init2(temp, 8*sizeof(double));
        !           321:     mpf_set_d(temp, d);
        !           322:     mpf_sub(f, temp, g);
        !           323:     mpf_clear(temp);
        !           324:   }
        !           325: };
        !           326:
        !           327: struct __gmp_binary_multiplies
        !           328: {
        !           329:   static void eval(mpz_ptr z, mpz_srcptr w, mpz_srcptr v)
        !           330:   { mpz_mul(z, w, v); }
        !           331:
        !           332:   static void eval(mpz_ptr z, mpz_srcptr w, mpir_ui l)
        !           333:   { mpz_mul_ui(z, w, l); }
        !           334:   static void eval(mpz_ptr z, mpir_ui l, mpz_srcptr w)
        !           335:   { mpz_mul_ui(z, w, l); }
        !           336:   static void eval(mpz_ptr z, mpz_srcptr w, mpir_si l)
        !           337:   { mpz_mul_si (z, w, l); }
        !           338:   static void eval(mpz_ptr z, mpir_si l, mpz_srcptr w)
        !           339:   { mpz_mul_si (z, w, l); }
        !           340:   static void eval(mpz_ptr z, mpz_srcptr w, double d)
        !           341:   {
        !           342:     mpz_t temp;
        !           343:     mpz_init_set_d(temp, d);
        !           344:     mpz_mul(z, w, temp);
        !           345:     mpz_clear(temp);
        !           346:   }
        !           347:   static void eval(mpz_ptr z, double d, mpz_srcptr w)
        !           348:   {
        !           349:     mpz_t temp;
        !           350:     mpz_init_set_d(temp, d);
        !           351:     mpz_mul(z, temp, w);
        !           352:     mpz_clear(temp);
        !           353:   }
        !           354:
        !           355:   static void eval(mpq_ptr q, mpq_srcptr r, mpq_srcptr s)
        !           356:   { mpq_mul(q, r, s); }
        !           357:
        !           358:   static void eval(mpq_ptr q, mpq_srcptr r, mpir_ui l)
        !           359:   {
        !           360:     mpq_t temp;
        !           361:     mpq_init(temp);
        !           362:     mpq_set_ui(temp, l, 1);
        !           363:     mpq_mul(q, r, temp);
        !           364:     mpq_clear(temp);
        !           365:   }
        !           366:   static void eval(mpq_ptr q, mpir_ui l, mpq_srcptr r)
        !           367:   {
        !           368:     mpq_t temp;
        !           369:     mpq_init(temp);
        !           370:     mpq_set_ui(temp, l, 1);
        !           371:     mpq_mul(q, temp, r);
        !           372:     mpq_clear(temp);
        !           373:   }
        !           374:   static void eval(mpq_ptr q, mpq_srcptr r, mpir_si l)
        !           375:   {
        !           376:     mpq_t temp;
        !           377:     mpq_init(temp);
        !           378:     mpq_set_si(temp, l, 1);
        !           379:     mpq_mul(q, r, temp);
        !           380:     mpq_clear(temp);
        !           381:   }
        !           382:   static void eval(mpq_ptr q, mpir_si l, mpq_srcptr r)
        !           383:   {
        !           384:     mpq_t temp;
        !           385:     mpq_init(temp);
        !           386:     mpq_set_si(temp, l, 1);
        !           387:     mpq_mul(q, temp, r);
        !           388:     mpq_clear(temp);
        !           389:   }
        !           390:   static void eval(mpq_ptr q, mpq_srcptr r, double d)
        !           391:   {
        !           392:     mpq_t temp;
        !           393:     mpq_init(temp);
        !           394:     mpq_set_d(temp, d);
        !           395:     mpq_mul(q, r, temp);
        !           396:     mpq_clear(temp);
        !           397:   }
        !           398:   static void eval(mpq_ptr q, double d, mpq_srcptr r)
        !           399:   {
        !           400:     mpq_t temp;
        !           401:     mpq_init(temp);
        !           402:     mpq_set_d(temp, d);
        !           403:     mpq_mul(q, temp, r);
        !           404:     mpq_clear(temp);
        !           405:   }
        !           406:
        !           407:   static void eval(mpf_ptr f, mpf_srcptr g, mpf_srcptr h)
        !           408:   { mpf_mul(f, g, h); }
        !           409:
        !           410:   static void eval(mpf_ptr f, mpf_srcptr g, mpir_ui l)
        !           411:   { mpf_mul_ui(f, g, l); }
        !           412:   static void eval(mpf_ptr f, mpir_ui l, mpf_srcptr g)
        !           413:   { mpf_mul_ui(f, g, l); }
        !           414:   static void eval(mpf_ptr f, mpf_srcptr g, mpir_si l)
        !           415:   {
        !           416:     if (l >= 0)
        !           417:       mpf_mul_ui(f, g, l);
        !           418:     else
        !           419:       {
        !           420:        mpf_mul_ui(f, g, -l);
        !           421:        mpf_neg(f, f);
        !           422:       }
        !           423:   }
        !           424:   static void eval(mpf_ptr f, mpir_si l, mpf_srcptr g)
        !           425:   {
        !           426:     if (l >= 0)
        !           427:       mpf_mul_ui(f, g, l);
        !           428:     else
        !           429:       {
        !           430:        mpf_mul_ui(f, g, -l);
        !           431:        mpf_neg(f, f);
        !           432:       }
        !           433:   }
        !           434:   static void eval(mpf_ptr f, mpf_srcptr g, double d)
        !           435:   {
        !           436:     mpf_t temp;
        !           437:     mpf_init2(temp, 8*sizeof(double));
        !           438:     mpf_set_d(temp, d);
        !           439:     mpf_mul(f, g, temp);
        !           440:     mpf_clear(temp);
        !           441:   }
        !           442:   static void eval(mpf_ptr f, double d, mpf_srcptr g)
        !           443:   {
        !           444:     mpf_t temp;
        !           445:     mpf_init2(temp, 8*sizeof(double));
        !           446:     mpf_set_d(temp, d);
        !           447:     mpf_mul(f, temp, g);
        !           448:     mpf_clear(temp);
        !           449:   }
        !           450: };
        !           451:
        !           452: struct __gmp_binary_divides
        !           453: {
        !           454:   static void eval(mpz_ptr z, mpz_srcptr w, mpz_srcptr v)
        !           455:   { mpz_tdiv_q(z, w, v); }
        !           456:
        !           457:   static void eval(mpz_ptr z, mpz_srcptr w, mpir_ui l)
        !           458:   { mpz_tdiv_q_ui(z, w, l); }
        !           459:   static void eval(mpz_ptr z, mpir_ui l, mpz_srcptr w)
        !           460:   {
        !           461:     if (mpz_sgn(w) >= 0)
        !           462:       {
        !           463:        if (mpz_fits_ui_p(w))
        !           464:          mpz_set_ui(z, l / mpz_get_ui(w));
        !           465:        else
        !           466:          mpz_set_ui(z, 0);
        !           467:       }
        !           468:     else
        !           469:       {
        !           470:        mpz_neg(z, w);
        !           471:        if (mpz_fits_ui_p(z))
        !           472:          {
        !           473:            mpz_set_ui(z, l / mpz_get_ui(z));
        !           474:            mpz_neg(z, z);
        !           475:          }
        !           476:        else
        !           477:          mpz_set_ui(z, 0);
        !           478:       }
        !           479:   }
        !           480:   static void eval(mpz_ptr z, mpz_srcptr w, mpir_si l)
        !           481:   {
        !           482:     if (l >= 0)
        !           483:       mpz_tdiv_q_ui(z, w, l);
        !           484:     else
        !           485:       {
        !           486:        mpz_tdiv_q_ui(z, w, -l);
        !           487:        mpz_neg(z, z);
        !           488:       }
        !           489:   }
        !           490:   static void eval(mpz_ptr z, mpir_si l, mpz_srcptr w)
        !           491:   {
        !           492:     if (mpz_fits_si_p(w))
        !           493:       mpz_set_si(z, l / mpz_get_si(w));
        !           494:     else
        !           495:       {
        !           496:         /* if w is bigger than a long then the quotient must be zero, unless
        !           497:            l==LONG_MIN and w==-LONG_MIN in which case the quotient is -1 */
        !           498:         mpz_set_si (z, (mpz_cmpabs_ui (w, (l >= 0 ? l : -l)) == 0 ? -1 : 0));
        !           499:       }
        !           500:   }
        !           501:   static void eval(mpz_ptr z, mpz_srcptr w, double d)
        !           502:   {
        !           503:     mpz_t temp;
        !           504:     mpz_init_set_d(temp, d);
        !           505:     mpz_tdiv_q(z, w, temp);
        !           506:     mpz_clear(temp);
        !           507:   }
        !           508:   static void eval(mpz_ptr z, double d, mpz_srcptr w)
        !           509:   {
        !           510:     mpz_t temp;
        !           511:     mpz_init_set_d(temp, d);
        !           512:     mpz_tdiv_q(z, temp, w);
        !           513:     mpz_clear(temp);
        !           514:   }
        !           515:
        !           516:   static void eval(mpq_ptr q, mpq_srcptr r, mpq_srcptr s)
        !           517:   { mpq_div(q, r, s); }
        !           518:
        !           519:   static void eval(mpq_ptr q, mpq_srcptr r, mpir_ui l)
        !           520:   {
        !           521:     mpq_t temp;
        !           522:     mpq_init(temp);
        !           523:     mpq_set_ui(temp, l, 1);
        !           524:     mpq_div(q, r, temp);
        !           525:     mpq_clear(temp);
        !           526:   }
        !           527:   static void eval(mpq_ptr q, mpir_ui l, mpq_srcptr r)
        !           528:   {
        !           529:     mpq_t temp;
        !           530:     mpq_init(temp);
        !           531:     mpq_set_ui(temp, l, 1);
        !           532:     mpq_div(q, temp, r);
        !           533:     mpq_clear(temp);
        !           534:   }
        !           535:   static void eval(mpq_ptr q, mpq_srcptr r, mpir_si l)
        !           536:   {
        !           537:     mpq_t temp;
        !           538:     mpq_init(temp);
        !           539:     mpq_set_si(temp, l, 1);
        !           540:     mpq_div(q, r, temp);
        !           541:     mpq_clear(temp);
        !           542:   }
        !           543:   static void eval(mpq_ptr q, mpir_si l, mpq_srcptr r)
        !           544:   {
        !           545:     mpq_t temp;
        !           546:     mpq_init(temp);
        !           547:     mpq_set_si(temp, l, 1);
        !           548:     mpq_div(q, temp, r);
        !           549:     mpq_clear(temp);
        !           550:   }
        !           551:   static void eval(mpq_ptr q, mpq_srcptr r, double d)
        !           552:   {
        !           553:     mpq_t temp;
        !           554:     mpq_init(temp);
        !           555:     mpq_set_d(temp, d);
        !           556:     mpq_div(q, r, temp);
        !           557:     mpq_clear(temp);
        !           558:   }
        !           559:   static void eval(mpq_ptr q, double d, mpq_srcptr r)
        !           560:   {
        !           561:     mpq_t temp;
        !           562:     mpq_init(temp);
        !           563:     mpq_set_d(temp, d);
        !           564:     mpq_div(q, temp, r);
        !           565:     mpq_clear(temp);
        !           566:   }
        !           567:
        !           568:   static void eval(mpf_ptr f, mpf_srcptr g, mpf_srcptr h)
        !           569:   { mpf_div(f, g, h); }
        !           570:
        !           571:   static void eval(mpf_ptr f, mpf_srcptr g, mpir_ui l)
        !           572:   { mpf_div_ui(f, g, l); }
        !           573:   static void eval(mpf_ptr f, mpir_ui l, mpf_srcptr g)
        !           574:   { mpf_ui_div(f, l, g); }
        !           575:   static void eval(mpf_ptr f, mpf_srcptr g, mpir_si l)
        !           576:   {
        !           577:     if (l >= 0)
        !           578:       mpf_div_ui(f, g, l);
        !           579:     else
        !           580:       {
        !           581:        mpf_div_ui(f, g, -l);
        !           582:        mpf_neg(f, f);
        !           583:       }
        !           584:   }
        !           585:   static void eval(mpf_ptr f, mpir_si l, mpf_srcptr g)
        !           586:   {
        !           587:     if (l >= 0)
        !           588:       mpf_ui_div(f, l, g);
        !           589:     else
        !           590:       {
        !           591:        mpf_ui_div(f, -l, g);
        !           592:        mpf_neg(f, f);
        !           593:       }
        !           594:   }
        !           595:   static void eval(mpf_ptr f, mpf_srcptr g, double d)
        !           596:   {
        !           597:     mpf_t temp;
        !           598:     mpf_init2(temp, 8*sizeof(double));
        !           599:     mpf_set_d(temp, d);
        !           600:     mpf_div(f, g, temp);
        !           601:     mpf_clear(temp);
        !           602:   }
        !           603:   static void eval(mpf_ptr f, double d, mpf_srcptr g)
        !           604:   {
        !           605:     mpf_t temp;
        !           606:     mpf_init2(temp, 8*sizeof(double));
        !           607:     mpf_set_d(temp, d);
        !           608:     mpf_div(f, temp, g);
        !           609:     mpf_clear(temp);
        !           610:   }
        !           611: };
        !           612:
        !           613: struct __gmp_binary_modulus
        !           614: {
        !           615:   static void eval(mpz_ptr z, mpz_srcptr w, mpz_srcptr v)
        !           616:   { mpz_tdiv_r(z, w, v); }
        !           617:
        !           618:   static void eval(mpz_ptr z, mpz_srcptr w, mpir_ui l)
        !           619:   { mpz_tdiv_r_ui(z, w, l); }
        !           620:   static void eval(mpz_ptr z, mpir_ui l, mpz_srcptr w)
        !           621:   {
        !           622:     if (mpz_sgn(w) >= 0)
        !           623:       {
        !           624:        if (mpz_fits_ui_p(w))
        !           625:          mpz_set_ui(z, l % mpz_get_ui(w));
        !           626:        else
        !           627:          mpz_set_ui(z, l);
        !           628:       }
        !           629:     else
        !           630:       {
        !           631:        mpz_neg(z, w);
        !           632:        if (mpz_fits_ui_p(z))
        !           633:          mpz_set_ui(z, l % mpz_get_ui(z));
        !           634:        else
        !           635:          mpz_set_ui(z, l);
        !           636:       }
        !           637:   }
        !           638:   static void eval(mpz_ptr z, mpz_srcptr w, mpir_si l)
        !           639:   {
        !           640:     mpz_tdiv_r_ui (z, w, (l >= 0 ? l : -l));
        !           641:   }
        !           642:   static void eval(mpz_ptr z, mpir_si l, mpz_srcptr w)
        !           643:   {
        !           644:     if (mpz_fits_si_p(w))
        !           645:       mpz_set_si(z, l % mpz_get_si(w));
        !           646:     else
        !           647:       {
        !           648:         /* if w is bigger than a long then the remainder is l unchanged,
        !           649:            unless l==LONG_MIN and w==-LONG_MIN in which case it's 0 */
        !           650:         mpz_set_si (z, mpz_cmpabs_ui (w, (l >= 0 ? l : -l)) == 0 ? 0 : l);
        !           651:       }
        !           652:   }
        !           653:   static void eval(mpz_ptr z, mpz_srcptr w, double d)
        !           654:   {
        !           655:     mpz_t temp;
        !           656:     mpz_init_set_d(temp, d);
        !           657:     mpz_tdiv_r(z, w, temp);
        !           658:     mpz_clear(temp);
        !           659:   }
        !           660:   static void eval(mpz_ptr z, double d, mpz_srcptr w)
        !           661:   {
        !           662:     mpz_t temp;
        !           663:     mpz_init_set_d(temp, d);
        !           664:     mpz_tdiv_r(z, temp, w);
        !           665:     mpz_clear(temp);
        !           666:   }
        !           667: };
        !           668:
        !           669: // Max allocations for plain types when converted to mpz_t
        !           670: #define __GMP_DBL_LIMBS (2 + DBL_MAX_EXP / GMP_NUMB_BITS)
        !           671: #define __GMP_ULI_LIMBS (1 + (8 * sizeof (mpir_ui) - 1) / GMP_NUMB_BITS)
        !           672:
        !           673: #define __GMPXX_TMP_UI                                                 \
        !           674:   mpz_t temp;                                                              \
        !           675:   mp_limb_t limbs[__GMP_ULI_LIMBS];                            \
        !           676:   temp->_mp_d = limbs;                                                 \
        !           677:   temp->_mp_alloc = __GMP_ULI_LIMBS;                   \
        !           678:   mpz_set_ui (temp, l)
        !           679: #define __GMPXX_TMP_SI                                                 \
        !           680:   mpz_t temp;                                                              \
        !           681:   mp_limb_t limbs[__GMP_ULI_LIMBS];                            \
        !           682:   temp->_mp_d = limbs;                                                 \
        !           683:   temp->_mp_alloc = __GMP_ULI_LIMBS;                   \
        !           684:   mpz_set_si (temp, l)
        !           685: #define __GMPXX_TMP_D                                                  \
        !           686:   mpz_t temp;                                                              \
        !           687:   mp_limb_t limbs[__GMP_DBL_LIMBS];                            \
        !           688:   temp->_mp_d = limbs;                                                 \
        !           689:   temp->_mp_alloc = __GMP_DBL_LIMBS;                   \
        !           690:   mpz_set_d (temp, d)
        !           691:
        !           692: struct __gmp_binary_and
        !           693: {
        !           694:   static void eval(mpz_ptr z, mpz_srcptr w, mpz_srcptr v)
        !           695:   { mpz_and(z, w, v); }
        !           696:
        !           697:   static void eval(mpz_ptr z, mpz_srcptr w, mpir_ui l)
        !           698:   {  __GMPXX_TMP_UI;   mpz_and (z, w, temp);  }
        !           699:   static void eval(mpz_ptr z, mpir_ui l, mpz_srcptr w)
        !           700:   {  __GMPXX_TMP_UI;   mpz_and (z, w, temp);  }
        !           701:   static void eval(mpz_ptr z, mpz_srcptr w, mpir_si l)
        !           702:   {  __GMPXX_TMP_SI;   mpz_and (z, w, temp);  }
        !           703:   static void eval(mpz_ptr z, mpir_si l, mpz_srcptr w)
        !           704:   {  __GMPXX_TMP_SI;   mpz_and (z, w, temp);  }
        !           705:   static void eval(mpz_ptr z, mpz_srcptr w, double d)
        !           706:   {  __GMPXX_TMP_D;    mpz_and (z, w, temp); }
        !           707:   static void eval(mpz_ptr z, double d, mpz_srcptr w)
        !           708:   {  __GMPXX_TMP_D;    mpz_and (z, w, temp); }
        !           709: };
        !           710:
        !           711: struct __gmp_binary_ior
        !           712: {
        !           713:   static void eval(mpz_ptr z, mpz_srcptr w, mpz_srcptr v)
        !           714:   { mpz_ior(z, w, v); }
        !           715:   static void eval(mpz_ptr z, mpz_srcptr w, mpir_ui l)
        !           716:   {  __GMPXX_TMP_UI;   mpz_ior (z, w, temp);  }
        !           717:   static void eval(mpz_ptr z, mpir_ui l, mpz_srcptr w)
        !           718:   {  __GMPXX_TMP_UI;   mpz_ior (z, w, temp);  }
        !           719:   static void eval(mpz_ptr z, mpz_srcptr w, mpir_si l)
        !           720:   {  __GMPXX_TMP_SI;   mpz_ior (z, w, temp);  }
        !           721:   static void eval(mpz_ptr z, mpir_si l, mpz_srcptr w)
        !           722:   {  __GMPXX_TMP_SI;   mpz_ior (z, w, temp);  }
        !           723:   static void eval(mpz_ptr z, mpz_srcptr w, double d)
        !           724:   {  __GMPXX_TMP_D;    mpz_ior (z, w, temp); }
        !           725:   static void eval(mpz_ptr z, double d, mpz_srcptr w)
        !           726:   {  __GMPXX_TMP_D;    mpz_ior (z, w, temp); }
        !           727: };
        !           728:
        !           729: struct __gmp_binary_xor
        !           730: {
        !           731:   static void eval(mpz_ptr z, mpz_srcptr w, mpz_srcptr v)
        !           732:   { mpz_xor(z, w, v); }
        !           733:   static void eval(mpz_ptr z, mpz_srcptr w, mpir_ui l)
        !           734:   {  __GMPXX_TMP_UI;   mpz_xor (z, w, temp);  }
        !           735:   static void eval(mpz_ptr z, mpir_ui l, mpz_srcptr w)
        !           736:   {  __GMPXX_TMP_UI;   mpz_xor (z, w, temp);  }
        !           737:   static void eval(mpz_ptr z, mpz_srcptr w, mpir_si l)
        !           738:   {  __GMPXX_TMP_SI;   mpz_xor (z, w, temp);  }
        !           739:   static void eval(mpz_ptr z, mpir_si l, mpz_srcptr w)
        !           740:   {  __GMPXX_TMP_SI;   mpz_xor (z, w, temp);  }
        !           741:   static void eval(mpz_ptr z, mpz_srcptr w, double d)
        !           742:   {  __GMPXX_TMP_D;    mpz_xor (z, w, temp); }
        !           743:   static void eval(mpz_ptr z, double d, mpz_srcptr w)
        !           744:   {  __GMPXX_TMP_D;    mpz_xor (z, w, temp); }
        !           745: };
        !           746:
        !           747: struct __gmp_binary_lshift
        !           748: {
        !           749:   static void eval(mpz_ptr z, mpz_srcptr w, mpir_ui l)
        !           750:   { mpz_mul_2exp(z, w, l); }
        !           751:   static void eval(mpq_ptr q, mpq_srcptr r, mpir_ui l)
        !           752:   { mpq_mul_2exp(q, r, l); }
        !           753:   static void eval(mpf_ptr f, mpf_srcptr g, mpir_ui l)
        !           754:   { mpf_mul_2exp(f, g, l); }
        !           755: };
        !           756:
        !           757: struct __gmp_binary_rshift
        !           758: {
        !           759:   static void eval(mpz_ptr z, mpz_srcptr w, mpir_ui l)
        !           760:   { mpz_fdiv_q_2exp(z, w, l); }
        !           761:   static void eval(mpq_ptr q, mpq_srcptr r, mpir_ui l)
        !           762:   { mpq_div_2exp(q, r, l); }
        !           763:   static void eval(mpf_ptr f, mpf_srcptr g, mpir_ui l)
        !           764:   { mpf_div_2exp(f, g, l); }
        !           765: };
        !           766:
        !           767: struct __gmp_binary_equal
        !           768: {
        !           769:   static bool eval(mpz_srcptr z, mpz_srcptr w) { return mpz_cmp(z, w) == 0; }
        !           770:
        !           771:   static bool eval(mpz_srcptr z, mpir_ui l)
        !           772:   { return mpz_cmp_ui(z, l) == 0; }
        !           773:   static bool eval(mpir_ui l, mpz_srcptr z)
        !           774:   { return mpz_cmp_ui(z, l) == 0; }
        !           775:   static bool eval(mpz_srcptr z, mpir_si l)
        !           776:   { return mpz_cmp_si(z, l) == 0; }
        !           777:   static bool eval(mpir_si l, mpz_srcptr z)
        !           778:   { return mpz_cmp_si(z, l) == 0; }
        !           779:   static bool eval(mpz_srcptr z, double d)
        !           780:   { return mpz_cmp_d(z, d) == 0; }
        !           781:   static bool eval(double d, mpz_srcptr z)
        !           782:   { return mpz_cmp_d(z, d) == 0; }
        !           783:
        !           784:   static bool eval(mpq_srcptr q, mpq_srcptr r)
        !           785:   { return mpq_equal(q, r) != 0; }
        !           786:
        !           787:   static bool eval(mpq_srcptr q, mpir_ui l)
        !           788:   { return mpq_cmp_ui(q, l, 1) == 0; }
        !           789:   static bool eval(mpir_ui l, mpq_srcptr q)
        !           790:   { return mpq_cmp_ui(q, l, 1) == 0; }
        !           791:   static bool eval(mpq_srcptr q, mpir_si l)
        !           792:   { return mpq_cmp_si(q, l, 1) == 0; }
        !           793:   static bool eval(mpir_si l, mpq_srcptr q)
        !           794:   { return mpq_cmp_si(q, l, 1) == 0; }
        !           795:   static bool eval(mpq_srcptr q, double d)
        !           796:   {
        !           797:     bool b;
        !           798:     mpq_t temp;
        !           799:     mpq_init(temp);
        !           800:     mpq_set_d(temp, d);
        !           801:     b = (mpq_equal(q, temp) != 0);
        !           802:     mpq_clear(temp);
        !           803:     return b;
        !           804:   }
        !           805:   static bool eval(double d, mpq_srcptr q)
        !           806:   {
        !           807:     bool b;
        !           808:     mpq_t temp;
        !           809:     mpq_init(temp);
        !           810:     mpq_set_d(temp, d);
        !           811:     b = (mpq_equal(temp, q) != 0);
        !           812:     mpq_clear(temp);
        !           813:     return b;
        !           814:   }
        !           815:
        !           816:   static bool eval(mpf_srcptr f, mpf_srcptr g) { return mpf_cmp(f, g) == 0; }
        !           817:
        !           818:   static bool eval(mpf_srcptr f, mpir_ui l)
        !           819:   { return mpf_cmp_ui(f, l) == 0; }
        !           820:   static bool eval(mpir_ui l, mpf_srcptr f)
        !           821:   { return mpf_cmp_ui(f, l) == 0; }
        !           822:   static bool eval(mpf_srcptr f, mpir_si l)
        !           823:   { return mpf_cmp_si(f, l) == 0; }
        !           824:   static bool eval(mpir_si l, mpf_srcptr f)
        !           825:   { return mpf_cmp_si(f, l) == 0; }
        !           826:   static bool eval(mpf_srcptr f, double d)
        !           827:   { return mpf_cmp_d(f, d) == 0; }
        !           828:   static bool eval(double d, mpf_srcptr f)
        !           829:   { return mpf_cmp_d(f, d) == 0; }
        !           830: };
        !           831:
        !           832: struct __gmp_binary_not_equal
        !           833: {
        !           834:   static bool eval(mpz_srcptr z, mpz_srcptr w) { return mpz_cmp(z, w) != 0; }
        !           835:
        !           836:   static bool eval(mpz_srcptr z, mpir_ui l)
        !           837:   { return mpz_cmp_ui(z, l) != 0; }
        !           838:   static bool eval(mpir_ui l, mpz_srcptr z)
        !           839:   { return mpz_cmp_ui(z, l) != 0; }
        !           840:   static bool eval(mpz_srcptr z, mpir_si l)
        !           841:   { return mpz_cmp_si(z, l) != 0; }
        !           842:   static bool eval(mpir_si l, mpz_srcptr z)
        !           843:   { return mpz_cmp_si(z, l) != 0; }
        !           844:   static bool eval(mpz_srcptr z, double d)
        !           845:   { return mpz_cmp_d(z, d) != 0; }
        !           846:   static bool eval(double d, mpz_srcptr z)
        !           847:   { return mpz_cmp_d(z, d) != 0; }
        !           848:
        !           849:   static bool eval(mpq_srcptr q, mpq_srcptr r)
        !           850:   { return mpq_equal(q, r) == 0; }
        !           851:
        !           852:   static bool eval(mpq_srcptr q, mpir_ui l)
        !           853:   { return mpq_cmp_ui(q, l, 1) != 0; }
        !           854:   static bool eval(mpir_ui l, mpq_srcptr q)
        !           855:   { return mpq_cmp_ui(q, l, 1) != 0; }
        !           856:   static bool eval(mpq_srcptr q, mpir_si l)
        !           857:   { return mpq_cmp_si(q, l, 1) != 0; }
        !           858:   static bool eval(mpir_si l, mpq_srcptr q)
        !           859:   { return mpq_cmp_si(q, l, 1) != 0; }
        !           860:   static bool eval(mpq_srcptr q, double d)
        !           861:   {
        !           862:     bool b;
        !           863:     mpq_t temp;
        !           864:     mpq_init(temp);
        !           865:     mpq_set_d(temp, d);
        !           866:     b = (mpq_equal(q, temp) == 0);
        !           867:     mpq_clear(temp);
        !           868:     return b;
        !           869:   }
        !           870:   static bool eval(double d, mpq_srcptr q)
        !           871:   {
        !           872:     bool b;
        !           873:     mpq_t temp;
        !           874:     mpq_init(temp);
        !           875:     mpq_set_d(temp, d);
        !           876:     b = (mpq_equal(temp, q) == 0);
        !           877:     mpq_clear(temp);
        !           878:     return b;
        !           879:   }
        !           880:
        !           881:   static bool eval(mpf_srcptr f, mpf_srcptr g) { return mpf_cmp(f, g) != 0; }
        !           882:
        !           883:   static bool eval(mpf_srcptr f, mpir_ui l)
        !           884:   { return mpf_cmp_ui(f, l) != 0; }
        !           885:   static bool eval(mpir_ui l, mpf_srcptr f)
        !           886:   { return mpf_cmp_ui(f, l) != 0; }
        !           887:   static bool eval(mpf_srcptr f, mpir_si l)
        !           888:   { return mpf_cmp_si(f, l) != 0; }
        !           889:   static bool eval(mpir_si l, mpf_srcptr f)
        !           890:   { return mpf_cmp_si(f, l) != 0; }
        !           891:   static bool eval(mpf_srcptr f, double d)
        !           892:   { return mpf_cmp_d(f, d) != 0; }
        !           893:   static bool eval(double d, mpf_srcptr f)
        !           894:   { return mpf_cmp_d(f, d) != 0; }
        !           895: };
        !           896:
        !           897: struct __gmp_binary_less
        !           898: {
        !           899:   static bool eval(mpz_srcptr z, mpz_srcptr w) { return mpz_cmp(z, w) < 0; }
        !           900:
        !           901:   static bool eval(mpz_srcptr z, mpir_ui l)
        !           902:   { return mpz_cmp_ui(z, l) < 0; }
        !           903:   static bool eval(mpir_ui l, mpz_srcptr z)
        !           904:   { return mpz_cmp_ui(z, l) > 0; }
        !           905:   static bool eval(mpz_srcptr z, mpir_si l)
        !           906:   { return mpz_cmp_si(z, l) < 0; }
        !           907:   static bool eval(mpir_si l, mpz_srcptr z)
        !           908:   { return mpz_cmp_si(z, l) > 0; }
        !           909:   static bool eval(mpz_srcptr z, double d)
        !           910:   { return mpz_cmp_d(z, d) < 0; }
        !           911:   static bool eval(double d, mpz_srcptr z)
        !           912:   { return mpz_cmp_d(z, d) > 0; }
        !           913:
        !           914:   static bool eval(mpq_srcptr q, mpq_srcptr r) { return mpq_cmp(q, r) < 0; }
        !           915:
        !           916:   static bool eval(mpq_srcptr q, mpir_ui l)
        !           917:   { return mpq_cmp_ui(q, l, 1) < 0; }
        !           918:   static bool eval(mpir_ui l, mpq_srcptr q)
        !           919:   { return mpq_cmp_ui(q, l, 1) > 0; }
        !           920:   static bool eval(mpq_srcptr q, mpir_si l)
        !           921:   { return mpq_cmp_si(q, l, 1) < 0; }
        !           922:   static bool eval(mpir_si l, mpq_srcptr q)
        !           923:   { return mpq_cmp_si(q, l, 1) > 0; }
        !           924:   static bool eval(mpq_srcptr q, double d)
        !           925:   {
        !           926:     bool b;
        !           927:     mpq_t temp;
        !           928:     mpq_init(temp);
        !           929:     mpq_set_d(temp, d);
        !           930:     b = (mpq_cmp(q, temp) < 0);
        !           931:     mpq_clear(temp);
        !           932:     return b;
        !           933:   }
        !           934:   static bool eval(double d, mpq_srcptr q)
        !           935:   {
        !           936:     bool b;
        !           937:     mpq_t temp;
        !           938:     mpq_init(temp);
        !           939:     mpq_set_d(temp, d);
        !           940:     b = (mpq_cmp(temp, q) < 0);
        !           941:     mpq_clear(temp);
        !           942:     return b;
        !           943:   }
        !           944:
        !           945:   static bool eval(mpf_srcptr f, mpf_srcptr g) { return mpf_cmp(f, g) < 0; }
        !           946:
        !           947:   static bool eval(mpf_srcptr f, mpir_ui l)
        !           948:   { return mpf_cmp_ui(f, l) < 0; }
        !           949:   static bool eval(mpir_ui l, mpf_srcptr f)
        !           950:   { return mpf_cmp_ui(f, l) > 0; }
        !           951:   static bool eval(mpf_srcptr f, mpir_si l)
        !           952:   { return mpf_cmp_si(f, l) < 0; }
        !           953:   static bool eval(mpir_si l, mpf_srcptr f)
        !           954:   { return mpf_cmp_si(f, l) > 0; }
        !           955:   static bool eval(mpf_srcptr f, double d)
        !           956:   { return mpf_cmp_d(f, d) < 0; }
        !           957:   static bool eval(double d, mpf_srcptr f)
        !           958:   { return mpf_cmp_d(f, d) > 0; }
        !           959: };
        !           960:
        !           961: struct __gmp_binary_less_equal
        !           962: {
        !           963:   static bool eval(mpz_srcptr z, mpz_srcptr w) { return mpz_cmp(z, w) <= 0; }
        !           964:
        !           965:   static bool eval(mpz_srcptr z, mpir_ui l)
        !           966:   { return mpz_cmp_ui(z, l) <= 0; }
        !           967:   static bool eval(mpir_ui l, mpz_srcptr z)
        !           968:   { return mpz_cmp_ui(z, l) >= 0; }
        !           969:   static bool eval(mpz_srcptr z, mpir_si l)
        !           970:   { return mpz_cmp_si(z, l) <= 0; }
        !           971:   static bool eval(mpir_si l, mpz_srcptr z)
        !           972:   { return mpz_cmp_si(z, l) >= 0; }
        !           973:   static bool eval(mpz_srcptr z, double d)
        !           974:   { return mpz_cmp_d(z, d) <= 0; }
        !           975:   static bool eval(double d, mpz_srcptr z)
        !           976:   { return mpz_cmp_d(z, d) >= 0; }
        !           977:
        !           978:   static bool eval(mpq_srcptr q, mpq_srcptr r) { return mpq_cmp(q, r) <= 0; }
        !           979:
        !           980:   static bool eval(mpq_srcptr q, mpir_ui l)
        !           981:   { return mpq_cmp_ui(q, l, 1) <= 0; }
        !           982:   static bool eval(mpir_ui l, mpq_srcptr q)
        !           983:   { return mpq_cmp_ui(q, l, 1) >= 0; }
        !           984:   static bool eval(mpq_srcptr q, mpir_si l)
        !           985:   { return mpq_cmp_si(q, l, 1) <= 0; }
        !           986:   static bool eval(mpir_si l, mpq_srcptr q)
        !           987:   { return mpq_cmp_si(q, l, 1) >= 0; }
        !           988:   static bool eval(mpq_srcptr q, double d)
        !           989:   {
        !           990:     bool b;
        !           991:     mpq_t temp;
        !           992:     mpq_init(temp);
        !           993:     mpq_set_d(temp, d);
        !           994:     b = (mpq_cmp(q, temp) <= 0);
        !           995:     mpq_clear(temp);
        !           996:     return b;
        !           997:   }
        !           998:   static bool eval(double d, mpq_srcptr q)
        !           999:   {
        !          1000:     bool b;
        !          1001:     mpq_t temp;
        !          1002:     mpq_init(temp);
        !          1003:     mpq_set_d(temp, d);
        !          1004:     b = (mpq_cmp(temp, q) <= 0);
        !          1005:     mpq_clear(temp);
        !          1006:     return b;
        !          1007:   }
        !          1008:
        !          1009:   static bool eval(mpf_srcptr f, mpf_srcptr g) { return mpf_cmp(f, g) <= 0; }
        !          1010:
        !          1011:   static bool eval(mpf_srcptr f, mpir_ui l)
        !          1012:   { return mpf_cmp_ui(f, l) <= 0; }
        !          1013:   static bool eval(mpir_ui l, mpf_srcptr f)
        !          1014:   { return mpf_cmp_ui(f, l) >= 0; }
        !          1015:   static bool eval(mpf_srcptr f, mpir_si l)
        !          1016:   { return mpf_cmp_si(f, l) <= 0; }
        !          1017:   static bool eval(mpir_si l, mpf_srcptr f)
        !          1018:   { return mpf_cmp_si(f, l) >= 0; }
        !          1019:   static bool eval(mpf_srcptr f, double d)
        !          1020:   { return mpf_cmp_d(f, d) <= 0; }
        !          1021:   static bool eval(double d, mpf_srcptr f)
        !          1022:   { return mpf_cmp_d(f, d) >= 0; }
        !          1023: };
        !          1024:
        !          1025: struct __gmp_binary_greater
        !          1026: {
        !          1027:   static bool eval(mpz_srcptr z, mpz_srcptr w) { return mpz_cmp(z, w) > 0; }
        !          1028:
        !          1029:   static bool eval(mpz_srcptr z, mpir_ui l)
        !          1030:   { return mpz_cmp_ui(z, l) > 0; }
        !          1031:   static bool eval(mpir_ui l, mpz_srcptr z)
        !          1032:   { return mpz_cmp_ui(z, l) < 0; }
        !          1033:   static bool eval(mpz_srcptr z, mpir_si l)
        !          1034:   { return mpz_cmp_si(z, l) > 0; }
        !          1035:   static bool eval(mpir_si l, mpz_srcptr z)
        !          1036:   { return mpz_cmp_si(z, l) < 0; }
        !          1037:   static bool eval(mpz_srcptr z, double d)
        !          1038:   { return mpz_cmp_d(z, d) > 0; }
        !          1039:   static bool eval(double d, mpz_srcptr z)
        !          1040:   { return mpz_cmp_d(z, d) < 0; }
        !          1041:
        !          1042:   static bool eval(mpq_srcptr q, mpq_srcptr r) { return mpq_cmp(q, r) > 0; }
        !          1043:
        !          1044:   static bool eval(mpq_srcptr q, mpir_ui l)
        !          1045:   { return mpq_cmp_ui(q, l, 1) > 0; }
        !          1046:   static bool eval(mpir_ui l, mpq_srcptr q)
        !          1047:   { return mpq_cmp_ui(q, l, 1) < 0; }
        !          1048:   static bool eval(mpq_srcptr q, mpir_si l)
        !          1049:   { return mpq_cmp_si(q, l, 1) > 0; }
        !          1050:   static bool eval(mpir_si l, mpq_srcptr q)
        !          1051:   { return mpq_cmp_si(q, l, 1) < 0; }
        !          1052:   static bool eval(mpq_srcptr q, double d)
        !          1053:   {
        !          1054:     bool b;
        !          1055:     mpq_t temp;
        !          1056:     mpq_init(temp);
        !          1057:     mpq_set_d(temp, d);
        !          1058:     b = (mpq_cmp(q, temp) > 0);
        !          1059:     mpq_clear(temp);
        !          1060:     return b;
        !          1061:   }
        !          1062:   static bool eval(double d, mpq_srcptr q)
        !          1063:   {
        !          1064:     bool b;
        !          1065:     mpq_t temp;
        !          1066:     mpq_init(temp);
        !          1067:     mpq_set_d(temp, d);
        !          1068:     b = (mpq_cmp(temp, q) > 0);
        !          1069:     mpq_clear(temp);
        !          1070:     return b;
        !          1071:   }
        !          1072:
        !          1073:   static bool eval(mpf_srcptr f, mpf_srcptr g) { return mpf_cmp(f, g) > 0; }
        !          1074:
        !          1075:   static bool eval(mpf_srcptr f, mpir_ui l)
        !          1076:   { return mpf_cmp_ui(f, l) > 0; }
        !          1077:   static bool eval(mpir_ui l, mpf_srcptr f)
        !          1078:   { return mpf_cmp_ui(f, l) < 0; }
        !          1079:   static bool eval(mpf_srcptr f, mpir_si l)
        !          1080:   { return mpf_cmp_si(f, l) > 0; }
        !          1081:   static bool eval(mpir_si l, mpf_srcptr f)
        !          1082:   { return mpf_cmp_si(f, l) < 0; }
        !          1083:   static bool eval(mpf_srcptr f, double d)
        !          1084:   { return mpf_cmp_d(f, d) > 0; }
        !          1085:   static bool eval(double d, mpf_srcptr f)
        !          1086:   { return mpf_cmp_d(f, d) < 0; }
        !          1087: };
        !          1088:
        !          1089: struct __gmp_binary_greater_equal
        !          1090: {
        !          1091:   static bool eval(mpz_srcptr z, mpz_srcptr w) { return mpz_cmp(z, w) >= 0; }
        !          1092:
        !          1093:   static bool eval(mpz_srcptr z, mpir_ui l)
        !          1094:   { return mpz_cmp_ui(z, l) >= 0; }
        !          1095:   static bool eval(mpir_ui l, mpz_srcptr z)
        !          1096:   { return mpz_cmp_ui(z, l) <= 0; }
        !          1097:   static bool eval(mpz_srcptr z, mpir_si l)
        !          1098:   { return mpz_cmp_si(z, l) >= 0; }
        !          1099:   static bool eval(mpir_si l, mpz_srcptr z)
        !          1100:   { return mpz_cmp_si(z, l) <= 0; }
        !          1101:   static bool eval(mpz_srcptr z, double d)
        !          1102:   { return mpz_cmp_d(z, d) >= 0; }
        !          1103:   static bool eval(double d, mpz_srcptr z)
        !          1104:   { return mpz_cmp_d(z, d) <= 0; }
        !          1105:
        !          1106:   static bool eval(mpq_srcptr q, mpq_srcptr r) { return mpq_cmp(q, r) >= 0; }
        !          1107:
        !          1108:   static bool eval(mpq_srcptr q, mpir_ui l)
        !          1109:   { return mpq_cmp_ui(q, l, 1) >= 0; }
        !          1110:   static bool eval(mpir_ui l, mpq_srcptr q)
        !          1111:   { return mpq_cmp_ui(q, l, 1) <= 0; }
        !          1112:   static bool eval(mpq_srcptr q, mpir_si l)
        !          1113:   { return mpq_cmp_si(q, l, 1) >= 0; }
        !          1114:   static bool eval(mpir_si l, mpq_srcptr q)
        !          1115:   { return mpq_cmp_si(q, l, 1) <= 0; }
        !          1116:   static bool eval(mpq_srcptr q, double d)
        !          1117:   {
        !          1118:     bool b;
        !          1119:     mpq_t temp;
        !          1120:     mpq_init(temp);
        !          1121:     mpq_set_d(temp, d);
        !          1122:     b = (mpq_cmp(q, temp) >= 0);
        !          1123:     mpq_clear(temp);
        !          1124:     return b;
        !          1125:   }
        !          1126:   static bool eval(double d, mpq_srcptr q)
        !          1127:   {
        !          1128:     bool b;
        !          1129:     mpq_t temp;
        !          1130:     mpq_init(temp);
        !          1131:     mpq_set_d(temp, d);
        !          1132:     b = (mpq_cmp(temp, q) >= 0);
        !          1133:     mpq_clear(temp);
        !          1134:     return b;
        !          1135:   }
        !          1136:
        !          1137:   static bool eval(mpf_srcptr f, mpf_srcptr g) { return mpf_cmp(f, g) >= 0; }
        !          1138:
        !          1139:   static bool eval(mpf_srcptr f, mpir_ui l)
        !          1140:   { return mpf_cmp_ui(f, l) >= 0; }
        !          1141:   static bool eval(mpir_ui l, mpf_srcptr f)
        !          1142:   { return mpf_cmp_ui(f, l) <= 0; }
        !          1143:   static bool eval(mpf_srcptr f, mpir_si l)
        !          1144:   { return mpf_cmp_si(f, l) >= 0; }
        !          1145:   static bool eval(mpir_si l, mpf_srcptr f)
        !          1146:   { return mpf_cmp_si(f, l) <= 0; }
        !          1147:   static bool eval(mpf_srcptr f, double d)
        !          1148:   { return mpf_cmp_d(f, d) >= 0; }
        !          1149:   static bool eval(double d, mpf_srcptr f)
        !          1150:   { return mpf_cmp_d(f, d) <= 0; }
        !          1151: };
        !          1152:
        !          1153: struct __gmp_unary_increment
        !          1154: {
        !          1155:   static void eval(mpz_ptr z) { mpz_add_ui(z, z, 1); }
        !          1156:   static void eval(mpq_ptr q)
        !          1157:   { mpz_add(mpq_numref(q), mpq_numref(q), mpq_denref(q)); }
        !          1158:   static void eval(mpf_ptr f) { mpf_add_ui(f, f, 1); }
        !          1159: };
        !          1160:
        !          1161: struct __gmp_unary_decrement
        !          1162: {
        !          1163:   static void eval(mpz_ptr z) { mpz_sub_ui(z, z, 1); }
        !          1164:   static void eval(mpq_ptr q)
        !          1165:   { mpz_sub(mpq_numref(q), mpq_numref(q), mpq_denref(q)); }
        !          1166:   static void eval(mpf_ptr f) { mpf_sub_ui(f, f, 1); }
        !          1167: };
        !          1168:
        !          1169: struct __gmp_abs_function
        !          1170: {
        !          1171:   static void eval(mpz_ptr z, mpz_srcptr w) { mpz_abs(z, w); }
        !          1172:   static void eval(mpq_ptr q, mpq_srcptr r) { mpq_abs(q, r); }
        !          1173:   static void eval(mpf_ptr f, mpf_srcptr g) { mpf_abs(f, g); }
        !          1174: };
        !          1175:
        !          1176: struct __gmp_trunc_function
        !          1177: {
        !          1178:   static void eval(mpf_ptr f, mpf_srcptr g) { mpf_trunc(f, g); }
        !          1179: };
        !          1180:
        !          1181: struct __gmp_floor_function
        !          1182: {
        !          1183:   static void eval(mpf_ptr f, mpf_srcptr g) { mpf_floor(f, g); }
        !          1184: };
        !          1185:
        !          1186: struct __gmp_ceil_function
        !          1187: {
        !          1188:   static void eval(mpf_ptr f, mpf_srcptr g) { mpf_ceil(f, g); }
        !          1189: };
        !          1190:
        !          1191: struct __gmp_sqrt_function
        !          1192: {
        !          1193:   static void eval(mpz_ptr z, mpz_srcptr w) { mpz_sqrt(z, w); }
        !          1194:   static void eval(mpf_ptr f, mpf_srcptr g) { mpf_sqrt(f, g); }
        !          1195: };
        !          1196:
        !          1197: struct __gmp_hypot_function
        !          1198: {
        !          1199:   static void eval(mpf_ptr f, mpf_srcptr g, mpf_srcptr h)
        !          1200:   {
        !          1201:     mpf_t temp;
        !          1202:     mpf_init2(temp, mpf_get_prec(f));
        !          1203:     mpf_mul(temp, g, g);
        !          1204:     mpf_mul(f, h, h);
        !          1205:     mpf_add(f, f, temp);
        !          1206:     mpf_sqrt(f, f);
        !          1207:     mpf_clear(temp);
        !          1208:   }
        !          1209:
        !          1210:   static void eval(mpf_ptr f, mpf_srcptr g, mpir_ui l)
        !          1211:   {
        !          1212:     mpf_t temp;
        !          1213:     mpf_init2(temp, mpf_get_prec(f));
        !          1214:     mpf_mul(temp, g, g);
        !          1215:     mpf_set_ui(f, l);
        !          1216:     mpf_mul(f, f, f);
        !          1217:     mpf_add(f, f, temp);
        !          1218:     mpf_sqrt(f, f);
        !          1219:     mpf_clear(temp);
        !          1220:   }
        !          1221:   static void eval(mpf_ptr f, mpir_ui l, mpf_srcptr g)
        !          1222:   {
        !          1223:     mpf_t temp;
        !          1224:     mpf_init2(temp, mpf_get_prec(f));
        !          1225:     mpf_mul(temp, g, g);
        !          1226:     mpf_set_ui(f, l);
        !          1227:     mpf_mul(f, f, f);
        !          1228:     mpf_add(f, f, temp);
        !          1229:     mpf_sqrt(f, f);
        !          1230:     mpf_clear(temp);
        !          1231:   }
        !          1232:   static void eval(mpf_ptr f, mpf_srcptr g, mpir_si l)
        !          1233:   {
        !          1234:     mpf_t temp;
        !          1235:     mpf_init2(temp, mpf_get_prec(f));
        !          1236:     mpf_mul(temp, g, g);
        !          1237:     mpf_set_si(f, l);
        !          1238:     mpf_mul(f, f, f);
        !          1239:     mpf_add(f, f, temp);
        !          1240:     mpf_sqrt(f, f);
        !          1241:     mpf_clear(temp);
        !          1242:   }
        !          1243:   static void eval(mpf_ptr f, mpir_si l, mpf_srcptr g)
        !          1244:   {
        !          1245:     mpf_t temp;
        !          1246:     mpf_init2(temp, mpf_get_prec(f));
        !          1247:     mpf_mul(temp, g, g);
        !          1248:     mpf_set_si(f, l);
        !          1249:     mpf_mul(f, f, f);
        !          1250:     mpf_add(f, f, temp);
        !          1251:     mpf_sqrt(f, f);
        !          1252:     mpf_clear(temp);
        !          1253:   }
        !          1254:   static void eval(mpf_ptr f, mpf_srcptr g, double d)
        !          1255:   {
        !          1256:     mpf_t temp;
        !          1257:     mpf_init2(temp, mpf_get_prec(f));
        !          1258:     mpf_mul(temp, g, g);
        !          1259:     mpf_set_d(f, d);
        !          1260:     mpf_mul(f, f, f);
        !          1261:     mpf_add(f, f, temp);
        !          1262:     mpf_sqrt(f, f);
        !          1263:     mpf_clear(temp);
        !          1264:   }
        !          1265:   static void eval(mpf_ptr f, double d, mpf_srcptr g)
        !          1266:   {
        !          1267:     mpf_t temp;
        !          1268:     mpf_init2(temp, mpf_get_prec(f));
        !          1269:     mpf_mul(temp, g, g);
        !          1270:     mpf_set_d(f, d);
        !          1271:     mpf_mul(f, f, f);
        !          1272:     mpf_add(f, f, temp);
        !          1273:     mpf_sqrt(f, f);
        !          1274:     mpf_clear(temp);
        !          1275:   }
        !          1276: };
        !          1277:
        !          1278: struct __gmp_sgn_function
        !          1279: {
        !          1280:   static int eval(mpz_srcptr z) { return mpz_sgn(z); }
        !          1281:   static int eval(mpq_srcptr q) { return mpq_sgn(q); }
        !          1282:   static int eval(mpf_srcptr f) { return mpf_sgn(f); }
        !          1283: };
        !          1284:
        !          1285: struct __gmp_cmp_function
        !          1286: {
        !          1287:   static int eval(mpz_srcptr z, mpz_srcptr w) { return mpz_cmp(z, w); }
        !          1288:
        !          1289:   static int eval(mpz_srcptr z, mpir_ui l)
        !          1290:   { return mpz_cmp_ui(z, l); }
        !          1291:   static int eval(mpir_ui l, mpz_srcptr z)
        !          1292:   { return -mpz_cmp_ui(z, l); }
        !          1293:   static int eval(mpz_srcptr z, mpir_si l)
        !          1294:   { return mpz_cmp_si(z, l); }
        !          1295:   static int eval(mpir_si l, mpz_srcptr z)
        !          1296:   { return -mpz_cmp_si(z, l); }
        !          1297:   static int eval(mpz_srcptr z, double d)
        !          1298:   { return mpz_cmp_d(z, d); }
        !          1299:   static int eval(double d, mpz_srcptr z)
        !          1300:   { return -mpz_cmp_d(z, d); }
        !          1301:
        !          1302:   static int eval(mpq_srcptr q, mpq_srcptr r) { return mpq_cmp(q, r); }
        !          1303:
        !          1304:   static int eval(mpq_srcptr q, mpir_ui l)
        !          1305:   { return mpq_cmp_ui(q, l, 1); }
        !          1306:   static int eval(mpir_ui l, mpq_srcptr q)
        !          1307:   { return -mpq_cmp_ui(q, l, 1); }
        !          1308:   static int eval(mpq_srcptr q, mpir_si l)
        !          1309:   { return mpq_cmp_si(q, l, 1); }
        !          1310:   static int eval(mpir_si l, mpq_srcptr q)
        !          1311:   { return -mpq_cmp_si(q, l, 1); }
        !          1312:   static int eval(mpq_srcptr q, double d)
        !          1313:   {
        !          1314:     int i;
        !          1315:     mpq_t temp;
        !          1316:     mpq_init(temp);
        !          1317:     mpq_set_d(temp, d);
        !          1318:     i = mpq_cmp(q, temp);
        !          1319:     mpq_clear(temp);
        !          1320:     return i;
        !          1321:   }
        !          1322:   static int eval(double d, mpq_srcptr q)
        !          1323:   {
        !          1324:     int i;
        !          1325:     mpq_t temp;
        !          1326:     mpq_init(temp);
        !          1327:     mpq_set_d(temp, d);
        !          1328:     i = mpq_cmp(temp, q);
        !          1329:     mpq_clear(temp);
        !          1330:     return i;
        !          1331:   }
        !          1332:
        !          1333:   static int eval(mpf_srcptr f, mpf_srcptr g) { return mpf_cmp(f, g); }
        !          1334:
        !          1335:   static int eval(mpf_srcptr f, mpir_ui l)
        !          1336:   { return mpf_cmp_ui(f, l); }
        !          1337:   static int eval(mpir_ui l, mpf_srcptr f)
        !          1338:   { return -mpf_cmp_ui(f, l); }
        !          1339:   static int eval(mpf_srcptr f, mpir_si l)
        !          1340:   { return mpf_cmp_si(f, l); }
        !          1341:   static int eval(mpir_si l, mpf_srcptr f)
        !          1342:   { return -mpf_cmp_si(f, l); }
        !          1343:   static int eval(mpf_srcptr f, double d)
        !          1344:   { return mpf_cmp_d(f, d); }
        !          1345:   static int eval(double d, mpf_srcptr f)
        !          1346:   { return -mpf_cmp_d(f, d); }
        !          1347: };
        !          1348:
        !          1349: struct __gmp_rand_function
        !          1350: {
        !          1351:   static void eval(mpz_ptr z, gmp_randstate_t s, mpir_ui l)
        !          1352:   { mpz_urandomb(z, s, l); }
        !          1353:   static void eval(mpz_ptr z, gmp_randstate_t s, mpz_srcptr w)
        !          1354:   { mpz_urandomm(z, s, w); }
        !          1355:   static void eval(mpf_ptr f, gmp_randstate_t s, mp_bitcnt_t prec)
        !          1356:   { mpf_urandomb(f, s, prec); }
        !          1357: };
        !          1358:
        !          1359:
        !          1360: /**************** Auxiliary classes ****************/
        !          1361:
        !          1362: /* this is much the same as gmp_allocated_string in gmp-impl.h
        !          1363:    since gmp-impl.h is not publicly available, I redefine it here
        !          1364:    I use a different name to avoid possible clashes */
        !          1365: extern "C" {
        !          1366: struct __gmp_alloc_cstring_c
        !          1367: {
        !          1368:    void (*free_func) (void *, size_t);
        !          1369: };
        !          1370: }
        !          1371:
        !          1372: struct __gmp_alloc_cstring : __gmp_alloc_cstring_c
        !          1373: {
        !          1374:   char *str;
        !          1375:   __gmp_alloc_cstring(char *s) { str = s; }
        !          1376:   ~__gmp_alloc_cstring()
        !          1377:   {
        !          1378:     mp_get_memory_functions (NULL, NULL, &free_func);
        !          1379:     (*free_func) (str, std::strlen(str)+1);
        !          1380:   }
        !          1381: };
        !          1382:
        !          1383: // general expression template class
        !          1384: template <class T, class U>
        !          1385: class __gmp_expr;
        !          1386:
        !          1387:
        !          1388: // templates for resolving expression types
        !          1389: template <class T>
        !          1390: struct __gmp_resolve_ref
        !          1391: {
        !          1392:   typedef T ref_type;
        !          1393: };
        !          1394:
        !          1395: template <class T, class U>
        !          1396: struct __gmp_resolve_ref<__gmp_expr<T, U> >
        !          1397: {
        !          1398:   typedef const __gmp_expr<T, U> & ref_type;
        !          1399: };
        !          1400:
        !          1401:
        !          1402: template <class T, class U = T>
        !          1403: struct __gmp_resolve_expr;
        !          1404:
        !          1405: template <>
        !          1406: struct __gmp_resolve_expr<mpz_t>
        !          1407: {
        !          1408:   typedef mpz_t value_type;
        !          1409:   typedef mpz_ptr ptr_type;
        !          1410: };
        !          1411:
        !          1412: template <>
        !          1413: struct __gmp_resolve_expr<mpq_t>
        !          1414: {
        !          1415:   typedef mpq_t value_type;
        !          1416:   typedef mpq_ptr ptr_type;
        !          1417: };
        !          1418:
        !          1419: template <>
        !          1420: struct __gmp_resolve_expr<mpf_t>
        !          1421: {
        !          1422:   typedef mpf_t value_type;
        !          1423:   typedef mpf_ptr ptr_type;
        !          1424: };
        !          1425:
        !          1426: template <>
        !          1427: struct __gmp_resolve_expr<mpz_t, mpq_t>
        !          1428: {
        !          1429:   typedef mpq_t value_type;
        !          1430: };
        !          1431:
        !          1432: template <>
        !          1433: struct __gmp_resolve_expr<mpq_t, mpz_t>
        !          1434: {
        !          1435:   typedef mpq_t value_type;
        !          1436: };
        !          1437:
        !          1438: template <>
        !          1439: struct __gmp_resolve_expr<mpz_t, mpf_t>
        !          1440: {
        !          1441:   typedef mpf_t value_type;
        !          1442: };
        !          1443:
        !          1444: template <>
        !          1445: struct __gmp_resolve_expr<mpf_t, mpz_t>
        !          1446: {
        !          1447:   typedef mpf_t value_type;
        !          1448: };
        !          1449:
        !          1450: template <>
        !          1451: struct __gmp_resolve_expr<mpq_t, mpf_t>
        !          1452: {
        !          1453:   typedef mpf_t value_type;
        !          1454: };
        !          1455:
        !          1456: template <>
        !          1457: struct __gmp_resolve_expr<mpf_t, mpq_t>
        !          1458: {
        !          1459:   typedef mpf_t value_type;
        !          1460: };
        !          1461:
        !          1462:
        !          1463:
        !          1464: template <class T, class U, class V>
        !          1465: struct __gmp_resolve_temp
        !          1466: {
        !          1467:   typedef __gmp_expr<T, T> temp_type;
        !          1468: };
        !          1469:
        !          1470: template <class T>
        !          1471: struct __gmp_resolve_temp<T, T, T>
        !          1472: {
        !          1473:   typedef const __gmp_expr<T, T> & temp_type;
        !          1474: };
        !          1475:
        !          1476:
        !          1477: // classes for evaluating unary and binary expressions
        !          1478: template <class T, class Op>
        !          1479: struct __gmp_unary_expr
        !          1480: {
        !          1481:   const T &val;
        !          1482:
        !          1483:   __gmp_unary_expr(const T &v) : val(v) { }
        !          1484: private:
        !          1485:   __gmp_unary_expr();
        !          1486: };
        !          1487:
        !          1488: template <class T, class U, class Op>
        !          1489: struct __gmp_binary_expr
        !          1490: {
        !          1491:   typename __gmp_resolve_ref<T>::ref_type val1;
        !          1492:   typename __gmp_resolve_ref<U>::ref_type val2;
        !          1493:
        !          1494:   __gmp_binary_expr(const T &v1, const U &v2) : val1(v1), val2(v2) { }
        !          1495: private:
        !          1496:   __gmp_binary_expr();
        !          1497: };
        !          1498:
        !          1499:
        !          1500: // functions for evaluating expressions
        !          1501: template <class T, class U>
        !          1502: void __gmp_set_expr(mpz_ptr, const __gmp_expr<T, U> &);
        !          1503: template <class T, class U>
        !          1504: void __gmp_set_expr(mpq_ptr, const __gmp_expr<T, U> &);
        !          1505: template <class T, class U>
        !          1506: void __gmp_set_expr(mpf_ptr, const __gmp_expr<T, U> &);
        !          1507:
        !          1508:
        !          1509: /**************** Macros for in-class declarations ****************/
        !          1510: /* This is just repetitive code that is easier to maintain if it's written
        !          1511:    only once */
        !          1512:
        !          1513: #define __GMPP_DECLARE_COMPOUND_OPERATOR(fun)                         \
        !          1514:   template <class T, class U>                                         \
        !          1515:   __gmp_expr<value_type, value_type> & fun(const __gmp_expr<T, U> &);
        !          1516: #ifdef MPIRXX_HAVE_LLONG
        !          1517: #define __GMPN_DECLARE_COMPOUND_OPERATOR(fun) \
        !          1518:   __gmp_expr & fun(signed char);              \
        !          1519:   __gmp_expr & fun(unsigned char);            \
        !          1520:   __gmp_expr & fun(signed int);               \
        !          1521:   __gmp_expr & fun(unsigned int);             \
        !          1522:   __gmp_expr & fun(signed short int);         \
        !          1523:   __gmp_expr & fun(unsigned short int);       \
        !          1524:   __gmp_expr & fun(signed long int);          \
        !          1525:   __gmp_expr & fun(unsigned long int);        \
        !          1526:   __gmp_expr & fun(signed long long int);     \
        !          1527:   __gmp_expr & fun(unsigned long long int);   \
        !          1528:   __gmp_expr & fun(float);                    \
        !          1529:   __gmp_expr & fun(double);                   \
        !          1530:   __gmp_expr & fun(long double);
        !          1531: #else
        !          1532: #define __GMPN_DECLARE_COMPOUND_OPERATOR(fun) \
        !          1533:   __gmp_expr & fun(signed char);              \
        !          1534:   __gmp_expr & fun(unsigned char);            \
        !          1535:   __gmp_expr & fun(signed int);               \
        !          1536:   __gmp_expr & fun(unsigned int);             \
        !          1537:   __gmp_expr & fun(signed short int);         \
        !          1538:   __gmp_expr & fun(unsigned short int);       \
        !          1539:   __gmp_expr & fun(signed long int);          \
        !          1540:   __gmp_expr & fun(unsigned long int);        \
        !          1541:   __gmp_expr & fun(float);                    \
        !          1542:   __gmp_expr & fun(double);                   \
        !          1543:   __gmp_expr & fun(long double);
        !          1544: #endif
        !          1545:
        !          1546: #define __GMP_DECLARE_COMPOUND_OPERATOR(fun) \
        !          1547: __GMPP_DECLARE_COMPOUND_OPERATOR(fun)        \
        !          1548: __GMPN_DECLARE_COMPOUND_OPERATOR(fun)
        !          1549:
        !          1550: #define __GMP_DECLARE_COMPOUND_OPERATOR_UI(fun) \
        !          1551:   __gmp_expr & fun(mpir_ui);
        !          1552:
        !          1553: #define __GMP_DECLARE_INCREMENT_OPERATOR(fun) \
        !          1554:   inline __gmp_expr & fun();                  \
        !          1555:   inline __gmp_expr fun(int);
        !          1556:
        !          1557:
        !          1558: /**************** mpz_class -- wrapper for mpz_t ****************/
        !          1559:
        !          1560: template <>
        !          1561: class __gmp_expr<mpz_t, mpz_t>
        !          1562: {
        !          1563: private:
        !          1564:   typedef mpz_t value_type;
        !          1565:   value_type mp;
        !          1566: public:
        !          1567:   mp_bitcnt_t get_prec() const { return mpf_get_default_prec(); }
        !          1568:
        !          1569:   // constructors and destructor
        !          1570:   __gmp_expr() { mpz_init(mp); }
        !          1571:
        !          1572:   __gmp_expr(const __gmp_expr &z) { mpz_init_set(mp, z.mp); }
        !          1573:   template <class T, class U>
        !          1574:   __gmp_expr(const __gmp_expr<T, U> &expr)
        !          1575:   { mpz_init(mp); __gmp_set_expr(mp, expr); }
        !          1576:
        !          1577:   __gmp_expr(signed char c) { mpz_init_set_si(mp, c); }
        !          1578:   __gmp_expr(unsigned char c) { mpz_init_set_ui(mp, c); }
        !          1579:
        !          1580:   __gmp_expr(signed int i) { mpz_init_set_si(mp, i); }
        !          1581:   __gmp_expr(unsigned int i) { mpz_init_set_ui(mp, i); }
        !          1582:
        !          1583:   __gmp_expr(signed short int s) { mpz_init_set_si(mp, s); }
        !          1584:   __gmp_expr(unsigned short int s) { mpz_init_set_ui(mp, s); }
        !          1585:
        !          1586:   __gmp_expr(signed long int l) { mpz_init_set_si(mp, l); }
        !          1587:   __gmp_expr(unsigned long int  l) { mpz_init_set_ui(mp, l); }
        !          1588:
        !          1589: #ifdef MPIRXX_HAVE_LLONG
        !          1590:   __gmp_expr(signed long long int l) { mpz_init_set_si(mp, l); }
        !          1591:   __gmp_expr(unsigned long long int  l) { mpz_init_set_ui(mp, l); }
        !          1592: #endif
        !          1593:
        !          1594: #if defined( _MSC_VER ) && _MSC_VER >= 1600
        !          1595: #if defined( _STDINT_H ) || defined ( _STDINT_H_ ) || defined ( _STDINT )
        !          1596:   __gmp_expr(intmax_t l) { mpz_init_set_sx(mp, l); }
        !          1597:   __gmp_expr(uintmax_t l) { mpz_init_set_ux(mp, l); }
        !          1598: #endif
        !          1599: #endif
        !          1600:
        !          1601:   __gmp_expr(float f) { mpz_init_set_d(mp, f); }
        !          1602:   __gmp_expr(double d) { mpz_init_set_d(mp, d); }
        !          1603:   // __gmp_expr(long double ld) { mpz_init_set_d(mp, ld); }
        !          1604:
        !          1605:   explicit __gmp_expr(const char *s)
        !          1606:   {
        !          1607:     if (mpz_init_set_str (mp, s, 0) != 0)
        !          1608:       {
        !          1609:         mpz_clear (mp);
        !          1610:         throw std::invalid_argument ("mpz_set_str");
        !          1611:       }
        !          1612:   }
        !          1613:   __gmp_expr(const char *s, int base)
        !          1614:   {
        !          1615:     if (mpz_init_set_str (mp, s, base) != 0)
        !          1616:       {
        !          1617:         mpz_clear (mp);
        !          1618:         throw std::invalid_argument ("mpz_set_str");
        !          1619:       }
        !          1620:   }
        !          1621:   explicit __gmp_expr(const std::string &s)
        !          1622:   {
        !          1623:     if (mpz_init_set_str (mp, s.c_str(), 0) != 0)
        !          1624:       {
        !          1625:         mpz_clear (mp);
        !          1626:         throw std::invalid_argument ("mpz_set_str");
        !          1627:       }
        !          1628:   }
        !          1629:   __gmp_expr(const std::string &s, int base)
        !          1630:   {
        !          1631:     if (mpz_init_set_str(mp, s.c_str(), base) != 0)
        !          1632:       {
        !          1633:         mpz_clear (mp);
        !          1634:         throw std::invalid_argument ("mpz_set_str");
        !          1635:       }
        !          1636:   }
        !          1637:
        !          1638:   explicit __gmp_expr(mpz_srcptr z) { mpz_init_set(mp, z); }
        !          1639:
        !          1640:   ~__gmp_expr() { mpz_clear(mp); }
        !          1641:
        !          1642:   // assignment operators
        !          1643:   __gmp_expr & operator=(const __gmp_expr &z) { mpz_set(mp, z.mp); return *this; }
        !          1644:   template <class T, class U>
        !          1645:   __gmp_expr<value_type, value_type> & operator=(const __gmp_expr<T, U> &expr)
        !          1646:   { __gmp_set_expr(mp, expr); return *this; }
        !          1647:
        !          1648:   __gmp_expr & operator=(signed char c) { mpz_set_si(mp, c); return *this; }
        !          1649:   __gmp_expr & operator=(unsigned char c) { mpz_set_ui(mp, c); return *this; }
        !          1650:
        !          1651:   __gmp_expr & operator=(signed short int s) { mpz_set_si(mp, s); return *this; }
        !          1652:   __gmp_expr & operator=(unsigned short int s) { mpz_set_ui(mp, s); return *this; }
        !          1653:
        !          1654:   __gmp_expr & operator=(signed int i) { mpz_set_si(mp, i); return *this; }
        !          1655:   __gmp_expr & operator=(unsigned int i) { mpz_set_ui(mp, i); return *this; }
        !          1656:
        !          1657:   __gmp_expr & operator=(signed long int i) { mpz_set_si(mp, i); return *this; }
        !          1658:   __gmp_expr & operator=(unsigned long int i) { mpz_set_ui(mp, i); return *this; }
        !          1659:
        !          1660: #ifdef MPIRXX_HAVE_LLONG
        !          1661:   __gmp_expr & operator=(signed long long int i) { mpz_set_si(mp, i); return *this; }
        !          1662:   __gmp_expr & operator=(unsigned long long int i) { mpz_set_ui(mp, i); return *this; }
        !          1663: #endif
        !          1664:
        !          1665: #if defined( _MSC_VER ) && _MSC_VER >= 1600
        !          1666: #if defined( _STDINT_H ) || defined ( _STDINT_H_ ) || defined ( _STDINT )
        !          1667:   __gmp_expr & operator=(intmax_t i) { mpz_set_sx(mp, i); return *this; }
        !          1668:   __gmp_expr & operator=(uintmax_t i) { mpz_set_ux(mp, i); return *this; }
        !          1669: #endif
        !          1670: #endif
        !          1671:
        !          1672:   __gmp_expr & operator=(float f) { mpz_set_d(mp, f); return *this; }
        !          1673:   __gmp_expr & operator=(double d) { mpz_set_d(mp, d); return *this; }
        !          1674:   // __gmp_expr & operator=(long double ld)
        !          1675:   // { mpz_set_ld(mp, ld); return *this; }
        !          1676:
        !          1677:   __gmp_expr & operator=(const char *s)
        !          1678:   {
        !          1679:     if (mpz_set_str (mp, s, 0) != 0)
        !          1680:       throw std::invalid_argument ("mpz_set_str");
        !          1681:     return *this;
        !          1682:   }
        !          1683:   __gmp_expr & operator=(const std::string &s)
        !          1684:   {
        !          1685:     if (mpz_set_str(mp, s.c_str(), 0) != 0)
        !          1686:       throw std::invalid_argument ("mpz_set_str");
        !          1687:     return *this;
        !          1688:   }
        !          1689:
        !          1690:   // string input/output functions
        !          1691:   int set_str(const char *s, int base)
        !          1692:   { return mpz_set_str(mp, s, base); }
        !          1693:   int set_str(const std::string &s, int base)
        !          1694:   { return mpz_set_str(mp, s.c_str(), base); }
        !          1695:   std::string get_str(int base = 10) const
        !          1696:   {
        !          1697:     __gmp_alloc_cstring temp(mpz_get_str(0, base, mp));
        !          1698:     return std::string(temp.str);
        !          1699:   }
        !          1700:
        !          1701:   // conversion functions
        !          1702:   mpz_srcptr __get_mp() const { return mp; }
        !          1703:   mpz_ptr __get_mp() { return mp; }
        !          1704:   mpz_srcptr get_mpz_t() const { return mp; }
        !          1705:   mpz_ptr get_mpz_t() { return mp; }
        !          1706:
        !          1707:   mpir_si get_si() const { return mpz_get_si(mp); }
        !          1708:   mpir_ui get_ui() const { return mpz_get_ui(mp); }
        !          1709: #if defined( _STDINT_H ) || defined ( _STDINT_H_ ) || defined ( _STDINT )
        !          1710:   intmax_t get_sx() const { return mpz_get_sx(mp); }
        !          1711:   uintmax_t get_ux() const { return mpz_get_ux(mp); }
        !          1712: #endif
        !          1713:   double get_d() const { return mpz_get_d(mp); }
        !          1714:
        !          1715:   // bool fits_schar_p() const { return mpz_fits_schar_p(mp); }
        !          1716:   // bool fits_uchar_p() const { return mpz_fits_uchar_p(mp); }
        !          1717:   bool fits_sint_p() const { return mpz_fits_sint_p(mp); }
        !          1718:   bool fits_uint_p() const { return mpz_fits_uint_p(mp); }
        !          1719:   bool fits_si_p() const { return mpz_fits_si_p(mp); }
        !          1720:   bool fits_ui_p() const { return mpz_fits_ui_p(mp); }
        !          1721:   bool fits_sshort_p() const { return mpz_fits_sshort_p(mp); }
        !          1722:   bool fits_ushort_p() const { return mpz_fits_ushort_p(mp); }
        !          1723:   bool fits_slong_p() const { return mpz_fits_slong_p(mp); }
        !          1724:   bool fits_ulong_p() const { return mpz_fits_ulong_p(mp); }
        !          1725:   // bool fits_float_p() const { return mpz_fits_float_p(mp); }
        !          1726:   // bool fits_double_p() const { return mpz_fits_double_p(mp); }
        !          1727:   // bool fits_ldouble_p() const { return mpz_fits_ldouble_p(mp); }
        !          1728:
        !          1729:   // member operators
        !          1730:   __GMP_DECLARE_COMPOUND_OPERATOR(operator+=)
        !          1731:   __GMP_DECLARE_COMPOUND_OPERATOR(operator-=)
        !          1732:   __GMP_DECLARE_COMPOUND_OPERATOR(operator*=)
        !          1733:   __GMP_DECLARE_COMPOUND_OPERATOR(operator/=)
        !          1734:   __GMP_DECLARE_COMPOUND_OPERATOR(operator%=)
        !          1735:
        !          1736:   __GMPP_DECLARE_COMPOUND_OPERATOR(operator&=)
        !          1737:   __GMPP_DECLARE_COMPOUND_OPERATOR(operator|=)
        !          1738:   __GMPP_DECLARE_COMPOUND_OPERATOR(operator^=)
        !          1739:
        !          1740:   __GMP_DECLARE_COMPOUND_OPERATOR_UI(operator<<=)
        !          1741:   __GMP_DECLARE_COMPOUND_OPERATOR_UI(operator>>=)
        !          1742:
        !          1743:   __GMP_DECLARE_INCREMENT_OPERATOR(operator++)
        !          1744:   __GMP_DECLARE_INCREMENT_OPERATOR(operator--)
        !          1745: };
        !          1746:
        !          1747: typedef __gmp_expr<mpz_t, mpz_t> mpz_class;
        !          1748:
        !          1749:
        !          1750: /**************** mpq_class -- wrapper for mpq_t ****************/
        !          1751:
        !          1752: template <>
        !          1753: class __gmp_expr<mpq_t, mpq_t>
        !          1754: {
        !          1755: private:
        !          1756:   typedef mpq_t value_type;
        !          1757:   value_type mp;
        !          1758: public:
        !          1759:   mp_bitcnt_t get_prec() const { return mpf_get_default_prec(); }
        !          1760:   void canonicalize() { mpq_canonicalize(mp); }
        !          1761:
        !          1762:   // constructors and destructor
        !          1763:   __gmp_expr() { mpq_init(mp); }
        !          1764:
        !          1765:   __gmp_expr(const __gmp_expr &q) { mpq_init(mp); mpq_set(mp, q.mp); }
        !          1766:   template <class T, class U>
        !          1767:   __gmp_expr(const __gmp_expr<T, U> &expr)
        !          1768:   { mpq_init(mp); __gmp_set_expr(mp, expr); }
        !          1769:
        !          1770:   __gmp_expr(signed char c) { mpq_init(mp); mpq_set_si(mp, c, 1); }
        !          1771:   __gmp_expr(unsigned char c) { mpq_init(mp); mpq_set_ui(mp, c, 1); }
        !          1772:
        !          1773:   __gmp_expr(signed int i) { mpq_init(mp); mpq_set_si(mp, i, 1); }
        !          1774:   __gmp_expr(unsigned int i) { mpq_init(mp); mpq_set_ui(mp, i, 1); }
        !          1775:
        !          1776:   __gmp_expr(signed short int s) { mpq_init(mp); mpq_set_si(mp, s, 1); }
        !          1777:   __gmp_expr(unsigned short int s) { mpq_init(mp); mpq_set_ui(mp, s, 1); }
        !          1778:
        !          1779:   __gmp_expr(signed long int l) { mpq_init(mp); mpq_set_si(mp, l, 1); }
        !          1780:   __gmp_expr(unsigned long int l) { mpq_init(mp); mpq_set_ui(mp, l, 1); }
        !          1781:
        !          1782: #ifdef MPIRXX_HAVE_LLONG
        !          1783:   __gmp_expr(signed long long int l) { mpq_init(mp); mpq_set_si(mp, l, 1); }
        !          1784:   __gmp_expr(unsigned long long int l) { mpq_init(mp); mpq_set_ui(mp, l, 1); }
        !          1785: #endif
        !          1786:
        !          1787:   __gmp_expr(float f) { mpq_init(mp); mpq_set_d(mp, f); }
        !          1788:   __gmp_expr(double d) { mpq_init(mp); mpq_set_d(mp, d); }
        !          1789:   // __gmp_expr(long double ld) { mpq_init(mp); mpq_set_ld(mp, ld); }
        !          1790:
        !          1791:   explicit __gmp_expr(const char *s)
        !          1792:   {
        !          1793:     mpq_init (mp);
        !          1794:     if (mpq_set_str (mp, s, 0) != 0)
        !          1795:       {
        !          1796:         mpq_clear (mp);
        !          1797:         throw std::invalid_argument ("mpq_set_str");
        !          1798:       }
        !          1799:   }
        !          1800:   __gmp_expr(const char *s, int base)
        !          1801:   {
        !          1802:     mpq_init (mp);
        !          1803:     if (mpq_set_str(mp, s, base) != 0)
        !          1804:       {
        !          1805:         mpq_clear (mp);
        !          1806:         throw std::invalid_argument ("mpq_set_str");
        !          1807:       }
        !          1808:   }
        !          1809:   explicit __gmp_expr(const std::string &s)
        !          1810:   {
        !          1811:     mpq_init (mp);
        !          1812:     if (mpq_set_str (mp, s.c_str(), 0) != 0)
        !          1813:       {
        !          1814:         mpq_clear (mp);
        !          1815:         throw std::invalid_argument ("mpq_set_str");
        !          1816:       }
        !          1817:   }
        !          1818:   __gmp_expr(const std::string &s, int base)
        !          1819:   {
        !          1820:     mpq_init(mp);
        !          1821:     if (mpq_set_str (mp, s.c_str(), base) != 0)
        !          1822:       {
        !          1823:         mpq_clear (mp);
        !          1824:         throw std::invalid_argument ("mpq_set_str");
        !          1825:       }
        !          1826:   }
        !          1827:   explicit __gmp_expr(mpq_srcptr q) { mpq_init(mp); mpq_set(mp, q); }
        !          1828:
        !          1829:   __gmp_expr(const mpz_class &num, const mpz_class &den)
        !          1830:   {
        !          1831:     mpq_init(mp);
        !          1832:     mpz_set(mpq_numref(mp), num.get_mpz_t());
        !          1833:     mpz_set(mpq_denref(mp), den.get_mpz_t());
        !          1834:   }
        !          1835:
        !          1836:   ~__gmp_expr() { mpq_clear(mp); }
        !          1837:
        !          1838:   // assignment operators
        !          1839:   __gmp_expr & operator=(const __gmp_expr &q)
        !          1840:   { mpq_set(mp, q.mp); return *this; }
        !          1841:   template <class T, class U>
        !          1842:   __gmp_expr<value_type, value_type> & operator=(const __gmp_expr<T, U> &expr)
        !          1843:   { __gmp_set_expr(mp, expr); return *this; }
        !          1844:
        !          1845:   __gmp_expr & operator=(signed char c)
        !          1846:   { mpq_set_si(mp, c, 1); return *this; }
        !          1847:   __gmp_expr & operator=(unsigned char c)
        !          1848:   { mpq_set_ui(mp, c, 1); return *this; }
        !          1849:
        !          1850:   __gmp_expr & operator=(signed int i) { mpq_set_si(mp, i, 1); return *this; }
        !          1851:   __gmp_expr & operator=(unsigned int i)
        !          1852:   { mpq_set_ui(mp, i, 1); return *this; }
        !          1853:
        !          1854:   __gmp_expr & operator=(signed short int s)
        !          1855:   { mpq_set_si(mp, s, 1); return *this; }
        !          1856:   __gmp_expr & operator=(unsigned short int s)
        !          1857:   { mpq_set_ui(mp, s, 1); return *this; }
        !          1858:
        !          1859:   __gmp_expr & operator=(signed long int l)
        !          1860:   { mpq_set_si(mp, l, 1); return *this; }
        !          1861:   __gmp_expr & operator=(unsigned long int l)
        !          1862:   { mpq_set_ui(mp, l, 1); return *this; }
        !          1863:
        !          1864: #ifdef MPIRXX_HAVE_LLONG
        !          1865:   __gmp_expr & operator=(signed long long int l)
        !          1866:   { mpq_set_si(mp, l, 1); return *this; }
        !          1867:   __gmp_expr & operator=(unsigned long long int l)
        !          1868:   { mpq_set_ui(mp, l, 1); return *this; }
        !          1869: #endif
        !          1870:
        !          1871:   __gmp_expr & operator=(float f) { mpq_set_d(mp, f); return *this; }
        !          1872:   __gmp_expr & operator=(double d) { mpq_set_d(mp, d); return *this; }
        !          1873:
        !          1874: //  __gmp_expr & operator=(long double ld)
        !          1875: //   { mpq_set_ld(mp, ld); return *this; }
        !          1876:
        !          1877:   __gmp_expr & operator=(const char *s)
        !          1878:   {
        !          1879:     if (mpq_set_str (mp, s, 0) != 0)
        !          1880:       throw std::invalid_argument ("mpq_set_str");
        !          1881:     return *this;
        !          1882:   }
        !          1883:   __gmp_expr & operator=(const std::string &s)
        !          1884:   {
        !          1885:     if (mpq_set_str(mp, s.c_str(), 0) != 0)
        !          1886:       throw std::invalid_argument ("mpq_set_str");
        !          1887:     return *this;
        !          1888:   }
        !          1889:
        !          1890:   // string input/output functions
        !          1891:   int set_str(const char *s, int base)
        !          1892:   { return mpq_set_str(mp, s, base); }
        !          1893:   int set_str(const std::string &s, int base)
        !          1894:   { return mpq_set_str(mp, s.c_str(), base); }
        !          1895:   std::string get_str(int base = 10) const
        !          1896:   {
        !          1897:     __gmp_alloc_cstring temp(mpq_get_str(0, base, mp));
        !          1898:     return std::string(temp.str);
        !          1899:   }
        !          1900:
        !          1901:   // conversion functions
        !          1902:
        !          1903:   // casting a reference to an mpz_t to mpz_class & is a dirty hack,
        !          1904:   // but works because the internal representation of mpz_class is
        !          1905:   // exactly an mpz_t
        !          1906:   const mpz_class & get_num() const
        !          1907:   { return reinterpret_cast<const mpz_class &>(*mpq_numref(mp)); }
        !          1908:   mpz_class & get_num()
        !          1909:   { return reinterpret_cast<mpz_class &>(*mpq_numref(mp)); }
        !          1910:   const mpz_class & get_den() const
        !          1911:   { return reinterpret_cast<const mpz_class &>(*mpq_denref(mp)); }
        !          1912:   mpz_class & get_den()
        !          1913:   { return reinterpret_cast<mpz_class &>(*mpq_denref(mp)); }
        !          1914:
        !          1915:   mpq_srcptr __get_mp() const { return mp; }
        !          1916:   mpq_ptr __get_mp() { return mp; }
        !          1917:   mpq_srcptr get_mpq_t() const { return mp; }
        !          1918:   mpq_ptr get_mpq_t() { return mp; }
        !          1919:
        !          1920:   mpz_srcptr get_num_mpz_t() const { return mpq_numref(mp); }
        !          1921:   mpz_ptr get_num_mpz_t() { return mpq_numref(mp); }
        !          1922:   mpz_srcptr get_den_mpz_t() const { return mpq_denref(mp); }
        !          1923:   mpz_ptr get_den_mpz_t() { return mpq_denref(mp); }
        !          1924:
        !          1925:   double get_d() const { return mpq_get_d(mp); }
        !          1926:
        !          1927:   // compound assignments
        !          1928:   __GMP_DECLARE_COMPOUND_OPERATOR(operator+=)
        !          1929:   __GMP_DECLARE_COMPOUND_OPERATOR(operator-=)
        !          1930:   __GMP_DECLARE_COMPOUND_OPERATOR(operator*=)
        !          1931:   __GMP_DECLARE_COMPOUND_OPERATOR(operator/=)
        !          1932:
        !          1933:   __GMP_DECLARE_COMPOUND_OPERATOR_UI(operator<<=)
        !          1934:   __GMP_DECLARE_COMPOUND_OPERATOR_UI(operator>>=)
        !          1935:
        !          1936:   __GMP_DECLARE_INCREMENT_OPERATOR(operator++)
        !          1937:   __GMP_DECLARE_INCREMENT_OPERATOR(operator--)
        !          1938: };
        !          1939:
        !          1940: typedef __gmp_expr<mpq_t, mpq_t> mpq_class;
        !          1941:
        !          1942:
        !          1943: /**************** mpf_class -- wrapper for mpf_t ****************/
        !          1944:
        !          1945: template <>
        !          1946: class __gmp_expr<mpf_t, mpf_t>
        !          1947: {
        !          1948: private:
        !          1949:   typedef mpf_t value_type;
        !          1950:   value_type mp;
        !          1951: public:
        !          1952:   mp_bitcnt_t get_prec() const { return mpf_get_prec(mp); }
        !          1953:
        !          1954:   void set_prec(mp_bitcnt_t prec) { mpf_set_prec(mp, prec); }
        !          1955:   void set_prec_raw(mp_bitcnt_t prec) { mpf_set_prec_raw(mp, prec); }
        !          1956:
        !          1957:   // constructors and destructor
        !          1958:   __gmp_expr() { mpf_init(mp); }
        !          1959:
        !          1960:   __gmp_expr(const __gmp_expr &f)
        !          1961:   { mpf_init2(mp, f.get_prec()); mpf_set(mp, f.mp); }
        !          1962:   __gmp_expr(const __gmp_expr &f, mp_bitcnt_t prec)
        !          1963:   { mpf_init2(mp, prec); mpf_set(mp, f.mp); }
        !          1964:   template <class T, class U>
        !          1965:   __gmp_expr(const __gmp_expr<T, U> &expr)
        !          1966:   { mpf_init2(mp, expr.get_prec()); __gmp_set_expr(mp, expr); }
        !          1967:   template <class T, class U>
        !          1968:   __gmp_expr(const __gmp_expr<T, U> &expr, mp_bitcnt_t prec)
        !          1969:   { mpf_init2(mp, prec); __gmp_set_expr(mp, expr); }
        !          1970:
        !          1971:   __gmp_expr(signed char c) { mpf_init_set_si(mp, c); }
        !          1972:   __gmp_expr(signed char c, mp_bitcnt_t prec)
        !          1973:   { mpf_init2(mp, prec); mpf_set_si(mp, c); }
        !          1974:   __gmp_expr(unsigned char c) { mpf_init_set_ui(mp, c); }
        !          1975:   __gmp_expr(unsigned char c, mp_bitcnt_t prec)
        !          1976:   { mpf_init2(mp, prec); mpf_set_ui(mp, c); }
        !          1977:
        !          1978:   __gmp_expr(signed short int s) { mpf_init_set_si(mp, s); }
        !          1979:   __gmp_expr(signed short int s, mp_bitcnt_t prec)
        !          1980:   { mpf_init2(mp, prec); mpf_set_si(mp, s); }
        !          1981:   __gmp_expr(unsigned short int s) { mpf_init_set_ui(mp, s); }
        !          1982:   __gmp_expr(unsigned short int s, mp_bitcnt_t prec)
        !          1983:   { mpf_init2(mp, prec); mpf_set_ui(mp, s); }
        !          1984:
        !          1985:   __gmp_expr(signed int i) { mpf_init_set_si(mp, i); }
        !          1986:   __gmp_expr(signed int i, mp_bitcnt_t prec)
        !          1987:   { mpf_init2(mp, prec); mpf_set_si(mp, i); }
        !          1988:   __gmp_expr(unsigned int i) { mpf_init_set_ui(mp, i); }
        !          1989:   __gmp_expr(unsigned int i, mp_bitcnt_t prec)
        !          1990:   { mpf_init2(mp, prec); mpf_set_ui(mp, i); }
        !          1991:
        !          1992:   __gmp_expr(signed long int s) { mpf_init_set_si(mp, s); }
        !          1993:   __gmp_expr(signed long int s, mp_bitcnt_t prec)
        !          1994:   { mpf_init2(mp, prec); mpf_set_si(mp, s); }
        !          1995:   __gmp_expr(unsigned long int s) { mpf_init_set_ui(mp, s); }
        !          1996:   __gmp_expr(unsigned long int s, mp_bitcnt_t prec)
        !          1997:   { mpf_init2(mp, prec); mpf_set_ui(mp, s); }
        !          1998:
        !          1999: #ifdef MPIRXX_HAVE_LLONG
        !          2000:   __gmp_expr(signed long long int s) { mpf_init_set_si(mp, s); }
        !          2001:   __gmp_expr(signed long long int s, mp_bitcnt_t prec)
        !          2002:   { mpf_init2(mp, prec); mpf_set_si(mp, s); }
        !          2003:   __gmp_expr(unsigned long long int s) { mpf_init_set_ui(mp, s); }
        !          2004:   __gmp_expr(unsigned long long int s, mp_bitcnt_t prec)
        !          2005:   { mpf_init2(mp, prec); mpf_set_ui(mp, s); }
        !          2006: #endif
        !          2007:
        !          2008:   __gmp_expr(float f) { mpf_init_set_d(mp, f); }
        !          2009:   __gmp_expr(float f, mp_bitcnt_t prec)
        !          2010:   { mpf_init2(mp, prec); mpf_set_d(mp, f); }
        !          2011:   __gmp_expr(double d) { mpf_init_set_d(mp, d); }
        !          2012:   __gmp_expr(double d, mp_bitcnt_t prec)
        !          2013:   { mpf_init2(mp, prec); mpf_set_d(mp, d); }
        !          2014:   // __gmp_expr(long double ld) { mpf_init_set_d(mp, ld); }
        !          2015:   // __gmp_expr(long double ld, mp_bitcnt_t prec)
        !          2016:   // { mpf_init2(mp, prec); mpf_set_d(mp, ld); }
        !          2017:
        !          2018:   explicit __gmp_expr(const char *s)
        !          2019:   {
        !          2020:     if (mpf_init_set_str (mp, s, 0) != 0)
        !          2021:       {
        !          2022:         mpf_clear (mp);
        !          2023:         throw std::invalid_argument ("mpf_set_str");
        !          2024:       }
        !          2025:   }
        !          2026:   __gmp_expr(const char *s, mp_bitcnt_t prec, int base = 0)
        !          2027:   {
        !          2028:     mpf_init2(mp, prec);
        !          2029:     if (mpf_set_str(mp, s, base) != 0)
        !          2030:       {
        !          2031:         mpf_clear (mp);
        !          2032:         throw std::invalid_argument ("mpf_set_str");
        !          2033:       }
        !          2034:   }
        !          2035:   explicit __gmp_expr(const std::string &s)
        !          2036:   {
        !          2037:     if (mpf_init_set_str(mp, s.c_str(), 0) != 0)
        !          2038:       {
        !          2039:         mpf_clear (mp);
        !          2040:         throw std::invalid_argument ("mpf_set_str");
        !          2041:       }
        !          2042:   }
        !          2043:   __gmp_expr(const std::string &s, mp_bitcnt_t prec, int base = 0)
        !          2044:   {
        !          2045:     mpf_init2(mp, prec);
        !          2046:     if (mpf_set_str(mp, s.c_str(), base) != 0)
        !          2047:       {
        !          2048:         mpf_clear (mp);
        !          2049:         throw std::invalid_argument ("mpf_set_str");
        !          2050:       }
        !          2051:   }
        !          2052:
        !          2053:   explicit __gmp_expr(mpf_srcptr f)
        !          2054:   { mpf_init2(mp, mpf_get_prec(f)); mpf_set(mp, f); }
        !          2055:   __gmp_expr(mpf_srcptr f, mp_bitcnt_t prec)
        !          2056:   { mpf_init2(mp, prec); mpf_set(mp, f); }
        !          2057:
        !          2058:   ~__gmp_expr() { mpf_clear(mp); }
        !          2059:
        !          2060:   // assignment operators
        !          2061:   __gmp_expr & operator=(const __gmp_expr &f)
        !          2062:   { mpf_set(mp, f.mp); return *this; }
        !          2063:   template <class T, class U>
        !          2064:   __gmp_expr<value_type, value_type> & operator=(const __gmp_expr<T, U> &expr)
        !          2065:   { __gmp_set_expr(mp, expr); return *this; }
        !          2066:
        !          2067:   __gmp_expr & operator=(signed char c) { mpf_set_si(mp, c); return *this; }
        !          2068:   __gmp_expr & operator=(unsigned char c) { mpf_set_ui(mp, c); return *this; }
        !          2069:
        !          2070:   __gmp_expr & operator=(signed int i) { mpf_set_si(mp, i); return *this; }
        !          2071:   __gmp_expr & operator=(unsigned int i) { mpf_set_ui(mp, i); return *this; }
        !          2072:
        !          2073:   __gmp_expr & operator=(signed short int s)
        !          2074:   { mpf_set_si(mp, s); return *this; }
        !          2075:   __gmp_expr & operator=(unsigned short int s)
        !          2076:   { mpf_set_ui(mp, s); return *this; }
        !          2077:
        !          2078:   __gmp_expr & operator=(signed long int l)
        !          2079:   { mpf_set_si(mp, l); return *this; }
        !          2080:   __gmp_expr & operator=(unsigned long int l)
        !          2081:   { mpf_set_ui(mp, l); return *this; }
        !          2082:
        !          2083: #ifdef MPIRXX_HAVE_LLONG
        !          2084:   __gmp_expr & operator=(signed long long int l)
        !          2085:   { mpf_set_si(mp, l); return *this; }
        !          2086:   __gmp_expr & operator=(unsigned long long int l)
        !          2087:   { mpf_set_ui(mp, l); return *this; }
        !          2088: #endif
        !          2089:
        !          2090:   __gmp_expr & operator=(float f) { mpf_set_d(mp, f); return *this; }
        !          2091:   __gmp_expr & operator=(double d) { mpf_set_d(mp, d); return *this; }
        !          2092:   // __gmp_expr & operator=(long double ld)
        !          2093:   // { mpf_set_ld(mp, ld); return *this; }
        !          2094:
        !          2095:   __gmp_expr & operator=(const char *s)
        !          2096:   {
        !          2097:     if (mpf_set_str (mp, s, 0) != 0)
        !          2098:       throw std::invalid_argument ("mpf_set_str");
        !          2099:     return *this;
        !          2100:   }
        !          2101:   __gmp_expr & operator=(const std::string &s)
        !          2102:   {
        !          2103:     if (mpf_set_str(mp, s.c_str(), 0) != 0)
        !          2104:       throw std::invalid_argument ("mpf_set_str");
        !          2105:     return *this;
        !          2106:   }
        !          2107:
        !          2108:   // string input/output functions
        !          2109:   int set_str(const char *s, int base)
        !          2110:   { return mpf_set_str(mp, s, base); }
        !          2111:   int set_str(const std::string &s, int base)
        !          2112:   { return mpf_set_str(mp, s.c_str(), base); }
        !          2113:   std::string get_str(mp_exp_t &expo, int base = 10, size_t size = 0) const
        !          2114:   {
        !          2115:     __gmp_alloc_cstring temp(mpf_get_str(0, &expo, base, size, mp));
        !          2116:     return std::string(temp.str);
        !          2117:   }
        !          2118:
        !          2119:   // conversion functions
        !          2120:   mpf_srcptr __get_mp() const { return mp; }
        !          2121:   mpf_ptr __get_mp() { return mp; }
        !          2122:   mpf_srcptr get_mpf_t() const { return mp; }
        !          2123:   mpf_ptr get_mpf_t() { return mp; }
        !          2124:
        !          2125:   mpir_si get_si() const { return mpf_get_si(mp); }
        !          2126:   mpir_ui get_ui() const { return mpf_get_ui(mp); }
        !          2127:   double get_d() const { return mpf_get_d(mp); }
        !          2128:
        !          2129:   // bool fits_schar_p() const { return mpf_fits_schar_p(mp); }
        !          2130:   // bool fits_uchar_p() const { return mpf_fits_uchar_p(mp); }
        !          2131:   bool fits_sint_p() const { return mpf_fits_sint_p(mp); }
        !          2132:   bool fits_uint_p() const { return mpf_fits_uint_p(mp); }
        !          2133:   bool fits_si_p() const { return mpf_fits_si_p(mp); }
        !          2134:   bool fits_ui_p() const { return mpf_fits_ui_p(mp); }
        !          2135:   bool fits_sshort_p() const { return mpf_fits_sshort_p(mp); }
        !          2136:   bool fits_ushort_p() const { return mpf_fits_ushort_p(mp); }
        !          2137:   bool fits_slong_p() const { return mpf_fits_slong_p(mp); }
        !          2138:   bool fits_ulong_p() const { return mpf_fits_ulong_p(mp); }
        !          2139:   // bool fits_float_p() const { return mpf_fits_float_p(mp); }
        !          2140:   // bool fits_double_p() const { return mpf_fits_double_p(mp); }
        !          2141:   // bool fits_ldouble_p() const { return mpf_fits_ldouble_p(mp); }
        !          2142:
        !          2143:   // compound assignments
        !          2144:   __GMP_DECLARE_COMPOUND_OPERATOR(operator+=)
        !          2145:   __GMP_DECLARE_COMPOUND_OPERATOR(operator-=)
        !          2146:   __GMP_DECLARE_COMPOUND_OPERATOR(operator*=)
        !          2147:   __GMP_DECLARE_COMPOUND_OPERATOR(operator/=)
        !          2148:
        !          2149:   __GMP_DECLARE_COMPOUND_OPERATOR_UI(operator<<=)
        !          2150:   __GMP_DECLARE_COMPOUND_OPERATOR_UI(operator>>=)
        !          2151:
        !          2152:   __GMP_DECLARE_INCREMENT_OPERATOR(operator++)
        !          2153:   __GMP_DECLARE_INCREMENT_OPERATOR(operator--)
        !          2154: };
        !          2155:
        !          2156: typedef __gmp_expr<mpf_t, mpf_t> mpf_class;
        !          2157:
        !          2158: /**************** I/O operators ****************/
        !          2159:
        !          2160: // these should (and will) be provided separately
        !          2161:
        !          2162: template <class T>
        !          2163: inline std::ostream & operator<<
        !          2164: (std::ostream &o, const __gmp_expr<T, T> &expr)
        !          2165: {
        !          2166:   return o << expr.__get_mp();
        !          2167: }
        !          2168:
        !          2169: template <class T, class U>
        !          2170: inline std::ostream & operator<<
        !          2171: (std::ostream &o, const __gmp_expr<T, U> &expr)
        !          2172: {
        !          2173:   __gmp_expr<T, T> temp(expr);
        !          2174:   return o << temp.__get_mp();
        !          2175: }
        !          2176:
        !          2177:
        !          2178: template <class T>
        !          2179: inline std::istream & operator>>(std::istream &i, __gmp_expr<T, T> &expr)
        !          2180: {
        !          2181:   return i >> expr.__get_mp();
        !          2182: }
        !          2183:
        !          2184: inline std::istream & operator>>(std::istream &i, mpq_class &q)
        !          2185: {
        !          2186:   i >> q.get_mpq_t();
        !          2187:   // q.canonicalize(); // you might want to uncomment this
        !          2188:   return i;
        !          2189: }
        !          2190:
        !          2191:
        !          2192: /**************** Functions for type conversion ****************/
        !          2193:
        !          2194: template <>
        !          2195: inline void __gmp_set_expr(mpz_ptr z, const mpz_class &w)
        !          2196: {
        !          2197:   mpz_set(z, w.get_mpz_t());
        !          2198: }
        !          2199:
        !          2200: template <class T>
        !          2201: inline void __gmp_set_expr(mpz_ptr z, const __gmp_expr<mpz_t, T> &expr)
        !          2202: {
        !          2203:   expr.eval(z);
        !          2204: }
        !          2205:
        !          2206: template <>
        !          2207: inline void __gmp_set_expr(mpz_ptr z, const mpq_class &q)
        !          2208: {
        !          2209:   mpz_set_q(z, q.get_mpq_t());
        !          2210: }
        !          2211:
        !          2212: template <class T>
        !          2213: inline void __gmp_set_expr(mpz_ptr z, const __gmp_expr<mpq_t, T> &expr)
        !          2214: {
        !          2215:   mpq_class temp(expr);
        !          2216:   mpz_set_q(z, temp.get_mpq_t());
        !          2217: }
        !          2218:
        !          2219: template <class T>
        !          2220: inline void __gmp_set_expr(mpz_ptr z, const mpf_class &f)
        !          2221: {
        !          2222:   mpz_set_f(z, f.get_mpf_t());
        !          2223: }
        !          2224:
        !          2225: template <class T>
        !          2226: inline void __gmp_set_expr(mpz_ptr z, const __gmp_expr<mpf_t, T> &expr)
        !          2227: {
        !          2228:   mpf_class temp(expr);
        !          2229:   mpz_set_f(z, temp.get_mpf_t());
        !          2230: }
        !          2231:
        !          2232: template <>
        !          2233: inline void __gmp_set_expr(mpq_ptr q, const mpz_class &z)
        !          2234: {
        !          2235:   mpq_set_z(q, z.get_mpz_t());
        !          2236: }
        !          2237:
        !          2238: template <class T>
        !          2239: inline void __gmp_set_expr(mpq_ptr q, const __gmp_expr<mpz_t, T> &expr)
        !          2240: {
        !          2241:   mpz_class temp(expr);
        !          2242:   mpq_set_z(q, temp.get_mpz_t());
        !          2243: }
        !          2244:
        !          2245: template <>
        !          2246: inline void __gmp_set_expr(mpq_ptr q, const mpq_class &r)
        !          2247: {
        !          2248:   mpq_set(q, r.get_mpq_t());
        !          2249: }
        !          2250:
        !          2251: template <class T>
        !          2252: inline void __gmp_set_expr(mpq_ptr q, const __gmp_expr<mpq_t, T> &expr)
        !          2253: {
        !          2254:   expr.eval(q);
        !          2255: }
        !          2256:
        !          2257: template <class T>
        !          2258: inline void __gmp_set_expr(mpq_ptr q, const mpf_class &f)
        !          2259: {
        !          2260:   mpq_set_f(q, f.get_mpf_t());
        !          2261: }
        !          2262:
        !          2263: template <class T>
        !          2264: inline void __gmp_set_expr(mpq_ptr q, const __gmp_expr<mpf_t, T> &expr)
        !          2265: {
        !          2266:   mpf_class temp(expr);
        !          2267:   mpq_set_f(q, temp.get_mpf_t());
        !          2268: }
        !          2269:
        !          2270: template <class T>
        !          2271: inline void __gmp_set_expr(mpf_ptr f, const mpz_class &z)
        !          2272: {
        !          2273:   mpf_set_z(f, z.get_mpz_t());
        !          2274: }
        !          2275:
        !          2276: template <class T>
        !          2277: inline void __gmp_set_expr(mpf_ptr f, const __gmp_expr<mpz_t, T> &expr)
        !          2278: {
        !          2279:   mpz_class temp(expr);
        !          2280:   mpf_set_z(f, temp.get_mpz_t());
        !          2281: }
        !          2282:
        !          2283: template <class T>
        !          2284: inline void __gmp_set_expr(mpf_ptr f, const mpq_class &q)
        !          2285: {
        !          2286:   mpf_set_q(f, q.get_mpq_t());
        !          2287: }
        !          2288:
        !          2289: template <class T>
        !          2290: inline void __gmp_set_expr(mpf_ptr f, const __gmp_expr<mpq_t, T> &expr)
        !          2291: {
        !          2292:   mpq_class temp(expr);
        !          2293:   mpf_set_q(f, temp.get_mpq_t());
        !          2294: }
        !          2295:
        !          2296: template <>
        !          2297: inline void __gmp_set_expr(mpf_ptr f, const mpf_class &g)
        !          2298: {
        !          2299:   mpf_set(f, g.get_mpf_t());
        !          2300: }
        !          2301:
        !          2302: template <class T>
        !          2303: inline void __gmp_set_expr(mpf_ptr f, const __gmp_expr<mpf_t, T> &expr)
        !          2304: {
        !          2305:   expr.eval(f, mpf_get_prec(f));
        !          2306: }
        !          2307:
        !          2308:
        !          2309: /**************** Specializations of __gmp_expr ****************/
        !          2310: /* The eval() method of __gmp_expr<T, U> evaluates the corresponding
        !          2311:    expression and assigns the result to its argument, which is either an
        !          2312:    mpz_t, mpq_t, or mpf_t as specified by the T argument.
        !          2313:    Compound expressions are evaluated recursively (temporaries are created
        !          2314:    to hold intermediate values), while for simple expressions the eval()
        !          2315:    method of the appropriate function object (available as the Op argument
        !          2316:    of either __gmp_unary_expr<T, Op> or __gmp_binary_expr<T, U, Op>) is
        !          2317:    called. */
        !          2318:
        !          2319:
        !          2320: /**************** Unary expressions ****************/
        !          2321: /* cases:
        !          2322:    - simple:   argument is mp*_class, that is, __gmp_expr<T, T>
        !          2323:    - compound: argument is __gmp_expr<T, U> (with U not equal to T) */
        !          2324:
        !          2325:
        !          2326: // simple expressions
        !          2327:
        !          2328: template <class T, class Op>
        !          2329: class __gmp_expr<T, __gmp_unary_expr<__gmp_expr<T, T>, Op> >
        !          2330: {
        !          2331: private:
        !          2332:   typedef __gmp_expr<T, T> val_type;
        !          2333:
        !          2334:   __gmp_unary_expr<val_type, Op> expr;
        !          2335: public:
        !          2336:   __gmp_expr(const val_type &val) : expr(val) { }
        !          2337:   void eval(typename __gmp_resolve_expr<T>::ptr_type p,
        !          2338:            mpir_ui = 0) const
        !          2339:   { Op::eval(p, expr.val.__get_mp()); }
        !          2340:   const val_type & get_val() const { return expr.val; }
        !          2341:   mp_bitcnt_t get_prec() const { return expr.val.get_prec(); }
        !          2342: };
        !          2343:
        !          2344:
        !          2345: // compound expressions
        !          2346:
        !          2347: template <class T, class U, class Op>
        !          2348: class __gmp_expr<T, __gmp_unary_expr<__gmp_expr<T, U>, Op> >
        !          2349: {
        !          2350: private:
        !          2351:   typedef __gmp_expr<T, U> val_type;
        !          2352:
        !          2353:   __gmp_unary_expr<val_type, Op> expr;
        !          2354: public:
        !          2355:   __gmp_expr(const val_type &val) : expr(val) { }
        !          2356:   void eval(typename __gmp_resolve_expr<T>::ptr_type p) const
        !          2357:   { __gmp_expr<T, T> temp(expr.val); Op::eval(p, temp.__get_mp()); }
        !          2358:   void eval(typename __gmp_resolve_expr<T>::ptr_type p,
        !          2359:            mp_bitcnt_t prec) const
        !          2360:   { __gmp_expr<T, T> temp(expr.val, prec); Op::eval(p, temp.__get_mp()); }
        !          2361:   const val_type & get_val() const { return expr.val; }
        !          2362:   mp_bitcnt_t get_prec() const { return expr.val.get_prec(); }
        !          2363: };
        !          2364:
        !          2365:
        !          2366: /**************** Binary expressions ****************/
        !          2367: /* simple:
        !          2368:    - arguments are both mp*_class
        !          2369:    - one argument is mp*_class, one is a built-in type
        !          2370:    compound:
        !          2371:    - one is mp*_class, one is __gmp_expr<T, U>
        !          2372:    - one is __gmp_expr<T, U>, one is built-in
        !          2373:    - both arguments are __gmp_expr<...> */
        !          2374:
        !          2375:
        !          2376: // simple expressions
        !          2377:
        !          2378: template <class T, class Op>
        !          2379: class __gmp_expr
        !          2380: <T, __gmp_binary_expr<__gmp_expr<T, T>, __gmp_expr<T, T>, Op> >
        !          2381: {
        !          2382: private:
        !          2383:   typedef __gmp_expr<T, T> val1_type;
        !          2384:   typedef __gmp_expr<T, T> val2_type;
        !          2385:
        !          2386:   __gmp_binary_expr<val1_type, val2_type, Op> expr;
        !          2387: public:
        !          2388:   __gmp_expr(const val1_type &val1, const val2_type &val2)
        !          2389:     : expr(val1, val2) { }
        !          2390:   void eval(typename __gmp_resolve_expr<T>::ptr_type p,
        !          2391:            mpir_ui = 0) const
        !          2392:   { Op::eval(p, expr.val1.__get_mp(), expr.val2.__get_mp()); }
        !          2393:   const val1_type & get_val1() const { return expr.val1; }
        !          2394:   const val2_type & get_val2() const { return expr.val2; }
        !          2395:   mp_bitcnt_t get_prec() const
        !          2396:   {
        !          2397:     mp_bitcnt_t prec1 = expr.val1.get_prec(),
        !          2398:       prec2 = expr.val2.get_prec();
        !          2399:     return (prec1 > prec2) ? prec1 : prec2;
        !          2400:   }
        !          2401: };
        !          2402:
        !          2403:
        !          2404: // simple expressions, T is a built-in numerical type
        !          2405:
        !          2406: template <class T, class U, class Op>
        !          2407: class __gmp_expr<T, __gmp_binary_expr<__gmp_expr<T, T>, U, Op> >
        !          2408: {
        !          2409: private:
        !          2410:   typedef __gmp_expr<T, T> val1_type;
        !          2411:   typedef U val2_type;
        !          2412:
        !          2413:   __gmp_binary_expr<val1_type, val2_type, Op> expr;
        !          2414: public:
        !          2415:   __gmp_expr(const val1_type &val1, const val2_type &val2) : expr(val1, val2) { }
        !          2416:   void eval(typename __gmp_resolve_expr<T>::ptr_type p, mpir_ui = 0) const
        !          2417:   { Op::eval(p, expr.val1.__get_mp(), expr.val2); }
        !          2418:   const val1_type & get_val1() const { return expr.val1; }
        !          2419:   const val2_type & get_val2() const { return expr.val2; }
        !          2420:   mp_bitcnt_t get_prec() const { return expr.val1.get_prec(); }
        !          2421: };
        !          2422:
        !          2423: template <class T, class U, class Op>
        !          2424: class __gmp_expr<T, __gmp_binary_expr<U, __gmp_expr<T, T>, Op> >
        !          2425: {
        !          2426: private:
        !          2427:   typedef U val1_type;
        !          2428:   typedef __gmp_expr<T, T> val2_type;
        !          2429:
        !          2430:   __gmp_binary_expr<val1_type, val2_type, Op> expr;
        !          2431: public:
        !          2432:   __gmp_expr(const val1_type &val1, const val2_type &val2)
        !          2433:     : expr(val1, val2) { }
        !          2434:   void eval(typename __gmp_resolve_expr<T>::ptr_type p,
        !          2435:            mpir_ui = 0) const
        !          2436:   { Op::eval(p, expr.val1, expr.val2.__get_mp()); }
        !          2437:   const val1_type & get_val1() const { return expr.val1; }
        !          2438:   const val2_type & get_val2() const { return expr.val2; }
        !          2439:   mp_bitcnt_t get_prec() const { return expr.val2.get_prec(); }
        !          2440: };
        !          2441:
        !          2442:
        !          2443: // compound expressions, one argument is a subexpression
        !          2444:
        !          2445: template <class T, class U, class V, class Op>
        !          2446: class __gmp_expr
        !          2447: <T, __gmp_binary_expr<__gmp_expr<T, T>, __gmp_expr<U, V>, Op> >
        !          2448: {
        !          2449: private:
        !          2450:   typedef __gmp_expr<T, T> val1_type;
        !          2451:   typedef __gmp_expr<U, V> val2_type;
        !          2452:
        !          2453:   __gmp_binary_expr<val1_type, val2_type, Op> expr;
        !          2454: public:
        !          2455:   __gmp_expr(const val1_type &val1, const val2_type &val2)
        !          2456:     : expr(val1, val2) { }
        !          2457:   void eval(typename __gmp_resolve_expr<T>::ptr_type p) const
        !          2458:   {
        !          2459:     __gmp_expr<T, T> temp(expr.val2);
        !          2460:     Op::eval(p, expr.val1.__get_mp(), temp.__get_mp());
        !          2461:   }
        !          2462:   void eval(typename __gmp_resolve_expr<T>::ptr_type p,
        !          2463:            mp_bitcnt_t prec) const
        !          2464:   {
        !          2465:     __gmp_expr<T, T> temp(expr.val2, prec);
        !          2466:     Op::eval(p, expr.val1.__get_mp(), temp.__get_mp());
        !          2467:   }
        !          2468:   const val1_type & get_val1() const { return expr.val1; }
        !          2469:   const val2_type & get_val2() const { return expr.val2; }
        !          2470:   mp_bitcnt_t get_prec() const
        !          2471:   {
        !          2472:     mp_bitcnt_t prec1 = expr.val1.get_prec(),
        !          2473:       prec2 = expr.val2.get_prec();
        !          2474:     return (prec1 > prec2) ? prec1 : prec2;
        !          2475:   }
        !          2476: };
        !          2477:
        !          2478: template <class T, class U, class V, class Op>
        !          2479: class __gmp_expr
        !          2480: <T, __gmp_binary_expr<__gmp_expr<U, V>, __gmp_expr<T, T>, Op> >
        !          2481: {
        !          2482: private:
        !          2483:   typedef __gmp_expr<U, V> val1_type;
        !          2484:   typedef __gmp_expr<T, T> val2_type;
        !          2485:
        !          2486:   __gmp_binary_expr<val1_type, val2_type, Op> expr;
        !          2487: public:
        !          2488:   __gmp_expr(const val1_type &val1, const val2_type &val2)
        !          2489:     : expr(val1, val2) { }
        !          2490:   void eval(typename __gmp_resolve_expr<T>::ptr_type p) const
        !          2491:   {
        !          2492:     __gmp_expr<T, T> temp(expr.val1);
        !          2493:     Op::eval(p, temp.__get_mp(), expr.val2.__get_mp());
        !          2494:   }
        !          2495:   void eval(typename __gmp_resolve_expr<T>::ptr_type p,
        !          2496:            mp_bitcnt_t prec) const
        !          2497:   {
        !          2498:     __gmp_expr<T, T> temp(expr.val1, prec);
        !          2499:     Op::eval(p, temp.__get_mp(), expr.val2.__get_mp());
        !          2500:   }
        !          2501:   const val1_type & get_val1() const { return expr.val1; }
        !          2502:   const val2_type & get_val2() const { return expr.val2; }
        !          2503:   mp_bitcnt_t get_prec() const
        !          2504:   {
        !          2505:     mp_bitcnt_t prec1 = expr.val1.get_prec(),
        !          2506:       prec2 = expr.val2.get_prec();
        !          2507:     return (prec1 > prec2) ? prec1 : prec2;
        !          2508:   }
        !          2509: };
        !          2510:
        !          2511: template <class T, class U, class Op>
        !          2512: class __gmp_expr
        !          2513: <T, __gmp_binary_expr<__gmp_expr<T, T>, __gmp_expr<T, U>, Op> >
        !          2514: {
        !          2515: private:
        !          2516:   typedef __gmp_expr<T, T> val1_type;
        !          2517:   typedef __gmp_expr<T, U> val2_type;
        !          2518:
        !          2519:   __gmp_binary_expr<val1_type, val2_type, Op> expr;
        !          2520: public:
        !          2521:   __gmp_expr(const val1_type &val1, const val2_type &val2)
        !          2522:     : expr(val1, val2) { }
        !          2523:   void eval(typename __gmp_resolve_expr<T>::ptr_type p) const
        !          2524:   {
        !          2525:     __gmp_expr<T, T> temp(expr.val2);
        !          2526:     Op::eval(p, expr.val1.__get_mp(), temp.__get_mp());
        !          2527:   }
        !          2528:   void eval(typename __gmp_resolve_expr<T>::ptr_type p,
        !          2529:            mp_bitcnt_t prec) const
        !          2530:   {
        !          2531:     __gmp_expr<T, T> temp(expr.val2, prec);
        !          2532:     Op::eval(p, expr.val1.__get_mp(), temp.__get_mp());
        !          2533:   }
        !          2534:   const val1_type & get_val1() const { return expr.val1; }
        !          2535:   const val2_type & get_val2() const { return expr.val2; }
        !          2536:   mp_bitcnt_t get_prec() const
        !          2537:   {
        !          2538:     mp_bitcnt_t prec1 = expr.val1.get_prec(),
        !          2539:       prec2 = expr.val2.get_prec();
        !          2540:     return (prec1 > prec2) ? prec1 : prec2;
        !          2541:   }
        !          2542: };
        !          2543:
        !          2544: template <class T, class U, class Op>
        !          2545: class __gmp_expr
        !          2546: <T, __gmp_binary_expr<__gmp_expr<T, U>, __gmp_expr<T, T>, Op> >
        !          2547: {
        !          2548: private:
        !          2549:   typedef __gmp_expr<T, U> val1_type;
        !          2550:   typedef __gmp_expr<T, T> val2_type;
        !          2551:
        !          2552:   __gmp_binary_expr<val1_type, val2_type, Op> expr;
        !          2553: public:
        !          2554:   __gmp_expr(const val1_type &val1, const val2_type &val2)
        !          2555:     : expr(val1, val2) { }
        !          2556:   void eval(typename __gmp_resolve_expr<T>::ptr_type p) const
        !          2557:   {
        !          2558:     __gmp_expr<T, T> temp(expr.val1);
        !          2559:     Op::eval(p, temp.__get_mp(), expr.val2.__get_mp());
        !          2560:   }
        !          2561:   void eval(typename __gmp_resolve_expr<T>::ptr_type p,
        !          2562:            mp_bitcnt_t prec) const
        !          2563:   {
        !          2564:     __gmp_expr<T, T> temp(expr.val1, prec);
        !          2565:     Op::eval(p, temp.__get_mp(), expr.val2.__get_mp());
        !          2566:   }
        !          2567:   const val1_type & get_val1() const { return expr.val1; }
        !          2568:   const val2_type & get_val2() const { return expr.val2; }
        !          2569:   mp_bitcnt_t get_prec() const
        !          2570:   {
        !          2571:     mp_bitcnt_t prec1 = expr.val1.get_prec(),
        !          2572:       prec2 = expr.val2.get_prec();
        !          2573:     return (prec1 > prec2) ? prec1 : prec2;
        !          2574:   }
        !          2575: };
        !          2576:
        !          2577:
        !          2578: // one argument is a subexpression, one is a built-in
        !          2579:
        !          2580: template <class T, class U, class V, class Op>
        !          2581: class __gmp_expr<T, __gmp_binary_expr<__gmp_expr<T, U>, V, Op> >
        !          2582: {
        !          2583: private:
        !          2584:   typedef __gmp_expr<T, U> val1_type;
        !          2585:   typedef V val2_type;
        !          2586:
        !          2587:   __gmp_binary_expr<val1_type, val2_type, Op> expr;
        !          2588: public:
        !          2589:   __gmp_expr(const val1_type &val1, const val2_type &val2)
        !          2590:     : expr(val1, val2) { }
        !          2591:   void eval(typename __gmp_resolve_expr<T>::ptr_type p) const
        !          2592:   {
        !          2593:     __gmp_expr<T, T> temp(expr.val1);
        !          2594:     Op::eval(p, temp.__get_mp(), expr.val2);
        !          2595:   }
        !          2596:   void eval(typename __gmp_resolve_expr<T>::ptr_type p,
        !          2597:            mp_bitcnt_t prec) const
        !          2598:   {
        !          2599:     __gmp_expr<T, T> temp(expr.val1, prec);
        !          2600:     Op::eval(p, temp.__get_mp(), expr.val2);
        !          2601:   }
        !          2602:   const val1_type & get_val1() const { return expr.val1; }
        !          2603:   const val2_type & get_val2() const { return expr.val2; }
        !          2604:   mp_bitcnt_t get_prec() const { return expr.val1.get_prec(); }
        !          2605: };
        !          2606:
        !          2607: template <class T, class U, class V, class Op>
        !          2608: class __gmp_expr<T, __gmp_binary_expr<U, __gmp_expr<T, V>, Op> >
        !          2609: {
        !          2610: private:
        !          2611:   typedef U val1_type;
        !          2612:   typedef __gmp_expr<T, V> val2_type;
        !          2613:
        !          2614:   __gmp_binary_expr<val1_type, val2_type, Op> expr;
        !          2615: public:
        !          2616:   __gmp_expr(const val1_type &val1, const val2_type &val2)
        !          2617:     : expr(val1, val2) { }
        !          2618:   void eval(typename __gmp_resolve_expr<T>::ptr_type p) const
        !          2619:   {
        !          2620:     __gmp_expr<T, T> temp(expr.val2);
        !          2621:     Op::eval(p, expr.val1, temp.__get_mp());
        !          2622:   }
        !          2623:   void eval(typename __gmp_resolve_expr<T>::ptr_type p,
        !          2624:            mp_bitcnt_t prec) const
        !          2625:   {
        !          2626:     __gmp_expr<T, T> temp(expr.val2, prec);
        !          2627:     Op::eval(p, expr.val1, temp.__get_mp());
        !          2628:   }
        !          2629:   const val1_type & get_val1() const { return expr.val1; }
        !          2630:   const val2_type & get_val2() const { return expr.val2; }
        !          2631:   mp_bitcnt_t get_prec() const { return expr.val2.get_prec(); }
        !          2632: };
        !          2633:
        !          2634:
        !          2635: // both arguments are subexpressions
        !          2636:
        !          2637: template <class T, class U, class V, class W, class Op>
        !          2638: class __gmp_expr
        !          2639: <T, __gmp_binary_expr<__gmp_expr<T, U>, __gmp_expr<V, W>, Op> >
        !          2640: {
        !          2641: private:
        !          2642:   typedef __gmp_expr<T, U> val1_type;
        !          2643:   typedef __gmp_expr<V, W> val2_type;
        !          2644:
        !          2645:   __gmp_binary_expr<val1_type, val2_type, Op> expr;
        !          2646: public:
        !          2647:   __gmp_expr(const val1_type &val1, const val2_type &val2)
        !          2648:     : expr(val1, val2) { }
        !          2649:   void eval(typename __gmp_resolve_expr<T>::ptr_type p) const
        !          2650:   {
        !          2651:     __gmp_expr<T, T> temp1(expr.val1), temp2(expr.val2);
        !          2652:     Op::eval(p, temp1.__get_mp(), temp2.__get_mp());
        !          2653:   }
        !          2654:   void eval(typename __gmp_resolve_expr<T>::ptr_type p,
        !          2655:            mp_bitcnt_t prec) const
        !          2656:   {
        !          2657:     __gmp_expr<T, T> temp1(expr.val1, prec), temp2(expr.val2, prec);
        !          2658:     Op::eval(p, temp1.__get_mp(), temp2.__get_mp());
        !          2659:   }
        !          2660:   const val1_type & get_val1() const { return expr.val1; }
        !          2661:   const val2_type & get_val2() const { return expr.val2; }
        !          2662:   mp_bitcnt_t get_prec() const
        !          2663:   {
        !          2664:     mp_bitcnt_t prec1 = expr.val1.get_prec(),
        !          2665:       prec2 = expr.val2.get_prec();
        !          2666:     return (prec1 > prec2) ? prec1 : prec2;
        !          2667:   }
        !          2668: };
        !          2669:
        !          2670: template <class T, class U, class V, class W, class Op>
        !          2671: class __gmp_expr
        !          2672: <T, __gmp_binary_expr<__gmp_expr<U, V>, __gmp_expr<T, W>, Op> >
        !          2673: {
        !          2674: private:
        !          2675:   typedef __gmp_expr<U, V> val1_type;
        !          2676:   typedef __gmp_expr<T, W> val2_type;
        !          2677:
        !          2678:   __gmp_binary_expr<val1_type, val2_type, Op> expr;
        !          2679: public:
        !          2680:   __gmp_expr(const val1_type &val1, const val2_type &val2)
        !          2681:     : expr(val1, val2) { }
        !          2682:   void eval(typename __gmp_resolve_expr<T>::ptr_type p) const
        !          2683:   {
        !          2684:     __gmp_expr<T, T> temp1(expr.val1), temp2(expr.val2);
        !          2685:     Op::eval(p, temp1.__get_mp(), temp2.__get_mp());
        !          2686:   }
        !          2687:   void eval(typename __gmp_resolve_expr<T>::ptr_type p,
        !          2688:            mp_bitcnt_t prec) const
        !          2689:   {
        !          2690:     __gmp_expr<T, T> temp1(expr.val1, prec), temp2(expr.val2, prec);
        !          2691:     Op::eval(p, temp1.__get_mp(), temp2.__get_mp());
        !          2692:   }
        !          2693:   const val1_type & get_val1() const { return expr.val1; }
        !          2694:   const val2_type & get_val2() const { return expr.val2; }
        !          2695:   mp_bitcnt_t get_prec() const
        !          2696:   {
        !          2697:     mp_bitcnt_t prec1 = expr.val1.get_prec(),
        !          2698:       prec2 = expr.val2.get_prec();
        !          2699:     return (prec1 > prec2) ? prec1 : prec2;
        !          2700:   }
        !          2701: };
        !          2702:
        !          2703: template <class T, class U, class V, class Op>
        !          2704: class __gmp_expr
        !          2705: <T, __gmp_binary_expr<__gmp_expr<T, U>, __gmp_expr<T, V>, Op> >
        !          2706: {
        !          2707: private:
        !          2708:   typedef __gmp_expr<T, U> val1_type;
        !          2709:   typedef __gmp_expr<T, V> val2_type;
        !          2710:
        !          2711:   __gmp_binary_expr<val1_type, val2_type, Op> expr;
        !          2712: public:
        !          2713:   __gmp_expr(const val1_type &val1, const val2_type &val2)
        !          2714:     : expr(val1, val2) { }
        !          2715:   void eval(typename __gmp_resolve_expr<T>::ptr_type p) const
        !          2716:   {
        !          2717:     __gmp_expr<T, T> temp1(expr.val1), temp2(expr.val2);
        !          2718:     Op::eval(p, temp1.__get_mp(), temp2.__get_mp());
        !          2719:   }
        !          2720:   void eval(typename __gmp_resolve_expr<T>::ptr_type p,
        !          2721:            mp_bitcnt_t prec) const
        !          2722:   {
        !          2723:     __gmp_expr<T, T> temp1(expr.val1, prec), temp2(expr.val2, prec);
        !          2724:     Op::eval(p, temp1.__get_mp(), temp2.__get_mp());
        !          2725:   }
        !          2726:   const val1_type & get_val1() const { return expr.val1; }
        !          2727:   const val2_type & get_val2() const { return expr.val2; }
        !          2728:   mp_bitcnt_t get_prec() const
        !          2729:   {
        !          2730:     mp_bitcnt_t prec1 = expr.val1.get_prec(),
        !          2731:       prec2 = expr.val2.get_prec();
        !          2732:     return (prec1 > prec2) ? prec1 : prec2;
        !          2733:   }
        !          2734: };
        !          2735:
        !          2736:
        !          2737: /**************** Special cases ****************/
        !          2738:
        !          2739: /* Some operations (i.e., add and subtract) with mixed mpz/mpq arguments
        !          2740:    can be done directly without first converting the mpz to mpq.
        !          2741:    Appropriate specializations of __gmp_expr are required. */
        !          2742:
        !          2743:
        !          2744: #define __GMPZQ_DEFINE_EXPR(eval_fun)                                       \
        !          2745:                                                                             \
        !          2746: template <>                                                                 \
        !          2747: class __gmp_expr<mpq_t, __gmp_binary_expr<mpz_class, mpq_class, eval_fun> > \
        !          2748: {                                                                           \
        !          2749: private:                                                                    \
        !          2750:   typedef mpz_class val1_type;                                              \
        !          2751:   typedef mpq_class val2_type;                                              \
        !          2752:                                                                             \
        !          2753:   __gmp_binary_expr<val1_type, val2_type, eval_fun> expr;                   \
        !          2754: public:                                                                     \
        !          2755:   __gmp_expr(const val1_type &val1, const val2_type &val2)                  \
        !          2756:     : expr(val1, val2) { }                                                  \
        !          2757:   void eval(mpq_ptr q) const                                                \
        !          2758:   { eval_fun::eval(q, expr.val1.get_mpz_t(), expr.val2.get_mpq_t()); }      \
        !          2759:   const val1_type & get_val1() const { return expr.val1; }                  \
        !          2760:   const val2_type & get_val2() const { return expr.val2; }                  \
        !          2761:   mp_bitcnt_t get_prec() const { return mpf_get_default_prec(); }     \
        !          2762: };                                                                          \
        !          2763:                                                                             \
        !          2764: template <>                                                                 \
        !          2765: class __gmp_expr<mpq_t, __gmp_binary_expr<mpq_class, mpz_class, eval_fun> > \
        !          2766: {                                                                           \
        !          2767: private:                                                                    \
        !          2768:   typedef mpq_class val1_type;                                              \
        !          2769:   typedef mpz_class val2_type;                                              \
        !          2770:                                                                             \
        !          2771:   __gmp_binary_expr<val1_type, val2_type, eval_fun> expr;                   \
        !          2772: public:                                                                     \
        !          2773:   __gmp_expr(const val1_type &val1, const val2_type &val2)                  \
        !          2774:     : expr(val1, val2) { }                                                  \
        !          2775:   void eval(mpq_ptr q) const                                                \
        !          2776:   { eval_fun::eval(q, expr.val1.get_mpq_t(), expr.val2.get_mpz_t()); }      \
        !          2777:   const val1_type & get_val1() const { return expr.val1; }                  \
        !          2778:   const val2_type & get_val2() const { return expr.val2; }                  \
        !          2779:   mp_bitcnt_t get_prec() const { return mpf_get_default_prec(); }     \
        !          2780: };                                                                          \
        !          2781:                                                                             \
        !          2782: template <class T>                                                          \
        !          2783: class __gmp_expr                                                            \
        !          2784: <mpq_t, __gmp_binary_expr<mpz_class, __gmp_expr<mpq_t, T>, eval_fun> >      \
        !          2785: {                                                                           \
        !          2786: private:                                                                    \
        !          2787:   typedef mpz_class val1_type;                                              \
        !          2788:   typedef __gmp_expr<mpq_t, T> val2_type;                                   \
        !          2789:                                                                             \
        !          2790:   __gmp_binary_expr<val1_type, val2_type, eval_fun> expr;                   \
        !          2791: public:                                                                     \
        !          2792:   __gmp_expr(const val1_type &val1, const val2_type &val2)                  \
        !          2793:     : expr(val1, val2) { }                                                  \
        !          2794:   void eval(mpq_ptr q) const                                                \
        !          2795:   {                                                                         \
        !          2796:     mpq_class temp(expr.val2);                                              \
        !          2797:     eval_fun::eval(q, expr.val1.get_mpz_t(), temp.get_mpq_t());             \
        !          2798:   }                                                                         \
        !          2799:   const val1_type & get_val1() const { return expr.val1; }                  \
        !          2800:   const val2_type & get_val2() const { return expr.val2; }                  \
        !          2801:   mp_bitcnt_t get_prec() const { return mpf_get_default_prec(); }     \
        !          2802: };                                                                          \
        !          2803:                                                                             \
        !          2804: template <class T>                                                          \
        !          2805: class __gmp_expr                                                            \
        !          2806: <mpq_t, __gmp_binary_expr<mpq_class, __gmp_expr<mpz_t, T>, eval_fun> >      \
        !          2807: {                                                                           \
        !          2808: private:                                                                    \
        !          2809:   typedef mpq_class val1_type;                                              \
        !          2810:   typedef __gmp_expr<mpz_t, T> val2_type;                                   \
        !          2811:                                                                             \
        !          2812:   __gmp_binary_expr<val1_type, val2_type, eval_fun> expr;                   \
        !          2813: public:                                                                     \
        !          2814:   __gmp_expr(const val1_type &val1, const val2_type &val2)                  \
        !          2815:     : expr(val1, val2) { }                                                  \
        !          2816:   void eval(mpq_ptr q) const                                                \
        !          2817:   {                                                                         \
        !          2818:     mpz_class temp(expr.val2);                                              \
        !          2819:     eval_fun::eval(q, expr.val1.get_mpq_t(), temp.get_mpz_t());             \
        !          2820:   }                                                                         \
        !          2821:   const val1_type & get_val1() const { return expr.val1; }                  \
        !          2822:   const val2_type & get_val2() const { return expr.val2; }                  \
        !          2823:   mp_bitcnt_t get_prec() const { return mpf_get_default_prec(); }     \
        !          2824: };                                                                          \
        !          2825:                                                                             \
        !          2826: template <class T>                                                          \
        !          2827: class __gmp_expr                                                            \
        !          2828: <mpq_t, __gmp_binary_expr<__gmp_expr<mpz_t, T>, mpq_class, eval_fun> >      \
        !          2829: {                                                                           \
        !          2830: private:                                                                    \
        !          2831:   typedef __gmp_expr<mpz_t, T> val1_type;                                   \
        !          2832:   typedef mpq_class val2_type;                                              \
        !          2833:                                                                             \
        !          2834:   __gmp_binary_expr<val1_type, val2_type, eval_fun> expr;                   \
        !          2835: public:                                                                     \
        !          2836:   __gmp_expr(const val1_type &val1, const val2_type &val2)                  \
        !          2837:     : expr(val1, val2) { }                                                  \
        !          2838:   void eval(mpq_ptr q) const                                                \
        !          2839:   {                                                                         \
        !          2840:     mpz_class temp(expr.val1);                                              \
        !          2841:     eval_fun::eval(q, temp.get_mpz_t(), expr.val2.get_mpq_t());             \
        !          2842:   }                                                                         \
        !          2843:   const val1_type & get_val1() const { return expr.val1; }                  \
        !          2844:   const val2_type & get_val2() const { return expr.val2; }                  \
        !          2845:   mp_bitcnt_t get_prec() const { return mpf_get_default_prec(); }     \
        !          2846: };                                                                          \
        !          2847:                                                                             \
        !          2848: template <class T>                                                          \
        !          2849: class __gmp_expr                                                            \
        !          2850: <mpq_t, __gmp_binary_expr<__gmp_expr<mpq_t, T>, mpz_class, eval_fun> >      \
        !          2851: {                                                                           \
        !          2852: private:                                                                    \
        !          2853:   typedef __gmp_expr<mpq_t, T> val1_type;                                   \
        !          2854:   typedef mpz_class val2_type;                                              \
        !          2855:                                                                             \
        !          2856:   __gmp_binary_expr<val1_type, val2_type, eval_fun> expr;                   \
        !          2857: public:                                                                     \
        !          2858:   __gmp_expr(const val1_type &val1, const val2_type &val2)                  \
        !          2859:     : expr(val1, val2) { }                                                  \
        !          2860:   void eval(mpq_ptr q) const                                                \
        !          2861:   {                                                                         \
        !          2862:     mpq_class temp(expr.val1);                                              \
        !          2863:     eval_fun::eval(q, temp.get_mpq_t(), expr.val2.get_mpz_t());             \
        !          2864:   }                                                                         \
        !          2865:   const val1_type & get_val1() const { return expr.val1; }                  \
        !          2866:   const val2_type & get_val2() const { return expr.val2; }                  \
        !          2867:   mp_bitcnt_t get_prec() const { return mpf_get_default_prec(); }     \
        !          2868: };                                                                          \
        !          2869:                                                                             \
        !          2870: template <class T, class U>                                                 \
        !          2871: class __gmp_expr<mpq_t, __gmp_binary_expr                                   \
        !          2872: <__gmp_expr<mpz_t, T>, __gmp_expr<mpq_t, U>, eval_fun> >                    \
        !          2873: {                                                                           \
        !          2874: private:                                                                    \
        !          2875:   typedef __gmp_expr<mpz_t, T> val1_type;                                   \
        !          2876:   typedef __gmp_expr<mpq_t, U> val2_type;                                   \
        !          2877:                                                                             \
        !          2878:   __gmp_binary_expr<val1_type, val2_type, eval_fun> expr;                   \
        !          2879: public:                                                                     \
        !          2880:   __gmp_expr(const val1_type &val1, const val2_type &val2)                  \
        !          2881:     : expr(val1, val2) { }                                                  \
        !          2882:   void eval(mpq_ptr q) const                                                \
        !          2883:   {                                                                         \
        !          2884:     mpz_class temp1(expr.val1);                                             \
        !          2885:     mpq_class temp2(expr.val2);                                             \
        !          2886:     eval_fun::eval(q, temp1.get_mpz_t(), temp2.get_mpq_t());                \
        !          2887:   }                                                                         \
        !          2888:   const val1_type & get_val1() const { return expr.val1; }                  \
        !          2889:   const val2_type & get_val2() const { return expr.val2; }                  \
        !          2890:   mp_bitcnt_t get_prec() const { return mpf_get_default_prec(); }     \
        !          2891: };                                                                          \
        !          2892:                                                                             \
        !          2893: template <class T, class U>                                                 \
        !          2894: class __gmp_expr<mpq_t, __gmp_binary_expr                                   \
        !          2895: <__gmp_expr<mpq_t, T>, __gmp_expr<mpz_t, U>, eval_fun> >                    \
        !          2896: {                                                                           \
        !          2897: private:                                                                    \
        !          2898:   typedef __gmp_expr<mpq_t, T> val1_type;                                   \
        !          2899:   typedef __gmp_expr<mpz_t, U> val2_type;                                   \
        !          2900:                                                                             \
        !          2901:   __gmp_binary_expr<val1_type, val2_type, eval_fun> expr;                   \
        !          2902: public:                                                                     \
        !          2903:   __gmp_expr(const val1_type &val1, const val2_type &val2)                  \
        !          2904:     : expr(val1, val2) { }                                                  \
        !          2905:   void eval(mpq_ptr q) const                                                \
        !          2906:   {                                                                         \
        !          2907:     mpq_class temp1(expr.val1);                                             \
        !          2908:     mpz_class temp2(expr.val2);                                             \
        !          2909:     eval_fun::eval(q, temp1.get_mpq_t(), temp2.get_mpz_t());                \
        !          2910:   }                                                                         \
        !          2911:   const val1_type & get_val1() const { return expr.val1; }                  \
        !          2912:   const val2_type & get_val2() const { return expr.val2; }                  \
        !          2913:   mp_bitcnt_t get_prec() const { return mpf_get_default_prec(); }     \
        !          2914: };
        !          2915:
        !          2916:
        !          2917: __GMPZQ_DEFINE_EXPR(__gmp_binary_plus)
        !          2918: __GMPZQ_DEFINE_EXPR(__gmp_binary_minus)
        !          2919:
        !          2920: /**************** Macros for defining functions ****************/
        !          2921: /* Results of operators and functions are instances of __gmp_expr<T, U>.
        !          2922:    T determines the numerical type of the expression: it can be either
        !          2923:    mpz_t, mpq_t, or mpf_t.  When the arguments of a binary
        !          2924:    expression have different numerical types, __gmp_resolve_expr is used
        !          2925:    to determine the "larger" type.
        !          2926:    U is either __gmp_unary_expr<V, Op> or __gmp_binary_expr<V, W, Op>,
        !          2927:    where V and W are the arguments' types -- they can in turn be
        !          2928:    expressions, thus allowing to build compound expressions to any
        !          2929:    degree of complexity.
        !          2930:    Op is a function object that must have an eval() method accepting
        !          2931:    appropriate arguments.
        !          2932:    Actual evaluation of a __gmp_expr<T, U> object is done when it gets
        !          2933:    assigned to an mp*_class ("lazy" evaluation): this is done by calling
        !          2934:    its eval() method. */
        !          2935:
        !          2936:
        !          2937: // non-member unary operators and functions
        !          2938:
        !          2939: #define __GMP_DEFINE_UNARY_FUNCTION(fun, eval_fun)                           \
        !          2940:                                                                              \
        !          2941: template <class T, class U>                                                  \
        !          2942: inline __gmp_expr<T, __gmp_unary_expr<__gmp_expr<T, U>, eval_fun> >          \
        !          2943: fun(const __gmp_expr<T, U> &expr)                                            \
        !          2944: {                                                                            \
        !          2945:   return __gmp_expr<T, __gmp_unary_expr<__gmp_expr<T, U>, eval_fun> >(expr); \
        !          2946: }
        !          2947:
        !          2948: #define __GMP_DEFINE_UNARY_TYPE_FUNCTION(type, fun, eval_fun) \
        !          2949:                                                               \
        !          2950: template <class T, class U>                                   \
        !          2951: inline type fun(const __gmp_expr<T, U> &expr)                 \
        !          2952: {                                                             \
        !          2953:   typename __gmp_resolve_temp<T, T, U>::temp_type temp(expr); \
        !          2954:   return eval_fun::eval(temp.__get_mp());                     \
        !          2955: }
        !          2956:
        !          2957:
        !          2958: // non-member binary operators and functions
        !          2959:
        !          2960: #define __GMPP_DEFINE_BINARY_FUNCTION(fun, eval_fun)                   \
        !          2961:                                                                        \
        !          2962: template <class T, class U, class V, class W>                          \
        !          2963: inline __gmp_expr<typename __gmp_resolve_expr<T, V>::value_type,       \
        !          2964: __gmp_binary_expr<__gmp_expr<T, U>, __gmp_expr<V, W>, eval_fun> >      \
        !          2965: fun(const __gmp_expr<T, U> &expr1, const __gmp_expr<V, W> &expr2)      \
        !          2966: {                                                                      \
        !          2967:   return __gmp_expr<typename __gmp_resolve_expr<T, V>::value_type,     \
        !          2968:      __gmp_binary_expr<__gmp_expr<T, U>, __gmp_expr<V, W>, eval_fun> > \
        !          2969:     (expr1, expr2);                                                    \
        !          2970: }
        !          2971:
        !          2972: #define __GMPNN_DEFINE_BINARY_FUNCTION(fun, eval_fun, type, bigtype)       \
        !          2973:                                                                            \
        !          2974: template <class T, class U>                                                \
        !          2975: inline __gmp_expr                                                          \
        !          2976: <T, __gmp_binary_expr<__gmp_expr<T, U>, bigtype, eval_fun> >               \
        !          2977: fun(const __gmp_expr<T, U> &expr, type t)                                  \
        !          2978: {                                                                          \
        !          2979:   return __gmp_expr                                                        \
        !          2980:     <T, __gmp_binary_expr<__gmp_expr<T, U>, bigtype, eval_fun> >(expr, t); \
        !          2981: }                                                                          \
        !          2982:                                                                            \
        !          2983: template <class T, class U>                                                \
        !          2984: inline __gmp_expr                                                          \
        !          2985: <T, __gmp_binary_expr<bigtype, __gmp_expr<T, U>, eval_fun> >               \
        !          2986: fun(type t, const __gmp_expr<T, U> &expr)                                  \
        !          2987: {                                                                          \
        !          2988:   return __gmp_expr                                                        \
        !          2989:     <T, __gmp_binary_expr<bigtype, __gmp_expr<T, U>, eval_fun> >(t, expr); \
        !          2990: }
        !          2991:
        !          2992: #define __GMPNS_DEFINE_BINARY_FUNCTION(fun, eval_fun, type)          \
        !          2993: __GMPNN_DEFINE_BINARY_FUNCTION(fun, eval_fun, type, mpir_si)
        !          2994:
        !          2995: #define __GMPNU_DEFINE_BINARY_FUNCTION(fun, eval_fun, type)            \
        !          2996: __GMPNN_DEFINE_BINARY_FUNCTION(fun, eval_fun, type, mpir_ui)
        !          2997:
        !          2998: #define __GMPND_DEFINE_BINARY_FUNCTION(fun, eval_fun, type) \
        !          2999: __GMPNN_DEFINE_BINARY_FUNCTION(fun, eval_fun, type, double)
        !          3000:
        !          3001: #define __GMPNLD_DEFINE_BINARY_FUNCTION(fun, eval_fun, type)     \
        !          3002: __GMPNN_DEFINE_BINARY_FUNCTION(fun, eval_fun, type, long double)
        !          3003:
        !          3004: #ifdef MPIRXX_HAVE_LLONG
        !          3005: #define __GMPN_DEFINE_BINARY_FUNCTION(fun, eval_fun)              \
        !          3006: __GMPNS_DEFINE_BINARY_FUNCTION(fun, eval_fun, signed char)        \
        !          3007: __GMPNU_DEFINE_BINARY_FUNCTION(fun, eval_fun, unsigned char)      \
        !          3008: __GMPNS_DEFINE_BINARY_FUNCTION(fun, eval_fun, signed int)         \
        !          3009: __GMPNU_DEFINE_BINARY_FUNCTION(fun, eval_fun, unsigned int)       \
        !          3010: __GMPNS_DEFINE_BINARY_FUNCTION(fun, eval_fun, signed short int)   \
        !          3011: __GMPNU_DEFINE_BINARY_FUNCTION(fun, eval_fun, unsigned short int) \
        !          3012: __GMPNS_DEFINE_BINARY_FUNCTION(fun, eval_fun, signed long int)    \
        !          3013: __GMPNU_DEFINE_BINARY_FUNCTION(fun, eval_fun, unsigned long int)  \
        !          3014: __GMPNS_DEFINE_BINARY_FUNCTION(fun, eval_fun, signed long long int)    \
        !          3015: __GMPNU_DEFINE_BINARY_FUNCTION(fun, eval_fun, unsigned long long int)  \
        !          3016: __GMPND_DEFINE_BINARY_FUNCTION(fun, eval_fun, float)              \
        !          3017: __GMPND_DEFINE_BINARY_FUNCTION(fun, eval_fun, double)             \
        !          3018: __GMPNLD_DEFINE_BINARY_FUNCTION(fun, eval_fun, long double)
        !          3019: #else
        !          3020: #define __GMPN_DEFINE_BINARY_FUNCTION(fun, eval_fun)              \
        !          3021: __GMPNS_DEFINE_BINARY_FUNCTION(fun, eval_fun, signed char)        \
        !          3022: __GMPNU_DEFINE_BINARY_FUNCTION(fun, eval_fun, unsigned char)      \
        !          3023: __GMPNS_DEFINE_BINARY_FUNCTION(fun, eval_fun, signed int)         \
        !          3024: __GMPNU_DEFINE_BINARY_FUNCTION(fun, eval_fun, unsigned int)       \
        !          3025: __GMPNS_DEFINE_BINARY_FUNCTION(fun, eval_fun, signed short int)   \
        !          3026: __GMPNU_DEFINE_BINARY_FUNCTION(fun, eval_fun, unsigned short int) \
        !          3027: __GMPNS_DEFINE_BINARY_FUNCTION(fun, eval_fun, signed long int)    \
        !          3028: __GMPNU_DEFINE_BINARY_FUNCTION(fun, eval_fun, unsigned long int)  \
        !          3029: __GMPND_DEFINE_BINARY_FUNCTION(fun, eval_fun, float)              \
        !          3030: __GMPND_DEFINE_BINARY_FUNCTION(fun, eval_fun, double)             \
        !          3031: __GMPNLD_DEFINE_BINARY_FUNCTION(fun, eval_fun, long double)
        !          3032: #endif
        !          3033:
        !          3034: #define __GMP_DEFINE_BINARY_FUNCTION(fun, eval_fun) \
        !          3035: __GMPP_DEFINE_BINARY_FUNCTION(fun, eval_fun)        \
        !          3036: __GMPN_DEFINE_BINARY_FUNCTION(fun, eval_fun)
        !          3037:
        !          3038:
        !          3039: #define __GMP_DEFINE_BINARY_FUNCTION_UI(fun, eval_fun)                 \
        !          3040:                                                                        \
        !          3041: template <class T, class U>                                            \
        !          3042: inline __gmp_expr                                                      \
        !          3043: <T, __gmp_binary_expr<__gmp_expr<T, U>, mpir_ui, eval_fun> >            \
        !          3044: fun(const __gmp_expr<T, U> &expr, mpir_ui l)                            \
        !          3045: {                                                                      \
        !          3046:   return __gmp_expr<T, __gmp_binary_expr                               \
        !          3047:     <__gmp_expr<T, U>, mpir_ui, eval_fun> >(expr, l);                   \
        !          3048: }
        !          3049:
        !          3050:
        !          3051: #define __GMPP_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun)         \
        !          3052:                                                                         \
        !          3053: template <class T, class U, class V, class W>                           \
        !          3054: inline type fun(const __gmp_expr<T, U> &expr1,                          \
        !          3055:                const __gmp_expr<V, W> &expr2)                          \
        !          3056: {                                                                       \
        !          3057:   typedef typename __gmp_resolve_expr<T, V>::value_type eval_type;      \
        !          3058:   typename __gmp_resolve_temp<eval_type, T, U>::temp_type temp1(expr1); \
        !          3059:   typename __gmp_resolve_temp<eval_type, V, W>::temp_type temp2(expr2); \
        !          3060:   return eval_fun::eval(temp1.__get_mp(), temp2.__get_mp());            \
        !          3061: }
        !          3062:
        !          3063: #define __GMPNN_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun,   \
        !          3064:                                            type2, bigtype)        \
        !          3065:                                                                    \
        !          3066: template <class T, class U>                                        \
        !          3067: inline type fun(const __gmp_expr<T, U> &expr, type2 t)             \
        !          3068: {                                                                  \
        !          3069:   typename __gmp_resolve_temp<T, T, U>::temp_type temp(expr);      \
        !          3070:   return eval_fun::eval(temp.__get_mp(), static_cast<bigtype>(t)); \
        !          3071: }                                                                  \
        !          3072:                                                                    \
        !          3073: template <class T, class U>                                        \
        !          3074: inline type fun(type2 t, const __gmp_expr<T, U> &expr)             \
        !          3075: {                                                                  \
        !          3076:   typename __gmp_resolve_temp<T, T, U>::temp_type temp(expr);      \
        !          3077:   return eval_fun::eval(static_cast<bigtype>(t), temp.__get_mp()); \
        !          3078: }
        !          3079:
        !          3080: #define __GMPNS_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun, type2) \
        !          3081: __GMPNN_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun,                \
        !          3082:                                    type2, mpir_si)
        !          3083:
        !          3084: #define __GMPNU_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun, type2) \
        !          3085: __GMPNN_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun,                \
        !          3086:                                    type2, mpir_ui)
        !          3087:
        !          3088: #define __GMPND_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun, type2) \
        !          3089: __GMPNN_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun, type2, double)
        !          3090:
        !          3091: #define __GMPNLD_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun, type2)     \
        !          3092: __GMPNN_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun, type2, long double)
        !          3093:
        !          3094: #ifdef MPIRXX_HAVE_LLONG
        !          3095: #define __GMPN_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun)              \
        !          3096: __GMPNS_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun, signed char)        \
        !          3097: __GMPNU_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun, unsigned char)      \
        !          3098: __GMPNS_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun, signed int)         \
        !          3099: __GMPNU_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun, unsigned int)       \
        !          3100: __GMPNS_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun, signed short int)   \
        !          3101: __GMPNU_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun, unsigned short int) \
        !          3102: __GMPNS_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun, signed long int)    \
        !          3103: __GMPNU_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun, unsigned long int)  \
        !          3104: __GMPNS_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun, signed long long int)    \
        !          3105: __GMPNU_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun, unsigned long long int)  \
        !          3106: __GMPND_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun, float)              \
        !          3107: __GMPND_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun, double)             \
        !          3108: __GMPNLD_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun, long double)
        !          3109: #else
        !          3110: #define __GMPN_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun)              \
        !          3111: __GMPNS_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun, signed char)        \
        !          3112: __GMPNU_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun, unsigned char)      \
        !          3113: __GMPNS_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun, signed int)         \
        !          3114: __GMPNU_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun, unsigned int)       \
        !          3115: __GMPNS_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun, signed short int)   \
        !          3116: __GMPNU_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun, unsigned short int) \
        !          3117: __GMPNS_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun, signed long int)    \
        !          3118: __GMPNU_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun, unsigned long int)  \
        !          3119: __GMPND_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun, float)              \
        !          3120: __GMPND_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun, double)             \
        !          3121: __GMPNLD_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun, long double)
        !          3122: #endif
        !          3123:
        !          3124: #define __GMP_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun) \
        !          3125: __GMPP_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun)        \
        !          3126: __GMPN_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun)
        !          3127:
        !          3128:
        !          3129: // member operators
        !          3130:
        !          3131: #define __GMPP_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun)                 \
        !          3132:                                                                              \
        !          3133: template <class T, class U>                                                  \
        !          3134: inline type##_class & type##_class::fun(const __gmp_expr<T, U> &expr)        \
        !          3135: {                                                                            \
        !          3136:   __gmp_set_expr(mp, __gmp_expr<type##_t, __gmp_binary_expr                  \
        !          3137:                 <type##_class, __gmp_expr<T, U>, eval_fun> >(*this, expr)); \
        !          3138:   return *this;                                                              \
        !          3139: }
        !          3140:
        !          3141: #define __GMPNN_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun,    \
        !          3142:                                         type2, bigtype)         \
        !          3143:                                                                  \
        !          3144: inline type##_class & type##_class::fun(type2 t)                 \
        !          3145: {                                                                \
        !          3146:   __gmp_set_expr(mp, __gmp_expr<type##_t, __gmp_binary_expr      \
        !          3147:                 <type##_class, bigtype, eval_fun> >(*this, t)); \
        !          3148:   return *this;                                                  \
        !          3149: }
        !          3150:
        !          3151: #define __GMPNS_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun, type2) \
        !          3152: __GMPNN_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun,                \
        !          3153:                                 type2, mpir_si)
        !          3154:
        !          3155: #define __GMPNU_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun, type2) \
        !          3156: __GMPNN_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun,                \
        !          3157:                                 type2, mpir_ui)
        !          3158:
        !          3159: #define __GMPND_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun, type2) \
        !          3160: __GMPNN_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun, type2, double)
        !          3161:
        !          3162: #define __GMPNLD_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun, type2)     \
        !          3163: __GMPNN_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun, type2, long double)
        !          3164:
        !          3165: #ifdef MPIRXX_HAVE_LLONG
        !          3166: #define __GMPN_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun)              \
        !          3167: __GMPNS_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun, signed char)        \
        !          3168: __GMPNU_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun, unsigned char)      \
        !          3169: __GMPNS_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun, signed int)         \
        !          3170: __GMPNU_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun, unsigned int)       \
        !          3171: __GMPNS_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun, signed short int)   \
        !          3172: __GMPNU_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun, unsigned short int) \
        !          3173: __GMPNS_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun, signed long int)    \
        !          3174: __GMPNU_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun, unsigned long int)  \
        !          3175: __GMPNS_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun, signed long long int)    \
        !          3176: __GMPNU_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun, unsigned long long int)  \
        !          3177: __GMPND_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun, float)              \
        !          3178: __GMPND_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun, double)             \
        !          3179: /* __GMPNLD_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun, long double) */
        !          3180: #else
        !          3181: #define __GMPN_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun)              \
        !          3182: __GMPNS_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun, signed char)        \
        !          3183: __GMPNU_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun, unsigned char)      \
        !          3184: __GMPNS_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun, signed int)         \
        !          3185: __GMPNU_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun, unsigned int)       \
        !          3186: __GMPNS_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun, signed short int)   \
        !          3187: __GMPNU_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun, unsigned short int) \
        !          3188: __GMPNS_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun, signed long int)    \
        !          3189: __GMPNU_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun, unsigned long int)  \
        !          3190: __GMPND_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun, float)              \
        !          3191: __GMPND_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun, double)             \
        !          3192: /* __GMPNLD_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun, long double) */
        !          3193: #endif
        !          3194: #define __GMP_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun) \
        !          3195: __GMPP_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun)        \
        !          3196: __GMPN_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun)
        !          3197:
        !          3198: #define __GMPZ_DEFINE_COMPOUND_OPERATOR(fun, eval_fun) \
        !          3199: __GMP_DEFINE_COMPOUND_OPERATOR(mpz, fun, eval_fun)
        !          3200:
        !          3201: #define __GMPZZ_DEFINE_COMPOUND_OPERATOR(fun, eval_fun) \
        !          3202: __GMPP_DEFINE_COMPOUND_OPERATOR(mpz, fun, eval_fun)
        !          3203:
        !          3204: #define __GMPQ_DEFINE_COMPOUND_OPERATOR(fun, eval_fun) \
        !          3205: __GMP_DEFINE_COMPOUND_OPERATOR(mpq, fun, eval_fun)
        !          3206:
        !          3207: #define __GMPF_DEFINE_COMPOUND_OPERATOR(fun, eval_fun) \
        !          3208: __GMP_DEFINE_COMPOUND_OPERATOR(mpf, fun, eval_fun)
        !          3209:
        !          3210:
        !          3211:
        !          3212: #define __GMP_DEFINE_COMPOUND_OPERATOR_UI(type, fun, eval_fun)  \
        !          3213:                                                                 \
        !          3214: inline type##_class & type##_class::fun(mpir_ui l)               \
        !          3215: {                                                               \
        !          3216:   __gmp_set_expr(mp, __gmp_expr<type##_t, __gmp_binary_expr     \
        !          3217:     <type##_class, mpir_ui, eval_fun> >(*this, l));              \
        !          3218:   return *this;                                                 \
        !          3219: }
        !          3220:
        !          3221: #define __GMPZ_DEFINE_COMPOUND_OPERATOR_UI(fun, eval_fun) \
        !          3222: __GMP_DEFINE_COMPOUND_OPERATOR_UI(mpz, fun, eval_fun)
        !          3223:
        !          3224: #define __GMPQ_DEFINE_COMPOUND_OPERATOR_UI(fun, eval_fun) \
        !          3225: __GMP_DEFINE_COMPOUND_OPERATOR_UI(mpq, fun, eval_fun)
        !          3226:
        !          3227: #define __GMPF_DEFINE_COMPOUND_OPERATOR_UI(fun, eval_fun) \
        !          3228: __GMP_DEFINE_COMPOUND_OPERATOR_UI(mpf, fun, eval_fun)
        !          3229:
        !          3230:
        !          3231:
        !          3232: #define __GMP_DEFINE_INCREMENT_OPERATOR(type, fun, eval_fun) \
        !          3233:                                                              \
        !          3234: inline type##_class & type##_class::fun()                    \
        !          3235: {                                                            \
        !          3236:   eval_fun::eval(mp);                                        \
        !          3237:   return *this;                                              \
        !          3238: }                                                            \
        !          3239:                                                              \
        !          3240: inline type##_class type##_class::fun(int)                   \
        !          3241: {                                                            \
        !          3242:   type##_class temp(*this);                                  \
        !          3243:   eval_fun::eval(mp);                                        \
        !          3244:   return temp;                                               \
        !          3245: }
        !          3246:
        !          3247: #define __GMPZ_DEFINE_INCREMENT_OPERATOR(fun, eval_fun) \
        !          3248: __GMP_DEFINE_INCREMENT_OPERATOR(mpz, fun, eval_fun)
        !          3249:
        !          3250: #define __GMPQ_DEFINE_INCREMENT_OPERATOR(fun, eval_fun) \
        !          3251: __GMP_DEFINE_INCREMENT_OPERATOR(mpq, fun, eval_fun)
        !          3252:
        !          3253: #define __GMPF_DEFINE_INCREMENT_OPERATOR(fun, eval_fun) \
        !          3254: __GMP_DEFINE_INCREMENT_OPERATOR(mpf, fun, eval_fun)
        !          3255:
        !          3256:
        !          3257:
        !          3258: /**************** Arithmetic operators and functions ****************/
        !          3259:
        !          3260: // non-member operators and functions
        !          3261:
        !          3262: __GMP_DEFINE_UNARY_FUNCTION(operator+, __gmp_unary_plus)
        !          3263: __GMP_DEFINE_UNARY_FUNCTION(operator-, __gmp_unary_minus)
        !          3264: __GMP_DEFINE_UNARY_FUNCTION(operator~, __gmp_unary_com)
        !          3265:
        !          3266: __GMP_DEFINE_BINARY_FUNCTION(operator+, __gmp_binary_plus)
        !          3267: __GMP_DEFINE_BINARY_FUNCTION(operator-, __gmp_binary_minus)
        !          3268: __GMP_DEFINE_BINARY_FUNCTION(operator*, __gmp_binary_multiplies)
        !          3269: __GMP_DEFINE_BINARY_FUNCTION(operator/, __gmp_binary_divides)
        !          3270: __GMP_DEFINE_BINARY_FUNCTION(operator%, __gmp_binary_modulus)
        !          3271: __GMP_DEFINE_BINARY_FUNCTION(operator&, __gmp_binary_and)
        !          3272: __GMP_DEFINE_BINARY_FUNCTION(operator|, __gmp_binary_ior)
        !          3273: __GMP_DEFINE_BINARY_FUNCTION(operator^, __gmp_binary_xor)
        !          3274:
        !          3275: __GMP_DEFINE_BINARY_FUNCTION_UI(operator<<, __gmp_binary_lshift)
        !          3276: __GMP_DEFINE_BINARY_FUNCTION_UI(operator>>, __gmp_binary_rshift)
        !          3277:
        !          3278: __GMP_DEFINE_BINARY_TYPE_FUNCTION(bool, operator==, __gmp_binary_equal)
        !          3279: __GMP_DEFINE_BINARY_TYPE_FUNCTION(bool, operator!=, __gmp_binary_not_equal)
        !          3280: __GMP_DEFINE_BINARY_TYPE_FUNCTION(bool, operator<, __gmp_binary_less)
        !          3281: __GMP_DEFINE_BINARY_TYPE_FUNCTION(bool, operator<=, __gmp_binary_less_equal)
        !          3282: __GMP_DEFINE_BINARY_TYPE_FUNCTION(bool, operator>, __gmp_binary_greater)
        !          3283: __GMP_DEFINE_BINARY_TYPE_FUNCTION(bool, operator>=, \
        !          3284:                                   __gmp_binary_greater_equal)
        !          3285:
        !          3286: __GMP_DEFINE_UNARY_FUNCTION(abs, __gmp_abs_function)
        !          3287: __GMP_DEFINE_UNARY_FUNCTION(trunc, __gmp_trunc_function)
        !          3288: __GMP_DEFINE_UNARY_FUNCTION(floor, __gmp_floor_function)
        !          3289: __GMP_DEFINE_UNARY_FUNCTION(ceil, __gmp_ceil_function)
        !          3290: __GMP_DEFINE_UNARY_FUNCTION(sqrt, __gmp_sqrt_function)
        !          3291: __GMP_DEFINE_BINARY_FUNCTION(hypot, __gmp_hypot_function)
        !          3292:
        !          3293: __GMP_DEFINE_UNARY_TYPE_FUNCTION(int, sgn, __gmp_sgn_function)
        !          3294: __GMP_DEFINE_BINARY_TYPE_FUNCTION(int, cmp, __gmp_cmp_function)
        !          3295:
        !          3296: // member operators for mpz_class
        !          3297:
        !          3298: __GMPZ_DEFINE_COMPOUND_OPERATOR(operator+=, __gmp_binary_plus)
        !          3299: __GMPZ_DEFINE_COMPOUND_OPERATOR(operator-=, __gmp_binary_minus)
        !          3300: __GMPZ_DEFINE_COMPOUND_OPERATOR(operator*=, __gmp_binary_multiplies)
        !          3301: __GMPZ_DEFINE_COMPOUND_OPERATOR(operator/=, __gmp_binary_divides)
        !          3302: __GMPZ_DEFINE_COMPOUND_OPERATOR(operator%=, __gmp_binary_modulus)
        !          3303:
        !          3304: __GMPZZ_DEFINE_COMPOUND_OPERATOR(operator&=, __gmp_binary_and)
        !          3305: __GMPZZ_DEFINE_COMPOUND_OPERATOR(operator|=, __gmp_binary_ior)
        !          3306: __GMPZZ_DEFINE_COMPOUND_OPERATOR(operator^=, __gmp_binary_xor)
        !          3307:
        !          3308: __GMPZ_DEFINE_COMPOUND_OPERATOR_UI(operator<<=, __gmp_binary_lshift)
        !          3309: __GMPZ_DEFINE_COMPOUND_OPERATOR_UI(operator>>=, __gmp_binary_rshift)
        !          3310:
        !          3311: __GMPZ_DEFINE_INCREMENT_OPERATOR(operator++, __gmp_unary_increment)
        !          3312: __GMPZ_DEFINE_INCREMENT_OPERATOR(operator--, __gmp_unary_decrement)
        !          3313:
        !          3314: // member operators for mpq_class
        !          3315:
        !          3316: __GMPQ_DEFINE_COMPOUND_OPERATOR(operator+=, __gmp_binary_plus)
        !          3317: __GMPQ_DEFINE_COMPOUND_OPERATOR(operator-=, __gmp_binary_minus)
        !          3318: __GMPQ_DEFINE_COMPOUND_OPERATOR(operator*=, __gmp_binary_multiplies)
        !          3319: __GMPQ_DEFINE_COMPOUND_OPERATOR(operator/=, __gmp_binary_divides)
        !          3320:
        !          3321: __GMPQ_DEFINE_COMPOUND_OPERATOR_UI(operator<<=, __gmp_binary_lshift)
        !          3322: __GMPQ_DEFINE_COMPOUND_OPERATOR_UI(operator>>=, __gmp_binary_rshift)
        !          3323:
        !          3324: __GMPQ_DEFINE_INCREMENT_OPERATOR(operator++, __gmp_unary_increment)
        !          3325: __GMPQ_DEFINE_INCREMENT_OPERATOR(operator--, __gmp_unary_decrement)
        !          3326:
        !          3327: // member operators for mpf_class
        !          3328:
        !          3329: __GMPF_DEFINE_COMPOUND_OPERATOR(operator+=, __gmp_binary_plus)
        !          3330: __GMPF_DEFINE_COMPOUND_OPERATOR(operator-=, __gmp_binary_minus)
        !          3331: __GMPF_DEFINE_COMPOUND_OPERATOR(operator*=, __gmp_binary_multiplies)
        !          3332: __GMPF_DEFINE_COMPOUND_OPERATOR(operator/=, __gmp_binary_divides)
        !          3333:
        !          3334: __GMPF_DEFINE_COMPOUND_OPERATOR_UI(operator<<=, __gmp_binary_lshift)
        !          3335: __GMPF_DEFINE_COMPOUND_OPERATOR_UI(operator>>=, __gmp_binary_rshift)
        !          3336:
        !          3337: __GMPF_DEFINE_INCREMENT_OPERATOR(operator++, __gmp_unary_increment)
        !          3338: __GMPF_DEFINE_INCREMENT_OPERATOR(operator--, __gmp_unary_decrement)
        !          3339:
        !          3340:
        !          3341:
        !          3342: /**************** Class wrapper for gmp_randstate_t ****************/
        !          3343:
        !          3344: class __gmp_urandomb_value { };
        !          3345: class __gmp_urandomm_value { };
        !          3346:
        !          3347: template <>
        !          3348: class __gmp_expr<mpz_t, __gmp_urandomb_value>
        !          3349: {
        !          3350: private:
        !          3351:   __gmp_randstate_struct *state;
        !          3352:   mp_bitcnt_t bits;
        !          3353: public:
        !          3354:   __gmp_expr(gmp_randstate_t s, mp_bitcnt_t l) : state(s), bits(l) { }
        !          3355:   void eval(mpz_ptr z) const { __gmp_rand_function::eval(z, state, bits); }
        !          3356:   mp_bitcnt_t get_prec() const { return mpf_get_default_prec(); }
        !          3357: };
        !          3358:
        !          3359: template <>
        !          3360: class __gmp_expr<mpz_t, __gmp_urandomm_value>
        !          3361: {
        !          3362: private:
        !          3363:   __gmp_randstate_struct *state;
        !          3364:   mpz_class range;
        !          3365: public:
        !          3366:   __gmp_expr(gmp_randstate_t s, const mpz_class &z) : state(s), range(z) { }
        !          3367:   void eval(mpz_ptr z) const
        !          3368:   { __gmp_rand_function::eval(z, state, range.get_mpz_t()); }
        !          3369:   mp_bitcnt_t get_prec() const { return mpf_get_default_prec(); }
        !          3370: };
        !          3371:
        !          3372: template <>
        !          3373: class __gmp_expr<mpf_t, __gmp_urandomb_value>
        !          3374: {
        !          3375: private:
        !          3376:   __gmp_randstate_struct *state;
        !          3377:   mp_bitcnt_t bits;
        !          3378: public:
        !          3379:   __gmp_expr(gmp_randstate_t s, mp_bitcnt_t l) : state(s), bits(l) { }
        !          3380:   void eval(mpf_ptr f, mp_bitcnt_t prec) const
        !          3381:   { __gmp_rand_function::eval(f, state, (bits>0) ? get_prec() : prec); }
        !          3382:   mp_bitcnt_t get_prec() const
        !          3383:   {
        !          3384:     if (bits == 0)
        !          3385:       return mpf_get_default_prec();
        !          3386:     else
        !          3387:       return bits;
        !          3388:   }
        !          3389: };
        !          3390:
        !          3391: extern "C" {
        !          3392:   typedef void __gmp_randinit_default_t (gmp_randstate_t);
        !          3393:   typedef void __gmp_randinit_lc_2exp_t (gmp_randstate_t, mpz_srcptr, mpir_ui, mp_bitcnt_t);
        !          3394:   typedef int __gmp_randinit_lc_2exp_size_t (gmp_randstate_t, mp_bitcnt_t);
        !          3395: }
        !          3396:
        !          3397: class gmp_randclass
        !          3398: {
        !          3399: private:
        !          3400:   gmp_randstate_t state;
        !          3401:
        !          3402:   // copy construction and assignment not allowed
        !          3403:   gmp_randclass(const gmp_randclass &);
        !          3404:   void operator=(const gmp_randclass &);
        !          3405: public:
        !          3406:   // constructors and destructor
        !          3407:   gmp_randclass(gmp_randalg_t alg, mp_bitcnt_t size)
        !          3408:   {
        !          3409:     switch (alg)
        !          3410:       {
        !          3411:       case GMP_RAND_ALG_LC: // no other cases for now
        !          3412:       default:
        !          3413:        gmp_randinit_lc_2exp_size(state, size);
        !          3414:        break;
        !          3415:       }
        !          3416:   }
        !          3417:
        !          3418:   // gmp_randinit_default
        !          3419:   gmp_randclass(__gmp_randinit_default_t* f) { f(state); }
        !          3420:
        !          3421:   // gmp_randinit_lc_2exp
        !          3422:   gmp_randclass(__gmp_randinit_lc_2exp_t* f,
        !          3423:                mpz_class z, mpir_ui l1, mp_bitcnt_t l2)
        !          3424:   { f(state, z.get_mpz_t(), l1, l2); }
        !          3425:
        !          3426:   // gmp_randinit_lc_2exp_size
        !          3427:   gmp_randclass(__gmp_randinit_lc_2exp_size_t* f,
        !          3428:                mp_bitcnt_t size)
        !          3429:   {
        !          3430:     if (f (state, size) == 0)
        !          3431:       throw std::length_error ("gmp_randinit_lc_2exp_size");
        !          3432:   }
        !          3433:
        !          3434:   ~gmp_randclass() { gmp_randclear(state); }
        !          3435:
        !          3436:   // initialize
        !          3437:   void seed(); // choose a random seed some way (?)
        !          3438:   void seed(mpir_ui s) { gmp_randseed_ui(state, s); }
        !          3439:   void seed(const mpz_class &z) { gmp_randseed(state, z.get_mpz_t()); }
        !          3440:
        !          3441:   // get random number
        !          3442:   __gmp_expr<mpz_t, __gmp_urandomb_value> get_z_bits(mp_bitcnt_t l)
        !          3443:   { return __gmp_expr<mpz_t, __gmp_urandomb_value>(state, l); }
        !          3444:   __gmp_expr<mpz_t, __gmp_urandomb_value> get_z_bits(const mpz_class &z)
        !          3445:   { return get_z_bits(z.get_ui()); }
        !          3446:
        !          3447:   __gmp_expr<mpz_t, __gmp_urandomm_value> get_z_range(const mpz_class &z)
        !          3448:   { return __gmp_expr<mpz_t, __gmp_urandomm_value>(state, z); }
        !          3449:
        !          3450:   __gmp_expr<mpf_t, __gmp_urandomb_value> get_f(mp_bitcnt_t prec = 0)
        !          3451:   { return __gmp_expr<mpf_t, __gmp_urandomb_value>(state, prec); }
        !          3452: };
        !          3453:
        !          3454:
        !          3455: /**************** #undef all private macros ****************/
        !          3456:
        !          3457: #undef __GMPP_DECLARE_COMPOUND_OPERATOR
        !          3458: #undef __GMPN_DECLARE_COMPOUND_OPERATOR
        !          3459: #undef __GMP_DECLARE_COMPOUND_OPERATOR
        !          3460: #undef __GMP_DECLARE_COMPOUND_OPERATOR_UI
        !          3461: #undef __GMP_DECLARE_INCREMENT_OPERATOR
        !          3462:
        !          3463: #undef __GMPZQ_DEFINE_EXPR
        !          3464: #undef __GMP_DEFINE_TERNARY_EXPR
        !          3465:
        !          3466: #undef __GMP_DEFINE_UNARY_FUNCTION
        !          3467: #undef __GMP_DEFINE_UNARY_TYPE_FUNCTION
        !          3468:
        !          3469: #undef __GMPP_DEFINE_BINARY_FUNCTION
        !          3470: #undef __GMPNN_DEFINE_BINARY_FUNCTION
        !          3471: #undef __GMPNS_DEFINE_BINARY_FUNCTION
        !          3472: #undef __GMPNU_DEFINE_BINARY_FUNCTION
        !          3473: #undef __GMPND_DEFINE_BINARY_FUNCTION
        !          3474: #undef __GMPNLD_DEFINE_BINARY_FUNCTION
        !          3475: #undef __GMPN_DEFINE_BINARY_FUNCTION
        !          3476: #undef __GMP_DEFINE_BINARY_FUNCTION
        !          3477:
        !          3478: #undef __GMP_DEFINE_BINARY_FUNCTION_UI
        !          3479:
        !          3480: #undef __GMPP_DEFINE_BINARY_TYPE_FUNCTION
        !          3481: #undef __GMPNN_DEFINE_BINARY_TYPE_FUNCTION
        !          3482: #undef __GMPNS_DEFINE_BINARY_TYPE_FUNCTION
        !          3483: #undef __GMPNU_DEFINE_BINARY_TYPE_FUNCTION
        !          3484: #undef __GMPND_DEFINE_BINARY_TYPE_FUNCTION
        !          3485: #undef __GMPNLD_DEFINE_BINARY_TYPE_FUNCTION
        !          3486: #undef __GMPN_DEFINE_BINARY_TYPE_FUNCTION
        !          3487: #undef __GMP_DEFINE_BINARY_TYPE_FUNCTION
        !          3488:
        !          3489: #undef __GMPP_DECLARE_COMPOUND_OPERATOR
        !          3490: #undef __GMPN_DECLARE_COMPOUND_OPERATOR
        !          3491: #undef __GMP_DECLARE_COMPOUND_OPERATOR
        !          3492:
        !          3493: #undef __GMP_DECLARE_COMPOUND_OPERATOR_UI
        !          3494: #undef __GMP_DECLARE_INCREMENT_OPERATOR
        !          3495:
        !          3496: #undef __GMPZ_DEFINE_COMPOUND_OPERATOR
        !          3497: #undef __GMPZZ_DEFINE_COMPOUND_OPERATOR
        !          3498: #undef __GMPZN_DEFINE_COMPOUND_OPERATOR
        !          3499: #undef __GMPZNN_DEFINE_COMPOUND_OPERATOR
        !          3500: #undef __GMPZNS_DEFINE_COMPOUND_OPERATOR
        !          3501: #undef __GMPZNU_DEFINE_COMPOUND_OPERATOR
        !          3502: #undef __GMPZND_DEFINE_COMPOUND_OPERATOR
        !          3503: #undef __GMPZNLD_DEFINE_COMPOUND_OPERATOR
        !          3504:
        !          3505: #undef __GMPP_DEFINE_COMPOUND_OPERATOR
        !          3506: #undef __GMPNN_DEFINE_COMPOUND_OPERATOR
        !          3507: #undef __GMPNS_DEFINE_COMPOUND_OPERATOR
        !          3508: #undef __GMPNU_DEFINE_COMPOUND_OPERATOR
        !          3509: #undef __GMPND_DEFINE_COMPOUND_OPERATOR
        !          3510: #undef __GMPNLD_DEFINE_COMPOUND_OPERATOR
        !          3511: #undef __GMPN_DEFINE_COMPOUND_OPERATOR
        !          3512: #undef __GMP_DEFINE_COMPOUND_OPERATOR
        !          3513:
        !          3514: #undef __GMPZ_DEFINE_COMPOUND_OPERATOR
        !          3515: #undef __GMPZZ_DEFINE_COMPOUND_OPERATOR
        !          3516: #undef __GMPQ_DEFINE_COMPOUND_OPERATOR
        !          3517: #undef __GMPF_DEFINE_COMPOUND_OPERATOR
        !          3518:
        !          3519: #undef __GMP_DEFINE_COMPOUND_OPERATOR_UI
        !          3520: #undef __GMPZ_DEFINE_COMPOUND_OPERATOR_UI
        !          3521: #undef __GMPQ_DEFINE_COMPOUND_OPERATOR_UI
        !          3522: #undef __GMPF_DEFINE_COMPOUND_OPERATOR_UI
        !          3523:
        !          3524: #undef __GMP_DEFINE_INCREMENT_OPERATOR
        !          3525: #undef __GMPZ_DEFINE_INCREMENT_OPERATOR
        !          3526: #undef __GMPQ_DEFINE_INCREMENT_OPERATOR
        !          3527: #undef __GMPF_DEFINE_INCREMENT_OPERATOR
        !          3528:
        !          3529: #endif /* __GMP_PLUSPLUS__ */

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>