SQLite4
Check-in [9cf2ab46f5]
Not logged in

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

Overview
Comment:Further progress on this. src4.test is now passing again.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | sqlite4-num
Files: files | file ages | folders
SHA1: 9cf2ab46f59736a4609fc7bf7ee5465cf0ea1816
User & Date: dan 2013-05-29 18:52:48
Context
2013-05-30
18:26
Change various things to use sqlite4_num instead of double. check-in: ba34125233 user: dan tags: sqlite4-num
2013-05-29
18:52
Further progress on this. src4.test is now passing again. check-in: 9cf2ab46f5 user: dan tags: sqlite4-num
2013-05-28
20:33
Further progress on decimal arithmetic. check-in: b55b217f6a user: dan tags: sqlite4-num
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/math.c.

571
572
573
574
575
576
577
578
579
580
581


582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611

612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630

631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
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
/*
** Convert a number into text.  Store the result in zOut[].  The
** zOut buffer must be at laest 30 characters in length.  The output
** will be zero-terminated.
*/
int sqlite4_num_to_text(sqlite4_num x, char *zOut, int bReal){
  char zBuf[24];
  int nOut = 0;
  char *zNum;
  int n;
  static const char zeros[] = "0000000000000000000000000";


  
  if( x.sign && x.m>0 ){
    /* Add initial "-" for negative non-zero values */
    zOut[0] = '-';
    zOut++;
    nOut++;
  }
  if( x.e>SQLITE4_MX_EXP ){
    /* Handle NaN and infinite values */
    if( x.m==0 ){
      memcpy(zOut, "NaN", 4);
    }else{
      memcpy(zOut, "inf", 4);
    }
    return nOut+3;
  }
  if( x.m==0 ){
    memcpy(zOut, "0", 2);
    return 1;
  }
  zNum = renderInt(x.m, zBuf, sizeof(zBuf));
  n = &zBuf[sizeof(zBuf)-1] - zNum;
  if( x.e>=0 && x.e+n<=25 ){
    /* Integer values with up to 25 digits */
    memcpy(zOut, zNum, n+1);
    nOut += n;
    if( x.e>0 ){
      memcpy(&zOut[nOut], zeros, x.e);
      zOut[nOut+x.e] = 0;
      nOut += x.e;

    }
    if( bReal ){
      memcpy(&zOut[nOut], ".0", 3);
      nOut += 2;
    }
    return nOut;
  }
  if( x.e<0 && n+x.e > 0 ){
    /* Fractional values where the decimal point occurs within the
    ** significant digits.  ex:  12.345 */
    int m = n+x.e;
    memcpy(zOut, zNum, m);
    nOut += m;
    zOut += m;
    zNum += m;
    n -= m;
    removeTrailingZeros(zNum, &n);
    if( n>0 ){
      zOut[0] = '.';

      memcpy(zOut+1, zNum, n);
      nOut += n;
      zOut[n+1] = 0;
    }else{
      if( bReal ){
        memcpy(zOut, ".0", 3);
        nOut += 2;
      }else{
        zOut[0] = 0;
      }
    }
    return nOut;
  }
  if( x.e<0 && x.e >= -n-5 ){
    /* Values less than 1 and with no more than 5 subsequent zeros prior
    ** to the first significant digit.  Ex:  0.0000012345 */
    int j = -(n + x.e);
    memcpy(zOut, "0.", 2);
    nOut += 2;
    zOut += 2;
    if( j>0 ){
      memcpy(zOut, zeros, j);
      nOut += j;
      zOut += j;
    }
    removeTrailingZeros(zNum, &n);
    memcpy(zOut, zNum, n+1);
    nOut += n;
    zOut[n+1] = 0;
    return nOut;
  }
  /* Exponential notation from here to the end.  ex:  1.234e-15 */
  zOut[0] = zNum[0];

  if( n>1 ){
    int nOrig = n;
    removeTrailingZeros(zNum, &n);
    x.e += nOrig - n;
  }
  if( n==1 ){
    /* Exactly one significant digit.  ex:  8e12 */
    zOut++;
    nOut++;
  }else{
    /* Two or or more significant digits.  ex: 1.23e17 */
    zOut[1] = '.';
    memcpy(zOut+2, zNum+1, n-1);
    zOut += n+1;
    nOut += n+1;
    x.e += n-1;
  }
  zOut[0] = 'e';
  zOut++;
  nOut++;
  if( x.e<0 ){
    zOut[0] = '-';
    x.e = -x.e;
  }else{
    zOut[0] = '+';
  }
  zOut++;
  nOut++;
  zNum = renderInt(x.e&0x7fff, zBuf, sizeof(zBuf));
  while( (zOut[0] = zNum[0])!=0 ){ zOut++; zNum++; nOut++; }
  return nOut;
}







<



>
>



|
|
<




|

|

|


|
|





|
|

|
<
|
>


|
|

|





|
|
<




|
>
|
|
|


|
|

|


|





|
|
<

|
|
<


|
|
|
|


|
>





|
<
<
<
<

|
|
|
<


|
<
<

|


|

|
<

|
|

571
572
573
574
575
576
577

578
579
580
581
582
583
584
585
586
587

588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609

610
611
612
613
614
615
616
617
618
619
620
621
622
623
624

625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
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
/*
** Convert a number into text.  Store the result in zOut[].  The
** zOut buffer must be at laest 30 characters in length.  The output
** will be zero-terminated.
*/
int sqlite4_num_to_text(sqlite4_num x, char *zOut, int bReal){
  char zBuf[24];

  char *zNum;
  int n;
  static const char zeros[] = "0000000000000000000000000";

  char *z = zOut;
  
  if( x.sign && x.m>0 ){
    /* Add initial "-" for negative non-zero values */
    z[0] = '-';
    z++;

  }
  if( x.e>SQLITE4_MX_EXP ){
    /* Handle NaN and infinite values */
    if( x.m==0 ){
      memcpy(z, "NaN", 4);
    }else{
      memcpy(z, "inf", 4);
    }
    return (z - zOut)+3;
  }
  if( x.m==0 ){
    memcpy(z, "0", 2);
    return 1+(z-zOut);
  }
  zNum = renderInt(x.m, zBuf, sizeof(zBuf));
  n = &zBuf[sizeof(zBuf)-1] - zNum;
  if( x.e>=0 && x.e+n<=25 ){
    /* Integer values with up to 25 digits */
    memcpy(z, zNum, n+1);
    z += n;
    if( x.e>0 ){
      memcpy(z, zeros, x.e);

      z += x.e;
      z[0] = 0;
    }
    if( bReal ){
      memcpy(z, ".0", 3);
      z += 2;
    }
    return (z - zOut);
  }
  if( x.e<0 && n+x.e > 0 ){
    /* Fractional values where the decimal point occurs within the
    ** significant digits.  ex:  12.345 */
    int m = n+x.e;
    memcpy(z, zNum, m);
    z += m;

    zNum += m;
    n -= m;
    removeTrailingZeros(zNum, &n);
    if( n>0 ){
      z[0] = '.';
      z++;
      memcpy(z, zNum, n);
      z += n;
      z[0] = 0;
    }else{
      if( bReal ){
        memcpy(z, ".0", 3);
        z += 2;
      }else{
        z[0] = 0;
      }
    }
    return (z - zOut);
  }
  if( x.e<0 && x.e >= -n-5 ){
    /* Values less than 1 and with no more than 5 subsequent zeros prior
    ** to the first significant digit.  Ex:  0.0000012345 */
    int j = -(n + x.e);
    memcpy(z, "0.", 2);
    z += 2;

    if( j>0 ){
      memcpy(z, zeros, j);
      z += j;

    }
    removeTrailingZeros(zNum, &n);
    memcpy(z, zNum, n);
    z += n;
    z[0] = 0;
    return (z - zOut);
  }
  /* Exponential notation from here to the end.  ex:  1.234e-15 */
  z[0] = zNum[0];
  z++;
  if( n>1 ){
    int nOrig = n;
    removeTrailingZeros(zNum, &n);
    x.e += nOrig - n;
  }
  if( n!=1 ){




    /* Two or or more significant digits.  ex: 1.23e17 */
    *z++ = '.';
    memcpy(z, zNum+1, n-1);
    z += n-1;

    x.e += n-1;
  }
  *z++ = 'e';


  if( x.e<0 ){
    *z++ = '-';
    x.e = -x.e;
  }else{
    *z++ = '+';
  }
  z++;

  zNum = renderInt(x.e&0x7fff, zBuf, sizeof(zBuf));
  while( (z[0] = zNum[0])!=0 ){ z++; zNum++; }
  return (z-zOut);
}

Changes to src/vdbe.c.

1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
....
1257
1258
1259
1260
1261
1262
1263


1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285


1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
case OP_Subtract:              /* same as TK_MINUS, in1, in2, out3 */
case OP_Multiply:              /* same as TK_STAR, in1, in2, out3 */
case OP_Divide:                /* same as TK_SLASH, in1, in2, out3 */
case OP_Remainder: {           /* same as TK_REM, in1, in2, out3 */
  int flags;      /* Combined MEM_* flags from both inputs */
  i64 iA;         /* Integer value of left operand */
  i64 iB;         /* Integer value of right operand */
  i64 iOut;
#if 0
  double rA;      /* Real value of left operand */
  double rB;      /* Real value of right operand */
#endif

  pIn1 = &aMem[pOp->p1];
  applyNumericAffinity(pIn1);
  pIn2 = &aMem[pOp->p2];
  applyNumericAffinity(pIn2);
  pOut = &aMem[pOp->p3];
  flags = pIn1->flags | pIn2->flags;
................................................................................
    pOut->u.num = sqlite4_num_from_int64(iB);
    MemSetTypeFlag(pOut, MEM_Int);

    break;
  }else{

 fp_math:


    switch( pOp->opcode ){
      case OP_Add: 
        pOut->u.num = sqlite4_num_add(pIn1->u.num, pIn2->u.num); break;
      case OP_Subtract: 
        pOut->u.num = sqlite4_num_sub(pIn2->u.num, pIn1->u.num); break;
      case OP_Multiply: 
        pOut->u.num = sqlite4_num_mul(pIn1->u.num, pIn2->u.num); break;
      case OP_Divide: 
        pOut->u.num = sqlite4_num_div(pIn2->u.num, pIn1->u.num); break;
      default: {
        sqlite4_num_to_int64(pIn1->u.num, &iA);
        sqlite4_num_to_int64(pIn2->u.num, &iB);
        if( iA==0 ) goto arithmetic_result_is_null;
        pOut->u.num = sqlite4_num_from_int64(iB % iA);
        break;
      }
    }

    if( sqlite4_num_isnan(pOut->u.num) ){
      goto arithmetic_result_is_null;
    }else{
      MemSetTypeFlag(pOut, MEM_Real);


    }
  }

  break;

#if 0
  if( (pIn1->flags & pIn2->flags & MEM_Int)==MEM_Int ){
    iA = pIn1->u.i;
    iB = pIn2->u.i;
    switch( pOp->opcode ){
      case OP_Add:       if( sqlite4AddInt64(&iB,iA) ) goto fp_math;  break;
      case OP_Subtract:  if( sqlite4SubInt64(&iB,iA) ) goto fp_math;  break;
      case OP_Multiply:  if( sqlite4MulInt64(&iB,iA) ) goto fp_math;  break;
      case OP_Divide: {
        if( iA==0 ) goto arithmetic_result_is_null;
        if( iA==-1 && iB==SMALLEST_INT64 ) goto fp_math;
        iB /= iA;
        break;
      }
      default: {
        if( iA==0 ) goto arithmetic_result_is_null;
        if( iA==-1 ) iA = 1;
        iB %= iA;
        break;
      }
    }
    pOut->u.i = iB;
    MemSetTypeFlag(pOut, MEM_Int);
  }else{
fp_math:
    rA = sqlite4VdbeRealValue(pIn1);
    rB = sqlite4VdbeRealValue(pIn2);
    switch( pOp->opcode ){
      case OP_Add:         rB += rA;       break;
      case OP_Subtract:    rB -= rA;       break;
      case OP_Multiply:    rB *= rA;       break;
      case OP_Divide: {
        /* (double)0 In case of SQLITE4_OMIT_FLOATING_POINT... */
        if( rA==(double)0 ) goto arithmetic_result_is_null;
        rB /= rA;
        break;
      }
      default: {
        iA = (i64)rA;
        iB = (i64)rB;
        if( iA==0 ) goto arithmetic_result_is_null;
        if( iA==-1 ) iA = 1;
        rB = (double)(iB % iA);
        break;
      }
    }
#ifdef SQLITE4_OMIT_FLOATING_POINT
    pOut->u.i = rB;
    MemSetTypeFlag(pOut, MEM_Int);
#else
    if( sqlite4IsNaN(rB) ){
      goto arithmetic_result_is_null;
    }
    pOut->r = rB;
    MemSetTypeFlag(pOut, MEM_Real);
    if( (flags & MEM_Real)==0 ){
      sqlite4VdbeIntegerAffinity(pOut);
    }
#endif
  }
  break;
#endif

arithmetic_result_is_null:
  sqlite4VdbeMemSetNull(pOut);
  break;
}

/* Opcode: CollSeq * * P4







|
|
<
<
<







 







>
>


|

|

|

|

|
|










>
>
|
|
|
<

<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







1215
1216
1217
1218
1219
1220
1221
1222
1223



1224
1225
1226
1227
1228
1229
1230
....
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289

1290












1291

















































1292
1293
1294
1295
1296
1297
1298
case OP_Subtract:              /* same as TK_MINUS, in1, in2, out3 */
case OP_Multiply:              /* same as TK_STAR, in1, in2, out3 */
case OP_Divide:                /* same as TK_SLASH, in1, in2, out3 */
case OP_Remainder: {           /* same as TK_REM, in1, in2, out3 */
  int flags;      /* Combined MEM_* flags from both inputs */
  i64 iA;         /* Integer value of left operand */
  i64 iB;         /* Integer value of right operand */
  sqlite4_num num1;
  sqlite4_num num2;




  pIn1 = &aMem[pOp->p1];
  applyNumericAffinity(pIn1);
  pIn2 = &aMem[pOp->p2];
  applyNumericAffinity(pIn2);
  pOut = &aMem[pOp->p3];
  flags = pIn1->flags | pIn2->flags;
................................................................................
    pOut->u.num = sqlite4_num_from_int64(iB);
    MemSetTypeFlag(pOut, MEM_Int);

    break;
  }else{

 fp_math:
    num1 = sqlite4VdbeNumValue(pIn1);
    num2 = sqlite4VdbeNumValue(pIn2);
    switch( pOp->opcode ){
      case OP_Add: 
        pOut->u.num = sqlite4_num_add(num1, num2); break;
      case OP_Subtract: 
        pOut->u.num = sqlite4_num_sub(num2, num1); break;
      case OP_Multiply: 
        pOut->u.num = sqlite4_num_mul(num1, num2); break;
      case OP_Divide: 
        pOut->u.num = sqlite4_num_div(num2, num1); break;
      default: {
        sqlite4_num_to_int64(num1, &iA);
        sqlite4_num_to_int64(num2, &iB);
        if( iA==0 ) goto arithmetic_result_is_null;
        pOut->u.num = sqlite4_num_from_int64(iB % iA);
        break;
      }
    }

    if( sqlite4_num_isnan(pOut->u.num) ){
      goto arithmetic_result_is_null;
    }else{
      MemSetTypeFlag(pOut, MEM_Real);
      if( (flags & MEM_Real)==0 ){
        sqlite4VdbeIntegerAffinity(pOut);
      }
    }
  }














  break;


















































arithmetic_result_is_null:
  sqlite4VdbeMemSetNull(pOut);
  break;
}

/* Opcode: CollSeq * * P4

Changes to src/vdbeInt.h.

405
406
407
408
409
410
411

412
413
414
415
416
417
418
#endif
void sqlite4VdbeMemSetNull(Mem*);
int sqlite4VdbeMemMakeWriteable(Mem*);
int sqlite4VdbeMemStringify(Mem*, int);
i64 sqlite4VdbeIntValue(Mem*);
int sqlite4VdbeMemIntegerify(Mem*);
double sqlite4VdbeRealValue(Mem*);

void sqlite4VdbeIntegerAffinity(Mem*);
int sqlite4VdbeMemRealify(Mem*);
int sqlite4VdbeMemNumerify(Mem*);
void sqlite4VdbeMemSetRowSet(Mem *pMem);

void sqlite4VdbeMemRelease(Mem *p);
void sqlite4VdbeMemReleaseExternal(Mem *p);







>







405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
#endif
void sqlite4VdbeMemSetNull(Mem*);
int sqlite4VdbeMemMakeWriteable(Mem*);
int sqlite4VdbeMemStringify(Mem*, int);
i64 sqlite4VdbeIntValue(Mem*);
int sqlite4VdbeMemIntegerify(Mem*);
double sqlite4VdbeRealValue(Mem*);
sqlite4_num sqlite4VdbeNumValue(Mem *);
void sqlite4VdbeIntegerAffinity(Mem*);
int sqlite4VdbeMemRealify(Mem*);
int sqlite4VdbeMemNumerify(Mem*);
void sqlite4VdbeMemSetRowSet(Mem *pMem);

void sqlite4VdbeMemRelease(Mem *p);
void sqlite4VdbeMemReleaseExternal(Mem *p);

Changes to src/vdbecodec.c.

116
117
118
119
120
121
122

123
124
125

126
127
128
129









130
131
132
133
134
135
136
137
...
139
140
141
142
143
144
145


146
147
148
149
150
151
152
...
232
233
234
235
236
237
238

239
240
241

242








243
244
245
246
247
248
249
...
260
261
262
263
264
265
266


267
268
269
270
271
272
273
274
275
      int iByte;
      sqlite4_int64 v = ((char*)p->a)[ofst];
      for(iByte=1; iByte<size; iByte++){
        v = v*256 + p->a[ofst+iByte];
      }
      sqlite4VdbeMemSetInt64(pOut, v);
    }else if( type<=21 ){

      sqlite4_uint64 x;
      int e;
      double r;

      n = sqlite4GetVarint64(p->a+ofst, p->n-ofst, &x);
      e = (int)x;
      n += sqlite4GetVarint64(p->a+ofst+n, p->n-(ofst+n), &x);
      if( n!=size ) return SQLITE4_CORRUPT;









      r = (double)x;
      if( e&1 ) r = -r;
      if( e&2 ){
        e = -(e>>2);
        if( e==0 ){
          r *= 1e+300*1e+300;
        }else{
          while( e<=-10 ){ r /= 1.0e10; e += 10; }
................................................................................
        }
      }else{
        e = e>>2;
        while( e>=10 ){ r *= 1.0e10; e -= 10; }
        while( e>0 ){ r *= 10.0; e--; }
      }
      sqlite4VdbeMemSetDouble(pOut, r);


    }else if( cclass==0 ){
      if( size==0 ){
        sqlite4VdbeMemSetStr(pOut, "", 0, SQLITE4_UTF8, SQLITE4_TRANSIENT, 0);
      }else if( p->a[ofst]>0x02 ){
        sqlite4VdbeMemSetStr(pOut, (char*)(p->a+ofst), size, 
                             SQLITE4_UTF8, SQLITE4_TRANSIENT, 0);
      }else{
................................................................................
      i64 i1;
      sqlite4_num_to_int64(aIn[i].u.num, &i1);
      n = significantBytes(i1);
      aOut[nOut++] = n+2;
      nPayload += n;
      aAux[i].n = n;
    }else if( flags & MEM_Real ){

      int e = 0;
      u8 sign = 0;
      double r;

      sqlite4_uint64 m;








      sqlite4_num_to_double(aIn[i].u.num, &r);
      if( sqlite4IsNaN(r) ){
        m = 0;
        e = 2;
      }else if( sqlite4IsInf(r)!=0 ){
        m = 1;
        e = 2 + (sqlite4IsInf(r)<0);
................................................................................
        m = r;
        if( e<0 ){
          e = (-e*4) + 2 + sign;
        }else{
          e = e*4 + sign;
        }
      }


      n = sqlite4PutVarint64(aAux[i].z, (sqlite4_uint64)e);
      n += sqlite4PutVarint64(aAux[i].z+n, m);
      aAux[i].n = n;
      aOut[nOut++] = n+9;
      nPayload += n;
    }else if( flags & MEM_Str ){
      n = aIn[i].n;
      if( n && (encoding!=SQLITE4_UTF8 || aIn[i].z[0]<2) ) n++;
      nPayload += n;







>


<
>




>
>
>
>
>
>
>
>
>
|







 







>
>







 







>
|
<
<
>
|
>
>
>
>
>
>
>
>







 







>
>

|







116
117
118
119
120
121
122
123
124
125

126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
...
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
...
244
245
246
247
248
249
250
251
252


253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
...
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
      int iByte;
      sqlite4_int64 v = ((char*)p->a)[ofst];
      for(iByte=1; iByte<size; iByte++){
        v = v*256 + p->a[ofst+iByte];
      }
      sqlite4VdbeMemSetInt64(pOut, v);
    }else if( type<=21 ){
      sqlite4_num num = {0, 0, 0, 0};
      sqlite4_uint64 x;
      int e;


      n = sqlite4GetVarint64(p->a+ofst, p->n-ofst, &x);
      e = (int)x;
      n += sqlite4GetVarint64(p->a+ofst+n, p->n-(ofst+n), &x);
      if( n!=size ) return SQLITE4_CORRUPT;

      num.m = x;
      num.e = (e >> 2);
      if( e & 0x02 ) num.e = -1 * num.e;
      if( e & 0x01 ) num.sign = 1;
      pOut->u.num = num;
      MemSetTypeFlag(pOut, MEM_Real);

#if 0
      double r = (double)x;
      if( e&1 ) r = -r;
      if( e&2 ){
        e = -(e>>2);
        if( e==0 ){
          r *= 1e+300*1e+300;
        }else{
          while( e<=-10 ){ r /= 1.0e10; e += 10; }
................................................................................
        }
      }else{
        e = e>>2;
        while( e>=10 ){ r *= 1.0e10; e -= 10; }
        while( e>0 ){ r *= 10.0; e--; }
      }
      sqlite4VdbeMemSetDouble(pOut, r);
#endif

    }else if( cclass==0 ){
      if( size==0 ){
        sqlite4VdbeMemSetStr(pOut, "", 0, SQLITE4_UTF8, SQLITE4_TRANSIENT, 0);
      }else if( p->a[ofst]>0x02 ){
        sqlite4VdbeMemSetStr(pOut, (char*)(p->a+ofst), size, 
                             SQLITE4_UTF8, SQLITE4_TRANSIENT, 0);
      }else{
................................................................................
      i64 i1;
      sqlite4_num_to_int64(aIn[i].u.num, &i1);
      n = significantBytes(i1);
      aOut[nOut++] = n+2;
      nPayload += n;
      aAux[i].n = n;
    }else if( flags & MEM_Real ){
      sqlite4_num *p = &aIn[i].u.num;
      int e;



      assert( p->sign==0 || p->sign==1 );
      if( p->e<0 ){
        e = (p->e*-4) + 2 + p->sign;
      }else{
        e = (p->e*4) + p->sign;
      }


#if 0
      sqlite4_num_to_double(aIn[i].u.num, &r);
      if( sqlite4IsNaN(r) ){
        m = 0;
        e = 2;
      }else if( sqlite4IsInf(r)!=0 ){
        m = 1;
        e = 2 + (sqlite4IsInf(r)<0);
................................................................................
        m = r;
        if( e<0 ){
          e = (-e*4) + 2 + sign;
        }else{
          e = e*4 + sign;
        }
      }
#endif

      n = sqlite4PutVarint64(aAux[i].z, (sqlite4_uint64)e);
      n += sqlite4PutVarint64(aAux[i].z+n, p->m);
      aAux[i].n = n;
      aOut[nOut++] = n+9;
      nPayload += n;
    }else if( flags & MEM_Str ){
      n = aIn[i].n;
      if( n && (encoding!=SQLITE4_UTF8 || aIn[i].z[0]<2) ) n++;
      nPayload += n;

Changes to src/vdbemem.c.

183
184
185
186
187
188
189

190
191
192
193
194
195
196
...
349
350
351
352
353
354
355















356
357
358
359
360
361
362
...
379
380
381
382
383
384
385
386

387
388
389
390
391
392
393
...
395
396
397
398
399
400
401

402
403
404


405
406
407


408
409
410
411
412
413
414
...
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
  /* For a Real or Integer, use sqlite4_mprintf() to produce the UTF-8
  ** string representation of the value. Then, if the required encoding
  ** is UTF-16le or UTF-16be do a translation.
  ** 
  ** FIX ME: It would be better if sqlite4_snprintf() could do UTF-16.
  */
  sqlite4_num_to_text(pMem->u.num, pMem->z, (pMem->flags & MEM_Int)==0);

  pMem->n = sqlite4Strlen30(pMem->z);
  pMem->enc = SQLITE4_UTF8;
  pMem->flags |= MEM_Str|MEM_Term;
  sqlite4VdbeChangeEncoding(pMem, enc);
  return rc;
}

................................................................................
    sqlite4AtoF(pMem->z, &val, pMem->n, pMem->enc);
    return val;
  }else{
    /* (double)0 In case of SQLITE4_OMIT_FLOATING_POINT... */
    return (double)0;
  }
}
















/*
** The MEM structure is already a MEM_Real.  Try to also make it a
** MEM_Int if we can.
*/
void sqlite4VdbeIntegerAffinity(Mem *pMem){
  i64 i;
................................................................................
  ** The second and third terms in the following conditional enforces
  ** the second condition under the assumption that addition overflow causes
  ** values to wrap around.  On x86 hardware, the third term is always
  ** true and could be omitted.  But we leave it in because other
  ** architectures might behave differently.
  */
  if( r==(double)i && i>SMALLEST_INT64 && ALWAYS(i<LARGEST_INT64) ){
    pMem->flags |= MEM_Int;

  }
}

/*
** Convert pMem to type integer.  Invalidate any prior representations.
*/
int sqlite4VdbeMemIntegerify(Mem *pMem){
................................................................................
  assert( (pMem->flags & MEM_RowSet)==0 );
  assert( EIGHT_BYTE_ALIGNMENT(pMem) );

  if( (pMem->flags & MEM_Int)==0 ){
    sqlite4VdbeMemNumerify(pMem);
  }
  if( (pMem->flags & MEM_Int)==0 ){

    i64 iVal;
    sqlite4_num_to_int64(pMem->u.num, &iVal);
    pMem->u.num = sqlite4_num_from_int64(iVal);


  }
  MemSetTypeFlag(pMem, MEM_Int);



  return SQLITE4_OK;
}

/*
** Convert pMem so that it is of type MEM_Real.
** Invalidate any prior representations.
*/
................................................................................
    assert( pMem->db==0 || sqlite4_mutex_held(pMem->db->mutex) );
    pMem->u.num = sqlite4_num_from_text(pMem->z, pMem->n, flags);
    if( pMem->u.num.e==0 ){
      MemSetTypeFlag(pMem, MEM_Int);
    }else{
      MemSetTypeFlag(pMem, MEM_Real);
    }
#if 0
    if( 0==sqlite4Atoi64(pMem->z, &i1, pMem->n, pMem->enc) ){
      pMem->u.num = sqlite4_num_from_int64(i1);
      MemSetTypeFlag(pMem, MEM_Int);
    }else{
      pMem->u.num = sqlite4_num_from_double(sqlite4VdbeRealValue(pMem));
      MemSetTypeFlag(pMem, MEM_Real);
      sqlite4VdbeIntegerAffinity(pMem);
    }
#endif
  }
  assert( (pMem->flags & (MEM_Int|MEM_Real|MEM_Null))!=0 );
  pMem->flags &= ~(MEM_Str|MEM_Blob);
  return SQLITE4_OK;
}

/*







>







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







 







|
>







 







>
|
|
|
>
>
|
<
|
>
>







 







<
<
<
<
<
<
<
<
<
<







183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
...
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
...
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
...
412
413
414
415
416
417
418
419
420
421
422
423
424
425

426
427
428
429
430
431
432
433
434
435
...
458
459
460
461
462
463
464










465
466
467
468
469
470
471
  /* For a Real or Integer, use sqlite4_mprintf() to produce the UTF-8
  ** string representation of the value. Then, if the required encoding
  ** is UTF-16le or UTF-16be do a translation.
  ** 
  ** FIX ME: It would be better if sqlite4_snprintf() could do UTF-16.
  */
  sqlite4_num_to_text(pMem->u.num, pMem->z, (pMem->flags & MEM_Int)==0);

  pMem->n = sqlite4Strlen30(pMem->z);
  pMem->enc = SQLITE4_UTF8;
  pMem->flags |= MEM_Str|MEM_Term;
  sqlite4VdbeChangeEncoding(pMem, enc);
  return rc;
}

................................................................................
    sqlite4AtoF(pMem->z, &val, pMem->n, pMem->enc);
    return val;
  }else{
    /* (double)0 In case of SQLITE4_OMIT_FLOATING_POINT... */
    return (double)0;
  }
}

/*
** Extract and return a numeric value from memory cell pMem. This call
** does not modify the contents or flags of *pMem in any way.
*/
sqlite4_num sqlite4VdbeNumValue(Mem *pMem){
  if( pMem->flags & (MEM_Real|MEM_Int) ){
    return pMem->u.num;
  }else if( pMem->flags & (MEM_Str|MEM_Blob) ){
    return sqlite4_num_from_text(pMem->z, pMem->n, SQLITE4_PREFIX_ONLY);
  }else{
    sqlite4_num zero = {0,0,0,0};
    return zero;
  }
}

/*
** The MEM structure is already a MEM_Real.  Try to also make it a
** MEM_Int if we can.
*/
void sqlite4VdbeIntegerAffinity(Mem *pMem){
  i64 i;
................................................................................
  ** The second and third terms in the following conditional enforces
  ** the second condition under the assumption that addition overflow causes
  ** values to wrap around.  On x86 hardware, the third term is always
  ** true and could be omitted.  But we leave it in because other
  ** architectures might behave differently.
  */
  if( r==(double)i && i>SMALLEST_INT64 && ALWAYS(i<LARGEST_INT64) ){
    pMem->u.num = sqlite4_num_from_int64(i);
    MemSetTypeFlag(pMem, MEM_Int);
  }
}

/*
** Convert pMem to type integer.  Invalidate any prior representations.
*/
int sqlite4VdbeMemIntegerify(Mem *pMem){
................................................................................
  assert( (pMem->flags & MEM_RowSet)==0 );
  assert( EIGHT_BYTE_ALIGNMENT(pMem) );

  if( (pMem->flags & MEM_Int)==0 ){
    sqlite4VdbeMemNumerify(pMem);
  }
  if( (pMem->flags & MEM_Int)==0 ){
    if( pMem->flags & MEM_Real ){
      i64 iVal;
      sqlite4_num_to_int64(pMem->u.num, &iVal);
      pMem->u.num = sqlite4_num_from_int64(iVal);
    }else{
      pMem->u.num = sqlite4_num_from_int64(0);
    }

  }

  MemSetTypeFlag(pMem, MEM_Int);
  return SQLITE4_OK;
}

/*
** Convert pMem so that it is of type MEM_Real.
** Invalidate any prior representations.
*/
................................................................................
    assert( pMem->db==0 || sqlite4_mutex_held(pMem->db->mutex) );
    pMem->u.num = sqlite4_num_from_text(pMem->z, pMem->n, flags);
    if( pMem->u.num.e==0 ){
      MemSetTypeFlag(pMem, MEM_Int);
    }else{
      MemSetTypeFlag(pMem, MEM_Real);
    }










  }
  assert( (pMem->flags & (MEM_Int|MEM_Real|MEM_Null))!=0 );
  pMem->flags &= ~(MEM_Str|MEM_Blob);
  return SQLITE4_OK;
}

/*

Changes to test/cast.test.

235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
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
...
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
  execsql {SELECT CAST(9223372036854774800 AS numeric)}
} 9223372036854774800
do_realnum_test cast-3.3 {
  execsql {SELECT CAST(9223372036854774800 AS real)}
} 9.22337203685477e+18
do_test cast-3.4 {
  execsql {SELECT CAST(CAST(9223372036854774800 AS real) AS integer)}
} 9223372036854774784
do_test cast-3.5 {
  execsql {SELECT CAST(-9223372036854774800 AS integer)}
} -9223372036854774800
do_test cast-3.6 {
  execsql {SELECT CAST(-9223372036854774800 AS numeric)}
} -9223372036854774800
do_realnum_test cast-3.7 {
  execsql {SELECT CAST(-9223372036854774800 AS real)}
} -9.22337203685477e+18
do_test cast-3.8 {
  execsql {SELECT CAST(CAST(-9223372036854774800 AS real) AS integer)}
} -9223372036854774784
do_test cast-3.11 {
  execsql {SELECT CAST('9223372036854774800' AS integer)}
} 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
ifcapable long_double {
  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
ifcapable long_double {
  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)}
................................................................................
  } 9.22337203685477e+18
  ifcapable long_double {
    do_test cast-3.24 {
      execsql {
        SELECT CAST(CAST(x'39323233333732303336383534373734383030' AS real)
                    AS integer)
      }
    } 9223372036854774784
  }
}
do_test case-3.31 {
  execsql {SELECT CAST(NULL AS numeric)}
} {{}}

# Test to see if it is possible to trick SQLite into reading past 







|











|












|













|







 







|







235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
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
...
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
  execsql {SELECT CAST(9223372036854774800 AS numeric)}
} 9223372036854774800
do_realnum_test cast-3.3 {
  execsql {SELECT CAST(9223372036854774800 AS real)}
} 9.22337203685477e+18
do_test cast-3.4 {
  execsql {SELECT CAST(CAST(9223372036854774800 AS real) AS integer)}
} 9223372036854774800
do_test cast-3.5 {
  execsql {SELECT CAST(-9223372036854774800 AS integer)}
} -9223372036854774800
do_test cast-3.6 {
  execsql {SELECT CAST(-9223372036854774800 AS numeric)}
} -9223372036854774800
do_realnum_test cast-3.7 {
  execsql {SELECT CAST(-9223372036854774800 AS real)}
} -9.22337203685477e+18
do_test cast-3.8 {
  execsql {SELECT CAST(CAST(-9223372036854774800 AS real) AS integer)}
} -9223372036854774800
do_test cast-3.11 {
  execsql {SELECT CAST('9223372036854774800' AS integer)}
} 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
ifcapable long_double {
  do_test cast-3.14 {
    execsql {SELECT CAST(CAST('9223372036854774800' AS real) AS integer)}
  } 9223372036854774800
}
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
ifcapable long_double {
  do_test cast-3.18 {
    execsql {SELECT CAST(CAST('-9223372036854774800' AS real) AS integer)}
  } -9223372036854774800
}
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)}
................................................................................
  } 9.22337203685477e+18
  ifcapable long_double {
    do_test cast-3.24 {
      execsql {
        SELECT CAST(CAST(x'39323233333732303336383534373734383030' AS real)
                    AS integer)
      }
    } 9223372036854774800
  }
}
do_test case-3.31 {
  execsql {SELECT CAST(NULL AS numeric)}
} {{}}

# Test to see if it is possible to trick SQLite into reading past 

Changes to test/num.test.

12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
...
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
# focus of this file is testing the sqlite_*_printf() interface.
#
# $Id: printf.test,v 1.31 2009/02/01 00:21:10 drh Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

if 0 {

do_test num-1.1.1 {
  sqlite4_num_compare 20 20 
} {equal}
do_test num-1.1.2 {
  sqlite4_num_compare 20 2e1
} {equal}
do_test num-1.1.3 {
................................................................................
  7    45.345687           {sign:0 e:-6  m:45345687}
  8    1000000000000000000 {sign:0 e:18  m:1}
} {
  do_test num-7.1.$tn {
    set res [sqlite4_num_from_double $in]
    list [lindex $res 0] [lindex $res 2] [lindex $res 3]
  } [list [lindex $out 0] [lindex $out 1] [lindex $out 2]]
}

}

#-------------------------------------------------------------------------
# Test the boundary conditions in sqlite4_num_from_text() for parsing 
# values that can fit in a signed 64-bit integer variable. And others.
# 
foreach {tn in out} {







<
<







 







<
<







12
13
14
15
16
17
18


19
20
21
22
23
24
25
...
103
104
105
106
107
108
109


110
111
112
113
114
115
116
# focus of this file is testing the sqlite_*_printf() interface.
#
# $Id: printf.test,v 1.31 2009/02/01 00:21:10 drh Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl



do_test num-1.1.1 {
  sqlite4_num_compare 20 20 
} {equal}
do_test num-1.1.2 {
  sqlite4_num_compare 20 2e1
} {equal}
do_test num-1.1.3 {
................................................................................
  7    45.345687           {sign:0 e:-6  m:45345687}
  8    1000000000000000000 {sign:0 e:18  m:1}
} {
  do_test num-7.1.$tn {
    set res [sqlite4_num_from_double $in]
    list [lindex $res 0] [lindex $res 2] [lindex $res 3]
  } [list [lindex $out 0] [lindex $out 1] [lindex $out 2]]


}

#-------------------------------------------------------------------------
# Test the boundary conditions in sqlite4_num_from_text() for parsing 
# values that can fit in a signed 64-bit integer variable. And others.
# 
foreach {tn in out} {

Changes to test/simple.test.

96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
....
1477
1478
1479
1480
1481
1482
1483

























1484

#
do_execsql_test 3.3 { INSERT INTO t1 VALUES('one', '111') } {}


#-------------------------------------------------------------------------
reset_db

breakpoint
do_execsql_test 4.1 { CREATE TABLE t1(k PRIMARY KEY, v) }
do_execsql_test 4.2 { CREATE INDEX i1 ON t1(v) }

do_execsql_test 4.3 { 
  SELECT * FROM sqlite_master
} {
  table t1 t1 2 {CREATE TABLE t1(k PRIMARY KEY, v)} 
................................................................................
  SELECT count(*) FROM t1 WHERE a = x'12345678'
} 1

do_execsql_test 75.3 { 
  SELECT count(*) FROM t1 WHERE b = x'12345678'
} 1


























finish_test








<







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
96
97
98
99
100
101
102

103
104
105
106
107
108
109
....
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
#
do_execsql_test 3.3 { INSERT INTO t1 VALUES('one', '111') } {}


#-------------------------------------------------------------------------
reset_db


do_execsql_test 4.1 { CREATE TABLE t1(k PRIMARY KEY, v) }
do_execsql_test 4.2 { CREATE INDEX i1 ON t1(v) }

do_execsql_test 4.3 { 
  SELECT * FROM sqlite_master
} {
  table t1 t1 2 {CREATE TABLE t1(k PRIMARY KEY, v)} 
................................................................................
  SELECT count(*) FROM t1 WHERE a = x'12345678'
} 1

do_execsql_test 75.3 { 
  SELECT count(*) FROM t1 WHERE b = x'12345678'
} 1

#-------------------------------------------------------------------------
# Real vs. integer values.
#
reset_db
do_execsql_test 76.1 {
  CREATE TABLE t1(a REAL);
  CREATE TABLE log(x);
  CREATE TRIGGER BEFORE INSERT ON t1 BEGIN
    INSERT INTO log VALUES('value = ' || new.a);
  END;
}

do_execsql_test 76.2 { INSERT INTO t1 VALUES(-23) }
do_execsql_test 76.3 {
  SELECT * FROM log;
} {{value = -23.0}}

do_execsql_test 76.4 {
  CREATE TABLE t2(a REAL, str);
}
do_execsql_test 76.5 {
  INSERT INTO t2 VALUES(0.0012345, '');
}
do_execsql_test 76.6 { SELECT cast(a AS TEXT) FROM t2 } {0.0012345}

finish_test