/ Check-in [a3f7614b]
Login

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

Overview
Comment:A different approach to handling integer/float comparisons. This seems to work better on systems where "long double" and "double" are the same type, but still needs refinement and testing.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | int-float-precision
Files: files | file ages | folders
SHA1: a3f7614b2095fbc1eca54801b2da88f85f294ec5
User & Date: drh 2015-11-06 14:59:07
Context
2015-11-06
17:59
Merge the fixes and tests for the ieee754 extension. Closed-Leaf check-in: 7a9988d3 user: drh tags: int-float-precision
14:59
A different approach to handling integer/float comparisons. This seems to work better on systems where "long double" and "double" are the same type, but still needs refinement and testing. check-in: a3f7614b user: drh tags: int-float-precision
04:14
More test cases for indexes on large numeric values. check-in: c220741a user: drh tags: int-float-precision
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/test1.c.

  7035   7035   #ifdef SQLITE_ENABLE_STMT_SCANSTATUS
  7036   7036        { "sqlite3_stmt_scanstatus",       test_stmt_scanstatus,   0 },
  7037   7037        { "sqlite3_stmt_scanstatus_reset", test_stmt_scanstatus_reset,   0 },
  7038   7038   #endif
  7039   7039   
  7040   7040     };
  7041   7041     static int bitmask_size = sizeof(Bitmask)*8;
         7042  +  static int longdouble_size = sizeof(LONGDOUBLE_TYPE);
  7042   7043     int i;
  7043   7044     extern int sqlite3_sync_count, sqlite3_fullsync_count;
  7044   7045     extern int sqlite3_opentemp_count;
  7045   7046     extern int sqlite3_like_count;
  7046   7047     extern int sqlite3_xferopt_count;
  7047   7048     extern int sqlite3_pager_readdb_count;
  7048   7049     extern int sqlite3_pager_writedb_count;
................................................................................
  7135   7136         (char*)&sqlite_static_bind_nbyte, TCL_LINK_INT);
  7136   7137     Tcl_LinkVar(interp, "sqlite_temp_directory",
  7137   7138         (char*)&sqlite3_temp_directory, TCL_LINK_STRING);
  7138   7139     Tcl_LinkVar(interp, "sqlite_data_directory",
  7139   7140         (char*)&sqlite3_data_directory, TCL_LINK_STRING);
  7140   7141     Tcl_LinkVar(interp, "bitmask_size",
  7141   7142         (char*)&bitmask_size, TCL_LINK_INT|TCL_LINK_READ_ONLY);
         7143  +  Tcl_LinkVar(interp, "longdouble_size",
         7144  +      (char*)&longdouble_size, TCL_LINK_INT|TCL_LINK_READ_ONLY);
  7142   7145     Tcl_LinkVar(interp, "sqlite_sync_count",
  7143   7146         (char*)&sqlite3_sync_count, TCL_LINK_INT);
  7144   7147     Tcl_LinkVar(interp, "sqlite_fullsync_count",
  7145   7148         (char*)&sqlite3_fullsync_count, TCL_LINK_INT);
  7146   7149   #if defined(SQLITE_ENABLE_FTS3) && defined(SQLITE_TEST)
  7147   7150     Tcl_LinkVar(interp, "sqlite_fts3_enable_parentheses",
  7148   7151         (char*)&sqlite3_fts3_enable_parentheses, TCL_LINK_INT);
  7149   7152   #endif
  7150   7153     return TCL_OK;
  7151   7154   }

Changes to src/vdbeaux.c.

  3630   3630   */
  3631   3631   static SQLITE_NOINLINE int sqlite3BlobCompare(const Mem *pB1, const Mem *pB2){
  3632   3632     int c = memcmp(pB1->z, pB2->z, pB1->n>pB2->n ? pB2->n : pB1->n);
  3633   3633     if( c ) return c;
  3634   3634     return pB1->n - pB2->n;
  3635   3635   }
  3636   3636   
         3637  +/*
         3638  +** Do a comparison between a 64-bit signed integer and a 64-bit floating-point
         3639  +** number.  Return negative, zero, or positive if the first (i64) is less than,
         3640  +** equal to, or greater than the second (double).
         3641  +*/
         3642  +static int sqlite3IntFloatCompare(i64 i, double r){
         3643  +  if( sizeof(LONGDOUBLE_TYPE)>8 ){
         3644  +    LONGDOUBLE_TYPE x = (LONGDOUBLE_TYPE)i;
         3645  +    if( x<r ) return -1;
         3646  +    if( x>r ) return +1;
         3647  +    return 0;
         3648  +  }else{
         3649  +    i64 y;
         3650  +    double s;
         3651  +    if( r<-9223372036854775808.0 ) return +1;
         3652  +    if( r>9223372036854775807.0 ) return -1;
         3653  +    y = (i64)r;
         3654  +    if( i<y ) return -1;
         3655  +    if( i>y ){
         3656  +      if( y==SMALLEST_INT64 && r>0.0 ) return -1;
         3657  +      return +1;
         3658  +    }
         3659  +    s = (double)i;
         3660  +    if( s<r ) return -1;
         3661  +    if( s>r ) return +1;
         3662  +    return 0;
         3663  +  }
         3664  +}
  3637   3665   
  3638   3666   /*
  3639   3667   ** Compare the values contained by the two memory cells, returning
  3640   3668   ** negative, zero or positive if pMem1 is less than, equal to, or greater
  3641   3669   ** than pMem2. Sorting order is NULL's first, followed by numbers (integers
  3642   3670   ** and reals) sorted numerically, followed by text ordered by the collating
  3643   3671   ** sequence pColl and finally blob's ordered by memcmp().
................................................................................
  3656   3684     /* If one value is NULL, it is less than the other. If both values
  3657   3685     ** are NULL, return 0.
  3658   3686     */
  3659   3687     if( combined_flags&MEM_Null ){
  3660   3688       return (f2&MEM_Null) - (f1&MEM_Null);
  3661   3689     }
  3662   3690   
  3663         -  /* If one value is a number and the other is not, the number is less.
  3664         -  ** If both are numbers, compare as reals if one is a real, or as integers
  3665         -  ** if both values are integers.
         3691  +  /* At least one of the two values is a number
  3666   3692     */
  3667   3693     if( combined_flags&(MEM_Int|MEM_Real) ){
  3668         -    LONGDOUBLE_TYPE r1, r2;
  3669   3694       if( (f1 & f2 & MEM_Int)!=0 ){
  3670   3695         if( pMem1->u.i < pMem2->u.i ) return -1;
  3671         -      if( pMem1->u.i > pMem2->u.i ) return 1;
         3696  +      if( pMem1->u.i > pMem2->u.i ) return +1;
         3697  +      return 0;
         3698  +    }
         3699  +    if( (f1 & f2 & MEM_Real)!=0 ){
         3700  +      if( pMem1->u.r < pMem2->u.r ) return -1;
         3701  +      if( pMem1->u.r > pMem2->u.r ) return +1;
  3672   3702         return 0;
         3703  +    }
         3704  +    if( (f1&MEM_Int)!=0 ){
         3705  +      if( (f2&MEM_Real)!=0 ){
         3706  +        return sqlite3IntFloatCompare(pMem1->u.i, pMem2->u.r);
         3707  +      }else{
         3708  +        return -1;
         3709  +      }
  3673   3710       }
  3674   3711       if( (f1&MEM_Real)!=0 ){
  3675         -      r1 = pMem1->u.r;
  3676         -    }else if( (f1&MEM_Int)!=0 ){
  3677         -      r1 = (LONGDOUBLE_TYPE)pMem1->u.i;
  3678         -    }else{
  3679         -      return 1;
         3712  +      if( (f2&MEM_Int)!=0 ){
         3713  +        return -sqlite3IntFloatCompare(pMem2->u.i, pMem1->u.r);
         3714  +      }else{
         3715  +        return -1;
         3716  +      }
  3680   3717       }
  3681         -    if( (f2&MEM_Real)!=0 ){
  3682         -      r2 = pMem2->u.r;
  3683         -    }else if( (f2&MEM_Int)!=0 ){
  3684         -      r2 = (LONGDOUBLE_TYPE)pMem2->u.i;
  3685         -    }else{
  3686         -      return -1;
  3687         -    }
  3688         -    if( r1<r2 ) return -1;
  3689         -    if( r1>r2 ) return 1;
  3690         -    return 0;
         3718  +    return +1;
  3691   3719     }
  3692   3720   
  3693   3721     /* If one value is a string and the other is a blob, the string is less.
  3694   3722     ** If both are strings, compare using the collating functions.
  3695   3723     */
  3696   3724     if( combined_flags&MEM_Str ){
  3697   3725       if( (f1 & MEM_Str)==0 ){
................................................................................
  3834   3862         serial_type = aKey1[idx1];
  3835   3863         testcase( serial_type==12 );
  3836   3864         if( serial_type>=10 ){
  3837   3865           rc = +1;
  3838   3866         }else if( serial_type==0 ){
  3839   3867           rc = -1;
  3840   3868         }else if( serial_type==7 ){
  3841         -        LONGDOUBLE_TYPE rhs = (LONGDOUBLE_TYPE)pRhs->u.i;
  3842   3869           sqlite3VdbeSerialGet(&aKey1[d1], serial_type, &mem1);
  3843         -        if( mem1.u.r<rhs ){
  3844         -          rc = -1;
  3845         -        }else if( mem1.u.r>rhs ){
  3846         -          rc = +1;
  3847         -        }
         3870  +        rc = -sqlite3IntFloatCompare(pRhs->u.i, mem1.u.r);
  3848   3871         }else{
  3849   3872           i64 lhs = vdbeRecordDecodeInt(serial_type, &aKey1[d1]);
  3850   3873           i64 rhs = pRhs->u.i;
  3851   3874           if( lhs<rhs ){
  3852   3875             rc = -1;
  3853   3876           }else if( lhs>rhs ){
  3854   3877             rc = +1;
................................................................................
  3864   3887           ** numbers). Types 10 and 11 are currently "reserved for future 
  3865   3888           ** use", so it doesn't really matter what the results of comparing
  3866   3889           ** them to numberic values are.  */
  3867   3890           rc = +1;
  3868   3891         }else if( serial_type==0 ){
  3869   3892           rc = -1;
  3870   3893         }else{
  3871         -        LONGDOUBLE_TYPE rhs = pRhs->u.r;
  3872         -        LONGDOUBLE_TYPE lhs;
  3873   3894           sqlite3VdbeSerialGet(&aKey1[d1], serial_type, &mem1);
  3874   3895           if( serial_type==7 ){
  3875         -          lhs = mem1.u.r;
         3896  +          if( mem1.u.r<pRhs->u.r ){
         3897  +            rc = -1;
         3898  +          }else if( mem1.u.r>pRhs->u.r ){
         3899  +            rc = +1;
         3900  +          }
  3876   3901           }else{
  3877         -          lhs = (LONGDOUBLE_TYPE)mem1.u.i;
  3878         -        }
  3879         -        if( lhs<rhs ){
  3880         -          rc = -1;
  3881         -        }else if( lhs>rhs ){
  3882         -          rc = +1;
         3902  +          rc = sqlite3IntFloatCompare(mem1.u.i, pRhs->u.r);
  3883   3903           }
  3884   3904         }
  3885   3905       }
  3886   3906   
  3887   3907       /* RHS is a string */
  3888   3908       else if( pRhs->flags & MEM_Str ){
  3889   3909         getVarint32(&aKey1[idx1], serial_type);
................................................................................
  4084   4104     int nKey1, const void *pKey1, /* Left key */
  4085   4105     UnpackedRecord *pPKey2        /* Right key */
  4086   4106   ){
  4087   4107     const u8 *aKey1 = (const u8*)pKey1;
  4088   4108     int serial_type;
  4089   4109     int res;
  4090   4110   
         4111  +  assert( pPKey2->aMem[0].flags & MEM_Str );
  4091   4112     vdbeAssertFieldCountWithinLimits(nKey1, pKey1, pPKey2->pKeyInfo);
  4092   4113     getVarint32(&aKey1[1], serial_type);
  4093   4114     if( serial_type<12 ){
  4094   4115       res = pPKey2->r1;      /* (pKey1/nKey1) is a number or a null */
  4095   4116     }else if( !(serial_type & 0x01) ){ 
  4096   4117       res = pPKey2->r2;      /* (pKey1/nKey1) is a blob */
  4097   4118     }else{

Changes to test/atof1.test.

    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     17   
    18         -if {![info exists __GNUC__] || [regexp arm $tcl_platform(machine)]} {
           18  +if {$::longdouble_size<=8} {
    19     19     finish_test
    20     20     return
    21     21   }
    22     22   
    23     23   expr srand(1)
    24     24   for {set i 1} {$i<20000} {incr i} {
    25     25     set pow [expr {int((rand()-0.5)*100)}]