ShortFloat.st
branchjv
changeset 18120 e3a375d5f6a8
parent 18045 c0c600e0d3b3
parent 17667 c8fdd1168ff1
child 18192 32a7c53ef4d0
--- a/ShortFloat.st	Tue Feb 04 21:09:59 2014 +0100
+++ b/ShortFloat.st	Wed Apr 01 10:20:10 2015 +0100
@@ -11,9 +11,11 @@
 "
 "{ Package: 'stx:libbasic' }"
 
+"{ NameSpace: Smalltalk }"
+
 LimitedPrecisionReal variableByteSubclass:#ShortFloat
 	instanceVariableNames:''
-	classVariableNames:''
+	classVariableNames:'DefaultPrintFormat Epsilon'
 	poolDictionaries:''
 	category:'Magnitude-Numbers'
 !
@@ -32,6 +34,10 @@
 #define __USE_ISOC99 1
 #include <math.h>
 
+#ifndef INT32
+# define INT32 int
+#endif
+
 /*
  * on some systems errno is a macro ... check for it here
  */
@@ -68,26 +74,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
@@ -96,22 +102,22 @@
 
 # ifndef isnanf
 #  define isnanf(x)      \
-	(((unsigned int *)(&x))[0] == 0xFFC00000)
+        (((unsigned int *)(&x))[0] == 0xFFC00000)
 # endif
 
 # ifndef isPositiveInfinityf
 #  define isPositiveInfinityf(x)      \
-	(((unsigned int *)(&x))[0] == 0x7F800000)
+        (((unsigned int *)(&x))[0] == 0x7F800000)
 # endif
 
 # ifndef isNegativeInfinityf
 #  define isNegativeInfinityf(x)      \
-	(((unsigned int *)(&x))[0] == 0xFF800000)
+        (((unsigned int *)(&x))[0] == 0xFF800000)
 # endif
 
 # ifndef isinff
 #  define isinff(x)      \
-	((((unsigned int *)(&x))[0] & 0x7FFFFFFF) == 0x7F800000)
+        ((((unsigned int *)(&x))[0] & 0x7FFFFFFF) == 0x7F800000)
 # endif
 
 # ifndef isfinitef
@@ -175,7 +181,7 @@
 documentation
 "
     ShortFloats represent rational numbers with limited precision.
-    They use the C-compilers 'float' format, which is usually the IEE single float format.
+    They use the C-compilers 'float' format, which is usually the IEEE single float format.
 
     In contrast to Floats (which use the C-compilers 64bit 'double' format),
     ShortFloats give you 32 bit floats.
@@ -185,42 +191,39 @@
     to bothe visualWorks and other smalltalks, which use C-doubles for the Float class.
     Thus, STX's Float precision is not worse than that of other ST's.
 
-    This may change in one of the next versions (at least on machines, which
-    provide different float and double types in their C-compiler.
-
     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 IEE floats
-	    23 bit mantissa,
-	    8 bit exponent,
-	    6 decimal digits (approx)
+            32bit single precision IEEE floats
+            23 bit mantissa,
+            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
 "
 ! !
 
@@ -243,6 +246,10 @@
 %}
 !
 
+coerce:aNumber
+    ^ aNumber asShortFloat.
+!
+
 fastFromString:aString at:startIndex
     "return the next ShortFloat from the string starting at startIndex.
      No spaces are skipped.
@@ -310,56 +317,28 @@
     r.i = __unsignedLongIntVal( anInteger );
     RETURN( __MKSFLOAT(r.f) );
 %}
-!
-
-readFrom:aStringOrStream
-    "read a shortFloat from a string"
-
-    |num|
-
-    num := super readFrom:aStringOrStream onError:[self error:'conversion error for: ' , self name].
-    num notNil ifTrue:[
-	num := num asShortFloat
-    ].
-    ^ num
 
     "
-     ShortFloat readFrom:'0.1'
-     ShortFloat readFrom:'0'
-     ShortFloat readFrom:'.123'
-     ShortFloat readFrom:'-.123'
-     ShortFloat readFrom:'1e4'
+        ShortFloat fromIEEE32Bit:(#[64 73 15 219] asInteger)
     "
-
-    "Modified: / 7.1.1998 / 16:17:59 / cg"
 !
 
-readFrom:aStringOrStream onError:exceptionBlock
-    "read a shortFloat from a string"
-
-    |num|
-
-    num := super readFrom:aStringOrStream onError:nil.
-    num isNil ifTrue:[
-	^ exceptionBlock value
-    ].
-    ^ num asShortFloat
-
-    "
-     ShortFloat readFrom:'0.1'
-     ShortFloat readFrom:'0'
-     ShortFloat readFrom:'.123'
-    "
-
-    "Modified: / 7.1.1998 / 16:17:59 / cg"
+fromNumber:aNumber
+    ^aNumber asShortFloat
 ! !
 
 !ShortFloat class methodsFor:'accessing'!
 
 defaultPrintFormat
-    "this is fixed in ShortFloat"
+    ^ DefaultPrintFormat
+!
 
-    ^ '.6'
+defaultPrintFormat:aString
+    DefaultPrintFormat := aString.
+!
+
+epsilon
+    ^ Epsilon
 ! !
 
 !ShortFloat class methodsFor:'binary storage'!
@@ -478,6 +457,20 @@
     "Modified: / 23-08-2006 / 16:01:55 / cg"
 ! !
 
+!ShortFloat class methodsFor:'class initialization'!
+
+initialize
+    Epsilon isNil ifTrue:[
+        DefaultPrintFormat := '.7'.  "/ print 7 valid digits
+        Epsilon := self computeEpsilon.
+    ].
+
+    "
+     Epsilon := nil.
+     self initialize
+    "
+! !
+
 !ShortFloat class methodsFor:'constants'!
 
 e
@@ -486,12 +479,31 @@
     ^ Float e asShortFloat
 !
 
+emax
+    "Answer the maximum exponent for this representation."
+
+    ^127
+!
+
+emin
+    "Answer the minimum exponent for this representation."
+
+    ^-126
+!
+
 pi
     "return the constant pi as ShortFloat"
 
     ^ Float pi asShortFloat
 !
 
+powersOfTwo
+    "/ sigh: cannot have PoersOfTwo as class nstvar (yet)
+    PowersOfTwo notNil ifTrue: [^PowersOfTwo].
+    PowersOfTwo := self newPowersOfTwo.
+    ^PowersOfTwo
+!
+
 unity
     "return the neutral element for multiplication (1.0) as ShortFloat"
 
@@ -523,24 +535,6 @@
     "Modified: 23.4.1996 / 16:00:23 / cg"
 !
 
-isIEEEFormat
-    "return true, if this machine represents floats in IEEE format.
-     Currently, no support is provided for non-ieee machines
-     to convert their floats into this (which is only relevant,
-     if such a machine wants to send floats as binary to some other
-     machine).
-     Machines with non-IEEE format are VAXed and IBM370-type systems
-     (among others). Today, most systems use IEEE format floats."
-
-%{
-#ifdef __s390__
-    RETURN(false);
-#endif
-%}.
-
-    ^ true "/ this may be a lie
-!
-
 numBitsInExponent
     "answer the number of bits in the exponent
      This is an IEEE float, where 8 bits are available:
@@ -1036,6 +1030,92 @@
     "
 !
 
+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 
+     read: http://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/
+    "
+
+%{  /* NOCONTEXT */
+
+    /*
+     * notice:
+     * the following inline code handles some common cases,
+     * and exists as an optimization, to speed up those cases.
+     *
+     * Conceptionally, (and for most other argument types),
+     * mixed arithmetic is implemented by double dispatching
+     * (see the message send at the bottom)
+     */
+
+    INT32 ulpDiff;
+    union {
+        float f;
+        INT32 i;
+    } myself, otherFloat;
+    int nEpsilon;
+    float scaledEpsilon;
+
+
+    if (!__isSmallInteger(nE)) {
+        goto tryHarder;
+    }
+
+    nEpsilon =  __intVal(nE);
+    scaledEpsilon = nEpsilon *__shortFloatVal(@global(Epsilon));
+
+    if (__isSmallInteger(aNumber)) {
+        otherFloat.f = (float)(__intVal(aNumber));
+    } else if (aNumber == nil) {
+        RETURN(false)
+    } else if (__qIsFloatLike(aNumber)) {
+        otherFloat.f = (float)(__floatVal(aNumber));
+    } else if (__qIsShortFloat(aNumber)) {
+        otherFloat.f = (double)(__shortFloatVal(aNumber));
+    } else {
+        goto tryHarder;
+    }
+
+    myself.f = __shortFloatVal(self);
+
+    // Check if the numbers are really close -- needed
+    // when comparing numbers near zero (ULP method below fails for numbers near 0!).
+    if (fabs(myself.f - otherFloat.f) <= scaledEpsilon) {
+        RETURN(true);
+    }
+
+    // if the signs differ, the numbers are different
+    if ((myself.f >= 0) != (otherFloat.f >= 0)) {
+        RETURN(false);
+    }
+
+    // compute the difference of the 'units in the last place" ULP
+    // (if ulpDiff == 1, two floats are adjecant)
+    ulpDiff = myself.i - otherFloat.i;
+    if (ulpDiff < 0) ulpDiff = -ulpDiff;
+    if (ulpDiff <= nEpsilon) {
+        RETURN(true);
+    } else {
+        RETURN(false)
+    }
+
+tryHarder:;
+%}.
+    ^ aNumber isAlmostEqualToFromShortFloat:self nEpsilon:nE
+
+    "
+        67329.234 asShortFloat isAlmostEqualTo:67329.23400000001 nEpsilon:1
+        1.0 asShortFloat isAlmostEqualTo:1.0001 nEpsilon:1
+        1.0 asShortFloat isAlmostEqualTo:-1.0 nEpsilon:1
+        1.0 asShortFloat isAlmostEqualTo:1 nEpsilon:1
+    "
+!
+
 ~= aNumber
     "return true, if the arguments value are not equal"
 
@@ -1125,12 +1205,66 @@
      LimitedPrecisonReal and its subclasses use #printString instead of
      #printOn: as basic print mechanism."
 
+    ^ self printStringWithFormat:DefaultPrintFormat
+
+    "
+        1.234 asShortFloat printString.
+        1.0 asShortFloat printString.
+        1e10 asShortFloat printString.
+        1.2e3 asShortFloat printString.
+        1.2e30 asShortFloat printString.
+        (1.0 uncheckedDivide:0) asShortFloat printString.
+        (0.0 uncheckedDivide:0) asShortFloat printString.
+        self pi printString.
+
+        self pi printString.
+        DefaultPrintFormat := '.3'.
+        self pi printString.
+        DefaultPrintFormat := '.7'.
+
+        DecimalPointCharacterForPrinting := $,.
+        1.234 asShortFloat printString.
+        1.0 asShortFloat printString.
+        1e10 asShortFloat printString.
+        1.2e3 asShortFloat printString.
+        1.2e30 asShortFloat printString.
+        (1.0 uncheckedDivide:0) asShortFloat printString.
+        (0.0 uncheckedDivide:0) asShortFloat printString.
+        DecimalPointCharacterForPrinting := $.
+    "
+!
+
+printStringWithFormat:format
+    "return a printed representation of the receiver;
+     fmt must be of the form: .nn, where nn is the number of digits.
+     To print 6 valid digits, use printStringWithFormat:'.6'
+     For Floats, the default used in printString, is 15 (because its a double);
+     for ShortFloats, it is 6 (because it is a float)"
+
 %{  /* NOCONTEXT */
 
     char buffer[64];
     REGISTER char *cp;
     int len;
     OBJ s;
+    char *fmt;
+    char fmtBuffer[20];
+
+    if (__isStringLike(format)) {
+        fmt = (char *) __stringVal(format);
+    } else {
+        /*
+         * in case we get called with garbage...
+         */
+        fmt = ".7";
+    }
+
+    /*
+     * build a printf format string
+     */
+    fmtBuffer[0] = '%';
+    strncpy(fmtBuffer+1, fmt, 10);
+    strcat(fmtBuffer, "g");
 
     /*
      * actually only needed on sparc: since thisContext is
@@ -1138,60 +1272,66 @@
      * manually save it here - very stupid ...
      */
     __BEGIN_PROTECT_REGISTERS__
-    len = snprintf(buffer, sizeof(buffer), "%.6g", (float)__shortFloatVal(self));
+    len = snprintf(buffer, sizeof(buffer), fmtBuffer, (float)__shortFloatVal(self));
     __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')) {
-	    if (__isCharacter(@global(DecimalPointCharacterForPrinting))) {
-		*cp++ = __intVal(__characterVal(@global(DecimalPointCharacterForPrinting)));
-	    } else {
-		*cp++ = '.';
-	    }
-	    *cp++ = '0';
-	    *cp = '\0';
-	} else {
-	    if (cp && (*cp == '.')) {
-		if (__isCharacter(@global(DecimalPointCharacterForPrinting))) {
-		    *cp = __intVal(__characterVal(@global(DecimalPointCharacterForPrinting)));
-		}
-	    }
-	}
+        /*
+         * 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')) {
+            if (__isCharacter(@global(DecimalPointCharacterForPrinting))) {
+                *cp++ = __intVal(__characterVal(@global(DecimalPointCharacterForPrinting)));
+            } else {
+                *cp++ = '.';
+            }
+            *cp++ = '0';
+            *cp = '\0';
+        } else {
+            if (cp && (*cp == '.')) {
+                if (__isCharacter(@global(DecimalPointCharacterForPrinting))) {
+                    *cp = __intVal(__characterVal(@global(DecimalPointCharacterForPrinting)));
+                }
+            }
+        }
 
-	s = __MKSTRING(buffer);
-	if (s != nil) {
-	    RETURN (s);
-	}
+        s = __MKSTRING(buffer);
+        if (s != nil) {
+            RETURN (s);
+        }
     }
 %}.
     ^ self asFloat printString
 
     "
-	1.234 asShortFloat printString.
-	1.0 asShortFloat printString.
-	1e10 asShortFloat printString.
-	1.2e3 asShortFloat printString.
-	1.2e30 asShortFloat printString.
-	(1.0 uncheckedDivide:0) asShortFloat printString.
-	(0.0 uncheckedDivide:0) asShortFloat printString.
-	self pi printString.
+        1.234 asShortFloat printString. 
+        ShortFloat pi printString.  
+        1.0 asShortFloat printString.   
+        1e10 asShortFloat printString.
+        1.2e3 asShortFloat printString.
+        1.2e30 asShortFloat printString.
+        (1.0 uncheckedDivide:0) asShortFloat printString.
+        (0.0 uncheckedDivide:0) asShortFloat printString.
+        self pi printString.
 
-	DecimalPointCharacterForPrinting := $,.
-	1.234 asShortFloat printString.
-	1.0 asShortFloat printString.
-	1e10 asShortFloat printString.
-	1.2e3 asShortFloat printString.
-	1.2e30 asShortFloat printString.
-	(1.0 uncheckedDivide:0) asShortFloat printString.
-	(0.0 uncheckedDivide:0) asShortFloat printString.
-	DecimalPointCharacterForPrinting := $.
+        self pi printString.
+        DefaultPrintFormat := '.3'.
+        self pi printString.
+        DefaultPrintFormat := '.7'.
+
+        DecimalPointCharacterForPrinting := $,.
+        1.234 asShortFloat printString.
+        1.0 asShortFloat printString.
+        1e10 asShortFloat printString.
+        1.2e3 asShortFloat printString.
+        1.2e30 asShortFloat printString.
+        (1.0 uncheckedDivide:0) asShortFloat printString.
+        (0.0 uncheckedDivide:0) asShortFloat printString.
+        DecimalPointCharacterForPrinting := $.
     "
 !
 
@@ -1262,31 +1402,27 @@
      */
 
     __BEGIN_PROTECT_REGISTERS__
-#ifdef SYSV
-    len = snprintf(buffer, sizeof(buffer), "%.6lg", (double)__shortFloatVal(self));
-#else
-    len = snprintf(buffer, sizeof(buffer), "%.6G", (double)__shortFloatVal(self));
-#endif
+    len = snprintf(buffer, sizeof(buffer), "%.8g", (float)__shortFloatVal(self));
     __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';
-	}
+        /*
+         * 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);
-	}
+        s = __MKSTRING(buffer);
+        if (s != nil) {
+            RETURN (s);
+        }
     }
 %}.
     "
@@ -1299,26 +1435,28 @@
     ^ ObjectMemory allocationFailureSignal raise.
 
     "
-	1.0 asShortFloat storeString
-	1.234 asShortFloat storeString
-	1e10 asShortFloat storeString
-	1.2e3 asShortFloat storeString
-	1.2e30 asShortFloat storeString
-	Float pi asShortFloat storeString
-	(1.0 uncheckedDivide:0) asShortFloat storeString
-	(0.0 uncheckedDivide:0) asShortFloat storeString
+        0.1 asShortFloat storeString
+        ((Array new:10 withAll:0.1 asShortFloat) inject:0 into:[:v :sumSoFar| sumSoFar + v]) storeString
+        1.0 asShortFloat storeString
+        1.234 asShortFloat storeString
+        1e10 asShortFloat storeString
+        1.2e3 asShortFloat storeString
+        1.2e30 asShortFloat storeString
+        Float pi asShortFloat storeString
+        (1.0 uncheckedDivide:0) asShortFloat storeString
+        (0.0 uncheckedDivide:0) asShortFloat storeString
 
      notice that the storeString is NOT affected by DecimalPointCharacterForPrinting:
 
-	DecimalPointCharacterForPrinting := $,.
-	1.234 asShortFloat storeString.
-	1.0 asShortFloat storeString.
-	1e10 asShortFloat storeString.
-	1.2e3 asShortFloat storeString.
-	1.2e30 asShortFloat storeString.
-	(1.0 uncheckedDivide:0) asShortFloat storeString.
-	(0.0 uncheckedDivide:0) asShortFloat storeString.
-	DecimalPointCharacterForPrinting := $.
+        DecimalPointCharacterForPrinting := $,.
+        1.234 asShortFloat storeString.
+        1.0 asShortFloat storeString.
+        1e10 asShortFloat storeString.
+        1.2e3 asShortFloat storeString.
+        1.2e30 asShortFloat storeString.
+        (1.0 uncheckedDivide:0) asShortFloat storeString.
+        (0.0 uncheckedDivide:0) asShortFloat storeString.
+        DecimalPointCharacterForPrinting := $.
     "
 ! !
 
@@ -1407,6 +1545,35 @@
     ^ self indexNotIntegerOrOutOfBounds:index
 ! !
 
+!ShortFloat methodsFor:'queries'!
+
+nextFloat:count
+    "answer the next float count places after (or before if count is negative) myself"
+
+%{
+    union u {
+        float d;
+        INT32 i;
+    } this;
+
+    if (__isSmallInteger(count)) {
+        this.d = __shortFloatVal(self);
+        if (isfinite(this.d))
+            this.i += __intVal(count);
+
+        RETURN(__MKSFLOAT(this.d));
+    }
+%}.
+    self primitiveFailed:#badArgument
+
+  "
+     (1.0 asShortFloat nextFloat:2) storeString
+     (67329.234 asShortFloat nextFloat:1) storeString
+     ShortFloat NaN nextFloat:100000
+     ShortFloat infinity nextFloat:100000
+  "
+! !
+
 !ShortFloat methodsFor:'special access'!
 
 exponent
@@ -1525,12 +1692,15 @@
 isNegativeZero
     "many systems have two float.Pnt zeros"
 
-%{
-#if defined(__i386__) && defined(linux)
-    RETURN ((__ByteArrayInstPtr(self)->ba_element[sizeof(float)-1] == 128) ? true : false );
+%{ /* NOCONTEXT */
+#if defined(__BORLANDC__)
+    union { float f; int i; } __u;
+   __u.f = __shortFloatVal(self);
+    RETURN ( (__u.f == 0.0 && __u.i < 0) ? true : false );
+#else
+    RETURN ( (__shortFloatVal(self) == 0.0 && signbit(__shortFloatVal(self)) != 0) ? true : false );
 #endif
 %}.
-    ^ super isNegativeZero
 
     "
      0.0 asShortFloat isNegativeZero
@@ -1539,12 +1709,23 @@
 !
 
 negative
-    "return true if the receiver is less than zero"
+    "return true if the receiver is less than zero.
+     -0.0 is positive for now."
 
 %{  /* NOCONTEXT */
 
-    RETURN ( (__shortFloatVal(self) < 0.0) ? true : false );
+    RETURN ( __shortFloatVal(self) < 0.0  ? true : false );
+    // RETURN ( signbit(__shortFloatVal(self)) != 0  ? true : false );
 %}.
+
+    "
+        0.0 asShortFloat negative
+        -0.0 asShortFloat negative
+        1.0 asShortFloat negative
+        -1.0 asShortFloat negative
+        (1.0 uncheckedDivide: 0.0) asShortFloat negative
+        (-1.0 uncheckedDivide: 0.0) asShortFloat negative
+    "
 !
 
 numberOfBits
@@ -1565,12 +1746,23 @@
 !
 
 positive
-    "return true if the receiver is greater or equal to zero"
+    "return true if the receiver is greater or equal to zero
+     0.0 and -0.0 are positive for now."
 
 %{  /* NOCONTEXT */
 
-    RETURN ( (__shortFloatVal(self) >= 0.0) ? true : false );
-%}
+    RETURN ( __shortFloatVal(self) >= 0.0 ? true : false );
+//    RETURN ( (signbit(__shortFloatVal(self)) == 0 ? true : false ) );
+%}.
+
+    "
+        0.0 asShortFloat positive
+        -0.0 asShortFloat positive
+        1.0 asShortFloat positive
+        -1.0 asShortFloat positive
+        (1.0 uncheckedDivide: 0.0) asShortFloat positive
+        (-1.0 uncheckedDivide: 0.0) asShortFloat positive
+    "
 !
 
 strictlyPositive
@@ -1906,10 +2098,12 @@
 !ShortFloat class methodsFor:'documentation'!
 
 version
-    ^ '$Header: /cvs/stx/stx/libbasic/ShortFloat.st,v 1.128 2013-03-31 20:47:22 cg Exp $'
+    ^ '$Header: /cvs/stx/stx/libbasic/ShortFloat.st,v 1.140 2015-03-25 19:18:18 cg Exp $'
 !
 
 version_CVS
-    ^ '$Header: /cvs/stx/stx/libbasic/ShortFloat.st,v 1.128 2013-03-31 20:47:22 cg Exp $'
+    ^ '$Header: /cvs/stx/stx/libbasic/ShortFloat.st,v 1.140 2015-03-25 19:18:18 cg Exp $'
 ! !
 
+
+ShortFloat initialize!