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