more 32 bit modulu arithmetic
authorClaus Gittinger <cg@exept.de>
Tue, 13 Apr 2010 20:58:43 +0200
changeset 12877 be732e8f6914
parent 12876 813dd84a5901
child 12878 7aa4debd20eb
more 32 bit modulu arithmetic
LargeInteger.st
--- a/LargeInteger.st	Tue Apr 13 20:58:23 2010 +0200
+++ b/LargeInteger.st	Tue Apr 13 20:58:43 2010 +0200
@@ -1290,6 +1290,133 @@
     "
 ! !
 
+!LargeInteger methodsFor:'bit operators-32bit'!
+
+bitInvert32
+    "return the value of the receiver with all bits inverted in 32bit signed int space
+     (changes the sign)"
+
+%{  /* NOCONTEXT */
+    unsigned INT v;
+
+    v = __unsignedLongIntVal(self);
+    v = ~v;
+#if __POINTER_SIZE__ == 8
+    v &= 0xFFFFFFFFL;
+#endif
+    RETURN ( __MKUINT(v) );
+%}.
+    ^ self primitiveFailed
+
+    "
+     16r80000000 bitInvert32 hexPrintString
+     16r7FFFFFFF bitInvert32 hexPrintString
+     16rFFFFFFFF bitInvert32 hexPrintString
+     0 bitInvert32 hexPrintString
+    "
+!
+
+bitRotate32:shiftCount
+    "return the value of the receiver rotated by shiftCount bits,
+     but only within 32 bits, rotating left for positive, right for negative counts.
+     Rotates through the sign bit.
+     Useful for crypt algorithms, or to emulate C/Java semantics."
+
+%{  /* NOCONTEXT */
+
+    unsigned INT bits;
+    int count;
+
+    if (__isSmallInteger(shiftCount)) {
+        count = __intVal(shiftCount);
+        count = count % 32;
+
+        bits = __unsignedLongIntVal(self);
+        if (count > 0) {
+            bits = (bits << count) | (bits >> (32-count));
+        } else {
+            bits = (bits >> (-count)) | (bits << (32-(-count)));
+        }
+#if __POINTER_SIZE__ == 8
+        bits &= 0xFFFFFFFFL;
+#endif
+        RETURN (__MKUINT(bits));
+    }
+%}.
+    ^ self primitiveFailed
+
+    "
+     (1 bitShift32:31) rotate32:0   
+     (1 bitShift32:31) rotate32:1   
+     (1 bitShift32:31) rotate32:-1   
+    "
+!
+
+bitShift32:shiftCount
+    "return the value of the receiver shifted by shiftCount bits,
+     but only within 32 bits, shifting into/out-of the sign bit.
+     May be useful for communication interfaces, to create ST-numbers
+     from a signed 32bit int value given as individual bytes,
+     or to emulate C/Java semantics.
+     The shift is unsigned"
+
+%{  /* NOCONTEXT */
+
+    unsigned INT bits;
+    int count;
+
+    if (__isSmallInteger(shiftCount)) {
+        count = __intVal(shiftCount);
+        if (count >= 32) {
+            RETURN (__mkSmallInteger(0));
+        }
+
+        bits = __unsignedLongIntVal(self);
+        if (count > 0) {
+            bits = bits << count;
+        } else {
+            bits = bits >> (-count);
+        }
+#if __POINTER_SIZE__ == 8
+        bits &= 0xFFFFFFFFL;
+#endif
+        RETURN (__MKUINT(bits));
+    }
+%}.
+    ^ self primitiveFailed
+
+    "
+     128 bitShift:24
+     128 bitShift32:24
+
+     1 bitShift:31
+     1 bitShift32:31
+    "
+!
+
+bitXor32:aNumber
+    "return the xor of the receiver and the argument.
+     The argument must be a SmallInteger or a 4-byte LargeInteger.
+     If the result overflows the 32 bit range, the value modulo 16rFFFFFFFF is returned.
+     This is of course not always correct, but allows for C/Java behavior to be emulated."
+
+%{  /* NOCONTEXT */
+    INT rslt;
+
+    rslt =  __unsignedLongIntVal(self) ^ __unsignedLongIntVal(aNumber);
+#if __POINTER_SIZE__ == 8
+    rslt &= 0xFFFFFFFFL;
+#endif
+    RETURN ( __MKUINT(rslt));
+%}.
+    self primitiveFailed
+
+    "
+     16r7FFFFFFF bitXor: 16r80000000          4294967295
+     16r7FFFFFFF bitXor32: 16r80000000
+    "
+! !
+
 !LargeInteger methodsFor:'byte access'!
 
 digitAt:index
@@ -1397,6 +1524,25 @@
     ^ self
 !
 
+asSigned32
+    "return a 32-bit integer with my bit-pattern. Receiver must be unsigned (i.e. positive).
+     May be required for bit operations on the sign-bit and/or to
+     convert C/Java numbers."
+
+%{  /* NOCONTEXT */
+    int rslt;
+
+    rslt =  (int)(__unsignedLongIntVal(self));
+    RETURN ( __MKINT(rslt));
+%}.
+    self primitiveFailed
+
+    "
+     16r80000000 asSigned32
+     16r40000000 asSigned32
+    "
+!
+
 asSmallInteger
     "return a SmallInteger with same value as myself -
      the result is invalid if the receivers value cannot
@@ -1417,6 +1563,25 @@
     ^ value
 !
 
+asUnsigned32
+    "return a 32-bit integer with my bit-pattern. Receiver must be unsigned (i.e. positive).
+     May be required for bit operations on the sign-bit and/or to
+     convert C/Java numbers."
+
+%{  /* NOCONTEXT */
+    unsigned int rslt;
+
+    rslt =  (int)(__unsignedLongIntVal(self));
+    RETURN ( __MKUINT(rslt));
+%}.
+    self primitiveFailed
+
+    "
+     16r80000000 asUnsigned32
+     16r40000000 asUnsigned32
+    "
+!
+
 coerce:aNumber
     "convert the argument aNumber into an instance of the receivers class and return it."
 
@@ -2289,6 +2454,31 @@
     "Modified: / 9.1.1998 / 13:27:37 / cg"
 ! !
 
+!LargeInteger methodsFor:'modulu arithmetic'!
+
+plus32:aNumber
+    "return the sum of the receiver and the argument, as SmallInteger.
+     The argument must be another SmallInteger.
+     If the result overflows the 32 bit range, the value modulo 16rFFFFFFFF is returned.
+     This is of course not always correct, but allows for C/Java behavior to be emulated."
+
+%{  /* NOCONTEXT */
+    INT sum;
+
+    sum =  __unsignedLongIntVal(self) + __unsignedLongIntVal(aNumber);
+#if __POINTER_SIZE__ == 8
+    sum &= 0xFFFFFFFFL;
+#endif
+    RETURN ( __MKUINT(sum));
+%}.
+    self primitiveFailed
+
+    "
+     16r7FFFFFFF + 1       ->  2147483648
+     16r7FFFFFFF plus32: 1 ->  -2147483648  
+    "
+! !
+
 !LargeInteger methodsFor:'printing & storing'!
 
 xxxstoreOn:aStream
@@ -4950,9 +5140,9 @@
 !LargeInteger class methodsFor:'documentation'!
 
 version
-    ^ '$Header: /cvs/stx/stx/libbasic/LargeInteger.st,v 1.199 2010-02-26 20:20:38 cg Exp $'
+    ^ '$Header: /cvs/stx/stx/libbasic/LargeInteger.st,v 1.200 2010-04-13 18:58:43 cg Exp $'
 !
 
 version_CVS
-    ^ '$Header: /cvs/stx/stx/libbasic/LargeInteger.st,v 1.199 2010-02-26 20:20:38 cg Exp $'
+    ^ '$Header: /cvs/stx/stx/libbasic/LargeInteger.st,v 1.200 2010-04-13 18:58:43 cg Exp $'
 ! !