Changeset: 1bdd5b492adc for MonetDB URL: https://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=1bdd5b492adc Added Files: gdk/gdk_analytic.c gdk/gdk_analytic.h sql/backends/monet5/sql_rank.mal.sh sql/backends/monet5/sql_rank_hge.mal sql/backends/monet5/sql_rank_hge.mal.sh Modified Files: gdk/Makefile.ag sql/backends/monet5/Makefile.ag sql/backends/monet5/sql_rank.c sql/backends/monet5/sql_rank.h sql/backends/monet5/sql_rank.mal sql/common/sql_types.c sql/test/analytics/Tests/analytics00.sql sql/test/analytics/Tests/analytics00.stable.out Branch: analytics Log Message:
First implementation for sum analytical function over a window. Also moved analytical functions implementation to the GDK layer. Still missing floating-point sum implementation, it's complex :( diffs (truncated from 1432 to 300 lines): diff --git a/gdk/Makefile.ag b/gdk/Makefile.ag --- a/gdk/Makefile.ag +++ b/gdk/Makefile.ag @@ -34,6 +34,7 @@ lib_gdk = { gdk_unique.c \ gdk_interprocess.c gdk_interprocess.h \ gdk_firstn.c \ + gdk_analytic.c gdk_analytic.h \ libbat.rc LIBS = ../common/options/libmoptions \ ../common/utils/libmutils \ @@ -52,6 +53,7 @@ headers_h = { HEADERS = h SOURCES = \ gdk.h \ + gdk_analytic.h \ gdk_atomic.h \ gdk_atoms.h \ gdk_bbp.h \ diff --git a/gdk/gdk_analytic.c b/gdk/gdk_analytic.c new file mode 100644 --- /dev/null +++ b/gdk/gdk_analytic.c @@ -0,0 +1,441 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * Copyright 1997 - July 2008 CWI, August 2008 - 2018 MonetDB B.V. + */ + +#include "monetdb_config.h" +#include "gdk.h" +#include "gdk_analytic.h" + +#define ANALYTICAL_LIMIT_IMP(TPE, OP) \ + do { \ + TPE *rp, *rb, *bp, curval; \ + rb = rp = (TPE*)Tloc(r, 0); \ + bp = (TPE*)Tloc(b, 0); \ + curval = *bp; \ + if (p) { \ + if (o) { \ + np = (bit*)Tloc(p, 0); \ + for(i=0; i<cnt; i++, np++, rp++, bp++) { \ + if (*np) { \ + if(is_##TPE##_nil(curval)) \ + has_nils = true; \ + for (;rb < rp; rb++) \ + *rb = curval; \ + curval = *bp; \ + } \ + if(!is_##TPE##_nil(*bp)) { \ + if(is_##TPE##_nil(curval)) \ + curval = *bp; \ + else \ + curval = OP(*bp, curval); \ + } \ + } \ + if(is_##TPE##_nil(curval)) \ + has_nils = true; \ + for (;rb < rp; rb++) \ + *rb = curval; \ + } else { /* single value, ie no ordering */ \ + np = (bit*)Tloc(p, 0); \ + for(i=0; i<cnt; i++, np++, rp++, bp++) { \ + if (*np) { \ + if(is_##TPE##_nil(curval)) \ + has_nils = true; \ + for (;rb < rp; rb++) \ + *rb = curval; \ + curval = *bp; \ + } \ + if(!is_##TPE##_nil(*bp)) { \ + if(is_##TPE##_nil(curval)) \ + curval = *bp; \ + else \ + curval = OP(*bp, curval); \ + } \ + } \ + if(is_##TPE##_nil(curval)) \ + has_nils = true; \ + for (;rb < rp; rb++) \ + *rb = curval; \ + } \ + } else if (o) { /* single value, ie no partitions */ \ + for(i=0; i<cnt; i++, rp++, bp++) { \ + if(!is_##TPE##_nil(*bp)) { \ + if(is_##TPE##_nil(curval)) \ + curval = *bp; \ + else \ + curval = OP(*bp, curval); \ + } \ + } \ + if(is_##TPE##_nil(curval)) \ + has_nils = true; \ + for(;rb < rp; rb++) \ + *rb = curval; \ + } else { /* single value, ie no ordering */ \ + if(is_##TPE##_nil(*bp)) \ + has_nils = true; \ + for(i=0; i<cnt; i++, rp++, bp++) \ + *rp = *bp; \ + } \ + } while(0); + +#ifdef HAVE_HUGE +#define ANALYTICAL_LIMIT_IMP_HUGE(IMP) \ + case TYPE_hge: \ + ANALYTICAL_LIMIT_IMP(hge, IMP) \ + break; +#else +#define ANALYTICAL_LIMIT_IMP_HUGE(IMP) +#endif + +#define ANALYTICAL_LIMIT(OP, IMP, SIGN_OP) \ +gdk_return \ +GDKanalytical##OP(BAT *r, BAT *b, BAT *p, BAT *o, int tpe) \ +{ \ + int (*atomcmp)(const void *, const void *); \ + const void *nil; \ + bool has_nils = false; \ + BUN i, j, cnt = BATcount(b); \ + bit *np; \ + gdk_return gdk_res = GDK_SUCCEED; \ + \ + switch(ATOMstorage(tpe)) { \ + case TYPE_bit: \ + ANALYTICAL_LIMIT_IMP(bit, IMP) \ + break; \ + case TYPE_bte: \ + ANALYTICAL_LIMIT_IMP(bte, IMP) \ + break; \ + case TYPE_sht: \ + ANALYTICAL_LIMIT_IMP(sht, IMP) \ + break; \ + case TYPE_int: \ + ANALYTICAL_LIMIT_IMP(int, IMP) \ + break; \ + case TYPE_lng: \ + ANALYTICAL_LIMIT_IMP(lng, IMP) \ + break; \ + ANALYTICAL_LIMIT_IMP_HUGE(IMP) \ + case TYPE_flt: \ + ANALYTICAL_LIMIT_IMP(flt, IMP) \ + break; \ + case TYPE_dbl: \ + ANALYTICAL_LIMIT_IMP(dbl, IMP) \ + break; \ + default: { \ + BATiter bpi = bat_iterator(b); \ + void *curval = BUNtail(bpi, 0); \ + nil = ATOMnilptr(tpe); \ + atomcmp = ATOMcompare(tpe); \ + if (p) { \ + if (o) { \ + np = (bit*)Tloc(p, 0); \ + for(i=0,j=0; i<cnt; i++, np++) { \ + if (*np) { \ + if((*atomcmp)(curval, nil) == 0) \ + has_nils = true; \ + for (;j < i; j++) { \ + if ((gdk_res = BUNappend(r, curval, false)) != GDK_SUCCEED) \ + goto finish; \ + } \ + curval = BUNtail(bpi, i); \ + } \ + void *next = BUNtail(bpi, i); \ + if((*atomcmp)(next, nil) != 0) { \ + if((*atomcmp)(curval, nil) == 0) \ + curval = next; \ + else \ + curval = atomcmp(next, curval) SIGN_OP 0 ? curval : next; \ + } \ + } \ + if((*atomcmp)(curval, nil) == 0) \ + has_nils = true; \ + for (;j < i; j++) { \ + if ((gdk_res = BUNappend(r, curval, false)) != GDK_SUCCEED) \ + goto finish; \ + } \ + } else { /* single value, ie no ordering */ \ + np = (bit*)Tloc(p, 0); \ + for(i=0,j=0; i<cnt; i++, np++) { \ + if (*np) { \ + if((*atomcmp)(curval, nil) == 0) \ + has_nils = true; \ + for (;j < i; j++) { \ + if ((gdk_res = BUNappend(r, curval, false)) != GDK_SUCCEED) \ + goto finish; \ + } \ + curval = BUNtail(bpi, i); \ + } \ + void *next = BUNtail(bpi, i); \ + if((*atomcmp)(next, nil) != 0) { \ + if((*atomcmp)(curval, nil) == 0) \ + curval = next; \ + else \ + curval = atomcmp(next, curval) SIGN_OP 0 ? curval : next; \ + } \ + } \ + if((*atomcmp)(curval, nil) == 0) \ + has_nils = true; \ + for (;j < i; j++) { \ + if ((gdk_res = BUNappend(r, curval, false)) != GDK_SUCCEED) \ + goto finish; \ + } \ + } \ + } else if (o) { /* single value, ie no partitions */ \ + for(i=0; i<cnt; i++) { \ + void *next = BUNtail(bpi, i); \ + if((*atomcmp)(next, nil) != 0) { \ + if((*atomcmp)(curval, nil) == 0) \ + curval = next; \ + else \ + curval = atomcmp(next, curval) SIGN_OP 0 ? curval : next; \ + } \ + } \ + if((*atomcmp)(curval, nil) == 0) \ + has_nils = true; \ + for (j=0; j < i; j++) { \ + if ((gdk_res = BUNappend(r, curval, false)) != GDK_SUCCEED) \ + goto finish; \ + } \ + } else { /* single value, ie no ordering */ \ + if((*atomcmp)(curval, nil) == 0) \ + has_nils = true; \ + for(i=0; i<cnt; i++) \ + if ((gdk_res = BUNappend(r, curval, false)) != GDK_SUCCEED) \ + goto finish; \ + } \ + } \ + } \ +finish: \ + BATsetcount(r, cnt); \ + r->tnonil = !has_nils; \ + r->tnil = has_nils; \ + return gdk_res; \ +} + +ANALYTICAL_LIMIT(min, MIN, >) +ANALYTICAL_LIMIT(max, MAX, <) + +#undef ANALYTICAL_LIMIT +#undef ANALYTICAL_LIMIT_IMP_HUGE +#undef ANALYTICAL_LIMIT_IMP + +#define ANALYTICAL_ADD_WITH_CHECK(lft, rgt, TPE2, dst, max, on_overflow) \ + do { \ + if ((rgt) < 1) { \ + if (-(max) - (rgt) > (lft)) { \ + on_overflow; \ + } else { \ + (dst) = (TPE2) (lft) + (rgt); \ + } \ + } else { \ + if ((max) - (rgt) < (lft)) { \ + on_overflow; \ + } else { \ + (dst) = (TPE2) (lft) + (rgt); \ + } \ + } \ + } while (0); + +#define ANALYTICAL_SUM_IMP(TPE1, TPE2) \ + do { \ + TPE1 *bp; \ + TPE2 *rp, *rb, curval; \ + bp = (TPE1*)Tloc(b, 0); \ + rb = rp = (TPE2*)Tloc(r, 0); \ + curval = TPE2##_nil; \ + if (p) { \ + if (o) { \ + np = (bit*)Tloc(p, 0); \ + for(i=0; i<cnt; i++, np++, rp++, bp++) { \ + if (*np) { \ + if(is_##TPE2##_nil(curval)) \ + has_nils = true; \ + for (;rb < rp; rb++) \ + *rb = curval; \ + curval = TPE2##_nil; \ + } \ + if (!is_##TPE1##_nil(*bp)) { \ + if(is_##TPE2##_nil(curval)) \ + curval = (TPE2) *bp; \ + else \ + ANALYTICAL_ADD_WITH_CHECK(*bp, curval, \ + TPE2, curval, \ + GDK_##TPE2##_max, \ + goto calc_overflow); \ + } \ + } \ + if(is_##TPE2##_nil(curval)) \ + has_nils = true; \ + for (;rb < rp; rb++) \ + *rb = curval; \ + } else { /* single value, ie no ordering */ \ + np = (bit*)Tloc(p, 0); \ + for(i=0; i<cnt; i++, np++, rp++, bp++) { \ _______________________________________________ checkin-list mailing list checkin-list@monetdb.org https://www.monetdb.org/mailman/listinfo/checkin-list