Home | History | Annotate | Line # | Download | only in demos
pexpr.c revision 1.1.1.2
      1      1.1  mrg /* Program for computing integer expressions using the GNU Multiple Precision
      2      1.1  mrg    Arithmetic Library.
      3      1.1  mrg 
      4  1.1.1.2  mrg Copyright 1997, 1999, 2000, 2001, 2002, 2005, 2008, 2012 Free Software
      5  1.1.1.2  mrg Foundation, Inc.
      6      1.1  mrg 
      7      1.1  mrg This program is free software; you can redistribute it and/or modify it under
      8      1.1  mrg the terms of the GNU General Public License as published by the Free Software
      9      1.1  mrg Foundation; either version 3 of the License, or (at your option) any later
     10      1.1  mrg version.
     11      1.1  mrg 
     12      1.1  mrg This program is distributed in the hope that it will be useful, but WITHOUT ANY
     13      1.1  mrg WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
     14      1.1  mrg PARTICULAR PURPOSE.  See the GNU General Public License for more details.
     15      1.1  mrg 
     16      1.1  mrg You should have received a copy of the GNU General Public License along with
     17      1.1  mrg this program.  If not, see http://www.gnu.org/licenses/.  */
     18      1.1  mrg 
     19      1.1  mrg 
     20      1.1  mrg /* This expressions evaluator works by building an expression tree (using a
     21      1.1  mrg    recursive descent parser) which is then evaluated.  The expression tree is
     22      1.1  mrg    useful since we want to optimize certain expressions (like a^b % c).
     23      1.1  mrg 
     24      1.1  mrg    Usage: pexpr [options] expr ...
     25      1.1  mrg    (Assuming you called the executable `pexpr' of course.)
     26      1.1  mrg 
     27      1.1  mrg    Command line options:
     28      1.1  mrg 
     29      1.1  mrg    -b        print output in binary
     30      1.1  mrg    -o        print output in octal
     31      1.1  mrg    -d        print output in decimal (the default)
     32      1.1  mrg    -x        print output in hexadecimal
     33      1.1  mrg    -b<NUM>   print output in base NUM
     34      1.1  mrg    -t        print timing information
     35      1.1  mrg    -html     output html
     36      1.1  mrg    -wml      output wml
     37      1.1  mrg    -split    split long lines each 80th digit
     38      1.1  mrg */
     39      1.1  mrg 
     40      1.1  mrg /* Define LIMIT_RESOURCE_USAGE if you want to make sure the program doesn't
     41      1.1  mrg    use up extensive resources (cpu, memory).  Useful for the GMP demo on the
     42      1.1  mrg    GMP web site, since we cannot load the server too much.  */
     43      1.1  mrg 
     44      1.1  mrg #include "pexpr-config.h"
     45      1.1  mrg 
     46      1.1  mrg #include <string.h>
     47      1.1  mrg #include <stdio.h>
     48      1.1  mrg #include <stdlib.h>
     49      1.1  mrg #include <setjmp.h>
     50      1.1  mrg #include <signal.h>
     51      1.1  mrg #include <ctype.h>
     52      1.1  mrg 
     53      1.1  mrg #include <time.h>
     54      1.1  mrg #include <sys/types.h>
     55      1.1  mrg #include <sys/time.h>
     56      1.1  mrg #if HAVE_SYS_RESOURCE_H
     57      1.1  mrg #include <sys/resource.h>
     58      1.1  mrg #endif
     59      1.1  mrg 
     60      1.1  mrg #include "gmp.h"
     61      1.1  mrg 
     62      1.1  mrg /* SunOS 4 and HPUX 9 don't define a canonical SIGSTKSZ, use a default. */
     63      1.1  mrg #ifndef SIGSTKSZ
     64      1.1  mrg #define SIGSTKSZ  4096
     65      1.1  mrg #endif
     66      1.1  mrg 
     67      1.1  mrg 
     68      1.1  mrg #define TIME(t,func)							\
     69      1.1  mrg   do { int __t0, __tmp;							\
     70      1.1  mrg     __t0 = cputime ();							\
     71      1.1  mrg     {func;}								\
     72      1.1  mrg     __tmp = cputime () - __t0;						\
     73      1.1  mrg     (t) = __tmp;							\
     74      1.1  mrg   } while (0)
     75      1.1  mrg 
     76      1.1  mrg /* GMP version 1.x compatibility.  */
     77      1.1  mrg #if ! (__GNU_MP_VERSION >= 2)
     78      1.1  mrg typedef MP_INT __mpz_struct;
     79      1.1  mrg typedef __mpz_struct mpz_t[1];
     80      1.1  mrg typedef __mpz_struct *mpz_ptr;
     81      1.1  mrg #define mpz_fdiv_q	mpz_div
     82      1.1  mrg #define mpz_fdiv_r	mpz_mod
     83      1.1  mrg #define mpz_tdiv_q_2exp	mpz_div_2exp
     84      1.1  mrg #define mpz_sgn(Z) ((Z)->size < 0 ? -1 : (Z)->size > 0)
     85      1.1  mrg #endif
     86      1.1  mrg 
     87      1.1  mrg /* GMP version 2.0 compatibility.  */
     88      1.1  mrg #if ! (__GNU_MP_VERSION > 2 || __GNU_MP_VERSION_MINOR >= 1)
     89      1.1  mrg #define mpz_swap(a,b) \
     90      1.1  mrg   do { __mpz_struct __t; __t = *a; *a = *b; *b = __t;} while (0)
     91      1.1  mrg #endif
     92      1.1  mrg 
     93      1.1  mrg jmp_buf errjmpbuf;
     94      1.1  mrg 
     95      1.1  mrg enum op_t {NOP, LIT, NEG, NOT, PLUS, MINUS, MULT, DIV, MOD, REM, INVMOD, POW,
     96      1.1  mrg 	   AND, IOR, XOR, SLL, SRA, POPCNT, HAMDIST, GCD, LCM, SQRT, ROOT, FAC,
     97      1.1  mrg 	   LOG, LOG2, FERMAT, MERSENNE, FIBONACCI, RANDOM, NEXTPRIME, BINOM,
     98      1.1  mrg 	   TIMING};
     99      1.1  mrg 
    100      1.1  mrg /* Type for the expression tree.  */
    101      1.1  mrg struct expr
    102      1.1  mrg {
    103      1.1  mrg   enum op_t op;
    104      1.1  mrg   union
    105      1.1  mrg   {
    106      1.1  mrg     struct {struct expr *lhs, *rhs;} ops;
    107      1.1  mrg     mpz_t val;
    108      1.1  mrg   } operands;
    109      1.1  mrg };
    110      1.1  mrg 
    111      1.1  mrg typedef struct expr *expr_t;
    112      1.1  mrg 
    113  1.1.1.2  mrg void cleanup_and_exit (int);
    114      1.1  mrg 
    115  1.1.1.2  mrg char *skipspace (char *);
    116  1.1.1.2  mrg void makeexp (expr_t *, enum op_t, expr_t, expr_t);
    117  1.1.1.2  mrg void free_expr (expr_t);
    118  1.1.1.2  mrg char *expr (char *, expr_t *);
    119  1.1.1.2  mrg char *term (char *, expr_t *);
    120  1.1.1.2  mrg char *power (char *, expr_t *);
    121  1.1.1.2  mrg char *factor (char *, expr_t *);
    122  1.1.1.2  mrg int match (char *, char *);
    123  1.1.1.2  mrg int matchp (char *, char *);
    124  1.1.1.2  mrg int cputime (void);
    125      1.1  mrg 
    126  1.1.1.2  mrg void mpz_eval_expr (mpz_ptr, expr_t);
    127  1.1.1.2  mrg void mpz_eval_mod_expr (mpz_ptr, expr_t, mpz_ptr);
    128      1.1  mrg 
    129      1.1  mrg char *error;
    130      1.1  mrg int flag_print = 1;
    131      1.1  mrg int print_timing = 0;
    132      1.1  mrg int flag_html = 0;
    133      1.1  mrg int flag_wml = 0;
    134      1.1  mrg int flag_splitup_output = 0;
    135      1.1  mrg char *newline = "";
    136      1.1  mrg gmp_randstate_t rstate;
    137      1.1  mrg 
    138      1.1  mrg 
    139      1.1  mrg 
    140      1.1  mrg /* cputime() returns user CPU time measured in milliseconds.  */
    141      1.1  mrg #if ! HAVE_CPUTIME
    142      1.1  mrg #if HAVE_GETRUSAGE
    143      1.1  mrg int
    144      1.1  mrg cputime (void)
    145      1.1  mrg {
    146      1.1  mrg   struct rusage rus;
    147      1.1  mrg 
    148      1.1  mrg   getrusage (0, &rus);
    149      1.1  mrg   return rus.ru_utime.tv_sec * 1000 + rus.ru_utime.tv_usec / 1000;
    150      1.1  mrg }
    151      1.1  mrg #else
    152      1.1  mrg #if HAVE_CLOCK
    153      1.1  mrg int
    154      1.1  mrg cputime (void)
    155      1.1  mrg {
    156      1.1  mrg   if (CLOCKS_PER_SEC < 100000)
    157      1.1  mrg     return clock () * 1000 / CLOCKS_PER_SEC;
    158      1.1  mrg   return clock () / (CLOCKS_PER_SEC / 1000);
    159      1.1  mrg }
    160      1.1  mrg #else
    161      1.1  mrg int
    162      1.1  mrg cputime (void)
    163      1.1  mrg {
    164      1.1  mrg   return 0;
    165      1.1  mrg }
    166      1.1  mrg #endif
    167      1.1  mrg #endif
    168      1.1  mrg #endif
    169      1.1  mrg 
    170      1.1  mrg 
    171      1.1  mrg int
    172      1.1  mrg stack_downwards_helper (char *xp)
    173      1.1  mrg {
    174      1.1  mrg   char  y;
    175      1.1  mrg   return &y < xp;
    176      1.1  mrg }
    177      1.1  mrg int
    178      1.1  mrg stack_downwards_p (void)
    179      1.1  mrg {
    180      1.1  mrg   char  x;
    181      1.1  mrg   return stack_downwards_helper (&x);
    182      1.1  mrg }
    183      1.1  mrg 
    184      1.1  mrg 
    185      1.1  mrg void
    186      1.1  mrg setup_error_handler (void)
    187      1.1  mrg {
    188      1.1  mrg #if HAVE_SIGACTION
    189      1.1  mrg   struct sigaction act;
    190      1.1  mrg   act.sa_handler = cleanup_and_exit;
    191      1.1  mrg   sigemptyset (&(act.sa_mask));
    192      1.1  mrg #define SIGNAL(sig)  sigaction (sig, &act, NULL)
    193      1.1  mrg #else
    194      1.1  mrg   struct { int sa_flags; } act;
    195      1.1  mrg #define SIGNAL(sig)  signal (sig, cleanup_and_exit)
    196      1.1  mrg #endif
    197      1.1  mrg   act.sa_flags = 0;
    198      1.1  mrg 
    199      1.1  mrg   /* Set up a stack for signal handling.  A typical cause of error is stack
    200      1.1  mrg      overflow, and in such situation a signal can not be delivered on the
    201      1.1  mrg      overflown stack.  */
    202      1.1  mrg #if HAVE_SIGALTSTACK
    203      1.1  mrg   {
    204      1.1  mrg     /* AIX uses stack_t, MacOS uses struct sigaltstack, various other
    205      1.1  mrg        systems have both. */
    206      1.1  mrg #if HAVE_STACK_T
    207      1.1  mrg     stack_t s;
    208      1.1  mrg #else
    209      1.1  mrg     struct sigaltstack s;
    210      1.1  mrg #endif
    211      1.1  mrg     s.ss_sp = malloc (SIGSTKSZ);
    212      1.1  mrg     s.ss_size = SIGSTKSZ;
    213      1.1  mrg     s.ss_flags = 0;
    214      1.1  mrg     if (sigaltstack (&s, NULL) != 0)
    215      1.1  mrg       perror("sigaltstack");
    216      1.1  mrg     act.sa_flags = SA_ONSTACK;
    217      1.1  mrg   }
    218      1.1  mrg #else
    219      1.1  mrg #if HAVE_SIGSTACK
    220      1.1  mrg   {
    221      1.1  mrg     struct sigstack s;
    222      1.1  mrg     s.ss_sp = malloc (SIGSTKSZ);
    223      1.1  mrg     if (stack_downwards_p ())
    224      1.1  mrg       s.ss_sp += SIGSTKSZ;
    225      1.1  mrg     s.ss_onstack = 0;
    226      1.1  mrg     if (sigstack (&s, NULL) != 0)
    227      1.1  mrg       perror("sigstack");
    228      1.1  mrg     act.sa_flags = SA_ONSTACK;
    229      1.1  mrg   }
    230      1.1  mrg #else
    231      1.1  mrg #endif
    232      1.1  mrg #endif
    233      1.1  mrg 
    234      1.1  mrg #ifdef LIMIT_RESOURCE_USAGE
    235      1.1  mrg   {
    236      1.1  mrg     struct rlimit limit;
    237      1.1  mrg 
    238      1.1  mrg     limit.rlim_cur = limit.rlim_max = 0;
    239      1.1  mrg     setrlimit (RLIMIT_CORE, &limit);
    240      1.1  mrg 
    241      1.1  mrg     limit.rlim_cur = 3;
    242      1.1  mrg     limit.rlim_max = 4;
    243      1.1  mrg     setrlimit (RLIMIT_CPU, &limit);
    244      1.1  mrg 
    245      1.1  mrg     limit.rlim_cur = limit.rlim_max = 16 * 1024 * 1024;
    246      1.1  mrg     setrlimit (RLIMIT_DATA, &limit);
    247      1.1  mrg 
    248      1.1  mrg     getrlimit (RLIMIT_STACK, &limit);
    249      1.1  mrg     limit.rlim_cur = 4 * 1024 * 1024;
    250      1.1  mrg     setrlimit (RLIMIT_STACK, &limit);
    251      1.1  mrg 
    252      1.1  mrg     SIGNAL (SIGXCPU);
    253      1.1  mrg   }
    254      1.1  mrg #endif /* LIMIT_RESOURCE_USAGE */
    255      1.1  mrg 
    256      1.1  mrg   SIGNAL (SIGILL);
    257      1.1  mrg   SIGNAL (SIGSEGV);
    258      1.1  mrg #ifdef SIGBUS /* not in mingw */
    259      1.1  mrg   SIGNAL (SIGBUS);
    260      1.1  mrg #endif
    261      1.1  mrg   SIGNAL (SIGFPE);
    262      1.1  mrg   SIGNAL (SIGABRT);
    263      1.1  mrg }
    264      1.1  mrg 
    265      1.1  mrg int
    266      1.1  mrg main (int argc, char **argv)
    267      1.1  mrg {
    268      1.1  mrg   struct expr *e;
    269      1.1  mrg   int i;
    270      1.1  mrg   mpz_t r;
    271      1.1  mrg   int errcode = 0;
    272      1.1  mrg   char *str;
    273      1.1  mrg   int base = 10;
    274      1.1  mrg 
    275      1.1  mrg   setup_error_handler ();
    276      1.1  mrg 
    277      1.1  mrg   gmp_randinit (rstate, GMP_RAND_ALG_LC, 128);
    278      1.1  mrg 
    279      1.1  mrg   {
    280      1.1  mrg #if HAVE_GETTIMEOFDAY
    281      1.1  mrg     struct timeval tv;
    282      1.1  mrg     gettimeofday (&tv, NULL);
    283      1.1  mrg     gmp_randseed_ui (rstate, tv.tv_sec + tv.tv_usec);
    284      1.1  mrg #else
    285      1.1  mrg     time_t t;
    286      1.1  mrg     time (&t);
    287      1.1  mrg     gmp_randseed_ui (rstate, t);
    288      1.1  mrg #endif
    289      1.1  mrg   }
    290      1.1  mrg 
    291      1.1  mrg   mpz_init (r);
    292      1.1  mrg 
    293      1.1  mrg   while (argc > 1 && argv[1][0] == '-')
    294      1.1  mrg     {
    295      1.1  mrg       char *arg = argv[1];
    296      1.1  mrg 
    297      1.1  mrg       if (arg[1] >= '0' && arg[1] <= '9')
    298      1.1  mrg 	break;
    299      1.1  mrg 
    300      1.1  mrg       if (arg[1] == 't')
    301      1.1  mrg 	print_timing = 1;
    302      1.1  mrg       else if (arg[1] == 'b' && arg[2] >= '0' && arg[2] <= '9')
    303      1.1  mrg 	{
    304      1.1  mrg 	  base = atoi (arg + 2);
    305      1.1  mrg 	  if (base < 2 || base > 62)
    306      1.1  mrg 	    {
    307      1.1  mrg 	      fprintf (stderr, "error: invalid output base\n");
    308      1.1  mrg 	      exit (-1);
    309      1.1  mrg 	    }
    310      1.1  mrg 	}
    311      1.1  mrg       else if (arg[1] == 'b' && arg[2] == 0)
    312      1.1  mrg 	base = 2;
    313      1.1  mrg       else if (arg[1] == 'x' && arg[2] == 0)
    314      1.1  mrg 	base = 16;
    315      1.1  mrg       else if (arg[1] == 'X' && arg[2] == 0)
    316      1.1  mrg 	base = -16;
    317      1.1  mrg       else if (arg[1] == 'o' && arg[2] == 0)
    318      1.1  mrg 	base = 8;
    319      1.1  mrg       else if (arg[1] == 'd' && arg[2] == 0)
    320      1.1  mrg 	base = 10;
    321      1.1  mrg       else if (arg[1] == 'v' && arg[2] == 0)
    322      1.1  mrg 	{
    323      1.1  mrg 	  printf ("pexpr linked to gmp %s\n", __gmp_version);
    324      1.1  mrg 	}
    325      1.1  mrg       else if (strcmp (arg, "-html") == 0)
    326      1.1  mrg 	{
    327      1.1  mrg 	  flag_html = 1;
    328      1.1  mrg 	  newline = "<br>";
    329      1.1  mrg 	}
    330      1.1  mrg       else if (strcmp (arg, "-wml") == 0)
    331      1.1  mrg 	{
    332      1.1  mrg 	  flag_wml = 1;
    333      1.1  mrg 	  newline = "<br/>";
    334      1.1  mrg 	}
    335      1.1  mrg       else if (strcmp (arg, "-split") == 0)
    336      1.1  mrg 	{
    337      1.1  mrg 	  flag_splitup_output = 1;
    338      1.1  mrg 	}
    339      1.1  mrg       else if (strcmp (arg, "-noprint") == 0)
    340      1.1  mrg 	{
    341      1.1  mrg 	  flag_print = 0;
    342      1.1  mrg 	}
    343      1.1  mrg       else
    344      1.1  mrg 	{
    345      1.1  mrg 	  fprintf (stderr, "error: unknown option `%s'\n", arg);
    346      1.1  mrg 	  exit (-1);
    347      1.1  mrg 	}
    348      1.1  mrg       argv++;
    349      1.1  mrg       argc--;
    350      1.1  mrg     }
    351      1.1  mrg 
    352      1.1  mrg   for (i = 1; i < argc; i++)
    353      1.1  mrg     {
    354      1.1  mrg       int s;
    355      1.1  mrg       int jmpval;
    356      1.1  mrg 
    357      1.1  mrg       /* Set up error handler for parsing expression.  */
    358      1.1  mrg       jmpval = setjmp (errjmpbuf);
    359      1.1  mrg       if (jmpval != 0)
    360      1.1  mrg 	{
    361      1.1  mrg 	  fprintf (stderr, "error: %s%s\n", error, newline);
    362      1.1  mrg 	  fprintf (stderr, "       %s%s\n", argv[i], newline);
    363      1.1  mrg 	  if (! flag_html)
    364      1.1  mrg 	    {
    365      1.1  mrg 	      /* ??? Dunno how to align expression position with arrow in
    366      1.1  mrg 		 HTML ??? */
    367      1.1  mrg 	      fprintf (stderr, "       ");
    368      1.1  mrg 	      for (s = jmpval - (long) argv[i]; --s >= 0; )
    369      1.1  mrg 		putc (' ', stderr);
    370      1.1  mrg 	      fprintf (stderr, "^\n");
    371      1.1  mrg 	    }
    372      1.1  mrg 
    373      1.1  mrg 	  errcode |= 1;
    374      1.1  mrg 	  continue;
    375      1.1  mrg 	}
    376      1.1  mrg 
    377      1.1  mrg       str = expr (argv[i], &e);
    378      1.1  mrg 
    379      1.1  mrg       if (str[0] != 0)
    380      1.1  mrg 	{
    381      1.1  mrg 	  fprintf (stderr,
    382      1.1  mrg 		   "error: garbage where end of expression expected%s\n",
    383      1.1  mrg 		   newline);
    384      1.1  mrg 	  fprintf (stderr, "       %s%s\n", argv[i], newline);
    385      1.1  mrg 	  if (! flag_html)
    386      1.1  mrg 	    {
    387      1.1  mrg 	      /* ??? Dunno how to align expression position with arrow in
    388      1.1  mrg 		 HTML ??? */
    389      1.1  mrg 	      fprintf (stderr, "        ");
    390      1.1  mrg 	      for (s = str - argv[i]; --s; )
    391      1.1  mrg 		putc (' ', stderr);
    392      1.1  mrg 	      fprintf (stderr, "^\n");
    393      1.1  mrg 	    }
    394      1.1  mrg 
    395      1.1  mrg 	  errcode |= 1;
    396      1.1  mrg 	  free_expr (e);
    397      1.1  mrg 	  continue;
    398      1.1  mrg 	}
    399      1.1  mrg 
    400      1.1  mrg       /* Set up error handler for evaluating expression.  */
    401      1.1  mrg       if (setjmp (errjmpbuf))
    402      1.1  mrg 	{
    403      1.1  mrg 	  fprintf (stderr, "error: %s%s\n", error, newline);
    404      1.1  mrg 	  fprintf (stderr, "       %s%s\n", argv[i], newline);
    405      1.1  mrg 	  if (! flag_html)
    406      1.1  mrg 	    {
    407      1.1  mrg 	      /* ??? Dunno how to align expression position with arrow in
    408      1.1  mrg 		 HTML ??? */
    409      1.1  mrg 	      fprintf (stderr, "       ");
    410      1.1  mrg 	      for (s = str - argv[i]; --s >= 0; )
    411      1.1  mrg 		putc (' ', stderr);
    412      1.1  mrg 	      fprintf (stderr, "^\n");
    413      1.1  mrg 	    }
    414      1.1  mrg 
    415      1.1  mrg 	  errcode |= 2;
    416      1.1  mrg 	  continue;
    417      1.1  mrg 	}
    418      1.1  mrg 
    419      1.1  mrg       if (print_timing)
    420      1.1  mrg 	{
    421      1.1  mrg 	  int t;
    422      1.1  mrg 	  TIME (t, mpz_eval_expr (r, e));
    423      1.1  mrg 	  printf ("computation took %d ms%s\n", t, newline);
    424      1.1  mrg 	}
    425      1.1  mrg       else
    426      1.1  mrg 	mpz_eval_expr (r, e);
    427      1.1  mrg 
    428      1.1  mrg       if (flag_print)
    429      1.1  mrg 	{
    430      1.1  mrg 	  size_t out_len;
    431      1.1  mrg 	  char *tmp, *s;
    432      1.1  mrg 
    433      1.1  mrg 	  out_len = mpz_sizeinbase (r, base >= 0 ? base : -base) + 2;
    434      1.1  mrg #ifdef LIMIT_RESOURCE_USAGE
    435      1.1  mrg 	  if (out_len > 100000)
    436      1.1  mrg 	    {
    437      1.1  mrg 	      printf ("result is about %ld digits, not printing it%s\n",
    438      1.1  mrg 		      (long) out_len - 3, newline);
    439      1.1  mrg 	      exit (-2);
    440      1.1  mrg 	    }
    441      1.1  mrg #endif
    442      1.1  mrg 	  tmp = malloc (out_len);
    443      1.1  mrg 
    444      1.1  mrg 	  if (print_timing)
    445      1.1  mrg 	    {
    446      1.1  mrg 	      int t;
    447      1.1  mrg 	      printf ("output conversion ");
    448      1.1  mrg 	      TIME (t, mpz_get_str (tmp, base, r));
    449      1.1  mrg 	      printf ("took %d ms%s\n", t, newline);
    450      1.1  mrg 	    }
    451      1.1  mrg 	  else
    452      1.1  mrg 	    mpz_get_str (tmp, base, r);
    453      1.1  mrg 
    454      1.1  mrg 	  out_len = strlen (tmp);
    455      1.1  mrg 	  if (flag_splitup_output)
    456      1.1  mrg 	    {
    457      1.1  mrg 	      for (s = tmp; out_len > 80; s += 80)
    458      1.1  mrg 		{
    459      1.1  mrg 		  fwrite (s, 1, 80, stdout);
    460      1.1  mrg 		  printf ("%s\n", newline);
    461      1.1  mrg 		  out_len -= 80;
    462      1.1  mrg 		}
    463      1.1  mrg 
    464      1.1  mrg 	      fwrite (s, 1, out_len, stdout);
    465      1.1  mrg 	    }
    466      1.1  mrg 	  else
    467      1.1  mrg 	    {
    468      1.1  mrg 	      fwrite (tmp, 1, out_len, stdout);
    469      1.1  mrg 	    }
    470      1.1  mrg 
    471      1.1  mrg 	  free (tmp);
    472      1.1  mrg 	  printf ("%s\n", newline);
    473      1.1  mrg 	}
    474      1.1  mrg       else
    475      1.1  mrg 	{
    476      1.1  mrg 	  printf ("result is approximately %ld digits%s\n",
    477      1.1  mrg 		  (long) mpz_sizeinbase (r, base >= 0 ? base : -base),
    478      1.1  mrg 		  newline);
    479      1.1  mrg 	}
    480      1.1  mrg 
    481      1.1  mrg       free_expr (e);
    482      1.1  mrg     }
    483      1.1  mrg 
    484      1.1  mrg   exit (errcode);
    485      1.1  mrg }
    486      1.1  mrg 
    487      1.1  mrg char *
    488      1.1  mrg expr (char *str, expr_t *e)
    489      1.1  mrg {
    490      1.1  mrg   expr_t e2;
    491      1.1  mrg 
    492      1.1  mrg   str = skipspace (str);
    493      1.1  mrg   if (str[0] == '+')
    494      1.1  mrg     {
    495      1.1  mrg       str = term (str + 1, e);
    496      1.1  mrg     }
    497      1.1  mrg   else if (str[0] == '-')
    498      1.1  mrg     {
    499      1.1  mrg       str = term (str + 1, e);
    500      1.1  mrg       makeexp (e, NEG, *e, NULL);
    501      1.1  mrg     }
    502      1.1  mrg   else if (str[0] == '~')
    503      1.1  mrg     {
    504      1.1  mrg       str = term (str + 1, e);
    505      1.1  mrg       makeexp (e, NOT, *e, NULL);
    506      1.1  mrg     }
    507      1.1  mrg   else
    508      1.1  mrg     {
    509      1.1  mrg       str = term (str, e);
    510      1.1  mrg     }
    511      1.1  mrg 
    512      1.1  mrg   for (;;)
    513      1.1  mrg     {
    514      1.1  mrg       str = skipspace (str);
    515      1.1  mrg       switch (str[0])
    516      1.1  mrg 	{
    517      1.1  mrg 	case 'p':
    518      1.1  mrg 	  if (match ("plus", str))
    519      1.1  mrg 	    {
    520      1.1  mrg 	      str = term (str + 4, &e2);
    521      1.1  mrg 	      makeexp (e, PLUS, *e, e2);
    522      1.1  mrg 	    }
    523      1.1  mrg 	  else
    524      1.1  mrg 	    return str;
    525      1.1  mrg 	  break;
    526      1.1  mrg 	case 'm':
    527      1.1  mrg 	  if (match ("minus", str))
    528      1.1  mrg 	    {
    529      1.1  mrg 	      str = term (str + 5, &e2);
    530      1.1  mrg 	      makeexp (e, MINUS, *e, e2);
    531      1.1  mrg 	    }
    532      1.1  mrg 	  else
    533      1.1  mrg 	    return str;
    534      1.1  mrg 	  break;
    535      1.1  mrg 	case '+':
    536      1.1  mrg 	  str = term (str + 1, &e2);
    537      1.1  mrg 	  makeexp (e, PLUS, *e, e2);
    538      1.1  mrg 	  break;
    539      1.1  mrg 	case '-':
    540      1.1  mrg 	  str = term (str + 1, &e2);
    541      1.1  mrg 	  makeexp (e, MINUS, *e, e2);
    542      1.1  mrg 	  break;
    543      1.1  mrg 	default:
    544      1.1  mrg 	  return str;
    545      1.1  mrg 	}
    546      1.1  mrg     }
    547      1.1  mrg }
    548      1.1  mrg 
    549      1.1  mrg char *
    550      1.1  mrg term (char *str, expr_t *e)
    551      1.1  mrg {
    552      1.1  mrg   expr_t e2;
    553      1.1  mrg 
    554      1.1  mrg   str = power (str, e);
    555      1.1  mrg   for (;;)
    556      1.1  mrg     {
    557      1.1  mrg       str = skipspace (str);
    558      1.1  mrg       switch (str[0])
    559      1.1  mrg 	{
    560      1.1  mrg 	case 'm':
    561      1.1  mrg 	  if (match ("mul", str))
    562      1.1  mrg 	    {
    563      1.1  mrg 	      str = power (str + 3, &e2);
    564      1.1  mrg 	      makeexp (e, MULT, *e, e2);
    565      1.1  mrg 	      break;
    566      1.1  mrg 	    }
    567      1.1  mrg 	  if (match ("mod", str))
    568      1.1  mrg 	    {
    569      1.1  mrg 	      str = power (str + 3, &e2);
    570      1.1  mrg 	      makeexp (e, MOD, *e, e2);
    571      1.1  mrg 	      break;
    572      1.1  mrg 	    }
    573      1.1  mrg 	  return str;
    574      1.1  mrg 	case 'd':
    575      1.1  mrg 	  if (match ("div", str))
    576      1.1  mrg 	    {
    577      1.1  mrg 	      str = power (str + 3, &e2);
    578      1.1  mrg 	      makeexp (e, DIV, *e, e2);
    579      1.1  mrg 	      break;
    580      1.1  mrg 	    }
    581      1.1  mrg 	  return str;
    582      1.1  mrg 	case 'r':
    583      1.1  mrg 	  if (match ("rem", str))
    584      1.1  mrg 	    {
    585      1.1  mrg 	      str = power (str + 3, &e2);
    586      1.1  mrg 	      makeexp (e, REM, *e, e2);
    587      1.1  mrg 	      break;
    588      1.1  mrg 	    }
    589      1.1  mrg 	  return str;
    590      1.1  mrg 	case 'i':
    591      1.1  mrg 	  if (match ("invmod", str))
    592      1.1  mrg 	    {
    593      1.1  mrg 	      str = power (str + 6, &e2);
    594      1.1  mrg 	      makeexp (e, REM, *e, e2);
    595      1.1  mrg 	      break;
    596      1.1  mrg 	    }
    597      1.1  mrg 	  return str;
    598      1.1  mrg 	case 't':
    599      1.1  mrg 	  if (match ("times", str))
    600      1.1  mrg 	    {
    601      1.1  mrg 	      str = power (str + 5, &e2);
    602      1.1  mrg 	      makeexp (e, MULT, *e, e2);
    603      1.1  mrg 	      break;
    604      1.1  mrg 	    }
    605      1.1  mrg 	  if (match ("thru", str))
    606      1.1  mrg 	    {
    607      1.1  mrg 	      str = power (str + 4, &e2);
    608      1.1  mrg 	      makeexp (e, DIV, *e, e2);
    609      1.1  mrg 	      break;
    610      1.1  mrg 	    }
    611      1.1  mrg 	  if (match ("through", str))
    612      1.1  mrg 	    {
    613      1.1  mrg 	      str = power (str + 7, &e2);
    614      1.1  mrg 	      makeexp (e, DIV, *e, e2);
    615      1.1  mrg 	      break;
    616      1.1  mrg 	    }
    617      1.1  mrg 	  return str;
    618      1.1  mrg 	case '*':
    619      1.1  mrg 	  str = power (str + 1, &e2);
    620      1.1  mrg 	  makeexp (e, MULT, *e, e2);
    621      1.1  mrg 	  break;
    622      1.1  mrg 	case '/':
    623      1.1  mrg 	  str = power (str + 1, &e2);
    624      1.1  mrg 	  makeexp (e, DIV, *e, e2);
    625      1.1  mrg 	  break;
    626      1.1  mrg 	case '%':
    627      1.1  mrg 	  str = power (str + 1, &e2);
    628      1.1  mrg 	  makeexp (e, MOD, *e, e2);
    629      1.1  mrg 	  break;
    630      1.1  mrg 	default:
    631      1.1  mrg 	  return str;
    632      1.1  mrg 	}
    633      1.1  mrg     }
    634      1.1  mrg }
    635      1.1  mrg 
    636      1.1  mrg char *
    637      1.1  mrg power (char *str, expr_t *e)
    638      1.1  mrg {
    639      1.1  mrg   expr_t e2;
    640      1.1  mrg 
    641      1.1  mrg   str = factor (str, e);
    642      1.1  mrg   while (str[0] == '!')
    643      1.1  mrg     {
    644      1.1  mrg       str++;
    645      1.1  mrg       makeexp (e, FAC, *e, NULL);
    646      1.1  mrg     }
    647      1.1  mrg   str = skipspace (str);
    648      1.1  mrg   if (str[0] == '^')
    649      1.1  mrg     {
    650      1.1  mrg       str = power (str + 1, &e2);
    651      1.1  mrg       makeexp (e, POW, *e, e2);
    652      1.1  mrg     }
    653      1.1  mrg   return str;
    654      1.1  mrg }
    655      1.1  mrg 
    656      1.1  mrg int
    657      1.1  mrg match (char *s, char *str)
    658      1.1  mrg {
    659      1.1  mrg   char *ostr = str;
    660      1.1  mrg   int i;
    661      1.1  mrg 
    662      1.1  mrg   for (i = 0; s[i] != 0; i++)
    663      1.1  mrg     {
    664      1.1  mrg       if (str[i] != s[i])
    665      1.1  mrg 	return 0;
    666      1.1  mrg     }
    667      1.1  mrg   str = skipspace (str + i);
    668      1.1  mrg   return str - ostr;
    669      1.1  mrg }
    670      1.1  mrg 
    671      1.1  mrg int
    672      1.1  mrg matchp (char *s, char *str)
    673      1.1  mrg {
    674      1.1  mrg   char *ostr = str;
    675      1.1  mrg   int i;
    676      1.1  mrg 
    677      1.1  mrg   for (i = 0; s[i] != 0; i++)
    678      1.1  mrg     {
    679      1.1  mrg       if (str[i] != s[i])
    680      1.1  mrg 	return 0;
    681      1.1  mrg     }
    682      1.1  mrg   str = skipspace (str + i);
    683      1.1  mrg   if (str[0] == '(')
    684      1.1  mrg     return str - ostr + 1;
    685      1.1  mrg   return 0;
    686      1.1  mrg }
    687      1.1  mrg 
    688      1.1  mrg struct functions
    689      1.1  mrg {
    690      1.1  mrg   char *spelling;
    691      1.1  mrg   enum op_t op;
    692      1.1  mrg   int arity; /* 1 or 2 means real arity; 0 means arbitrary.  */
    693      1.1  mrg };
    694      1.1  mrg 
    695      1.1  mrg struct functions fns[] =
    696      1.1  mrg {
    697      1.1  mrg   {"sqrt", SQRT, 1},
    698      1.1  mrg #if __GNU_MP_VERSION >= 2
    699      1.1  mrg   {"root", ROOT, 2},
    700      1.1  mrg   {"popc", POPCNT, 1},
    701      1.1  mrg   {"hamdist", HAMDIST, 2},
    702      1.1  mrg #endif
    703      1.1  mrg   {"gcd", GCD, 0},
    704      1.1  mrg #if __GNU_MP_VERSION > 2 || __GNU_MP_VERSION_MINOR >= 1
    705      1.1  mrg   {"lcm", LCM, 0},
    706      1.1  mrg #endif
    707      1.1  mrg   {"and", AND, 0},
    708      1.1  mrg   {"ior", IOR, 0},
    709      1.1  mrg #if __GNU_MP_VERSION > 2 || __GNU_MP_VERSION_MINOR >= 1
    710      1.1  mrg   {"xor", XOR, 0},
    711      1.1  mrg #endif
    712      1.1  mrg   {"plus", PLUS, 0},
    713      1.1  mrg   {"pow", POW, 2},
    714      1.1  mrg   {"minus", MINUS, 2},
    715      1.1  mrg   {"mul", MULT, 0},
    716      1.1  mrg   {"div", DIV, 2},
    717      1.1  mrg   {"mod", MOD, 2},
    718      1.1  mrg   {"rem", REM, 2},
    719      1.1  mrg #if __GNU_MP_VERSION >= 2
    720      1.1  mrg   {"invmod", INVMOD, 2},
    721      1.1  mrg #endif
    722      1.1  mrg   {"log", LOG, 2},
    723      1.1  mrg   {"log2", LOG2, 1},
    724      1.1  mrg   {"F", FERMAT, 1},
    725      1.1  mrg   {"M", MERSENNE, 1},
    726      1.1  mrg   {"fib", FIBONACCI, 1},
    727      1.1  mrg   {"Fib", FIBONACCI, 1},
    728      1.1  mrg   {"random", RANDOM, 1},
    729      1.1  mrg   {"nextprime", NEXTPRIME, 1},
    730      1.1  mrg   {"binom", BINOM, 2},
    731      1.1  mrg   {"binomial", BINOM, 2},
    732      1.1  mrg   {"fac", FAC, 1},
    733      1.1  mrg   {"fact", FAC, 1},
    734      1.1  mrg   {"factorial", FAC, 1},
    735      1.1  mrg   {"time", TIMING, 1},
    736      1.1  mrg   {"", NOP, 0}
    737      1.1  mrg };
    738      1.1  mrg 
    739      1.1  mrg char *
    740      1.1  mrg factor (char *str, expr_t *e)
    741      1.1  mrg {
    742      1.1  mrg   expr_t e1, e2;
    743      1.1  mrg 
    744      1.1  mrg   str = skipspace (str);
    745      1.1  mrg 
    746      1.1  mrg   if (isalpha (str[0]))
    747      1.1  mrg     {
    748      1.1  mrg       int i;
    749      1.1  mrg       int cnt;
    750      1.1  mrg 
    751      1.1  mrg       for (i = 0; fns[i].op != NOP; i++)
    752      1.1  mrg 	{
    753      1.1  mrg 	  if (fns[i].arity == 1)
    754      1.1  mrg 	    {
    755      1.1  mrg 	      cnt = matchp (fns[i].spelling, str);
    756      1.1  mrg 	      if (cnt != 0)
    757      1.1  mrg 		{
    758      1.1  mrg 		  str = expr (str + cnt, &e1);
    759      1.1  mrg 		  str = skipspace (str);
    760      1.1  mrg 		  if (str[0] != ')')
    761      1.1  mrg 		    {
    762      1.1  mrg 		      error = "expected `)'";
    763      1.1  mrg 		      longjmp (errjmpbuf, (int) (long) str);
    764      1.1  mrg 		    }
    765      1.1  mrg 		  makeexp (e, fns[i].op, e1, NULL);
    766      1.1  mrg 		  return str + 1;
    767      1.1  mrg 		}
    768      1.1  mrg 	    }
    769      1.1  mrg 	}
    770      1.1  mrg 
    771      1.1  mrg       for (i = 0; fns[i].op != NOP; i++)
    772      1.1  mrg 	{
    773      1.1  mrg 	  if (fns[i].arity != 1)
    774      1.1  mrg 	    {
    775      1.1  mrg 	      cnt = matchp (fns[i].spelling, str);
    776      1.1  mrg 	      if (cnt != 0)
    777      1.1  mrg 		{
    778      1.1  mrg 		  str = expr (str + cnt, &e1);
    779      1.1  mrg 		  str = skipspace (str);
    780      1.1  mrg 
    781      1.1  mrg 		  if (str[0] != ',')
    782      1.1  mrg 		    {
    783      1.1  mrg 		      error = "expected `,' and another operand";
    784      1.1  mrg 		      longjmp (errjmpbuf, (int) (long) str);
    785      1.1  mrg 		    }
    786      1.1  mrg 
    787      1.1  mrg 		  str = skipspace (str + 1);
    788      1.1  mrg 		  str = expr (str, &e2);
    789      1.1  mrg 		  str = skipspace (str);
    790      1.1  mrg 
    791      1.1  mrg 		  if (fns[i].arity == 0)
    792      1.1  mrg 		    {
    793      1.1  mrg 		      while (str[0] == ',')
    794      1.1  mrg 			{
    795      1.1  mrg 			  makeexp (&e1, fns[i].op, e1, e2);
    796      1.1  mrg 			  str = skipspace (str + 1);
    797      1.1  mrg 			  str = expr (str, &e2);
    798      1.1  mrg 			  str = skipspace (str);
    799      1.1  mrg 			}
    800      1.1  mrg 		    }
    801      1.1  mrg 
    802      1.1  mrg 		  if (str[0] != ')')
    803      1.1  mrg 		    {
    804      1.1  mrg 		      error = "expected `)'";
    805      1.1  mrg 		      longjmp (errjmpbuf, (int) (long) str);
    806      1.1  mrg 		    }
    807      1.1  mrg 
    808      1.1  mrg 		  makeexp (e, fns[i].op, e1, e2);
    809      1.1  mrg 		  return str + 1;
    810      1.1  mrg 		}
    811      1.1  mrg 	    }
    812      1.1  mrg 	}
    813      1.1  mrg     }
    814      1.1  mrg 
    815      1.1  mrg   if (str[0] == '(')
    816      1.1  mrg     {
    817      1.1  mrg       str = expr (str + 1, e);
    818      1.1  mrg       str = skipspace (str);
    819      1.1  mrg       if (str[0] != ')')
    820      1.1  mrg 	{
    821      1.1  mrg 	  error = "expected `)'";
    822      1.1  mrg 	  longjmp (errjmpbuf, (int) (long) str);
    823      1.1  mrg 	}
    824      1.1  mrg       str++;
    825      1.1  mrg     }
    826      1.1  mrg   else if (str[0] >= '0' && str[0] <= '9')
    827      1.1  mrg     {
    828      1.1  mrg       expr_t res;
    829      1.1  mrg       char *s, *sc;
    830      1.1  mrg 
    831      1.1  mrg       res = malloc (sizeof (struct expr));
    832      1.1  mrg       res -> op = LIT;
    833      1.1  mrg       mpz_init (res->operands.val);
    834      1.1  mrg 
    835      1.1  mrg       s = str;
    836      1.1  mrg       while (isalnum (str[0]))
    837      1.1  mrg 	str++;
    838      1.1  mrg       sc = malloc (str - s + 1);
    839      1.1  mrg       memcpy (sc, s, str - s);
    840      1.1  mrg       sc[str - s] = 0;
    841      1.1  mrg 
    842      1.1  mrg       mpz_set_str (res->operands.val, sc, 0);
    843      1.1  mrg       *e = res;
    844      1.1  mrg       free (sc);
    845      1.1  mrg     }
    846      1.1  mrg   else
    847      1.1  mrg     {
    848      1.1  mrg       error = "operand expected";
    849      1.1  mrg       longjmp (errjmpbuf, (int) (long) str);
    850      1.1  mrg     }
    851      1.1  mrg   return str;
    852      1.1  mrg }
    853      1.1  mrg 
    854      1.1  mrg char *
    855      1.1  mrg skipspace (char *str)
    856      1.1  mrg {
    857      1.1  mrg   while (str[0] == ' ')
    858      1.1  mrg     str++;
    859      1.1  mrg   return str;
    860      1.1  mrg }
    861      1.1  mrg 
    862      1.1  mrg /* Make a new expression with operation OP and right hand side
    863      1.1  mrg    RHS and left hand side lhs.  Put the result in R.  */
    864      1.1  mrg void
    865      1.1  mrg makeexp (expr_t *r, enum op_t op, expr_t lhs, expr_t rhs)
    866      1.1  mrg {
    867      1.1  mrg   expr_t res;
    868      1.1  mrg   res = malloc (sizeof (struct expr));
    869      1.1  mrg   res -> op = op;
    870      1.1  mrg   res -> operands.ops.lhs = lhs;
    871      1.1  mrg   res -> operands.ops.rhs = rhs;
    872      1.1  mrg   *r = res;
    873      1.1  mrg   return;
    874      1.1  mrg }
    875      1.1  mrg 
    876      1.1  mrg /* Free the memory used by expression E.  */
    877      1.1  mrg void
    878      1.1  mrg free_expr (expr_t e)
    879      1.1  mrg {
    880      1.1  mrg   if (e->op != LIT)
    881      1.1  mrg     {
    882      1.1  mrg       free_expr (e->operands.ops.lhs);
    883      1.1  mrg       if (e->operands.ops.rhs != NULL)
    884      1.1  mrg 	free_expr (e->operands.ops.rhs);
    885      1.1  mrg     }
    886      1.1  mrg   else
    887      1.1  mrg     {
    888      1.1  mrg       mpz_clear (e->operands.val);
    889      1.1  mrg     }
    890      1.1  mrg }
    891      1.1  mrg 
    892      1.1  mrg /* Evaluate the expression E and put the result in R.  */
    893      1.1  mrg void
    894      1.1  mrg mpz_eval_expr (mpz_ptr r, expr_t e)
    895      1.1  mrg {
    896      1.1  mrg   mpz_t lhs, rhs;
    897      1.1  mrg 
    898      1.1  mrg   switch (e->op)
    899      1.1  mrg     {
    900      1.1  mrg     case LIT:
    901      1.1  mrg       mpz_set (r, e->operands.val);
    902      1.1  mrg       return;
    903      1.1  mrg     case PLUS:
    904      1.1  mrg       mpz_init (lhs); mpz_init (rhs);
    905      1.1  mrg       mpz_eval_expr (lhs, e->operands.ops.lhs);
    906      1.1  mrg       mpz_eval_expr (rhs, e->operands.ops.rhs);
    907      1.1  mrg       mpz_add (r, lhs, rhs);
    908      1.1  mrg       mpz_clear (lhs); mpz_clear (rhs);
    909      1.1  mrg       return;
    910      1.1  mrg     case MINUS:
    911      1.1  mrg       mpz_init (lhs); mpz_init (rhs);
    912      1.1  mrg       mpz_eval_expr (lhs, e->operands.ops.lhs);
    913      1.1  mrg       mpz_eval_expr (rhs, e->operands.ops.rhs);
    914      1.1  mrg       mpz_sub (r, lhs, rhs);
    915      1.1  mrg       mpz_clear (lhs); mpz_clear (rhs);
    916      1.1  mrg       return;
    917      1.1  mrg     case MULT:
    918      1.1  mrg       mpz_init (lhs); mpz_init (rhs);
    919      1.1  mrg       mpz_eval_expr (lhs, e->operands.ops.lhs);
    920      1.1  mrg       mpz_eval_expr (rhs, e->operands.ops.rhs);
    921      1.1  mrg       mpz_mul (r, lhs, rhs);
    922      1.1  mrg       mpz_clear (lhs); mpz_clear (rhs);
    923      1.1  mrg       return;
    924      1.1  mrg     case DIV:
    925      1.1  mrg       mpz_init (lhs); mpz_init (rhs);
    926      1.1  mrg       mpz_eval_expr (lhs, e->operands.ops.lhs);
    927      1.1  mrg       mpz_eval_expr (rhs, e->operands.ops.rhs);
    928      1.1  mrg       mpz_fdiv_q (r, lhs, rhs);
    929      1.1  mrg       mpz_clear (lhs); mpz_clear (rhs);
    930      1.1  mrg       return;
    931      1.1  mrg     case MOD:
    932      1.1  mrg       mpz_init (rhs);
    933      1.1  mrg       mpz_eval_expr (rhs, e->operands.ops.rhs);
    934      1.1  mrg       mpz_abs (rhs, rhs);
    935      1.1  mrg       mpz_eval_mod_expr (r, e->operands.ops.lhs, rhs);
    936      1.1  mrg       mpz_clear (rhs);
    937      1.1  mrg       return;
    938      1.1  mrg     case REM:
    939      1.1  mrg       /* Check if lhs operand is POW expression and optimize for that case.  */
    940      1.1  mrg       if (e->operands.ops.lhs->op == POW)
    941      1.1  mrg 	{
    942      1.1  mrg 	  mpz_t powlhs, powrhs;
    943      1.1  mrg 	  mpz_init (powlhs);
    944      1.1  mrg 	  mpz_init (powrhs);
    945      1.1  mrg 	  mpz_init (rhs);
    946      1.1  mrg 	  mpz_eval_expr (powlhs, e->operands.ops.lhs->operands.ops.lhs);
    947      1.1  mrg 	  mpz_eval_expr (powrhs, e->operands.ops.lhs->operands.ops.rhs);
    948      1.1  mrg 	  mpz_eval_expr (rhs, e->operands.ops.rhs);
    949      1.1  mrg 	  mpz_powm (r, powlhs, powrhs, rhs);
    950      1.1  mrg 	  if (mpz_cmp_si (rhs, 0L) < 0)
    951      1.1  mrg 	    mpz_neg (r, r);
    952      1.1  mrg 	  mpz_clear (powlhs);
    953      1.1  mrg 	  mpz_clear (powrhs);
    954      1.1  mrg 	  mpz_clear (rhs);
    955      1.1  mrg 	  return;
    956      1.1  mrg 	}
    957      1.1  mrg 
    958      1.1  mrg       mpz_init (lhs); mpz_init (rhs);
    959      1.1  mrg       mpz_eval_expr (lhs, e->operands.ops.lhs);
    960      1.1  mrg       mpz_eval_expr (rhs, e->operands.ops.rhs);
    961      1.1  mrg       mpz_fdiv_r (r, lhs, rhs);
    962      1.1  mrg       mpz_clear (lhs); mpz_clear (rhs);
    963      1.1  mrg       return;
    964      1.1  mrg #if __GNU_MP_VERSION >= 2
    965      1.1  mrg     case INVMOD:
    966      1.1  mrg       mpz_init (lhs); mpz_init (rhs);
    967      1.1  mrg       mpz_eval_expr (lhs, e->operands.ops.lhs);
    968      1.1  mrg       mpz_eval_expr (rhs, e->operands.ops.rhs);
    969      1.1  mrg       mpz_invert (r, lhs, rhs);
    970      1.1  mrg       mpz_clear (lhs); mpz_clear (rhs);
    971      1.1  mrg       return;
    972      1.1  mrg #endif
    973      1.1  mrg     case POW:
    974      1.1  mrg       mpz_init (lhs); mpz_init (rhs);
    975      1.1  mrg       mpz_eval_expr (lhs, e->operands.ops.lhs);
    976      1.1  mrg       if (mpz_cmpabs_ui (lhs, 1) <= 0)
    977      1.1  mrg 	{
    978      1.1  mrg 	  /* For 0^rhs and 1^rhs, we just need to verify that
    979      1.1  mrg 	     rhs is well-defined.  For (-1)^rhs we need to
    980      1.1  mrg 	     determine (rhs mod 2).  For simplicity, compute
    981      1.1  mrg 	     (rhs mod 2) for all three cases.  */
    982      1.1  mrg 	  expr_t two, et;
    983      1.1  mrg 	  two = malloc (sizeof (struct expr));
    984      1.1  mrg 	  two -> op = LIT;
    985      1.1  mrg 	  mpz_init_set_ui (two->operands.val, 2L);
    986      1.1  mrg 	  makeexp (&et, MOD, e->operands.ops.rhs, two);
    987      1.1  mrg 	  e->operands.ops.rhs = et;
    988      1.1  mrg 	}
    989      1.1  mrg 
    990      1.1  mrg       mpz_eval_expr (rhs, e->operands.ops.rhs);
    991      1.1  mrg       if (mpz_cmp_si (rhs, 0L) == 0)
    992      1.1  mrg 	/* x^0 is 1 */
    993      1.1  mrg 	mpz_set_ui (r, 1L);
    994      1.1  mrg       else if (mpz_cmp_si (lhs, 0L) == 0)
    995      1.1  mrg 	/* 0^y (where y != 0) is 0 */
    996      1.1  mrg 	mpz_set_ui (r, 0L);
    997      1.1  mrg       else if (mpz_cmp_ui (lhs, 1L) == 0)
    998      1.1  mrg 	/* 1^y is 1 */
    999      1.1  mrg 	mpz_set_ui (r, 1L);
   1000      1.1  mrg       else if (mpz_cmp_si (lhs, -1L) == 0)
   1001      1.1  mrg 	/* (-1)^y just depends on whether y is even or odd */
   1002      1.1  mrg 	mpz_set_si (r, (mpz_get_ui (rhs) & 1) ? -1L : 1L);
   1003      1.1  mrg       else if (mpz_cmp_si (rhs, 0L) < 0)
   1004      1.1  mrg 	/* x^(-n) is 0 */
   1005      1.1  mrg 	mpz_set_ui (r, 0L);
   1006      1.1  mrg       else
   1007      1.1  mrg 	{
   1008      1.1  mrg 	  unsigned long int cnt;
   1009      1.1  mrg 	  unsigned long int y;
   1010      1.1  mrg 	  /* error if exponent does not fit into an unsigned long int.  */
   1011      1.1  mrg 	  if (mpz_cmp_ui (rhs, ~(unsigned long int) 0) > 0)
   1012      1.1  mrg 	    goto pow_err;
   1013      1.1  mrg 
   1014      1.1  mrg 	  y = mpz_get_ui (rhs);
   1015      1.1  mrg 	  /* x^y == (x/(2^c))^y * 2^(c*y) */
   1016      1.1  mrg #if __GNU_MP_VERSION >= 2
   1017      1.1  mrg 	  cnt = mpz_scan1 (lhs, 0);
   1018      1.1  mrg #else
   1019      1.1  mrg 	  cnt = 0;
   1020      1.1  mrg #endif
   1021      1.1  mrg 	  if (cnt != 0)
   1022      1.1  mrg 	    {
   1023      1.1  mrg 	      if (y * cnt / cnt != y)
   1024      1.1  mrg 		goto pow_err;
   1025      1.1  mrg 	      mpz_tdiv_q_2exp (lhs, lhs, cnt);
   1026      1.1  mrg 	      mpz_pow_ui (r, lhs, y);
   1027      1.1  mrg 	      mpz_mul_2exp (r, r, y * cnt);
   1028      1.1  mrg 	    }
   1029      1.1  mrg 	  else
   1030      1.1  mrg 	    mpz_pow_ui (r, lhs, y);
   1031      1.1  mrg 	}
   1032      1.1  mrg       mpz_clear (lhs); mpz_clear (rhs);
   1033      1.1  mrg       return;
   1034      1.1  mrg     pow_err:
   1035      1.1  mrg       error = "result of `pow' operator too large";
   1036      1.1  mrg       mpz_clear (lhs); mpz_clear (rhs);
   1037      1.1  mrg       longjmp (errjmpbuf, 1);
   1038      1.1  mrg     case GCD:
   1039      1.1  mrg       mpz_init (lhs); mpz_init (rhs);
   1040      1.1  mrg       mpz_eval_expr (lhs, e->operands.ops.lhs);
   1041      1.1  mrg       mpz_eval_expr (rhs, e->operands.ops.rhs);
   1042      1.1  mrg       mpz_gcd (r, lhs, rhs);
   1043      1.1  mrg       mpz_clear (lhs); mpz_clear (rhs);
   1044      1.1  mrg       return;
   1045      1.1  mrg #if __GNU_MP_VERSION > 2 || __GNU_MP_VERSION_MINOR >= 1
   1046      1.1  mrg     case LCM:
   1047      1.1  mrg       mpz_init (lhs); mpz_init (rhs);
   1048      1.1  mrg       mpz_eval_expr (lhs, e->operands.ops.lhs);
   1049      1.1  mrg       mpz_eval_expr (rhs, e->operands.ops.rhs);
   1050      1.1  mrg       mpz_lcm (r, lhs, rhs);
   1051      1.1  mrg       mpz_clear (lhs); mpz_clear (rhs);
   1052      1.1  mrg       return;
   1053      1.1  mrg #endif
   1054      1.1  mrg     case AND:
   1055      1.1  mrg       mpz_init (lhs); mpz_init (rhs);
   1056      1.1  mrg       mpz_eval_expr (lhs, e->operands.ops.lhs);
   1057      1.1  mrg       mpz_eval_expr (rhs, e->operands.ops.rhs);
   1058      1.1  mrg       mpz_and (r, lhs, rhs);
   1059      1.1  mrg       mpz_clear (lhs); mpz_clear (rhs);
   1060      1.1  mrg       return;
   1061      1.1  mrg     case IOR:
   1062      1.1  mrg       mpz_init (lhs); mpz_init (rhs);
   1063      1.1  mrg       mpz_eval_expr (lhs, e->operands.ops.lhs);
   1064      1.1  mrg       mpz_eval_expr (rhs, e->operands.ops.rhs);
   1065      1.1  mrg       mpz_ior (r, lhs, rhs);
   1066      1.1  mrg       mpz_clear (lhs); mpz_clear (rhs);
   1067      1.1  mrg       return;
   1068      1.1  mrg #if __GNU_MP_VERSION > 2 || __GNU_MP_VERSION_MINOR >= 1
   1069      1.1  mrg     case XOR:
   1070      1.1  mrg       mpz_init (lhs); mpz_init (rhs);
   1071      1.1  mrg       mpz_eval_expr (lhs, e->operands.ops.lhs);
   1072      1.1  mrg       mpz_eval_expr (rhs, e->operands.ops.rhs);
   1073      1.1  mrg       mpz_xor (r, lhs, rhs);
   1074      1.1  mrg       mpz_clear (lhs); mpz_clear (rhs);
   1075      1.1  mrg       return;
   1076      1.1  mrg #endif
   1077      1.1  mrg     case NEG:
   1078      1.1  mrg       mpz_eval_expr (r, e->operands.ops.lhs);
   1079      1.1  mrg       mpz_neg (r, r);
   1080      1.1  mrg       return;
   1081      1.1  mrg     case NOT:
   1082      1.1  mrg       mpz_eval_expr (r, e->operands.ops.lhs);
   1083      1.1  mrg       mpz_com (r, r);
   1084      1.1  mrg       return;
   1085      1.1  mrg     case SQRT:
   1086      1.1  mrg       mpz_init (lhs);
   1087      1.1  mrg       mpz_eval_expr (lhs, e->operands.ops.lhs);
   1088      1.1  mrg       if (mpz_sgn (lhs) < 0)
   1089      1.1  mrg 	{
   1090      1.1  mrg 	  error = "cannot take square root of negative numbers";
   1091      1.1  mrg 	  mpz_clear (lhs);
   1092      1.1  mrg 	  longjmp (errjmpbuf, 1);
   1093      1.1  mrg 	}
   1094      1.1  mrg       mpz_sqrt (r, lhs);
   1095      1.1  mrg       return;
   1096      1.1  mrg #if __GNU_MP_VERSION > 2 || __GNU_MP_VERSION_MINOR >= 1
   1097      1.1  mrg     case ROOT:
   1098      1.1  mrg       mpz_init (lhs); mpz_init (rhs);
   1099      1.1  mrg       mpz_eval_expr (lhs, e->operands.ops.lhs);
   1100      1.1  mrg       mpz_eval_expr (rhs, e->operands.ops.rhs);
   1101      1.1  mrg       if (mpz_sgn (rhs) <= 0)
   1102      1.1  mrg 	{
   1103      1.1  mrg 	  error = "cannot take non-positive root orders";
   1104      1.1  mrg 	  mpz_clear (lhs); mpz_clear (rhs);
   1105      1.1  mrg 	  longjmp (errjmpbuf, 1);
   1106      1.1  mrg 	}
   1107      1.1  mrg       if (mpz_sgn (lhs) < 0 && (mpz_get_ui (rhs) & 1) == 0)
   1108      1.1  mrg 	{
   1109      1.1  mrg 	  error = "cannot take even root orders of negative numbers";
   1110      1.1  mrg 	  mpz_clear (lhs); mpz_clear (rhs);
   1111      1.1  mrg 	  longjmp (errjmpbuf, 1);
   1112      1.1  mrg 	}
   1113      1.1  mrg 
   1114      1.1  mrg       {
   1115      1.1  mrg 	unsigned long int nth = mpz_get_ui (rhs);
   1116      1.1  mrg 	if (mpz_cmp_ui (rhs, ~(unsigned long int) 0) > 0)
   1117      1.1  mrg 	  {
   1118      1.1  mrg 	    /* If we are asked to take an awfully large root order, cheat and
   1119      1.1  mrg 	       ask for the largest order we can pass to mpz_root.  This saves
   1120      1.1  mrg 	       some error prone special cases.  */
   1121      1.1  mrg 	    nth = ~(unsigned long int) 0;
   1122      1.1  mrg 	  }
   1123      1.1  mrg 	mpz_root (r, lhs, nth);
   1124      1.1  mrg       }
   1125      1.1  mrg       mpz_clear (lhs); mpz_clear (rhs);
   1126      1.1  mrg       return;
   1127      1.1  mrg #endif
   1128      1.1  mrg     case FAC:
   1129      1.1  mrg       mpz_eval_expr (r, e->operands.ops.lhs);
   1130      1.1  mrg       if (mpz_size (r) > 1)
   1131      1.1  mrg 	{
   1132      1.1  mrg 	  error = "result of `!' operator too large";
   1133      1.1  mrg 	  longjmp (errjmpbuf, 1);
   1134      1.1  mrg 	}
   1135      1.1  mrg       mpz_fac_ui (r, mpz_get_ui (r));
   1136      1.1  mrg       return;
   1137      1.1  mrg #if __GNU_MP_VERSION >= 2
   1138      1.1  mrg     case POPCNT:
   1139      1.1  mrg       mpz_eval_expr (r, e->operands.ops.lhs);
   1140      1.1  mrg       { long int cnt;
   1141      1.1  mrg 	cnt = mpz_popcount (r);
   1142      1.1  mrg 	mpz_set_si (r, cnt);
   1143      1.1  mrg       }
   1144      1.1  mrg       return;
   1145      1.1  mrg     case HAMDIST:
   1146      1.1  mrg       { long int cnt;
   1147      1.1  mrg 	mpz_init (lhs); mpz_init (rhs);
   1148      1.1  mrg 	mpz_eval_expr (lhs, e->operands.ops.lhs);
   1149      1.1  mrg 	mpz_eval_expr (rhs, e->operands.ops.rhs);
   1150      1.1  mrg 	cnt = mpz_hamdist (lhs, rhs);
   1151      1.1  mrg 	mpz_clear (lhs); mpz_clear (rhs);
   1152      1.1  mrg 	mpz_set_si (r, cnt);
   1153      1.1  mrg       }
   1154      1.1  mrg       return;
   1155      1.1  mrg #endif
   1156      1.1  mrg     case LOG2:
   1157      1.1  mrg       mpz_eval_expr (r, e->operands.ops.lhs);
   1158      1.1  mrg       { unsigned long int cnt;
   1159      1.1  mrg 	if (mpz_sgn (r) <= 0)
   1160      1.1  mrg 	  {
   1161      1.1  mrg 	    error = "logarithm of non-positive number";
   1162      1.1  mrg 	    longjmp (errjmpbuf, 1);
   1163      1.1  mrg 	  }
   1164      1.1  mrg 	cnt = mpz_sizeinbase (r, 2);
   1165      1.1  mrg 	mpz_set_ui (r, cnt - 1);
   1166      1.1  mrg       }
   1167      1.1  mrg       return;
   1168      1.1  mrg     case LOG:
   1169      1.1  mrg       { unsigned long int cnt;
   1170      1.1  mrg 	mpz_init (lhs); mpz_init (rhs);
   1171      1.1  mrg 	mpz_eval_expr (lhs, e->operands.ops.lhs);
   1172      1.1  mrg 	mpz_eval_expr (rhs, e->operands.ops.rhs);
   1173      1.1  mrg 	if (mpz_sgn (lhs) <= 0)
   1174      1.1  mrg 	  {
   1175      1.1  mrg 	    error = "logarithm of non-positive number";
   1176      1.1  mrg 	    mpz_clear (lhs); mpz_clear (rhs);
   1177      1.1  mrg 	    longjmp (errjmpbuf, 1);
   1178      1.1  mrg 	  }
   1179      1.1  mrg 	if (mpz_cmp_ui (rhs, 256) >= 0)
   1180      1.1  mrg 	  {
   1181      1.1  mrg 	    error = "logarithm base too large";
   1182      1.1  mrg 	    mpz_clear (lhs); mpz_clear (rhs);
   1183      1.1  mrg 	    longjmp (errjmpbuf, 1);
   1184      1.1  mrg 	  }
   1185      1.1  mrg 	cnt = mpz_sizeinbase (lhs, mpz_get_ui (rhs));
   1186      1.1  mrg 	mpz_set_ui (r, cnt - 1);
   1187      1.1  mrg 	mpz_clear (lhs); mpz_clear (rhs);
   1188      1.1  mrg       }
   1189      1.1  mrg       return;
   1190      1.1  mrg     case FERMAT:
   1191      1.1  mrg       {
   1192      1.1  mrg 	unsigned long int t;
   1193      1.1  mrg 	mpz_init (lhs);
   1194      1.1  mrg 	mpz_eval_expr (lhs, e->operands.ops.lhs);
   1195      1.1  mrg 	t = (unsigned long int) 1 << mpz_get_ui (lhs);
   1196      1.1  mrg 	if (mpz_cmp_ui (lhs, ~(unsigned long int) 0) > 0 || t == 0)
   1197      1.1  mrg 	  {
   1198      1.1  mrg 	    error = "too large Mersenne number index";
   1199      1.1  mrg 	    mpz_clear (lhs);
   1200      1.1  mrg 	    longjmp (errjmpbuf, 1);
   1201      1.1  mrg 	  }
   1202      1.1  mrg 	mpz_set_ui (r, 1);
   1203      1.1  mrg 	mpz_mul_2exp (r, r, t);
   1204      1.1  mrg 	mpz_add_ui (r, r, 1);
   1205      1.1  mrg 	mpz_clear (lhs);
   1206      1.1  mrg       }
   1207      1.1  mrg       return;
   1208      1.1  mrg     case MERSENNE:
   1209      1.1  mrg       mpz_init (lhs);
   1210      1.1  mrg       mpz_eval_expr (lhs, e->operands.ops.lhs);
   1211      1.1  mrg       if (mpz_cmp_ui (lhs, ~(unsigned long int) 0) > 0)
   1212      1.1  mrg 	{
   1213      1.1  mrg 	  error = "too large Mersenne number index";
   1214      1.1  mrg 	  mpz_clear (lhs);
   1215      1.1  mrg 	  longjmp (errjmpbuf, 1);
   1216      1.1  mrg 	}
   1217      1.1  mrg       mpz_set_ui (r, 1);
   1218      1.1  mrg       mpz_mul_2exp (r, r, mpz_get_ui (lhs));
   1219      1.1  mrg       mpz_sub_ui (r, r, 1);
   1220      1.1  mrg       mpz_clear (lhs);
   1221      1.1  mrg       return;
   1222      1.1  mrg     case FIBONACCI:
   1223      1.1  mrg       { mpz_t t;
   1224      1.1  mrg 	unsigned long int n, i;
   1225      1.1  mrg 	mpz_init (lhs);
   1226      1.1  mrg 	mpz_eval_expr (lhs, e->operands.ops.lhs);
   1227      1.1  mrg 	if (mpz_sgn (lhs) <= 0 || mpz_cmp_si (lhs, 1000000000) > 0)
   1228      1.1  mrg 	  {
   1229      1.1  mrg 	    error = "Fibonacci index out of range";
   1230      1.1  mrg 	    mpz_clear (lhs);
   1231      1.1  mrg 	    longjmp (errjmpbuf, 1);
   1232      1.1  mrg 	  }
   1233      1.1  mrg 	n = mpz_get_ui (lhs);
   1234      1.1  mrg 	mpz_clear (lhs);
   1235      1.1  mrg 
   1236      1.1  mrg #if __GNU_MP_VERSION > 2 || __GNU_MP_VERSION_MINOR >= 1
   1237      1.1  mrg 	mpz_fib_ui (r, n);
   1238      1.1  mrg #else
   1239      1.1  mrg 	mpz_init_set_ui (t, 1);
   1240      1.1  mrg 	mpz_set_ui (r, 1);
   1241      1.1  mrg 
   1242      1.1  mrg 	if (n <= 2)
   1243      1.1  mrg 	  mpz_set_ui (r, 1);
   1244      1.1  mrg 	else
   1245      1.1  mrg 	  {
   1246      1.1  mrg 	    for (i = 3; i <= n; i++)
   1247      1.1  mrg 	      {
   1248      1.1  mrg 		mpz_add (t, t, r);
   1249      1.1  mrg 		mpz_swap (t, r);
   1250      1.1  mrg 	      }
   1251      1.1  mrg 	  }
   1252      1.1  mrg 	mpz_clear (t);
   1253      1.1  mrg #endif
   1254      1.1  mrg       }
   1255      1.1  mrg       return;
   1256      1.1  mrg     case RANDOM:
   1257      1.1  mrg       {
   1258      1.1  mrg 	unsigned long int n;
   1259      1.1  mrg 	mpz_init (lhs);
   1260      1.1  mrg 	mpz_eval_expr (lhs, e->operands.ops.lhs);
   1261      1.1  mrg 	if (mpz_sgn (lhs) <= 0 || mpz_cmp_si (lhs, 1000000000) > 0)
   1262      1.1  mrg 	  {
   1263      1.1  mrg 	    error = "random number size out of range";
   1264      1.1  mrg 	    mpz_clear (lhs);
   1265      1.1  mrg 	    longjmp (errjmpbuf, 1);
   1266      1.1  mrg 	  }
   1267      1.1  mrg 	n = mpz_get_ui (lhs);
   1268      1.1  mrg 	mpz_clear (lhs);
   1269      1.1  mrg 	mpz_urandomb (r, rstate, n);
   1270      1.1  mrg       }
   1271      1.1  mrg       return;
   1272      1.1  mrg     case NEXTPRIME:
   1273      1.1  mrg       {
   1274      1.1  mrg 	mpz_eval_expr (r, e->operands.ops.lhs);
   1275      1.1  mrg 	mpz_nextprime (r, r);
   1276      1.1  mrg       }
   1277      1.1  mrg       return;
   1278      1.1  mrg     case BINOM:
   1279      1.1  mrg       mpz_init (lhs); mpz_init (rhs);
   1280      1.1  mrg       mpz_eval_expr (lhs, e->operands.ops.lhs);
   1281      1.1  mrg       mpz_eval_expr (rhs, e->operands.ops.rhs);
   1282      1.1  mrg       {
   1283      1.1  mrg 	unsigned long int k;
   1284      1.1  mrg 	if (mpz_cmp_ui (rhs, ~(unsigned long int) 0) > 0)
   1285      1.1  mrg 	  {
   1286      1.1  mrg 	    error = "k too large in (n over k) expression";
   1287      1.1  mrg 	    mpz_clear (lhs); mpz_clear (rhs);
   1288      1.1  mrg 	    longjmp (errjmpbuf, 1);
   1289      1.1  mrg 	  }
   1290      1.1  mrg 	k = mpz_get_ui (rhs);
   1291      1.1  mrg 	mpz_bin_ui (r, lhs, k);
   1292      1.1  mrg       }
   1293      1.1  mrg       mpz_clear (lhs); mpz_clear (rhs);
   1294      1.1  mrg       return;
   1295      1.1  mrg     case TIMING:
   1296      1.1  mrg       {
   1297      1.1  mrg 	int t0;
   1298      1.1  mrg 	t0 = cputime ();
   1299      1.1  mrg 	mpz_eval_expr (r, e->operands.ops.lhs);
   1300      1.1  mrg 	printf ("time: %d\n", cputime () - t0);
   1301      1.1  mrg       }
   1302      1.1  mrg       return;
   1303      1.1  mrg     default:
   1304      1.1  mrg       abort ();
   1305      1.1  mrg     }
   1306      1.1  mrg }
   1307      1.1  mrg 
   1308      1.1  mrg /* Evaluate the expression E modulo MOD and put the result in R.  */
   1309      1.1  mrg void
   1310      1.1  mrg mpz_eval_mod_expr (mpz_ptr r, expr_t e, mpz_ptr mod)
   1311      1.1  mrg {
   1312      1.1  mrg   mpz_t lhs, rhs;
   1313      1.1  mrg 
   1314      1.1  mrg   switch (e->op)
   1315      1.1  mrg     {
   1316      1.1  mrg       case POW:
   1317      1.1  mrg 	mpz_init (lhs); mpz_init (rhs);
   1318      1.1  mrg 	mpz_eval_mod_expr (lhs, e->operands.ops.lhs, mod);
   1319      1.1  mrg 	mpz_eval_expr (rhs, e->operands.ops.rhs);
   1320      1.1  mrg 	mpz_powm (r, lhs, rhs, mod);
   1321      1.1  mrg 	mpz_clear (lhs); mpz_clear (rhs);
   1322      1.1  mrg 	return;
   1323      1.1  mrg       case PLUS:
   1324      1.1  mrg 	mpz_init (lhs); mpz_init (rhs);
   1325      1.1  mrg 	mpz_eval_mod_expr (lhs, e->operands.ops.lhs, mod);
   1326      1.1  mrg 	mpz_eval_mod_expr (rhs, e->operands.ops.rhs, mod);
   1327      1.1  mrg 	mpz_add (r, lhs, rhs);
   1328      1.1  mrg 	if (mpz_cmp_si (r, 0L) < 0)
   1329      1.1  mrg 	  mpz_add (r, r, mod);
   1330      1.1  mrg 	else if (mpz_cmp (r, mod) >= 0)
   1331      1.1  mrg 	  mpz_sub (r, r, mod);
   1332      1.1  mrg 	mpz_clear (lhs); mpz_clear (rhs);
   1333      1.1  mrg 	return;
   1334      1.1  mrg       case MINUS:
   1335      1.1  mrg 	mpz_init (lhs); mpz_init (rhs);
   1336      1.1  mrg 	mpz_eval_mod_expr (lhs, e->operands.ops.lhs, mod);
   1337      1.1  mrg 	mpz_eval_mod_expr (rhs, e->operands.ops.rhs, mod);
   1338      1.1  mrg 	mpz_sub (r, lhs, rhs);
   1339      1.1  mrg 	if (mpz_cmp_si (r, 0L) < 0)
   1340      1.1  mrg 	  mpz_add (r, r, mod);
   1341      1.1  mrg 	else if (mpz_cmp (r, mod) >= 0)
   1342      1.1  mrg 	  mpz_sub (r, r, mod);
   1343      1.1  mrg 	mpz_clear (lhs); mpz_clear (rhs);
   1344      1.1  mrg 	return;
   1345      1.1  mrg       case MULT:
   1346      1.1  mrg 	mpz_init (lhs); mpz_init (rhs);
   1347      1.1  mrg 	mpz_eval_mod_expr (lhs, e->operands.ops.lhs, mod);
   1348      1.1  mrg 	mpz_eval_mod_expr (rhs, e->operands.ops.rhs, mod);
   1349      1.1  mrg 	mpz_mul (r, lhs, rhs);
   1350      1.1  mrg 	mpz_mod (r, r, mod);
   1351      1.1  mrg 	mpz_clear (lhs); mpz_clear (rhs);
   1352      1.1  mrg 	return;
   1353      1.1  mrg       default:
   1354      1.1  mrg 	mpz_init (lhs);
   1355      1.1  mrg 	mpz_eval_expr (lhs, e);
   1356      1.1  mrg 	mpz_mod (r, lhs, mod);
   1357      1.1  mrg 	mpz_clear (lhs);
   1358      1.1  mrg 	return;
   1359      1.1  mrg     }
   1360      1.1  mrg }
   1361      1.1  mrg 
   1362      1.1  mrg void
   1363      1.1  mrg cleanup_and_exit (int sig)
   1364      1.1  mrg {
   1365      1.1  mrg   switch (sig) {
   1366      1.1  mrg #ifdef LIMIT_RESOURCE_USAGE
   1367      1.1  mrg   case SIGXCPU:
   1368      1.1  mrg     printf ("expression took too long to evaluate%s\n", newline);
   1369      1.1  mrg     break;
   1370      1.1  mrg #endif
   1371      1.1  mrg   case SIGFPE:
   1372      1.1  mrg     printf ("divide by zero%s\n", newline);
   1373      1.1  mrg     break;
   1374      1.1  mrg   default:
   1375      1.1  mrg     printf ("expression required too much memory to evaluate%s\n", newline);
   1376      1.1  mrg     break;
   1377      1.1  mrg   }
   1378      1.1  mrg   exit (-2);
   1379      1.1  mrg }
   1380