1 /* mpq expression evaluation 2 3 Copyright 2000, 2001, 2002 Free Software Foundation, Inc. 4 5 This file is part of the GNU MP Library. 6 7 The GNU MP Library is free software; you can redistribute it and/or modify 8 it under the terms of the GNU Lesser General Public License as published by 9 the Free Software Foundation; either version 3 of the License, or (at your 10 option) any later version. 11 12 The GNU MP Library is distributed in the hope that it will be useful, but 13 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 14 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 15 License for more details. 16 17 You should have received a copy of the GNU Lesser General Public License 18 along with the GNU MP Library. If not, see http://www.gnu.org/licenses/. */ 19 20 #include <stdio.h> 21 #include <string.h> 22 #include "gmp.h" 23 #include "expr-impl.h" 24 25 26 /* Change this to "#define TRACE(x) x" to get some traces. */ 27 #define TRACE(x) 28 29 30 static void 31 e_mpq_pow_ui (mpq_ptr r, mpq_srcptr b, unsigned long e) 32 { 33 mpz_pow_ui (mpq_numref(r), mpq_numref(b), e); 34 mpz_pow_ui (mpq_denref(r), mpq_denref(b), e); 35 } 36 37 /* Wrapped because mpq_sgn is a macro. */ 38 static int 39 e_mpq_sgn (mpq_srcptr x) 40 { 41 return mpq_sgn (x); 42 } 43 44 /* Wrapped because mpq_equal only guarantees a non-zero return, whereas we 45 want 1 or 0 for == and !=. */ 46 static int 47 e_mpq_equal (mpq_srcptr x, mpq_srcptr y) 48 { 49 return mpq_equal (x, y) != 0; 50 } 51 static int 52 e_mpq_notequal (mpq_srcptr x, mpq_srcptr y) 53 { 54 return ! mpq_equal (x, y); 55 } 56 57 static void 58 e_mpq_num (mpq_ptr w, mpq_srcptr x) 59 { 60 if (w != x) 61 mpz_set (mpq_numref(w), mpq_numref(x)); 62 mpz_set_ui (mpq_denref(w), 1L); 63 } 64 static void 65 e_mpq_den (mpq_ptr w, mpq_srcptr x) 66 { 67 if (w == x) 68 mpz_swap (mpq_numref(w), mpq_denref(w)); 69 else 70 mpz_set (mpq_numref(w), mpq_denref(x)); 71 mpz_set_ui (mpq_denref(w), 1L); 72 } 73 74 75 static const struct mpexpr_operator_t _mpq_expr_standard_table[] = { 76 77 { "**", (mpexpr_fun_t) e_mpq_pow_ui, 78 MPEXPR_TYPE_BINARY_UI | MPEXPR_TYPE_RIGHTASSOC, 220 }, 79 80 { "!", (mpexpr_fun_t) e_mpq_sgn, 81 MPEXPR_TYPE_LOGICAL_NOT | MPEXPR_TYPE_PREFIX, 210 }, 82 { "-", (mpexpr_fun_t) mpq_neg, 83 MPEXPR_TYPE_UNARY | MPEXPR_TYPE_PREFIX, 210 }, 84 85 { "*", (mpexpr_fun_t) mpq_mul, MPEXPR_TYPE_BINARY, 200 }, 86 { "/", (mpexpr_fun_t) mpq_div, MPEXPR_TYPE_BINARY, 200 }, 87 88 { "+", (mpexpr_fun_t) mpq_add, MPEXPR_TYPE_BINARY, 190 }, 89 { "-", (mpexpr_fun_t) mpq_sub, MPEXPR_TYPE_BINARY, 190 }, 90 91 { "<<", (mpexpr_fun_t) mpq_mul_2exp, MPEXPR_TYPE_BINARY_UI, 180 }, 92 { ">>", (mpexpr_fun_t) mpq_div_2exp, MPEXPR_TYPE_BINARY_UI, 180 }, 93 94 { "<=", (mpexpr_fun_t) mpq_cmp, MPEXPR_TYPE_CMP_LE, 170 }, 95 { "<", (mpexpr_fun_t) mpq_cmp, MPEXPR_TYPE_CMP_LT, 170 }, 96 { ">=", (mpexpr_fun_t) mpq_cmp, MPEXPR_TYPE_CMP_GE, 170 }, 97 { ">", (mpexpr_fun_t) mpq_cmp, MPEXPR_TYPE_CMP_GT, 170 }, 98 99 { "==", (mpexpr_fun_t) e_mpq_equal, MPEXPR_TYPE_I_BINARY, 160 }, 100 { "!=", (mpexpr_fun_t) e_mpq_notequal, MPEXPR_TYPE_I_BINARY, 160 }, 101 102 { "&&", (mpexpr_fun_t) e_mpq_sgn, MPEXPR_TYPE_LOGICAL_AND, 120 }, 103 { "||", (mpexpr_fun_t) e_mpq_sgn, MPEXPR_TYPE_LOGICAL_OR, 110 }, 104 105 { ":", NULL, MPEXPR_TYPE_COLON, 101 }, 106 { "?", (mpexpr_fun_t) e_mpq_sgn, MPEXPR_TYPE_QUESTION, 100 }, 107 108 { ")", (mpexpr_fun_t) e_mpq_sgn, MPEXPR_TYPE_CLOSEPAREN, 4 }, 109 { "(", (mpexpr_fun_t) e_mpq_sgn, MPEXPR_TYPE_OPENPAREN, 3 }, 110 { ",", (mpexpr_fun_t) e_mpq_sgn, MPEXPR_TYPE_ARGSEP, 2 }, 111 { "$", NULL, MPEXPR_TYPE_VARIABLE, 1 }, 112 113 { "abs", (mpexpr_fun_t) mpq_abs, MPEXPR_TYPE_UNARY }, 114 { "cmp", (mpexpr_fun_t) mpq_cmp, MPEXPR_TYPE_I_BINARY }, 115 { "den", (mpexpr_fun_t) e_mpq_den, MPEXPR_TYPE_UNARY }, 116 { "max", (mpexpr_fun_t) mpq_cmp, MPEXPR_TYPE_MAX | MPEXPR_TYPE_PAIRWISE }, 117 { "min", (mpexpr_fun_t) mpq_cmp, MPEXPR_TYPE_MIN | MPEXPR_TYPE_PAIRWISE }, 118 { "num", (mpexpr_fun_t) e_mpq_num, MPEXPR_TYPE_UNARY }, 119 { "sgn", (mpexpr_fun_t) e_mpq_sgn, MPEXPR_TYPE_I_UNARY }, 120 121 { NULL } 122 }; 123 124 const struct mpexpr_operator_t * const mpq_expr_standard_table 125 = _mpq_expr_standard_table; 126 127 128 int 129 #if HAVE_STDARG 130 mpq_expr (mpq_ptr res, int base, const char *e, ...) 131 #else 132 mpq_expr (va_alist) 133 va_dcl 134 #endif 135 { 136 mpq_srcptr var[MPEXPR_VARIABLES]; 137 va_list ap; 138 int ret; 139 #if HAVE_STDARG 140 va_start (ap, e); 141 #else 142 mpq_ptr res; 143 int base; 144 const char *e; 145 va_start (ap); 146 res = va_arg (ap, mpq_ptr); 147 base = va_arg (ap, int); 148 e = va_arg (ap, const char *); 149 #endif 150 151 TRACE (printf ("mpq_expr(): base %d, %s\n", base, e)); 152 ret = mpexpr_va_to_var ((void **) var, ap); 153 va_end (ap); 154 155 if (ret != MPEXPR_RESULT_OK) 156 return ret; 157 158 return mpq_expr_a (mpq_expr_standard_table, res, base, e, strlen(e), var); 159 } 160