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

Reply via email to