Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support comparisons of different numeric types. #4576

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@

package io.deephaven.function.comparators;

import java.lang.Number;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.Comparator;

import static io.deephaven.function.Basic.isNull;
Expand All @@ -14,7 +17,7 @@
*
* @param <T> type to compare.
*/
public class NullNaNAwareComparator<T extends Comparable<? super T>> implements Comparator<T> {
public class NullNaNAwareComparator<T> implements Comparator<T> {

/**
* Creates a comparator.
Expand Down Expand Up @@ -56,7 +59,34 @@ public int compare(final T o1, final T o2) {
return -1;
}

return o1.compareTo(o2);
if (o1 instanceof Number && o2 instanceof Number) {
return toBigDecimal((Number) o1).compareTo(toBigDecimal((Number) o2));
} else if (o1 instanceof Comparable && o2 instanceof Comparable) {
return ((Comparable) o1).compareTo(o2);
} else {
throw new UnsupportedOperationException("Input types are not java.lang.Number or java.lang.Comparable: ("
+ o1.getClass() + ", " + o2.getClass() + ")");
}
}

/**
* Convert a number to a BigDecimal.
*
* @param x a number
* @return number represented as a BigDecimal
*/
protected static BigDecimal toBigDecimal(final Number x) {
if (x instanceof Byte || x instanceof Short || x instanceof Integer || x instanceof Long) {
return new BigDecimal(x.longValue());
} else if (x instanceof Float || x instanceof Double) {
return new BigDecimal(x.doubleValue());
} else if (x instanceof BigInteger) {
return new BigDecimal((BigInteger) x);
} else if (x instanceof BigDecimal) {
return (BigDecimal) x;
} else {
throw new UnsupportedOperationException(
"Unsupported java.lang.Number data type passed in to toBigDecimal (" + x.getClass() + ")");
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,47 @@

import io.deephaven.base.testing.BaseArrayTestCase;

import java.lang.Number;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.Comparator;

import static io.deephaven.util.QueryConstants.NULL_DOUBLE;
import static io.deephaven.util.QueryConstants.NULL_FLOAT;

import static io.deephaven.function.comparators.NullNaNAwareComparator.toBigDecimal;

/**
* Test NullNaNAwareComparator.
*/
public class TestNullNaNAwareComparator extends BaseArrayTestCase {

public void testNotComparable() {
final Object v1 = new java.lang.Object();
final Object v2 = new java.lang.Object();

final Comparator<Object> cmp = new NullNaNAwareComparator<>();

try {
cmp.compare(v1, v2);
fail("Expected UnsupportedOperationException");
} catch (final UnsupportedOperationException e) {
// expected
}
}

public void testString() {
final String v1 = "a";
final String v2 = "b";

final Comparator<String> cmp = new NullNaNAwareComparator<>();
assertEquals(0, cmp.compare(v1, v1));
assertEquals(0, cmp.compare(v2, v2));
assertEquals(-1, cmp.compare(v1, v2));
assertEquals(1, cmp.compare(v2, v1));
}

public void testDouble() {
final Double v1 = 1.4;
final Double v2 = 2.3;
Expand Down Expand Up @@ -94,4 +125,33 @@ public void testFloat() {
assertEquals(-1, cmp.compare(v1, v6));
assertEquals(1, cmp.compare(v6, v1));
}

public void testMixedNumeric() {
final Float v1 = 1.4f;
final Double v2 = 2.3d;

final Comparator<Number> cmp = new NullNaNAwareComparator<Number>();
assertEquals(0, cmp.compare(v1, v1));
assertEquals(0, cmp.compare(v2, v2));
assertEquals(-1, cmp.compare(v1, v2));
assertEquals(1, cmp.compare(v2, v1));
}

public void testToBigDecimal() {
assertEquals(new BigDecimal(1), toBigDecimal((byte) 1));
assertEquals(new BigDecimal(1), toBigDecimal((short) 1));
assertEquals(new BigDecimal(1), toBigDecimal((int) 1));
assertEquals(new BigDecimal(1), toBigDecimal((long) 1));
assertEquals(new BigDecimal(1), toBigDecimal((float) 1));
assertEquals(new BigDecimal(1), toBigDecimal((double) 1));
assertEquals(new BigDecimal(1), toBigDecimal(BigInteger.valueOf(1)));
assertEquals(new BigDecimal(1), toBigDecimal(new BigDecimal(1)));

try {
toBigDecimal(new AtomicInteger(1));
fail("Expected UnsupportedOperationException");
} catch (final UnsupportedOperationException e) {
// expected
}
}
}