 # Why doesn't NumericType implement Comparable?

Just wondering: how come `RealType`, a subtype of `NumericType`, implements `Comparable`, but ```NumericType`` itself doesn’t?

If `NumericType` implemented `Comparable` then `NumericComposite` would also have to implement `Comparable`: is there any reason not to?

1 Like

What is greater: ARGB(0, 0, 0, 255) or ARGB(0, 255, 0, 0)? There is no one-dimensional order in multi-dimensional types, e.g. `ComplexType` is also not `Comparable` for the same reason.

1 Like

Fair. But for `NumericComposite`, I’d expect that e.g. if any of the elements is greater than any of the given elements, then it’s greater. One could also consider the vector length. In this case, ARGB(0, 0, 0, 255) or ARGB(0, 255, 0, 0) have the same length. I understand these are opinionated choices and non-obvious and therefore likely best avoided.

A related question then: is there a sensible way to collapse a `NumericComposite`? E.g. if you express a 3D volume as a 2D of vectors, how can one easily apply the max to each composite pixel to do a max projection?

With a converter:

``````maxProjection = Converters.convert(
composite,
(a, b) -> {
double max = -Double.MAX_VALUE;
for (int i = 0; i < length; ++i) {
final double value = a.get(i).getRealDouble();
if (value > max)
max = value;
}
b.setReal(max);
},
new DoubleType());
``````

(plusminus some typos…)

Also, `NumericComposite` is a `Composite` of `NumericType`, i.e. each scalar is already not `Comparable`. I believe you mean `RealComposite`, but I also agree that even there the assumption that the `Composite` spans an Euclidean space where amplitude is the dimension for `Comparable` is a bit too narrow. A multi-dimensional `Comparable` with multi-dimensional return type would be better, but we do not currently have this. On the other hand, I believe you can do what you want with the above `Converter` or something similar. I wrote it for a concrete `DoubleType` but that is not required because `RealComposite.get(int)` returns `RealType` which is `Comparable`, at that level you could do it.

Thanks, it is clear. I was hoping, though, for an elegant approach where `NumericType` or `RealType` math can be applied for the reduction, a là ```RealType::add``, so that I never have to write a consumer anonymous class or a loop.

With such an approach, `Views.collapse` would be the map, and `Converters.convert???` would be the reduce, to e.g. trivially max project a 3D stack into a 2D image.

As a side note, the `Comparable` javadoc states that “It is strongly recommended (though not required) that natural orderings be consistent with equals.”. For example, using vector length would mean that
ARGB(0, 0, 0, 255) and ARGB(0, 255, 0, 0) are considered equal by `compareTo` but not by `equals`. In my opinion, that would be too “surprising”. I think an explicit `LengthComparator` or something like that would be preferable for that.

2 Likes

Thanks @tpietzsch, that makes sense.

For the ARGB example, the opinionated view could be to e.g. acquire a split view of the channels with `Converters.argbChannels`, then `Views.collapse` it to a `NumericComposite`, then do the max projection or whatever operation, now that each channel has been conceptually transformed to merely an entry into each pixel’s vector.

Just for completeness: `Views.collapseReal(...)` collapses to a `RealComposite` which would be the right thing to do for `Converters.argbChannels`.