--- a/ShortFloat.st Mon Nov 25 12:14:31 2019 +0100
+++ b/ShortFloat.st Mon Nov 25 14:17:45 2019 +0100
@@ -203,38 +203,38 @@
Thus, STX's Float precision is not worse than that of other ST's.
WARNING:
- The layout of shortFloat instances is known by the runtime system and the compiler;
- you may not add instance variables here.
- Also, subclassing is complicated by the fact, that the VM creates floats/shortFloats,
- and does some of its float-checks by an identity compare with the ShortFloat-class.
- (i.e. your subclasses instances may not be recognized as float-like objects,
- thus mixed mode arithmetic will always coerce them, effectively slowing things down).
- This may be changed, to use a flag bit in the class.
+ The layout of shortFloat instances is known by the runtime system and the compiler;
+ you may not add instance variables here.
+ Also, subclassing is complicated by the fact, that the VM creates floats/shortFloats,
+ and does some of its float-checks by an identity compare with the ShortFloat-class.
+ (i.e. your subclasses instances may not be recognized as float-like objects,
+ thus mixed mode arithmetic will always coerce them, effectively slowing things down).
+ This may be changed, to use a flag bit in the class.
Mixed mode arithmetic:
- shortFloat op shortFloat -> shortFloat
- shortFloat op fix -> shortFloat
- shortFloat op fraction -> shortFloat
- shortFloat op integer -> shortFloat
- shortFloat op longFloat -> longFloat
- shortFloat op float -> float
- shortFloat op complex -> complex
+ shortFloat op shortFloat -> shortFloat
+ shortFloat op fix -> shortFloat
+ shortFloat op fraction -> shortFloat
+ shortFloat op integer -> shortFloat
+ shortFloat op longFloat -> longFloat
+ shortFloat op float -> float
+ shortFloat op complex -> complex
Representation:
- 32bit single precision IEEE floats
- 23 bit mantissa + 1 hidden bit, providing a precision of 24bits,
- 8 bit exponent,
- 6 decimal digits (approx.)
+ 32bit single precision IEEE floats
+ 23 bit mantissa + 1 hidden bit, providing a precision of 24bits,
+ 8 bit exponent,
+ 6 decimal digits (approx.)
Range and Precision of Storage Formats: see LimitedPrecisionReal >> documentation
[author:]
- Claus Gittinger
+ Claus Gittinger
[see also:]
- Number
- Float LongFloat Fraction FixedPoint Integer Complex
- FloatArray DoubleArray
+ Number
+ Float LongFloat Fraction FixedPoint Integer Complex
+ FloatArray DoubleArray
"
! !
@@ -264,24 +264,29 @@
Returns garbage if the argument string is not a valid float number.
This is a specially tuned entry (using a low-level C-call to atof).
- It has been added to allow high speed string decomposition
+ It has been added to allow high speed string decomposition
into numbers, especially for mass-data (reading millions of floats)."
%{ /* NOCONTEXT */
if (__isStringLike(aString) && __isSmallInteger(startIndex)) {
- char *cp = (char *)(__stringVal(aString));
- int idx = __intVal(startIndex) - 1;
-
- if ((unsigned)idx < __stringSize(aString)) {
+ char *cp = (char *)(__stringVal(aString));
+ int idx = __intVal(startIndex) - 1;
+
+ if ((unsigned)idx < __stringSize(aString)) {
#ifndef NO_STRTOF
- float strtof(const char *, char**);
- float val = strtof(cp+idx, NULL);
+ float strtof(const char *, char**);
+ float val = strtof(cp+idx, NULL);
#else
- double atof(const char *);
- double val = atof(cp + idx);
+# ifndef NO_STRTOD
+ double strtod(const char *, char**);
+ double val = strtod(cp+idx, NULL);
+# else
+ double atof(const char *);
+ double val = atof(cp + idx);
+# endif
#endif
- RETURN (__MKSFLOAT(val));
- }
+ RETURN (__MKSFLOAT(val));
+ }
}
%}.
self primitiveFailed.
@@ -303,17 +308,17 @@
"
Time millisecondsToRun:[
- 1000000 timesRepeat:[
- ShortFloat readFrom:'123.45'
- ]
+ 1000000 timesRepeat:[
+ ShortFloat readFrom:'123.45'
+ ]
]
"
"
Time millisecondsToRun:[
- 1000000 timesRepeat:[
- ShortFloat fastFromString:'123.45' at:1
- ]
+ 1000000 timesRepeat:[
+ ShortFloat fastFromString:'123.45' at:1
+ ]
]
"
@@ -343,9 +348,9 @@
defaultPrintFormat
"/ by default, I will print 7 digits
- "/ ShortFloat pi -> 3.141593
- "/ Float pi -> 3.14159265358979
- "/ LongFloat pi -> 3.141592653589793239
+ "/ ShortFloat pi -> 3.141593
+ "/ Float pi -> 3.14159265358979
+ "/ LongFloat pi -> 3.141592653589793239
^ DefaultPrintFormat
!
@@ -495,7 +500,7 @@
"return a shortFloat which represents not-a-Number (i.e. an invalid number)"
NaN isNil ifTrue:[
- NaN := super NaN
+ NaN := super NaN
].
^ NaN
@@ -517,7 +522,7 @@
!
eBias
- "Answer the exponent's bias;
+ "Answer the exponent's bias;
that is the offset of the zero exponent when stored"
^ 127
@@ -539,7 +544,7 @@
"return a shortFloat which represents positive infinity (for my instances)"
PositiveInfinity isNil ifTrue:[
- PositiveInfinity := Float infinity asShortFloat
+ PositiveInfinity := Float infinity asShortFloat
].
^ PositiveInfinity
@@ -566,7 +571,7 @@
"return the natural logarithm of 2 as a shortFloat"
Ln2 isNil ifTrue:[
- Ln2 := Float ln2 asShortFloat
+ Ln2 := Float ln2 asShortFloat
].
^ Ln2
@@ -583,7 +588,7 @@
instead, check using isFinite or isInfinite"
NegativeInfinity isNil ifTrue:[
- NegativeInfinity := Float negativeInfinity asShortFloat
+ NegativeInfinity := Float negativeInfinity asShortFloat
].
^ NegativeInfinity
@@ -595,7 +600,7 @@
"return the constant phi as ShortFloat"
Phi isNil ifTrue:[
- Phi := Float phi asShortFloat
+ Phi := Float phi asShortFloat
].
^ Phi
!
@@ -646,7 +651,7 @@
(i.e. the value-delta of the least significant bit)"
Epsilon isNil ifTrue:[
- Epsilon := self computeEpsilon.
+ Epsilon := self computeEpsilon.
].
^ Epsilon
@@ -680,7 +685,7 @@
numBitsInExponent
"answer the number of bits in the exponent
This is an IEEE float, where 8 bits are available:
- seeeeeee emmmmmmm mmmmmmmm mmmmmmmm
+ seeeeeee emmmmmmm mmmmmmmm mmmmmmmm
"
^ 8
@@ -1211,7 +1216,7 @@
"
Epsilon isNil ifTrue:[
- Epsilon := self class computeEpsilon.
+ Epsilon := self class computeEpsilon.
].
%{ /* NOCONTEXT */
@@ -1228,31 +1233,31 @@
INT32 ulpDiff;
union {
- float f;
- INT32 i;
+ float f;
+ INT32 i;
} myself, otherFloat;
int nEpsilon;
float scaledEpsilon;
if (!__isSmallInteger(nE)) {
- goto tryHarder;
+ goto tryHarder;
}
nEpsilon = __intVal(nE);
scaledEpsilon = nEpsilon *__shortFloatVal(@global(Epsilon));
if (__isSmallInteger(aNumber)) {
- otherFloat.f = (float)(__intVal(aNumber));
+ otherFloat.f = (float)(__intVal(aNumber));
} else if (aNumber == nil) {
- RETURN(false)
+ RETURN(false)
} else if (__qIsFloatLike(aNumber)) {
- otherFloat.f = (float)(__floatVal(aNumber));
+ otherFloat.f = (float)(__floatVal(aNumber));
} else if (__qIsShortFloat(aNumber)) {
- otherFloat.f = __shortFloatVal(aNumber);
+ otherFloat.f = __shortFloatVal(aNumber);
// } else if (__qIsLongFloat(aNumber)) {
// otherFloat.f = (float)(__longFloatVal(aNumber));
} else {
- goto tryHarder;
+ goto tryHarder;
}
myself.f = __shortFloatVal(self);
@@ -1261,18 +1266,18 @@
// when comparing numbers near zero (ULP method below fails for numbers near 0!).
# ifdef NO_ABSF
if (fabs((double)(myself.f - otherFloat.f)) <= scaledEpsilon) {
- RETURN(true);
+ RETURN(true);
}
# else
// fprintf(stderr, "%.10f %.10f\n", fabsf(myself.f - otherFloat.f), scaledEpsilon);
if (fabsf(myself.f - otherFloat.f) <= scaledEpsilon) {
- RETURN(true);
+ RETURN(true);
}
#endif
// if the signs differ, the numbers are different
if ((myself.f >= 0) != (otherFloat.f >= 0)) {
- RETURN(false);
+ RETURN(false);
}
// compute the difference of the 'units in the last place" ULP
@@ -1280,9 +1285,9 @@
ulpDiff = myself.i - otherFloat.i;
if (ulpDiff < 0) ulpDiff = -ulpDiff;
if (ulpDiff <= nEpsilon) {
- RETURN(true);
+ RETURN(true);
} else {
- RETURN(false)
+ RETURN(false)
}
tryHarder:;
@@ -1290,15 +1295,15 @@
^ aNumber isAlmostEqualToFromShortFloat:self nEpsilon:nE
"
- 67329.234 asShortFloat isAlmostEqualTo:67329.23401 asShortFloat nEpsilon:1
- 1.0 asShortFloat isAlmostEqualTo:1.0000001 asShortFloat nEpsilon:1
- 1.0 asShortFloat isAlmostEqualTo:1.0000001 nEpsilon:1
- 1.0 asShortFloat isAlmostEqualTo:-1.0 nEpsilon:1
- 1.0 asShortFloat isAlmostEqualTo:1 nEpsilon:1
- 0.0 asShortFloat isAlmostEqualTo:0.0000001 asShortFloat nEpsilon:1
- 0.0 asShortFloat isAlmostEqualTo:0.000001 asShortFloat nEpsilon:1
- 0.0 asShortFloat isAlmostEqualTo:self epsilon nEpsilon:1
- 0.0 asShortFloat - 1.192093e-07 asShortFloat
+ 67329.234 asShortFloat isAlmostEqualTo:67329.23401 asShortFloat nEpsilon:1
+ 1.0 asShortFloat isAlmostEqualTo:1.0000001 asShortFloat nEpsilon:1
+ 1.0 asShortFloat isAlmostEqualTo:1.0000001 nEpsilon:1
+ 1.0 asShortFloat isAlmostEqualTo:-1.0 nEpsilon:1
+ 1.0 asShortFloat isAlmostEqualTo:1 nEpsilon:1
+ 0.0 asShortFloat isAlmostEqualTo:0.0000001 asShortFloat nEpsilon:1
+ 0.0 asShortFloat isAlmostEqualTo:0.000001 asShortFloat nEpsilon:1
+ 0.0 asShortFloat isAlmostEqualTo:self epsilon nEpsilon:1
+ 0.0 asShortFloat - 1.192093e-07 asShortFloat
"
"Modified: / 10-05-2018 / 00:47:22 / stefan"
@@ -1714,24 +1719,24 @@
int len;
if (__isStringLike(formatString)) {
- /*
- * actually only needed on sparc: since thisContext is
- * in a global register, which gets destroyed by printf,
- * manually save it here - very stupid ...
- */
- __BEGIN_PROTECT_REGISTERS__
-
- len = snprintf(buffer, sizeof(buffer), __stringVal(formatString), __shortFloatVal(self));
-
- __END_PROTECT_REGISTERS__
-
- if (len < 0) goto fail;
- if (len >= sizeof(buffer)) goto fail;
-
- s = __MKSTRING_L(buffer, len);
- if (s != nil) {
- RETURN (s);
- }
+ /*
+ * actually only needed on sparc: since thisContext is
+ * in a global register, which gets destroyed by printf,
+ * manually save it here - very stupid ...
+ */
+ __BEGIN_PROTECT_REGISTERS__
+
+ len = snprintf(buffer, sizeof(buffer), __stringVal(formatString), __shortFloatVal(self));
+
+ __END_PROTECT_REGISTERS__
+
+ if (len < 0) goto fail;
+ if (len >= sizeof(buffer)) goto fail;
+
+ s = __MKSTRING_L(buffer, len);
+ if (s != nil) {
+ RETURN (s);
+ }
}
fail: ;
#endif /* not __SCHTEAM__ */
@@ -2014,11 +2019,11 @@
#endif
{
#if defined(__i386__) && defined(__GNUC__)
- float frac = frexpf(myVal, &exp);
- RETURN (__MKSFLOAT(frac));
+ float frac = frexpf(myVal, &exp);
+ RETURN (__MKSFLOAT(frac));
#else
- double frac = frexp( (double)(myVal), &exp);
- RETURN (__MKFLOAT(frac));
+ double frac = frexp( (double)(myVal), &exp);
+ RETURN (__MKFLOAT(frac));
#endif
}
%}.
@@ -2061,9 +2066,9 @@
^ false
"
- 1.0 asShortFloat isFinite
- (0.0 asShortFloat uncheckedDivide: 0.0) isFinite
- (1.0 asShortFloat uncheckedDivide: 0.0) isFinite
+ 1.0 asShortFloat isFinite
+ (0.0 asShortFloat uncheckedDivide: 0.0) isFinite
+ (1.0 asShortFloat uncheckedDivide: 0.0) isFinite
"
!
@@ -2209,7 +2214,7 @@
* ST-80 (and X3J20) returns integer.
*/
if ((fVal >= (float)_MIN_INT) && (fVal <= (float)_MAX_INT)) {
- RETURN ( __mkSmallInteger( (INT) fVal ) );
+ RETURN ( __mkSmallInteger( (INT) fVal ) );
}
__qMKSFLOAT(val, fVal);
%}.
@@ -2263,7 +2268,7 @@
* ST-80 (and X3J20) returns integer.
*/
if ((fVal >= (float)_MIN_INT) && (fVal <= (float)_MAX_INT)) {
- RETURN ( __mkSmallInteger( (INT) fVal ) );
+ RETURN ( __mkSmallInteger( (INT) fVal ) );
}
__qMKSFLOAT(val, fVal);
%}.
@@ -2358,22 +2363,22 @@
fVal = __shortFloatVal(self);
#if (defined(__i386__) || defined(__x86_64__)) && defined(__GNUC__)
if (fVal < 0.0) {
- fVal = ceilf(fVal - (float)0.5);
+ fVal = ceilf(fVal - (float)0.5);
} else {
- fVal = floorf(fVal + (float)0.5);
+ fVal = floorf(fVal + (float)0.5);
}
#else
if (fVal < 0.0) {
- fVal = (float)ceil((double)fVal - 0.5);
+ fVal = (float)ceil((double)fVal - 0.5);
} else {
- fVal = (float)floor((double)fVal + 0.5);
+ fVal = (float)floor((double)fVal + 0.5);
}
#endif
/*
* ST-80 (and X3J20) return integer.
*/
if ((fVal >= (float)_MIN_INT) && (fVal <= (float)_MAX_INT)) {
- RETURN ( __mkSmallInteger( (INT) fVal ) );
+ RETURN ( __mkSmallInteger( (INT) fVal ) );
}
__qMKSFLOAT(val, fVal);
%}.
@@ -2403,15 +2408,15 @@
fVal = __shortFloatVal(self);
#if (defined(__i386__) || defined(__x86_64__)) && defined(__GNUC__)
if (fVal < 0.0) {
- fVal = ceilf(fVal - (float)0.5);
+ fVal = ceilf(fVal - (float)0.5);
} else {
- fVal = floorf(fVal + (float)0.5);
+ fVal = floorf(fVal + (float)0.5);
}
#else
if (fVal < 0.0) {
- fVal = (float)ceil((double)fVal - 0.5);
+ fVal = (float)ceil((double)fVal - 0.5);
} else {
- fVal = (float)floor((double)fVal + 0.5);
+ fVal = (float)floor((double)fVal + 0.5);
}
#endif
__qMKSFLOAT(v, fVal);
@@ -2446,22 +2451,22 @@
fVal = __shortFloatVal(self);
#if (defined(__i386__) || defined(__x86_64__)) && defined(__GNUC__)
if (fVal < 0.0) {
- fVal = ceilf(fVal);
+ fVal = ceilf(fVal);
} else {
- fVal = floorf(fVal);
+ fVal = floorf(fVal);
}
#else
if (fVal < 0.0) {
- fVal = (float)ceil((double)fVal);
+ fVal = (float)ceil((double)fVal);
} else {
- fVal = (float)floor((double)fVal);
+ fVal = (float)floor((double)fVal);
}
#endif
/*
* ST-80 (and X3J20) returns integer.
*/
if ((fVal >= (float)_MIN_INT) && (fVal <= (float)_MAX_INT)) {
- RETURN ( __mkSmallInteger( (INT) fVal ) );
+ RETURN ( __mkSmallInteger( (INT) fVal ) );
}
__qMKSFLOAT(val, fVal);
%}.
@@ -2489,15 +2494,15 @@
fVal = __shortFloatVal(self);
#if (defined(__i386__) || defined(xx__x86_64__)) && defined(__GNUC__)
if (fVal < 0.0) {
- fVal = ceilf(fVal);
+ fVal = ceilf(fVal);
} else {
- fVal = floorf(fVal);
+ fVal = floorf(fVal);
}
#else
if (fVal < 0.0) {
- fVal = (float)ceil((double)fVal);
+ fVal = (float)ceil((double)fVal);
} else {
- fVal = (float)floor((double)fVal);
+ fVal = (float)floor((double)fVal);
}
#endif
__qMKSFLOAT(v, fVal);