00001 #include "numbpart.cc"
00002
00009
00010 namespace parse_term
00011 {
00012
00013 signed short int gZ_priority (const char ch)
00014 {
00015 switch (ch)
00016 {
00017 case '+': case '-': return 1;
00018 case '*': case '/': case ':': case '%': return 2;
00019 case '^': return 3;
00020 default: return 0;
00021 }
00022 }
00023
00024 bool gZ_mehrstellig(const char ch)
00025 {
00026 switch (ch)
00027 {
00028 case '+': case '-':
00029 case '*': case '/': case ':': case '%':
00030 case '^':
00031 return true;
00032 default: return false;
00033 }
00034 }
00035
00036 bool gZ_einstellig(const char ch)
00037 {
00038 switch (ch)
00039 {
00040 case 'F': case 'L': case 'P':
00041 case 'f': case 'p': case 's':
00042 case 'q': case 'i': case 'd':
00043 case 'r':
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057 return true;
00058 default: return false;
00059 }
00060 }
00061
00062 bool gZ_priority_le (const char a, const char b)
00063 {
00064 return gZ_priority(a)<=gZ_priority(b);
00065 }
00066
00067 bool gZ_priority_gr (const char a, const char b)
00068 {
00069 return gZ_priority(a)>gZ_priority(b);
00070 }
00071
00072 bool get_number (mpz_t n, char* &s, const char op='R', const char upto_op='\0')
00073 {
00074
00075
00076
00077
00078
00079
00080 while (s[0]==' ') s++;
00081
00082 bool term_structure_ok = true;
00083 char* s_anf = s;
00084 char h;
00085 mpz_t tmp;
00086 mpz_init(tmp);
00087
00088 if (s[0]=='(')
00089 {
00090 s++;
00091 term_structure_ok=get_number(tmp,s);
00092 if (s[0]==')') s++;
00093 else
00094 {
00095 term_structure_ok=false;
00096 cerr << "error: ')' expected at '" << s << "'" << endl;
00097 }
00098 }
00099 else if (gZ_einstellig(s[0]))
00100 {
00101 s++;
00102 term_structure_ok=get_number(tmp,s,s_anf[0]);
00103 }
00104 else if (s[0]>='0' && s[0]<='9')
00105 {
00106 char* anf=s;
00107 while (s[0]>='0' && s[0]<='9') s++;
00108 h=s[0]; s[0]='\0';
00109 if (mpz_set_str(tmp, anf, 10))
00110 {
00111 term_structure_ok=false;
00112 s[0]=h;
00113 cerr << "error: number expected at '" << anf << "'" << endl;
00114 }
00115 s[0]=h;
00116 }
00117 else term_structure_ok=false;
00118
00119 while (s[0]==' ') s++;
00120 if (s[0]=='*' && s[1]=='*') { s[0]=' '; ++s; s[0]='^'; }
00121 h=s[0];
00122
00123 if (term_structure_ok && !gZ_einstellig(op))
00124 {
00125 if (gZ_priority_gr(h,op) || (h=='^' && op=='^'))
00126 {
00127
00128
00129 #ifdef VERBOSE_WARN
00130 if (op=='^' && h=='^') cout << "Warning: a^b^c ambiguent; using a^(b^c)." << endl;
00131 #endif
00132 term_structure_ok=get_number(tmp,++s,h,op);
00133 if (s[0]=='*' && s[1]=='*') { s[0]=' '; ++s; s[0]='^'; }
00134 h=s[0];
00135 }
00136 }
00137
00138 if (term_structure_ok) switch (op)
00139 {
00140 case '\0':
00141 break;
00142 case 'R' :
00143
00144 mpz_set(n,tmp);
00145 break;
00146 case 'F' :
00147 {
00148 if (mpz_cmp_ui(tmp,100000)>0)
00149 {
00150 cerr << "fibonacci: argument to big: " << tmp << endl;
00151 exit(1);
00152 }
00153 if (mpz_sgn(tmp)<0)
00154 {
00155 cerr << "fibonacci: argument negative: " << tmp << endl;
00156 exit(1);
00157 }
00158 #ifdef VERBOSE_INFO
00159 cout << "computing fibonacci number" << endl;
00160 #endif
00161 mpz_fib_ui(n,mpz_get_ui(tmp));
00162 }
00163 break;
00164 case 'L' :
00165 {
00166 if (mpz_cmp_ui(tmp,100000)>0)
00167 {
00168 cerr << "lucas: argument too big: " << tmp << endl;
00169 exit(1);
00170 }
00171 if (mpz_sgn(tmp)<0)
00172 {
00173 cerr << "lucas: argument negative: " << tmp << endl;
00174 exit(1);
00175 }
00176 #ifdef VERBOSE_INFO
00177 cout << "computing lucas number" << endl;
00178 #endif
00179 mpz_lucnum_ui(n,mpz_get_ui(tmp));
00180 }
00181 break;
00182 case 'P' :
00183 {
00184 if (mpz_cmp_ui(tmp,1000000)>0)
00185 {
00186 cerr << "partition number: argument to big: " << tmp << endl;
00187 exit(1);
00188 }
00189 if (mpz_sgn(tmp)<0)
00190 {
00191 cerr << "partition number: argument negative: " << tmp << endl;
00192 exit(1);
00193 }
00194 #ifdef VERBOSE_INFO
00195 cout << "computing partition number" << endl;
00196 #endif
00197 numbpart::numbpart(n,mpz_get_ui(tmp));
00198 }
00199 break;
00200 case 'f' :
00201 {
00202 if (mpz_cmp_ui(tmp,100000)>0)
00203 {
00204 cerr << "factorial: argument to big: " << tmp << endl;
00205 exit(1);
00206 }
00207 if (mpz_sgn(tmp)<0)
00208 {
00209 cerr << "factorial: argument negative: " << tmp << endl;
00210 exit(1);
00211 }
00212 #ifdef VERBOSE_INFO
00213 cout << "computing factorial" << endl;
00214 #endif
00215 mpz_fac_ui(n,mpz_get_ui(tmp));
00216 }
00217 break;
00218 case 'p' :
00219 {
00220 mpz_set(n,tmp); mpz_sub_ui(n,n,1);
00221 do { mpz_nextprime(n,n); } while (!mpz_probab_prime_p(n,50));
00222 }
00223 break;
00224 case 's' :
00225 {
00226
00227 mpz_set(n,tmp);
00228 if (mpz_cmp_ui(n,7)<0) mpz_set_ui(n,7);
00229 mpz_sub_ui(n,n,1);
00230 do
00231 {
00232 mpz_nextprime(n,n);
00233 mpz_div_ui(tmp,n,2);
00234 } while (!mpz_probab_prime_p(tmp,20) || !mpz_probab_prime_p(n,50) );
00235 }
00236 break;
00237 case 'q' :
00238 {
00239 #ifdef VERBOSE_NOTICE
00240 cout << "special command q, testing argument..." << endl;
00241 #endif
00242 mpz_set(n,tmp);
00243 if (!mpz_probab_prime_p(n,50))
00244 {
00245 cout << "argument is not prime, aborting program." << endl;
00246 exit(0);
00247 }
00248 }
00249 break;
00250 case 'i' :
00251 mpz_add_ui(n,tmp,1);
00252 break;
00253 case 'd' :
00254 mpz_sub_ui(n,tmp,1);
00255 break;
00256 case 'r' :
00257 mpz_sqrt(n,tmp);
00258 break;
00259 case '+' :
00260 mpz_add(n,n,tmp);
00261 break;
00262 case '-' :
00263 mpz_sub(n,n,tmp);
00264 break;
00265 case '*' :
00266 mpz_mul(n,n,tmp);
00267 break;
00268 case '/' :
00269 case ':' :
00270 {
00271 mpz_t q;
00272 mpz_init(q);
00273 mpz_div(q,n,tmp);
00274 #ifdef VERBOSE_WARN
00275 mpz_mul(tmp,q,tmp);
00276 if (mpz_cmp(tmp,n))
00277 {
00278 cout << "Warning: result of division is truncated!" << endl;
00279 }
00280 #endif
00281 mpz_set(n,q);
00282 mpz_clear(q);
00283 }
00284 break;
00285 case '%' :
00286 mpz_mod(n,n,tmp);
00287 break;
00288 case '^' :
00289 #ifdef VERBOSE_WARN
00290 if (h=='^') cout << "Warning: a^b^c ambiguent; using (a^b)^c." << endl;
00291 #endif
00292 if (!mpz_fits_ulong_p(tmp))
00293 {
00294 cerr << "argument for exponentiation too big!" << endl;
00295 exit(1);
00296 }
00297 mpz_pow_ui(n,n,mpz_get_ui(tmp));
00298 break;
00299 default :
00300 s=--s_anf;
00301 cerr << "error: operation +-*/:^ expected at '" << s << "'" << endl;
00302 term_structure_ok=false;
00303 break;
00304 }
00305 mpz_clear(tmp);
00306
00307 if ((gZ_einstellig(op) || op=='R') && !(h=='\0'||h==')'||gZ_mehrstellig(h)) ) return false;
00308 if (gZ_einstellig(op)) return term_structure_ok;
00309
00310 if (term_structure_ok && h!='\0' && h!=')' )
00311 {
00312
00313
00314 if (upto_op=='\0') return get_number(n,++s,h);
00315 if (gZ_priority_le(h,upto_op)) return term_structure_ok;
00316 else return get_number(n,++s,h,upto_op);
00317 }
00318 else return term_structure_ok;
00319 }
00320
00321 }