66 * no finite(x) ? |
70 * no finite(x) ? |
67 * no isnan(x) ? |
71 * no isnan(x) ? |
68 */ |
72 */ |
69 # ifndef isnan |
73 # ifndef isnan |
70 # define isnan(x) \ |
74 # define isnan(x) \ |
71 ((((unsigned int *)(&x))[0] == 0x00000000) && \ |
75 ((((unsigned int *)(&x))[0] == 0x00000000) && \ |
72 (((unsigned int *)(&x))[1] == 0xFFF80000)) |
76 (((unsigned int *)(&x))[1] == 0xFFF80000)) |
73 # endif |
77 # endif |
74 |
78 |
75 # ifndef isPositiveInfinity |
79 # ifndef isPositiveInfinity |
76 # define isPositiveInfinity(x) \ |
80 # define isPositiveInfinity(x) \ |
77 ((((unsigned int *)(&x))[0] == 0x00000000) && \ |
81 ((((unsigned int *)(&x))[0] == 0x00000000) && \ |
78 (((unsigned int *)(&x))[1] == 0x7FF00000)) |
82 (((unsigned int *)(&x))[1] == 0x7FF00000)) |
79 # endif |
83 # endif |
80 |
84 |
81 # ifndef isNegativeInfinity |
85 # ifndef isNegativeInfinity |
82 # define isNegativeInfinity(x) \ |
86 # define isNegativeInfinity(x) \ |
83 ((((unsigned int *)(&x))[0] == 0x00000000) && \ |
87 ((((unsigned int *)(&x))[0] == 0x00000000) && \ |
84 (((unsigned int *)(&x))[1] == 0xFFF00000)) |
88 (((unsigned int *)(&x))[1] == 0xFFF00000)) |
85 # endif |
89 # endif |
86 |
90 |
87 # ifndef isinf |
91 # ifndef isinf |
88 # define isinf(x) \ |
92 # define isinf(x) \ |
89 ((((unsigned int *)(&x))[0] == 0x00000000) && \ |
93 ((((unsigned int *)(&x))[0] == 0x00000000) && \ |
90 ((((unsigned int *)(&x))[1] & 0x7FF00000) == 0x7FF00000)) |
94 ((((unsigned int *)(&x))[1] & 0x7FF00000) == 0x7FF00000)) |
91 # endif |
95 # endif |
92 |
96 |
93 # ifndef isfinite |
97 # ifndef isfinite |
94 # define isfinite(x) (!isinf(x) && !isnan(x)) |
98 # define isfinite(x) (!isinf(x) && !isnan(x)) |
95 # endif |
99 # endif |
96 |
100 |
97 # ifndef isnanf |
101 # ifndef isnanf |
98 # define isnanf(x) \ |
102 # define isnanf(x) \ |
99 (((unsigned int *)(&x))[0] == 0xFFC00000) |
103 (((unsigned int *)(&x))[0] == 0xFFC00000) |
100 # endif |
104 # endif |
101 |
105 |
102 # ifndef isPositiveInfinityf |
106 # ifndef isPositiveInfinityf |
103 # define isPositiveInfinityf(x) \ |
107 # define isPositiveInfinityf(x) \ |
104 (((unsigned int *)(&x))[0] == 0x7F800000) |
108 (((unsigned int *)(&x))[0] == 0x7F800000) |
105 # endif |
109 # endif |
106 |
110 |
107 # ifndef isNegativeInfinityf |
111 # ifndef isNegativeInfinityf |
108 # define isNegativeInfinityf(x) \ |
112 # define isNegativeInfinityf(x) \ |
109 (((unsigned int *)(&x))[0] == 0xFF800000) |
113 (((unsigned int *)(&x))[0] == 0xFF800000) |
110 # endif |
114 # endif |
111 |
115 |
112 # ifndef isinff |
116 # ifndef isinff |
113 # define isinff(x) \ |
117 # define isinff(x) \ |
114 ((((unsigned int *)(&x))[0] & 0x7FFFFFFF) == 0x7F800000) |
118 ((((unsigned int *)(&x))[0] & 0x7FFFFFFF) == 0x7F800000) |
115 # endif |
119 # endif |
116 |
120 |
117 # ifndef isfinitef |
121 # ifndef isfinitef |
118 # define isfinitef(x) (!isinff(x) && !isnanf(x)) |
122 # define isfinitef(x) (!isinff(x) && !isnanf(x)) |
119 # endif |
123 # endif |
992 1.0 asShortFloat hash |
1015 1.0 asShortFloat hash |
993 0.5 asShortFloat hash |
1016 0.5 asShortFloat hash |
994 0.25 asShortFloat hash |
1017 0.25 asShortFloat hash |
995 0.5 hash |
1018 0.5 hash |
996 0.25 hash |
1019 0.25 hash |
|
1020 " |
|
1021 ! |
|
1022 |
|
1023 isAlmostEqualTo:aNumber nEpsilon:nE |
|
1024 "return true, if the argument, aNumber represents almost the same numeric value |
|
1025 as the receiver, false otherwise. |
|
1026 |
|
1027 nE is the number of minimal float distances, that the numbers may differ and |
|
1028 still be considered equal. |
|
1029 |
|
1030 For background information why floats need this |
|
1031 read: http://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/ |
|
1032 " |
|
1033 |
|
1034 %{ /* NOCONTEXT */ |
|
1035 |
|
1036 /* |
|
1037 * notice: |
|
1038 * the following inline code handles some common cases, |
|
1039 * and exists as an optimization, to speed up those cases. |
|
1040 * |
|
1041 * Conceptionally, (and for most other argument types), |
|
1042 * mixed arithmetic is implemented by double dispatching |
|
1043 * (see the message send at the bottom) |
|
1044 */ |
|
1045 |
|
1046 INT32 ulpDiff; |
|
1047 union { |
|
1048 float f; |
|
1049 INT32 i; |
|
1050 } myself, otherFloat; |
|
1051 int nEpsilon; |
|
1052 float scaledEpsilon; |
|
1053 |
|
1054 |
|
1055 if (!__isSmallInteger(nE)) { |
|
1056 goto tryHarder; |
|
1057 } |
|
1058 |
|
1059 nEpsilon = __intVal(nE); |
|
1060 scaledEpsilon = nEpsilon *__shortFloatVal(@global(Epsilon)); |
|
1061 |
|
1062 if (__isSmallInteger(aNumber)) { |
|
1063 otherFloat.f = (float)(__intVal(aNumber)); |
|
1064 } else if (aNumber == nil) { |
|
1065 RETURN(false) |
|
1066 } else if (__qIsFloatLike(aNumber)) { |
|
1067 otherFloat.f = (float)(__floatVal(aNumber)); |
|
1068 } else if (__qIsShortFloat(aNumber)) { |
|
1069 otherFloat.f = (double)(__shortFloatVal(aNumber)); |
|
1070 } else { |
|
1071 goto tryHarder; |
|
1072 } |
|
1073 |
|
1074 myself.f = __shortFloatVal(self); |
|
1075 |
|
1076 // Check if the numbers are really close -- needed |
|
1077 // when comparing numbers near zero (ULP method below fails for numbers near 0!). |
|
1078 if (fabs(myself.f - otherFloat.f) <= scaledEpsilon) { |
|
1079 RETURN(true); |
|
1080 } |
|
1081 |
|
1082 // if the signs differ, the numbers are different |
|
1083 if ((myself.f >= 0) != (otherFloat.f >= 0)) { |
|
1084 RETURN(false); |
|
1085 } |
|
1086 |
|
1087 // compute the difference of the 'units in the last place" ULP |
|
1088 // (if ulpDiff == 1, two floats are adjecant) |
|
1089 ulpDiff = myself.i - otherFloat.i; |
|
1090 if (ulpDiff < 0) ulpDiff = -ulpDiff; |
|
1091 if (ulpDiff <= nEpsilon) { |
|
1092 RETURN(true); |
|
1093 } else { |
|
1094 RETURN(false) |
|
1095 } |
|
1096 |
|
1097 tryHarder:; |
|
1098 %}. |
|
1099 ^ aNumber isAlmostEqualToFromShortFloat:self nEpsilon:nE |
|
1100 |
|
1101 " |
|
1102 67329.234 asShortFloat isAlmostEqualTo:67329.23400000001 nEpsilon:1 |
|
1103 1.0 asShortFloat isAlmostEqualTo:1.0001 nEpsilon:1 |
|
1104 1.0 asShortFloat isAlmostEqualTo:-1.0 nEpsilon:1 |
|
1105 1.0 asShortFloat isAlmostEqualTo:1 nEpsilon:1 |
997 " |
1106 " |
998 ! |
1107 ! |
999 |
1108 |
1000 ~= aNumber |
1109 ~= aNumber |
1001 "return true, if the arguments value are not equal" |
1110 "return true, if the arguments value are not equal" |
1090 |
1199 |
1091 char buffer[64]; |
1200 char buffer[64]; |
1092 REGISTER char *cp; |
1201 REGISTER char *cp; |
1093 int len; |
1202 int len; |
1094 OBJ s; |
1203 OBJ s; |
|
1204 char *fmt; |
|
1205 char fmtBuffer[20]; |
|
1206 |
|
1207 if (__isStringLike(@global(DefaultPrintFormat))) { |
|
1208 fmt = (char *) __stringVal(@global(DefaultPrintFormat)); |
|
1209 } else { |
|
1210 /* |
|
1211 * in case we get called before #initialize ... |
|
1212 */ |
|
1213 fmt = ".7"; |
|
1214 } |
|
1215 |
|
1216 /* |
|
1217 * build a printf format string |
|
1218 */ |
|
1219 fmtBuffer[0] = '%'; |
|
1220 strncpy(fmtBuffer+1, fmt, 10); |
|
1221 strcat(fmtBuffer, "g"); |
1095 |
1222 |
1096 /* |
1223 /* |
1097 * actually only needed on sparc: since thisContext is |
1224 * actually only needed on sparc: since thisContext is |
1098 * in a global register, which gets destroyed by printf, |
1225 * in a global register, which gets destroyed by printf, |
1099 * manually save it here - very stupid ... |
1226 * manually save it here - very stupid ... |
1100 */ |
1227 */ |
1101 __BEGIN_PROTECT_REGISTERS__ |
1228 __BEGIN_PROTECT_REGISTERS__ |
1102 len = snprintf(buffer, sizeof(buffer), "%.6g", (float)__shortFloatVal(self)); |
1229 len = snprintf(buffer, sizeof(buffer), fmtBuffer, (float)__shortFloatVal(self)); |
1103 __END_PROTECT_REGISTERS__ |
1230 __END_PROTECT_REGISTERS__ |
1104 |
1231 |
1105 if (len >= 0 && len <= sizeof(buffer)-3) { |
1232 if (len >= 0 && len <= sizeof(buffer)-3) { |
1106 /* |
1233 /* |
1107 * kludge to make integral float f prints as "f.0" (not as "f" as printf does) |
1234 * kludge to make integral float f prints as "f.0" (not as "f" as printf does) |
1108 * (i.e. look if string contains '.' or 'e' and append '.0' if not) |
1235 * (i.e. look if string contains '.' or 'e' and append '.0' if not) |
1109 */ |
1236 */ |
1110 for (cp = buffer; *cp; cp++) { |
1237 for (cp = buffer; *cp; cp++) { |
1111 if ((*cp == '.') || (*cp == ',') || (*cp == 'E') || (*cp == 'e')) break; |
1238 if ((*cp == '.') || (*cp == ',') || (*cp == 'E') || (*cp == 'e')) break; |
1112 } |
1239 } |
1113 if (!*cp && (cp[-1] >= '0') && (cp[-1] <= '9')) { |
1240 if (!*cp && (cp[-1] >= '0') && (cp[-1] <= '9')) { |
1114 if (__isCharacter(@global(DecimalPointCharacterForPrinting))) { |
1241 if (__isCharacter(@global(DecimalPointCharacterForPrinting))) { |
1115 *cp++ = __intVal(__characterVal(@global(DecimalPointCharacterForPrinting))); |
1242 *cp++ = __intVal(__characterVal(@global(DecimalPointCharacterForPrinting))); |
1116 } else { |
1243 } else { |
1117 *cp++ = '.'; |
1244 *cp++ = '.'; |
1118 } |
1245 } |
1119 *cp++ = '0'; |
1246 *cp++ = '0'; |
1120 *cp = '\0'; |
1247 *cp = '\0'; |
1121 } else { |
1248 } else { |
1122 if (cp && (*cp == '.')) { |
1249 if (cp && (*cp == '.')) { |
1123 if (__isCharacter(@global(DecimalPointCharacterForPrinting))) { |
1250 if (__isCharacter(@global(DecimalPointCharacterForPrinting))) { |
1124 *cp = __intVal(__characterVal(@global(DecimalPointCharacterForPrinting))); |
1251 *cp = __intVal(__characterVal(@global(DecimalPointCharacterForPrinting))); |
1125 } |
1252 } |
1126 } |
1253 } |
1127 } |
1254 } |
1128 |
1255 |
1129 s = __MKSTRING(buffer); |
1256 s = __MKSTRING(buffer); |
1130 if (s != nil) { |
1257 if (s != nil) { |
1131 RETURN (s); |
1258 RETURN (s); |
1132 } |
1259 } |
1133 } |
1260 } |
1134 %}. |
1261 %}. |
1135 ^ self asFloat printString |
1262 ^ self asFloat printString |
1136 |
1263 |
1137 " |
1264 " |
1138 1.234 asShortFloat printString. |
1265 1.234 asShortFloat printString. |
1139 1.0 asShortFloat printString. |
1266 1.0 asShortFloat printString. |
1140 1e10 asShortFloat printString. |
1267 1e10 asShortFloat printString. |
1141 1.2e3 asShortFloat printString. |
1268 1.2e3 asShortFloat printString. |
1142 1.2e30 asShortFloat printString. |
1269 1.2e30 asShortFloat printString. |
1143 (1.0 uncheckedDivide:0) asShortFloat printString. |
1270 (1.0 uncheckedDivide:0) asShortFloat printString. |
1144 (0.0 uncheckedDivide:0) asShortFloat printString. |
1271 (0.0 uncheckedDivide:0) asShortFloat printString. |
1145 self pi printString. |
1272 self pi printString. |
1146 |
1273 |
1147 DecimalPointCharacterForPrinting := $,. |
1274 self pi printString. |
1148 1.234 asShortFloat printString. |
1275 DefaultPrintFormat := '.3'. |
1149 1.0 asShortFloat printString. |
1276 self pi printString. |
1150 1e10 asShortFloat printString. |
1277 DefaultPrintFormat := '.7'. |
1151 1.2e3 asShortFloat printString. |
1278 |
1152 1.2e30 asShortFloat printString. |
1279 DecimalPointCharacterForPrinting := $,. |
1153 (1.0 uncheckedDivide:0) asShortFloat printString. |
1280 1.234 asShortFloat printString. |
1154 (0.0 uncheckedDivide:0) asShortFloat printString. |
1281 1.0 asShortFloat printString. |
1155 DecimalPointCharacterForPrinting := $. |
1282 1e10 asShortFloat printString. |
|
1283 1.2e3 asShortFloat printString. |
|
1284 1.2e30 asShortFloat printString. |
|
1285 (1.0 uncheckedDivide:0) asShortFloat printString. |
|
1286 (0.0 uncheckedDivide:0) asShortFloat printString. |
|
1287 DecimalPointCharacterForPrinting := $. |
1156 " |
1288 " |
1157 ! |
1289 ! |
1158 |
1290 |
1159 printfPrintString:formatString |
1291 printfPrintString:formatString |
1160 "non-standard: return a printed representation of the receiver |
1292 "non-standard: return a printed representation of the receiver |
1221 /* |
1353 /* |
1222 * build a printf format string |
1354 * build a printf format string |
1223 */ |
1355 */ |
1224 |
1356 |
1225 __BEGIN_PROTECT_REGISTERS__ |
1357 __BEGIN_PROTECT_REGISTERS__ |
1226 #ifdef SYSV |
1358 len = snprintf(buffer, sizeof(buffer), "%.8g", (float)__shortFloatVal(self)); |
1227 len = snprintf(buffer, sizeof(buffer), "%.6lg", (double)__shortFloatVal(self)); |
|
1228 #else |
|
1229 len = snprintf(buffer, sizeof(buffer), "%.6G", (double)__shortFloatVal(self)); |
|
1230 #endif |
|
1231 __END_PROTECT_REGISTERS__ |
1359 __END_PROTECT_REGISTERS__ |
1232 |
1360 |
1233 if (len >= 0 && len < sizeof(buffer)-3) { |
1361 if (len >= 0 && len < sizeof(buffer)-3) { |
1234 /* |
1362 /* |
1235 * kludge to make integral float f prints as "f.0" (not as "f" as printf does) |
1363 * kludge to make integral float f prints as "f.0" (not as "f" as printf does) |
1236 * (i.e. look if string contains '.' or 'e' and append '.0' if not) |
1364 * (i.e. look if string contains '.' or 'e' and append '.0' if not) |
1237 */ |
1365 */ |
1238 for (cp = buffer; *cp; cp++) { |
1366 for (cp = buffer; *cp; cp++) { |
1239 if ((*cp == '.') || (*cp == ',') || (*cp == 'E') || (*cp == 'e')) break; |
1367 if ((*cp == '.') || (*cp == ',') || (*cp == 'E') || (*cp == 'e')) break; |
1240 } |
1368 } |
1241 if (!*cp && (cp[-1] >= '0') && (cp[-1] <= '9')) { |
1369 if (!*cp && (cp[-1] >= '0') && (cp[-1] <= '9')) { |
1242 *cp++ = '.'; |
1370 *cp++ = '.'; |
1243 *cp++ = '0'; |
1371 *cp++ = '0'; |
1244 *cp = '\0'; |
1372 *cp = '\0'; |
1245 } |
1373 } |
1246 |
1374 |
1247 s = __MKSTRING(buffer); |
1375 s = __MKSTRING(buffer); |
1248 if (s != nil) { |
1376 if (s != nil) { |
1249 RETURN (s); |
1377 RETURN (s); |
1250 } |
1378 } |
1251 } |
1379 } |
1252 %}. |
1380 %}. |
1253 " |
1381 " |
1254 memory allocation (for the new string) failed. |
1382 memory allocation (for the new string) failed. |
1255 When we arrive here, there was no memory, even after a garbage collect. |
1383 When we arrive here, there was no memory, even after a garbage collect. |
1258 Bad luck - you should increase the swap space on your machine. |
1386 Bad luck - you should increase the swap space on your machine. |
1259 " |
1387 " |
1260 ^ ObjectMemory allocationFailureSignal raise. |
1388 ^ ObjectMemory allocationFailureSignal raise. |
1261 |
1389 |
1262 " |
1390 " |
1263 1.0 asShortFloat storeString |
1391 0.1 asShortFloat storeString |
1264 1.234 asShortFloat storeString |
1392 ((Array new:10 withAll:0.1 asShortFloat) inject:0 into:[:v :sumSoFar| sumSoFar + v]) storeString |
1265 1e10 asShortFloat storeString |
1393 1.0 asShortFloat storeString |
1266 1.2e3 asShortFloat storeString |
1394 1.234 asShortFloat storeString |
1267 1.2e30 asShortFloat storeString |
1395 1e10 asShortFloat storeString |
1268 Float pi asShortFloat storeString |
1396 1.2e3 asShortFloat storeString |
1269 (1.0 uncheckedDivide:0) asShortFloat storeString |
1397 1.2e30 asShortFloat storeString |
1270 (0.0 uncheckedDivide:0) asShortFloat storeString |
1398 Float pi asShortFloat storeString |
|
1399 (1.0 uncheckedDivide:0) asShortFloat storeString |
|
1400 (0.0 uncheckedDivide:0) asShortFloat storeString |
1271 |
1401 |
1272 notice that the storeString is NOT affected by DecimalPointCharacterForPrinting: |
1402 notice that the storeString is NOT affected by DecimalPointCharacterForPrinting: |
1273 |
1403 |
1274 DecimalPointCharacterForPrinting := $,. |
1404 DecimalPointCharacterForPrinting := $,. |
1275 1.234 asShortFloat storeString. |
1405 1.234 asShortFloat storeString. |
1276 1.0 asShortFloat storeString. |
1406 1.0 asShortFloat storeString. |
1277 1e10 asShortFloat storeString. |
1407 1e10 asShortFloat storeString. |
1278 1.2e3 asShortFloat storeString. |
1408 1.2e3 asShortFloat storeString. |
1279 1.2e30 asShortFloat storeString. |
1409 1.2e30 asShortFloat storeString. |
1280 (1.0 uncheckedDivide:0) asShortFloat storeString. |
1410 (1.0 uncheckedDivide:0) asShortFloat storeString. |
1281 (0.0 uncheckedDivide:0) asShortFloat storeString. |
1411 (0.0 uncheckedDivide:0) asShortFloat storeString. |
1282 DecimalPointCharacterForPrinting := $. |
1412 DecimalPointCharacterForPrinting := $. |
1283 " |
1413 " |
1284 ! ! |
1414 ! ! |
1285 |
1415 |
1286 !ShortFloat methodsFor:'private accessing'! |
1416 !ShortFloat methodsFor:'private accessing'! |
1287 |
1417 |
1366 ^ self elementBoundsError:value |
1496 ^ self elementBoundsError:value |
1367 ]. |
1497 ]. |
1368 ^ self indexNotIntegerOrOutOfBounds:index |
1498 ^ self indexNotIntegerOrOutOfBounds:index |
1369 ! ! |
1499 ! ! |
1370 |
1500 |
|
1501 !ShortFloat methodsFor:'queries'! |
|
1502 |
|
1503 nextFloat:count |
|
1504 "answer the next float count places after (or before if count is negative) myself" |
|
1505 |
|
1506 %{ |
|
1507 union u { |
|
1508 float d; |
|
1509 INT32 i; |
|
1510 } this; |
|
1511 |
|
1512 if (__isSmallInteger(count)) { |
|
1513 this.d = __shortFloatVal(self); |
|
1514 if (isfinite(this.d)) |
|
1515 this.i += __intVal(count); |
|
1516 |
|
1517 RETURN(__MKSFLOAT(this.d)); |
|
1518 } |
|
1519 %}. |
|
1520 self primitiveFailed:#badArgument |
|
1521 |
|
1522 " |
|
1523 (1.0 asShortFloat nextFloat:2) storeString |
|
1524 (67329.234 asShortFloat nextFloat:1) storeString |
|
1525 ShortFloat NaN nextFloat:100000 |
|
1526 ShortFloat infinity nextFloat:100000 |
|
1527 " |
|
1528 ! ! |
|
1529 |
1371 !ShortFloat methodsFor:'special access'! |
1530 !ShortFloat methodsFor:'special access'! |
1372 |
1531 |
1373 exponent |
1532 exponent |
1374 "extract a normalized floats exponent. |
1533 "extract a normalized floats exponent. |
1375 The returned value depends on the float-representation of |
1534 The returned value depends on the float-representation of |