SQLite

Check-in Differences
Login

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

Difference From 6935ac71bad3d36c To 552b1b106691eddb

2024-06-12
11:39
Slight API doc tweak for xCheckReservedLock(), based on forum feedback. No code changes. (check-in: 2af7a96f68 user: stephan tags: trunk)
10:17
Improvements to the layout and comments for the new round() implementation. (Leaf check-in: d6b1df1a22 user: drh tags: round-up-2)
00:30
Test cases for the round() function for values within one epsilon of the 5 round-up threshold. (check-in: 552b1b1066 user: drh tags: round-up-2)
2024-06-11
22:47
A second approach to working on the round() function so that it gives a small boost to numbers that are ...49999999 such that they round up. (check-in: 44dd632896 user: drh tags: round-up-2)
20:03
Fix a problem with rolling back hot journals using the unix-dotfile VFS. (check-in: 4ae3300b79 user: dan tags: unix-dotfile-fix)
17:37
Merge trunk enhancements into the exists-to-join branch. (check-in: 5f25a9518a user: drh tags: exists-to-join)
17:04
Remove some dead JS code and update some JS docs. (check-in: 6935ac71ba user: stephan tags: trunk)
17:04
When compiling shell.c in SQLITE_SHELL_FIDDLE mode, ensure that the shell_main_exit goto label is reachable. (check-in: 06e6f64533 user: stephan tags: trunk)
2024-06-10
14:31
Change the rounding behavior of float point to decimal conversions such that if the next digit is 4 but the value is within one epsilon of the next digit being 5 and if the epsilon is small compared the number of digits to be rendered, then go ahead and round up anyhow, even though the correct behavior would be to round down. (check-in: 4a790d3b28 user: drh tags: round-up)

Changes to src/func.c.
431
432
433
434
435
436
437






















438
439
440
441
442
443
444
445



446
447


448
449
450
451



452
453
454
455
456
457
458
459
460
461

462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
      p2 = len-p1;
      if( p2<0 ) p2 = 0;
    }
    sqlite3_result_blob64(context, (char*)&z[p1], (u64)p2, SQLITE_TRANSIENT);
  }
}























/*
** Implementation of the round() function
*/
#ifndef SQLITE_OMIT_FLOATING_POINT
static void roundFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
  int n = 0;
  double r;
  char *zBuf;



  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;



  }
  if( sqlite3_value_type(argv[0])==SQLITE_NULL ) return;
  r = sqlite3_value_double(argv[0]);
  /* If Y==0 and X will fit in a 64-bit int,
  ** handle the rounding directly,
  ** otherwise use printf.
  */
  if( r<-4503599627370496.0 || r>+4503599627370496.0 ){
    /* The value has no fractional part so there is nothing to round */
  }else if( n==0 ){ 

    r = (double)((sqlite_int64)(r+(r<0?-0.5:+0.5)));
  }else{
    zBuf = sqlite3_mprintf("%!.*f",n,r);
    if( zBuf==0 ){
      sqlite3_result_error_nomem(context);
      return;
    }
    sqlite3AtoF(zBuf, &r, sqlite3Strlen30(zBuf), SQLITE_UTF8);
    sqlite3_free(zBuf);
  }
  sqlite3_result_double(context, r);
}
#endif

/*
** Allocate nByte bytes of space using sqlite3Malloc(). If the
** allocation fails, call sqlite3_result_error_nomem() to notify







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





|
|
|
>
>
>


>
>




>
>
>



<
<
<
<
<
<
|
>
|

|
<
<
<
|
<
|
<







431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484






485
486
487
488
489



490

491

492
493
494
495
496
497
498
      p2 = len-p1;
      if( p2<0 ) p2 = 0;
    }
    sqlite3_result_blob64(context, (char*)&z[p1], (u64)p2, SQLITE_TRANSIENT);
  }
}

/*
** The library round() function is only available if
** SQLITE_ENABLE_MATH_FUNCTIONS is defined.  Without that macro, we
** have to grow our own.
**
** The sqlite3Round(x) routine only needs to deal with non-negative
** numbers.
*/
#ifdef SQLITE_ENABLE_MATH_FUNCTIONS
# define sqlite3Round(X) round(X)
#else
static double sqlite3Round(double x){
  assert( x>=0.0 );
  if( x>+4503599627370496.0 ){
    return x;
  }else{
    sqlite3_int64 ii = (sqlite3_int64)(x+0.5);
    return (double)ii;
  }
}
#endif

/*
** Implementation of the round() function
*/
#ifndef SQLITE_OMIT_FLOATING_POINT
static void roundFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
  int n = 0;        /* Second argument. Digits to the right of decimal point */
  double r;         /* First argument.  Value to be rounded */
  double rX = 1.0;  /* Scaling factor.  pow(10,n) */
  double rSgn;      /* Sign of the first first */
  static const double rTwoPowerMinus52 =  /* pow(2,-52) */
                           2.220446049250313080847263336181640625e-16;
  assert( argc==1 || argc==2 );
  if( argc==2 ){
    double rY = 10;
    int i;
    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;
    for(i=n, rY=10; i>0; i>>=1, rY=rY*rY){
      if( i&1 ) rX *= rY;
    }
  }
  if( sqlite3_value_type(argv[0])==SQLITE_NULL ) return;
  r = sqlite3_value_double(argv[0]);






  if( r<0 ){
    rSgn = -1.0;
    r = -r;
  }else{
    rSgn = 1.0;



  }

  r = rSgn*sqlite3Round(r*rX + rX*r*rTwoPowerMinus52)/rX;

  sqlite3_result_double(context, r);
}
#endif

/*
** Allocate nByte bytes of space using sqlite3Malloc(). If the
** allocation fails, call sqlite3_result_error_nomem() to notify
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
  int argc,
  sqlite3_value **argv
){
  assert( argc==0 );
  (void)argv;
  sqlite3_result_double(context, M_PI);
}

#endif /* SQLITE_ENABLE_MATH_FUNCTIONS */

/*
** Implementation of sign(X) function.
*/
static void signFunc(
  sqlite3_context *context,







<







2521
2522
2523
2524
2525
2526
2527

2528
2529
2530
2531
2532
2533
2534
  int argc,
  sqlite3_value **argv
){
  assert( argc==0 );
  (void)argv;
  sqlite3_result_double(context, M_PI);
}

#endif /* SQLITE_ENABLE_MATH_FUNCTIONS */

/*
** Implementation of sign(X) function.
*/
static void signFunc(
  sqlite3_context *context,
Added test/round2.test.




































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
# 2024-06-10
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# 
#  https://sqlite.org/forum/forumpost/c0753dfb2d5d7f75
#

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

load_static_extension db stmtrand ieee754
do_execsql_test 1.1 {
  WITH RECURSIVE
    c(n) AS (VALUES(0) UNION ALL SELECT n+1 FROM c WHERE n<100000),
    r(a,b) AS MATERIALIZED (SELECT stmtrand()%100000, stmtrand()%100000 FROM c),
    f(x,y,n) AS (
       SELECT CAST(format('%d.%d5',a,b) AS real),
              CAST(format('%d.%d6',a,b) AS real),
               length(format('%d',b)) FROM r)
    SELECT x, n, round(x,n), round(y,n) FROM f
     WHERE round(x,n)<>round(y,n);

} {}
do_execsql_test 1.2 {
  SELECT round(0.15,1);
} 0.2
do_execsql_test 1.3 {
  SELECT round(0.14999999999999999,1);
} 0.2
do_execsql_test 1.4 {
  SELECT round(0.1499999999999999944488848768742172978818416595458984375,1);
} 0.2
do_execsql_test 1.5 {
  SELECT round(ieee754_from_blob(x'3fc3333333333333'),1);
} 0.2
do_execsql_test 1.6 {
  SELECT round(ieee754_from_blob(x'3fc3333333333332'),1);
} 0.1



finish_test