Hello all
This email is an explanation about two aspects in a recent commit that
way be worth explanation. The committed class is:
https://builds.apache.org/job/sis-trunk/site/apidocs/org/apache/sis/math/MathFunctions.html
Multiple NaN values
-----------------
Many developers know the java.lang.Double.NaN constant, but it may be
less known that there is actually thousands of different NaN values. All
floating values having a bit pattern in the [0x7F800001 ... 0x7FFFFFFF]
or in the [0xFF800001 ... 0xFFFFFFFF] ranges are NaN numbers. Some of
them are "signalling NaN", some of them may have their bit patterns
changed by the processor in an hardward-dependant way. However the
[0x7FA00000 ... 0x7FE00000] range seems stable at least on Inter processor.
The coveage module (to be proposed to Apache SIS after metadata and
referencing) uses this trick for mixing "qualitative data" together with
"quantitative data" in a raster. Calculations involving quantitative
data like Sea Surface Temperature use the 'float' type. However those
data are often mixed with missing values because of clouds, lack of
satellite data, land surfaces, etc. Many software (including NetCDF file
format) deal with missing values by replacing them by a "pad value",
often -9999. However such practice may be dangerous: developers have to
check for pad values in about every corner of their code, otherwise a
calculation mixing a real value with a pad value will produce a wrong
result (not necessarily in a way easy to spot). Replacing all pad values
by Float.NaN resolve this issue, but we lost the differentiation between
the causes of missing values (clouds, lands, etc.).
The MathFunctions.toNaNFloat(int) and toNaNOrdinal(float) methods try to
give the best of both worlds: true NaN numbers while encoding in them
the cause of missing data. However those methods probably need to be
tested in a wider spectrum of environments than other methods.
Positive and negative zeros
-----------------------
MathFunctions contains some functions for differentiating positive zero
from negative zero. We can not differentiate those two zeros with the
usual <, >, <=, >= or == operators, so we need again to look at the bits
pattern (note that Math.abs(float, float) and Math.abs(double, double)
do that too). Most of the time, we don't need to differentiate those two
zeros. But one special case is when dealing with an envelope crossing
the anti-meridian in the way described by the Web Coverage Service (WCS)
specification. They are the red box in the figure show on this page:
http://www.geotoolkit.org/apidocs/org/geotoolkit/geometry/GeneralEnvelope.html
The most tricky case occurs when the envelope goes from 0 to 360° of
longitude, which in the [-180 ... 180]° range is represented by [0 ...
-0]°C. The later range is different than [-0 ... 0]°C, which is an empty
range. So the GeneralEnvelope class need to be especially careful about
the sign of zero. The MathFunctions.isPositive(double),
isNegative(double) and related methods are there for this purpose.
Martin