Skip to content

Commit

Permalink
An idea for improving accuracy of fp-to-decimal conversion for system…
Browse files Browse the repository at this point in the history
…s that

do not have "long double".  Does not quite work.  Retained only for
documentation purposes.

FossilOrigin-Name: 702243333843219f8904ee0fd12283080d6c6b3fc1ffb36c534cdefb3563c00d
  • Loading branch information
drh committed Jul 3, 2023
1 parent fecdff4 commit c27bda0
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 26 deletions.
15 changes: 9 additions & 6 deletions manifest
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
C This\scheck-in\sadds\sthe\suse\sof\s"long\sdouble"\sto\ssqlite3FpDecode()\swhich\swhen\nrun\son\sx86\susing\sa\scompiler\sthat\stranslates\s"long\sdouble"\sinto\sbinary80,\ncauses\sall\slegacy\stests\sto\spass.\s\sBut\son\sa\ssystem\swhere\s"long\sdouble"\sis\sjust\nan\salias\sfor\s"double",\ssome\sof\sthe\stests\sare\sstill\sfailing.
D 2023-07-01T20:21:27.087
C An\sidea\sfor\simproving\saccuracy\sof\sfp-to-decimal\sconversion\sfor\ssystems\sthat\ndo\snot\shave\s"long\sdouble".\s\sDoes\snot\squite\swork.\s\sRetained\sonly\sfor\ndocumentation\spurposes.
D 2023-07-03T00:40:37.359
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
Expand Down Expand Up @@ -705,7 +705,7 @@ F src/trigger.c ad6ab9452715fa9a8075442e15196022275b414b9141b566af8cdb7a1605f2b0
F src/update.c 0aa36561167a7c40d01163238c297297962f31a15a8d742216b3c37cdf25f731
F src/upsert.c 5303dc6c518fa7d4b280ec65170f465c7a70b7ac2b22491598f6d0b4875b3145
F src/utf.c ee39565f0843775cc2c81135751ddd93eceb91a673ea2c57f61c76f288b041a0
F src/util.c d68692390be083744bd0dfafc797472b0d304743040220e18b93bc9bad8c8d6e
F src/util.c 12741de9969af5134488b7c89a97ecc22144f93f62c6255f797abb9b3121608a
F src/vacuum.c 604fcdaebe76f3497c855afcbf91b8fa5046b32de3045bab89cc008d68e40104
F src/vdbe.c 74282a947234513872a83b0bab1b8c644ece64b3e27b053ef17677c8ff9c81e0
F src/vdbe.h 41485521f68e9437fdb7ec4a90f9d86ab294e9bb8281e33b235915e29122cfc0
Expand Down Expand Up @@ -2041,8 +2041,11 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
P 07eab52e0801bb0e4743b304a06ad16e18cdf8eaa18c0faf8d47a1f5d8576ea0
R c4051b06b266c29a490b4cec354913fc
P ce06982f880339cf46704e95c907249827c3e44af2b9420005200ca8abd3f371
R ae7783ab51788007ac81a8600cb6b0a8
T *branch * fp-to-decimal-branch1
T *sym-fp-to-decimal-branch1 *
T -sym-fp-to-decimal-refactor *
U drh
Z 95eef79511e3e10371b4b76031a5a06d
Z 0f216e6dd96bccb8187eb2a64c983082
# Remove this line to create a well-formed Fossil manifest.
2 changes: 1 addition & 1 deletion manifest.uuid
Original file line number Diff line number Diff line change
@@ -1 +1 @@
ce06982f880339cf46704e95c907249827c3e44af2b9420005200ca8abd3f371
702243333843219f8904ee0fd12283080d6c6b3fc1ffb36c534cdefb3563c00d
64 changes: 45 additions & 19 deletions src/util.c
Original file line number Diff line number Diff line change
Expand Up @@ -937,16 +937,18 @@ int sqlite3Atoi(const char *z){
** decimal point if n is negative. No rounding is performed if
** n is zero.
*/
void sqlite3FpDecode(FpDecode *p, double rr, int iRound, int mxRound){
void sqlite3FpDecode(FpDecode *p, double r, int iRound, int mxRound){
int i;
u64 v;
int e, exp = 0;
long double r;
p->isSpecial = 0;
if( rr<0.0 ){

/* Convert negative numbers to positive. Deal with Infinity, 0.0, and
** NaN. */
if( r<0.0 ){
p->sign = '-';
rr = -rr;
}else if( rr==0.0 ){
r = -r;
}else if( r==0.0 ){
p->sign = '+';
p->n = 1;
p->iDP = 1;
Expand All @@ -955,31 +957,55 @@ void sqlite3FpDecode(FpDecode *p, double rr, int iRound, int mxRound){
}else{
p->sign = '+';
}
memcpy(&v,&rr,8);
memcpy(&v,&r,8);
e = v>>52;
if( (e&0x7ff)==0x7ff ){
p->isSpecial = 1 + (v!=0x7ff0000000000000L);
p->n = 0;
p->iDP = 0;
return;
}
r = rr;

/* At this point, r is positive (non-zero) and is not Inf or NaN.
** The strategy is to multiple or divide r by powers of 10 until
** it is in between 1.0e+17 and 1.0e+19. Then convert r into
** an unsigned 64-bit integer v, and extract digits from v.
/* Multiply r by powers of ten until it lands somewhere in between
** 1.0e+19 and 1.0e+17.
*/
if( r>=1.0e+19 ){
while( r>=1.0e+119L ){ exp+=100; r *= 1.0e-100L; }
while( r>=1.0e+29L ){ exp+=10; r *= 1.0e-10L; }
while( r>=1.0e+19L ){ exp++; r *= 1.0e-1L; }
if( sizeof(long double)>8
|| (v & 0x0000000000ffffffLL)==0
|| (v & 0xffffffffff000000LL)==0
){
long double rr = r;
if( rr>=1.0e+19 ){
while( rr>=1.0e+119L ){ exp+=100; rr *= 1.0e-100L; }
while( rr>=1.0e+29L ){ exp+=10; rr *= 1.0e-10L; }
while( rr>=1.0e+19L ){ exp++; rr *= 1.0e-1L; }
}else{
while( rr<1.0e-97L ){ exp-=100; rr *= 1.0e+100L; }
while( rr<1.0e+07L ){ exp-=10; rr *= 1.0e+10L; }
while( rr<1.0e+17L ){ exp--; rr *= 1.0e+1L; }
}
v = (u64)rr;
}else{
while( r<1.0e-97L ){ exp-=100; r *= 1.0e+100L; }
while( r<1.0e+07L ){ exp-=10; r *= 1.0e+10L; }
while( r<1.0e+17L ){ exp--; r *= 1.0e+1L; }
double r2, r3;
v &= 0xffffffffff000000LL;
memcpy(&r2, &v, 8);
assert( r2<r );
assert( r2>0.0 );
r3 = r - r2;
assert( r3>0.0 );
if( r2>=1.0e+19 ){
while( r2>=1.0e+119L ){ exp+=100; r2 *= 1.0e-100; r3 *= 1.0e-100; }
while( r2>=1.0e+29L ){ exp+=10; r2 *= 1.0e-10; r3 *= 1.0e-10; }
while( r2>=1.0e+19L ){ exp++; r2 *= 1.0e-1; r3 *= 1.0e-1; }
}else{
while( r2<1.0e-97L ){ exp-=100; r2 *= 1.0e+100; r3 *= 1.0e+100; }
while( r2<1.0e+07L ){ exp-=10; r2 *= 1.0e+10; r3 *= 1.0e+10; }
while( r2<1.0e+17L ){ exp--; r2 *= 1.0e+1; r3 *= 1.0e+1; }
}
v = (u64)(r2+r3);
}
v = (u64)r;


/* Extract significant digits. */
i = sizeof(p->z)-1;
while( v ){ p->z[i--] = (v%10) + '0'; v /= 10; }
p->n = sizeof(p->z) - 1 - i;
Expand Down

0 comments on commit c27bda0

Please sign in to comment.