SmallInteger.st
changeset 62 e1b4369c61fb
parent 50 71f3b9444905
child 68 59faa75185ba
--- a/SmallInteger.st	Fri Feb 25 14:03:58 1994 +0100
+++ b/SmallInteger.st	Fri Feb 25 14:05:47 1994 +0100
@@ -22,15 +22,15 @@
 COPYRIGHT (c) 1988 by Claus Gittinger
               All Rights Reserved
 
-$Header: /cvs/stx/stx/libbasic/SmallInteger.st,v 1.9 1994-02-05 12:24:25 claus Exp $
+$Header: /cvs/stx/stx/libbasic/SmallInteger.st,v 1.10 1994-02-25 13:05:25 claus Exp $
 
 SmallIntegers are Integers in the range of +/- 2^30 (i.e. 31 bits).
 These are no real objects - they have no instances (not even storage !!)
 and cannot be subclassed.
 The reason is to save both storage and runtime by not collecting
 SmallIntegers in the system. SmallInts are marked by having the TAG_INT 
-bit set in contrast to Objects which do not. Since this knowledge is 
-hardwired into the system (an there is no class-field stored with
+bit set, in contrast to all other objects which do not. Since this knowledge 
+is hardwired into the system (an there is no class-field stored with
 SmallIntegers) there can be no subclass of SmallInteger (sorry).
 '!
 
@@ -107,14 +107,7 @@
     ^ false
 ! !
 
-!SmallInteger methodsFor:'error catching'!
-
-at:index
-    "catch indexed access - report an error
-     defined here since at: in Object ommits the SmallInteger check"
-
-    self notIndexed
-!
+!SmallInteger methodsFor:'catching messages'!
 
 basicAt:index
     "catch indexed access - report an error
@@ -123,13 +116,6 @@
     self notIndexed
 !
 
-at:index put:anObject
-    "catch indexed access - report an error
-     defined here since at:put: in Object ommits the SmallInteger check"
-
-    self notIndexed
-!
-
 basicAt:index put:anObject
     "catch indexed access - report an error
      defined here since basicAt:put: in Object ommits the SmallInteger check"
@@ -138,15 +124,14 @@
 !
 
 size
-    "return the number of indexed instvars - SmallIntegers have none
-     defined here since size in Object ommits the SmallInteger check"
+    "return the number of indexed instvars - SmallIntegers have none."
 
     ^ 0
 !
 
 basicSize
-    "return the number of indexed instvars - SmallIntegers have none
-     defined here since basicSize in Object ommits the SmallInteger check"
+    "return the number of indexed instvars - SmallIntegers have none.
+     Defined here since basicSize in Object ommits the SmallInteger check"
 
     ^ 0
 ! !
@@ -192,6 +177,7 @@
         RETURN ( true );
     }
     if (! _isNonNilObject(aNumber)) {
+        /* a smallint or nil */
         RETURN ( false );
     }
 
@@ -213,6 +199,7 @@
         RETURN ( false );
     }
     if (! _isNonNilObject(aNumber)) {
+        /* a smallint or nil */
         RETURN ( true );
     }
 
@@ -238,7 +225,7 @@
         RETURN ( ((INT)self < (INT)aNumber) ? true : false );
 #endif
     }
-    if (_isFloat(aNumber)) {
+    if (__isFloat(aNumber)) {
         RETURN ( ((double)_intVal(self) < _floatVal(aNumber)) ? true : false );
     }
 %}
@@ -260,7 +247,7 @@
         RETURN ( ((INT)self > (INT)aNumber) ? true : false );
 #endif
     }
-    if (_isFloat(aNumber)) {
+    if (__isFloat(aNumber)) {
         RETURN ( ((double)_intVal(self) > _floatVal(aNumber)) ? true : false );
     }
 %}
@@ -281,7 +268,7 @@
         RETURN ( ((INT)self >= (INT)aNumber) ? true : false );
 #endif
     }
-    if (_isFloat(aNumber)) {
+    if (__isFloat(aNumber)) {
         RETURN ( ((double)_intVal(self) >= _floatVal(aNumber)) ? true : false );
     }
 %}
@@ -302,7 +289,7 @@
         RETURN ( ((INT)self <= (INT)aNumber) ? true : false );
 #endif
     }
-    if (_isFloat(aNumber)) {
+    if (__isFloat(aNumber)) {
         RETURN ( ((double)_intVal(self) <= _floatVal(aNumber)) ? true : false );
     }
 %}
@@ -313,10 +300,8 @@
 identityHash
     "return an integer useful for hashing on identity"
 
-    self >= 0 ifTrue:[
-        ^ self + 8192
-    ].
-    ^ self negated + 8192
+    self >= 0 ifTrue:[^ self].
+    ^ self negated
 !
 
 min:aNumber
@@ -335,7 +320,7 @@
         }
         RETURN ( aNumber );
     }
-    if (_isFloat(aNumber)) {
+    if (__isFloat(aNumber)) {
         if ( (double)_intVal(self) < _floatVal(aNumber) ) {
             RETURN ( self );
         }
@@ -363,7 +348,7 @@
         }
         RETURN ( aNumber );
     }
-    if (_isFloat(aNumber)) {
+    if (__isFloat(aNumber)) {
         if ( (double)_intVal(self) > _floatVal(aNumber) ) {
             RETURN ( self );
         }
@@ -514,14 +499,11 @@
 #endif
     }
     if ((aNumber != nil) && (_qClass(aNumber) == Float)) {
-        extern char *newNextPtr, *newEndPtr;
         OBJ newFloat;
         double val;
 
         val = _floatVal(aNumber);
-        _qAlignedNew(newFloat, sizeof(struct floatstruct), SENDER);
-        _InstPtr(newFloat)->o_class = Float;
-        _FloatInstPtr(newFloat)->f_floatvalue = (double)(_intVal(self)) + val;
+        _qMKFLOAT(newFloat, (double)(_intVal(self)) + val, SENDER);
         RETURN ( newFloat );
     }
 %}
@@ -549,14 +531,11 @@
 #endif
     }
     if ((aNumber != nil) && (_qClass(aNumber) == Float)) {
-        extern char *newNextPtr, *newEndPtr;
         OBJ newFloat;
         double val;
 
         val = _floatVal(aNumber);
-        _qAlignedNew(newFloat, sizeof(struct floatstruct), SENDER);
-        _InstPtr(newFloat)->o_class = Float;
-        _FloatInstPtr(newFloat)->f_floatvalue = (double)(_intVal(self)) - val;
+        _qMKFLOAT(newFloat, (double)(_intVal(self)) - val, SENDER);
         RETURN ( newFloat );
     }
 %}
@@ -604,14 +583,11 @@
         }
 #endif
     } else if ((aNumber != nil) && (_qClass(aNumber) == Float)) {
-        extern char *newNextPtr, *newEndPtr;
         OBJ newFloat;
         double val;
 
         val = _floatVal(aNumber);
-        _qAlignedNew(newFloat, sizeof(struct floatstruct), SENDER);
-        _InstPtr(newFloat)->o_class = Float;
-        _FloatInstPtr(newFloat)->f_floatvalue = (double)(_intVal(self)) * val;
+        _qMKFLOAT(newFloat, (double)(_intVal(self)) * val, SENDER);
         RETURN ( newFloat );
     }
 %}
@@ -667,11 +643,18 @@
 */
         }
     } else {
-        if (_isFloat(aNumber)) {
+        if (__isFloat(aNumber)) {
             dval = _floatVal(aNumber);
             if (dval != 0.0) {
+                OBJ newFloat;
+
                 me = _intVal(self);
+
+                _qMKFLOAT(newFloat, (double)me / dval, SENDER);
+                RETURN ( newFloat );
+/*
                 RETURN ( _MKFLOAT((double)me / dval COMMA_CON) );
+*/
             }
         }
     }
@@ -700,7 +683,7 @@
             RETURN ( _MKSMALLINT(_intVal(self) / val) );
         }
     } else {
-        if (_isFraction(aNumber)) {
+        if (__isFraction(aNumber)) {
             OBJ t;
             INT num, den;
 
@@ -759,8 +742,11 @@
 
     INT val = _intVal(self);
 
+    if (val >= 0) {
+        RETURN (self);
+    }
     if (val != _MIN_INT) {
-        RETURN ( (val < 0) ? _MKSMALLINT(-val) : self );
+        RETURN ( _MKSMALLINT(-val) );
     }
 %}
 .
@@ -787,9 +773,10 @@
 !SmallInteger methodsFor:'modulu arithmetic'!
 
 times:aNumber
-    "return the product of the receiver and the argument as SmallInteger. 
-     If the result overflows integer range the value modulu the SmallInteger 
-     range is returned.
+    "return the product of the receiver and the argument, as SmallInteger.
+     The argument must be another SmallInteger.
+     If the result overflows the smallInteger range, the value modulu the 
+     smallInteger range is returned (i.e. the low bits of the product).
      This is of course not always correct, but some code does a modulu anyway
      and can therefore speed things up by not going through LargeIntegers."
 
@@ -804,9 +791,10 @@
 !
 
 plus:aNumber
-    "return the sum of the receiver and the argument as SmallInteger.
-     If the result overflows integer range, the value modulu the SmallInteger
-     range is returned.
+    "return the sum of the receiver and the argument, as SmallInteger.
+     The argument must be another SmallInteger.
+     If the result overflows the smallInteger range, the value modulu the 
+     smallInteger range is returned (i.e. the low bits of the sum).
      This is of course not always correct, but some code does a modulu anyway
      and can therefore speed things up by not going through LargeIntegers."
 
@@ -818,6 +806,24 @@
 %}
 .
     self primitiveFailed
+! 
+
+subtract:aNumber
+    "return the difference of the receiver and the argument, as SmallInteger.
+     The argument must be another SmallInteger.
+     If the result overflows the smallInteger range, the value modulu the 
+     smallInteger range is returned (i.e. the low bits of the sum).
+     This is of course not always correct, but some code does a modulu anyway
+     and can therefore speed things up by not going through LargeIntegers."
+
+%{  /* NOCONTEXT */
+
+    if (_isSmallInteger(aNumber)) {
+        RETURN ( _MKSMALLINT((_intVal(self) - _intVal(aNumber)) & 0x7FFFFFFF) );
+    }
+%}
+.
+    self primitiveFailed
 ! !
 
 !SmallInteger class methodsFor:'bit mask constants'!
@@ -847,25 +853,37 @@
 !
 
 allMask:anInteger
-    "True if all bits in anInteger are 1 in the receiver"
+    "return true if all 1-bits in anInteger are also 1 in the receiver"
+
+    ^ (self bitAnd:anInteger) == anInteger
 
-    ^(self bitAnd:anInteger) == anInteger
+    "2r00001111 allMask:2r00000001"
+    "2r00001111 allMask:2r00011110"
+    "2r00001111 allMask:2r00000000"
 !
 
 anyMask:anInteger
-    "True if any 1 bits in anInteger are 1 in the receiver"
+    "return true if any 1-bits in anInteger is also 1 in the receiver.
+     (somewhat incorrect, if the mask is zero)"
 
-    ^(self bitAnd:anInteger) ~~ 0
+    ^ (self bitAnd:anInteger) ~~ 0
+
+    "2r00001111 anyMask:2r00000001"
+    "2r00001111 anyMask:2r11110000"
 !
 
 noMask:anInteger
-    "True if no 1 bits in anInteger are 1 in the receiver"
+    "return true if no 1-bit in anInteger is 1 in the receiver"
 
-    ^(self bitAnd:anInteger) == 0
+    ^ (self bitAnd:anInteger) == 0
+
+    "2r00001111 noMask:2r00000001"
+    "2r00001111 noMask:2r11110000"
 !
 
 highBit
-    "return the bitIndex of the highest bit set"
+    "return the bitIndex of the highest bit set. The returned bitIndex
+     starts at 1 for the least significant bit. Returns -1 if no bit is set."
 
 %{  /* NOCONTEXT */
 
@@ -889,10 +907,17 @@
     }
     RETURN ( _MKSMALLINT(index) );
 %}
+    "2r000100 highBit"
+    "2r010100 highBit"
+    "2r000001 highBit"
+    "0 highBit"
+    "SmallInteger maxVal highBit"
 !
 
 lowBit
-    "return the bitIndex of the lowest bit set"
+    "return the bitIndex of the lowest bit set. The returned bitIndex
+     starts at 1 for the least significant bit. Returns -1 if no bit is set."
+
 %{  /* NOCONTEXT */
 
     INT mask, index, bits;
@@ -915,13 +940,17 @@
         index++;
     }
     RETURN ( _MKSMALLINT(-1) );
-    /* notreached */
 %}
+    "2r000100 lowBit"
+    "2r010010 lowBit"
+    "2r100001 lowBit"
+    "0 lowBit"
 !
 
 bitShift:shiftCount
     "return the value of the receiver shifted by shiftCount bits;
-     leftShift if shiftCount > 0; rightShift otherwise"
+     leftShift if shiftCount > 0; rightShift otherwise.
+     This method is (currently) not handling largeInteger overflow"
 
 %{  /* NOCONTEXT */
 
@@ -955,6 +984,8 @@
 %}
 .
     ^ self retry:#bitOr coercing:anInteger
+
+    "(2r000000100 bitOr:2r00000011) radixPrintStringRadix:2"
 !
 
 bitAnd:anInteger
@@ -969,6 +1000,8 @@
 %}
 .
     ^ self retry:#bitAnd coercing:anInteger
+
+    "(2r001010100 bitAnd:2r00001111) radixPrintStringRadix:2"
 !
 
 bitXor:anInteger
@@ -1052,6 +1085,9 @@
 %}
 .
     self primitiveFailed
+
+    "(16r12345678 digitAt:1) printStringRadix:16"
+    "(16r12345678 digitAt:3) printStringRadix:16"
 ! !
 
 !SmallInteger methodsFor:'misc math functions'!
@@ -1136,9 +1172,12 @@
 
     OBJ newFloat;
 
-    _qAlignedNew(newFloat, sizeof(struct floatstruct), SENDER);
+    _qMKFLOAT(newFloat, (double)_intVal(self), SENDER);
+/*
+    _qNew(newFloat, sizeof(struct floatstruct), SENDER);
     _InstPtr(newFloat)->o_class = Float;
     _FloatInstPtr(newFloat)->f_floatvalue = _intVal(self);
+*/
     RETURN ( newFloat );
 %}
 !
@@ -1150,7 +1189,7 @@
 !
 
 asCharacter
-    "Return self as an ascii character"
+    "Return a character with the receiver as ascii value"
 
     ^ Character value:self
 ! !
@@ -1170,7 +1209,9 @@
 !
 
 to:stop do:aBlock
-    "reimplemented for speed"
+    "evaluate aBlock for every integer between (and including) the receiver
+     and the argument, stop.
+     Reimplemented for speed"
 
     |home index|
 %{
@@ -1233,7 +1274,9 @@
     }
 %}
 .
-    ^super to:stop do:aBlock
+    ^ super to:stop do:aBlock
+
+    "1 to:10 do:[:i | i printNewline]"
 !
 
 to:stop by:incr do:aBlock
@@ -1340,6 +1383,8 @@
 %}
 .
     ^ super to:stop do:aBlock
+
+    "1 to:10 by:3 do:[:i | i printNewline]"
 ! !
 
 !SmallInteger class methodsFor:'binary storage'!
@@ -1391,12 +1436,17 @@
 
 !SmallInteger methodsFor:'printing & storing'!
 
+printOn:aStream
+    "append my printstring (base 10) to aStream"
+
+    aStream nextPutAll:(self printString)
+!
+
 printString
     "return my printstring (base 10)"
 
 %{  /* NOCONTEXT */
 
-    extern char *newNextPtr, *newEndPtr;
     char buffer[30];
     OBJ newString;
 #ifdef THISCONTEXT_IN_REGISTER
@@ -1415,11 +1465,10 @@
 !
 
 printStringRadix:radix
-    "return my printstring (base 10)"
+    "return my printstring (optimized for bases 16, 10 and 8)"
 
 %{  /* NOCONTEXT */
 
-    extern char *newNextPtr, *newEndPtr;
     char *format = (char *)0;
     char buffer[30];
     OBJ newString;
@@ -1453,20 +1502,30 @@
     }
 %}
 .
+    "fall back for seldom used bases"
     ^ super printStringRadix:radix
+
+    "123 printStringRadix:16"
+    "123 printStringRadix:8"
+    "123 printStringRadix:2"
+    "123 printStringRadix:3"
+    "123 printStringRadix:1"
 !
 
 printfPrintString:formatString
     "non-portable, but sometimes useful.
      return a printed representation of the receiver
-     as specified by formatString, which is defined by printf.
-     No checking for string overrun - must be shorter than 256 chars or else ..."
+     as specified by formatString, which is defined by the C-
+     function 'printf'.
+     No checking for string overrun - the resulting string 
+     must be shorter than 256 chars or else ...
+     This method is NONSTANDARD and may be removed without notice."
 
 %{  /* STACK: 400 */
 
     char buffer[256];
 
-    if (_isString(formatString)) {
+    if (__isString(formatString)) {
 #ifdef THISCONTEXT_IN_REGISTER
         OBJ sav = __thisContext;
 #endif