Unsigned bit twiddling
Jim Laskey (Oracle)
james.laskey at oracle.com
Mon Feb 24 09:23:21 PST 2014
I had a slight change for com.oracle.graal.api.code.UnsignedMath - doesn’t affect int on 64 bit but does on 32 bit and makes long compares 10% faster. Don’t know if it’s used much in graal, but it irks me when I see complex implementations when it can be done simpler.
-- Jim
diff -r 39076a984c33 graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/UnsignedMath.java
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/UnsignedMath.java Wed Feb 19 00:39:44 2014 -0800
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/UnsignedMath.java Mon Feb 24 13:17:57 2014 -0400
@@ -29,65 +29,81 @@
/**
* Utilities for unsigned comparisons. All methods have correct, but slow, standard Java
* implementations so that they can be used with compilers not supporting the intrinsics.
+ *
+ * The technique employed here is to use the isomorphism between signed and unsigned
+ * ints created by toggling the sign bit. This maps one from to the other while
+ * preserving comparison order.
+ *
+ * int Map(int x) { return x ^ 0x80000000; }
+ *
+ * Map(0u) == 0x80000000 (MIN_VALUE)
+ * Map(1u) == 0x80000001
+ * Map(0x7FFFFFFFu) == -1
+ * Map(0x80000000u) == 0
+ * Map(0x80000001u) == 1
+ * Map(0xFFFFFFFEu) == 0x7FFFFFFE
+ * Map(0xFFFFFFFFu) == 0x7FFFFFFF (MAX_VALUE)
*/
public class UnsignedMath {
+ private static final int INTTOGGLE = 0x80000000;
+ private static final long LONGTOGGLE = 0x8000000000000000L;
private static final long MASK = 0xffffffffL;
/**
* Unsigned comparison aboveThan for two numbers.
*/
public static boolean aboveThan(int a, int b) {
- return (a & MASK) > (b & MASK);
+ return (a ^ INTTOGGLE) > (b ^ INTTOGGLE);
}
/**
* Unsigned comparison aboveOrEqual for two numbers.
*/
public static boolean aboveOrEqual(int a, int b) {
- return (a & MASK) >= (b & MASK);
+ return (a ^ INTTOGGLE) >= (b ^ INTTOGGLE);
}
/**
* Unsigned comparison belowThan for two numbers.
*/
public static boolean belowThan(int a, int b) {
- return (a & MASK) < (b & MASK);
+ return (a ^ INTTOGGLE) < (b ^ INTTOGGLE);
}
/**
* Unsigned comparison belowOrEqual for two numbers.
*/
public static boolean belowOrEqual(int a, int b) {
- return (a & MASK) <= (b & MASK);
+ return (a ^ INTTOGGLE) <= (b ^ INTTOGGLE);
}
/**
* Unsigned comparison aboveThan for two numbers.
*/
public static boolean aboveThan(long a, long b) {
- return (a > b) ^ ((a < 0) != (b < 0));
+ return (a ^ LONGTOGGLE) > (b ^ LONGTOGGLE);
}
/**
* Unsigned comparison aboveOrEqual for two numbers.
*/
public static boolean aboveOrEqual(long a, long b) {
- return (a >= b) ^ ((a < 0) != (b < 0));
+ return (a ^ LONGTOGGLE) >= (b ^ LONGTOGGLE);
}
/**
* Unsigned comparison belowThan for two numbers.
*/
public static boolean belowThan(long a, long b) {
- return (a < b) ^ ((a < 0) != (b < 0));
+ return (a ^ LONGTOGGLE) < (b ^ LONGTOGGLE);
}
/**
* Unsigned comparison belowOrEqual for two numbers.
*/
public static boolean belowOrEqual(long a, long b) {
- return (a <= b) ^ ((a < 0) != (b < 0));
+ return (a ^ LONGTOGGLE) <= (b ^ LONGTOGGLE);
}
/**
More information about the graal-dev
mailing list