Horiguchi-san,

On Tue, Oct 1, 2019 at 3:41 PM Kyotaro Horiguchi
<horikyota....@gmail.com> wrote:
> I found a trick seems workable generically (*1). (2.0 *
> (PG_INT64_MAX/2 + 1)) will generate the value next to the
> PG_INT64_MAX based on some assumptions
> (*1). IS_DOUBLE_SAFE_IN_INT64() below would be able to check if
> the value can be converted into int64 safely or not.

Thanks for sharing a nice way of checking overflow. I tested your
IS_DOUBLE_SAFE_IN_INT64() macro in my environment by the simple code
(attached to this email) and confirmed that it appropriately handled
the overflow. However, further consideration is needed for different
architectures.

I attached the modified patch. In the patch, I placed the macro in
"src/include/c.h", but this may not be a good choice because c.h is
widely included from a lot of files. Do you have any good ideas about
its placement?

Thanks,
Yuya Watari
NTT Software Innovation Center
watari.y...@gmail.com
#include <stdio.h>
#include <stdint.h>
#include <math.h>
#include <float.h>

#define PG_INT64_MAX INT64_MAX
#define PG_INT64_MIN INT64_MIN

/*
 * Check if a double value can be casted into int64.
 *
 * This macro is assuming that FLT_RADIX == 2 so that the * 2.0 trick works,
 * PG_INT64_MAX is so below DBL_MAX that the doubled value can be represented
 * in double and DBL_MANT_DIG is equal or smaller than DBL_MAX_EXP so that
 * ceil() returns expected result.
 */
#define MIN_DOUBLE_OVER_INT64_MAX (2.0 * (double) (PG_INT64_MAX / 2 + 1))
#define MAX_DOUBLE_UNDER_INT64_MIN (2.0 * (double) (PG_INT64_MIN / 2 - 1))

#if -PG_INT64_MAX != PG_INT64_MIN
#define IS_DOUBLE_SAFE_IN_INT64(x)                              \
        ((x) < MIN_DOUBLE_OVER_INT64_MAX && ceil(x) >= (double) PG_INT64_MIN)
#else
#define IS_DOUBLE_SAFE_IN_INT64(x)                              \
        ((x) < MIN_DOUBLE_OVER_INT64_MAX && (x) > MAX_DOUBLE_UNDER_INT64_MIN)
#endif

int main()
{
        double values[] =
        {
                -pow(2, 63) - 1025,
                -pow(2, 63),
                pow(2, 63) - 1024,
                pow(2, 63),
                INFINITY,
                -INFINITY,
                NAN
        };

        for (int i = 0; i < sizeof(values) / sizeof(values[0]); i++)
        {
                double value = values[i];
                printf("value == %lf, Overflow = %s\n", value,
                        !IS_DOUBLE_SAFE_IN_INT64(value) ? "true" : "false");
        }
}

Attachment: v3-keep-compiler-silence.patch
Description: Binary data

Reply via email to