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