/ Changes On Branch floating-point-conversions
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Changes In Branch floating-point-conversions Excluding Merge-Ins

This is equivalent to a diff from 699b792c to 0f706acf

2012-06-21
15:22
Merge changes to trunk that ensure that floating point values are exactly preserved on a round-trip through ".dump". (check-in: 4cebd607 user: drh tags: trunk)
15:02
Disable the atof1.test module when compiling on MSVC. (Closed-Leaf check-in: 0f706acf user: drh tags: floating-point-conversions)
2012-06-19
06:35
Add tests to check that the "unicode61" and "icu" tokenizers both identify white-space codepoints outside the ASCII range. (check-in: bfb2d473 user: dan tags: trunk)
04:36
Move variable declaration to fix compilation with MSVC. (check-in: d45f7a01 user: mistachkin tags: floating-point-conversions)
03:11
Improved accuracy on text-to-real and real-to-text conversions. Most conversions now round-trip correctly. Still need to fix some corner cases. (check-in: 8ecffca9 user: drh tags: floating-point-conversions)
00:45
Improved rounding accuracy on text-to-float conversions. (check-in: 699b792c user: drh tags: trunk)
2012-06-18
20:52
Fix a problem with identifying white-space characters outside of the ascii range in the ICU tokenizer. (check-in: 892b7411 user: dan tags: trunk)

Changes to src/func.c.

   859    859   ** "NULL".  Otherwise, the argument is enclosed in single quotes with
   860    860   ** single-quote escapes.
   861    861   */
   862    862   static void quoteFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
   863    863     assert( argc==1 );
   864    864     UNUSED_PARAMETER(argc);
   865    865     switch( sqlite3_value_type(argv[0]) ){
   866         -    case SQLITE_INTEGER:
   867    866       case SQLITE_FLOAT: {
          867  +      double r1, r2;
          868  +      char zBuf[50];
          869  +      r1 = sqlite3_value_double(argv[0]);
          870  +      sqlite3_snprintf(sizeof(zBuf), zBuf, "%!.15g", r1);
          871  +      sqlite3AtoF(zBuf, &r2, 20, SQLITE_UTF8);
          872  +      if( r1!=r2 ){
          873  +        sqlite3_snprintf(sizeof(zBuf), zBuf, "%!.20e", r1);
          874  +      }
          875  +      sqlite3_result_text(context, zBuf, -1, SQLITE_TRANSIENT);
          876  +      break;
          877  +    }
          878  +    case SQLITE_INTEGER: {
   868    879         sqlite3_result_value(context, argv[0]);
   869    880         break;
   870    881       }
   871    882       case SQLITE_BLOB: {
   872    883         char *zText = 0;
   873    884         char const *zBlob = sqlite3_value_blob(argv[0]);
   874    885         int nBlob = sqlite3_value_bytes(argv[0]);

Changes to src/printf.c.

   120    120   ** The counter *cnt is incremented each time.  After counter exceeds
   121    121   ** 16 (the number of significant digits in a 64-bit float) '0' is
   122    122   ** always returned.
   123    123   */
   124    124   static char et_getdigit(LONGDOUBLE_TYPE *val, int *cnt){
   125    125     int digit;
   126    126     LONGDOUBLE_TYPE d;
   127         -  if( (*cnt)++ >= 16 ) return '0';
          127  +  if( (*cnt)<=0 ) return '0';
          128  +  (*cnt)--;
   128    129     digit = (int)*val;
   129    130     d = digit;
   130    131     digit += '0';
   131    132     *val = (*val - d)*10.0;
   132    133     return (char)digit;
   133    134   }
   134    135   #endif /* SQLITE_OMIT_FLOATING_POINT */
................................................................................
   424    425           exp = 0;
   425    426           if( sqlite3IsNaN((double)realvalue) ){
   426    427             bufpt = "NaN";
   427    428             length = 3;
   428    429             break;
   429    430           }
   430    431           if( realvalue>0.0 ){
   431         -          while( realvalue>=1e32 && exp<=350 ){ realvalue *= 1e-32; exp+=32; }
   432         -          while( realvalue>=1e8 && exp<=350 ){ realvalue *= 1e-8; exp+=8; }
   433         -          while( realvalue>=10.0 && exp<=350 ){ realvalue *= 0.1; exp++; }
          432  +          LONGDOUBLE_TYPE scale = 1.0;
          433  +          while( realvalue>=1e100*scale && exp<=350 ){ scale *= 1e100;exp+=100;}
          434  +          while( realvalue>=1e64*scale && exp<=350 ){ scale *= 1e64; exp+=64; }
          435  +          while( realvalue>=1e8*scale && exp<=350 ){ scale *= 1e8; exp+=8; }
          436  +          while( realvalue>=10.0*scale && exp<=350 ){ scale *= 10.0; exp++; }
          437  +          realvalue /= scale;
   434    438             while( realvalue<1e-8 ){ realvalue *= 1e8; exp-=8; }
   435    439             while( realvalue<1.0 ){ realvalue *= 10.0; exp--; }
   436    440             if( exp>350 ){
   437    441               if( prefix=='-' ){
   438    442                 bufpt = "-Inf";
   439    443               }else if( prefix=='+' ){
   440    444                 bufpt = "+Inf";
................................................................................
   459    463             if( exp<-4 || exp>precision ){
   460    464               xtype = etEXP;
   461    465             }else{
   462    466               precision = precision - exp;
   463    467               xtype = etFLOAT;
   464    468             }
   465    469           }else{
   466         -          flag_rtz = 0;
          470  +          flag_rtz = flag_altform2;
   467    471           }
   468    472           if( xtype==etEXP ){
   469    473             e2 = 0;
   470    474           }else{
   471    475             e2 = exp;
   472    476           }
   473    477           if( e2+precision+width > etBUFSIZE - 15 ){
................................................................................
   474    478             bufpt = zExtra = sqlite3Malloc( e2+precision+width+15 );
   475    479             if( bufpt==0 ){
   476    480               pAccum->mallocFailed = 1;
   477    481               return;
   478    482             }
   479    483           }
   480    484           zOut = bufpt;
   481         -        nsd = 0;
          485  +        nsd = 16 + flag_altform2*10;
   482    486           flag_dp = (precision>0 ?1:0) | flag_alternateform | flag_altform2;
   483    487           /* The sign in front of the number */
   484    488           if( prefix ){
   485    489             *(bufpt++) = prefix;
   486    490           }
   487    491           /* Digits prior to the decimal point */
   488    492           if( e2<0 ){

Changes to src/test_config.c.

   612    612     LINKVAR( MAX_DEFAULT_PAGE_SIZE );
   613    613   
   614    614     {
   615    615       static const int cv_TEMP_STORE = SQLITE_TEMP_STORE;
   616    616       Tcl_LinkVar(interp, "TEMP_STORE", (char *)&(cv_TEMP_STORE),
   617    617                   TCL_LINK_INT | TCL_LINK_READ_ONLY);
   618    618     }
          619  +
          620  +#ifdef _MSC_VER
          621  +  {
          622  +    static const int cv__MSC_VER = 1;
          623  +    Tcl_LinkVar(interp, "_MSC_VER", (char *)&(cv__MSC_VER),
          624  +                TCL_LINK_INT | TCL_LINK_READ_ONLY);
          625  +  }
          626  +#endif
          627  +#ifdef __GNUC__
          628  +  {
          629  +    static const int cv___GNUC__ = 1;
          630  +    Tcl_LinkVar(interp, "__GNUC__", (char *)&(cv___GNUC__),
          631  +                TCL_LINK_INT | TCL_LINK_READ_ONLY);
          632  +  }
          633  +#endif
   619    634   }
   620    635   
   621    636   
   622    637   /*
   623    638   ** Register commands with the TCL interpreter.
   624    639   */
   625    640   int Sqliteconfig_Init(Tcl_Interp *interp){
   626    641     set_options(interp);
   627    642     return TCL_OK;
   628    643   }

Changes to test/atof1.test.

    10     10   #***********************************************************************
    11     11   # 
    12     12   # Tests of the sqlite3AtoF() function.
    13     13   #
    14     14   
    15     15   set testdir [file dirname $argv0]
    16     16   source $testdir/tester.tcl
           17  +
           18  +if {![info exists __GNUC__]} {
           19  +  finish_test
           20  +  return
           21  +}
    17     22   
    18     23   expr srand(1)
    19         -for {set i 1} {$i<10000} {incr i} {
    20         -  do_test 1.$i {
    21         -    set pow [expr {int((rand()-0.5)*100)}]
    22         -    set x [expr {pow((rand()-0.5)*2*rand(),$pow)}]
    23         -    set xf [format %.45e $x]
           24  +for {set i 1} {$i<20000} {incr i} {
           25  +  set pow [expr {int((rand()-0.5)*100)}]
           26  +  set x [expr {pow((rand()-0.5)*2*rand(),$pow)}]
           27  +  set xf [format %.32e $x]
           28  +
           29  +  # Verify that text->real conversions get exactly same ieee754 floating-
           30  +  # point value in SQLite as they do in TCL.
           31  +  #
           32  +  do_test atof1-1.$i.1 {
    24     33       set y [db eval "SELECT $xf=\$x"]
    25     34       if {!$y} {
    26     35         puts -nonewline \173[db eval "SELECT real2hex($xf), real2hex(\$x)"]\175
    27     36         db eval "SELECT $xf+0.0 AS a, \$x AS b" {
    28     37           puts [format "\n%.60e\n%.60e\n%.60e" $x $a $b]
    29     38         }
    30     39       }
           40  +    set y
           41  +  } {1}
           42  +
           43  +  # Verify that round-trip real->text->real conversions using the quote()
           44  +  # function preserve the bits of the numeric value exactly.
           45  +  #
           46  +  do_test atof1-1.$i.2 {
           47  +    set y [db eval {SELECT $x=CAST(quote($x) AS real)}]
           48  +    if {!$y} {
           49  +      db eval {SELECT real2hex($x) a, real2hex(CAST(quote($x) AS real)) b} {}
           50  +      puts "\nIN:    $a $xf"
           51  +      puts [format {QUOTE: %16s %s} {} [db eval {SELECT quote($x)}]]
           52  +      db eval {SELECT CAST(quote($x) AS real) c} {}
           53  +      puts "OUT:   $b [format %.32e $c]"
           54  +    }
    31     55       set y
    32     56     } {1}
    33     57   }
    34     58   
    35     59   
    36     60   finish_test

Changes to test/date.test.

   147    147   datetest 2.51 {datetime('2003-10-22 12:24','nonsense')} NULL
   148    148   
   149    149   datetest 3.1 {strftime('%d','2003-10-31 12:34:56.432')} 31
   150    150   datetest 3.2.1 {strftime('pre%fpost','2003-10-31 12:34:56.432')} pre56.432post
   151    151   datetest 3.2.2 {strftime('%f','2003-10-31 12:34:59.9999999')} 59.999
   152    152   datetest 3.3 {strftime('%H','2003-10-31 12:34:56.432')} 12
   153    153   datetest 3.4 {strftime('%j','2003-10-31 12:34:56.432')} 304
   154         -datetest 3.5 {strftime('%J','2003-10-31 12:34:56.432')} 2452944.02426426
          154  +datetest 3.5 {strftime('%J','2003-10-31 12:34:56.432')} 2452944.024264259
   155    155   datetest 3.6 {strftime('%m','2003-10-31 12:34:56.432')} 10
   156    156   datetest 3.7 {strftime('%M','2003-10-31 12:34:56.432')} 34
   157    157   datetest 3.8.1 {strftime('%s','2003-10-31 12:34:56.432')} 1067603696
   158    158   datetest 3.8.2 {strftime('%s','2038-01-19 03:14:07')} 2147483647
   159    159   datetest 3.8.3 {strftime('%s','2038-01-19 03:14:08')} 2147483648
   160    160   datetest 3.8.4 {strftime('%s','2201-04-09 12:00:00')} 7298164800
   161    161   datetest 3.8.5 {strftime('%s','9999-12-31 23:59:59')} 253402300799

Changes to test/func.test.

   308    308     do_test func-4.36 {
   309    309       execsql {SELECT round(99999999999994.5);}
   310    310     } {99999999999995.0}
   311    311     do_test func-4.37 {
   312    312       execsql {SELECT round(9999999999999.55,1);}
   313    313     } {9999999999999.6}
   314    314     do_test func-4.38 {
   315         -    execsql {SELECT round(9999999999999.555,2);}
          315  +    execsql {SELECT round(9999999999999.556,2);}
   316    316     } {9999999999999.56}
   317    317   }
   318    318   
   319    319   # Test the upper() and lower() functions
   320    320   #
   321    321   do_test func-5.1 {
   322    322     execsql {SELECT upper(t1) FROM tbl1}