LargeInteger.st
changeset 11959 1ff0e6f908d9
parent 11927 75c9deec4a70
child 12121 38c8767f98f2
--- 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 $'
 ! !