Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Remove all use of the "long double" data type from SQLite, as hardware support for long double is increasingly rare and the use of long double creates challenges for some compilers. |
---|---|
Downloads: | Tarball | ZIP archive | SQL archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA3-256: |
761d8fd18b0ee8681b12998f01a2eca1 |
User & Date: | drh 2024-10-02 13:26:17 |
References
2024-12-07
| ||
14:48 | On x64 hardware, round-trip uint64_t→double→uint64_t conversions fail for values greater than UINT64_MAX-2047. This caused the SQLite text-to-float converter routine to give incorrect results for values between '1.8446744073709550592eNNN' and '1.8446744073709551609eNNN' for any exponent NNN. This problem was introduced by check-in [761d8fd18b0ee868] and first appeared in version 3.47.0 and was reported by forum post 569a7209179a7f5e. Fixed by this check-in. (check-in: 81342fa6 user: drh tags: trunk) | |
Context
2024-10-02
| ||
16:55 | Adjust the new truncation behavior of sqlite_dbpage(N,null) such that it causes the database to be truncated to N-1 pages. This makes more since. An error is raised if N is less than 2. (check-in: 7d5ff86e user: drh tags: trunk) | |
13:26 | Remove all use of the "long double" data type from SQLite, as hardware support for long double is increasingly rare and the use of long double creates challenges for some compilers. (check-in: 761d8fd1 user: drh tags: trunk) | |
11:34 | Remove a few more traces of long double from the code. (Closed-Leaf check-in: 11d6a89e user: drh tags: omit-long-double) | |
11:15 | Ensure that if sqlite3_snapshot_get() is called immediately after a "BEGIN", then it locks the database such that the returned snapshot object may not be invalidated by a writer or checkpointer until after the sqlite3_snapshot_get() caller has closed its transaction. (check-in: eb5277e4 user: dan tags: trunk) | |
Changes
Changes to ext/wasm/GNUmakefile.
︙ | ︙ | |||
235 236 237 238 239 240 241 | -DSQLITE_THREADSAFE=0 \ -DSQLITE_TEMP_STORE=2 \ -DSQLITE_ENABLE_MATH_FUNCTIONS \ -DSQLITE_OS_KV_OPTIONAL=1 \ '-DSQLITE_DEFAULT_UNIX_VFS="unix-none"' \ -DSQLITE_USE_URI=1 \ -DSQLITE_C=$(sqlite3.c) \ | < | 235 236 237 238 239 240 241 242 243 244 245 246 247 248 | -DSQLITE_THREADSAFE=0 \ -DSQLITE_TEMP_STORE=2 \ -DSQLITE_ENABLE_MATH_FUNCTIONS \ -DSQLITE_OS_KV_OPTIONAL=1 \ '-DSQLITE_DEFAULT_UNIX_VFS="unix-none"' \ -DSQLITE_USE_URI=1 \ -DSQLITE_C=$(sqlite3.c) \ -DSQLITE_OMIT_DEPRECATED \ -DSQLITE_OMIT_UTF16 \ -DSQLITE_OMIT_LOAD_EXTENSION \ -DSQLITE_OMIT_SHARED_CACHE # ^^^ These particular OMITs are hard-coded in sqlite3-wasm.c and # removing them from this list will serve only to break the speedtest1 # builds. |
︙ | ︙ |
Changes to ext/wasm/api/sqlite3-wasm.c.
︙ | ︙ | |||
123 124 125 126 127 128 129 | /**********************************************************************/ /* SQLITE_USE_... */ #ifndef SQLITE_USE_URI # define SQLITE_USE_URI 1 #endif | < < < < | 123 124 125 126 127 128 129 130 131 132 133 134 135 136 | /**********************************************************************/ /* SQLITE_USE_... */ #ifndef SQLITE_USE_URI # define SQLITE_USE_URI 1 #endif #ifdef SQLITE_WASM_EXTRA_INIT # define SQLITE_EXTRA_INIT sqlite3_wasm_extra_init #endif /* ** If SQLITE_WASM_BARE_BONES is defined, undefine most of the ENABLE ** macros. |
︙ | ︙ | |||
159 160 161 162 163 164 165 | # define SQLITE_OMIT_INTROSPECTION_PRAGMAS # undef SQLITE_OMIT_JSON # define SQLITE_OMIT_JSON # undef SQLITE_OMIT_PROGRESS_CALLBACK # define SQLITE_OMIT_PROGRESS_CALLBACK # undef SQLITE_OMIT_WAL # define SQLITE_OMIT_WAL | < < | 155 156 157 158 159 160 161 162 163 164 165 166 167 168 | # define SQLITE_OMIT_INTROSPECTION_PRAGMAS # undef SQLITE_OMIT_JSON # define SQLITE_OMIT_JSON # undef SQLITE_OMIT_PROGRESS_CALLBACK # define SQLITE_OMIT_PROGRESS_CALLBACK # undef SQLITE_OMIT_WAL # define SQLITE_OMIT_WAL /* The following OMITs do not work with the standard amalgamation, so require a custom build: fossil clean -x ./configure OPTS='...' make -e sqlite3 |
︙ | ︙ | |||
223 224 225 226 227 228 229 | ** this writing we are tied to Emscripten for various reasons ** and cannot test the library with other build environments. */ #define SQLITE_WASM_EXPORT __attribute__((used,visibility("default"))) // See also: //__attribute__((export_name("theExportedName"), used, visibility("default"))) | < < < < < < < < < < < < < < < < < | 217 218 219 220 221 222 223 224 225 226 227 228 229 230 | ** this writing we are tied to Emscripten for various reasons ** and cannot test the library with other build environments. */ #define SQLITE_WASM_EXPORT __attribute__((used,visibility("default"))) // See also: //__attribute__((export_name("theExportedName"), used, visibility("default"))) /* ** Which sqlite3.c we're using needs to be configurable to enable ** building against a custom copy, e.g. the SEE variant. Note that we ** #include the .c file, rather than the header, so that the WASM ** extensions have access to private API internals. ** ** The caveat here is that custom variants need to account for |
︙ | ︙ |
Changes to src/global.c.
︙ | ︙ | |||
239 240 241 242 243 244 245 | SQLITE_DEFAULT_MEMSTATUS, /* bMemstat */ 1, /* bCoreMutex */ SQLITE_THREADSAFE==1, /* bFullMutex */ SQLITE_USE_URI, /* bOpenUri */ SQLITE_ALLOW_COVERING_INDEX_SCAN, /* bUseCis */ 0, /* bSmallMalloc */ 1, /* bExtraSchemaChecks */ | < | 239 240 241 242 243 244 245 246 247 248 249 250 251 252 | SQLITE_DEFAULT_MEMSTATUS, /* bMemstat */ 1, /* bCoreMutex */ SQLITE_THREADSAFE==1, /* bFullMutex */ SQLITE_USE_URI, /* bOpenUri */ SQLITE_ALLOW_COVERING_INDEX_SCAN, /* bUseCis */ 0, /* bSmallMalloc */ 1, /* bExtraSchemaChecks */ #ifdef SQLITE_DEBUG 0, /* bJsonSelfcheck */ #endif 0x7ffffffe, /* mxStrlen */ 0, /* neverCorrupt */ SQLITE_DEFAULT_LOOKASIDE, /* szLookaside, nLookaside */ SQLITE_STMTJRNL_SPILL, /* nStmtSpill */ |
︙ | ︙ |
Changes to src/main.c.
︙ | ︙ | |||
155 156 157 158 159 160 161 | ** name of a directory, then that directory will be used to store ** all database files specified with a relative pathname. ** ** See also the "PRAGMA data_store_directory" SQL command. */ char *sqlite3_data_directory = 0; | < < < < < < < < < < < < < < < < < < < < < < < < < < < | 155 156 157 158 159 160 161 162 163 164 165 166 167 168 | ** name of a directory, then that directory will be used to store ** all database files specified with a relative pathname. ** ** See also the "PRAGMA data_store_directory" SQL command. */ char *sqlite3_data_directory = 0; /* ** Initialize SQLite. ** ** This routine must be called to initialize the memory allocation, ** VFS, and mutex subsystems prior to doing any serious work with ** SQLite. But as long as you do not compile with SQLITE_OMIT_AUTOINIT ** this routine will be called automatically by key routines such as |
︙ | ︙ | |||
376 377 378 379 380 381 382 | */ #ifdef SQLITE_EXTRA_INIT if( bRunExtraInit ){ int SQLITE_EXTRA_INIT(const char*); rc = SQLITE_EXTRA_INIT(0); } #endif | < < < < < | 349 350 351 352 353 354 355 356 357 358 359 360 361 362 | */ #ifdef SQLITE_EXTRA_INIT if( bRunExtraInit ){ int SQLITE_EXTRA_INIT(const char*); rc = SQLITE_EXTRA_INIT(0); } #endif return rc; } /* ** Undo the effects of sqlite3_initialize(). Must not be called while ** there are outstanding database connections or memory allocations or ** while any part of SQLite is otherwise in use in any thread. This |
︙ | ︙ | |||
4632 4633 4634 4635 4636 4637 4638 | u64 *pU64 = va_arg(ap,u64*); int *pI2 = va_arg(ap,int*); *pI1 = rLogEst; *pU64 = sqlite3LogEstToInt(rLogEst); *pI2 = sqlite3LogEst(*pU64); break; } | < < < < < < < < < < < < < < < < < < < < < < < < | 4600 4601 4602 4603 4604 4605 4606 4607 4608 4609 4610 4611 4612 4613 | u64 *pU64 = va_arg(ap,u64*); int *pI2 = va_arg(ap,int*); *pI1 = rLogEst; *pU64 = sqlite3LogEstToInt(rLogEst); *pI2 = sqlite3LogEst(*pU64); break; } #if defined(SQLITE_DEBUG) && !defined(SQLITE_OMIT_WSD) /* sqlite3_test_control(SQLITE_TESTCTRL_TUNE, id, *piValue) ** ** If "id" is an integer between 1 and SQLITE_NTUNE then set the value ** of the id-th tuning parameter to *piValue. If "id" is between -1 ** and -SQLITE_NTUNE, then write the current value of the (-id)-th |
︙ | ︙ |
Changes to src/shell.c.in.
︙ | ︙ | |||
11253 11254 11255 11256 11257 11258 11259 | {"pending_byte", SQLITE_TESTCTRL_PENDING_BYTE,1, "OFFSET " }, {"prng_restore", SQLITE_TESTCTRL_PRNG_RESTORE,0, "" }, {"prng_save", SQLITE_TESTCTRL_PRNG_SAVE, 0, "" }, {"prng_seed", SQLITE_TESTCTRL_PRNG_SEED, 0, "SEED ?db?" }, {"seek_count", SQLITE_TESTCTRL_SEEK_COUNT, 0, "" }, {"sorter_mmap", SQLITE_TESTCTRL_SORTER_MMAP, 0, "NMAX" }, {"tune", SQLITE_TESTCTRL_TUNE, 1, "ID VALUE" }, | < | 11253 11254 11255 11256 11257 11258 11259 11260 11261 11262 11263 11264 11265 11266 | {"pending_byte", SQLITE_TESTCTRL_PENDING_BYTE,1, "OFFSET " }, {"prng_restore", SQLITE_TESTCTRL_PRNG_RESTORE,0, "" }, {"prng_save", SQLITE_TESTCTRL_PRNG_SAVE, 0, "" }, {"prng_seed", SQLITE_TESTCTRL_PRNG_SEED, 0, "SEED ?db?" }, {"seek_count", SQLITE_TESTCTRL_SEEK_COUNT, 0, "" }, {"sorter_mmap", SQLITE_TESTCTRL_SORTER_MMAP, 0, "NMAX" }, {"tune", SQLITE_TESTCTRL_TUNE, 1, "ID VALUE" }, }; int testctrl = -1; int iCtrl = -1; int rc2 = 0; /* 0: usage. 1: %d 2: %x 3: no-output */ int isOk = 0; int i, n2; const char *zCmd = 0; |
︙ | ︙ | |||
11487 11488 11489 11490 11491 11492 11493 | if( nArg==3 ){ int opt = booleanValue(azArg[2]); rc2 = sqlite3_test_control(testctrl, opt); isOk = 3; } break; | < < < < < < < < < < < < < < < | 11486 11487 11488 11489 11490 11491 11492 11493 11494 11495 11496 11497 11498 11499 | if( nArg==3 ){ int opt = booleanValue(azArg[2]); rc2 = sqlite3_test_control(testctrl, opt); isOk = 3; } break; /* sqlite3_test_control(sqlite3*) */ case SQLITE_TESTCTRL_INTERNAL_FUNCTIONS: rc2 = sqlite3_test_control(testctrl, p->db); isOk = 3; break; case SQLITE_TESTCTRL_IMPOSTER: |
︙ | ︙ |
Changes to src/sqlite.h.in.
︙ | ︙ | |||
8364 8365 8366 8367 8368 8369 8370 | #define SQLITE_TESTCTRL_RESULT_INTREAL 27 #define SQLITE_TESTCTRL_PRNG_SEED 28 #define SQLITE_TESTCTRL_EXTRA_SCHEMA_CHECKS 29 #define SQLITE_TESTCTRL_SEEK_COUNT 30 #define SQLITE_TESTCTRL_TRACEFLAGS 31 #define SQLITE_TESTCTRL_TUNE 32 #define SQLITE_TESTCTRL_LOGEST 33 | | | 8364 8365 8366 8367 8368 8369 8370 8371 8372 8373 8374 8375 8376 8377 8378 | #define SQLITE_TESTCTRL_RESULT_INTREAL 27 #define SQLITE_TESTCTRL_PRNG_SEED 28 #define SQLITE_TESTCTRL_EXTRA_SCHEMA_CHECKS 29 #define SQLITE_TESTCTRL_SEEK_COUNT 30 #define SQLITE_TESTCTRL_TRACEFLAGS 31 #define SQLITE_TESTCTRL_TUNE 32 #define SQLITE_TESTCTRL_LOGEST 33 #define SQLITE_TESTCTRL_USELONGDOUBLE 34 /* NOT USED */ #define SQLITE_TESTCTRL_LAST 34 /* Largest TESTCTRL */ /* ** CAPI3REF: SQL Keyword Checking ** ** These routines provide access to the set of SQL language keywords ** recognized by SQLite. Applications can uses these routines to determine |
︙ | ︙ |
Changes to src/sqliteInt.h.
︙ | ︙ | |||
656 657 658 659 660 661 662 | ** substitute integer for floating-point */ #ifdef SQLITE_OMIT_FLOATING_POINT # define double sqlite_int64 # define float sqlite_int64 # define fabs(X) ((X)<0?-(X):(X)) # define sqlite3IsOverflow(X) 0 | < | 656 657 658 659 660 661 662 663 664 665 666 667 668 669 | ** substitute integer for floating-point */ #ifdef SQLITE_OMIT_FLOATING_POINT # define double sqlite_int64 # define float sqlite_int64 # define fabs(X) ((X)<0?-(X):(X)) # define sqlite3IsOverflow(X) 0 # ifndef SQLITE_BIG_DBL # define SQLITE_BIG_DBL (((sqlite3_int64)1)<<50) # endif # define SQLITE_OMIT_DATETIME_FUNCS 1 # define SQLITE_OMIT_TRACE 1 # undef SQLITE_MIXED_ENDIAN_64BIT_FLOAT # undef SQLITE_HAVE_ISNAN |
︙ | ︙ | |||
831 832 833 834 835 836 837 | #ifndef INT8_TYPE # ifdef HAVE_INT8_T # define INT8_TYPE int8_t # else # define INT8_TYPE signed char # endif #endif | < < < | 830 831 832 833 834 835 836 837 838 839 840 841 842 843 | #ifndef INT8_TYPE # ifdef HAVE_INT8_T # define INT8_TYPE int8_t # else # define INT8_TYPE signed char # endif #endif typedef sqlite_int64 i64; /* 8-byte signed integer */ typedef sqlite_uint64 u64; /* 8-byte unsigned integer */ typedef UINT32_TYPE u32; /* 4-byte unsigned integer */ typedef UINT16_TYPE u16; /* 2-byte unsigned integer */ typedef INT16_TYPE i16; /* 2-byte signed integer */ typedef UINT8_TYPE u8; /* 1-byte unsigned integer */ typedef INT8_TYPE i8; /* 1-byte signed integer */ |
︙ | ︙ | |||
4245 4246 4247 4248 4249 4250 4251 | #define SQLITE_NTUNE 6 /* Should be zero for all trunk check-ins */ #ifdef SQLITE_DEBUG # define Tuning(X) (sqlite3Config.aTune[(X)-1]) #else # define Tuning(X) 0 #endif | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 4241 4242 4243 4244 4245 4246 4247 4248 4249 4250 4251 4252 4253 4254 4255 4256 4257 4258 4259 4260 4261 4262 4263 4264 4265 4266 4267 | #define SQLITE_NTUNE 6 /* Should be zero for all trunk check-ins */ #ifdef SQLITE_DEBUG # define Tuning(X) (sqlite3Config.aTune[(X)-1]) #else # define Tuning(X) 0 #endif /* ** Structure containing global configuration data for the SQLite library. ** ** This structure also contains some state information. */ struct Sqlite3Config { int bMemstat; /* True to enable memory status */ u8 bCoreMutex; /* True to enable core mutexing */ u8 bFullMutex; /* True to enable full mutexing */ u8 bOpenUri; /* True to interpret filenames as URIs */ u8 bUseCis; /* Use covering indices for full-scans */ u8 bSmallMalloc; /* Avoid large memory allocations if true */ u8 bExtraSchemaChecks; /* Verify type,name,tbl_name in schema */ #ifdef SQLITE_DEBUG u8 bJsonSelfcheck; /* Double-check JSON parsing */ #endif int mxStrlen; /* Maximum string length */ int neverCorrupt; /* Database is always well-formed */ int szLookaside; /* Default lookaside buffer size */ int nLookaside; /* Default lookaside buffer count */ |
︙ | ︙ |
Changes to src/test1.c.
︙ | ︙ | |||
7309 7310 7311 7312 7313 7314 7315 | return TCL_ERROR; } if( Tcl_GetBooleanFromObj(interp,objv[1],&i) ) return TCL_ERROR; sqlite3_test_control(SQLITE_TESTCTRL_EXTRA_SCHEMA_CHECKS, i); return TCL_OK; } | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 7309 7310 7311 7312 7313 7314 7315 7316 7317 7318 7319 7320 7321 7322 | return TCL_ERROR; } if( Tcl_GetBooleanFromObj(interp,objv[1],&i) ) return TCL_ERROR; sqlite3_test_control(SQLITE_TESTCTRL_EXTRA_SCHEMA_CHECKS, i); return TCL_OK; } /* ** tclcmd: database_may_be_corrupt ** ** Indicate that database files might be corrupt. In other words, set the normal ** state of operation. */ static int SQLITE_TCLAPI database_may_be_corrupt( |
︙ | ︙ | |||
9146 9147 9148 9149 9150 9151 9152 | { "dbconfig_maindbname_icecube", test_dbconfig_maindbname_icecube }, { "save_prng_state", save_prng_state, 0 }, { "restore_prng_state", restore_prng_state, 0 }, { "reset_prng_state", reset_prng_state, 0 }, { "prng_seed", prng_seed, 0 }, { "extra_schema_checks", extra_schema_checks, 0}, | < | 9115 9116 9117 9118 9119 9120 9121 9122 9123 9124 9125 9126 9127 9128 | { "dbconfig_maindbname_icecube", test_dbconfig_maindbname_icecube }, { "save_prng_state", save_prng_state, 0 }, { "restore_prng_state", restore_prng_state, 0 }, { "reset_prng_state", reset_prng_state, 0 }, { "prng_seed", prng_seed, 0 }, { "extra_schema_checks", extra_schema_checks, 0}, { "database_never_corrupt", database_never_corrupt, 0}, { "database_may_be_corrupt", database_may_be_corrupt, 0}, { "optimization_control", optimization_control,0}, #if SQLITE_OS_WIN { "lock_win32_file", win32_file_lock, 0 }, #endif { "tcl_objproc", runAsObjProc, 0 }, |
︙ | ︙ | |||
9295 9296 9297 9298 9299 9300 9301 | { "sqlite3_unregister_cksumvfs", test_unregister_cksumvfs, 0 }, { "number_of_cores", guess_number_of_cores, 0 }, #ifndef SQLITE_OMIT_VIRTUALTABLE { "create_null_module", test_create_null_module, 0 }, #endif }; static int bitmask_size = sizeof(Bitmask)*8; | < | 9263 9264 9265 9266 9267 9268 9269 9270 9271 9272 9273 9274 9275 9276 | { "sqlite3_unregister_cksumvfs", test_unregister_cksumvfs, 0 }, { "number_of_cores", guess_number_of_cores, 0 }, #ifndef SQLITE_OMIT_VIRTUALTABLE { "create_null_module", test_create_null_module, 0 }, #endif }; static int bitmask_size = sizeof(Bitmask)*8; int i; extern int sqlite3_sync_count, sqlite3_fullsync_count; extern int sqlite3_opentemp_count; extern int sqlite3_like_count; extern int sqlite3_xferopt_count; extern int sqlite3_pager_readdb_count; extern int sqlite3_pager_writedb_count; |
︙ | ︙ | |||
9396 9397 9398 9399 9400 9401 9402 | (char*)&sqlite_static_bind_nbyte, TCL_LINK_INT); Tcl_LinkVar(interp, "sqlite_temp_directory", (char*)&sqlite3_temp_directory, TCL_LINK_STRING); Tcl_LinkVar(interp, "sqlite_data_directory", (char*)&sqlite3_data_directory, TCL_LINK_STRING); Tcl_LinkVar(interp, "bitmask_size", (char*)&bitmask_size, TCL_LINK_INT|TCL_LINK_READ_ONLY); | < < | 9363 9364 9365 9366 9367 9368 9369 9370 9371 9372 9373 9374 9375 9376 | (char*)&sqlite_static_bind_nbyte, TCL_LINK_INT); Tcl_LinkVar(interp, "sqlite_temp_directory", (char*)&sqlite3_temp_directory, TCL_LINK_STRING); Tcl_LinkVar(interp, "sqlite_data_directory", (char*)&sqlite3_data_directory, TCL_LINK_STRING); Tcl_LinkVar(interp, "bitmask_size", (char*)&bitmask_size, TCL_LINK_INT|TCL_LINK_READ_ONLY); Tcl_LinkVar(interp, "sqlite_sync_count", (char*)&sqlite3_sync_count, TCL_LINK_INT); Tcl_LinkVar(interp, "sqlite_fullsync_count", (char*)&sqlite3_fullsync_count, TCL_LINK_INT); #if defined(SQLITE_ENABLE_TREETRACE) Tcl_LinkVar(interp, "sqlite3_unsupported_treetrace", (char*)&sqlite3TreeTrace, TCL_LINK_INT); |
︙ | ︙ |
Changes to src/test_config.c.
︙ | ︙ | |||
508 509 510 511 512 513 514 | #ifdef SQLITE_OMIT_LOOKASIDE Tcl_SetVar2(interp, "sqlite_options", "lookaside", "0", TCL_GLOBAL_ONLY); #else Tcl_SetVar2(interp, "sqlite_options", "lookaside", "1", TCL_GLOBAL_ONLY); #endif | < < < < | 508 509 510 511 512 513 514 515 516 517 518 519 520 521 | #ifdef SQLITE_OMIT_LOOKASIDE Tcl_SetVar2(interp, "sqlite_options", "lookaside", "0", TCL_GLOBAL_ONLY); #else Tcl_SetVar2(interp, "sqlite_options", "lookaside", "1", TCL_GLOBAL_ONLY); #endif #ifdef SQLITE_OMIT_MEMORYDB Tcl_SetVar2(interp, "sqlite_options", "memorydb", "0", TCL_GLOBAL_ONLY); #else Tcl_SetVar2(interp, "sqlite_options", "memorydb", "1", TCL_GLOBAL_ONLY); #endif #ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT |
︙ | ︙ |
Changes to src/util.c.
︙ | ︙ | |||
454 455 456 457 458 459 460 | while( z[0] ){ h += UpperToLower[(unsigned char)z[0]]; z++; } return h; } | < | 454 455 456 457 458 459 460 461 462 463 464 465 466 467 | while( z[0] ){ h += UpperToLower[(unsigned char)z[0]]; z++; } return h; } /* Double-Double multiplication. (x[0],x[1]) *= (y,yy) ** ** Reference: ** T. J. Dekker, "A Floating-Point Technique for Extending the ** Available Precision". 1971-07-26. */ static void dekkerMul2(volatile double *x, double y, double yy){ |
︙ | ︙ | |||
490 491 492 493 494 495 496 | c = p+q; cc = p - c + q + tx*ty; cc = x[0]*yy + x[1]*y + cc; x[0] = c + cc; x[1] = c - x[0]; x[1] += cc; } | < < < | 489 490 491 492 493 494 495 496 497 498 499 500 501 502 | c = p+q; cc = p - c + q + tx*ty; cc = x[0]*yy + x[1]*y + cc; x[0] = c + cc; x[1] = c - x[0]; x[1] += cc; } /* ** The string z[] is an text representation of a real number. ** Convert this string to a double and write it into *pResult. ** ** The string z[] is length bytes in length (bytes, not characters) and ** uses the encoding enc. The string is not necessarily zero-terminated. |
︙ | ︙ | |||
539 540 541 542 543 544 545 546 547 548 549 550 551 552 | u64 s = 0; /* significand */ int d = 0; /* adjust exponent for shifting decimal point */ int esign = 1; /* sign of exponent */ int e = 0; /* exponent */ int eValid = 1; /* True exponent is either not used or is well-formed */ int nDigit = 0; /* Number of digits processed */ int eType = 1; /* 1: pure integer, 2+: fractional -1 or less: bad UTF16 */ assert( enc==SQLITE_UTF8 || enc==SQLITE_UTF16LE || enc==SQLITE_UTF16BE ); *pResult = 0.0; /* Default return value, in case of an error */ if( length==0 ) return 0; if( enc==SQLITE_UTF8 ){ incr = 1; | > > | 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 | u64 s = 0; /* significand */ int d = 0; /* adjust exponent for shifting decimal point */ int esign = 1; /* sign of exponent */ int e = 0; /* exponent */ int eValid = 1; /* True exponent is either not used or is well-formed */ int nDigit = 0; /* Number of digits processed */ int eType = 1; /* 1: pure integer, 2+: fractional -1 or less: bad UTF16 */ double rr[2]; u64 s2; assert( enc==SQLITE_UTF8 || enc==SQLITE_UTF16LE || enc==SQLITE_UTF16BE ); *pResult = 0.0; /* Default return value, in case of an error */ if( length==0 ) return 0; if( enc==SQLITE_UTF8 ){ incr = 1; |
︙ | ︙ | |||
650 651 652 653 654 655 656 | e--; } while( e<0 && (s%10)==0 ){ s /= 10; e++; } | < < < < < < < < < < < < < < < < < < < < < < < < < < | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | < | 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 | e--; } while( e<0 && (s%10)==0 ){ s /= 10; e++; } rr[0] = (double)s; s2 = (u64)rr[0]; #if defined(_MSC_VER) && _MSC_VER<1700 if( s2==0x8000000000000000LL ){ s2 = 2*(u64)(0.5*rr[0]); } #endif rr[1] = s>=s2 ? (double)(s - s2) : -(double)(s2 - s); if( e>0 ){ while( e>=100 ){ e -= 100; dekkerMul2(rr, 1.0e+100, -1.5902891109759918046e+83); } while( e>=10 ){ e -= 10; dekkerMul2(rr, 1.0e+10, 0.0); } while( e>=1 ){ e -= 1; dekkerMul2(rr, 1.0e+01, 0.0); } }else{ while( e<=-100 ){ e += 100; dekkerMul2(rr, 1.0e-100, -1.99918998026028836196e-117); } while( e<=-10 ){ e += 10; dekkerMul2(rr, 1.0e-10, -3.6432197315497741579e-27); } while( e<=-1 ){ e += 1; dekkerMul2(rr, 1.0e-01, -5.5511151231257827021e-18); } } *pResult = rr[0]+rr[1]; if( sqlite3IsNaN(*pResult) ) *pResult = 1e300*1e300; if( sign<0 ) *pResult = -*pResult; assert( !sqlite3IsNaN(*pResult) ); atof_return: /* return true if number and no extra non-whitespace characters after */ if( z==zEnd && nDigit>0 && eValid && eType>0 ){ return eType; |
︙ | ︙ | |||
1032 1033 1034 1035 1036 1037 1038 1039 1040 | ** into the middle of p->zBuf[]. There are p->n significant digits. ** The p->z[] array is *not* zero-terminated. */ void sqlite3FpDecode(FpDecode *p, double r, int iRound, int mxRound){ int i; u64 v; int e, exp = 0; p->isSpecial = 0; p->z = p->zBuf; | > > < | 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 | ** into the middle of p->zBuf[]. There are p->n significant digits. ** The p->z[] array is *not* zero-terminated. */ void sqlite3FpDecode(FpDecode *p, double r, int iRound, int mxRound){ int i; u64 v; int e, exp = 0; double rr[2]; p->isSpecial = 0; p->z = p->zBuf; assert( mxRound>0 ); /* Convert negative numbers to positive. Deal with Infinity, 0.0, and ** NaN. */ if( r<0.0 ){ p->sign = '-'; r = -r; |
︙ | ︙ | |||
1062 1063 1064 1065 1066 1067 1068 | p->n = 0; p->iDP = 0; return; } /* Multiply r by powers of ten until it lands somewhere in between ** 1.0e+19 and 1.0e+17. | | < < < < < < < < < < < < < < | | | | | | | | < | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | < < | 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 | p->n = 0; p->iDP = 0; return; } /* Multiply r by powers of ten until it lands somewhere in between ** 1.0e+19 and 1.0e+17. ** ** Use Dekker-style double-double computation to increase the ** precision. ** ** The error terms on constants like 1.0e+100 computed using the ** decimal extension, for example as follows: ** ** SELECT decimal_exp(decimal_sub('1.0e+100',decimal(1.0e+100))); */ rr[0] = r; rr[1] = 0.0; if( rr[0]>9.223372036854774784e+18 ){ while( rr[0]>9.223372036854774784e+118 ){ exp += 100; dekkerMul2(rr, 1.0e-100, -1.99918998026028836196e-117); } while( rr[0]>9.223372036854774784e+28 ){ exp += 10; dekkerMul2(rr, 1.0e-10, -3.6432197315497741579e-27); } while( rr[0]>9.223372036854774784e+18 ){ exp += 1; dekkerMul2(rr, 1.0e-01, -5.5511151231257827021e-18); } }else{ while( rr[0]<9.223372036854774784e-83 ){ exp -= 100; dekkerMul2(rr, 1.0e+100, -1.5902891109759918046e+83); } while( rr[0]<9.223372036854774784e+07 ){ exp -= 10; dekkerMul2(rr, 1.0e+10, 0.0); } while( rr[0]<9.22337203685477478e+17 ){ exp -= 1; dekkerMul2(rr, 1.0e+01, 0.0); } } v = rr[1]<0.0 ? (u64)rr[0]-(u64)(-rr[1]) : (u64)rr[0]+(u64)rr[1]; /* Extract significant digits. */ i = sizeof(p->zBuf)-1; assert( v>0 ); while( v ){ p->zBuf[i--] = (v%10) + '0'; v /= 10; } assert( i>=0 && i<sizeof(p->zBuf)-1 ); p->n = sizeof(p->zBuf) - 1 - i; |
︙ | ︙ |
Changes to src/vdbeaux.c.
︙ | ︙ | |||
4508 4509 4510 4511 4512 4513 4514 | } /* The following two functions are used only within testcase() to prove ** test coverage. These functions do no exist for production builds. ** We must use separate SQLITE_NOINLINE functions here, since otherwise ** optimizer code movement causes gcov to become very confused. */ | | < < < < < < < < < < < | 4508 4509 4510 4511 4512 4513 4514 4515 4516 4517 4518 4519 4520 4521 4522 4523 4524 4525 4526 4527 4528 4529 4530 4531 4532 4533 4534 4535 4536 | } /* The following two functions are used only within testcase() to prove ** test coverage. These functions do no exist for production builds. ** We must use separate SQLITE_NOINLINE functions here, since otherwise ** optimizer code movement causes gcov to become very confused. */ #if defined(SQLITE_COVERAGE_TEST) || defined(SQLITE_DEBUG) static int SQLITE_NOINLINE doubleLt(double a, double b){ return a<b; } static int SQLITE_NOINLINE doubleEq(double a, double b){ return a==b; } #endif /* ** Do a comparison between a 64-bit signed integer and a 64-bit floating-point ** number. Return negative, zero, or positive if the first (i64) is less than, ** equal to, or greater than the second (double). */ int sqlite3IntFloatCompare(i64 i, double r){ if( sqlite3IsNaN(r) ){ /* SQLite considers NaN to be a NULL. And all integer values are greater ** than NULL */ return 1; }else{ i64 y; if( r<-9223372036854775808.0 ) return +1; if( r>=9223372036854775808.0 ) return -1; y = (i64)r; if( i<y ) return -1; if( i>y ) return +1; |
︙ | ︙ |
Changes to test/atof1.test.
︙ | ︙ | |||
11 12 13 14 15 16 17 | # # Tests of the sqlite3AtoF() function. # set testdir [file dirname $argv0] source $testdir/tester.tcl | | | 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | # # Tests of the sqlite3AtoF() function. # set testdir [file dirname $argv0] source $testdir/tester.tcl set mxpow 35 expr srand(1) for {set i 1} {$i<20000} {incr i} { set pow [expr {int((rand()-0.5)*$mxpow)}] set x [expr {pow((rand()-0.5)*2*rand(),$pow)}] set xf [format %.32e $x] # Verify that text->real conversions get exactly same ieee754 floating- |
︙ | ︙ |
Changes to test/cast.test.
︙ | ︙ | |||
258 259 260 261 262 263 264 | } 9223372036854774800 do_test cast-3.12 { execsql {SELECT CAST('9223372036854774800' AS numeric)} } 9223372036854774800 do_realnum_test cast-3.13 { execsql {SELECT CAST('9223372036854774800' AS real)} } 9.22337203685477e+18 | < | | | < < | | | < < | | | | | | < | 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 | } 9223372036854774800 do_test cast-3.12 { execsql {SELECT CAST('9223372036854774800' AS numeric)} } 9223372036854774800 do_realnum_test cast-3.13 { execsql {SELECT CAST('9223372036854774800' AS real)} } 9.22337203685477e+18 do_test cast-3.14 { execsql {SELECT CAST(CAST('9223372036854774800' AS real) AS integer)} } 9223372036854774784 do_test cast-3.15 { execsql {SELECT CAST('-9223372036854774800' AS integer)} } -9223372036854774800 do_test cast-3.16 { execsql {SELECT CAST('-9223372036854774800' AS numeric)} } -9223372036854774800 do_realnum_test cast-3.17 { execsql {SELECT CAST('-9223372036854774800' AS real)} } -9.22337203685477e+18 do_test cast-3.18 { execsql {SELECT CAST(CAST('-9223372036854774800' AS real) AS integer)} } -9223372036854774784 if {[db eval {PRAGMA encoding}]=="UTF-8"} { do_test cast-3.21 { execsql {SELECT CAST(x'39323233333732303336383534373734383030' AS integer)} } 9223372036854774800 do_test cast-3.22 { execsql {SELECT CAST(x'39323233333732303336383534373734383030' AS numeric)} } 9223372036854774800 do_realnum_test cast-3.23 { execsql {SELECT CAST(x'39323233333732303336383534373734383030' AS real)} } 9.22337203685477e+18 do_test cast-3.24 { execsql { SELECT CAST(CAST(x'39323233333732303336383534373734383030' AS real) AS integer) } } 9223372036854774784 } do_test cast-3.31 { execsql {SELECT CAST(NULL AS numeric)} } {{}} # Test to see if it is possible to trick SQLite into reading past # the end of a blob when converting it to a number. |
︙ | ︙ |
Changes to test/fp-speed-1.c.
︙ | ︙ | |||
8 9 10 11 12 13 14 | ** gcc -Os -c sqlite3.c ** gcc -I. -Os test/fp-speed-1.c sqlite3.o -ldl -lm -lpthread ** ** To run the test: ** ** time ./a.out 0 10000000 <-- standard library ** time ./a.out 1 10000000 <-- SQLite | < | 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | ** gcc -Os -c sqlite3.c ** gcc -I. -Os test/fp-speed-1.c sqlite3.o -ldl -lm -lpthread ** ** To run the test: ** ** time ./a.out 0 10000000 <-- standard library ** time ./a.out 1 10000000 <-- SQLite */ static double aVal[] = { -1.0163830486285643089e+063, +0.0049243807391586981e-019, +7.3818732407343994867e-095, +7.0678595219225717143e+000, +9.2807266319850025655e+120, |
︙ | ︙ | |||
146 147 148 149 150 151 152 | case 1: { printf("Doing %d calls to sqlite3_snprintf()\n", cnt); for(i=0; i<cnt; i++){ sqlite3_snprintf(sizeof(zBuf), zBuf, "%!.26g", aVal[i%NN]); } break; } | < < < < < < < < < | 145 146 147 148 149 150 151 152 153 154 | case 1: { printf("Doing %d calls to sqlite3_snprintf()\n", cnt); for(i=0; i<cnt; i++){ sqlite3_snprintf(sizeof(zBuf), zBuf, "%!.26g", aVal[i%NN]); } break; } } return 0; } |
Changes to test/func.test.
︙ | ︙ | |||
257 258 259 260 261 262 263 | do_test func-4.15 { execsql {SELECT typeof(round(5.1));} } {real} do_test func-4.16 { catchsql {SELECT round(b,2.0) FROM t1 ORDER BY b} } {0 {-2.0 1.23 2.0}} # Verify some values reported on the mailing list. | < < < | 257 258 259 260 261 262 263 264 265 266 267 268 269 270 | do_test func-4.15 { execsql {SELECT typeof(round(5.1));} } {real} do_test func-4.16 { catchsql {SELECT round(b,2.0) FROM t1 ORDER BY b} } {0 {-2.0 1.23 2.0}} # Verify some values reported on the mailing list. for {set i 1} {$i<999} {incr i} { set x1 [expr 40222.5 + $i] set x2 [expr 40223.0 + $i] do_test func-4.17.$i { execsql {SELECT round($x1);} } $x2 } |
︙ | ︙ |
Changes to test/func4.test.
︙ | ︙ | |||
33 34 35 36 37 38 39 | # It is true on the exact same platform with -O0. Both results seem # reasonable, so we'll just very the expectation accordingly. # set highPrecision(3) [expr \ {[db eval {SELECT toreal(9007199254740992 + 1);}] eq {{}}}] if {!$highPrecision(1) || !$highPrecision(2) || !$highPrecision(3)} { | | | 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 | # It is true on the exact same platform with -O0. Both results seem # reasonable, so we'll just very the expectation accordingly. # set highPrecision(3) [expr \ {[db eval {SELECT toreal(9007199254740992 + 1);}] eq {{}}}] if {!$highPrecision(1) || !$highPrecision(2) || !$highPrecision(3)} { puts "NOTICE:\ highPrecision: $highPrecision(1) $highPrecision(2) $highPrecision(3)" } do_execsql_test func4-1.1 { SELECT tointeger(NULL); } {{}} do_execsql_test func4-1.2 { |
︙ | ︙ |
Changes to test/speedtest1.c.
︙ | ︙ | |||
17 18 19 20 21 22 23 | " --incrvacuum Enable incremenatal vacuum mode\n" " --journal M Set the journal_mode to M\n" " --key KEY Set the encryption key to KEY\n" " --lookaside N SZ Configure lookaside for N slots of SZ bytes each\n" " --memdb Use an in-memory database\n" " --mmap SZ MMAP the first SZ bytes of the database file\n" " --multithread Set multithreaded mode\n" | < | 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | " --incrvacuum Enable incremenatal vacuum mode\n" " --journal M Set the journal_mode to M\n" " --key KEY Set the encryption key to KEY\n" " --lookaside N SZ Configure lookaside for N slots of SZ bytes each\n" " --memdb Use an in-memory database\n" " --mmap SZ MMAP the first SZ bytes of the database file\n" " --multithread Set multithreaded mode\n" " --nomemstat Disable memory statistics\n" " --nomutex Open db with SQLITE_OPEN_NOMUTEX\n" " --nosync Set PRAGMA synchronous=OFF\n" " --notnull Add NOT NULL constraints to table columns\n" " --output FILE Store SQL output in FILE\n" " --pagesize N Set the page size to N\n" " --pcache N SZ Configure N pages of pagecache each of size SZ bytes\n" |
︙ | ︙ | |||
2273 2274 2275 2276 2277 2278 2279 | void *pHeap = 0; /* Allocated heap space */ void *pLook = 0; /* Allocated lookaside space */ void *pPCache = 0; /* Allocated storage for pcache */ int iCur, iHi; /* Stats values, current and "highwater" */ int i; /* Loop counter */ int rc; /* API return code */ | < | 2272 2273 2274 2275 2276 2277 2278 2279 2280 2281 2282 2283 2284 2285 | void *pHeap = 0; /* Allocated heap space */ void *pLook = 0; /* Allocated lookaside space */ void *pPCache = 0; /* Allocated storage for pcache */ int iCur, iHi; /* Stats values, current and "highwater" */ int i; /* Loop counter */ int rc; /* API return code */ #ifdef SQLITE_SPEEDTEST1_WASM /* Resetting all state is important for the WASM build, which may ** call main() multiple times. */ memset(&g, 0, sizeof(g)); iTestNumber = 0; #endif |
︙ | ︙ | |||
2331 2332 2333 2334 2335 2336 2337 | doIncrvac = 1; }else if( strcmp(z,"journal")==0 ){ ARGC_VALUE_CHECK(1); zJMode = argv[++i]; }else if( strcmp(z,"key")==0 ){ ARGC_VALUE_CHECK(1); zKey = argv[++i]; | < < < < | 2329 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340 2341 2342 2343 2344 2345 2346 2347 2348 2349 2350 2351 2352 2353 2354 2355 2356 2357 2358 2359 2360 | doIncrvac = 1; }else if( strcmp(z,"journal")==0 ){ ARGC_VALUE_CHECK(1); zJMode = argv[++i]; }else if( strcmp(z,"key")==0 ){ ARGC_VALUE_CHECK(1); zKey = argv[++i]; }else if( strcmp(z,"lookaside")==0 ){ ARGC_VALUE_CHECK(2); nLook = integerValue(argv[i+1]); szLook = integerValue(argv[i+2]); i += 2; }else if( strcmp(z,"memdb")==0 ){ memDb = 1; #if SQLITE_VERSION_NUMBER>=3006000 }else if( strcmp(z,"multithread")==0 ){ sqlite3_config(SQLITE_CONFIG_MULTITHREAD); }else if( strcmp(z,"nomemstat")==0 ){ sqlite3_config(SQLITE_CONFIG_MEMSTATUS, 0); #endif #if SQLITE_VERSION_NUMBER>=3007017 }else if( strcmp(z, "mmap")==0 ){ ARGC_VALUE_CHECK(1); mmapSize = integerValue(argv[++i]); #endif }else if( strcmp(z,"nomutex")==0 ){ openFlags |= SQLITE_OPEN_NOMUTEX; }else if( strcmp(z,"nosync")==0 ){ noSync = 1; }else if( strcmp(z,"notnull")==0 ){ g.zNN = "NOT NULL"; }else if( strcmp(z,"output")==0 ){ |
︙ | ︙ | |||
2525 2526 2527 2528 2529 2530 2531 | #if SQLITE_VERSION_NUMBER>=3006001 if( nLook>0 && szLook>0 ){ pLook = malloc( nLook*szLook ); rc = sqlite3_db_config(g.db, SQLITE_DBCONFIG_LOOKASIDE,pLook,szLook,nLook); if( rc ) fatal_error("lookaside configuration failed: %d\n", rc); } #endif | < < < < < | 2519 2520 2521 2522 2523 2524 2525 2526 2527 2528 2529 2530 2531 2532 | #if SQLITE_VERSION_NUMBER>=3006001 if( nLook>0 && szLook>0 ){ pLook = malloc( nLook*szLook ); rc = sqlite3_db_config(g.db, SQLITE_DBCONFIG_LOOKASIDE,pLook,szLook,nLook); if( rc ) fatal_error("lookaside configuration failed: %d\n", rc); } #endif if( g.nReserve>0 ){ sqlite3_file_control(g.db, 0, SQLITE_FCNTL_RESERVE_BYTES, &g.nReserve); } if( g.stmtScanStatus ){ sqlite3_db_config(g.db, SQLITE_DBCONFIG_STMT_SCANSTATUS, 1, 0); } |
︙ | ︙ |
Changes to test/testrunner_data.tcl.
︙ | ︙ | |||
199 200 201 202 203 204 205 | -DSQLITE_ENABLE_FTS4=1 -DSQLITE_ENABLE_RTREE=1 -DSQLITE_ENABLE_STAT4 -DSQLITE_ENABLE_RBU -DSQLITE_MAX_ATTACHED=125 -DSQLITE_MAX_MMAP_SIZE=12884901888 -DSQLITE_ENABLE_SORTER_MMAP=1 | < | 199 200 201 202 203 204 205 206 207 208 209 210 211 212 | -DSQLITE_ENABLE_FTS4=1 -DSQLITE_ENABLE_RTREE=1 -DSQLITE_ENABLE_STAT4 -DSQLITE_ENABLE_RBU -DSQLITE_MAX_ATTACHED=125 -DSQLITE_MAX_MMAP_SIZE=12884901888 -DSQLITE_ENABLE_SORTER_MMAP=1 --enable-session } set build(Device-One) { -O2 -DSQLITE_DEBUG=1 -DSQLITE_DEFAULT_AUTOVACUUM=1 -DSQLITE_DEFAULT_CACHE_SIZE=64 |
︙ | ︙ | |||
339 340 341 342 343 344 345 | -DSQLITE_OMIT_LOOKASIDE=1 } set build(Valgrind) { -DSQLITE_ENABLE_STAT4 -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_RTREE -DSQLITE_ENABLE_HIDDEN_COLUMNS | < | 338 339 340 341 342 343 344 345 346 347 348 349 350 351 | -DSQLITE_OMIT_LOOKASIDE=1 } set build(Valgrind) { -DSQLITE_ENABLE_STAT4 -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_RTREE -DSQLITE_ENABLE_HIDDEN_COLUMNS -DCONFIG_SLOWDOWN_FACTOR=8.0 } set build(Windows-Memdebug) { MEMDEBUG=1 DEBUG=3 } |
︙ | ︙ |
Changes to tool/speed-check.sh.
︙ | ︙ | |||
95 96 97 98 99 100 101 | ;; --cachesize) shift; SPEEDTEST_OPTS="$SPEEDTEST_OPTS --cachesize $1" ;; --stmtcache) shift; SPEEDTEST_OPTS="$SPEEDTEST_OPTS --stmtcache $1" ;; | < < < | 95 96 97 98 99 100 101 102 103 104 105 106 107 108 | ;; --cachesize) shift; SPEEDTEST_OPTS="$SPEEDTEST_OPTS --cachesize $1" ;; --stmtcache) shift; SPEEDTEST_OPTS="$SPEEDTEST_OPTS --stmtcache $1" ;; --checkpoint) SPEEDTEST_OPTS="$SPEEDTEST_OPTS --checkpoint" ;; --explain) doExplain=1 ;; --vdbeprofile) |
︙ | ︙ |