in java/dfp/src/main/java/com/epam/deltix/dfp/JavaImplCmp.java [24:146]
public static int compare(final long /*BID_UINT64*/ x, final long /*BID_UINT64*/ y) {
// SIMPLE (CASE2)
// if all the bits are the same, these numbers are equivalent.
if (x == y) {
return 0;
}
final boolean x_mask_sign = (x & MASK_SIGN) == MASK_SIGN;
final boolean y_mask_sign = (y & MASK_SIGN) == MASK_SIGN;
final boolean xIsSpecial = (x & MASK_STEERING_BITS) == MASK_STEERING_BITS;
final boolean yIsSpecial = (y & MASK_STEERING_BITS) == MASK_STEERING_BITS;
if (xIsSpecial || yIsSpecial) {
// NaN (CASE1)
// if either number is NAN, the comparison is unordered,
// rather than equal : return 0
final boolean xIsNaN = (x & MASK_NAN) == MASK_NAN;
final boolean yIsNaN = (y & MASK_NAN) == MASK_NAN;
if (xIsNaN || yIsNaN) {
return (xIsNaN ? 1 : 0) - (yIsNaN ? 1 : 0);
}
// INFINITY (CASE3)
final boolean xIsInf = (x & MASK_INF) == MASK_INF;
final boolean yIsInf = (y & MASK_INF) == MASK_INF;
if (xIsInf) {
if (x_mask_sign) {
// x is -inf, so it is less than y unless y is -inf
return yIsInf && y_mask_sign ? 0 : -1;
}
// x is pos infinity, it is greater, unless y is positive
// infinity => return y!=pos_infinity
return yIsInf && !y_mask_sign ? 0 : 1;
} else if (yIsInf) {
// x is finite, so if y is positive infinity, then x is less
// if y is negative infinity, then x is greater
return y_mask_sign ? 1 : -1;
}
}
final int exp_x, exp_y;
final long /*BID_UINT64*/ sig_x, sig_y;
final boolean x_is_zero, y_is_zero;
// if steering bits are 11 (condition will be 0), then exponent is G[0:w+1] =>
if (xIsSpecial) {
exp_x = (int) ((x & MASK_BINARY_EXPONENT2) >>> 51);
sig_x = (x & MASK_BINARY_SIG2) | MASK_BINARY_OR2;
x_is_zero = sig_x > 9999999999999999L;
} else {
exp_x = (int) ((x & MASK_BINARY_EXPONENT1) >>> 53);
sig_x = x & MASK_BINARY_SIG1;
x_is_zero = sig_x == 0;
}
// if steering bits are 11 (condition will be 0), then exponent is G[0:w+1] =>
if (yIsSpecial) {
exp_y = (int) ((y & MASK_BINARY_EXPONENT2) >>> 51);
sig_y = (y & MASK_BINARY_SIG2) | MASK_BINARY_OR2;
y_is_zero = sig_y > 9999999999999999L;
} else {
exp_y = (int) ((y & MASK_BINARY_EXPONENT1) >>> 53);
sig_y = y & MASK_BINARY_SIG1;
y_is_zero = sig_y == 0;
}
// ZERO (CASE4)
// some properties:
// (+ZERO==-ZERO) => therefore ignore the sign, and neither number is greater
// (ZERO x 10^A == ZERO x 10^B) for any valid A, B =>
// therefore ignore the exponent field
// (Any non-canonical # is considered 0)
if (x_is_zero || y_is_zero) {
if (x_is_zero && y_is_zero) {
// if both numbers are zero, they are equal
return 0;
} else if (x_is_zero) {
// if x is zero, it is greater if Y is negative
return y_mask_sign ? 1 : -1;
} else {
// if y is zero, X is greater if it is positive
return x_mask_sign ? -1 : 1;
}
}
// OPPOSITE SIGN (CASE5)
// now, if the sign bits differ, x is greater if y is negative
if (x_mask_sign ^ y_mask_sign) {
return y_mask_sign ? 1 : -1;
}
// REDUNDANT REPRESENTATIONS (CASE6)
// if both components are either bigger or smaller,
// it is clear what needs to be done
final int exp_diff = exp_x - exp_y;
final long sig_diff = sig_x - sig_y;
// if |exp_x - exp_y| < 15, it comes down to the compensated significand
if (exp_diff > 0) {
if (exp_diff > 15 || sig_diff > 0) {
return x_mask_sign ? -1 : 1;
}
// otherwise adjust the x significand upwards
// __mul_64x64_to_128MACH (sig_n_prime, sig_x, bid_mult_factor[exp_x - exp_y]); // @AD: Note: The __mul_64x64_to_128MACH macro is the same as __mul_64x64_to_128
final long __CY = bid_mult_factor[exp_diff];
final long sig_n_prime_w1 = Mul64Impl.unsignedMultiplyHigh(sig_x, __CY);
final long sig_n_prime_w0 = sig_x * __CY;
// if values are equal
if (sig_n_prime_w1 == 0 && sig_n_prime_w0 == sig_y) {
return 0;
}
// if positive, return whichever significand abs is smaller
// (converse if negative)
return (sig_n_prime_w1 == 0 && UnsignedLong.isLess(sig_n_prime_w0, sig_y)) ^ !x_mask_sign ? 1 : -1; // @AD: TODO: Check this case carefully
}
if (exp_diff < -15 || sig_diff < 0) {
return x_mask_sign ? 1 : -1;
} else if (exp_diff == 0 && sig_diff > 0) {
return x_mask_sign ? -1 : 1;
}
// adjust the y significand upwards
// __mul_64x64_to_128MACH (sig_n_prime, sig_y, bid_mult_factor[exp_y - exp_x]); // @AD: Note: The __mul_64x64_to_128MACH macro is the same as __mul_64x64_to_128
final long __CY = bid_mult_factor[-exp_diff];
final long sig_n_prime_w1 = Mul64Impl.unsignedMultiplyHigh(sig_y, __CY);
final long sig_n_prime_w0 = sig_y * __CY;
// if values are equal
if (sig_n_prime_w1 == 0 && sig_n_prime_w0 == sig_x) {
return 0;
}
// if positive, return whichever significand abs is smaller
// (converse if negative)
return (sig_n_prime_w1 != 0 || UnsignedLong.isLess(sig_x, sig_n_prime_w0)) ^ !x_mask_sign ? 1 : -1; // @AD: TODO: Check this case carefully
}