2018-07-29 03:30:48 +02:00
|
|
|
/*-------------------------------------------------------------------------
|
|
|
|
*
|
|
|
|
* float.h
|
|
|
|
* Definitions for the built-in floating-point types
|
|
|
|
*
|
2022-01-08 01:04:57 +01:00
|
|
|
* Portions Copyright (c) 1996-2022, PostgreSQL Global Development Group
|
2018-07-29 03:30:48 +02:00
|
|
|
* Portions Copyright (c) 1994, Regents of the University of California
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* IDENTIFICATION
|
2018-07-31 17:50:28 +02:00
|
|
|
* src/include/utils/float.h
|
2018-07-29 03:30:48 +02:00
|
|
|
*
|
|
|
|
*-------------------------------------------------------------------------
|
|
|
|
*/
|
|
|
|
#ifndef FLOAT_H
|
|
|
|
#define FLOAT_H
|
|
|
|
|
|
|
|
#include <math.h>
|
|
|
|
|
|
|
|
#ifndef M_PI
|
|
|
|
/* From my RH5.2 gcc math.h file - thomas 2000-04-03 */
|
|
|
|
#define M_PI 3.14159265358979323846
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/* Radians per degree, a.k.a. PI / 180 */
|
|
|
|
#define RADIANS_PER_DEGREE 0.0174532925199432957692
|
|
|
|
|
|
|
|
/* Visual C++ etc lacks NAN, and won't accept 0.0/0.0. */
|
|
|
|
#if defined(WIN32) && !defined(NAN)
|
|
|
|
static const uint32 nan[2] = {0xffffffff, 0x7fffffff};
|
|
|
|
|
|
|
|
#define NAN (*(const float8 *) nan)
|
|
|
|
#endif
|
|
|
|
|
|
|
|
extern PGDLLIMPORT int extra_float_digits;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Utility functions in float.c
|
|
|
|
*/
|
Avoid a performance regression in float overflow/underflow detection.
Commit 6bf0bc842 replaced float.c's CHECKFLOATVAL() macro with static
inline subroutines, but that wasn't too well thought out. In the original
coding, the unlikely condition (isinf(result) or result == 0) was checked
first, and the inf_is_valid or zero_is_valid condition only afterwards.
The inline-subroutine coding caused that to be swapped around, which is
pretty horrid for performance because (a) in common cases the is_valid
condition is twice as expensive to evaluate (e.g., requiring two isinf()
calls not one) and (b) in common cases the is_valid condition is false,
requiring us to perform the unlikely-condition check anyway. Net result
is that one isinf() call becomes two or three, resulting in visible
performance loss as reported by Keisuke Kuroda.
The original fix proposal was to revert the replacement of the macro,
but on second thought, that macro was just a bad idea from the beginning:
if anything it's a net negative for readability of the code. So instead,
let's just open-code all the overflow/underflow tests, being careful to
test the unlikely condition first (and mark it unlikely() to help the
compiler get the point).
Also, rather than having N copies of the actual ereport() calls, collapse
those into out-of-line error subroutines to save some code space. This
does mean that the error file/line numbers won't be very helpful for
figuring out where the issue really is --- but we'd already burned that
bridge by putting the ereports into static inlines.
In HEAD, check_float[48]_val() are gone altogether. In v12, leave them
present in float.h but unused in the core code, just in case some
extension is depending on them.
Emre Hasegeli, with some kibitzing from me and Andres Freund
Discussion: https://postgr.es/m/CANDwggLe1Gc1OrRqvPfGE=kM9K0FSfia0hbeFCEmwabhLz95AA@mail.gmail.com
2020-02-13 19:37:43 +01:00
|
|
|
extern void float_overflow_error(void) pg_attribute_noreturn();
|
|
|
|
extern void float_underflow_error(void) pg_attribute_noreturn();
|
|
|
|
extern void float_zero_divide_error(void) pg_attribute_noreturn();
|
2018-07-29 03:30:48 +02:00
|
|
|
extern int is_infinite(float8 val);
|
|
|
|
extern float8 float8in_internal(char *num, char **endptr_p,
|
Convert a few datatype input functions to use "soft" error reporting.
This patch converts the input functions for bool, int2, int4, int8,
float4, float8, numeric, and contrib/cube to the new soft-error style.
array_in and record_in are also converted. There's lots more to do,
but this is enough to provide proof-of-concept that the soft-error
API is usable, as well as reference examples for how to convert
input functions.
This patch is mostly by me, but it owes very substantial debt to
earlier work by Nikita Glukhov, Andrew Dunstan, and Amul Sul.
Thanks to Andres Freund for review.
Discussion: https://postgr.es/m/3bbbb0df-7382-bf87-9737-340ba096e034@postgrespro.ru
2022-12-09 16:14:53 +01:00
|
|
|
const char *type_name, const char *orig_string,
|
|
|
|
struct Node *escontext);
|
2022-12-21 14:37:17 +01:00
|
|
|
extern float4 float4in_internal(char *num, char **endptr_p,
|
|
|
|
const char *type_name, const char *orig_string,
|
|
|
|
struct Node *escontext);
|
2018-07-29 03:30:48 +02:00
|
|
|
extern char *float8out_internal(float8 num);
|
|
|
|
extern int float4_cmp_internal(float4 a, float4 b);
|
|
|
|
extern int float8_cmp_internal(float8 a, float8 b);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Routines to provide reasonably platform-independent handling of
|
|
|
|
* infinity and NaN
|
|
|
|
*
|
|
|
|
* We assume that isinf() and isnan() are available and work per spec.
|
|
|
|
* (On some platforms, we have to supply our own; see src/port.) However,
|
|
|
|
* generating an Infinity or NaN in the first place is less well standardized;
|
|
|
|
* pre-C99 systems tend not to have C99's INFINITY and NaN macros. We
|
|
|
|
* centralize our workarounds for this here.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
* The funny placements of the two #pragmas is necessary because of a
|
|
|
|
* long lived bug in the Microsoft compilers.
|
|
|
|
* See http://support.microsoft.com/kb/120968/en-us for details
|
|
|
|
*/
|
2019-10-08 10:27:30 +02:00
|
|
|
#ifdef _MSC_VER
|
2018-07-29 03:30:48 +02:00
|
|
|
#pragma warning(disable:4756)
|
|
|
|
#endif
|
|
|
|
static inline float4
|
|
|
|
get_float4_infinity(void)
|
|
|
|
{
|
|
|
|
#ifdef INFINITY
|
|
|
|
/* C99 standard way */
|
|
|
|
return (float4) INFINITY;
|
|
|
|
#else
|
2019-10-08 10:27:30 +02:00
|
|
|
#ifdef _MSC_VER
|
2018-07-29 03:30:48 +02:00
|
|
|
#pragma warning(default:4756)
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/*
|
|
|
|
* On some platforms, HUGE_VAL is an infinity, elsewhere it's just the
|
|
|
|
* largest normal float8. We assume forcing an overflow will get us a
|
|
|
|
* true infinity.
|
|
|
|
*/
|
|
|
|
return (float4) (HUGE_VAL * HUGE_VAL);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline float8
|
|
|
|
get_float8_infinity(void)
|
|
|
|
{
|
|
|
|
#ifdef INFINITY
|
|
|
|
/* C99 standard way */
|
|
|
|
return (float8) INFINITY;
|
|
|
|
#else
|
|
|
|
|
|
|
|
/*
|
|
|
|
* On some platforms, HUGE_VAL is an infinity, elsewhere it's just the
|
|
|
|
* largest normal float8. We assume forcing an overflow will get us a
|
|
|
|
* true infinity.
|
|
|
|
*/
|
|
|
|
return (float8) (HUGE_VAL * HUGE_VAL);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline float4
|
|
|
|
get_float4_nan(void)
|
|
|
|
{
|
|
|
|
#ifdef NAN
|
|
|
|
/* C99 standard way */
|
|
|
|
return (float4) NAN;
|
|
|
|
#else
|
|
|
|
/* Assume we can get a NAN via zero divide */
|
|
|
|
return (float4) (0.0 / 0.0);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline float8
|
|
|
|
get_float8_nan(void)
|
|
|
|
{
|
|
|
|
/* (float8) NAN doesn't work on some NetBSD/MIPS releases */
|
|
|
|
#if defined(NAN) && !(defined(__NetBSD__) && defined(__mips__))
|
|
|
|
/* C99 standard way */
|
|
|
|
return (float8) NAN;
|
|
|
|
#else
|
|
|
|
/* Assume we can get a NaN via zero divide */
|
|
|
|
return (float8) (0.0 / 0.0);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
Avoid a performance regression in float overflow/underflow detection.
Commit 6bf0bc842 replaced float.c's CHECKFLOATVAL() macro with static
inline subroutines, but that wasn't too well thought out. In the original
coding, the unlikely condition (isinf(result) or result == 0) was checked
first, and the inf_is_valid or zero_is_valid condition only afterwards.
The inline-subroutine coding caused that to be swapped around, which is
pretty horrid for performance because (a) in common cases the is_valid
condition is twice as expensive to evaluate (e.g., requiring two isinf()
calls not one) and (b) in common cases the is_valid condition is false,
requiring us to perform the unlikely-condition check anyway. Net result
is that one isinf() call becomes two or three, resulting in visible
performance loss as reported by Keisuke Kuroda.
The original fix proposal was to revert the replacement of the macro,
but on second thought, that macro was just a bad idea from the beginning:
if anything it's a net negative for readability of the code. So instead,
let's just open-code all the overflow/underflow tests, being careful to
test the unlikely condition first (and mark it unlikely() to help the
compiler get the point).
Also, rather than having N copies of the actual ereport() calls, collapse
those into out-of-line error subroutines to save some code space. This
does mean that the error file/line numbers won't be very helpful for
figuring out where the issue really is --- but we'd already burned that
bridge by putting the ereports into static inlines.
In HEAD, check_float[48]_val() are gone altogether. In v12, leave them
present in float.h but unused in the core code, just in case some
extension is depending on them.
Emre Hasegeli, with some kibitzing from me and Andres Freund
Discussion: https://postgr.es/m/CANDwggLe1Gc1OrRqvPfGE=kM9K0FSfia0hbeFCEmwabhLz95AA@mail.gmail.com
2020-02-13 19:37:43 +01:00
|
|
|
* Floating-point arithmetic with overflow/underflow reported as errors
|
2018-07-29 03:30:48 +02:00
|
|
|
*
|
|
|
|
* There isn't any way to check for underflow of addition/subtraction
|
|
|
|
* because numbers near the underflow value have already been rounded to
|
|
|
|
* the point where we can't detect that the two values were originally
|
|
|
|
* different, e.g. on x86, '1e-45'::float4 == '2e-45'::float4 ==
|
|
|
|
* 1.4013e-45.
|
|
|
|
*/
|
|
|
|
|
|
|
|
static inline float4
|
|
|
|
float4_pl(const float4 val1, const float4 val2)
|
|
|
|
{
|
|
|
|
float4 result;
|
|
|
|
|
|
|
|
result = val1 + val2;
|
Avoid a performance regression in float overflow/underflow detection.
Commit 6bf0bc842 replaced float.c's CHECKFLOATVAL() macro with static
inline subroutines, but that wasn't too well thought out. In the original
coding, the unlikely condition (isinf(result) or result == 0) was checked
first, and the inf_is_valid or zero_is_valid condition only afterwards.
The inline-subroutine coding caused that to be swapped around, which is
pretty horrid for performance because (a) in common cases the is_valid
condition is twice as expensive to evaluate (e.g., requiring two isinf()
calls not one) and (b) in common cases the is_valid condition is false,
requiring us to perform the unlikely-condition check anyway. Net result
is that one isinf() call becomes two or three, resulting in visible
performance loss as reported by Keisuke Kuroda.
The original fix proposal was to revert the replacement of the macro,
but on second thought, that macro was just a bad idea from the beginning:
if anything it's a net negative for readability of the code. So instead,
let's just open-code all the overflow/underflow tests, being careful to
test the unlikely condition first (and mark it unlikely() to help the
compiler get the point).
Also, rather than having N copies of the actual ereport() calls, collapse
those into out-of-line error subroutines to save some code space. This
does mean that the error file/line numbers won't be very helpful for
figuring out where the issue really is --- but we'd already burned that
bridge by putting the ereports into static inlines.
In HEAD, check_float[48]_val() are gone altogether. In v12, leave them
present in float.h but unused in the core code, just in case some
extension is depending on them.
Emre Hasegeli, with some kibitzing from me and Andres Freund
Discussion: https://postgr.es/m/CANDwggLe1Gc1OrRqvPfGE=kM9K0FSfia0hbeFCEmwabhLz95AA@mail.gmail.com
2020-02-13 19:37:43 +01:00
|
|
|
if (unlikely(isinf(result)) && !isinf(val1) && !isinf(val2))
|
|
|
|
float_overflow_error();
|
2018-07-29 03:30:48 +02:00
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline float8
|
|
|
|
float8_pl(const float8 val1, const float8 val2)
|
|
|
|
{
|
|
|
|
float8 result;
|
|
|
|
|
|
|
|
result = val1 + val2;
|
Avoid a performance regression in float overflow/underflow detection.
Commit 6bf0bc842 replaced float.c's CHECKFLOATVAL() macro with static
inline subroutines, but that wasn't too well thought out. In the original
coding, the unlikely condition (isinf(result) or result == 0) was checked
first, and the inf_is_valid or zero_is_valid condition only afterwards.
The inline-subroutine coding caused that to be swapped around, which is
pretty horrid for performance because (a) in common cases the is_valid
condition is twice as expensive to evaluate (e.g., requiring two isinf()
calls not one) and (b) in common cases the is_valid condition is false,
requiring us to perform the unlikely-condition check anyway. Net result
is that one isinf() call becomes two or three, resulting in visible
performance loss as reported by Keisuke Kuroda.
The original fix proposal was to revert the replacement of the macro,
but on second thought, that macro was just a bad idea from the beginning:
if anything it's a net negative for readability of the code. So instead,
let's just open-code all the overflow/underflow tests, being careful to
test the unlikely condition first (and mark it unlikely() to help the
compiler get the point).
Also, rather than having N copies of the actual ereport() calls, collapse
those into out-of-line error subroutines to save some code space. This
does mean that the error file/line numbers won't be very helpful for
figuring out where the issue really is --- but we'd already burned that
bridge by putting the ereports into static inlines.
In HEAD, check_float[48]_val() are gone altogether. In v12, leave them
present in float.h but unused in the core code, just in case some
extension is depending on them.
Emre Hasegeli, with some kibitzing from me and Andres Freund
Discussion: https://postgr.es/m/CANDwggLe1Gc1OrRqvPfGE=kM9K0FSfia0hbeFCEmwabhLz95AA@mail.gmail.com
2020-02-13 19:37:43 +01:00
|
|
|
if (unlikely(isinf(result)) && !isinf(val1) && !isinf(val2))
|
|
|
|
float_overflow_error();
|
2018-07-29 03:30:48 +02:00
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline float4
|
|
|
|
float4_mi(const float4 val1, const float4 val2)
|
|
|
|
{
|
|
|
|
float4 result;
|
|
|
|
|
|
|
|
result = val1 - val2;
|
Avoid a performance regression in float overflow/underflow detection.
Commit 6bf0bc842 replaced float.c's CHECKFLOATVAL() macro with static
inline subroutines, but that wasn't too well thought out. In the original
coding, the unlikely condition (isinf(result) or result == 0) was checked
first, and the inf_is_valid or zero_is_valid condition only afterwards.
The inline-subroutine coding caused that to be swapped around, which is
pretty horrid for performance because (a) in common cases the is_valid
condition is twice as expensive to evaluate (e.g., requiring two isinf()
calls not one) and (b) in common cases the is_valid condition is false,
requiring us to perform the unlikely-condition check anyway. Net result
is that one isinf() call becomes two or three, resulting in visible
performance loss as reported by Keisuke Kuroda.
The original fix proposal was to revert the replacement of the macro,
but on second thought, that macro was just a bad idea from the beginning:
if anything it's a net negative for readability of the code. So instead,
let's just open-code all the overflow/underflow tests, being careful to
test the unlikely condition first (and mark it unlikely() to help the
compiler get the point).
Also, rather than having N copies of the actual ereport() calls, collapse
those into out-of-line error subroutines to save some code space. This
does mean that the error file/line numbers won't be very helpful for
figuring out where the issue really is --- but we'd already burned that
bridge by putting the ereports into static inlines.
In HEAD, check_float[48]_val() are gone altogether. In v12, leave them
present in float.h but unused in the core code, just in case some
extension is depending on them.
Emre Hasegeli, with some kibitzing from me and Andres Freund
Discussion: https://postgr.es/m/CANDwggLe1Gc1OrRqvPfGE=kM9K0FSfia0hbeFCEmwabhLz95AA@mail.gmail.com
2020-02-13 19:37:43 +01:00
|
|
|
if (unlikely(isinf(result)) && !isinf(val1) && !isinf(val2))
|
|
|
|
float_overflow_error();
|
2018-07-29 03:30:48 +02:00
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline float8
|
|
|
|
float8_mi(const float8 val1, const float8 val2)
|
|
|
|
{
|
|
|
|
float8 result;
|
|
|
|
|
|
|
|
result = val1 - val2;
|
Avoid a performance regression in float overflow/underflow detection.
Commit 6bf0bc842 replaced float.c's CHECKFLOATVAL() macro with static
inline subroutines, but that wasn't too well thought out. In the original
coding, the unlikely condition (isinf(result) or result == 0) was checked
first, and the inf_is_valid or zero_is_valid condition only afterwards.
The inline-subroutine coding caused that to be swapped around, which is
pretty horrid for performance because (a) in common cases the is_valid
condition is twice as expensive to evaluate (e.g., requiring two isinf()
calls not one) and (b) in common cases the is_valid condition is false,
requiring us to perform the unlikely-condition check anyway. Net result
is that one isinf() call becomes two or three, resulting in visible
performance loss as reported by Keisuke Kuroda.
The original fix proposal was to revert the replacement of the macro,
but on second thought, that macro was just a bad idea from the beginning:
if anything it's a net negative for readability of the code. So instead,
let's just open-code all the overflow/underflow tests, being careful to
test the unlikely condition first (and mark it unlikely() to help the
compiler get the point).
Also, rather than having N copies of the actual ereport() calls, collapse
those into out-of-line error subroutines to save some code space. This
does mean that the error file/line numbers won't be very helpful for
figuring out where the issue really is --- but we'd already burned that
bridge by putting the ereports into static inlines.
In HEAD, check_float[48]_val() are gone altogether. In v12, leave them
present in float.h but unused in the core code, just in case some
extension is depending on them.
Emre Hasegeli, with some kibitzing from me and Andres Freund
Discussion: https://postgr.es/m/CANDwggLe1Gc1OrRqvPfGE=kM9K0FSfia0hbeFCEmwabhLz95AA@mail.gmail.com
2020-02-13 19:37:43 +01:00
|
|
|
if (unlikely(isinf(result)) && !isinf(val1) && !isinf(val2))
|
|
|
|
float_overflow_error();
|
2018-07-29 03:30:48 +02:00
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline float4
|
|
|
|
float4_mul(const float4 val1, const float4 val2)
|
|
|
|
{
|
|
|
|
float4 result;
|
|
|
|
|
|
|
|
result = val1 * val2;
|
Avoid a performance regression in float overflow/underflow detection.
Commit 6bf0bc842 replaced float.c's CHECKFLOATVAL() macro with static
inline subroutines, but that wasn't too well thought out. In the original
coding, the unlikely condition (isinf(result) or result == 0) was checked
first, and the inf_is_valid or zero_is_valid condition only afterwards.
The inline-subroutine coding caused that to be swapped around, which is
pretty horrid for performance because (a) in common cases the is_valid
condition is twice as expensive to evaluate (e.g., requiring two isinf()
calls not one) and (b) in common cases the is_valid condition is false,
requiring us to perform the unlikely-condition check anyway. Net result
is that one isinf() call becomes two or three, resulting in visible
performance loss as reported by Keisuke Kuroda.
The original fix proposal was to revert the replacement of the macro,
but on second thought, that macro was just a bad idea from the beginning:
if anything it's a net negative for readability of the code. So instead,
let's just open-code all the overflow/underflow tests, being careful to
test the unlikely condition first (and mark it unlikely() to help the
compiler get the point).
Also, rather than having N copies of the actual ereport() calls, collapse
those into out-of-line error subroutines to save some code space. This
does mean that the error file/line numbers won't be very helpful for
figuring out where the issue really is --- but we'd already burned that
bridge by putting the ereports into static inlines.
In HEAD, check_float[48]_val() are gone altogether. In v12, leave them
present in float.h but unused in the core code, just in case some
extension is depending on them.
Emre Hasegeli, with some kibitzing from me and Andres Freund
Discussion: https://postgr.es/m/CANDwggLe1Gc1OrRqvPfGE=kM9K0FSfia0hbeFCEmwabhLz95AA@mail.gmail.com
2020-02-13 19:37:43 +01:00
|
|
|
if (unlikely(isinf(result)) && !isinf(val1) && !isinf(val2))
|
|
|
|
float_overflow_error();
|
|
|
|
if (unlikely(result == 0.0f) && val1 != 0.0f && val2 != 0.0f)
|
|
|
|
float_underflow_error();
|
2018-07-29 03:30:48 +02:00
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline float8
|
|
|
|
float8_mul(const float8 val1, const float8 val2)
|
|
|
|
{
|
|
|
|
float8 result;
|
|
|
|
|
|
|
|
result = val1 * val2;
|
Avoid a performance regression in float overflow/underflow detection.
Commit 6bf0bc842 replaced float.c's CHECKFLOATVAL() macro with static
inline subroutines, but that wasn't too well thought out. In the original
coding, the unlikely condition (isinf(result) or result == 0) was checked
first, and the inf_is_valid or zero_is_valid condition only afterwards.
The inline-subroutine coding caused that to be swapped around, which is
pretty horrid for performance because (a) in common cases the is_valid
condition is twice as expensive to evaluate (e.g., requiring two isinf()
calls not one) and (b) in common cases the is_valid condition is false,
requiring us to perform the unlikely-condition check anyway. Net result
is that one isinf() call becomes two or three, resulting in visible
performance loss as reported by Keisuke Kuroda.
The original fix proposal was to revert the replacement of the macro,
but on second thought, that macro was just a bad idea from the beginning:
if anything it's a net negative for readability of the code. So instead,
let's just open-code all the overflow/underflow tests, being careful to
test the unlikely condition first (and mark it unlikely() to help the
compiler get the point).
Also, rather than having N copies of the actual ereport() calls, collapse
those into out-of-line error subroutines to save some code space. This
does mean that the error file/line numbers won't be very helpful for
figuring out where the issue really is --- but we'd already burned that
bridge by putting the ereports into static inlines.
In HEAD, check_float[48]_val() are gone altogether. In v12, leave them
present in float.h but unused in the core code, just in case some
extension is depending on them.
Emre Hasegeli, with some kibitzing from me and Andres Freund
Discussion: https://postgr.es/m/CANDwggLe1Gc1OrRqvPfGE=kM9K0FSfia0hbeFCEmwabhLz95AA@mail.gmail.com
2020-02-13 19:37:43 +01:00
|
|
|
if (unlikely(isinf(result)) && !isinf(val1) && !isinf(val2))
|
|
|
|
float_overflow_error();
|
|
|
|
if (unlikely(result == 0.0) && val1 != 0.0 && val2 != 0.0)
|
|
|
|
float_underflow_error();
|
2018-07-29 03:30:48 +02:00
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline float4
|
|
|
|
float4_div(const float4 val1, const float4 val2)
|
|
|
|
{
|
|
|
|
float4 result;
|
|
|
|
|
2020-07-21 01:44:41 +02:00
|
|
|
if (unlikely(val2 == 0.0f) && !isnan(val1))
|
Avoid a performance regression in float overflow/underflow detection.
Commit 6bf0bc842 replaced float.c's CHECKFLOATVAL() macro with static
inline subroutines, but that wasn't too well thought out. In the original
coding, the unlikely condition (isinf(result) or result == 0) was checked
first, and the inf_is_valid or zero_is_valid condition only afterwards.
The inline-subroutine coding caused that to be swapped around, which is
pretty horrid for performance because (a) in common cases the is_valid
condition is twice as expensive to evaluate (e.g., requiring two isinf()
calls not one) and (b) in common cases the is_valid condition is false,
requiring us to perform the unlikely-condition check anyway. Net result
is that one isinf() call becomes two or three, resulting in visible
performance loss as reported by Keisuke Kuroda.
The original fix proposal was to revert the replacement of the macro,
but on second thought, that macro was just a bad idea from the beginning:
if anything it's a net negative for readability of the code. So instead,
let's just open-code all the overflow/underflow tests, being careful to
test the unlikely condition first (and mark it unlikely() to help the
compiler get the point).
Also, rather than having N copies of the actual ereport() calls, collapse
those into out-of-line error subroutines to save some code space. This
does mean that the error file/line numbers won't be very helpful for
figuring out where the issue really is --- but we'd already burned that
bridge by putting the ereports into static inlines.
In HEAD, check_float[48]_val() are gone altogether. In v12, leave them
present in float.h but unused in the core code, just in case some
extension is depending on them.
Emre Hasegeli, with some kibitzing from me and Andres Freund
Discussion: https://postgr.es/m/CANDwggLe1Gc1OrRqvPfGE=kM9K0FSfia0hbeFCEmwabhLz95AA@mail.gmail.com
2020-02-13 19:37:43 +01:00
|
|
|
float_zero_divide_error();
|
2018-07-29 03:30:48 +02:00
|
|
|
result = val1 / val2;
|
2020-11-05 00:11:15 +01:00
|
|
|
if (unlikely(isinf(result)) && !isinf(val1))
|
Avoid a performance regression in float overflow/underflow detection.
Commit 6bf0bc842 replaced float.c's CHECKFLOATVAL() macro with static
inline subroutines, but that wasn't too well thought out. In the original
coding, the unlikely condition (isinf(result) or result == 0) was checked
first, and the inf_is_valid or zero_is_valid condition only afterwards.
The inline-subroutine coding caused that to be swapped around, which is
pretty horrid for performance because (a) in common cases the is_valid
condition is twice as expensive to evaluate (e.g., requiring two isinf()
calls not one) and (b) in common cases the is_valid condition is false,
requiring us to perform the unlikely-condition check anyway. Net result
is that one isinf() call becomes two or three, resulting in visible
performance loss as reported by Keisuke Kuroda.
The original fix proposal was to revert the replacement of the macro,
but on second thought, that macro was just a bad idea from the beginning:
if anything it's a net negative for readability of the code. So instead,
let's just open-code all the overflow/underflow tests, being careful to
test the unlikely condition first (and mark it unlikely() to help the
compiler get the point).
Also, rather than having N copies of the actual ereport() calls, collapse
those into out-of-line error subroutines to save some code space. This
does mean that the error file/line numbers won't be very helpful for
figuring out where the issue really is --- but we'd already burned that
bridge by putting the ereports into static inlines.
In HEAD, check_float[48]_val() are gone altogether. In v12, leave them
present in float.h but unused in the core code, just in case some
extension is depending on them.
Emre Hasegeli, with some kibitzing from me and Andres Freund
Discussion: https://postgr.es/m/CANDwggLe1Gc1OrRqvPfGE=kM9K0FSfia0hbeFCEmwabhLz95AA@mail.gmail.com
2020-02-13 19:37:43 +01:00
|
|
|
float_overflow_error();
|
2020-11-05 00:11:15 +01:00
|
|
|
if (unlikely(result == 0.0f) && val1 != 0.0f && !isinf(val2))
|
Avoid a performance regression in float overflow/underflow detection.
Commit 6bf0bc842 replaced float.c's CHECKFLOATVAL() macro with static
inline subroutines, but that wasn't too well thought out. In the original
coding, the unlikely condition (isinf(result) or result == 0) was checked
first, and the inf_is_valid or zero_is_valid condition only afterwards.
The inline-subroutine coding caused that to be swapped around, which is
pretty horrid for performance because (a) in common cases the is_valid
condition is twice as expensive to evaluate (e.g., requiring two isinf()
calls not one) and (b) in common cases the is_valid condition is false,
requiring us to perform the unlikely-condition check anyway. Net result
is that one isinf() call becomes two or three, resulting in visible
performance loss as reported by Keisuke Kuroda.
The original fix proposal was to revert the replacement of the macro,
but on second thought, that macro was just a bad idea from the beginning:
if anything it's a net negative for readability of the code. So instead,
let's just open-code all the overflow/underflow tests, being careful to
test the unlikely condition first (and mark it unlikely() to help the
compiler get the point).
Also, rather than having N copies of the actual ereport() calls, collapse
those into out-of-line error subroutines to save some code space. This
does mean that the error file/line numbers won't be very helpful for
figuring out where the issue really is --- but we'd already burned that
bridge by putting the ereports into static inlines.
In HEAD, check_float[48]_val() are gone altogether. In v12, leave them
present in float.h but unused in the core code, just in case some
extension is depending on them.
Emre Hasegeli, with some kibitzing from me and Andres Freund
Discussion: https://postgr.es/m/CANDwggLe1Gc1OrRqvPfGE=kM9K0FSfia0hbeFCEmwabhLz95AA@mail.gmail.com
2020-02-13 19:37:43 +01:00
|
|
|
float_underflow_error();
|
2018-07-29 03:30:48 +02:00
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline float8
|
|
|
|
float8_div(const float8 val1, const float8 val2)
|
|
|
|
{
|
|
|
|
float8 result;
|
|
|
|
|
2020-07-21 01:44:41 +02:00
|
|
|
if (unlikely(val2 == 0.0) && !isnan(val1))
|
Avoid a performance regression in float overflow/underflow detection.
Commit 6bf0bc842 replaced float.c's CHECKFLOATVAL() macro with static
inline subroutines, but that wasn't too well thought out. In the original
coding, the unlikely condition (isinf(result) or result == 0) was checked
first, and the inf_is_valid or zero_is_valid condition only afterwards.
The inline-subroutine coding caused that to be swapped around, which is
pretty horrid for performance because (a) in common cases the is_valid
condition is twice as expensive to evaluate (e.g., requiring two isinf()
calls not one) and (b) in common cases the is_valid condition is false,
requiring us to perform the unlikely-condition check anyway. Net result
is that one isinf() call becomes two or three, resulting in visible
performance loss as reported by Keisuke Kuroda.
The original fix proposal was to revert the replacement of the macro,
but on second thought, that macro was just a bad idea from the beginning:
if anything it's a net negative for readability of the code. So instead,
let's just open-code all the overflow/underflow tests, being careful to
test the unlikely condition first (and mark it unlikely() to help the
compiler get the point).
Also, rather than having N copies of the actual ereport() calls, collapse
those into out-of-line error subroutines to save some code space. This
does mean that the error file/line numbers won't be very helpful for
figuring out where the issue really is --- but we'd already burned that
bridge by putting the ereports into static inlines.
In HEAD, check_float[48]_val() are gone altogether. In v12, leave them
present in float.h but unused in the core code, just in case some
extension is depending on them.
Emre Hasegeli, with some kibitzing from me and Andres Freund
Discussion: https://postgr.es/m/CANDwggLe1Gc1OrRqvPfGE=kM9K0FSfia0hbeFCEmwabhLz95AA@mail.gmail.com
2020-02-13 19:37:43 +01:00
|
|
|
float_zero_divide_error();
|
2018-07-29 03:30:48 +02:00
|
|
|
result = val1 / val2;
|
2020-11-05 00:11:15 +01:00
|
|
|
if (unlikely(isinf(result)) && !isinf(val1))
|
Avoid a performance regression in float overflow/underflow detection.
Commit 6bf0bc842 replaced float.c's CHECKFLOATVAL() macro with static
inline subroutines, but that wasn't too well thought out. In the original
coding, the unlikely condition (isinf(result) or result == 0) was checked
first, and the inf_is_valid or zero_is_valid condition only afterwards.
The inline-subroutine coding caused that to be swapped around, which is
pretty horrid for performance because (a) in common cases the is_valid
condition is twice as expensive to evaluate (e.g., requiring two isinf()
calls not one) and (b) in common cases the is_valid condition is false,
requiring us to perform the unlikely-condition check anyway. Net result
is that one isinf() call becomes two or three, resulting in visible
performance loss as reported by Keisuke Kuroda.
The original fix proposal was to revert the replacement of the macro,
but on second thought, that macro was just a bad idea from the beginning:
if anything it's a net negative for readability of the code. So instead,
let's just open-code all the overflow/underflow tests, being careful to
test the unlikely condition first (and mark it unlikely() to help the
compiler get the point).
Also, rather than having N copies of the actual ereport() calls, collapse
those into out-of-line error subroutines to save some code space. This
does mean that the error file/line numbers won't be very helpful for
figuring out where the issue really is --- but we'd already burned that
bridge by putting the ereports into static inlines.
In HEAD, check_float[48]_val() are gone altogether. In v12, leave them
present in float.h but unused in the core code, just in case some
extension is depending on them.
Emre Hasegeli, with some kibitzing from me and Andres Freund
Discussion: https://postgr.es/m/CANDwggLe1Gc1OrRqvPfGE=kM9K0FSfia0hbeFCEmwabhLz95AA@mail.gmail.com
2020-02-13 19:37:43 +01:00
|
|
|
float_overflow_error();
|
2020-11-05 00:11:15 +01:00
|
|
|
if (unlikely(result == 0.0) && val1 != 0.0 && !isinf(val2))
|
Avoid a performance regression in float overflow/underflow detection.
Commit 6bf0bc842 replaced float.c's CHECKFLOATVAL() macro with static
inline subroutines, but that wasn't too well thought out. In the original
coding, the unlikely condition (isinf(result) or result == 0) was checked
first, and the inf_is_valid or zero_is_valid condition only afterwards.
The inline-subroutine coding caused that to be swapped around, which is
pretty horrid for performance because (a) in common cases the is_valid
condition is twice as expensive to evaluate (e.g., requiring two isinf()
calls not one) and (b) in common cases the is_valid condition is false,
requiring us to perform the unlikely-condition check anyway. Net result
is that one isinf() call becomes two or three, resulting in visible
performance loss as reported by Keisuke Kuroda.
The original fix proposal was to revert the replacement of the macro,
but on second thought, that macro was just a bad idea from the beginning:
if anything it's a net negative for readability of the code. So instead,
let's just open-code all the overflow/underflow tests, being careful to
test the unlikely condition first (and mark it unlikely() to help the
compiler get the point).
Also, rather than having N copies of the actual ereport() calls, collapse
those into out-of-line error subroutines to save some code space. This
does mean that the error file/line numbers won't be very helpful for
figuring out where the issue really is --- but we'd already burned that
bridge by putting the ereports into static inlines.
In HEAD, check_float[48]_val() are gone altogether. In v12, leave them
present in float.h but unused in the core code, just in case some
extension is depending on them.
Emre Hasegeli, with some kibitzing from me and Andres Freund
Discussion: https://postgr.es/m/CANDwggLe1Gc1OrRqvPfGE=kM9K0FSfia0hbeFCEmwabhLz95AA@mail.gmail.com
2020-02-13 19:37:43 +01:00
|
|
|
float_underflow_error();
|
2018-07-29 03:30:48 +02:00
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Routines for NaN-aware comparisons
|
|
|
|
*
|
|
|
|
* We consider all NaNs to be equal and larger than any non-NaN. This is
|
|
|
|
* somewhat arbitrary; the important thing is to have a consistent sort
|
|
|
|
* order.
|
|
|
|
*/
|
|
|
|
|
|
|
|
static inline bool
|
|
|
|
float4_eq(const float4 val1, const float4 val2)
|
|
|
|
{
|
|
|
|
return isnan(val1) ? isnan(val2) : !isnan(val2) && val1 == val2;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline bool
|
|
|
|
float8_eq(const float8 val1, const float8 val2)
|
|
|
|
{
|
|
|
|
return isnan(val1) ? isnan(val2) : !isnan(val2) && val1 == val2;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline bool
|
|
|
|
float4_ne(const float4 val1, const float4 val2)
|
|
|
|
{
|
|
|
|
return isnan(val1) ? !isnan(val2) : isnan(val2) || val1 != val2;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline bool
|
|
|
|
float8_ne(const float8 val1, const float8 val2)
|
|
|
|
{
|
|
|
|
return isnan(val1) ? !isnan(val2) : isnan(val2) || val1 != val2;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline bool
|
|
|
|
float4_lt(const float4 val1, const float4 val2)
|
|
|
|
{
|
|
|
|
return !isnan(val1) && (isnan(val2) || val1 < val2);
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline bool
|
|
|
|
float8_lt(const float8 val1, const float8 val2)
|
|
|
|
{
|
|
|
|
return !isnan(val1) && (isnan(val2) || val1 < val2);
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline bool
|
|
|
|
float4_le(const float4 val1, const float4 val2)
|
|
|
|
{
|
|
|
|
return isnan(val2) || (!isnan(val1) && val1 <= val2);
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline bool
|
|
|
|
float8_le(const float8 val1, const float8 val2)
|
|
|
|
{
|
|
|
|
return isnan(val2) || (!isnan(val1) && val1 <= val2);
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline bool
|
|
|
|
float4_gt(const float4 val1, const float4 val2)
|
|
|
|
{
|
|
|
|
return !isnan(val2) && (isnan(val1) || val1 > val2);
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline bool
|
|
|
|
float8_gt(const float8 val1, const float8 val2)
|
|
|
|
{
|
|
|
|
return !isnan(val2) && (isnan(val1) || val1 > val2);
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline bool
|
|
|
|
float4_ge(const float4 val1, const float4 val2)
|
|
|
|
{
|
|
|
|
return isnan(val1) || (!isnan(val2) && val1 >= val2);
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline bool
|
|
|
|
float8_ge(const float8 val1, const float8 val2)
|
|
|
|
{
|
|
|
|
return isnan(val1) || (!isnan(val2) && val1 >= val2);
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline float4
|
|
|
|
float4_min(const float4 val1, const float4 val2)
|
|
|
|
{
|
|
|
|
return float4_lt(val1, val2) ? val1 : val2;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline float8
|
|
|
|
float8_min(const float8 val1, const float8 val2)
|
|
|
|
{
|
|
|
|
return float8_lt(val1, val2) ? val1 : val2;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline float4
|
|
|
|
float4_max(const float4 val1, const float4 val2)
|
|
|
|
{
|
|
|
|
return float4_gt(val1, val2) ? val1 : val2;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline float8
|
|
|
|
float8_max(const float8 val1, const float8 val2)
|
|
|
|
{
|
|
|
|
return float8_gt(val1, val2) ? val1 : val2;
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif /* FLOAT_H */
|