Thread: NAN code

NAN code

From
Bruce Momjian
Date:
I have changed the NAN code, so if NAN is not defined, we just use 'num'
as NAN, since we only get here if num is NAN.  Seems like a good fix for
platforms that can't assign a NAN to a variable.

---------------------------------------------------------------------------
   if (NUMERIC_IS_NAN(num))   {       result = (float32)palloc(sizeof(float32data));
#ifdef NAN       *result = NAN;
#else       *result = num;
#endif       return result;   }

--  Bruce Momjian                        |  http://www.op.net/~candle maillist@candle.pha.pa.us            |  (610)
853-3000+  If your life is a hard drive,     |  830 Blythe Avenue +  Christ can be your backup.        |  Drexel Hill,
Pennsylvania19026
 


Re: [HACKERS] NAN code

From
jwieck@debis.com (Jan Wieck)
Date:
>
> I have changed the NAN code, so if NAN is not defined, we just use 'num'
> as NAN, since we only get here if num is NAN.  Seems like a good fix for
> platforms that can't assign a NAN to a variable.
>
> ---------------------------------------------------------------------------
>
>     if (NUMERIC_IS_NAN(num))
>     {
>         result = (float32)palloc(sizeof(float32data));
> #ifdef NAN
>         *result = NAN;
> #else
>         *result = num;
> #endif
>         return result;
>     }

    And  I  where  so happy to have finally found that damned NAN
    define :-}

    Anyway - that above is absolutely wrong.

    num is  of  type  Numeric,  which  is  a  pointer  to  struct
    NumericData!   So  the  above  should result in some compiler
    warning (in fact it type casts a pointer into a double  value
    - and that will give unpredictable results).

    Seems  that only isnan() is defined as part of Posix. But not
    a definition that can force a NAN.  So  we  have  to  find  a
    portable  way  to  define the value NaN for double and float.
    Does anybody know of such a way?


Jan

--

#======================================================================#
# It's easier to get forgiveness for being wrong than for being right. #
# Let's break this rule - forgive me.                                  #
#======================================== jwieck@debis.com (Jan Wieck) #

Re: [HACKERS] NAN code

From
orion.SAPserv.Hamburg.dsh.de!wieck@sapserv.debis.de
Date:
>
> I have changed the NAN code, so if NAN is not defined, we just use 'num'
> as NAN, since we only get here if num is NAN.  Seems like a good fix for
> platforms that can't assign a NAN to a variable.
>
> ---------------------------------------------------------------------------
>
>     if (NUMERIC_IS_NAN(num))
>     {
>         result = (float32)palloc(sizeof(float32data));
> #ifdef NAN
>         *result = NAN;
> #else
>         *result = num;
> #endif
>         return result;
>     }

    And  I  where  so happy to have finally found that damned NAN
    define :-}

    Anyway - that above is absolutely wrong.

    num is  of  type  Numeric,  which  is  a  pointer  to  struct
    NumericData!   So  the  above  should result in some compiler
    warning (in fact it type casts a pointer into a double  value
    - and that will give unpredictable results).

    Seems  that only isnan() is defined as part of Posix. But not
    a definition that can force a NAN.  So  we  have  to  find  a
    portable  way  to  define the value NaN for double and float.
    Does anybody know of such a way?


Jan

--

#======================================================================#
# It's easier to get forgiveness for being wrong than for being right. #
# Let's break this rule - forgive me.                                  #
#======================================== jwieck@debis.com (Jan Wieck) #

Re: [HACKERS] NAN code

From
Hal Snyder
Date:
orion.SAPserv.Hamburg.dsh.de!wieck@sapserv.debis.de writes:

>     Seems  that only isnan() is defined as part of Posix. But not
>     a definition that can force a NAN.  So  we  have  to  find  a
>     portable  way  to  define the value NaN for double and float.
>     Does anybody know of such a way?

Bruce changed it to defining NAN as (0.0/0.0) if NAN isn't already
defined. This works on FreeBSD. I don't know if it will break on other
systems that don't have NAN already.


Re: [HACKERS] NAN code

From
Bruce Momjian
Date:
>     num is  of  type  Numeric,  which  is  a  pointer  to  struct
>     NumericData!   So  the  above  should result in some compiler
>     warning (in fact it type casts a pointer into a double  value
>     - and that will give unpredictable results).
> 
>     Seems  that only isnan() is defined as part of Posix. But not
>     a definition that can force a NAN.  So  we  have  to  find  a
>     portable  way  to  define the value NaN for double and float.
>     Does anybody know of such a way?

See my later postings.  0.0/0.0 seems to do it.

--  Bruce Momjian                        |  http://www.op.net/~candle maillist@candle.pha.pa.us            |  (610)
853-3000+  If your life is a hard drive,     |  830 Blythe Avenue +  Christ can be your backup.        |  Drexel Hill,
Pennsylvania19026
 


Re: [HACKERS] NAN code

From
"Thomas G. Lockhart"
Date:
> >     Seems  that only isnan() is defined as part of Posix. But not
> >     a definition that can force a NAN.  So  we  have  to  find  a
> >     portable  way  to  define the value NaN for double and float.
> >     Does anybody know of such a way?
> Bruce changed it to defining NAN as (0.0/0.0) if NAN isn't already
> defined. This works on FreeBSD. I don't know if it will break on other
> systems that don't have NAN already.

The NaN concept is not portable on every platform, since it is an IEEE
754 floating point feature. Older machines like VAX don't have it, and
older compilers don't support it cleanly. The divide-by-zero technique
to get NaN is likely to result in a signaled FPE, where we want a quiet
assignment of a special value (NaN on those platforms for which it is
available).

Here is the code we already have in Postgres to support the date/time
data types; you'll see NAN, HUGE_VAL, and DBL_MAX used for special
values:

#ifdef NAN
#define DT_INVALID      (NAN)
#else
#define DT_INVALID      (DBL_MIN+DBL_MIN)
#endif
#ifdef HUGE_VAL
#define DT_NOBEGIN      (-HUGE_VAL)
#define DT_NOEND        (HUGE_VAL)
#else
#define DT_NOBEGIN      (-DBL_MAX)
#define DT_NOEND        (DBL_MAX)
#endif
#define DT_CURRENT      (DBL_MIN)
#define DT_EPOCH        (-DBL_MIN)

#define DATETIME_INVALID(j)     {j = DT_INVALID;}
#ifdef NAN
#define DATETIME_IS_INVALID(j)  (isnan(j))
#else
#define DATETIME_IS_INVALID(j)  (j == DT_INVALID)
#endif

Of course, for historical reasons the date/time stuff has these special
reserved values which may not be necessary for the numerics. If
necessary, I would suggest something similar for the numeric stuff, or
perhaps on platforms without NAN and no way to generate it then just
throw an error.

As an aside, I worked on this a few years ago on my Alpha-dunix boxes
(for converting back and forth between VAX and IEEE floating point
binary values) and found that for the DEC compiler you had to use a
particular compiler flag to keep NaN as an unsignaled value. Otherwise
the call to isnan() failed when the value was put on the stack to set up
the function call to isnan() :/
                      - Tom


Re: [HACKERS] NAN code

From
jwieck@debis.com (Jan Wieck)
Date:
Bruce Momjian wrote:

>
> >     Seems  that only isnan() is defined as part of Posix. But not
> >     a definition that can force a NAN.  So  we  have  to  find  a
> >     portable  way  to  define the value NaN for double and float.
> >     Does anybody know of such a way?
>
> See my later postings.  0.0/0.0 seems to do it.

    Seen  them. Just that I'm a little in doubt if this construct
    couldn't  generate  a  SIGFPE  on  all   of   our   supported
    platform/compiler combos.  Still think we should add autoconf
    stuff to search for a NAN definition and only fallback to the
    above if that fails.

    While  searching for the NAN definition I've noticed too that
    our float4/float8 datatypes can  output  'NaN',  but  do  not
    parse  them back.  They simply elog(ERROR, ...) if you try to
    use 'NaN' as an input string for a floating point  attribute.
    Shouldn't  all  input  functions  be  able  to parse back any
    possible result of the corresponding output function?  As  of
    now,  I  cannot  imagine a construct (except a user defined C
    function), that could result in a float8-NaN value stored  in
    the  database.   But  as  soon  as  it  happens, the database
    wouldn't any longer be dump/reloadable!


Jan

--

#======================================================================#
# It's easier to get forgiveness for being wrong than for being right. #
# Let's break this rule - forgive me.                                  #
#======================================== jwieck@debis.com (Jan Wieck) #

Re: [HACKERS] NAN code

From
"Thomas G. Lockhart"
Date:
>     While  searching for the NAN definition I've noticed too that
>     our float4/float8 datatypes can  output  'NaN',  but  do  not
>     parse  them back.

Yeah, I just noticed that a few minutes ago too.

I've got some patches which fix this, at least for machines with NaN
support (and for HUGE_VAL/Infinity too). We'll need some more code to
handle non-IEEE machines...
                   - Tom


Re: [HACKERS] NAN code

From
jwieck@debis.com (Jan Wieck)
Date:
>
> >     While  searching for the NAN definition I've noticed too that
> >     our float4/float8 datatypes can  output  'NaN',  but  do  not
> >     parse  them back.
>
> Yeah, I just noticed that a few minutes ago too.
>
> I've got some patches which fix this, at least for machines with NaN
> support (and for HUGE_VAL/Infinity too). We'll need some more code to
> handle non-IEEE machines...

    The  final  might  be  that  for  machines/compilers with NaN
    support, NAN is

        #define NAN (0.0/0.0)

    or whatever is the correct thing for it (best choice is still
    the definition from a system header like nan.h if available),
    while for those who cannot support it it'll be

        #define NAN unsupported_nan_request()

        double unsupported_nan_request(void)
        {
            elog(ERROR, "unsupported request for NaN as floating point value");
            return 0.0;
        }


Jan

--

#======================================================================#
# It's easier to get forgiveness for being wrong than for being right. #
# Let's break this rule - forgive me.                                  #
#======================================== jwieck@debis.com (Jan Wieck) #