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