# HG changeset patch # User Claus Gittinger # Date 1271185123 -7200 # Node ID be732e8f6914b5d159f129b68d25d0c69d880a9c # Parent 813dd84a590114f633db20e1ae93e01305464635 more 32 bit modulu arithmetic diff -r 813dd84a5901 -r be732e8f6914 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 $' ! !