00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include <config.h>
00024 #include "checked.defs.hh"
00025
00026 namespace Parma_Polyhedra_Library {
00027
00028 namespace Checked {
00029
00031 unsigned long rational_sqrt_precision_parameter;
00032
00033 struct number_struct {
00034 unsigned int base;
00035 bool neg_mantissa;
00036 bool neg_exponent;
00037 std::string mantissa;
00038 unsigned long exponent;
00039 };
00040
00046 inline int
00047 get_digit(int c, int base = 10) {
00048 if (c >= '0' && c < '0' + (base > 10 ? 10 : base))
00049 return c - '0';
00050 if (base > 10) {
00051 base -= 10;
00052 if (c >= 'A' && c < 'A' + base)
00053 return c - 'A' + 10;
00054 if (c >= 'a' && c < 'a' + base)
00055 return c - 'a' + 10;
00056 }
00057 return -1;
00058 }
00059
00067 inline bool
00068 sum_sign(bool& a_neg, unsigned long& a_mod,
00069 bool b_neg, unsigned long b_mod) {
00070 if (a_neg == b_neg) {
00071 if (a_mod > ULONG_MAX - b_mod)
00072 return false;
00073 a_mod += b_mod;
00074 }
00075 else if (a_mod >= b_mod)
00076 a_mod -= b_mod;
00077 else {
00078 a_neg = !a_neg;
00079 a_mod = b_mod - a_mod;
00080 }
00081 return true;
00082 }
00083
00084
00090 Result
00091 parse_number_part(std::istream& is, number_struct& num) {
00092 enum { BASE, INTEGER, FRACTIONAL, EXPONENT } state = BASE;
00093 unsigned long max_exp_div;
00094 int max_exp_rem;
00095 bool empty_exponent = true;
00096 bool empty_mantissa = true;
00097 long exponent_offset = 0;
00098 num.base = 10;
00099 num.neg_mantissa = false;
00100 num.neg_exponent = false;
00101 num.mantissa.erase();
00102 num.exponent = 0;
00103 int c;
00104 do {
00105 c = is.get();
00106 } while (isspace(c));
00107 switch (c) {
00108 case '-':
00109 num.neg_mantissa = true;
00110
00111 case '+':
00112 c = is.get();
00113 if (c == 'i' || c == 'I')
00114 goto inf;
00115 break;
00116 case 'n':
00117 case 'N':
00118 c = is.get();
00119 if (c != 'a' && c != 'A')
00120 goto error;
00121 c = is.get();
00122 if (c != 'n' && c != 'N')
00123 goto error;
00124 return VC_NAN;
00125 inf:
00126 case 'i':
00127 case 'I':
00128 c = is.get();
00129 if (c != 'n' && c != 'n')
00130 goto error;
00131 c = is.get();
00132 if (c != 'f' && c != 'F')
00133 goto error;
00134 return num.neg_mantissa ? VC_MINUS_INFINITY : VC_PLUS_INFINITY;
00135 }
00136 if (get_digit(c, 10) < 0)
00137 goto error;
00138 if (c == '0') {
00139 int d = is.get();
00140 if (d == 'x' || d == 'X') {
00141 num.base = 16;
00142 state = INTEGER;
00143 c = is.get();
00144 }
00145 else {
00146 c = d;
00147 empty_mantissa = false;
00148 }
00149 }
00150 else {
00151 num.mantissa += (char) c;
00152 empty_mantissa = false;
00153 c = is.get();
00154 }
00155 while (true) {
00156 switch (state) {
00157 case BASE:
00158 if (get_digit(c, 10) >= 0) {
00159 if (c != '0' || !num.mantissa.empty())
00160 num.mantissa += (char) c;
00161 empty_mantissa = false;
00162 break;
00163 }
00164 if (c == '^') {
00165 c = is.get();
00166 if (c != '^')
00167 goto error;
00168 std::string::const_iterator i;
00169 num.base = 0;
00170 for (i = num.mantissa.begin(); i != num.mantissa.end(); i++) {
00171 num.base = num.base * 10 + (*i - '0');
00172 if (num.base > 36)
00173 goto error;
00174 }
00175 if (num.base < 2)
00176 goto error;
00177 num.mantissa.erase();
00178 empty_mantissa = true;
00179 state = INTEGER;
00180 break;
00181 }
00182 goto integer;
00183 case INTEGER:
00184 if (get_digit(c, num.base) >= 0) {
00185 if (c != '0' || !num.mantissa.empty())
00186 num.mantissa += (char) c;
00187 empty_mantissa = false;
00188 break;
00189 }
00190 integer:
00191 if (c == '.') {
00192 state = FRACTIONAL;
00193 break;
00194 }
00195 goto fractional;
00196 case FRACTIONAL:
00197 if (get_digit(c, num.base) >= 0) {
00198 exponent_offset--;
00199 if (c != '0' || !num.mantissa.empty())
00200 num.mantissa += (char) c;
00201 empty_mantissa = false;
00202 break;
00203 }
00204 fractional:
00205 if (empty_mantissa)
00206 goto error;
00207 if (c == 'e' || c == 'E')
00208 goto exp;
00209 if (c == '*') {
00210 c = is.get();
00211 if (c != '^')
00212 goto error;
00213 exp:
00214 state = EXPONENT;
00215 max_exp_div = LONG_MAX / num.base;
00216 max_exp_rem = LONG_MAX % num.base;
00217 c = is.get();
00218 if (c == '-') {
00219 num.neg_exponent = true;
00220 break;
00221 }
00222 if (c == '+')
00223 break;
00224 continue;
00225 }
00226 goto ok;
00227 case EXPONENT:
00228 int d = get_digit(c, 10);
00229 if (d >= 0) {
00230 empty_exponent = false;
00231 if (num.exponent > max_exp_div
00232 || (num.exponent == max_exp_div && d > max_exp_rem))
00233 return V_CVT_STR_UNK;
00234 num.exponent = num.exponent * 10 + d;
00235 break;
00236 }
00237 if (empty_exponent)
00238 goto error;
00239 goto ok;
00240 }
00241 c = is.get();
00242 }
00243
00244 {
00245 ok:
00246 is.unget();
00247 unsigned int n = num.mantissa.size();
00248 while (n > 0 && num.mantissa[n - 1] == '0') {
00249 --n;
00250 exponent_offset++;
00251 }
00252 num.mantissa.erase(n);
00253 bool neg;
00254 if (exponent_offset < 0) {
00255 neg = true;
00256 exponent_offset = -exponent_offset;
00257 }
00258 else
00259 neg = false;
00260 sum_sign(num.neg_exponent, num.exponent,
00261 neg, exponent_offset);
00262 return V_EQ;
00263 }
00264
00265 error:
00266 is.unget();
00267 return V_CVT_STR_UNK;
00268 }
00269
00270
00271
00272
00273
00274
00275 Result
00276 parse_number(std::istream& is, number_struct& num, number_struct& den) {
00277
00278 Result r = parse_number_part(is, num);
00279 if (r != V_EQ)
00280 return r;
00281 if (is.get() != '/') {
00282 is.unget();
00283 den.base = 0;
00284 return r;
00285 }
00286
00287 r = parse_number_part(is, den);
00288 if (r != V_EQ)
00289 return V_CVT_STR_UNK;
00290 if (num.base == den.base) {
00291 if (sum_sign(num.neg_exponent, num.exponent,
00292 !den.neg_exponent, den.exponent)) {
00293 if (num.neg_exponent) {
00294 den.neg_exponent = false;
00295 den.exponent = num.exponent;
00296 num.exponent = 0;
00297 }
00298 else
00299 den.exponent = 0;
00300 }
00301 }
00302 return V_EQ;
00303 }
00304
00305
00306 Result
00307 input_mpq(mpq_class& to, std::istream& is) {
00308 number_struct num_struct;
00309 number_struct den_struct;
00310 Result r = parse_number(is, num_struct, den_struct);
00311 if (r != V_EQ)
00312 return r;
00313 if (den_struct.base && den_struct.mantissa.empty())
00314 return VC_NAN;
00315 if (num_struct.mantissa.empty()) {
00316 to = 0;
00317 return V_EQ;
00318 }
00319 mpz_ptr num = to.get_num().get_mpz_t();
00320 mpz_ptr den = to.get_den().get_mpz_t();
00321 mpz_set_str(num, num_struct.mantissa.c_str(), num_struct.base);
00322 if (den_struct.base) {
00323 if (num_struct.neg_mantissa ^ den_struct.neg_mantissa)
00324 mpz_neg(num, num);
00325 mpz_set_str(den, den_struct.mantissa.c_str(), den_struct.base);
00326 if (num_struct.exponent || den_struct.exponent) {
00327
00328 mpz_t z;
00329 mpz_init(z);
00330 if (num_struct.exponent) {
00331 mpz_ui_pow_ui(z, num_struct.base, num_struct.exponent);
00332 if (num_struct.neg_exponent)
00333 mpz_mul(den, den, z);
00334 else
00335 mpz_mul(num, num, z);
00336 }
00337 if (den_struct.exponent) {
00338 mpz_ui_pow_ui(z, den_struct.base, den_struct.exponent);
00339 if (den_struct.neg_exponent)
00340 mpz_mul(num, num, z);
00341 else
00342 mpz_mul(den, den, z);
00343 }
00344 mpz_clear(z);
00345 }
00346 }
00347 else {
00348 if (num_struct.neg_mantissa)
00349 mpz_neg(num, num);
00350 if (num_struct.exponent) {
00351 if (num_struct.neg_exponent) {
00352
00353 mpz_ui_pow_ui(den, num_struct.base, num_struct.exponent);
00354 goto end;
00355 }
00356
00357 mpz_t z;
00358 mpz_init(z);
00359 mpz_ui_pow_ui(z, num_struct.base, num_struct.exponent);
00360 mpz_mul(num, num, z);
00361 mpz_clear(z);
00362 }
00363 mpz_set_ui(den, 1);
00364 return V_EQ;
00365 }
00366 end:
00367
00368 to.canonicalize();
00369 return V_EQ;
00370 }
00371
00372 }
00373
00374 }
00375