diff options
author | Kevin Ryde <user42@zip.com.au> | 2001-08-16 00:06:03 +0200 |
---|---|---|
committer | Kevin Ryde <user42@zip.com.au> | 2001-08-16 00:06:03 +0200 |
commit | be55c6e600c7a6ac646b6f2160cae69e3e8387fe (patch) | |
tree | 6d61360aa112025cee3ae007d2de49cbad240cc0 /demos | |
parent | 228661011f7d148f1aa30a5e7b8b09438da459a9 (diff) | |
download | gmp-be55c6e600c7a6ac646b6f2160cae69e3e8387fe.tar.gz |
Regenerate for:
* demos/calc/calc.y, calclex.l: Reposition "%{" so copyright notice
gets into generated files.
Diffstat (limited to 'demos')
-rw-r--r-- | demos/calc/calc.c | 171 |
1 files changed, 127 insertions, 44 deletions
diff --git a/demos/calc/calc.c b/demos/calc/calc.c index b91fcc164..f9c537fd1 100644 --- a/demos/calc/calc.c +++ b/demos/calc/calc.c @@ -31,7 +31,90 @@ #define RSHIFT 281 #define UMINUS 282 -#line 86 "calc.y" +#line 1 "calc.y" + +/* A simple integer desk calculator using yacc and gmp. + +Copyright 2000, 2001 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +This program is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation; either version 2 of the License, or (at your option) any later +version. + +This program is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A +PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with +this program; if not, write to the Free Software Foundation, Inc., 59 Temple +Place - Suite 330, Boston, MA 02111-1307, USA. */ + + +/* This is a simple program, meant only to show one way to use GMP for this + sort of thing. There's few features, and error checking is minimal. + Standard input is read, there's no command line options. + + Examples: + 2+3*4 expressions are evaluated + x=5^6 variables a to z can be set and used + + Operators: + + - * arithmetic + / % division and remainder (rounding towards negative infinity) + ^ exponentiation + ! factorial + << >> left and right shifts + <= >= > \ comparisons, giving 1 if true, 0 if false + == != < / + && || logical and/or, giving 1 if true, 0 if false + + Functions: + abs(n) absolute value + bin(n,m) binomial coefficient + fib(n) fibonacci number + gcd(a,b,..) greatest common divisor + kron(a,b) kronecker symbol + lcm(a,b,..) least common multiple + nextprime(n) next prime after n + powm(b,e,m) modulo powering, b^e%m + root(n,r) r-th root + sqrt(n) square root + + Other: + hex \ set hex or decimal for input and output + decimal / ("0x" can be used for hex too) + quit exit program (EOF works too) + ; statements are separated with a ; or newline + \ continue expressions with \ before newline + # xxx comments are # though to newline + + Hex numbers must be entered in upper case, to distinguish them from the + variables a to f (like in bc). + + + Expressions are evaluated as they're read. If user defined functions + were wanted it'd be necessary to build a parse tree like pexpr.c does, or + a list of operations for a stack based evaluator. That would also make + it possible to detect and optimize evaluations "mod m" like pexpr.c does. + + A stack is used for intermediate values in the expression evaluation, + separate from the yacc parser stack. This is simple, makes error + recovery easy, minimizes the junk around mpz calls in the rules, and + saves initializing or clearing "mpz_t"s during a calculation. A + disadvantage though is that variables must be copied to the stack to be + worked on. A more sophisticated calculator or language system might be + able to avoid that when executing a compiled or semi-compiled form. + + Avoiding repeated initializing and clearing of "mpz_t"s is important. In + this program the time spent parsing is obviously much greater than any + possible saving from this, but a proper calculator or language should + take some trouble over it. Don't be surprised if an init/clear takes 3 + or more times as long as a 10 limb addition, depending on the system (see + the mpz_init_realloc_clear example in tune/README). */ + #include <stdio.h> #include <stdlib.h> @@ -87,7 +170,7 @@ mpz_t variable[26]; } -#line 142 "calc.y" +#line 140 "calc.y" typedef union { char *str; int var; @@ -174,11 +257,11 @@ static const short yyrhs[] = { 44, #if YYDEBUG != 0 static const short yyrline[] = { 0, - 166, 168, 170, 172, 173, 175, 177, 182, 188, 189, - 190, 195, 197, 198, 199, 200, 201, 202, 204, 206, - 208, 210, 212, 213, 214, 215, 216, 217, 219, 220, - 222, 223, 225, 227, 228, 230, 231, 232, 233, 235, - 237, 243, 253, 255, 257, 259 + 164, 166, 168, 170, 171, 173, 175, 180, 186, 187, + 188, 193, 195, 196, 197, 198, 199, 200, 202, 204, + 206, 208, 210, 211, 212, 213, 214, 215, 217, 218, + 220, 221, 223, 225, 226, 228, 229, 230, 231, 233, + 235, 241, 251, 253, 255, 257 }; #endif @@ -906,11 +989,11 @@ yyreduce: switch (yyn) { case 5: -#line 173 "calc.y" +#line 171 "calc.y" { sp = stack[0]; yyerrok; ; break;} case 7: -#line 177 "calc.y" +#line 175 "calc.y" { mpz_out_str (stdout, obase, sp); putchar ('\n'); sp--; @@ -918,7 +1001,7 @@ case 7: ; break;} case 8: -#line 182 "calc.y" +#line 180 "calc.y" { CHECK_VARIABLE (yyvsp[-2].var); mpz_swap (variable[yyvsp[-2].var], sp); @@ -927,131 +1010,131 @@ case 8: ; break;} case 9: -#line 188 "calc.y" +#line 186 "calc.y" { ibase = 16; obase = -16; ; break;} case 10: -#line 189 "calc.y" +#line 187 "calc.y" { ibase = 0; obase = 10; ; break;} case 11: -#line 190 "calc.y" +#line 188 "calc.y" { exit (0); ; break;} case 13: -#line 197 "calc.y" +#line 195 "calc.y" { sp--; mpz_add (sp, sp, sp+1); ; break;} case 14: -#line 198 "calc.y" +#line 196 "calc.y" { sp--; mpz_sub (sp, sp, sp+1); ; break;} case 15: -#line 199 "calc.y" +#line 197 "calc.y" { sp--; mpz_mul (sp, sp, sp+1); ; break;} case 16: -#line 200 "calc.y" +#line 198 "calc.y" { sp--; mpz_fdiv_q (sp, sp, sp+1); ; break;} case 17: -#line 201 "calc.y" +#line 199 "calc.y" { sp--; mpz_fdiv_r (sp, sp, sp+1); ; break;} case 18: -#line 202 "calc.y" +#line 200 "calc.y" { CHECK_UI ("exponentiation", sp); sp--; mpz_pow_ui (sp, sp, mpz_get_ui (sp+1)); ; break;} case 19: -#line 204 "calc.y" +#line 202 "calc.y" { CHECK_UI ("lshift", sp); sp--; mpz_mul_2exp (sp, sp, mpz_get_ui (sp+1)); ; break;} case 20: -#line 206 "calc.y" +#line 204 "calc.y" { CHECK_UI ("rshift", sp); sp--; mpz_fdiv_q_2exp (sp, sp, mpz_get_ui (sp+1)); ; break;} case 21: -#line 208 "calc.y" +#line 206 "calc.y" { CHECK_UI ("factorial", sp); mpz_fac_ui (sp, mpz_get_ui (sp)); ; break;} case 22: -#line 210 "calc.y" +#line 208 "calc.y" { mpz_neg (sp, sp); ; break;} case 23: -#line 212 "calc.y" +#line 210 "calc.y" { sp--; mpz_set_ui (sp, mpz_cmp (sp, sp+1) < 0); ; break;} case 24: -#line 213 "calc.y" +#line 211 "calc.y" { sp--; mpz_set_ui (sp, mpz_cmp (sp, sp+1) <= 0); ; break;} case 25: -#line 214 "calc.y" +#line 212 "calc.y" { sp--; mpz_set_ui (sp, mpz_cmp (sp, sp+1) == 0); ; break;} case 26: -#line 215 "calc.y" +#line 213 "calc.y" { sp--; mpz_set_ui (sp, mpz_cmp (sp, sp+1) != 0); ; break;} case 27: -#line 216 "calc.y" +#line 214 "calc.y" { sp--; mpz_set_ui (sp, mpz_cmp (sp, sp+1) >= 0); ; break;} case 28: -#line 217 "calc.y" +#line 215 "calc.y" { sp--; mpz_set_ui (sp, mpz_cmp (sp, sp+1) > 0); ; break;} case 29: -#line 219 "calc.y" +#line 217 "calc.y" { sp--; mpz_set_ui (sp, mpz_sgn (sp) && mpz_sgn (sp+1)); ; break;} case 30: -#line 220 "calc.y" +#line 218 "calc.y" { sp--; mpz_set_ui (sp, mpz_sgn (sp) || mpz_sgn (sp+1)); ; break;} case 31: -#line 222 "calc.y" +#line 220 "calc.y" { mpz_abs (sp, sp); ; break;} case 32: -#line 223 "calc.y" +#line 221 "calc.y" { sp--; CHECK_UI ("binomial", sp+1); mpz_bin_ui (sp, sp, mpz_get_ui (sp+1)); ; break;} case 33: -#line 225 "calc.y" +#line 223 "calc.y" { CHECK_UI ("fibonacci", sp); mpz_fib_ui (sp, mpz_get_ui (sp)); ; break;} case 35: -#line 228 "calc.y" +#line 226 "calc.y" { sp--; mpz_set_si (sp, mpz_kronecker (sp, sp+1)); ; break;} case 37: -#line 231 "calc.y" +#line 229 "calc.y" { mpz_nextprime (sp, sp); ; break;} case 38: -#line 232 "calc.y" +#line 230 "calc.y" { sp -= 2; mpz_powm (sp, sp, sp+1, sp+2); ; break;} case 39: -#line 233 "calc.y" +#line 231 "calc.y" { sp--; CHECK_UI ("nth-root", sp+1); mpz_root (sp, sp, mpz_get_ui (sp+1)); ; break;} case 40: -#line 235 "calc.y" +#line 233 "calc.y" { mpz_sqrt (sp, sp); ; break;} case 41: -#line 237 "calc.y" +#line 235 "calc.y" { sp++; CHECK_OVERFLOW (); @@ -1060,7 +1143,7 @@ case 41: ; break;} case 42: -#line 243 "calc.y" +#line 241 "calc.y" { sp++; CHECK_OVERFLOW (); @@ -1072,11 +1155,11 @@ case 42: ; break;} case 44: -#line 255 "calc.y" +#line 253 "calc.y" { sp--; mpz_gcd (sp, sp, sp+1); ; break;} case 46: -#line 259 "calc.y" +#line 257 "calc.y" { sp--; mpz_lcm (sp, sp, sp+1); ; break;} } @@ -1301,7 +1384,7 @@ yyerrhandle: } return 1; } -#line 261 "calc.y" +#line 259 "calc.y" yyerror (char *s) |