Mercurial > hg > xemacs-beta
comparison src/data.c @ 2013:f2fdfc131770
[xemacs-hg @ 2004-04-14 22:50:52 by james]
Work around GMP string to number limitations.
author | james |
---|---|
date | Wed, 14 Apr 2004 22:50:54 +0000 |
parents | a9cdbfb4716e |
children | 92f7301e4a23 |
comparison
equal
deleted
inserted
replaced
2012:dd25e95fdbe1 | 2013:f2fdfc131770 |
---|---|
1269 #endif | 1269 #endif |
1270 return make_float (atof ((const char *) p)); | 1270 return make_float (atof ((const char *) p)); |
1271 #ifdef HAVE_BIGFLOAT | 1271 #ifdef HAVE_BIGFLOAT |
1272 else | 1272 else |
1273 { | 1273 { |
1274 /* GMP bigfloat_set_string returns random values with initial + */ | 1274 /* The GMP version of bigfloat_set_string (mpf_set_str) has the |
1275 following limitation: if p starts with a '+' sign, it does | |
1276 nothing; i.e., it leaves its bigfloat argument untouched. | |
1277 Therefore, move p past any leading '+' signs. */ | |
1275 if (*p == '+') | 1278 if (*p == '+') |
1276 p++; | 1279 p++; |
1277 bigfloat_set_prec (scratch_bigfloat, bigfloat_get_default_prec ()); | 1280 bigfloat_set_prec (scratch_bigfloat, bigfloat_get_default_prec ()); |
1278 bigfloat_set_string (scratch_bigfloat, (const char *) p, b); | 1281 bigfloat_set_string (scratch_bigfloat, (const char *) p, b); |
1279 return make_bigfloat_bf (scratch_bigfloat); | 1282 return make_bigfloat_bf (scratch_bigfloat); |
1282 } | 1285 } |
1283 | 1286 |
1284 #ifdef HAVE_RATIO | 1287 #ifdef HAVE_RATIO |
1285 if (qxestrchr (p, '/') != NULL) | 1288 if (qxestrchr (p, '/') != NULL) |
1286 { | 1289 { |
1287 /* GMP ratio_set_string returns random values with initial + sign */ | 1290 /* The GMP version of ratio_set_string (mpq_set_str) has the following |
1291 limitations: | |
1292 - If p starts with a '+' sign, it does nothing; i.e., it leaves its | |
1293 ratio argument untouched. | |
1294 - If p has a '+' sign after the '/' (e.g., 300/+400), it sets the | |
1295 numerator from the string, but *leaves the denominator unchanged*. | |
1296 - If p has trailing nonnumeric characters, it sets the numerator from | |
1297 the string, but leaves the denominator unchanged. | |
1298 - If p has more than one '/', (e.g., 1/2/3), then it sets the | |
1299 numerator from the string, but leaves the denominator unchanged. | |
1300 | |
1301 Therefore, move p past any leading '+' signs, temporarily drop a null | |
1302 after the numeric characters we are trying to convert, and then put | |
1303 the nulled character back afterward. I am not going to fix problem | |
1304 #2; just don't write ratios that look like that. */ | |
1305 Ibyte *end, save; | |
1306 | |
1288 if (*p == '+') | 1307 if (*p == '+') |
1289 p++; | 1308 p++; |
1309 | |
1310 for (end = p; | |
1311 (*end >= '0' && *end <= '9') || | |
1312 (b > 10 && *end >= 'a' && *end <= 'a' + b - 11) || | |
1313 (b > 10 && *end >= 'A' && *end <= 'A' + b - 11); | |
1314 end++); | |
1315 if (*end == '/') | |
1316 for (end++; | |
1317 (*end >= '0' && *end <= '9') || | |
1318 (b > 10 && *end >= 'a' && *end <= 'a' + b - 11) || | |
1319 (b > 10 && *end >= 'A' && *end <= 'A' + b - 11); | |
1320 end++); | |
1321 | |
1322 save = *end; | |
1323 *end = '\0'; | |
1290 ratio_set_string (scratch_ratio, (const char *) p, b); | 1324 ratio_set_string (scratch_ratio, (const char *) p, b); |
1325 *end = save; | |
1326 ratio_canonicalize (scratch_ratio); | |
1291 return make_ratio_rt (scratch_ratio); | 1327 return make_ratio_rt (scratch_ratio); |
1292 } | 1328 } |
1293 #endif /* HAVE_RATIO */ | 1329 #endif /* HAVE_RATIO */ |
1294 | 1330 |
1295 #ifdef HAVE_BIGNUM | 1331 #ifdef HAVE_BIGNUM |
1296 /* GMP bignum_set_string returns random values when the string starts with a | 1332 { |
1297 plus sign */ | 1333 /* The GMP version of bignum_set_string (mpz_set_str) has the following |
1298 if (*p == '+') | 1334 limitations: |
1299 p++; | 1335 - If p starts with a '+' sign, it does nothing; i.e., it leaves its |
1300 /* GMP bignum_set_string returns random values when fed an empty string */ | 1336 bignum argument untouched. |
1301 if (*p == '\0') | 1337 - If p is the empty string, it does nothing. |
1302 return make_int (0); | 1338 - If p has trailing nonnumeric characters, it does nothing. |
1303 bignum_set_string (scratch_bignum, (const char *) p, b); | 1339 |
1304 return Fcanonicalize_number (make_bignum_bg (scratch_bignum)); | 1340 Therefore, move p past any leading '+' signs, temporarily drop a null |
1341 after the numeric characters we are trying to convert, special case the | |
1342 empty string, and then put the nulled character back afterward. */ | |
1343 Ibyte *end, save; | |
1344 Lisp_Object retval; | |
1345 | |
1346 if (*p == '+') | |
1347 p++; | |
1348 for (end = p; | |
1349 (*end >= '0' && *end <= '9') || | |
1350 (b > 10 && *end >= 'a' && *end <= 'a' + b - 11) || | |
1351 (b > 10 && *end >= 'A' && *end <= 'A' + b - 11); | |
1352 end++); | |
1353 save = *end; | |
1354 *end = '\0'; | |
1355 if (*p == '\0') | |
1356 retval = make_int (0); | |
1357 else | |
1358 { | |
1359 bignum_set_string (scratch_bignum, (const char *) p, b); | |
1360 retval = Fcanonicalize_number (make_bignum_bg (scratch_bignum)); | |
1361 } | |
1362 *end = save; | |
1363 return retval; | |
1364 } | |
1305 #else | 1365 #else |
1306 if (b == 10) | 1366 if (b == 10) |
1307 { | 1367 { |
1308 /* Use the system-provided functions for base 10. */ | 1368 /* Use the system-provided functions for base 10. */ |
1309 #if SIZEOF_EMACS_INT == SIZEOF_INT | 1369 #if SIZEOF_EMACS_INT == SIZEOF_INT |