public void testUnsignedCompare() {
long a = 1L;
long b = 1L;
+ int result;
- int result = Utils.unsignedCompare(a, b);
+ result = Utils.unsignedCompare(a, b);
assertEquals(0, result);
+
+ result = Utils.unsignedCompare(0L, 1L);
+ assertEquals(-1, result);
+ result = Utils.unsignedCompare(0xFFFFFFFFL, 0x100000000L);
+ assertEquals(-1, result);
+ result = Utils.unsignedCompare(-4L, -1L);
+ assertEquals(-1, result);
+ result = Utils.unsignedCompare(-0x80000000L, -1L);
+ assertEquals(-1, result);
+ result = Utils.unsignedCompare(0x7FFFFFFFFFFFFFFEL, 0x7FFFFFFFFFFFFFFFL);
+ assertEquals(-1, result);
+
+ result = Utils.unsignedCompare(1L, 0L);
+ assertEquals(1, result);
+ result = Utils.unsignedCompare(0x100000000L, 0xFFFFFFFFL);
+ assertEquals(1, result);
+ result = Utils.unsignedCompare(-1L, -4L);
+ assertEquals(1, result);
+ result = Utils.unsignedCompare(-1L, -0x80000000L);
+ assertEquals(1, result);
+ result = Utils.unsignedCompare(0x7FFFFFFFFFFFFFFFL, 0x7FFFFFFFFFFFFFFEL);
+ assertEquals(1, result);
}
}
\ No newline at end of file
// ------------------------------------------------------------------------
/**
- * Unsigned long comparison.
+ * Performs an unsigned long comparison on two unsigned long numbers.
*
- * @param a
- * First operand.
- * @param b
- * Second operand.
- * @return -1 if a < b, 1 if a > b, 0 if a == b.
+ * @note As Java does not support unsigned types and arithmetic, parameters
+ * are received encoded as a signed long (two-complement) but the
+ * operation is an unsigned comparator.
+ *
+ * @param left
+ * Left operand of the comparator.
+ * @param right
+ * Right operand of the comparator.
+ * @return -1 if left < right, 1 if left > right, 0 if left == right.
*/
- public static int unsignedCompare(long a, long b) {
- boolean aLeftBit = (a & (1 << (Long.SIZE - 1))) != 0;
- boolean bLeftBit = (b & (1 << (Long.SIZE - 1))) != 0;
-
- if (aLeftBit && !bLeftBit) {
- return 1;
- } else if (!aLeftBit && bLeftBit) {
- return -1;
- } else {
- if (a < b) {
- return -1;
- } else if (a > b) {
- return 1;
- } else {
- return 0;
- }
- }
+ public static int unsignedCompare(long left, long right) {
+ /*
+ * This method assumes that the arithmetic overflow on signed
+ * integer wrap on a circular domain (modulo arithmetic in
+ * two-complement), which is the defined behavior in Java.
+ *
+ * This idea is to rotate the domain by the length of the negative
+ * space, and then use the signed operator.
+ */
+ return Long.compare(left + Long.MIN_VALUE, right + Long.MIN_VALUE);
}
/**