G'day,

Thanks for the added initialisation of hue, in response to a compiler
warning that the variable might be used before being initialised.
This initialisation was added as r739 to CD, to the file
cd/src/drv/cddxf.c, line 1662.

As I mentioned previously, I always break out in a sweat when
floating-point (nominally double-precision, in this case) entities
are subject to an equality check.  This happens in the altered
function (RGB_to_HSB) in a number of places, especially in the
paragraph:

          if (*sat != 0)        /* hue from 0 to 359 */
          {
            if (red   == maximum) *hue = (green - blue)/delta;
            if (green == maximum) *hue = 2 + (blue - red)/delta;
            if (blue  == maximum) *hue = 4 + (red - green)/delta;
            *hue *= 60;
            if (*hue < 0) *hue += 360;
          }

While digging around various places regarding floating-point
equality in general (I was focussing on the internal 80-bit
double-extended format versus the 64-bit double format), I found a
surprise, or, more precisely, a "disappointment" in the GCC
documentation (info gcc):

        Section 13.6 Disappointments and Misunderstandings
        ==================================================

        [...]

          * On 68000 and x86 systems, for instance, you can get paradoxical
            results if you test the precise values of floating point numbers.
            For example, you can find that a floating point value which is not
            a NaN is not equal to itself.  This results from the fact that the
            floating point registers hold a few more bits of precision than
            fit in a `double' in memory.  Compiled code moves values between
            memory and floating point registers at its convenience, and moving
            them into memory truncates them.

            You can partially avoid this problem by using the `-ffloat-store'
            option (*note Optimize Options::).

        [...]

So, when dealing with optimized floating-point code, it's possible
to have code that seems absurd, such as (for "float x;" and/or
"double x;"; perhaps also other floating-point formats):

        x = PARADOXICAL_VALUE;
        if (x == x)
             printf("%s\n", "equal");
        else
             printf("%s\n", "not equal?!");

and the output would be "not equal?!\n".  (This is a very, very,
slimmed-down example; where optimization is enabled, the compiler
might be able to trace code flow here, although I don't know if
the presence of floating-point almost immediately cuts off some
analysis opportunities.)

-----

For the function in question, the colour parameters are:

     unsigned char r, unsigned char g, unsigned char b

and are immediately converted to the double variables:

     double red   = r / 255.0;
     double green = g / 255.0;
     double blue  = b / 255.0;

If r/g/b were converted to signed-integer variables (at least
16-bit), then some of the contentious equality-test cases could
operate on the integer variables, bypassing the floating-point
uncertainty.

The function could be reworked so that the majority of operations
use signed integer variables derived from the r/g/b parameters,
and defer double-precision conversions until as late as possible.

cheers,

sur-behoffski
programmer, Grouse Software

------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
Iup-users mailing list
Iup-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/iup-users

Reply via email to