Changeset: 310a5d3fa000 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=310a5d3fa000
Added Files:
        sql/test/BugTracker-2009/Tests/AVG_of_SQRT.SF-2757642.sql
        
sql/test/BugTracker-2017/Tests/insert_into_multiple_subqueries.Bug-6448.sql
        
sql/test/BugTracker-2017/Tests/insert_into_multiple_subqueries.Bug-6448.stable.err
        
sql/test/BugTracker-2017/Tests/insert_into_multiple_subqueries.Bug-6448.stable.out
        
sql/test/BugTracker-2017/Tests/sqlitelogictest-cast-decimal.Bug-6445.stable.err
        
sql/test/BugTracker-2017/Tests/sqlitelogictest-cast-decimal.Bug-6445.stable.out
        sql/test/BugTracker-2017/Tests/sqlsmith.Bug-6449.sql
        sql/test/BugTracker-2017/Tests/sqlsmith.Bug-6449.stable.err
        sql/test/BugTracker-2017/Tests/sqlsmith.Bug-6449.stable.out
        sql/test/BugTracker-2017/Tests/table_returning_with.Bug-6444.sql
        sql/test/BugTracker-2017/Tests/table_returning_with.Bug-6444.stable.err
        sql/test/BugTracker-2017/Tests/table_returning_with.Bug-6444.stable.out
        sql/test/Tests/fsum.sql
        sql/test/Tests/fsum.stable.err
        sql/test/Tests/fsum.stable.out
Removed Files:
        sql/test/BugTracker-2009/Tests/AVG_of_SQRT.SF-2757642.SQL.py
Modified Files:
        gdk/ChangeLog.Jul2017
        gdk/gdk_aggr.c
        gdk/gdk_utils.c
        monetdb5/mal/mal_parser.c
        sql/backends/monet5/sql_gencode.c
        sql/server/rel_optimizer.c
        sql/server/rel_select.c
        sql/server/rel_sequence.c
        sql/server/rel_updates.c
        sql/server/sql_parser.h
        sql/server/sql_parser.y
        sql/server/sql_privileges.c
        sql/server/sql_scan.c
        sql/test/BugTracker-2009/Tests/AVG_of_SQRT.SF-2757642.stable.out
        sql/test/BugTracker-2017/Tests/All
        sql/test/BugTracker/Tests/drop_schema_crash.SF-1504794.stable.err
        sql/test/BugTracker/Tests/set_a_new_user_password.SF-1844050.stable.err
        sql/test/Dependencies/Tests/Dependencies.stable.err
        sql/test/Tests/All
        sql/test/emptydb-upgrade-chain-hge/Tests/upgrade.stable.out.int128
        sql/test/emptydb-upgrade-chain/Tests/upgrade.stable.out
        sql/test/emptydb-upgrade-chain/Tests/upgrade.stable.out.int128
        sql/test/emptydb-upgrade-hge/Tests/upgrade.stable.out.int128
        sql/test/emptydb-upgrade/Tests/upgrade.stable.out
        sql/test/emptydb-upgrade/Tests/upgrade.stable.out.int128
        sql/test/testdb-upgrade-chain-hge/Tests/upgrade.stable.out.int128
        sql/test/testdb-upgrade-chain/Tests/upgrade.stable.out
        sql/test/testdb-upgrade-chain/Tests/upgrade.stable.out.int128
        sql/test/testdb-upgrade-hge/Tests/upgrade.stable.out.int128
        sql/test/testdb-upgrade/Tests/upgrade.stable.out
        sql/test/testdb-upgrade/Tests/upgrade.stable.out.int128
        tools/merovingian/daemon/merovingian.c
Branch: default
Log Message:

Merge with Jul2017


diffs (truncated from 5073 to 300 lines):

diff --git a/gdk/ChangeLog.Jul2017 b/gdk/ChangeLog.Jul2017
--- a/gdk/ChangeLog.Jul2017
+++ b/gdk/ChangeLog.Jul2017
@@ -1,3 +1,10 @@
 # ChangeLog file for MonetDB
 # This file is updated with Maddlog
 
+* Mon Oct 30 2017 Sjoerd Mullender <sjo...@acm.org>
+- Reimplemented summing of a column of floating point (flt and dbl)
+  values.  The old code could give wildly inaccurate results when adding
+  up lots and lots of values due to lack of precision.  Try SELECT sum(c)
+  FROM t; where t is 100,000,000 rows, c is of type REAL and all values
+  are equal to 1.1.  (The old code returned 33554432 instead of 1.1e8.)
+
diff --git a/gdk/gdk_aggr.c b/gdk/gdk_aggr.c
--- a/gdk/gdk_aggr.c
+++ b/gdk/gdk_aggr.c
@@ -147,6 +147,292 @@ BATgroupaggrinit(BAT *b, BAT *g, BAT *e,
 /* ---------------------------------------------------------------------- */
 /* sum */
 
+#if defined(_MSC_VER) && _MSC_VER < 1800
+#define isnan(x)       _isnan(x)
+#define isinf(x)       (_fpclass(x) & (_FPCLASS_NINF | _FPCLASS_PINF))
+#endif
+
+static inline int
+samesign(double x, double y)
+{
+       return (x >= 0) == (y >= 0);
+}
+
+/* Add two values, producing the sum and the remainder due to limited
+ * range of floating point arithmetic.  This function depends on the
+ * fact that the sum returns INFINITY in *hi of the correct sign
+ * (i.e. isinf() returns TRUE) in case of overflow. */
+static inline void
+twosum(double *hi, double *lo, double x, double y)
+{
+       volatile double yr;
+
+       assert(fabs(x) >= fabs(y));
+
+       *hi = x + y;
+       yr = *hi - x;
+       *lo = y - yr;
+}
+
+static inline void
+exchange(double *x, double *y)
+{
+       double t = *x;
+       *x = *y;
+       *y = t;
+}
+
+static BUN
+dofsum(const void *restrict values, oid seqb, BUN start, BUN end,
+       void *restrict results, BUN ngrp, int tp1, int tp2,
+       const oid *restrict cand, const oid *candend, const oid *restrict gids,
+       oid min, oid max, int skip_nils, int abort_on_error,
+       int nil_if_empty, const char *func)
+{
+       struct pergroup {
+               size_t npartials;
+               size_t maxpartials;
+               double *partials;
+               int valseen;
+       } *pergroup;
+       size_t listi;
+       size_t parti;
+       size_t i;
+       BUN grp;
+       double x, y;
+       double lo, hi;
+       double twopow = pow((double) FLT_RADIX, (double) (DBL_MAX_EXP - 1));
+       BUN nils = 0;
+
+       ALGODEBUG fprintf(stderr, "#%s: floating point summation\n", func);
+       /* we only deal with the two floating point types */
+       assert(tp1 == TYPE_flt || tp1 == TYPE_dbl);
+       assert(tp2 == TYPE_flt || tp2 == TYPE_dbl);
+       /* if input is dbl, then so it output */
+       assert(tp2 == TYPE_flt || tp1 == TYPE_dbl);
+       /* if no gids, then we have a single group */
+       assert(ngrp == 1 || gids != NULL);
+       if (gids == NULL || ngrp == 1) {
+               min = max = 0;
+               ngrp = 1;
+               gids = NULL;
+       }
+       pergroup = GDKmalloc(ngrp * sizeof(*pergroup));
+       if (pergroup == NULL)
+               return BUN_NONE;
+       for (grp = 0; grp < ngrp; grp++) {
+               pergroup[grp].npartials = 1;
+               pergroup[grp].valseen = 0;
+               pergroup[grp].maxpartials = 32;
+               pergroup[grp].partials = GDKmalloc(pergroup[grp].maxpartials * 
sizeof(double));
+               if (pergroup[grp].partials == NULL) {
+                       while (grp > 0)
+                               GDKfree(pergroup[--grp].partials);
+                       GDKfree(pergroup);
+                       return BUN_NONE;
+               }
+               pergroup[grp].partials[0] = 0;
+       }
+       for (;;) {
+               if (cand) {
+                       if (cand >= candend)
+                               break;
+                       listi = *cand++ - seqb;
+               } else {
+                       if (start >= end)
+                               break;
+                       listi = start++;
+               }
+               grp = gids ? gids[listi] : 0;
+               if (grp < min || grp > max)
+                       continue;
+               if (pergroup[grp].partials == NULL)
+                       continue;
+               if (tp1 == TYPE_flt && ((const flt *) values)[listi] != flt_nil)
+                       x = ((const flt *) values)[listi];
+               else if (tp1 == TYPE_dbl && ((const dbl *) values)[listi] != 
dbl_nil)
+                       x = ((const dbl *) values)[listi];
+               else {
+                       /* it's a nil */
+                       if (!skip_nils) {
+                               if (tp2 == TYPE_flt)
+                                       ((flt *) results)[grp] = flt_nil;
+                               else
+                                       ((dbl *) results)[grp] = dbl_nil;
+                               GDKfree(pergroup[grp].partials);
+                               pergroup[grp].partials = NULL;
+                               if (++nils == ngrp)
+                                       break;
+                       }
+                       continue;
+               }
+               pergroup[grp].valseen = 1;
+               i = 1;
+               for (parti = 1; parti < pergroup[grp].npartials; parti++) {
+                       y = pergroup[grp].partials[parti];
+                       if (fabs(x) < fabs(y))
+                               exchange(&x, &y);
+                       twosum(&hi, &lo, x, y);
+                       if (isinf(hi)) {
+                               int sign = hi > 0 ? 1 : -1;
+                               x = x - twopow * sign - twopow * sign;
+                               pergroup[grp].partials[0] += sign;
+                               if (fabs(x) < fabs(y))
+                                       exchange(&x, &y);
+                               twosum(&hi, &lo, x, y);
+                       }
+                       if (lo != 0)
+                               pergroup[grp].partials[i++] = lo;
+                       x = hi;
+               }
+               if (x != 0) {
+                       if (i == pergroup[grp].maxpartials - 1) {
+                               /* -1 to make sure we have one spare
+                                 * for the final step below */
+                               double *temp;
+                               pergroup[grp].maxpartials += 
pergroup[grp].maxpartials;
+                               temp = GDKrealloc(pergroup[grp].partials, 
pergroup[grp].maxpartials);
+                               if (temp == NULL)
+                                       goto bailout;
+                               pergroup[grp].partials = temp;
+                       }
+                       pergroup[grp].partials[i++] = x;
+               }
+               pergroup[grp].npartials = i;
+       }
+
+       for (grp = 0; grp < ngrp; grp++) {
+               if (pergroup[grp].partials == NULL)
+                       continue;
+               if (!pergroup[grp].valseen) {
+                       if (tp2 == TYPE_flt)
+                               ((flt *) results)[grp] = nil_if_empty ? flt_nil 
: 0;
+                       else
+                               ((dbl *) results)[grp] = nil_if_empty ? dbl_nil 
: 0;
+                       nils += nil_if_empty;
+                       GDKfree(pergroup[grp].partials);
+                       pergroup[grp].partials = NULL;
+                       continue;
+               }
+               if (isinf(pergroup[grp].partials[0]) ||
+                   isnan(pergroup[grp].partials[0])) {
+                       /* isnan: cannot happen: infinities of both
+                        * signs in summands */
+                       if (abort_on_error) {
+                               goto overflow;
+                       }
+                       if (tp2 == TYPE_flt)
+                               ((flt *) results)[grp] = flt_nil;
+                       else
+                               ((dbl *) results)[grp] = dbl_nil;
+                       nils++;
+                       GDKfree(pergroup[grp].partials);
+                       pergroup[grp].partials = NULL;
+                       continue;
+               }
+
+               if (fabs(pergroup[grp].partials[0]) == 1.0 &&
+                   pergroup[grp].npartials > 1 &&
+                   !samesign(pergroup[grp].partials[0], 
pergroup[grp].partials[pergroup[grp].npartials - 1])) {
+                       twosum(&hi, &lo, pergroup[grp].partials[0] * twopow, 
pergroup[grp].partials[pergroup[grp].npartials - 1] / 2);
+                       if (isinf(2 * hi)) {
+                               if (hi + 2 * lo - hi == 2 * lo &&
+                                   pergroup[grp].npartials > 2 &&
+                                   samesign(lo, 
pergroup[grp].partials[pergroup[grp].npartials - 2])) {
+                                       GDKfree(pergroup[grp].partials);
+                                       pergroup[grp].partials = NULL;
+                                       x = 2 * (hi + 2 * lo);
+                                       if (tp2 == TYPE_flt) {
+                                               if (x > GDK_flt_max ||
+                                                   x <= GDK_flt_min) {
+                                                       if (abort_on_error)
+                                                               goto overflow;
+                                                       ((flt *) results)[grp] 
= flt_nil;
+                                                       nils++;
+                                               } else
+                                                       ((flt *) results)[grp] 
= (flt) x;
+                                       } else if (x == GDK_dbl_min) {
+                                               if (abort_on_error)
+                                                       goto overflow;
+                                               ((dbl *) results)[grp] = 
dbl_nil;
+                                               nils++;
+                                       } else
+                                               ((dbl *) results)[grp] = x;
+                                       continue;
+                               }
+                       } else {
+                               if (lo) {
+                                       /* we made sure above that we
+                                        * have space for one more
+                                        * partial */
+                                       
pergroup[grp].partials[pergroup[grp].npartials - 1] = 2 * lo;
+                                       
pergroup[grp].partials[pergroup[grp].npartials++] = 2 * hi;
+                               } else {
+                                       
pergroup[grp].partials[pergroup[grp].npartials - 1] = 2 * hi;
+                               }
+                               pergroup[grp].partials[0] = 0;
+                       }
+               }
+
+               if (pergroup[grp].npartials == 0) {
+                       GDKfree(pergroup[grp].partials);
+                       pergroup[grp].partials = NULL;
+                       if (tp2 == TYPE_flt)
+                               ((flt *) results)[grp] = 0;
+                       else
+                               ((dbl *) results)[grp] = 0;
+                       continue;
+               }
+               if (pergroup[grp].partials[0] != 0)
+                       goto overflow;
+
+               /* accumulate into x */
+               x = pergroup[grp].partials[--pergroup[grp].npartials];
+               while (pergroup[grp].npartials > 0) {
+                       twosum(&x, &lo, x, 
pergroup[grp].partials[--pergroup[grp].npartials]);
+                       if (lo) {
+                               
pergroup[grp].partials[pergroup[grp].npartials++] = lo;
+                               break;
+                       }
+               }
+
+               if (pergroup[grp].npartials >= 2 &&
+                   samesign(pergroup[grp].partials[pergroup[grp].npartials - 
1], pergroup[grp].partials[pergroup[grp].npartials - 2]) &&
+                   x + 2 * pergroup[grp].partials[pergroup[grp].npartials - 1] 
- x == 2 * pergroup[grp].partials[pergroup[grp].npartials - 1]) {
+                       x += 2 * pergroup[grp].partials[pergroup[grp].npartials 
- 1];
+                       pergroup[grp].partials[pergroup[grp].npartials - 1] = 
-pergroup[grp].partials[pergroup[grp].npartials - 1];
+               }
+
+               GDKfree(pergroup[grp].partials);
+               pergroup[grp].partials = NULL;
+               if (tp2 == TYPE_flt) {
+                       if (x > GDK_flt_max || x <= GDK_flt_min) {
+                               if (abort_on_error)
+                                       goto overflow;
+                               ((flt *) results)[grp] = flt_nil;
+                               nils++;
+                       } else
+                               ((flt *) results)[grp] = (flt) x;
+               } else if (x == GDK_dbl_min) {
+                       if (abort_on_error)
+                               goto overflow;
+                       ((dbl *) results)[grp] = dbl_nil;
+                       nils++;
+               } else
+                       ((dbl *) results)[grp] = x;
+       }
+       GDKfree(pergroup);
+       return nils;
+
+  overflow:
+       GDKerror("22003!overflow in calculation.\n");
_______________________________________________
checkin-list mailing list
checkin-list@monetdb.org
https://www.monetdb.org/mailman/listinfo/checkin-list

Reply via email to