aboutsummaryrefslogtreecommitdiff
path: root/src/main.c
diff options
context:
space:
mode:
authordrh <>2023-09-14 10:46:50 +0000
committerdrh <>2023-09-14 10:46:50 +0000
commitdc03af67a4427542a34fd64a88a72089c2e192c1 (patch)
tree688dd454730831b3120a00727c2031151c111d65 /src/main.c
parent595c3ecc9424edab864dea21d0408114065923e9 (diff)
parent23164c984e9f8fa5b495cc5c797952c33a0e3473 (diff)
downloadsqlite-dc03af67a4427542a34fd64a88a72089c2e192c1.tar.gz
sqlite-dc03af67a4427542a34fd64a88a72089c2e192c1.zip
Do not set the global bUseLongDouble flag based purely on sizeof(long double)
being more than 8. That is a necessary but not sufficient condition to use the long double routines. Instead, do a run-time test to verify that long double really does provide extra precision. FossilOrigin-Name: aa999d490b743f455f2fb6c41009098330380f0bc2e9b1c28fbc82141a9138ce
Diffstat (limited to 'src/main.c')
-rw-r--r--src/main.c34
1 files changed, 32 insertions, 2 deletions
diff --git a/src/main.c b/src/main.c
index d69ebf75b..a43afab16 100644
--- a/src/main.c
+++ b/src/main.c
@@ -160,6 +160,32 @@ char *sqlite3_temp_directory = 0;
char *sqlite3_data_directory = 0;
/*
+** Determine whether or not high-precision (long double) floating point
+** math works correctly on CPU currently running.
+*/
+static SQLITE_NOINLINE int hasHighPrecisionDouble(int rc){
+ if( sizeof(LONGDOUBLE_TYPE)<=8 ){
+ /* If the size of "long double" is not more than 8, then
+ ** high-precision math is not possible. */
+ return 0;
+ }else{
+ /* Just because sizeof(long double)>8 does not mean that the underlying
+ ** hardware actually supports high-precision floating point. For example,
+ ** clearing the 0x100 bit in the floating-point control word on Intel
+ ** processors will make long double work like double, even though long
+ ** double takes up more space. The only way to determine if long double
+ ** actually works is to run an experiment. */
+ LONGDOUBLE_TYPE a, b, c;
+ rc++;
+ a = 1.0+rc*0.1;
+ b = 1.0e+18+rc*25.0;
+ c = a+b;
+ return b!=c;
+ }
+}
+
+
+/*
** Initialize SQLite.
**
** This routine must be called to initialize the memory allocation,
@@ -354,6 +380,10 @@ int sqlite3_initialize(void){
}
#endif
+ /* Experimentally determine if high-precision floating point is
+ ** available. */
+ sqlite3Config.bUseLongDouble = hasHighPrecisionDouble(rc);
+
return rc;
}
@@ -4554,11 +4584,11 @@ int sqlite3_test_control(int op, ...){
** X<0 Make no changes to the bUseLongDouble. Just report value.
** X==0 Disable bUseLongDouble
** X==1 Enable bUseLongDouble
- ** X==2 Set bUseLongDouble to its default value for this platform
+ ** X>=2 Set bUseLongDouble to its default value for this platform
*/
case SQLITE_TESTCTRL_USELONGDOUBLE: {
int b = va_arg(ap, int);
- if( b==2 ) b = sizeof(LONGDOUBLE_TYPE)>8;
+ if( b>=2 ) b = hasHighPrecisionDouble(b);
if( b>=0 ) sqlite3Config.bUseLongDouble = b>0;
rc = sqlite3Config.bUseLongDouble!=0;
break;