/ Check-in [f084f5a8]
Login

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

Overview
Comment:Updated sqlite3AtoF() that performs slightly better with GCC, and significantly better with MSVC.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1:f084f5a8ba850de627ca8e9de6c81ab1ad9b7a1b
User & Date: shane 2009-08-21 02:13:14
Context
2009-08-21
08:29
Add assert() statements to os_unix.c to check that the mutex is held when it should be. check-in: 11a669b6 user: dan tags: trunk
02:13
Updated sqlite3AtoF() that performs slightly better with GCC, and significantly better with MSVC. check-in: f084f5a8 user: shane tags: trunk
02:07
Updates for test_init.c for configure and other consistency changes. check-in: 3ba316e9 user: shane tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/util.c.

10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
...
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

303
304
305
306
307





308
309
310
311
312
313
314
315
316


317
318
319
320
321

322
323


324
325
326

327
328
329
330
331

332
333
334
335
336
337

338
339

340
341
342





























343
344
345
346
347

348
349

350


351



352


353
354
355
356
357
358
359
...
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
**
*************************************************************************
** Utility functions used throughout sqlite.
**
** This file contains functions for allocating memory, comparing
** strings, and stuff like that.
**
** $Id: util.c,v 1.262 2009/07/28 16:44:26 danielk1977 Exp $
*/
#include "sqliteInt.h"
#include <stdarg.h>
#ifdef SQLITE_HAVE_ISNAN
# include <math.h>
#endif

................................................................................
    while( sqlite3Isdigit(*z) ){ z += incr; }
    *realnum = 1;
  }
  return *z==0;
}

/*
** The string z[] is an ascii representation of a real number.
** Convert this string to a double.
**
** This routine assumes that z[] really is a valid number.  If it
** is not, the result is undefined.
**
** This routine is used instead of the library atof() function because
** the library atof() might want to use "," as the decimal point instead
** of "." depending on how locale is set.  But that would cause problems
** for SQL.  So this routine always uses "." regardless of locale.
*/
int sqlite3AtoF(const char *z, double *pResult){
#ifndef SQLITE_OMIT_FLOATING_POINT
  int sign = 1;
  const char *zBegin = z;

  LONGDOUBLE_TYPE v1 = 0.0;
  int nSignificant = 0;







  while( sqlite3Isspace(*z) ) z++;

  if( *z=='-' ){
    sign = -1;
    z++;
  }else if( *z=='+' ){
    z++;
  }

  while( z[0]=='0' ){
    z++;
  }

  while( sqlite3Isdigit(*z) ){
    v1 = v1*10.0 + (*z - '0');
    z++;
    nSignificant++;
  }





  if( *z=='.' ){
    LONGDOUBLE_TYPE divisor = 1.0;
    z++;
    if( nSignificant==0 ){
      while( z[0]=='0' ){
        divisor *= 10.0;
        z++;
      }
    }


    while( sqlite3Isdigit(*z) ){
      if( nSignificant<18 ){
        v1 = v1*10.0 + (*z - '0');
        divisor *= 10.0;
        nSignificant++;

      }
      z++;


    }
    v1 /= divisor;
  }

  if( *z=='e' || *z=='E' ){
    int esign = 1;
    int eval = 0;
    LONGDOUBLE_TYPE scale = 1.0;
    z++;

    if( *z=='-' ){
      esign = -1;
      z++;
    }else if( *z=='+' ){
      z++;
    }

    while( sqlite3Isdigit(*z) ){
      eval = eval*10 + *z - '0';

      z++;
    }
    while( eval>=64 ){ scale *= 1.0e+64; eval -= 64; }





























    while( eval>=16 ){ scale *= 1.0e+16; eval -= 16; }
    while( eval>=4 ){ scale *= 1.0e+4; eval -= 4; }
    while( eval>=1 ){ scale *= 1.0e+1; eval -= 1; }
    if( esign<0 ){
      v1 /= scale;

    }else{
      v1 *= scale;

    }


  }



  *pResult = (double)(sign<0 ? -v1 : v1);


  return (int)(z - zBegin);
#else
  return sqlite3Atoi64(z, pResult);
#endif /* SQLITE_OMIT_FLOATING_POINT */
}

/*
................................................................................
}



#if !defined(SQLITE_OMIT_BLOB_LITERAL) || defined(SQLITE_HAS_CODEC)
/*
** Translate a single byte of Hex into an integer.
** This routinen only works if h really is a valid hexadecimal
** character:  0..9a..fA..F
*/
static u8 hexToInt(int h){
  assert( (h>='0' && h<='9') ||  (h>='a' && h<='f') ||  (h>='A' && h<='F') );
#ifdef SQLITE_ASCII
  h += 9*(1&(h>>6));
#endif







<







 







|












<

>
|
|
>
>
>
>
>
>
>

>






>
|
<
|
>
|
|
<
|

>
>
>
>
>

<

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

<
<
<

>






>

<
>


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







 







|







10
11
12
13
14
15
16

17
18
19
20
21
22
23
...
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
303
304
305
306
307
308

309
310
311
312

313
314
315
316
317
318
319
320

321






322
323
324

325


326
327

328
329
330

331
332
333



334
335
336
337
338
339
340
341
342
343

344
345
346

347
348
349
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
379

380
381

382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
...
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
**
*************************************************************************
** Utility functions used throughout sqlite.
**
** This file contains functions for allocating memory, comparing
** strings, and stuff like that.
**

*/
#include "sqliteInt.h"
#include <stdarg.h>
#ifdef SQLITE_HAVE_ISNAN
# include <math.h>
#endif

................................................................................
    while( sqlite3Isdigit(*z) ){ z += incr; }
    *realnum = 1;
  }
  return *z==0;
}

/*
** The string z[] is an ASCII representation of a real number.
** Convert this string to a double.
**
** This routine assumes that z[] really is a valid number.  If it
** is not, the result is undefined.
**
** This routine is used instead of the library atof() function because
** the library atof() might want to use "," as the decimal point instead
** of "." depending on how locale is set.  But that would cause problems
** for SQL.  So this routine always uses "." regardless of locale.
*/
int sqlite3AtoF(const char *z, double *pResult){
#ifndef SQLITE_OMIT_FLOATING_POINT

  const char *zBegin = z;
  /* sign * significand * (10 ^ (esign * exponent)) */
  int sign = 1;   /* sign of significand */
  i64 s = 0;      /* significand */
  int d = 0;      /* adjust exponent for shifting decimal point */
  int esign = 1;  /* sign of exponent */
  int e = 0;      /* exponent */
  double result;
  int nDigits = 0;

  /* skip leading spaces */
  while( sqlite3Isspace(*z) ) z++;
  /* get sign of significand */
  if( *z=='-' ){
    sign = -1;
    z++;
  }else if( *z=='+' ){
    z++;
  }
  /* skip leading zeroes */
  while( z[0]=='0' ) z++, nDigits++;


  /* copy max significant digits to significand */
  while( sqlite3Isdigit(*z) && s<((LARGEST_INT64-9)/10) ){
    s = s*10 + (*z - '0');

    z++, nDigits++;
  }
  /* skip non-significant significand digits
  ** (increase exponent by d to shift decimal left) */
  while( sqlite3Isdigit(*z) ) z++, nDigits++, d++;

  /* if decimal point is present */
  if( *z=='.' ){

    z++;






    /* copy digits from after decimal to significand
    ** (decrease exponent by d to shift decimal right) */
    while( sqlite3Isdigit(*z) && s<((LARGEST_INT64-9)/10) ){

      s = s*10 + (*z - '0');


      z++, nDigits++, d--;
    }

    /* skip non-significant digits */
    while( sqlite3Isdigit(*z) ) z++, nDigits++;
  }


  /* if exponent is present */
  if( *z=='e' || *z=='E' ){



    z++;
    /* get sign of exponent */
    if( *z=='-' ){
      esign = -1;
      z++;
    }else if( *z=='+' ){
      z++;
    }
    /* copy digits to exponent */
    while( sqlite3Isdigit(*z) ){

      e = e*10 + (*z - '0');
      z++;
    }

  }

  /* adjust exponent by d, and update sign */
  e = (e*esign) + d;
  if( e<0 ) {
    esign = -1;
    e *= -1;
  } else {
    esign = 1;
  }

  /* if 0 significand */
  if( !s ) {
    /* In the IEEE 754 standard, zero is signed.
    ** Add the sign if we've seen at least one digit */
    result = (sign<0 && nDigits) ? -(double)0 : (double)0;
  } else {
    /* attempt to reduce exponent */
    if( esign>0 ){
      while( s<(LARGEST_INT64/10) && e>0 ) e--,s*=10;
    }

    /* adjust the sign of significand */
    s = sign<0 ? -s : s;

    /* if exponent, scale significand as appropriate
    ** and store in result. */
    if( e ){
      double scale = 1.0;
      while( e>=16 ){ scale *= 1.0e+16; e -= 16; }
      while( e>=4 ){ scale *= 1.0e+4; e -= 4; }
      while( e>=1 ){ scale *= 1.0e+1; e -= 1; }
      if( esign<0 ){

        result = s / scale;
      }else{

        result = s * scale;
      }
    } else {
      result = (double)s;
    }
  }

  /* store the result */
  *pResult = result;

  /* return number of characters used */
  return (int)(z - zBegin);
#else
  return sqlite3Atoi64(z, pResult);
#endif /* SQLITE_OMIT_FLOATING_POINT */
}

/*
................................................................................
}



#if !defined(SQLITE_OMIT_BLOB_LITERAL) || defined(SQLITE_HAS_CODEC)
/*
** Translate a single byte of Hex into an integer.
** This routine only works if h really is a valid hexadecimal
** character:  0..9a..fA..F
*/
static u8 hexToInt(int h){
  assert( (h>='0' && h<='9') ||  (h>='a' && h<='f') ||  (h>='A' && h<='F') );
#ifdef SQLITE_ASCII
  h += 9*(1&(h>>6));
#endif

Changes to test/nan.test.

309
310
311
312
313
314
315
316
317
318
319
320
} {-9.88131291682493e-324 real}

do_test nan-4.20 {
  db eval {DELETE FROM t1}
  set big [string repeat 9 10000].0e-9000
  db eval "INSERT INTO t1 VALUES($big)"
  db eval {SELECT x, typeof(x) FROM t1}
} {{} null}



finish_test







|




309
310
311
312
313
314
315
316
317
318
319
320
} {-9.88131291682493e-324 real}

do_test nan-4.20 {
  db eval {DELETE FROM t1}
  set big [string repeat 9 10000].0e-9000
  db eval "INSERT INTO t1 VALUES($big)"
  db eval {SELECT x, typeof(x) FROM t1}
} {inf real}



finish_test