SmallInt.st
changeset 2 6526dde5f3ac
parent 1 a27a279701f8
child 3 24d81bf47225
--- a/SmallInt.st	Fri Jul 16 11:39:45 1993 +0200
+++ b/SmallInt.st	Mon Oct 04 11:32:33 1993 +0100
@@ -59,6 +59,8 @@
 %{  /* NOCONTEXT */
     RETURN ( _MKSMALLINT(N_INT_BITS) );
 %}
+
+    "SmallInteger maxBits"
 !
 
 maxBytes
@@ -67,6 +69,8 @@
 %{  /* NOCONTEXT */
     RETURN ( _MKSMALLINT(N_INT_BITS / 8 + 1) );
 %}
+
+    "SmallInteger maxBytes"
 !
 
 minVal
@@ -75,6 +79,8 @@
 %{  /* NOCONTEXT */
     RETURN ( _MKSMALLINT(_MIN_INT) );
 %}
+
+    "SmallInteger minVal"
 !
 
 maxVal
@@ -83,6 +89,8 @@
 %{  /* NOCONTEXT */
     RETURN ( _MKSMALLINT(_MAX_INT) );
 %}
+
+    "SmallInteger maxVal"
 ! !
 
 !SmallInteger methodsFor:'error catching'!
@@ -133,14 +141,14 @@
 
 shallowCopy
     "return a shallow copy of myself
-     - reimplemented here since numbers are unique"
+     - reimplemented here since smallintegers are unique"
 
     ^ self
 !
 
 deepCopy
     "return a deep copy of myself
-     - reimplemented here since numbers are unique"
+     - reimplemented here since smallintegers are unique"
 
     ^ self
 ! !
@@ -412,9 +420,9 @@
 %{  /* NOCONTEXT */
 
     if (_isSmallInteger(min) && _isSmallInteger(max)) {
-	REGISTER INT selfVal;
+        REGISTER INT selfVal;
 
-	selfVal = _intVal(self);
+        selfVal = _intVal(self);
         if (selfVal < _intVal(min)) {
              RETURN ( false );
         }
@@ -465,24 +473,24 @@
 
     if (_isSmallInteger(aNumber)) {
 #ifdef _ADD_IO_IO
-	RETURN ( _ADD_IO_IO(self, aNumber) );
+        RETURN ( _ADD_IO_IO(self, aNumber) );
 #else
         REGISTER INT sum;
-	extern OBJ _makeLarge();
+        extern OBJ _makeLarge();
 
         sum =  _intVal(self) + _intVal(aNumber);
         if ((sum >= _MIN_INT) && (sum <= _MAX_INT)) {
             RETURN ( _MKSMALLINT(sum) );
         }
-	RETURN ( _makeLarge(sum) );
+        RETURN ( _makeLarge(sum) );
 #endif
     }
     if ((aNumber != nil) && (_qClass(aNumber) == Float)) {
         extern char *newNextPtr, *newEndPtr;
         OBJ newFloat;
-	double val;
+        double val;
 
-	val = _floatVal(aNumber);
+        val = _floatVal(aNumber);
         _qAlignedNew(newFloat, sizeof(struct floatstruct), SENDER);
         _InstPtr(newFloat)->o_class = Float;
         _FloatInstPtr(newFloat)->f_floatvalue = (double)(_intVal(self)) + val;
@@ -500,24 +508,24 @@
 
     if (_isSmallInteger(aNumber)) {
 #ifdef _SUB_IO_IO
-	RETURN ( _SUB_IO_IO(self, aNumber) );
+        RETURN ( _SUB_IO_IO(self, aNumber) );
 #else
         REGISTER INT diff;
-	extern OBJ _makeLarge();
+        extern OBJ _makeLarge();
 
         diff =  _intVal(self) - _intVal(aNumber);
         if ((diff >= _MIN_INT) && (diff <= _MAX_INT)) {
             RETURN ( _MKSMALLINT(diff) );
         }
-	RETURN ( _makeLarge(diff) );
+        RETURN ( _makeLarge(diff) );
 #endif
     }
     if ((aNumber != nil) && (_qClass(aNumber) == Float)) {
         extern char *newNextPtr, *newEndPtr;
         OBJ newFloat;
-	double val;
+        double val;
 
-	val = _floatVal(aNumber);
+        val = _floatVal(aNumber);
         _qAlignedNew(newFloat, sizeof(struct floatstruct), SENDER);
         _InstPtr(newFloat)->o_class = Float;
         _FloatInstPtr(newFloat)->f_floatvalue = (double)(_intVal(self)) - val;
@@ -562,9 +570,9 @@
     } else if ((aNumber != nil) && (_qClass(aNumber) == Float)) {
         extern char *newNextPtr, *newEndPtr;
         OBJ newFloat;
-	double val;
+        double val;
 
-	val = _floatVal(aNumber);
+        val = _floatVal(aNumber);
         _qAlignedNew(newFloat, sizeof(struct floatstruct), SENDER);
         _InstPtr(newFloat)->o_class = Float;
         _FloatInstPtr(newFloat)->f_floatvalue = (double)(_intVal(self)) * val;
@@ -634,7 +642,7 @@
                 me = _intVal(self);
                 RETURN ( _MKFLOAT((double)me / dval COMMA_CON) );
             }
-        }
+	}
     }
 %}
 .
@@ -648,39 +656,54 @@
     ^ aNumber quotientFromInteger:self
 !
 
-// anInteger
+// aNumber
     "return the integer part of the quotient of the receivers value
      and the arguments value"
 
 %{  /* NOCONTEXT */
     INT val;
 
-    if (_isSmallInteger(anInteger)) {
-        val = _intVal(anInteger);
+    if (_isSmallInteger(aNumber)) {
+        val = _intVal(aNumber);
         if (val != 0) {
             RETURN ( _MKSMALLINT(_intVal(self) / val) );
         }
+    } else {
+	if (_isFraction(aNumber)) {
+	    OBJ t;
+	    INT num, den;
+
+	    t = _FractionInstPtr(aNumber)->f_numerator;
+	    if (_isSmallInteger(t)) {
+		num = _intVal(t);
+	        t = _FractionInstPtr(aNumber)->f_denominator;
+	        if (_isSmallInteger(t)) {
+		    den = _intVal(t);
+		    RETURN ( _MKSMALLINT(_intVal(self) * den / num ));
+	        }
+	    }
+	}
     }
 %}
 .
-    (anInteger = 0) ifTrue:[
+    (aNumber = 0) ifTrue:[
         DivisionByZeroSignal raise.
         ^ self
     ].
-    ^ self retry:#// coercing:anInteger
+    ^ self retry:#// coercing:aNumber
 !
 
-\\ anInteger
+\\ aNumber
     "return the integer rest of the receivers value
      divided by the arguments value"
 
 %{  /* NOCONTEXT */
     INT mySelf, val;
 
-    if (_isSmallInteger(anInteger)) {
+    if (_isSmallInteger(aNumber)) {
         mySelf = _intVal(self);
         if (mySelf < 0) mySelf = -mySelf;
-        val = _intVal(anInteger);
+        val = _intVal(aNumber);
         if (val != 0) {
             if (val < 0) {
                 RETURN ( _MKSMALLINT(-(mySelf % -val)) );
@@ -690,11 +713,11 @@
     }
 %}
 .
-    (anInteger = 0) ifTrue:[
+    (aNumber = 0) ifTrue:[
         DivisionByZeroSignal raise.
         ^ self
     ].
-    ^ self retry:#\\ coercing:anInteger
+    ^ self retry:#\\ coercing:aNumber
 !
 
 abs
@@ -1014,25 +1037,25 @@
         INT orgArg, ttt, selfInt, temp;
 
         ttt = orgArg = _intVal(anInteger);
-	if (ttt) {
+        if (ttt) {
             selfInt = _intVal(self);
             while (ttt != 0) {
                 temp = selfInt % ttt;
                 selfInt = ttt;
                 ttt = temp;
             }
-	    /*
-	     * since its not defined in what the sign of
-	     * a modulu result is when the arg is negative,
-	     * change it explicitely here ...
-	     */
-	    if (orgArg < 0) {
-		/* result should be negative */
+            /*
+             * since its not defined in what the sign of
+             * a modulu result is when the arg is negative,
+             * change it explicitely here ...
+             */
+            if (orgArg < 0) {
+                /* result should be negative */
                 if (selfInt > 0) selfInt = -selfInt;
-	    } else {
-		/* result should be positive */
-		if (selfInt < 0) selfInt = -selfInt;
-	    }
+            } else {
+                /* result should be positive */
+                if (selfInt < 0) selfInt = -selfInt;
+            }
             RETURN ( _MKSMALLINT(selfInt) );
         }
     }
@@ -1121,8 +1144,8 @@
     REGISTER OBJFUNC code;
     extern OBJ Block, _value_;
     static struct inlineCache blockVal = _ILC1;
+    REGISTER OBJ rHome;
 #ifdef UPDATE_WHOLE_STACK
-    REGISTER OBJ rHome;
 #   undef home
 #   define home rHome
 #endif
@@ -1130,37 +1153,58 @@
     if (_isSmallInteger(stop)) {
         tmp = _intVal(self);
         final = _intVal(stop);
-        if (_isBlock(aBlock)
+        if (__isBlock(aBlock)
          && ((code = _BlockInstPtr(aBlock)->b_code) != (OBJFUNC)nil)
          && (_BlockInstPtr(aBlock)->b_nargs == _MKSMALLINT(1))) {
             /*
-	     * arg is a compiled block - 
+             * arg is a compiled block - 
              * directly call it without going through "Block-value"
              */
             home = _BlockInstPtr(aBlock)->b_home;
-            while (tmp <= final) {
-                if (InterruptPending != nil) interrupt(CONARG);
+#ifndef UPDATE_WHOLE_STACK
+            rHome = home;
+            if ((rHome == nil) || (_qSpace(rHome) >= STACKSPACE)) {
+                /*
+                 * home will not move - keep in in a register
+                 */
+                while (tmp <= final) {
+                    if (InterruptPending != nil) interrupt(CONARG);
+# ifdef PASS_ARG_REF
+                    index = _MKSMALLINT(tmp);
+                    (*code)(rHome, CON_COMMA &index);
+# else
+                    (*code)(rHome, CON_COMMA _MKSMALLINT(tmp));
+# endif
+                    tmp++;
+                }
+            } else 
+#endif
+            {
+                while (tmp <= final) {
+                    if (InterruptPending != nil) interrupt(CONARG);
 
-                index = _MKSMALLINT(tmp);
 #ifdef PASS_ARG_REF
-                (*code)(home, CON_COMMA &index);
+                    index = _MKSMALLINT(tmp);
+                    (*code)(home, CON_COMMA &index);
 #else
-                (*code)(home, CON_COMMA index);
+                    (*code)(home, CON_COMMA _MKSMALLINT(tmp));
 #endif
-                tmp++;
+                    tmp++;
+                }
             }
         } else {
             /*
-	     * arg is something else - call it with Block-value"
+             * arg is something else - call it with Block-value"
              */
             while (tmp <= final) {
                 if (InterruptPending != nil) interrupt(CONARG);
 
+#ifdef PASS_ARG_REF
                 index = _MKSMALLINT(tmp);
-#ifdef PASS_ARG_REF
                 (*blockVal.ilc_func)(aBlock, _value_, CON_COMMA nil, &blockVal, &index);
 #else
-                (*blockVal.ilc_func)(aBlock, _value_, CON_COMMA nil, &blockVal, index);
+                (*blockVal.ilc_func)(aBlock, _value_, CON_COMMA nil, &blockVal, 
+                                                      _MKSMALLINT(tmp));
 #endif
                 tmp++;
             }
@@ -1182,8 +1226,8 @@
     REGISTER OBJFUNC code;
     extern OBJ Block, _value_;
     static struct inlineCache blockVal = _ILC1;
+    REGISTER OBJ rHome;
 #ifdef UPDATE_WHOLE_STACK
-    REGISTER OBJ rHome;
 #   undef home
 #   define home rHome
 #endif
@@ -1193,74 +1237,144 @@
         tmp = _intVal(self);
         final = _intVal(stop);
         step = _intVal(incr);
-        if (_isBlock(aBlock)
+        if (__isBlock(aBlock)
          && ((code = _BlockInstPtr(aBlock)->b_code) != (OBJFUNC)nil)
          && (_BlockInstPtr(aBlock)->b_nargs == _MKSMALLINT(1))) {
             /*
-	     * arg is a compiled block - 
+             * arg is a compiled block - 
              * directly call it without going through "Block-value"
              */
             home = _BlockInstPtr(aBlock)->b_home;
-	    if (step < 0) {
+            if (step < 0) {
+#ifndef UPDATE_WHOLE_STACK
+                rHome = home;
+                if ((rHome == nil) || (_qSpace(rHome) >= STACKSPACE)) {
+                    while (tmp >= final) {
+                        if (InterruptPending != nil) interrupt(CONARG);
+
+# ifdef PASS_ARG_REF
+                        index = _MKSMALLINT(tmp);
+                        (*code)(rHome, CON_COMMA &index);
+# else
+                        (*code)(rHome, CON_COMMA _MKSMALLINT(tmp));
+# endif
+                        tmp += step;
+                    }
+                } else 
+#endif
+                {
+                    while (tmp >= final) {
+                        if (InterruptPending != nil) interrupt(CONARG);
+
+#ifdef PASS_ARG_REF
+                        index = _MKSMALLINT(tmp);
+                        (*code)(home, CON_COMMA &index);
+#else
+                        (*code)(home, CON_COMMA _MKSMALLINT(tmp));
+#endif
+                        tmp += step;
+                    }
+                }
+            } else {
+#ifndef UPDATE_WHOLE_STACK
+                rHome = home;
+                if ((rHome == nil) || (_qSpace(rHome) >= STACKSPACE)) {
+                    while (tmp <= final) {
+                        if (InterruptPending != nil) interrupt(CONARG);
+
+# ifdef PASS_ARG_REF
+                        index = _MKSMALLINT(tmp);
+                        (*code)(rHome, CON_COMMA &index);
+# else
+                        (*code)(rHome, CON_COMMA _MKSMALLINT(tmp));
+# endif
+                        tmp += step;
+                    }
+                } else
+#endif
+                {
+                    while (tmp <= final) {
+                        if (InterruptPending != nil) interrupt(CONARG);
+
+#ifdef PASS_ARG_REF
+                        index = _MKSMALLINT(tmp);
+                        (*code)(home, CON_COMMA &index);
+#else
+                        (*code)(home, CON_COMMA _MKSMALLINT(tmp));
+#endif
+                        tmp += step;
+                    }
+                }
+            }
+        } else {
+            /*
+             * arg is something else - call it with Block-value"
+             */
+            if (step < 0) {
                 while (tmp >= final) {
                     if (InterruptPending != nil) interrupt(CONARG);
 
+#ifdef PASS_ARG_REF
                     index = _MKSMALLINT(tmp);
-#ifdef PASS_ARG_REF
-                    (*code)(home, CON_COMMA &index);
+                    (*blockVal.ilc_func)(aBlock, _value_, CON_COMMA nil, &blockVal, &index);
 #else
-                    (*code)(home, CON_COMMA index);
+                    (*blockVal.ilc_func)(aBlock, _value_, CON_COMMA nil, &blockVal,
+                                                          _MKSMALLINT(tmp));
 #endif
                     tmp += step;
                 }
-	    } else {
+            } else {
                 while (tmp <= final) {
                     if (InterruptPending != nil) interrupt(CONARG);
 
+#ifdef PASS_ARG_REF
                     index = _MKSMALLINT(tmp);
-#ifdef PASS_ARG_REF
-                    (*code)(home, CON_COMMA &index);
+                    (*blockVal.ilc_func)(aBlock, _value_, CON_COMMA nil, &blockVal, &index);
 #else
-                    (*code)(home, CON_COMMA index);
+                    (*blockVal.ilc_func)(aBlock, _value_, CON_COMMA nil, &blockVal,
+                                                          _MKSMALLINT(tmp));
 #endif
                     tmp += step;
                 }
             }
-        } else {
-            /*
-	     * arg is something else - call it with Block-value"
-             */
-	    if (step < 0) {
-                while (tmp >= final) {
-                    if (InterruptPending != nil) interrupt(CONARG);
-
-                    index = _MKSMALLINT(tmp);
-#ifdef PASS_ARG_REF
-                    (*blockVal.ilc_func)(aBlock, _value_, CON_COMMA nil, &blockVal, &index);
-#else
-                    (*blockVal.ilc_func)(aBlock, _value_, CON_COMMA nil, &blockVal, index);
-#endif
-                    tmp += step;
-                }
-	    } else {
-                while (tmp <= final) {
-                    if (InterruptPending != nil) interrupt(CONARG);
-
-                    index = _MKSMALLINT(tmp);
-#ifdef PASS_ARG_REF
-                    (*blockVal.ilc_func)(aBlock, _value_, CON_COMMA nil, &blockVal, &index);
-#else
-                    (*blockVal.ilc_func)(aBlock, _value_, CON_COMMA nil, &blockVal, index);
-#endif
-                    tmp += step;
-                }
-	    }
         }
         RETURN ( self );
     }
 %}
 .
-    ^super to:stop do:aBlock
+    ^ super to:stop do:aBlock
+! !
+
+!SmallInteger class methodsFor:'binary storage'!
+
+binaryDefinitionFrom: stream manager: manager
+    "read the binary representation as stored in storeBinaryOn:"
+
+    | value |
+
+    value := stream next bitAnd: 16r7F.
+    value > 16r3F ifTrue: [
+        value := value - 16r80
+    ].
+    value := (value bitShift: 8) bitOr: stream next.
+    value := (value bitShift: 8) bitOr: stream next.
+    value := (value bitShift: 8) bitOr: stream next.
+    ^ value
+! !
+
+!SmallInteger methodsFor:'binary storage'!
+
+hasSpecialBinaryRepresentation
+    ^ true
+!
+
+storeBinaryOn: stream manager: manager
+    "SmallIntegers are stored as their value with the 32nd bit set as a tag."
+
+    stream nextPut: (((self bitShift: -24) bitAnd: 16rFF) bitOr: 16r80).
+    stream nextPut: ((self bitShift: -16) bitAnd: 16rFF).
+    stream nextPut: ((self bitShift: -8) bitAnd: 16rFF).
+    stream nextPut: (self bitAnd: 16rFF)
 ! !
 
 !SmallInteger methodsFor:'printing & storing'!
@@ -1300,16 +1414,16 @@
 
     if (_isSmallInteger(radix)) {
         switch (_intVal(radix)) {
-	    case 10:
-		format = "%d";
-		break;
-	    case 16:
-		format = "%x";
-		break;
-	    case 8:
-		format = "%o";
-		break;
-	}
+            case 10:
+                format = "%d";
+                break;
+            case 16:
+                format = "%x";
+                break;
+            case 8:
+                format = "%o";
+                break;
+        }
     }
 
     if (format) {