Skip to content

Commit 6b1a213

Browse files
committed
New method for preventing compile-time calculation of degree constants.
Commit 65abaab tried to prevent the scaling constants used in the degree-based trig functions from being precomputed at compile time, because some compilers do that with functions that don't yield results identical-to-the-last-bit to what you get at runtime. A report from Peter Eisentraut suggests that some recent compilers are smart enough to see through that trick, though. Instead, let's put the inputs to these calculations into non-const global variables, which should be a more reliable way of convincing the compiler that it can't assume that they are compile-time constants. (If we really get desperate, we could mark these variables "volatile", but I do not believe we should have to.)
1 parent 40e89e2 commit 6b1a213

File tree

1 file changed

+27
-22
lines changed

1 file changed

+27
-22
lines changed

src/backend/utils/adt/float.c

Lines changed: 27 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -77,15 +77,24 @@ static float8 atan_1_0 = 0;
7777
static float8 tan_45 = 0;
7878
static float8 cot_45 = 0;
7979

80+
/*
81+
* These are intentionally not static; don't "fix" them. They will never
82+
* be referenced by other files, much less changed; but we don't want the
83+
* compiler to know that, else it might try to precompute expressions
84+
* involving them. See comments for init_degree_constants().
85+
*/
86+
float8 degree_c_thirty = 30.0;
87+
float8 degree_c_forty_five = 45.0;
88+
float8 degree_c_sixty = 60.0;
89+
float8 degree_c_one_half = 0.5;
90+
float8 degree_c_one = 1.0;
91+
8092
/* Local function prototypes */
8193
static int float4_cmp_internal(float4 a, float4 b);
8294
static int float8_cmp_internal(float8 a, float8 b);
8395
static double sind_q1(double x);
8496
static double cosd_q1(double x);
85-
86-
/* This is INTENTIONALLY NOT STATIC. Don't "fix" it. */
87-
void init_degree_constants(float8 thirty, float8 forty_five, float8 sixty,
88-
float8 one_half, float8 one);
97+
static void init_degree_constants(void);
8998

9099
#ifndef HAVE_CBRT
91100
/*
@@ -1814,35 +1823,31 @@ dtan(PG_FUNCTION_ARGS)
18141823
* compilers out there that will precompute expressions such as sin(constant)
18151824
* using a sin() function different from what will be used at runtime. If we
18161825
* want exact results, we must ensure that none of the scaling constants used
1817-
* in the degree-based trig functions are computed that way.
1818-
*
1819-
* The whole approach fails if init_degree_constants() gets inlined into the
1820-
* call sites, since then constant-folding can happen anyway. Currently it
1821-
* seems sufficient to declare it non-static to prevent that. We have no
1822-
* expectation that other files will call this, but don't tell gcc that.
1826+
* in the degree-based trig functions are computed that way. To do so, we
1827+
* compute them from the variables degree_c_thirty etc, which are also really
1828+
* constants, but the compiler cannot assume that.
18231829
*
18241830
* Other hazards we are trying to forestall with this kluge include the
18251831
* possibility that compilers will rearrange the expressions, or compute
18261832
* some intermediate results in registers wider than a standard double.
18271833
*/
1828-
void
1829-
init_degree_constants(float8 thirty, float8 forty_five, float8 sixty,
1830-
float8 one_half, float8 one)
1831-
{
1832-
sin_30 = sin(thirty * RADIANS_PER_DEGREE);
1833-
one_minus_cos_60 = 1.0 - cos(sixty * RADIANS_PER_DEGREE);
1834-
asin_0_5 = asin(one_half);
1835-
acos_0_5 = acos(one_half);
1836-
atan_1_0 = atan(one);
1837-
tan_45 = sind_q1(forty_five) / cosd_q1(forty_five);
1838-
cot_45 = cosd_q1(forty_five) / sind_q1(forty_five);
1834+
static void
1835+
init_degree_constants(void)
1836+
{
1837+
sin_30 = sin(degree_c_thirty * RADIANS_PER_DEGREE);
1838+
one_minus_cos_60 = 1.0 - cos(degree_c_sixty * RADIANS_PER_DEGREE);
1839+
asin_0_5 = asin(degree_c_one_half);
1840+
acos_0_5 = acos(degree_c_one_half);
1841+
atan_1_0 = atan(degree_c_one);
1842+
tan_45 = sind_q1(degree_c_forty_five) / cosd_q1(degree_c_forty_five);
1843+
cot_45 = cosd_q1(degree_c_forty_five) / sind_q1(degree_c_forty_five);
18391844
degree_consts_set = true;
18401845
}
18411846

18421847
#define INIT_DEGREE_CONSTANTS() \
18431848
do { \
18441849
if (!degree_consts_set) \
1845-
init_degree_constants(30.0, 45.0, 60.0, 0.5, 1.0); \
1850+
init_degree_constants(); \
18461851
} while(0)
18471852

18481853

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy