Re: [cp-patches] RFC: gnu.java.math.MPN optimizations

2006-03-23 Thread Ian Rogers
I have created a project to benchmark the java.math library (and these 
proposed changes). From looking at GMP it is amazing how complex these 
libraries can be made. The benchmark project is at 
http://bigintbench.sourceforge.net/. My first goal is to port some of 
the gmp benchmark programs. Interest welcomed.


Many thanks,

Ian Rogers
-- http://www.cs.man.ac.uk/~irogers/



[cp-patches] RFC: gnu.java.math.MPN optimizations

2006-03-22 Thread Ian Rogers

Hi,

sorry for not really knowing what the etiquette should be here. This 
patch alters the MPN class so that when performing adds and subtracts it 
avoids the use of longs. This is possible by an unsigned_less_than 
operation that itself uses longs, but any tree pattern matcher (such as 
those produced by iburg) should be able to convert into an unsigned 
integer comparison. ie match:
boolcmp: BOOLEAN_CMP_INT(LONG_AND(register, INT_CONSTANT), 
LONG_AND(register, INT_CONSTANT))
where the INT_CONSTANTs are both 0xL the boolean operation is 
less than and the emitted code just does an unsigned integer compare on 
the two registers.
In any case the revised code has fewer long/int operations, I believe. 
I've also not tested the code, so I'm really just putting it here to 
generate discussion.


Thanks,

Ian Rogers
-- http://www.cs.man.ac.uk/~irogers

--- MPN.java	2005-07-02 21:32:13.0 +0100
+++ MPN.hack	2006-03-22 10:55:05.0 +
@@ -47,68 +47,66 @@
  * (at least on platforms that use 32-bit limbs).
  */
 
 public class MPN
 {
+  /**
+	* Perform an unsigned less than comparison on two signed integers
+	*/
+  private static boolean unsigned_less_than(int x, int y)
+  {
+	 return ((long)x  0xL)  ((long)y  0xL);
+  }
   /** Add x[0:size-1] and y, and write the size least
* significant words of the result to dest.
* Return carry, either 0 or 1.
* All values are unsigned.
* This is basically the same as gmp's mpn_add_1. */
   public static int add_1 (int[] dest, int[] x, int size, int y)
   {
-long carry = (long) y  0xL;
-for (int i = 0;  i  size;  i++)
-  {
-	carry += ((long) x[i]  0xL);
-	dest[i] = (int) carry;
-	carry = 32;
-  }
-return (int) carry;
+	 boolean carry = false;
+	 for (int i = 0; i  size; i++) {
+		int result = x[i] + y + (carry ? 1 : 0);
+		carry = unsigned_less_than(result, x[i]);
+		dest[i] = result;
+	 }
+	 return carry ? 1 : 0;
   }
 
   /** Add x[0:len-1] and y[0:len-1] and write the len least
* significant words of the result to dest[0:len-1].
* All words are treated as unsigned.
* @return the carry, either 0 or 1
* This function is basically the same as gmp's mpn_add_n.
*/
   public static int add_n (int dest[], int[] x, int[] y, int len)
   {
-long carry = 0;
-for (int i = 0; i  len;  i++)
-  {
-	carry += ((long) x[i]  0xL)
-	  + ((long) y[i]  0xL);
-	dest[i] = (int) carry;
-	carry = 32;
-  }
-return (int) carry;
+	 boolean carry = false;
+	 for (int i = 0; i  size; i++) {
+		int result = x[i] + y[i] + (carry ? 1 : 0);
+		carry = unsigned_less_than(result, x[i]);
+		dest[i] = result;
+	 }
+	 return carry ? 1 : 0;
   }
 
   /** Subtract Y[0:size-1] from X[0:size-1], and write
* the size least significant words of the result to dest[0:size-1].
* Return borrow, either 0 or 1.
* This is basically the same as gmp's mpn_sub_n function.
*/
 
-  public static int sub_n (int[] dest, int[] X, int[] Y, int size)
+  public static int sub_n (int[] dest, int[] x, int[] y, int size)
   {
-int cy = 0;
-for (int i = 0;  i  size;  i++)
-  {
-	int y = Y[i];
-	int x = X[i];
-	y += cy;	/* add previous carry to subtrahend */
-	// Invert the high-order bit, because: (unsigned) X  (unsigned) Y
-	// iff: (int) (X^0x8000)  (int) (Y^0x8000).
-	cy = (y^0x8000)  (cy^0x8000) ? 1 : 0;
-	y = x - y;
-	cy += (y^0x8000)  (x ^ 0x8000) ? 1 : 0;
-	dest[i] = y;
-  }
-return cy;
+	 boolean borrow = false;
+	 for (int i = 0; i  size; i++) {
+		int subtrahend = y[i] + (borrow ? 1 : 0);
+		int result = x[i] - subtrahend;
+		borrow = unsigned_less_than(x[i], subtrahend);
+		dest[i] = result;
+	 }
+	 return borrow ? 1 : 0;
   }
 
   /** Multiply x[0:len-1] by y, and write the len least
* significant words of the product to dest[0:len-1].
* Return the most significant word of the product.