#OTHER
authorClaus Gittinger <cg@exept.de>
Thu, 10 Mar 2016 15:59:13 +0100
changeset 19317 18904be01e63
parent 19316 a6049bf9fcc0
child 19318 eee0a5c4dcea
#OTHER class: SmallInteger changed: #bitShift: shifting negative numbers
SmallInteger.st
--- a/SmallInteger.st	Thu Mar 10 15:25:36 2016 +0100
+++ b/SmallInteger.st	Thu Mar 10 15:59:13 2016 +0100
@@ -1401,9 +1401,9 @@
     "return the value of the receiver shifted by shiftCount bits;
      leftShift if shiftCount > 0; rightShift otherwise.
      Notice: the result of bitShift: on negative receivers is not
-	     defined in the language standard (since the implementation
-	     is free to choose any internal representation for integers).
-	     However, ST/X preserves the sign."
+             defined in the language standard (since the implementation
+             is free to choose any internal representation for integers).
+             However, ST/X preserves the sign."
 
 %{  /* NOCONTEXT */
 #ifdef __SCHTEAM__
@@ -1412,68 +1412,80 @@
     INT bits, count;
 
     if (__isSmallInteger(shiftCount)) {
-	bits = __intVal(self);
-	if (bits == 0) {
-	    RETURN (self);
-	}
-
-	count = __intVal(shiftCount);
-
-	if (count > 0) {
-	    /*
-	     * a left shift
-	     */
+        bits = __intVal(self);
+        if (bits == 0) {
+            RETURN (self);
+        }
+        count = __intVal(shiftCount);
+
+        if (count > 0) {
+            INT sign = 1;
+            if (bits < 0) {
+                bits = -bits;
+                sign = -1;
+            }
+            /*
+             * a left shift
+             */
 # if defined(USE_LONGLONG_FOR_SHIFT)
-	    if (count <= N_INT_BITS) {
-		unsigned LONGLONG result;
-
-		result = (unsigned LONGLONG)bits;
-		result <<= count;
-		if (result <= _MAX_INT) {
-		    RETURN ( __mkSmallInteger(result) );
-		}
-		{
-		    RETURN (__MKLARGEINT64(1, (INT)(result >> 32), (INT)(result & 0xFFFFFFFF)));
-		}
-	    }
+            if (count <= N_INT_BITS) {
+                unsigned LONGLONG result;
+
+                result = (unsigned LONGLONG)bits;
+                result <<= count;
+                if (result <= _MAX_INT) {
+                    if (sign < 0) {
+                        RETURN ( __MKINT(-result) );
+                    }
+                    RETURN ( __mkSmallInteger(result) );
+                }
+                {
+                    RETURN (__MKLARGEINT64(sign, (INT)(result >> 32), (INT)(result & 0xFFFFFFFF)));
+                }
+            }
 # else
-	    /*
-	     * check for overflow
-	     */
-	    if (count < (N_INT_BITS-1)) {
-		if (! (bits >> (N_INT_BITS - 1 - count))) {
-		    RETURN ( __mkSmallInteger(bits << count) );
-		}
-		/*
-		 * so, there is an overflow ...
-		 * handle it as largeInteger
-		 */
-		/* FALL THROUGH */
-	    }
+            /*
+             * check for overflow
+             */
+            if (count < (N_INT_BITS-1)) {
+                if (! (bits >> (N_INT_BITS - 1 - count))) {
+                    INT result = bits << count;
+                    
+                    if (sign < 0) {
+                        RETURN ( __MKINT(-result) );
+                    }
+                    RETURN ( __mkSmallInteger(result) );
+                }
+                /*
+                 * so, there is an overflow ...
+                 * handle it as largeInteger
+                 */
+                /* FALL THROUGH */
+            }
 # endif
-	} else {
-	    if (count == 0) {
-		RETURN (self);
-	    }
-
-	    /*
-	     * right shifts cannot overflow
-	     *
-	     * some machines ignore shifts bigger than
-	     * the number of bits in an int ...
-	     */
-	    count = -count;
-	    if (count > (N_INT_BITS-1)) {
-		RETURN (__mkSmallInteger(0));
-	    }
-
-	    RETURN ( __mkSmallInteger(bits >> count) );
-	}
+        } else {
+            if (count == 0) {
+                RETURN (self);
+            }
+
+            /*
+             * right shifts cannot overflow
+             *
+             * some machines ignore shifts bigger than
+             * the number of bits in an int ...
+             */
+            count = -count;
+            if (count > (N_INT_BITS-1)) {
+                RETURN (__mkSmallInteger(0));
+            }
+
+            RETURN ( __mkSmallInteger(bits >> count) );
+        }
     }
 #endif /* not __SCHTEAM__ */
 %}.
     (shiftCount isMemberOf:SmallInteger) ifTrue:[
-	^ (LargeInteger value:self) bitShift:shiftCount
+        ^ (LargeInteger value:self) bitShift:shiftCount
     ].
     ^ self bitShift:shiftCount asInteger   "/ is this a good idea ?
 !