fmin/fmax missing
authorClaus Gittinger <cg@exept.de>
Thu, 28 Nov 2019 16:19:31 +0100
changeset 25002 34d9021dd872
parent 25001 4d5ec8f74450
child 25003 18856dfc86e4
fmin/fmax missing
Float.st
--- 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
     "
 !