--- 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 $'
! !