mirror of
https://github.com/sqlite/sqlite.git
synced 2025-11-12 13:01:09 +03:00
Smaller and faster sqlite3IsNaN() implementation makes deserialization of
floating point values much faster. FossilOrigin-Name: ea748edecb261f2b862d542daff6e99a6fd8879a8ace94b440d99e110577d1c1
This commit is contained in:
@@ -3802,8 +3802,12 @@ void sqlite3MutexWarnOnContention(sqlite3_mutex*);
|
||||
#endif
|
||||
|
||||
#ifndef SQLITE_OMIT_FLOATING_POINT
|
||||
# define EXP754 (((u64)0x7ff)<<52)
|
||||
# define MAN754 ((((u64)1)<<52)-1)
|
||||
# define IsNaN(X) (((X)&EXP754)==EXP754 && ((X)&MAN754)!=0)
|
||||
int sqlite3IsNaN(double);
|
||||
#else
|
||||
# define IsNaN(X) 0
|
||||
# define sqlite3IsNaN(X) 0
|
||||
#endif
|
||||
|
||||
|
||||
42
src/util.c
42
src/util.c
@@ -58,47 +58,11 @@ int sqlite3FaultSim(int iTest){
|
||||
#ifndef SQLITE_OMIT_FLOATING_POINT
|
||||
/*
|
||||
** Return true if the floating point value is Not a Number (NaN).
|
||||
**
|
||||
** Use the math library isnan() function if compiled with SQLITE_HAVE_ISNAN.
|
||||
** Otherwise, we have our own implementation that works on most systems.
|
||||
*/
|
||||
int sqlite3IsNaN(double x){
|
||||
int rc; /* The value return */
|
||||
#if !SQLITE_HAVE_ISNAN && !HAVE_ISNAN
|
||||
/*
|
||||
** Systems that support the isnan() library function should probably
|
||||
** make use of it by compiling with -DSQLITE_HAVE_ISNAN. But we have
|
||||
** found that many systems do not have a working isnan() function so
|
||||
** this implementation is provided as an alternative.
|
||||
**
|
||||
** This NaN test sometimes fails if compiled on GCC with -ffast-math.
|
||||
** On the other hand, the use of -ffast-math comes with the following
|
||||
** warning:
|
||||
**
|
||||
** This option [-ffast-math] should never be turned on by any
|
||||
** -O option since it can result in incorrect output for programs
|
||||
** which depend on an exact implementation of IEEE or ISO
|
||||
** rules/specifications for math functions.
|
||||
**
|
||||
** Under MSVC, this NaN test may fail if compiled with a floating-
|
||||
** point precision mode other than /fp:precise. From the MSDN
|
||||
** documentation:
|
||||
**
|
||||
** The compiler [with /fp:precise] will properly handle comparisons
|
||||
** involving NaN. For example, x != x evaluates to true if x is NaN
|
||||
** ...
|
||||
*/
|
||||
#ifdef __FAST_MATH__
|
||||
# error SQLite will not work correctly with the -ffast-math option of GCC.
|
||||
#endif
|
||||
volatile double y = x;
|
||||
volatile double z = y;
|
||||
rc = (y!=z);
|
||||
#else /* if HAVE_ISNAN */
|
||||
rc = isnan(x);
|
||||
#endif /* HAVE_ISNAN */
|
||||
testcase( rc );
|
||||
return rc;
|
||||
u64 y;
|
||||
memcpy(&y,&x,sizeof(y));
|
||||
return IsNaN(y);
|
||||
}
|
||||
#endif /* SQLITE_OMIT_FLOATING_POINT */
|
||||
|
||||
|
||||
@@ -3652,7 +3652,7 @@ u32 sqlite3VdbeSerialPut(u8 *buf, Mem *pMem, u32 serial_type){
|
||||
** routine so that in most cases the overhead of moving the stack pointer
|
||||
** is avoided.
|
||||
*/
|
||||
static u32 SQLITE_NOINLINE serialGet(
|
||||
static u32 serialGet(
|
||||
const unsigned char *buf, /* Buffer to deserialize from */
|
||||
u32 serial_type, /* Serial type to deserialize */
|
||||
Mem *pMem /* Memory cell to write value into */
|
||||
@@ -3684,7 +3684,7 @@ static u32 SQLITE_NOINLINE serialGet(
|
||||
assert( sizeof(x)==8 && sizeof(pMem->u.r)==8 );
|
||||
swapMixedEndianFloat(x);
|
||||
memcpy(&pMem->u.r, &x, sizeof(x));
|
||||
pMem->flags = sqlite3IsNaN(pMem->u.r) ? MEM_Null : MEM_Real;
|
||||
pMem->flags = IsNaN(x) ? MEM_Null : MEM_Real;
|
||||
}
|
||||
return 8;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user