--- a/Float.st Wed Nov 27 22:47:34 2019 +0100
+++ b/Float.st Thu Nov 28 16:19:31 2019 +0100
@@ -34,6 +34,7 @@
#define __USE_ISOC9X 1
#define __USE_ISOC99 1
#include <math.h>
+#include <float.h>
#ifndef INT64
# ifdef HAS_LONGLONG
@@ -205,19 +206,19 @@
documentation
"
Floats represent rational numbers with limited precision.
- They use the C-compiler's 'double' format,
+ They use the C-compiler's 'double' format,
which is usually the 8byte IEEE double float format.
Floats give you 64 bit floats.
In contrast to ShortFloats (32bit) and LongFloats (>=64bit).
WARNING:
- The layout of Float 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 float-checks by an identity compare with the Float-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).
+ The layout of Float 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 float-checks by an identity compare with the Float-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).
Notice, that Floats are defined as Byte-array to prevent the garbage collector
from going into the value ... otherwise I needed a special case in many places.
@@ -232,29 +233,29 @@
instances.
Mixed mode arithmetic:
- float op float -> float
- float op fix -> float
- float op fraction -> float
- float op integer -> float
- float op shortFloat -> float
- float op longFloat -> longFloat
- float op complex -> complex
+ float op float -> float
+ float op fix -> float
+ float op fraction -> float
+ float op integer -> float
+ float op shortFloat -> float
+ float op longFloat -> longFloat
+ float op complex -> complex
Representation:
- 64bit double precision IEEE floats
- 52 bit mantissa + 1 hidden bit providing 53 bits of precision,
- 11 bit exponent,
- 15 decimal digits (approx.)
+ 64bit double precision IEEE floats
+ 52 bit mantissa + 1 hidden bit providing 53 bits of precision,
+ 11 bit exponent,
+ 15 decimal digits (approx.)
Range and Precision of Storage Formats: see LimitedPrecisionReal >> documentation
[author:]
- Claus Gittinger
+ Claus Gittinger
[see also:]
- Number
- ShortFloat LongFloat Fraction FixedPoint Integer Complex
- FloatArray DoubleArray
+ Number
+ ShortFloat LongFloat Fraction FixedPoint Integer Complex
+ FloatArray DoubleArray
"
!
@@ -318,21 +319,21 @@
int idx = __intVal(startIndex) - 1;
if (__isStringLike(aString) && __isSmallInteger(startIndex)) {
- char *cp = (char *)(__stringVal(aString));
- double val;
- OBJ newFloat;
-
- if ((unsigned)idx < __stringSize(aString)) {
+ char *cp = (char *)(__stringVal(aString));
+ double val;
+ OBJ newFloat;
+
+ if ((unsigned)idx < __stringSize(aString)) {
#ifndef NO_STRTOD
- double strtod(const char *, char**);
- val = strtod(cp+idx, NULL);
+ double strtod(const char *, char**);
+ val = strtod(cp+idx, NULL);
#else
- double atof();
- val = atof(cp + idx);
+ double atof();
+ val = atof(cp + idx);
#endif
- __qMKFLOAT(newFloat, val);
- RETURN (newFloat);
- }
+ __qMKFLOAT(newFloat, val);
+ RETURN (newFloat);
+ }
}
%}.
self primitiveFailed.
@@ -366,17 +367,17 @@
"
Time millisecondsToRun:[
- 1000000 timesRepeat:[
- Float readFrom:'123.45'
- ]
+ 1000000 timesRepeat:[
+ Float readFrom:'123.45'
+ ]
]
"
"
Time millisecondsToRun:[
- 1000000 timesRepeat:[
- Float fastFromString:'123.45' at:1
- ]
+ 1000000 timesRepeat:[
+ Float fastFromString:'123.45' at:1
+ ]
]
"
@@ -516,9 +517,9 @@
defaultPrintFormat
"/ by default, I will print 15 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
!
@@ -751,7 +752,7 @@
instead, check using isFinite or isInfinite"
PositiveInfinity isNil ifTrue:[
- PositiveInfinity := super infinity
+ PositiveInfinity := super infinity
].
^ PositiveInfinity
@@ -793,7 +794,7 @@
instead, check using isFinite or isInfinite"
NegativeInfinity isNil ifTrue:[
- NegativeInfinity := super negativeInfinity
+ NegativeInfinity := super negativeInfinity
].
^ NegativeInfinity
@@ -909,7 +910,7 @@
!Float class methodsFor:'queries'!
eBias
- "Answer the exponent's bias;
+ "Answer the exponent's bias;
that is the offset of the zero exponent when stored"
^ 1023
@@ -933,7 +934,7 @@
see https://en.wikipedia.org/wiki/Machine_epsilon"
Epsilon isNil ifTrue:[
- Epsilon := self computeEpsilon.
+ Epsilon := self computeEpsilon.
].
^ Epsilon
@@ -941,7 +942,7 @@
Float epsilon -> 1.11022302462516E-16
ShortFloat epsilon -> 5.960464e-08
LongFloat epsilon -> 5.42101086242752217E-20
- QuadFloat epsilon ->
+ QuadFloat epsilon ->
"
"Modified (comment): / 22-06-2017 / 13:44:12 / cg"
@@ -956,6 +957,26 @@
"Modified (comment): / 10-06-2019 / 21:27:46 / Claus Gittinger"
!
+fmin
+%{
+ RETURN(__MKFLOAT(DBL_MIN));
+%}.
+
+ "
+ Float fmin
+ "
+!
+
+fmax
+%{
+ RETURN(__MKFLOAT(DBL_MAX));
+%}.
+
+ "
+ Float fmax
+ "
+!
+
isBuiltInClass
"return true if this class is known by the run-time-system.
Here, true is returned for myself, false for subclasses."
@@ -1410,8 +1431,8 @@
float fVal = (float)dVal;
if (isfinite(fVal) || !isfinite(dVal)) {
- __qMKSFLOAT(newFloat, fVal);
- RETURN ( newFloat );
+ __qMKSFLOAT(newFloat, fVal);
+ RETURN ( newFloat );
}
%}.
"
@@ -1419,11 +1440,11 @@
if you need -INF for a zero receiver, try Number trapInfinity:[...]
"
^ self class
- raise:#infiniteResultSignal
- receiver:self
- selector:#asShortFloat
- arguments:#()
- errorString:'receiver is out of the single-precision float range'
+ raise:#infiniteResultSignal
+ receiver:self
+ selector:#asShortFloat
+ arguments:#()
+ errorString:'receiver is out of the single-precision float range'
"Modified: / 07-06-2019 / 02:34:14 / Claus Gittinger"
!
@@ -1440,7 +1461,7 @@
|shifty sign expPart exp fraction fractionPart result zeroBitsCount|
self isFinite ifFalse:[
- ^ self asMetaNumber
+ ^ self asMetaNumber
"/ ^ self class
"/ raise:#domainErrorSignal
"/ receiver:self
@@ -1452,10 +1473,10 @@
"Extract the bits of an IEEE double float "
shifty := LargeInteger basicNew numberOfDigits:8.
UninterpretedBytes isBigEndian ifTrue:[
- "/ shifty := ((self longWordAt: 1) bitShift: 32) + (self longWordAt: 2).
- 1 to:8 do:[:i | shifty digitAt:(9-i) put:(self basicAt:i)].
+ "/ shifty := ((self longWordAt: 1) bitShift: 32) + (self longWordAt: 2).
+ 1 to:8 do:[:i | shifty digitAt:(9-i) put:(self basicAt:i)].
] ifFalse:[
- 1 to:8 do:[:i | shifty digitAt:i put:(self basicAt:i)].
+ 1 to:8 do:[:i | shifty digitAt:i put:(self basicAt:i)].
].
" Extract the sign and the biased exponent "
@@ -1476,19 +1497,19 @@
the number of trailing zero bits in the fraction to minimize
the (huge) time otherwise spent in #gcd:. "
exp negative ifTrue: [
- result := sign * (fraction bitShift: exp negated)
+ result := sign * (fraction bitShift: exp negated)
] ifFalse:[
- zeroBitsCount := fraction lowBit - 1.
- exp := exp - zeroBitsCount.
- exp <= 0 ifTrue: [
- zeroBitsCount := zeroBitsCount + exp.
- "exp := 0." " Not needed; exp not refernced again "
- result := sign * (fraction bitShift:zeroBitsCount negated)
- ] ifFalse: [
- result := Fraction
- numerator: (sign * (fraction bitShift: zeroBitsCount negated))
- denominator: (1 bitShift:exp)
- ]
+ zeroBitsCount := fraction lowBit - 1.
+ exp := exp - zeroBitsCount.
+ exp <= 0 ifTrue: [
+ zeroBitsCount := zeroBitsCount + exp.
+ "exp := 0." " Not needed; exp not refernced again "
+ result := sign * (fraction bitShift:zeroBitsCount negated)
+ ] ifFalse: [
+ result := Fraction
+ numerator: (sign * (fraction bitShift: zeroBitsCount negated))
+ denominator: (1 bitShift:exp)
+ ]
].
"Low cost validation omitted after extensive testing"
@@ -1911,15 +1932,15 @@
val = __floatVal(self);
{
- __threadErrno = 0;
- rslt = cbrt(val);
- if (! isnan(rslt)) /* Currently all our systems support isnan() */
- {
- if (__threadErrno == 0) {
- __qMKFLOAT(newFloat, rslt);
- RETURN ( newFloat );
- }
- }
+ __threadErrno = 0;
+ rslt = cbrt(val);
+ if (! isnan(rslt)) /* Currently all our systems support isnan() */
+ {
+ if (__threadErrno == 0) {
+ __qMKFLOAT(newFloat, rslt);
+ RETURN ( newFloat );
+ }
+ }
}
# endif /* WIN32 */
%}.
@@ -1928,10 +1949,10 @@
"
8 cbrt
-8 cbrt
- 8.0 cbrt
- -8.0 cbrt
- 8.0 raisedTo:(1/3)
- -8.0 raisedTo:(1/3)
+ 8.0 cbrt
+ -8.0 cbrt
+ 8.0 raisedTo:(1/3)
+ -8.0 raisedTo:(1/3)
"
!
@@ -1975,29 +1996,29 @@
OBJ newFloat;
if (__isSmallInteger(exp)) {
- int __exp = __intVal(exp);
-
- val = __floatVal(self);
-
- {
- __threadErrno = 0;
- rslt = ldexp(val, __exp);
- if (! isnan(rslt)) /* Currently all our systems support isnan() */
- {
- if (__threadErrno == 0) {
- __qMKFLOAT(newFloat, rslt);
- RETURN ( newFloat );
- }
- }
- }
+ int __exp = __intVal(exp);
+
+ val = __floatVal(self);
+
+ {
+ __threadErrno = 0;
+ rslt = ldexp(val, __exp);
+ if (! isnan(rslt)) /* Currently all our systems support isnan() */
+ {
+ if (__threadErrno == 0) {
+ __qMKFLOAT(newFloat, rslt);
+ RETURN ( newFloat );
+ }
+ }
+ }
}
#endif
%}.
^ super ldexp:exp
"
- 1.0 mantissa ldexp:1.0 exponent
- -1.0 mantissa ldexp:-1.0 exponent
+ 1.0 mantissa ldexp:1.0 exponent
+ -1.0 mantissa ldexp:-1.0 exponent
1.0 ldexp:16 -> 65536.0
1.0 ldexp:100 -> 1.26765060022823E+30
@@ -2139,9 +2160,9 @@
reciprocalLogBase2
"optimized for self = 10, for use in conversion for printing"
- ^ self = 10.0s
- ifTrue: [Ln2 / Ln10]
- ifFalse: [Ln2 / self ln]
+ ^ self = 10.0s
+ ifTrue: [Ln2 / Ln10]
+ ifFalse: [Ln2 / self ln]
!
sqrt
@@ -2358,24 +2379,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), __floatVal(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), __floatVal(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__ */
@@ -2661,19 +2682,19 @@
if (! (isnan(myVal) || isinf(myVal)))
#endif
{
- frac = frexp(myVal, &exp);
- RETURN (__mkSmallInteger(exp));
+ frac = frexp(myVal, &exp);
+ RETURN (__mkSmallInteger(exp));
}
%}.
^ super exponent
"
- 1.0 exponent
- 2.0 exponent
+ 1.0 exponent
+ 2.0 exponent
3.0 exponent
3.0 mantissa
3.0 mantissa * (2 raisedTo:3.0 exponent)
- 4.0 exponent
+ 4.0 exponent
0.5 exponent
0.4 exponent
0.25 exponent
@@ -2745,11 +2766,11 @@
%}.
"
- 1.0 isFinite
- 1 isFinite
-
- Float NaN isFinite
- Float infinity isFinite
+ 1.0 isFinite
+ 1 isFinite
+
+ Float NaN isFinite
+ Float infinity isFinite
Float negativeInfinity isFinite
(0.0 uncheckedDivide: 0.0) isFinite
(1.0 uncheckedDivide: 0.0) isFinite
@@ -2779,10 +2800,10 @@
^ false
"
- 1.0 isInfinite
- (0.0 uncheckedDivide: 0.0) isInfinite
- (1.0 uncheckedDivide: 0.0) isInfinite
- (-1.0 uncheckedDivide: 0.0) isInfinite
+ 1.0 isInfinite
+ (0.0 uncheckedDivide: 0.0) isInfinite
+ (1.0 uncheckedDivide: 0.0) isInfinite
+ (-1.0 uncheckedDivide: 0.0) isInfinite
"
!
@@ -2806,11 +2827,11 @@
%}.
"
- self NaN isNaN
- 1.0 isNaN
- (0.0 uncheckedDivide: 0.0) isNaN
- (1.0 uncheckedDivide: 0.0) isNaN
- (-1.0 uncheckedDivide: 0.0) isNaN
+ self NaN isNaN
+ 1.0 isNaN
+ (0.0 uncheckedDivide: 0.0) isNaN
+ (1.0 uncheckedDivide: 0.0) isNaN
+ (-1.0 uncheckedDivide: 0.0) isNaN
"
!
@@ -2862,13 +2883,13 @@
(1.0 uncheckedDivide: 0.0) negative
(-1.0 uncheckedDivide: 0.0) negative
- Float infinity negative
- Float negativeInfinity negative
- Float NaN negative
-
- Float infinity positive
- Float negativeInfinity positive
- Float NaN positive
+ Float infinity negative
+ Float negativeInfinity negative
+ Float NaN negative
+
+ Float infinity positive
+ Float negativeInfinity positive
+ Float NaN positive
"
!
@@ -2906,13 +2927,13 @@
(1.0 uncheckedDivide: 0.0) positive
(-1.0 uncheckedDivide: 0.0) positive
- Float infinity positive
- Float negativeInfinity positive
- Float NaN positive
-
- Float infinity negative
- Float negativeInfinity negative
- Float NaN negative
+ Float infinity positive
+ Float negativeInfinity positive
+ Float NaN positive
+
+ Float infinity negative
+ Float negativeInfinity negative
+ Float NaN negative
"
!