--- a/LargeInteger.st Wed Sep 16 21:22:45 2009 +0200
+++ b/LargeInteger.st Thu Sep 17 00:26:31 2009 +0200
@@ -892,6 +892,109 @@
#endif
RETURN ( __mkSmallInteger(v1 & v2) );
}
+
+ if (__isLargeInteger(anInteger)) {
+ OBJ _myDigitByteArray = __INST(digitByteArray);
+ OBJ _otherDigitByteArray = __LargeIntegerInstPtr(anInteger)->l_digits;
+
+ if (__isByteArray(_myDigitByteArray)
+ && __isByteArray(_otherDigitByteArray)) {
+ unsigned char *pDigits1, *pDigits2;
+ int size1, size2, minSize;
+ union {
+ double d; // force align
+ unsigned char chars[2048+8];
+ } buffer;
+ unsigned char *pRslt;
+ OBJ newDigits, newLarge;
+
+ pDigits1 = (unsigned char *)(__byteArrayVal(_myDigitByteArray));
+ pDigits2 = (unsigned char *)(__byteArrayVal(_otherDigitByteArray));
+ pRslt = (void *)(buffer.chars);
+
+ size1 = __byteArraySize(_myDigitByteArray);
+ size2 = __byteArraySize(_otherDigitByteArray);
+ minSize = (size1 < size2) ? size1 : size2;
+ if (minSize <= sizeof(buffer.chars)) {
+ int n = minSize;
+
+ /* not worth it - but a nice try and first testbed for mmx... */
+#define x__USE_MMX__
+#ifdef __USE_MMX__
+#ifdef __VISUALC__
+ if (((INT)pRslt & 7) == 0) { // 8-byte aligned
+ if (((INT)pDigits1 & 7) == ((INT)pDigits2 & 7)) { // same align
+ while (((INT)pDigits1 & 7) && (n >= sizeof(int))) {
+ ((int *)pRslt)[0] = ((int *)pDigits1)[0] & ((int *)pDigits2)[0];
+ pRslt += sizeof(int);
+ pDigits1 += sizeof(int);
+ pDigits2 += sizeof(int);
+ pDigits2 += sizeof(int);
+ n -= sizeof(int);
+ }
+ for (; n >= 8; n -= 8) {
+ __asm {
+ mov eax, pDigits1
+ movq mm0, [eax]
+ mov eax, pDigits2
+ movq mm1, [eax]
+ pand mm0, mm1
+ mov eax, pRslt
+ movq [eax], mm0
+ }
+ pDigits1 += 8;
+ pDigits2 += 8;
+ pRslt += 8;
+ }
+ __asm {
+ emms ; switch back to FPU state.
+ }
+ }
+ }
+#endif /* __VISUALC__ */
+#endif /* __USE_MMX__ */
+
+ for (; n >= sizeof(INT)*4; n -= sizeof(INT)*4) {
+ ((INT *)pRslt)[0] = ((INT *)pDigits1)[0] & ((INT *)pDigits2)[0];
+ ((INT *)pRslt)[1] = ((INT *)pDigits1)[1] & ((INT *)pDigits2)[1];
+ ((INT *)pRslt)[2] = ((INT *)pDigits1)[2] & ((INT *)pDigits2)[2];
+ ((INT *)pRslt)[3] = ((INT *)pDigits1)[3] & ((INT *)pDigits2)[3];
+ pRslt += sizeof(INT)*4;
+ pDigits1 += sizeof(INT)*4;
+ pDigits2 += sizeof(INT)*4;
+ }
+ for (; n >= sizeof(INT); n -= sizeof(INT)) {
+ ((INT *)pRslt)[0] = ((INT *)pDigits1)[0] & ((INT *)pDigits2)[0];
+ pRslt += sizeof(INT);
+ pDigits1 += sizeof(INT);
+ pDigits2 += sizeof(INT);
+ }
+ for (; n > 0; n--) {
+ *pRslt = *pDigits1 & *pDigits2;
+ pRslt++;
+ pDigits1++;
+ pDigits2++;
+ }
+ // normalize
+ while ((pRslt[-1]==0) && (pRslt > buffer.chars)) {
+ pRslt--;
+ }
+ // allocate result
+ newDigits = __MKBYTEARRAY(buffer.chars, (pRslt-buffer.chars));
+ if (newDigits) {
+ __PROTECT__(newDigits);
+ newLarge = __STX___new(sizeof(struct __LargeInteger));
+ __UNPROTECT__(newDigits);
+ if (newLarge) {
+ __InstPtr(newLarge)->o_class = LargeInteger; __STORE(newLarge, LargeInteger);
+ __LargeIntegerInstPtr(newLarge)->l_digits = newDigits; __STORE(newLarge, newDigits);
+ __LargeIntegerInstPtr(newLarge)->l_sign = __MKSMALLINT(1);
+ RETURN (newLarge);
+ }
+ }
+ }
+ }
+ }
%}.
^ super bitAnd:anInteger
@@ -4839,5 +4942,5 @@
!LargeInteger class methodsFor:'documentation'!
version
- ^ '$Header: /cvs/stx/stx/libbasic/LargeInteger.st,v 1.195 2009-09-14 22:16:50 cg Exp $'
+ ^ '$Header: /cvs/stx/stx/libbasic/LargeInteger.st,v 1.196 2009-09-16 22:26:31 cg Exp $'
! !