ShortFloat.st
changeset 24976 0b3c34125507
parent 24975 fdf3a5b2f6b6
child 24986 0ba981e902f9
equal deleted inserted replaced
24975:fdf3a5b2f6b6 24976:0b3c34125507
   201     to bothe VisualWorks and other Smalltalks, which use C-doubles for the Float class
   201     to bothe VisualWorks and other Smalltalks, which use C-doubles for the Float class
   202     (i.e. VisualST and V'Age).
   202     (i.e. VisualST and V'Age).
   203     Thus, STX's Float precision is not worse than that of other ST's.
   203     Thus, STX's Float precision is not worse than that of other ST's.
   204 
   204 
   205     WARNING:
   205     WARNING:
   206         The layout of shortFloat instances is known by the runtime system and the compiler;
   206 	The layout of shortFloat instances is known by the runtime system and the compiler;
   207         you may not add instance variables here.
   207 	you may not add instance variables here.
   208         Also, subclassing is complicated by the fact, that the VM creates floats/shortFloats,
   208 	Also, subclassing is complicated by the fact, that the VM creates floats/shortFloats,
   209         and does some of its float-checks by an identity compare with the ShortFloat-class.
   209 	and does some of its float-checks by an identity compare with the ShortFloat-class.
   210         (i.e. your subclasses instances may not be recognized as float-like objects,
   210 	(i.e. your subclasses instances may not be recognized as float-like objects,
   211          thus mixed mode arithmetic will always coerce them, effectively slowing things down).
   211 	 thus mixed mode arithmetic will always coerce them, effectively slowing things down).
   212         This may be changed, to use a flag bit in the class.
   212 	This may be changed, to use a flag bit in the class.
   213 
   213 
   214     Mixed mode arithmetic:
   214     Mixed mode arithmetic:
   215         shortFloat op shortFloat   -> shortFloat
   215 	shortFloat op shortFloat   -> shortFloat
   216         shortFloat op fix         -> shortFloat
   216 	shortFloat op fix         -> shortFloat
   217         shortFloat op fraction    -> shortFloat
   217 	shortFloat op fraction    -> shortFloat
   218         shortFloat op integer     -> shortFloat
   218 	shortFloat op integer     -> shortFloat
   219         shortFloat op longFloat   -> longFloat
   219 	shortFloat op longFloat   -> longFloat
   220         shortFloat op float       -> float
   220 	shortFloat op float       -> float
   221         shortFloat op complex     -> complex
   221 	shortFloat op complex     -> complex
   222 
   222 
   223     Representation:
   223     Representation:
   224             32bit single precision IEEE floats
   224 	    32bit single precision IEEE floats
   225             23 bit mantissa + 1 hidden bit, providing a precision of 24bits,
   225 	    23 bit mantissa + 1 hidden bit, providing a precision of 24bits,
   226             8 bit exponent,
   226 	    8 bit exponent,
   227             6 decimal digits (approx.)
   227 	    6 decimal digits (approx.)
   228 
   228 
   229     Range and Precision of Storage Formats: see LimitedPrecisionReal >> documentation
   229     Range and Precision of Storage Formats: see LimitedPrecisionReal >> documentation
   230 
   230 
   231     [author:]
   231     [author:]
   232         Claus Gittinger
   232 	Claus Gittinger
   233 
   233 
   234     [see also:]
   234     [see also:]
   235         Number
   235 	Number
   236         Float LongFloat Fraction FixedPoint Integer Complex
   236 	Float LongFloat Fraction FixedPoint Integer Complex
   237         FloatArray DoubleArray
   237 	FloatArray DoubleArray
   238 "
   238 "
   239 ! !
   239 ! !
   240 
   240 
   241 !ShortFloat class methodsFor:'instance creation'!
   241 !ShortFloat class methodsFor:'instance creation'!
   242 
   242 
   262      No spaces are skipped.
   262      No spaces are skipped.
   263      Raises an exception, if the startIndex is not valid.
   263      Raises an exception, if the startIndex is not valid.
   264      Returns garbage if the argument string is not a valid float number.
   264      Returns garbage if the argument string is not a valid float number.
   265 
   265 
   266      This is a specially tuned entry (using a low-level C-call to atof).
   266      This is a specially tuned entry (using a low-level C-call to atof).
   267      It has been added to allow high speed string decomposition 
   267      It has been added to allow high speed string decomposition
   268      into numbers, especially for mass-data (reading millions of floats)."
   268      into numbers, especially for mass-data (reading millions of floats)."
   269 
   269 
   270 %{   /* NOCONTEXT */
   270 %{   /* NOCONTEXT */
   271      if (__isStringLike(aString) && __isSmallInteger(startIndex)) {
   271      if (__isStringLike(aString) && __isSmallInteger(startIndex)) {
   272         char *cp = (char *)(__stringVal(aString));
   272 	char *cp = (char *)(__stringVal(aString));
   273         int idx = __intVal(startIndex) - 1;
   273 	int idx = __intVal(startIndex) - 1;
   274 
   274 
   275         if ((unsigned)idx < __stringSize(aString)) {
   275 	if ((unsigned)idx < __stringSize(aString)) {
   276 #ifndef NO_STRTOF
   276 #ifndef NO_STRTOF
   277             float strtof(const char *, char**);
   277 	    float strtof(const char *, char**);
   278             float val = strtof(cp+idx, NULL);
   278 	    float val = strtof(cp+idx, NULL);
   279 #else
   279 #else
   280             double atof(const char *);
   280 # ifndef NO_STRTOD
   281             double val = atof(cp + idx);
   281 	    double strtod(const char *, char**);
   282 #endif
   282 	    double val = strtod(cp+idx, NULL);
   283             RETURN (__MKSFLOAT(val));
   283 # else
   284         }
   284 	    double atof(const char *);
       
   285 	    double val = atof(cp + idx);
       
   286 # endif
       
   287 #endif
       
   288 	    RETURN (__MKSFLOAT(val));
       
   289 	}
   285      }
   290      }
   286 %}.
   291 %}.
   287      self primitiveFailed.
   292      self primitiveFailed.
   288 
   293 
   289     "
   294     "
   301      ShortFloat fastFromString:'hello123.45E4' at:1
   306      ShortFloat fastFromString:'hello123.45E4' at:1
   302     "
   307     "
   303 
   308 
   304     "
   309     "
   305      Time millisecondsToRun:[
   310      Time millisecondsToRun:[
   306         1000000 timesRepeat:[
   311 	1000000 timesRepeat:[
   307             ShortFloat readFrom:'123.45'
   312 	    ShortFloat readFrom:'123.45'
   308         ]
   313 	]
   309      ]
   314      ]
   310     "
   315     "
   311 
   316 
   312     "
   317     "
   313      Time millisecondsToRun:[
   318      Time millisecondsToRun:[
   314         1000000 timesRepeat:[
   319 	1000000 timesRepeat:[
   315             ShortFloat fastFromString:'123.45' at:1
   320 	    ShortFloat fastFromString:'123.45' at:1
   316         ]
   321 	]
   317      ]
   322      ]
   318     "
   323     "
   319 
   324 
   320     "Modified (comment): / 27-10-2018 / 08:58:13 / Claus Gittinger"
   325     "Modified (comment): / 27-10-2018 / 08:58:13 / Claus Gittinger"
   321 !
   326 !
   341 
   346 
   342 !ShortFloat class methodsFor:'accessing'!
   347 !ShortFloat class methodsFor:'accessing'!
   343 
   348 
   344 defaultPrintFormat
   349 defaultPrintFormat
   345     "/ by default, I will print 7 digits
   350     "/ by default, I will print 7 digits
   346     "/  ShortFloat pi   -> 3.141593  
   351     "/  ShortFloat pi   -> 3.141593
   347     "/  Float pi        -> 3.14159265358979  
   352     "/  Float pi        -> 3.14159265358979
   348     "/  LongFloat pi    -> 3.141592653589793239  
   353     "/  LongFloat pi    -> 3.141592653589793239
   349 
   354 
   350     ^ DefaultPrintFormat
   355     ^ DefaultPrintFormat
   351 !
   356 !
   352 
   357 
   353 defaultPrintFormat:aString
   358 defaultPrintFormat:aString
   493 
   498 
   494 NaN
   499 NaN
   495     "return a shortFloat which represents not-a-Number (i.e. an invalid number)"
   500     "return a shortFloat which represents not-a-Number (i.e. an invalid number)"
   496 
   501 
   497     NaN isNil ifTrue:[
   502     NaN isNil ifTrue:[
   498         NaN := super NaN
   503 	NaN := super NaN
   499     ].
   504     ].
   500     ^ NaN
   505     ^ NaN
   501 
   506 
   502     "
   507     "
   503      self NaN
   508      self NaN
   515     ].
   520     ].
   516     ^ E
   521     ^ E
   517 !
   522 !
   518 
   523 
   519 eBias
   524 eBias
   520     "Answer the exponent's bias; 
   525     "Answer the exponent's bias;
   521      that is the offset of the zero exponent when stored"
   526      that is the offset of the zero exponent when stored"
   522 
   527 
   523     ^ 127
   528     ^ 127
   524 !
   529 !
   525 
   530 
   537 
   542 
   538 infinity
   543 infinity
   539     "return a shortFloat which represents positive infinity (for my instances)"
   544     "return a shortFloat which represents positive infinity (for my instances)"
   540 
   545 
   541     PositiveInfinity isNil ifTrue:[
   546     PositiveInfinity isNil ifTrue:[
   542         PositiveInfinity := Float infinity asShortFloat
   547 	PositiveInfinity := Float infinity asShortFloat
   543     ].
   548     ].
   544     ^ PositiveInfinity
   549     ^ PositiveInfinity
   545 
   550 
   546     "Created: / 20-06-2017 / 13:44:45 / cg"
   551     "Created: / 20-06-2017 / 13:44:45 / cg"
   547     "Modified (comment): / 08-06-2019 / 14:32:27 / Claus Gittinger"
   552     "Modified (comment): / 08-06-2019 / 14:32:27 / Claus Gittinger"
   564 
   569 
   565 ln2
   570 ln2
   566     "return the natural logarithm of 2 as a shortFloat"
   571     "return the natural logarithm of 2 as a shortFloat"
   567 
   572 
   568     Ln2 isNil ifTrue:[
   573     Ln2 isNil ifTrue:[
   569         Ln2 := Float ln2 asShortFloat
   574 	Ln2 := Float ln2 asShortFloat
   570     ].
   575     ].
   571     ^ Ln2
   576     ^ Ln2
   572 
   577 
   573     "
   578     "
   574      self ln2
   579      self ln2
   581     "return a shortFloat which represents negative infinity (for my instances).
   586     "return a shortFloat which represents negative infinity (for my instances).
   582      Warning: do not compare equal against infinities;
   587      Warning: do not compare equal against infinities;
   583      instead, check using isFinite or isInfinite"
   588      instead, check using isFinite or isInfinite"
   584 
   589 
   585     NegativeInfinity isNil ifTrue:[
   590     NegativeInfinity isNil ifTrue:[
   586         NegativeInfinity := Float negativeInfinity asShortFloat
   591 	NegativeInfinity := Float negativeInfinity asShortFloat
   587     ].
   592     ].
   588     ^ NegativeInfinity
   593     ^ NegativeInfinity
   589 
   594 
   590     "Created: / 20-06-2017 / 13:45:08 / cg"
   595     "Created: / 20-06-2017 / 13:45:08 / cg"
   591     "Modified (comment): / 09-06-2019 / 12:57:11 / Claus Gittinger"
   596     "Modified (comment): / 09-06-2019 / 12:57:11 / Claus Gittinger"
   593 
   598 
   594 phi
   599 phi
   595     "return the constant phi as ShortFloat"
   600     "return the constant phi as ShortFloat"
   596 
   601 
   597     Phi isNil ifTrue:[
   602     Phi isNil ifTrue:[
   598         Phi := Float phi asShortFloat
   603 	Phi := Float phi asShortFloat
   599     ].
   604     ].
   600     ^ Phi
   605     ^ Phi
   601 !
   606 !
   602 
   607 
   603 pi
   608 pi
   644 epsilon
   649 epsilon
   645     "return the maximum relative spacing of instances of mySelf
   650     "return the maximum relative spacing of instances of mySelf
   646      (i.e. the value-delta of the least significant bit)"
   651      (i.e. the value-delta of the least significant bit)"
   647 
   652 
   648     Epsilon isNil ifTrue:[
   653     Epsilon isNil ifTrue:[
   649         Epsilon := self computeEpsilon.
   654 	Epsilon := self computeEpsilon.
   650     ].
   655     ].
   651     ^ Epsilon
   656     ^ Epsilon
   652 
   657 
   653     "
   658     "
   654      self epsilon
   659      self epsilon
   678 !
   683 !
   679 
   684 
   680 numBitsInExponent
   685 numBitsInExponent
   681     "answer the number of bits in the exponent
   686     "answer the number of bits in the exponent
   682      This is an IEEE float, where 8 bits are available:
   687      This is an IEEE float, where 8 bits are available:
   683         seeeeeee emmmmmmm mmmmmmmm mmmmmmmm
   688 	seeeeeee emmmmmmm mmmmmmmm mmmmmmmm
   684     "
   689     "
   685 
   690 
   686     ^ 8
   691     ^ 8
   687 
   692 
   688     "
   693     "
  1209      For background information why floats need this
  1214      For background information why floats need this
  1210      read: http://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/
  1215      read: http://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/
  1211     "
  1216     "
  1212 
  1217 
  1213     Epsilon isNil ifTrue:[
  1218     Epsilon isNil ifTrue:[
  1214         Epsilon := self class computeEpsilon.
  1219 	Epsilon := self class computeEpsilon.
  1215     ].
  1220     ].
  1216 
  1221 
  1217 %{  /* NOCONTEXT */
  1222 %{  /* NOCONTEXT */
  1218 
  1223 
  1219     /*
  1224     /*
  1226      * (see the message send at the bottom)
  1231      * (see the message send at the bottom)
  1227      */
  1232      */
  1228 
  1233 
  1229     INT32 ulpDiff;
  1234     INT32 ulpDiff;
  1230     union {
  1235     union {
  1231         float f;
  1236 	float f;
  1232         INT32 i;
  1237 	INT32 i;
  1233     } myself, otherFloat;
  1238     } myself, otherFloat;
  1234     int nEpsilon;
  1239     int nEpsilon;
  1235     float scaledEpsilon;
  1240     float scaledEpsilon;
  1236 
  1241 
  1237     if (!__isSmallInteger(nE)) {
  1242     if (!__isSmallInteger(nE)) {
  1238         goto tryHarder;
  1243 	goto tryHarder;
  1239     }
  1244     }
  1240 
  1245 
  1241     nEpsilon =  __intVal(nE);
  1246     nEpsilon =  __intVal(nE);
  1242     scaledEpsilon = nEpsilon *__shortFloatVal(@global(Epsilon));
  1247     scaledEpsilon = nEpsilon *__shortFloatVal(@global(Epsilon));
  1243 
  1248 
  1244     if (__isSmallInteger(aNumber)) {
  1249     if (__isSmallInteger(aNumber)) {
  1245         otherFloat.f = (float)(__intVal(aNumber));
  1250 	otherFloat.f = (float)(__intVal(aNumber));
  1246     } else if (aNumber == nil) {
  1251     } else if (aNumber == nil) {
  1247         RETURN(false)
  1252 	RETURN(false)
  1248     } else if (__qIsFloatLike(aNumber)) {
  1253     } else if (__qIsFloatLike(aNumber)) {
  1249         otherFloat.f = (float)(__floatVal(aNumber));
  1254 	otherFloat.f = (float)(__floatVal(aNumber));
  1250     } else if (__qIsShortFloat(aNumber)) {
  1255     } else if (__qIsShortFloat(aNumber)) {
  1251         otherFloat.f = __shortFloatVal(aNumber);
  1256 	otherFloat.f = __shortFloatVal(aNumber);
  1252 //    } else if (__qIsLongFloat(aNumber)) {
  1257 //    } else if (__qIsLongFloat(aNumber)) {
  1253 //        otherFloat.f = (float)(__longFloatVal(aNumber));
  1258 //        otherFloat.f = (float)(__longFloatVal(aNumber));
  1254     } else {
  1259     } else {
  1255         goto tryHarder;
  1260 	goto tryHarder;
  1256     }
  1261     }
  1257 
  1262 
  1258     myself.f = __shortFloatVal(self);
  1263     myself.f = __shortFloatVal(self);
  1259 
  1264 
  1260     // Check if the numbers are really close -- needed
  1265     // Check if the numbers are really close -- needed
  1261     // when comparing numbers near zero (ULP method below fails for numbers near 0!).
  1266     // when comparing numbers near zero (ULP method below fails for numbers near 0!).
  1262 # ifdef NO_ABSF
  1267 # ifdef NO_ABSF
  1263     if (fabs((double)(myself.f - otherFloat.f)) <= scaledEpsilon) {
  1268     if (fabs((double)(myself.f - otherFloat.f)) <= scaledEpsilon) {
  1264         RETURN(true);
  1269 	RETURN(true);
  1265     }
  1270     }
  1266 # else
  1271 # else
  1267     // fprintf(stderr, "%.10f %.10f\n", fabsf(myself.f - otherFloat.f), scaledEpsilon);
  1272     // fprintf(stderr, "%.10f %.10f\n", fabsf(myself.f - otherFloat.f), scaledEpsilon);
  1268     if (fabsf(myself.f - otherFloat.f) <= scaledEpsilon) {
  1273     if (fabsf(myself.f - otherFloat.f) <= scaledEpsilon) {
  1269         RETURN(true);
  1274 	RETURN(true);
  1270     }
  1275     }
  1271 #endif
  1276 #endif
  1272 
  1277 
  1273     // if the signs differ, the numbers are different
  1278     // if the signs differ, the numbers are different
  1274     if ((myself.f >= 0) != (otherFloat.f >= 0)) {
  1279     if ((myself.f >= 0) != (otherFloat.f >= 0)) {
  1275         RETURN(false);
  1280 	RETURN(false);
  1276     }
  1281     }
  1277 
  1282 
  1278     // compute the difference of the 'units in the last place" ULP
  1283     // compute the difference of the 'units in the last place" ULP
  1279     // (if ulpDiff == 1, two floats are adjecant)
  1284     // (if ulpDiff == 1, two floats are adjecant)
  1280     ulpDiff = myself.i - otherFloat.i;
  1285     ulpDiff = myself.i - otherFloat.i;
  1281     if (ulpDiff < 0) ulpDiff = -ulpDiff;
  1286     if (ulpDiff < 0) ulpDiff = -ulpDiff;
  1282     if (ulpDiff <= nEpsilon) {
  1287     if (ulpDiff <= nEpsilon) {
  1283         RETURN(true);
  1288 	RETURN(true);
  1284     } else {
  1289     } else {
  1285         RETURN(false)
  1290 	RETURN(false)
  1286     }
  1291     }
  1287 
  1292 
  1288 tryHarder:;
  1293 tryHarder:;
  1289 %}.
  1294 %}.
  1290     ^ aNumber isAlmostEqualToFromShortFloat:self nEpsilon:nE
  1295     ^ aNumber isAlmostEqualToFromShortFloat:self nEpsilon:nE
  1291 
  1296 
  1292     "
  1297     "
  1293         67329.234 asShortFloat isAlmostEqualTo:67329.23401 asShortFloat nEpsilon:1
  1298 	67329.234 asShortFloat isAlmostEqualTo:67329.23401 asShortFloat nEpsilon:1
  1294         1.0 asShortFloat isAlmostEqualTo:1.0000001 asShortFloat nEpsilon:1
  1299 	1.0 asShortFloat isAlmostEqualTo:1.0000001 asShortFloat nEpsilon:1
  1295         1.0 asShortFloat isAlmostEqualTo:1.0000001  nEpsilon:1
  1300 	1.0 asShortFloat isAlmostEqualTo:1.0000001  nEpsilon:1
  1296         1.0 asShortFloat isAlmostEqualTo:-1.0 nEpsilon:1
  1301 	1.0 asShortFloat isAlmostEqualTo:-1.0 nEpsilon:1
  1297         1.0 asShortFloat isAlmostEqualTo:1 nEpsilon:1
  1302 	1.0 asShortFloat isAlmostEqualTo:1 nEpsilon:1
  1298         0.0 asShortFloat isAlmostEqualTo:0.0000001 asShortFloat nEpsilon:1
  1303 	0.0 asShortFloat isAlmostEqualTo:0.0000001 asShortFloat nEpsilon:1
  1299         0.0 asShortFloat isAlmostEqualTo:0.000001 asShortFloat nEpsilon:1
  1304 	0.0 asShortFloat isAlmostEqualTo:0.000001 asShortFloat nEpsilon:1
  1300         0.0 asShortFloat isAlmostEqualTo:self epsilon nEpsilon:1
  1305 	0.0 asShortFloat isAlmostEqualTo:self epsilon nEpsilon:1
  1301         0.0 asShortFloat - 1.192093e-07 asShortFloat
  1306 	0.0 asShortFloat - 1.192093e-07 asShortFloat
  1302     "
  1307     "
  1303 
  1308 
  1304     "Modified: / 10-05-2018 / 00:47:22 / stefan"
  1309     "Modified: / 10-05-2018 / 00:47:22 / stefan"
  1305 !
  1310 !
  1306 
  1311 
  1712     char buffer[256];
  1717     char buffer[256];
  1713     OBJ s;
  1718     OBJ s;
  1714     int len;
  1719     int len;
  1715 
  1720 
  1716     if (__isStringLike(formatString)) {
  1721     if (__isStringLike(formatString)) {
  1717         /*
  1722 	/*
  1718          * actually only needed on sparc: since thisContext is
  1723 	 * actually only needed on sparc: since thisContext is
  1719          * in a global register, which gets destroyed by printf,
  1724 	 * in a global register, which gets destroyed by printf,
  1720          * manually save it here - very stupid ...
  1725 	 * manually save it here - very stupid ...
  1721          */
  1726 	 */
  1722         __BEGIN_PROTECT_REGISTERS__
  1727 	__BEGIN_PROTECT_REGISTERS__
  1723 
  1728 
  1724         len = snprintf(buffer, sizeof(buffer), __stringVal(formatString), __shortFloatVal(self));
  1729 	len = snprintf(buffer, sizeof(buffer), __stringVal(formatString), __shortFloatVal(self));
  1725 
  1730 
  1726         __END_PROTECT_REGISTERS__
  1731 	__END_PROTECT_REGISTERS__
  1727 
  1732 
  1728         if (len < 0) goto fail;
  1733 	if (len < 0) goto fail;
  1729         if (len >= sizeof(buffer)) goto fail;
  1734 	if (len >= sizeof(buffer)) goto fail;
  1730 
  1735 
  1731         s = __MKSTRING_L(buffer, len);
  1736 	s = __MKSTRING_L(buffer, len);
  1732         if (s != nil) {
  1737 	if (s != nil) {
  1733             RETURN (s);
  1738 	    RETURN (s);
  1734         }
  1739 	}
  1735     }
  1740     }
  1736 fail: ;
  1741 fail: ;
  1737 #endif /* not __SCHTEAM__ */
  1742 #endif /* not __SCHTEAM__ */
  1738 %}.
  1743 %}.
  1739     ^ super printfPrintString:formatString
  1744     ^ super printfPrintString:formatString
  2012     // should we?
  2017     // should we?
  2013     if (!isnanf(myVal) && isfinitef(myVal))
  2018     if (!isnanf(myVal) && isfinitef(myVal))
  2014 #endif
  2019 #endif
  2015     {
  2020     {
  2016 #if defined(__i386__) && defined(__GNUC__)
  2021 #if defined(__i386__) && defined(__GNUC__)
  2017         float frac = frexpf(myVal, &exp);
  2022 	float frac = frexpf(myVal, &exp);
  2018         RETURN (__MKSFLOAT(frac));
  2023 	RETURN (__MKSFLOAT(frac));
  2019 #else
  2024 #else
  2020         double frac = frexp( (double)(myVal), &exp);
  2025 	double frac = frexp( (double)(myVal), &exp);
  2021         RETURN (__MKFLOAT(frac));
  2026 	RETURN (__MKFLOAT(frac));
  2022 #endif
  2027 #endif
  2023     }
  2028     }
  2024 %}.
  2029 %}.
  2025     ^ super mantissa
  2030     ^ super mantissa
  2026 
  2031 
  2059     if (isfinitef(fV)) { RETURN (true); }
  2064     if (isfinitef(fV)) { RETURN (true); }
  2060 %}.
  2065 %}.
  2061     ^ false
  2066     ^ false
  2062 
  2067 
  2063     "
  2068     "
  2064         1.0 asShortFloat isFinite
  2069 	1.0 asShortFloat isFinite
  2065         (0.0 asShortFloat uncheckedDivide: 0.0) isFinite
  2070 	(0.0 asShortFloat uncheckedDivide: 0.0) isFinite
  2066         (1.0 asShortFloat uncheckedDivide: 0.0) isFinite
  2071 	(1.0 asShortFloat uncheckedDivide: 0.0) isFinite
  2067     "
  2072     "
  2068 !
  2073 !
  2069 
  2074 
  2070 isNaN
  2075 isNaN
  2071     "return true, if the receiver is an invalid float (NaN - not a number).
  2076     "return true, if the receiver is an invalid float (NaN - not a number).
  2207 #endif
  2212 #endif
  2208     /*
  2213     /*
  2209      * ST-80 (and X3J20) returns integer.
  2214      * ST-80 (and X3J20) returns integer.
  2210      */
  2215      */
  2211     if ((fVal >= (float)_MIN_INT) && (fVal <= (float)_MAX_INT)) {
  2216     if ((fVal >= (float)_MIN_INT) && (fVal <= (float)_MAX_INT)) {
  2212         RETURN ( __mkSmallInteger( (INT) fVal ) );
  2217 	RETURN ( __mkSmallInteger( (INT) fVal ) );
  2213     }
  2218     }
  2214     __qMKSFLOAT(val, fVal);
  2219     __qMKSFLOAT(val, fVal);
  2215 %}.
  2220 %}.
  2216     ^ val asInteger
  2221     ^ val asInteger
  2217 
  2222 
  2261 #endif
  2266 #endif
  2262     /*
  2267     /*
  2263      * ST-80 (and X3J20) returns integer.
  2268      * ST-80 (and X3J20) returns integer.
  2264      */
  2269      */
  2265     if ((fVal >= (float)_MIN_INT) && (fVal <= (float)_MAX_INT)) {
  2270     if ((fVal >= (float)_MIN_INT) && (fVal <= (float)_MAX_INT)) {
  2266         RETURN ( __mkSmallInteger( (INT) fVal ) );
  2271 	RETURN ( __mkSmallInteger( (INT) fVal ) );
  2267     }
  2272     }
  2268     __qMKSFLOAT(val, fVal);
  2273     __qMKSFLOAT(val, fVal);
  2269 %}.
  2274 %}.
  2270     ^ val asInteger
  2275     ^ val asInteger
  2271 
  2276 
  2356     float fVal;
  2361     float fVal;
  2357 
  2362 
  2358     fVal = __shortFloatVal(self);
  2363     fVal = __shortFloatVal(self);
  2359 #if (defined(__i386__) || defined(__x86_64__)) && defined(__GNUC__)
  2364 #if (defined(__i386__) || defined(__x86_64__)) && defined(__GNUC__)
  2360     if (fVal < 0.0) {
  2365     if (fVal < 0.0) {
  2361         fVal = ceilf(fVal - (float)0.5);
  2366 	fVal = ceilf(fVal - (float)0.5);
  2362     } else {
  2367     } else {
  2363         fVal = floorf(fVal + (float)0.5);
  2368 	fVal = floorf(fVal + (float)0.5);
  2364     }
  2369     }
  2365 #else
  2370 #else
  2366     if (fVal < 0.0) {
  2371     if (fVal < 0.0) {
  2367         fVal = (float)ceil((double)fVal - 0.5);
  2372 	fVal = (float)ceil((double)fVal - 0.5);
  2368     } else {
  2373     } else {
  2369         fVal = (float)floor((double)fVal + 0.5);
  2374 	fVal = (float)floor((double)fVal + 0.5);
  2370     }
  2375     }
  2371 #endif
  2376 #endif
  2372     /*
  2377     /*
  2373      * ST-80 (and X3J20) return integer.
  2378      * ST-80 (and X3J20) return integer.
  2374      */
  2379      */
  2375     if ((fVal >= (float)_MIN_INT) && (fVal <= (float)_MAX_INT)) {
  2380     if ((fVal >= (float)_MIN_INT) && (fVal <= (float)_MAX_INT)) {
  2376         RETURN ( __mkSmallInteger( (INT) fVal ) );
  2381 	RETURN ( __mkSmallInteger( (INT) fVal ) );
  2377     }
  2382     }
  2378     __qMKSFLOAT(val, fVal);
  2383     __qMKSFLOAT(val, fVal);
  2379 %}.
  2384 %}.
  2380     ^ val asInteger
  2385     ^ val asInteger
  2381 
  2386 
  2401     OBJ v;
  2406     OBJ v;
  2402 
  2407 
  2403     fVal = __shortFloatVal(self);
  2408     fVal = __shortFloatVal(self);
  2404 #if (defined(__i386__) || defined(__x86_64__)) && defined(__GNUC__)
  2409 #if (defined(__i386__) || defined(__x86_64__)) && defined(__GNUC__)
  2405     if (fVal < 0.0) {
  2410     if (fVal < 0.0) {
  2406         fVal = ceilf(fVal - (float)0.5);
  2411 	fVal = ceilf(fVal - (float)0.5);
  2407     } else {
  2412     } else {
  2408         fVal = floorf(fVal + (float)0.5);
  2413 	fVal = floorf(fVal + (float)0.5);
  2409     }
  2414     }
  2410 #else
  2415 #else
  2411     if (fVal < 0.0) {
  2416     if (fVal < 0.0) {
  2412         fVal = (float)ceil((double)fVal - 0.5);
  2417 	fVal = (float)ceil((double)fVal - 0.5);
  2413     } else {
  2418     } else {
  2414         fVal = (float)floor((double)fVal + 0.5);
  2419 	fVal = (float)floor((double)fVal + 0.5);
  2415     }
  2420     }
  2416 #endif
  2421 #endif
  2417     __qMKSFLOAT(v, fVal);
  2422     __qMKSFLOAT(v, fVal);
  2418     RETURN (v);
  2423     RETURN (v);
  2419 %}
  2424 %}
  2444     float fVal;
  2449     float fVal;
  2445 
  2450 
  2446     fVal = __shortFloatVal(self);
  2451     fVal = __shortFloatVal(self);
  2447 #if (defined(__i386__) || defined(__x86_64__)) && defined(__GNUC__)
  2452 #if (defined(__i386__) || defined(__x86_64__)) && defined(__GNUC__)
  2448     if (fVal < 0.0) {
  2453     if (fVal < 0.0) {
  2449         fVal = ceilf(fVal);
  2454 	fVal = ceilf(fVal);
  2450     } else {
  2455     } else {
  2451         fVal = floorf(fVal);
  2456 	fVal = floorf(fVal);
  2452     }
  2457     }
  2453 #else
  2458 #else
  2454     if (fVal < 0.0) {
  2459     if (fVal < 0.0) {
  2455         fVal = (float)ceil((double)fVal);
  2460 	fVal = (float)ceil((double)fVal);
  2456     } else {
  2461     } else {
  2457         fVal = (float)floor((double)fVal);
  2462 	fVal = (float)floor((double)fVal);
  2458     }
  2463     }
  2459 #endif
  2464 #endif
  2460     /*
  2465     /*
  2461      * ST-80 (and X3J20) returns integer.
  2466      * ST-80 (and X3J20) returns integer.
  2462      */
  2467      */
  2463     if ((fVal >= (float)_MIN_INT) && (fVal <= (float)_MAX_INT)) {
  2468     if ((fVal >= (float)_MIN_INT) && (fVal <= (float)_MAX_INT)) {
  2464         RETURN ( __mkSmallInteger( (INT) fVal ) );
  2469 	RETURN ( __mkSmallInteger( (INT) fVal ) );
  2465     }
  2470     }
  2466     __qMKSFLOAT(val, fVal);
  2471     __qMKSFLOAT(val, fVal);
  2467 %}.
  2472 %}.
  2468     ^ val asInteger
  2473     ^ val asInteger
  2469 
  2474 
  2487     OBJ v;
  2492     OBJ v;
  2488 
  2493 
  2489     fVal = __shortFloatVal(self);
  2494     fVal = __shortFloatVal(self);
  2490 #if (defined(__i386__) || defined(xx__x86_64__)) && defined(__GNUC__)
  2495 #if (defined(__i386__) || defined(xx__x86_64__)) && defined(__GNUC__)
  2491     if (fVal < 0.0) {
  2496     if (fVal < 0.0) {
  2492         fVal = ceilf(fVal);
  2497 	fVal = ceilf(fVal);
  2493     } else {
  2498     } else {
  2494         fVal = floorf(fVal);
  2499 	fVal = floorf(fVal);
  2495     }
  2500     }
  2496 #else
  2501 #else
  2497     if (fVal < 0.0) {
  2502     if (fVal < 0.0) {
  2498         fVal = (float)ceil((double)fVal);
  2503 	fVal = (float)ceil((double)fVal);
  2499     } else {
  2504     } else {
  2500         fVal = (float)floor((double)fVal);
  2505 	fVal = (float)floor((double)fVal);
  2501     }
  2506     }
  2502 #endif
  2507 #endif
  2503     __qMKSFLOAT(v, fVal);
  2508     __qMKSFLOAT(v, fVal);
  2504     RETURN (v);
  2509     RETURN (v);
  2505 %}
  2510 %}