Changeset: 3ccd6847f78f for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=3ccd6847f78f
Modified Files:
        gdk/gdk_analytic.h
        gdk/gdk_analytic_func.c
        sql/backends/monet5/sql_rank.c
        sql/backends/monet5/sql_rank.h
        sql/backends/monet5/sql_rank.mal
        sql/backends/monet5/sql_rank.mal.sh
        sql/backends/monet5/sql_rank_hge.mal
        sql/backends/monet5/sql_rank_hge.mal.sh
        sql/backends/monet5/sql_upgrades.c
        sql/scripts/39_analytics.sql
        sql/scripts/39_analytics_hge.sql
        sql/test/analytics/Tests/analytics14.sql
        sql/test/analytics/Tests/analytics14.stable.out
Branch: statistics-analytics
Log Message:

Implemented quantile_avg as a window function


diffs (truncated from 1442 to 300 lines):

diff --git a/gdk/gdk_analytic.h b/gdk/gdk_analytic.h
--- a/gdk/gdk_analytic.h
+++ b/gdk/gdk_analytic.h
@@ -43,6 +43,6 @@ gdk_export gdk_return GDKanalytical_stdd
 gdk_export gdk_return GDKanalytical_variance_samp(BAT *r, BAT *b, BAT *s, BAT 
*e, int tpe);
 gdk_export gdk_return GDKanalytical_variance_pop(BAT *r, BAT *b, BAT *s, BAT 
*e, int tpe);
 gdk_export gdk_return GDKanalytical_quantile(BAT *r, BAT *b, BAT *s, BAT *e, 
BAT *q, const void *restrict quantile, int tp1, int tp2);
-gdk_export gdk_return GDKanalytical_median_avg(BAT *r, BAT *b, BAT *s, BAT *e, 
int tpe);
+gdk_export gdk_return GDKanalytical_quantile_avg(BAT *r, BAT *b, BAT *s, BAT 
*e, BAT *q, const void *restrict quantile, int tp1, int tp2);
 
 #endif //_GDK_ANALYTIC_H_
diff --git a/gdk/gdk_analytic_func.c b/gdk/gdk_analytic_func.c
--- a/gdk/gdk_analytic_func.c
+++ b/gdk/gdk_analytic_func.c
@@ -2003,77 +2003,158 @@ nosupport:
        return GDK_FAIL;
 }
 
-#define ANALYTICAL_MEDIAN_AVG(TPE)     \
-       do { \
-               TPE *restrict bp = (TPE*) Tloc(b, 0), ns, ne; \
-               for (; i < cnt; i++, rb++) { \
-                       ss = (BUN) start[i]; \
-                       ee = (BUN) end[i]; \
-                       f = (ee - ss - 1) * 0.5f; \
-                       lo = floor(f); \
-                       hi = ceil(f); \
-                       ns = bp[ss + (BUN) hi]; \
-                       ne = bp[ss + (BUN) lo]; \
-                       if (is_##TPE##_nil(ns) || is_##TPE##_nil(ne)) { \
-                               v = dbl_nil; \
-                               has_nils = true; \
-                       } else \
-                               v = (f - lo) * ns + (lo + 1 - f) * ne; \
-                       *rb = v; \
+#define ANALYTICAL_QUANTILE_AVG_IMP_SINGLE_FIXED(TPE)                  \
+       do {                                                            \
+               TPE *bp = (TPE*)Tloc(b, 0), ns, ne; \
+               if (is_dbl_nil(qua)) {                                  \
+                       has_nils = true;                                \
+                       for (; i < cnt; i++, rb++)                      \
+                               *rb = dbl_nil;                  \
+               } else {                                                \
+                       for (; i < cnt; i++, rb++) { \
+                               ss = (BUN) start[i]; \
+                               ee = (BUN) end[i]; \
+                               f = (ee - ss - 1) * qua; \
+                               lo = floor(f); \
+                               hi = ceil(f); \
+                               ns = bp[ss + (BUN) hi]; \
+                               ne = bp[ss + (BUN) lo]; \
+                               if (is_##TPE##_nil(ns) || is_##TPE##_nil(ne)) { 
\
+                                       v = dbl_nil; \
+                                       has_nils = true; \
+                               } else \
+                                       v = (f - lo) * ns + (lo + 1 - f) * ne; \
+                               *rb = v; \
+                       }       \
                }       \
        } while (0)
 
+#define ANALYTICAL_QUANTILE_AVG_IMP_MULTI_FIXED(TPE1, TPE2)            \
+       do {                                                            \
+               TPE2 *restrict qp = (TPE2*)Tloc(q, 0);                  \
+               for (; i < cnt; i++, rb++) {                            \
+                       TPE2 qua = qp[i];                               \
+                       if (is_##TPE2##_nil(qua)) { \
+                               *rb = dbl_nil; \
+                               has_nils = true; \
+                       } else { \
+                               ss = (BUN) start[i]; \
+                               ee = (BUN) end[i]; \
+                               f = (ee - ss - 1) * qua; \
+                               lo = floor(f); \
+                               hi = ceil(f); \
+                               ns = bp[ss + (BUN) hi]; \
+                               ne = bp[ss + (BUN) lo]; \
+                               if (is_##TPE1##_nil(ns) || is_##TPE1##_nil(ne)) 
{ \
+                                       v = dbl_nil; \
+                                       has_nils = true; \
+                               } else \
+                                       v = (f - lo) * ns + (lo + 1 - f) * ne; \
+                               *rb = v; \
+                       } \
+               }       \
+       } while (0)
+
+#define ANALYTICAL_QUANTILE_AVG_CALC_FIXED(TPE1)       \
+       do {                                                            \
+               TPE1 *restrict bp = (TPE1*)Tloc(b, 0), ns, ne;          \
+               switch (tp2) {                                          \
+               case TYPE_flt:                                          \
+                       ANALYTICAL_QUANTILE_AVG_IMP_MULTI_FIXED(TPE1, flt); \
+                       break;                                          \
+               case TYPE_dbl:                                          \
+                       ANALYTICAL_QUANTILE_AVG_IMP_MULTI_FIXED(TPE1, dbl); \
+                       break;                                          \
+               default:                                                \
+                       goto nosupport;                                 \
+               }                                                       \
+       } while (0)
+
 gdk_return
-GDKanalytical_median_avg(BAT *r, BAT *b, BAT *s, BAT *e, int tpe)
+GDKanalytical_quantile_avg(BAT *r, BAT *b, BAT *s, BAT *e, BAT *q, const void 
*restrict quantile, int tp1, int tp2)
 {
-       bool has_nils = false;
        BUN i = 0, cnt = BATcount(b), ss, ee;
        lng *restrict start, *restrict end;
-       dbl f, lo, hi, v, *restrict rb = (dbl*) Tloc(r, 0);
+       dbl qua = 0, f, *restrict rb = (dbl*) Tloc(r, 0), v, lo, hi;
+       bool has_nils = false;
 
-       assert(s && e);
+       assert(s && e && ((q && !quantile) || (!q && quantile)));
        start = (lng *) Tloc(s, 0);
        end = (lng *) Tloc(e, 0);
 
-       if (!ATOMlinear(tpe)) {
-               GDKerror("GDKanalytical_median_avg: cannot determine quantile 
on "
-                        "non-linear type %s\n", ATOMname(tpe));
-               return GDK_FAIL;
-       }
-
-       switch (tpe) {
-       case TYPE_bte:
-               ANALYTICAL_MEDIAN_AVG(bte);
-               break;
-       case TYPE_sht:
-               ANALYTICAL_MEDIAN_AVG(sht);
-               break;
-       case TYPE_int:
-               ANALYTICAL_MEDIAN_AVG(int);
-               break;
-       case TYPE_lng:
-               ANALYTICAL_MEDIAN_AVG(lng);
-               break;
+       if (quantile) {
+               switch (tp2) {
+               case TYPE_flt:{
+                       flt val = *(flt *) quantile;
+                       qua = !is_flt_nil(val) ? (dbl) val : dbl_nil;
+               } break;
+               case TYPE_dbl:{
+                       qua = *(dbl *) quantile;
+               } break;
+               default:
+                       goto nosupport;
+               }
+               switch (tp1) {
+               case TYPE_bte:
+                       ANALYTICAL_QUANTILE_AVG_IMP_SINGLE_FIXED(bte);
+                       break;
+               case TYPE_sht:
+                       ANALYTICAL_QUANTILE_AVG_IMP_SINGLE_FIXED(sht);
+                       break;
+               case TYPE_int:
+                       ANALYTICAL_QUANTILE_AVG_IMP_SINGLE_FIXED(int);
+                       break;
+               case TYPE_lng:
+                       ANALYTICAL_QUANTILE_AVG_IMP_SINGLE_FIXED(lng);
+                       break;
 #ifdef HAVE_HGE
-       case TYPE_hge:
-               ANALYTICAL_MEDIAN_AVG(hge);
-               break;
+               case TYPE_hge:
+                       ANALYTICAL_QUANTILE_AVG_IMP_SINGLE_FIXED(hge);
+                       break;
 #endif
-       case TYPE_flt:
-               ANALYTICAL_MEDIAN_AVG(flt);
-               break;
-       case TYPE_dbl:
-               ANALYTICAL_MEDIAN_AVG(dbl);
-               break;
-       default:
-               GDKerror("GDKanalytical_median_avg: average of type %s 
unsupported.\n", ATOMname(tpe));
-               return GDK_FAIL;
+               case TYPE_flt:
+                       ANALYTICAL_QUANTILE_AVG_IMP_SINGLE_FIXED(flt);
+                       break;
+               case TYPE_dbl:
+                       ANALYTICAL_QUANTILE_AVG_IMP_SINGLE_FIXED(dbl);
+                       break;
+               default:
+                       goto nosupport;
+               }
+       } else {
+               switch (tp1) {
+               case TYPE_bte:
+                       ANALYTICAL_QUANTILE_AVG_CALC_FIXED(bte);
+                       break;
+               case TYPE_sht:
+                       ANALYTICAL_QUANTILE_AVG_CALC_FIXED(sht);
+                       break;
+               case TYPE_int:
+                       ANALYTICAL_QUANTILE_AVG_CALC_FIXED(int);
+                       break;
+               case TYPE_lng:
+                       ANALYTICAL_QUANTILE_AVG_CALC_FIXED(lng);
+                       break;
+#ifdef HAVE_HGE
+               case TYPE_hge:
+                       ANALYTICAL_QUANTILE_AVG_CALC_FIXED(hge);
+                       break;
+#endif
+               case TYPE_flt:
+                       ANALYTICAL_QUANTILE_AVG_CALC_FIXED(flt);
+                       break;
+               case TYPE_dbl:
+                       ANALYTICAL_QUANTILE_AVG_CALC_FIXED(dbl);
+                       break;
+               default:
+                       goto nosupport;
+               }
        }
        BATsetcount(r, cnt);
-       r->tkey = BATcount(r) <= 1;
-       r->tsorted = BATcount(r) <= 1;
-       r->trevsorted = BATcount(r) <= 1;
        r->tnonil = !has_nils;
        r->tnil = has_nils;
        return GDK_SUCCEED;
+nosupport:
+       GDKerror("%s: type %s not supported for the quantile.\n", __func__, 
ATOMname(tp2));
+       return GDK_FAIL;
 }
diff --git a/sql/backends/monet5/sql_rank.c b/sql/backends/monet5/sql_rank.c
--- a/sql/backends/monet5/sql_rank.c
+++ b/sql/backends/monet5/sql_rank.c
@@ -1514,12 +1514,11 @@ SQLprod(Client cntxt, MalBlkPtr mb, MalS
                                                                 
GDKanalyticalprod);
 }
 
-static str
-do_fp_window(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci, const 
char *op, const char* err,
-                        gdk_return (*func)(BAT *, BAT *, BAT *, BAT *, int))
+str
+SQLavg(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
 {
        BAT *r, *b, *s, *e;
-       str msg = SQLanalytics_args(&r, &b, &s, &e, cntxt, mb, stk, pci, 
TYPE_dbl, op, err);
+       str msg = SQLanalytics_args(&r, &b, &s, &e, cntxt, mb, stk, pci, 
TYPE_dbl, "sql.avg", SQLSTATE(42000) "avg(:any_1,:lng,:lng)");
        int tpe = getArgType(mb, pci, 1);
        gdk_return gdk_res;
 
@@ -1531,14 +1530,14 @@ do_fp_window(Client cntxt, MalBlkPtr mb,
        if (b) {
                bat *res = getArgReference_bat(stk, pci, 0);
 
-               gdk_res = func(r, b, s, e, tpe);
+               gdk_res = GDKanalyticalavg(r, b, s, e, tpe);
                BBPunfix(b->batCacheid);
                if (s) BBPunfix(s->batCacheid);
                if (e) BBPunfix(e->batCacheid);
                if (gdk_res == GDK_SUCCEED)
                        BBPkeepref(*res = r->batCacheid);
                else
-                       throw(SQL, op, GDK_EXCEPTION);
+                       throw(SQL, "sql.avg", GDK_EXCEPTION);
        } else {
                ptr *res = getArgReference(stk, pci, 0);
                ptr *in = getArgReference(stk, pci, 1);
@@ -1574,25 +1573,12 @@ do_fp_window(Client cntxt, MalBlkPtr mb,
                                *res = *in;
                                break;
                        default:
-                               throw(SQL, op, SQLSTATE(42000) "%s not 
available for %s", op, ATOMname(tpe));
+                               throw(SQL, "sql.avg", SQLSTATE(42000) "sql.avg 
not available for %s", ATOMname(tpe));
                }
        }
        return msg;
 }
 
-str
-SQLavg(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
-{
-       return do_fp_window(cntxt, mb, stk, pci, "sql.avg", SQLSTATE(42000) 
"avg(:any_1,:lng,:lng)", GDKanalyticalavg);
-}
-
-str
-SQLmedian_avg(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
-{
-       return do_fp_window(cntxt, mb, stk, pci, "sql.median_avg", 
SQLSTATE(42000) "median_avg(:any_1,:lng,:lng)",
-                                               GDKanalytical_median_avg);
-}
-
 static str
 do_stddev_and_variance(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr 
pci, const char* op, const char* err, 
                                           gdk_return (*func)(BAT *, BAT *, BAT 
*, BAT *, int))
@@ -1668,6 +1654,106 @@ SQLvar_pop(Client cntxt, MalBlkPtr mb, M
                                                                  
GDKanalytical_variance_pop);
 }
 
+#define QUANTILE_SINGLE_IMP(TPE) \
+       do { \
+               TPE val = *(TPE*) VALget(qua), *toset; \
+               if (!VALisnil(qua) && (val > 1.0f || val < 0.0f)) \
+                       throw(SQL, op, SQLSTATE(42000) "quantile value must be 
in range [0,1]"); \
_______________________________________________
checkin-list mailing list
[email protected]
https://www.monetdb.org/mailman/listinfo/checkin-list

Reply via email to