added cbrt
authorClaus Gittinger <cg@exept.de>
Mon, 08 Dec 2014 18:52:53 +0100
changeset 17199 63d9a071e8ff
parent 17198 7518cd20d9d3
child 17200 3f919ff62213
added cbrt
Float.st
--- a/Float.st	Mon Dec 08 18:30:24 2014 +0100
+++ b/Float.st	Mon Dec 08 18:52:53 2014 +0100
@@ -104,6 +104,9 @@
 # ifndef sqrt
   double sqrt();
 # endif
+# ifndef cbrt
+  double cbrt();
+# endif
 # ifndef tan
   double tan();
 # endif
@@ -117,26 +120,26 @@
  */
 # ifndef isnan
 #  define isnan(x)      \
-        ((((unsigned int *)(&x))[0] == 0x00000000) && \
-         (((unsigned int *)(&x))[1] == 0xFFF80000))
+	((((unsigned int *)(&x))[0] == 0x00000000) && \
+	 (((unsigned int *)(&x))[1] == 0xFFF80000))
 # endif
 
 # ifndef isPositiveInfinity
 #  define isPositiveInfinity(x) \
-        ((((unsigned int *)(&x))[0] == 0x00000000) && \
-         (((unsigned int *)(&x))[1] == 0x7FF00000))
+	((((unsigned int *)(&x))[0] == 0x00000000) && \
+	 (((unsigned int *)(&x))[1] == 0x7FF00000))
 # endif
 
 # ifndef isNegativeInfinity
 #  define isNegativeInfinity(x) \
-        ((((unsigned int *)(&x))[0] == 0x00000000) && \
-         (((unsigned int *)(&x))[1] == 0xFFF00000))
+	((((unsigned int *)(&x))[0] == 0x00000000) && \
+	 (((unsigned int *)(&x))[1] == 0xFFF00000))
 # endif
 
 # ifndef isinf
 #  define isinf(x) \
-        ((((unsigned int *)(&x))[0] == 0x00000000) && \
-         ((((unsigned int *)(&x))[1] & 0x7FF00000) == 0x7FF00000))
+	((((unsigned int *)(&x))[0] == 0x00000000) && \
+	 ((((unsigned int *)(&x))[1] & 0x7FF00000) == 0x7FF00000))
 # endif
 
 # ifndef isfinite
@@ -200,12 +203,12 @@
     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.
@@ -220,29 +223,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 IEE floats
-            53 bit mantissa,
-            11 bit exponent,
-            15 decimal digits (approx)
+	    64bit double precision IEE floats
+	    53 bit mantissa,
+	    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
 "
 !
 
@@ -521,17 +524,17 @@
 
 initialize
     Pi isNil ifTrue:[
-        DefaultPrintFormat := '.15'.  "/ print 15 valid digits
-        Pi := 3.14159265358979323846264338327950288419716939937510582097494459.
-        Halfpi := Pi / 2.0.
-        HalfpiNegative := Halfpi negated.
-        Twopi := Pi * 2.0.
-        E := 2.7182818284590452353602874713526625.
-        Sqrt2 := 1.41421356237309504880168872420969808.
-        RadiansPerDegree := Pi / 180.0.
-        Ln2 := 0.69314718055994530941723212145817657.
-        Ln10 := 10.0 ln.
-        Epsilon := self computeEpsilon.
+	DefaultPrintFormat := '.15'.  "/ print 15 valid digits
+	Pi := 3.14159265358979323846264338327950288419716939937510582097494459.
+	Halfpi := Pi / 2.0.
+	HalfpiNegative := Halfpi negated.
+	Twopi := Pi * 2.0.
+	E := 2.7182818284590452353602874713526625.
+	Sqrt2 := 1.41421356237309504880168872420969808.
+	RadiansPerDegree := Pi / 180.0.
+	Ln2 := 0.69314718055994530941723212145817657.
+	Ln10 := 10.0 ln.
+	Epsilon := self computeEpsilon.
     ].
 
     "
@@ -1389,14 +1392,14 @@
     "
 !
 
-isAlmostEqualTo:aNumber nEpsilon:nE 
+isAlmostEqualTo:aNumber nEpsilon:nE
     "return true, if the argument, aNumber represents almost the same numeric value
      as the receiver, false otherwise.
 
      nE is the number of minimal float distances, that the numbers may differ and
      still be considered equal.
 
-     For background information why floats need this 
+     For background information why floats need this
      read: http://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/
     "
 
@@ -1414,30 +1417,30 @@
 
     INT64 ulpDiff;
     union {
-        double d;
-        INT64 i;
+	double d;
+	INT64 i;
     } myself, otherFloat;
     int nEpsilon;
     double scaledEpsilon;
 
 
     if (!__isSmallInteger(nE)) {
-        goto tryHarder;
+	goto tryHarder;
     }
 
     nEpsilon =  __intVal(nE);
     scaledEpsilon = nEpsilon *__floatVal(@global(Epsilon));
 
     if (__isSmallInteger(aNumber)) {
-        otherFloat.d = (double)(__intVal(aNumber));
+	otherFloat.d = (double)(__intVal(aNumber));
     } else if (aNumber == nil) {
-        RETURN(false)
+	RETURN(false)
     } else if (__qIsFloatLike(aNumber)) {
-        otherFloat.d = (double)(__floatVal(aNumber));
+	otherFloat.d = (double)(__floatVal(aNumber));
     } else if (__qIsShortFloat(aNumber)) {
-        otherFloat.d = (double)(__shortFloatVal(aNumber));
+	otherFloat.d = (double)(__shortFloatVal(aNumber));
     } else {
-        goto tryHarder;
+	goto tryHarder;
     }
 
     myself.d = __floatVal(self);
@@ -1445,12 +1448,12 @@
     // Check if the numbers are really close -- needed
     // when comparing numbers near zero (ULP method below fails for numbers near 0!).
     if (fabs(myself.d - otherFloat.d) <= scaledEpsilon) {
-        RETURN(true);
+	RETURN(true);
     }
 
     // if the signs differ, the numbers are different
     if ((myself.d >= 0) != (otherFloat.d >= 0)) {
-        RETURN(false);
+	RETURN(false);
     }
 
     // compute the difference of the 'units in the last place" ULP
@@ -1458,9 +1461,9 @@
     ulpDiff = myself.i - otherFloat.i;
     if (ulpDiff < 0) ulpDiff = -ulpDiff;
     if (ulpDiff <= nEpsilon) {
-        RETURN(true);
+	RETURN(true);
     } else {
-        RETURN(false)
+	RETURN(false)
     }
 
 tryHarder:;
@@ -1468,13 +1471,13 @@
     ^ aNumber isAlmostEqualToFromFloat:self nEpsilon:nE
 
     "
-        67329.234 isAlmostEqualTo:67329.23400000001 nEpsilon:1
-        1.0 isAlmostEqualTo:1.0001 nEpsilon:1
-        1.0 isAlmostEqualTo:-1.0 nEpsilon:1
-        1 isAlmostEqualTo:1.000000000000001 nEpsilon:1
-        1 isAlmostEqualTo:1.000000000000001 nEpsilon:10
-        1.0 isAlmostEqualTo:1 nEpsilon:1
-        1.0 isAlmostEqualTo:1 asFraction nEpsilon:1
+	67329.234 isAlmostEqualTo:67329.23400000001 nEpsilon:1
+	1.0 isAlmostEqualTo:1.0001 nEpsilon:1
+	1.0 isAlmostEqualTo:-1.0 nEpsilon:1
+	1 isAlmostEqualTo:1.000000000000001 nEpsilon:1
+	1 isAlmostEqualTo:1.000000000000001 nEpsilon:10
+	1.0 isAlmostEqualTo:1 nEpsilon:1
+	1.0 isAlmostEqualTo:1 asFraction nEpsilon:1
     "
 !
 
@@ -1652,6 +1655,44 @@
     "Modified: / 16.11.2001 / 14:16:51 / cg"
 !
 
+cbrt
+    "return the cubic root of myself."
+
+%{  /* NOCONTEXT */
+
+    double val, rslt;
+    OBJ newFloat;
+
+    val = __floatVal(self);
+
+#ifdef WIN32 /* dont know (yet) how to suppress the warnBox opened by win32 */
+    if (val >= 0.0)
+#endif
+    {
+	__threadErrno = 0;
+	rslt = cbrt(val);
+	if (! isnan(rslt))  /* Currently all our systems support isnan() */
+	{
+	    if (__threadErrno == 0) {
+		__qMKFLOAT(newFloat, rslt);
+		RETURN ( newFloat );
+	    }
+	}
+    }
+%}.
+    ^ self class
+	raise:#imaginaryResultSignal
+	receiver:self
+	selector:#cbrt
+	arguments:#()
+	errorString:'bad receiver in cbrt'
+
+    "
+     8 cbrt
+     -8 cbrt
+    "
+!
+
 sqrt
     "return the square root of myself.
      Raises an exception, if the receiver is less than zero."
@@ -1872,23 +1913,23 @@
     __END_PROTECT_REGISTERS__
 
     if (len >= 0 && len < sizeof(buffer)-3) {
-        /*
-         * kludge to make integral float f prints as "f.0" (not as "f" as printf does)
-         * (i.e. look if string contains '.' or 'e' and append '.0' if not)
-         */
-        for (cp = buffer; *cp; cp++) {
-            if ((*cp == '.') || (*cp == ',') || (*cp == 'E') || (*cp == 'e')) break;
-        }
-        if (!*cp && (cp[-1] >= '0') && (cp[-1] <= '9')) {
-            *cp++ = '.';
-            *cp++ = '0';
-            *cp = '\0';
-        }
-
-        s = __MKSTRING(buffer);
-        if (s != nil) {
-            RETURN (s);
-        }
+	/*
+	 * kludge to make integral float f prints as "f.0" (not as "f" as printf does)
+	 * (i.e. look if string contains '.' or 'e' and append '.0' if not)
+	 */
+	for (cp = buffer; *cp; cp++) {
+	    if ((*cp == '.') || (*cp == ',') || (*cp == 'E') || (*cp == 'e')) break;
+	}
+	if (!*cp && (cp[-1] >= '0') && (cp[-1] <= '9')) {
+	    *cp++ = '.';
+	    *cp++ = '0';
+	    *cp = '\0';
+	}
+
+	s = __MKSTRING(buffer);
+	if (s != nil) {
+	    RETURN (s);
+	}
     }
 %}.
     "
@@ -1901,28 +1942,28 @@
     ^ ObjectMemory allocationFailureSignal raise.
 
     "
-        1.0 storeString
-        0.1 storeString
-        ((Array new:10 withAll:0.1) inject:0 into:[:v :sumSoFar| sumSoFar + v]) storeString
-        1.234 storeString
-        1e10 storeString
-        1.2e3 storeString
-        1.2e30 storeString
-        Float pi storeString
-        (1.0 uncheckedDivide:0) storeString
-        (0.0 uncheckedDivide:0) storeString
+	1.0 storeString
+	0.1 storeString
+	((Array new:10 withAll:0.1) inject:0 into:[:v :sumSoFar| sumSoFar + v]) storeString
+	1.234 storeString
+	1e10 storeString
+	1.2e3 storeString
+	1.2e30 storeString
+	Float pi storeString
+	(1.0 uncheckedDivide:0) storeString
+	(0.0 uncheckedDivide:0) storeString
 
      notice that the storeString is NOT affected by DecimalPointCharacterForPrinting:
 
-        DecimalPointCharacterForPrinting := $,.
-        1.234 storeString.
-        1.0 storeString.
-        1e10 storeString.
-        1.2e3 storeString.
-        1.2e30 storeString.
-        (1.0 uncheckedDivide:0) storeString.
-        (0.0 uncheckedDivide:0) storeString.
-        DecimalPointCharacterForPrinting := $.
+	DecimalPointCharacterForPrinting := $,.
+	1.234 storeString.
+	1.0 storeString.
+	1e10 storeString.
+	1.2e3 storeString.
+	1.2e30 storeString.
+	(1.0 uncheckedDivide:0) storeString.
+	(0.0 uncheckedDivide:0) storeString.
+	DecimalPointCharacterForPrinting := $.
     "
 ! !
 
@@ -2016,12 +2057,12 @@
     "return the size in bytes of the float.
 
      Notice:
-        the need to redefine this method here is due to the
-        inability of many machines to store floats in non-double aligned memory.
-        Therefore, on some machines, the first 4 bytes of a float are left unused,
-        and the actual float is stored at index 5 .. 12.
-        To hide this at one place, this method knows about that, and returns
-        values as if this filler wasn't present."
+	the need to redefine this method here is due to the
+	inability of many machines to store floats in non-double aligned memory.
+	Therefore, on some machines, the first 4 bytes of a float are left unused,
+	and the actual float is stored at index 5 .. 12.
+	To hide this at one place, this method knows about that, and returns
+	values as if this filler wasn't present."
 
 %{  /* NOCONTEXT */
 
@@ -2036,16 +2077,16 @@
 
 %{
     union {
-        double d;
-        INT64 i;
+	double d;
+	INT64 i;
     } this;
 
     if (__isSmallInteger(count)) {
-        this.d = __floatVal(self);
-        if (isfinite(this.d))
-            this.i += __intVal(count);
-
-        RETURN(__MKFLOAT(this.d));
+	this.d = __floatVal(self);
+	if (isfinite(this.d))
+	    this.i += __intVal(count);
+
+	RETURN(__MKFLOAT(this.d));
     }
 %}.
     self primitiveFailed:#badArgument
@@ -3020,11 +3061,11 @@
 !Float class methodsFor:'documentation'!
 
 version
-    ^ '$Header: /cvs/stx/stx/libbasic/Float.st,v 1.202 2014-06-30 19:40:12 stefan Exp $'
+    ^ '$Header: /cvs/stx/stx/libbasic/Float.st,v 1.203 2014-12-08 17:52:53 cg Exp $'
 !
 
 version_CVS
-    ^ '$Header: /cvs/stx/stx/libbasic/Float.st,v 1.202 2014-06-30 19:40:12 stefan Exp $'
+    ^ '$Header: /cvs/stx/stx/libbasic/Float.st,v 1.203 2014-12-08 17:52:53 cg Exp $'
 ! !