/ Check-in [4f47c3c8]
Login

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

Overview
Comment:Make the round() function work correctly on numbers with very large exponents. Ticket #1340. (CVS 2585)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1:4f47c3c884e38b810450b6127ab33c7b86e6743c
User & Date: drh 2005-08-13 03:07:47
Context
2005-08-13
12:59
Add the "!" flag to the "%g" mprintf conversion parameter to force a decimal point. This prevents floating point values from appearing as integers. Use this flag when converting floating point to text. Ticket #1362. (CVS 2586) check-in: 4b98dace user: drh tags: trunk
03:07
Make the round() function work correctly on numbers with very large exponents. Ticket #1340. (CVS 2585) check-in: 4f47c3c8 user: drh tags: trunk
00:56
Fix a memory leak that occurs when a CREATE TABLE that contains a DEFAULT VALUE fails due to a name conflict. Tickets #1356 and #1357. (CVS 2584) check-in: 25cfe939 user: drh tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/func.c.

12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
...
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
** This file contains the C functions that implement various SQL
** functions of SQLite.  
**
** There is only one exported symbol in this file - the function
** sqliteRegisterBuildinFunctions() found at the bottom of the file.
** All other code has file scope.
**
** $Id: func.c,v 1.102 2005/07/09 02:38:06 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>
#include <math.h>
#include <stdlib.h>
#include <assert.h>
#include "vdbeInt.h"
................................................................................

/*
** Implementation of the round() function
*/
static void roundFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
  int n = 0;
  double r;
  char zBuf[100];
  assert( argc==1 || argc==2 );
  if( argc==2 ){
    if( SQLITE_NULL==sqlite3_value_type(argv[1]) ) return;
    n = sqlite3_value_int(argv[1]);
    if( n>30 ) n = 30;
    if( n<0 ) n = 0;
  }







|







 







|







12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
...
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
** This file contains the C functions that implement various SQL
** functions of SQLite.  
**
** There is only one exported symbol in this file - the function
** sqliteRegisterBuildinFunctions() found at the bottom of the file.
** All other code has file scope.
**
** $Id: func.c,v 1.103 2005/08/13 03:07:47 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>
#include <math.h>
#include <stdlib.h>
#include <assert.h>
#include "vdbeInt.h"
................................................................................

/*
** Implementation of the round() function
*/
static void roundFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
  int n = 0;
  double r;
  char zBuf[500];  /* larger than the %f representation of the largest double */
  assert( argc==1 || argc==2 );
  if( argc==2 ){
    if( SQLITE_NULL==sqlite3_value_type(argv[1]) ) return;
    n = sqlite3_value_int(argv[1]);
    if( n>30 ) n = 30;
    if( n<0 ) n = 0;
  }

Changes to src/printf.c.

432
433
434
435
436
437
438

439
440
441
442
443
444
445
        /* It makes more sense to use 0.5 */
        for(idx=precision, rounder=0.5; idx>0; idx--, rounder*=0.1);
#endif
        if( infop->type==etFLOAT ) realvalue += rounder;
        /* Normalize realvalue to within 10.0 > realvalue >= 1.0 */
        exp = 0;
        if( realvalue>0.0 ){

          while( realvalue>=1e8 && exp<=350 ){ realvalue *= 1e-8; exp+=8; }
          while( realvalue>=10.0 && exp<=350 ){ realvalue *= 0.1; exp++; }
          while( realvalue<1e-8 && exp>=-350 ){ realvalue *= 1e8; exp-=8; }
          while( realvalue<1.0 && exp>=-350 ){ realvalue *= 10.0; exp--; }
          if( exp>350 || exp<-350 ){
            bufpt = "NaN";
            length = 3;







>







432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
        /* It makes more sense to use 0.5 */
        for(idx=precision, rounder=0.5; idx>0; idx--, rounder*=0.1);
#endif
        if( infop->type==etFLOAT ) realvalue += rounder;
        /* Normalize realvalue to within 10.0 > realvalue >= 1.0 */
        exp = 0;
        if( realvalue>0.0 ){
          while( realvalue>=1e32 && exp<=350 ){ realvalue *= 1e-32; exp+=32; }
          while( realvalue>=1e8 && exp<=350 ){ realvalue *= 1e-8; exp+=8; }
          while( realvalue>=10.0 && exp<=350 ){ realvalue *= 0.1; exp++; }
          while( realvalue<1e-8 && exp>=-350 ){ realvalue *= 1e8; exp-=8; }
          while( realvalue<1.0 && exp>=-350 ){ realvalue *= 10.0; exp--; }
          if( exp>350 || exp<-350 ){
            bufpt = "NaN";
            length = 3;

Changes to test/printf.test.

7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
..
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
...
170
171
172
173
174
175
176

177





178
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this file is testing the sqlite_*_printf() interface.
#
# $Id: printf.test,v 1.14 2004/09/09 00:35:30 drh Exp $

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

set n 1
foreach v {1 2 5 10 99 100 1000000 999999999 0 -1 -2 -5 -10 -99 -100 -9999999} {
  set v32 [expr {$v&0xffffffff}]
................................................................................
      sqlite3_mprintf_double {A double: %d %d %010g} $a $b $x
    }] [format {A double: %d %d %010g} $a $b $x]
    incr n
  }
  incr m
}

}

do_test printf-3.1 {
  sqlite3_mprintf_str {A String: (%*.*s)} 10 10 {This is the string}
} [format {A String: (%*.*s)} 10 10 {This is the string}]
do_test printf-3.2 {
  sqlite3_mprintf_str {A String: (%*.*s)} 10 5 {This is the string}
} [format {A String: (%*.*s)} 10 5 {This is the string}]
................................................................................

# Ticket #831
#
do_test printf-10.2 {
  sqlite3_mprintf_stronly %q {}
} {}








finish_test







|







 







|







 







>
|
>
>
>
>
>

7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
..
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
...
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this file is testing the sqlite_*_printf() interface.
#
# $Id: printf.test,v 1.15 2005/08/13 03:07:47 drh Exp $

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

set n 1
foreach v {1 2 5 10 99 100 1000000 999999999 0 -1 -2 -5 -10 -99 -100 -9999999} {
  set v32 [expr {$v&0xffffffff}]
................................................................................
      sqlite3_mprintf_double {A double: %d %d %010g} $a $b $x
    }] [format {A double: %d %d %010g} $a $b $x]
    incr n
  }
  incr m
}

}  ;# endif not windows

do_test printf-3.1 {
  sqlite3_mprintf_str {A String: (%*.*s)} 10 10 {This is the string}
} [format {A String: (%*.*s)} 10 10 {This is the string}]
do_test printf-3.2 {
  sqlite3_mprintf_str {A String: (%*.*s)} 10 5 {This is the string}
} [format {A String: (%*.*s)} 10 5 {This is the string}]
................................................................................

# Ticket #831
#
do_test printf-10.2 {
  sqlite3_mprintf_stronly %q {}
} {}

# Ticket #1340:  Test for loss of precision on large positive exponents
#
do_test printf-10.3 {
  sqlite3_mprintf_double {%d %d %f} 1 1 1e300
} {1 1 1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.000000}


finish_test