281 returns garbage if the argument string is not a valid float number. |
281 returns garbage if the argument string is not a valid float number. |
282 It has been added to allow high speed string decomposition into numbers, |
282 It has been added to allow high speed string decomposition into numbers, |
283 especially for mass-data." |
283 especially for mass-data." |
284 |
284 |
285 %{ /* NOCONTEXT */ |
285 %{ /* NOCONTEXT */ |
286 if (__isString(aString) && __isSmallInteger(startIndex)) { |
286 if (__isStringLike(aString) && __isSmallInteger(startIndex)) { |
287 char *cp = (char *)(__stringVal(aString)); |
287 char *cp = (char *)(__stringVal(aString)); |
288 int idx = __intVal(startIndex) - 1; |
288 int idx = __intVal(startIndex) - 1; |
289 double atof(); |
289 double atof(); |
290 double val; |
290 double val; |
291 |
291 |
292 if ((unsigned)idx < __stringSize(aString)) { |
292 if ((unsigned)idx < __stringSize(aString)) { |
293 val = atof(cp + idx); |
293 val = atof(cp + idx); |
294 RETURN (__MKFLOAT(val)); |
294 RETURN (__MKFLOAT(val)); |
295 } |
295 } |
296 } |
296 } |
297 %}. |
297 %}. |
298 self primitiveFailed. |
298 self primitiveFailed. |
299 |
299 |
300 " |
300 " |
310 Float fastFromString:'12345' at:6 |
310 Float fastFromString:'12345' at:6 |
311 Float fastFromString:'12345' at:0 |
311 Float fastFromString:'12345' at:0 |
312 Float fastFromString:'hello123.45E4' at:1 |
312 Float fastFromString:'hello123.45E4' at:1 |
313 |
313 |
314 Time millisecondsToRun:[ |
314 Time millisecondsToRun:[ |
315 100000 timesRepeat:[ |
315 100000 timesRepeat:[ |
316 Float readFrom:'123.45' |
316 Float readFrom:'123.45' |
317 ] |
317 ] |
318 ] |
318 ] |
319 " |
319 " |
320 |
320 |
321 " |
321 " |
322 Time millisecondsToRun:[ |
322 Time millisecondsToRun:[ |
323 100000 timesRepeat:[ |
323 100000 timesRepeat:[ |
324 Float fastFromString:'123.45' at:1 |
324 Float fastFromString:'123.45' at:1 |
325 ] |
325 ] |
326 ] |
326 ] |
327 " |
327 " |
328 |
|
329 |
|
330 ! |
328 ! |
331 |
329 |
332 fromVAXFloatBytes:b1 b2:b2 b3:b3 b4:b4 |
330 fromVAXFloatBytes:b1 b2:b2 b3:b3 b4:b4 |
333 "creates a double, given the four vax float bytes to an ieee double. |
331 "creates a double, given the four vax float bytes to an ieee double. |
334 For NaNs and Infinity, nil is returned. |
332 For NaNs and Infinity, nil is returned. |
1481 __BEGIN_PROTECT_REGISTERS__ |
1479 __BEGIN_PROTECT_REGISTERS__ |
1482 len = snprintf(buffer, sizeof(buffer), fmtBuffer, __floatVal(self)); |
1480 len = snprintf(buffer, sizeof(buffer), fmtBuffer, __floatVal(self)); |
1483 __END_PROTECT_REGISTERS__ |
1481 __END_PROTECT_REGISTERS__ |
1484 |
1482 |
1485 if (len >= 0 && len < sizeof(buffer)-3) { |
1483 if (len >= 0 && len < sizeof(buffer)-3) { |
1486 /* |
1484 /* |
1487 * kludge to make integral float f prints as "f.0" (not as "f" as printf does) |
1485 * kludge to make integral float f prints as "f.0" (not as "f" as printf does) |
1488 * (i.e. look if string contains '.' or 'e' and append '.0' if not) |
1486 * (i.e. look if string contains '.' or 'e' and append '.0' if not) |
1489 */ |
1487 */ |
1490 for (cp = buffer; *cp; cp++) { |
1488 for (cp = buffer; *cp; cp++) { |
1491 if ((*cp == '.') || (*cp == 'E') || (*cp == 'e')) break; |
1489 if ((*cp == '.') || (*cp == 'E') || (*cp == 'e')) break; |
1492 } |
1490 } |
1493 if (!*cp && (cp[-1] >= '0') && (cp[-1] <= '9')) { |
1491 if (!*cp && (cp[-1] >= '0') && (cp[-1] <= '9')) { |
1494 if (__isCharacter(@global(DecimalPointCharacterForPrinting))) { |
1492 if (__isCharacter(@global(DecimalPointCharacterForPrinting))) { |
1495 *cp++ = __intVal(__characterVal(@global(DecimalPointCharacterForPrinting))); |
1493 *cp++ = __intVal(__characterVal(@global(DecimalPointCharacterForPrinting))); |
1496 } else { |
1494 } else { |
1497 *cp++ = '.'; |
1495 *cp++ = '.'; |
1498 } |
1496 } |
1499 *cp++ = '0'; |
1497 *cp++ = '0'; |
1500 *cp = '\0'; |
1498 *cp = '\0'; |
1501 } else { |
1499 } else { |
1502 if (cp && (*cp == '.')) { |
1500 if (cp && (*cp == '.')) { |
1503 if (__isCharacter(@global(DecimalPointCharacterForPrinting))) { |
1501 if (__isCharacter(@global(DecimalPointCharacterForPrinting))) { |
1504 *cp = __intVal(__characterVal(@global(DecimalPointCharacterForPrinting))); |
1502 *cp = __intVal(__characterVal(@global(DecimalPointCharacterForPrinting))); |
1505 } |
1503 } |
1506 } |
1504 } |
1507 } |
1505 } |
1508 |
1506 |
1509 s = __MKSTRING(buffer); |
1507 s = __MKSTRING(buffer); |
1510 if (s != nil) { |
1508 if (s != nil) { |
1511 RETURN (s); |
1509 RETURN (s); |
1512 } |
1510 } |
1513 } |
1511 } |
1514 %}. |
1512 %}. |
1515 " |
1513 " |
1516 memory allocation (for the new string) failed. |
1514 memory allocation (for the new string) failed. |
1517 When we arrive here, there was no memory, even after a garbage collect. |
1515 When we arrive here, there was no memory, even after a garbage collect. |
1520 Bad luck - you should increase the swap space on your machine. |
1518 Bad luck - you should increase the swap space on your machine. |
1521 " |
1519 " |
1522 ^ ObjectMemory allocationFailureSignal raise. |
1520 ^ ObjectMemory allocationFailureSignal raise. |
1523 |
1521 |
1524 " |
1522 " |
1525 1.0 printString |
1523 1.0 printString |
1526 1.234 printString |
1524 1.234 printString |
1527 1e10 printString |
1525 1e10 printString |
1528 1.2e3 printString |
1526 1.2e3 printString |
1529 1.2e30 printString |
1527 1.2e30 printString |
1530 (1.0 uncheckedDivide:0) printString |
1528 (1.0 uncheckedDivide:0) printString |
1531 (0.0 uncheckedDivide:0) printString |
1529 (0.0 uncheckedDivide:0) printString |
1532 |
1530 |
1533 DecimalPointCharacter := $,. |
1531 DecimalPointCharacter := $,. |
1534 1.234 printString. |
1532 1.234 printString. |
1535 1.0 printString. |
1533 1.0 printString. |
1536 1e10 printString. |
1534 1e10 printString. |
1537 1.2e3 printString. |
1535 1.2e3 printString. |
1538 1.2e30 printString. |
1536 1.2e30 printString. |
1539 (1.0 uncheckedDivide:0) printString. |
1537 (1.0 uncheckedDivide:0) printString. |
1540 (0.0 uncheckedDivide:0) printString. |
1538 (0.0 uncheckedDivide:0) printString. |
1541 DecimalPointCharacter := $. |
1539 DecimalPointCharacter := $. |
1542 " |
1540 " |
1543 ! |
1541 ! |
1544 |
1542 |
1545 printfPrintString:formatString |
1543 printfPrintString:formatString |
1546 "non-standard: return a printed representation of the receiver |
1544 "non-standard: return a printed representation of the receiver |
1558 %{ /* STACK: 400 */ |
1556 %{ /* STACK: 400 */ |
1559 char buffer[256]; |
1557 char buffer[256]; |
1560 OBJ s; |
1558 OBJ s; |
1561 int len; |
1559 int len; |
1562 |
1560 |
1563 if (__isString(formatString)) { |
1561 if (__isStringLike(formatString)) { |
1564 /* |
1562 /* |
1565 * actually only needed on sparc: since thisContext is |
1563 * actually only needed on sparc: since thisContext is |
1566 * in a global register, which gets destroyed by printf, |
1564 * in a global register, which gets destroyed by printf, |
1567 * manually save it here - very stupid ... |
1565 * manually save it here - very stupid ... |
1568 */ |
1566 */ |
1569 __BEGIN_PROTECT_REGISTERS__ |
1567 __BEGIN_PROTECT_REGISTERS__ |
1570 |
1568 |
1571 len = snprintf(buffer, sizeof(buffer), __stringVal(formatString), __floatVal(self)); |
1569 len = snprintf(buffer, sizeof(buffer), __stringVal(formatString), __floatVal(self)); |
1572 |
1570 |
1573 __END_PROTECT_REGISTERS__ |
1571 __END_PROTECT_REGISTERS__ |
1574 |
1572 |
1575 if (len < 0) goto fail; |
1573 if (len < 0) goto fail; |
1576 |
1574 |
1577 s = __MKSTRING_L(buffer, len); |
1575 s = __MKSTRING_L(buffer, len); |
1578 if (s != nil) { |
1576 if (s != nil) { |
1579 RETURN (s); |
1577 RETURN (s); |
1580 } |
1578 } |
1581 } |
1579 } |
1582 fail: ; |
1580 fail: ; |
1583 %}. |
1581 %}. |
1584 self primitiveFailed |
1582 self primitiveFailed |
1585 |
1583 |