Changeset: 3ca5b1c53516 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=3ca5b1c53516
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/analytics15.sql
sql/test/analytics/Tests/analytics15.stable.out
Branch: statistics-analytics
Log Message:
Implemented correlation as a window function.
There's room for optimization, but first implement it.
Also added missing correlation aggregate for interval types.
diffs (truncated from 1167 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
@@ -44,5 +44,6 @@ gdk_export gdk_return GDKanalytical_vari
gdk_export gdk_return GDKanalytical_variance_pop(BAT *r, BAT *b, BAT *s, BAT
*e, int tpe);
gdk_export gdk_return GDKanalytical_covariance_pop(BAT *r, BAT *b1, BAT *b2,
BAT *s, BAT *e, int tpe);
gdk_export gdk_return GDKanalytical_covariance_samp(BAT *r, BAT *b1, BAT *b2,
BAT *s, BAT *e, int tpe);
+gdk_export gdk_return GDKanalytical_correlation(BAT *r, BAT *b1, BAT *b2, BAT
*s, BAT *e, int tpe);
#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
@@ -1882,3 +1882,86 @@ GDKanalytical_##NAME(BAT *r, BAT *b1, BA
GDK_ANALYTICAL_COVARIANCE(covariance_samp, 1, m2 / (n - 1))
GDK_ANALYTICAL_COVARIANCE(covariance_pop, 0, m2 / n)
+
+#define ANALYTICAL_CORRELATION_CALC(TPE) \
+ do { \
+ TPE *bp1 = (TPE*)Tloc(b1, 0), *bp2 = (TPE*)Tloc(b2, 0), *bs1,
*be1, *bs2, v1, v2; \
+ for (; i < cnt; i++, rb++) { \
+ bs1 = bp1 + start[i]; \
+ be1 = bp1 + end[i]; \
+ bs2 = bp2 + start[i]; \
+ for (; bs1 < be1; bs1++, bs2++) { \
+ v1 = *bs1; \
+ v2 = *bs2; \
+ if (is_##TPE##_nil(v1) || is_##TPE##_nil(v2))
\
+ continue; \
+ n++; \
+ delta1 = (dbl) v1 - mean1; \
+ mean1 += delta1 / n; \
+ delta2 = (dbl) v2 - mean2; \
+ mean2 += delta2 / n; \
+ aux = (dbl) v2 - mean2; \
+ up += delta1 * aux; \
+ down1 += delta1 * ((dbl) v1 - mean1); \
+ down2 += delta2 * aux; \
+ } \
+ if (n > 0 && up > 0 && down1 > 0 && down2 > 0) { \
+ *rb = (up / n) / (sqrt(down1 / n) * sqrt(down2
/ n)); \
+ assert(!is_dbl_nil(*rb)); \
+ } else { \
+ *rb = dbl_nil; \
+ nils++; \
+ } \
+ n = 0; \
+ mean1 = 0; \
+ mean2 = 0; \
+ up = 0; \
+ down1 = 0; \
+ down2 = 0; \
+ } \
+ } while (0)
+
+gdk_return
+GDKanalytical_correlation(BAT *r, BAT *b1, BAT *b2, BAT *s, BAT *e, int tpe)
+{
+ BUN i = 0, cnt = BATcount(b1), n = 0, nils = 0;
+ lng *restrict start, *restrict end;
+ dbl *restrict rb = (dbl *) Tloc(r, 0), mean1 = 0, mean2 = 0, up = 0,
down1 = 0, down2 = 0, delta1, delta2, aux;
+
+ assert(s && e && BATcount(b1) == BATcount(b2));
+ start = (lng *) Tloc(s, 0);
+ end = (lng *) Tloc(e, 0);
+
+ switch (tpe) {
+ case TYPE_bte:
+ ANALYTICAL_CORRELATION_CALC(bte);
+ break;
+ case TYPE_sht:
+ ANALYTICAL_CORRELATION_CALC(sht);
+ break;
+ case TYPE_int:
+ ANALYTICAL_CORRELATION_CALC(int);
+ break;
+ case TYPE_lng:
+ ANALYTICAL_CORRELATION_CALC(lng);
+ break;
+#ifdef HAVE_HGE
+ case TYPE_hge:
+ ANALYTICAL_CORRELATION_CALC(hge);
+ break;
+#endif
+ case TYPE_flt:
+ ANALYTICAL_CORRELATION_CALC(flt);
+ break;
+ case TYPE_dbl:
+ ANALYTICAL_CORRELATION_CALC(dbl);
+ break;
+ default:
+ GDKerror("%s: correlation of type %s unsupported.\n", __func__,
ATOMname(tpe));
+ return GDK_FAIL;
+ }
+ BATsetcount(r, cnt);
+ r->tnonil = nils == 0;
+ r->tnil = nils > 0;
+ return GDK_SUCCEED;
+}
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
@@ -1647,7 +1647,7 @@ SQLvar_pop(Client cntxt, MalBlkPtr mb, M
static str
do_covariance_and_correlation(Client cntxt, MalBlkPtr mb, MalStkPtr stk,
InstrPtr pci, const char* op, const char* err,
- gdk_return
(*func)(BAT *, BAT *, BAT *, BAT *, BAT *, int), BUN minimum)
+ gdk_return
(*func)(BAT *, BAT *, BAT *, BAT *, BAT *, int), BUN minimum, dbl single_case)
{
BAT *r = NULL, *b = NULL, *c = NULL, *s = NULL, *e = NULL;
int tp1, tp2;
@@ -1711,9 +1711,9 @@ do_covariance_and_correlation(Client cnt
const void *restrict nil = ATOMnilptr(tp1);
int (*cmp) (const void *, const void *) =
ATOMcompare(tp1);
ValRecord *input2 = &(stk)->stk[(pci)->argv[2]];
- dbl *restrict rb = (dbl*) Tloc(r, 0), res =
VALisnil(input2) ? dbl_nil : 0;
+ dbl *restrict rb = (dbl*) Tloc(r, 0), res =
VALisnil(input2) ? dbl_nil : single_case;
lng *restrict start = (lng*) Tloc(s, 0), *restrict end
= (lng*) Tloc(e, 0);
- bool has_nils = VALisnil(input2);
+ bool has_nils = is_dbl_nil(res);
for (BUN i = 0; i < cnt; i++) {
for (lng j = start[i] ; j < end[i] ; j++) {
@@ -1771,12 +1771,19 @@ str
SQLcovar_samp(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
{
return do_covariance_and_correlation(cntxt, mb, stk, pci,
"sql.covariance", SQLSTATE(42000) "covariance(:any_1,:any_1,:lng,:lng)",
-
GDKanalytical_covariance_samp, 1);
+
GDKanalytical_covariance_samp, 1, 0.0f);
}
str
SQLcovar_pop(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
{
return do_covariance_and_correlation(cntxt, mb, stk, pci,
"sql.covariancep", SQLSTATE(42000) "covariancep(:any_1,:any_1,:lng,:lng)",
-
GDKanalytical_covariance_pop, 0);
+
GDKanalytical_covariance_pop, 0, 0.0f);
}
+
+str
+SQLcorr(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
+{
+ return do_covariance_and_correlation(cntxt, mb, stk, pci, "sql.corr",
SQLSTATE(42000) "corr(:any_1,:any_1,:lng,:lng)",
+
GDKanalytical_correlation, 0, dbl_nil);
+}
diff --git a/sql/backends/monet5/sql_rank.h b/sql/backends/monet5/sql_rank.h
--- a/sql/backends/monet5/sql_rank.h
+++ b/sql/backends/monet5/sql_rank.h
@@ -42,5 +42,6 @@ sql5_export str SQLvar_samp(Client cntxt
sql5_export str SQLvar_pop(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr
pci);
sql5_export str SQLcovar_samp(Client cntxt, MalBlkPtr mb, MalStkPtr stk,
InstrPtr pci);
sql5_export str SQLcovar_pop(Client cntxt, MalBlkPtr mb, MalStkPtr stk,
InstrPtr pci);
+sql5_export str SQLcorr(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr
pci);
#endif /* _SQL_RANK_H */
diff --git a/sql/backends/monet5/sql_rank.mal b/sql/backends/monet5/sql_rank.mal
--- a/sql/backends/monet5/sql_rank.mal
+++ b/sql/backends/monet5/sql_rank.mal
@@ -610,6 +610,23 @@ address SQLcovar_pop
comment "return the covariance population value of groups";
+pattern sql.corr(b:bte, c:bte, s:lng, e:lng) :dbl
+address SQLcorr
+comment "return the correlation value of groups";
+
+pattern batsql.corr(b:bat[:bte], c:bte, s:bat[:lng], e:bat[:lng]) :bat[:dbl]
+address SQLcorr
+comment "return the correlation value of groups";
+
+pattern batsql.corr(b:bte, c:bat[:bte], s:lng, e:lng) :bat[:dbl]
+address SQLcorr
+comment "return the correlation value of groups";
+
+pattern batsql.corr(b:bat[:bte], c:bat[:bte], s:bat[:lng], e:bat[:lng])
:bat[:dbl]
+address SQLcorr
+comment "return the correlation value of groups";
+
+
pattern sql.avg(b:sht, s:lng, e:lng) :dbl
address SQLavg
comment "return the average of groups";
@@ -687,6 +704,23 @@ address SQLcovar_pop
comment "return the covariance population value of groups";
+pattern sql.corr(b:sht, c:sht, s:lng, e:lng) :dbl
+address SQLcorr
+comment "return the correlation value of groups";
+
+pattern batsql.corr(b:bat[:sht], c:sht, s:bat[:lng], e:bat[:lng]) :bat[:dbl]
+address SQLcorr
+comment "return the correlation value of groups";
+
+pattern batsql.corr(b:sht, c:bat[:sht], s:lng, e:lng) :bat[:dbl]
+address SQLcorr
+comment "return the correlation value of groups";
+
+pattern batsql.corr(b:bat[:sht], c:bat[:sht], s:bat[:lng], e:bat[:lng])
:bat[:dbl]
+address SQLcorr
+comment "return the correlation value of groups";
+
+
pattern sql.avg(b:int, s:lng, e:lng) :dbl
address SQLavg
comment "return the average of groups";
@@ -764,6 +798,23 @@ address SQLcovar_pop
comment "return the covariance population value of groups";
+pattern sql.corr(b:int, c:int, s:lng, e:lng) :dbl
+address SQLcorr
+comment "return the correlation value of groups";
+
+pattern batsql.corr(b:bat[:int], c:int, s:bat[:lng], e:bat[:lng]) :bat[:dbl]
+address SQLcorr
+comment "return the correlation value of groups";
+
+pattern batsql.corr(b:int, c:bat[:int], s:lng, e:lng) :bat[:dbl]
+address SQLcorr
+comment "return the correlation value of groups";
+
+pattern batsql.corr(b:bat[:int], c:bat[:int], s:bat[:lng], e:bat[:lng])
:bat[:dbl]
+address SQLcorr
+comment "return the correlation value of groups";
+
+
pattern sql.avg(b:lng, s:lng, e:lng) :dbl
address SQLavg
comment "return the average of groups";
@@ -841,6 +892,23 @@ address SQLcovar_pop
comment "return the covariance population value of groups";
+pattern sql.corr(b:lng, c:lng, s:lng, e:lng) :dbl
+address SQLcorr
+comment "return the correlation value of groups";
+
+pattern batsql.corr(b:bat[:lng], c:lng, s:bat[:lng], e:bat[:lng]) :bat[:dbl]
+address SQLcorr
+comment "return the correlation value of groups";
+
+pattern batsql.corr(b:lng, c:bat[:lng], s:lng, e:lng) :bat[:dbl]
+address SQLcorr
+comment "return the correlation value of groups";
+
+pattern batsql.corr(b:bat[:lng], c:bat[:lng], s:bat[:lng], e:bat[:lng])
:bat[:dbl]
+address SQLcorr
+comment "return the correlation value of groups";
+
+
pattern sql.avg(b:flt, s:lng, e:lng) :dbl
address SQLavg
comment "return the average of groups";
@@ -918,6 +986,23 @@ address SQLcovar_pop
comment "return the covariance population value of groups";
+pattern sql.corr(b:flt, c:flt, s:lng, e:lng) :dbl
+address SQLcorr
+comment "return the correlation value of groups";
+
+pattern batsql.corr(b:bat[:flt], c:flt, s:bat[:lng], e:bat[:lng]) :bat[:dbl]
+address SQLcorr
+comment "return the correlation value of groups";
+
+pattern batsql.corr(b:flt, c:bat[:flt], s:lng, e:lng) :bat[:dbl]
+address SQLcorr
+comment "return the correlation value of groups";
+
+pattern batsql.corr(b:bat[:flt], c:bat[:flt], s:bat[:lng], e:bat[:lng])
:bat[:dbl]
+address SQLcorr
+comment "return the correlation value of groups";
+
+
pattern sql.avg(b:dbl, s:lng, e:lng) :dbl
address SQLavg
comment "return the average of groups";
@@ -995,3 +1080,19 @@ address SQLcovar_pop
comment "return the covariance population value of groups";
+pattern sql.corr(b:dbl, c:dbl, s:lng, e:lng) :dbl
+address SQLcorr
+comment "return the correlation value of groups";
+
+pattern batsql.corr(b:bat[:dbl], c:dbl, s:bat[:lng], e:bat[:lng]) :bat[:dbl]
+address SQLcorr
+comment "return the correlation value of groups";
+
+pattern batsql.corr(b:dbl, c:bat[:dbl], s:lng, e:lng) :bat[:dbl]
+address SQLcorr
+comment "return the correlation value of groups";
+
+pattern batsql.corr(b:bat[:dbl], c:bat[:dbl], s:bat[:lng], e:bat[:lng])
:bat[:dbl]
+address SQLcorr
+comment "return the correlation value of groups";
+
diff --git a/sql/backends/monet5/sql_rank.mal.sh
b/sql/backends/monet5/sql_rank.mal.sh
_______________________________________________
checkin-list mailing list
[email protected]
https://www.monetdb.org/mailman/listinfo/checkin-list