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