Changeset: 19ee664bb76a for MonetDB URL: http://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=19ee664bb76a Modified Files: gdk/gdk_aggr.c gdk/gdk_calc.c gdk/gdk_calc_private.h Branch: default Log Message:
Cosmetics: move average calculation to gdk_aggr.c
diffs (truncated from 426 to 300 lines):
diff --git a/gdk/gdk_aggr.c b/gdk/gdk_aggr.c
--- a/gdk/gdk_aggr.c
+++ b/gdk/gdk_aggr.c
@@ -1024,6 +1024,66 @@ BATprod(void *res, int tp, BAT *b, BAT *
/* ---------------------------------------------------------------------- */
/* average */
+#define AVERAGE_ITER(TYPE, x, a, r, n) \
+ do { \
+ TYPE an, xn, z1; \
+ BUN z2; \
+ (n)++; \
+ /* calculate z1 = (x - a) / n, rounded down (towards */ \
+ /* negative infinity), and calculate z2 = remainder */ \
+ /* of the division (i.e. 0 <= z2 < n); do this */ \
+ /* without causing overflow */ \
+ an = (TYPE) ((a) / (SBUN) (n)); \
+ xn = (TYPE) ((x) / (SBUN) (n)); \
+ /* z1 will be (x - a) / n rounded towards -INF */ \
+ z1 = xn - an; \
+ xn = (x) - (TYPE) (xn * (SBUN) (n)); \
+ an = (a) - (TYPE) (an * (SBUN) (n)); \
+ /* z2 will be remainder of above division */ \
+ if (xn >= an) { \
+ z2 = (BUN) (xn - an); \
+ /* loop invariant: */ \
+ /* (x - a) - z1 * n == z2 */ \
+ while (z2 >= (n)) { \
+ z2 -= (n); \
+ z1++; \
+ } \
+ } else { \
+ z2 = (BUN) (an - xn); \
+ /* loop invariant (until we break): */ \
+ /* (x - a) - z1 * n == -z2 */ \
+ for (;;) { \
+ z1--; \
+ if (z2 < (n)) { \
+ /* proper remainder */ \
+ z2 = (n) - z2; \
+ break; \
+ } \
+ z2 -= (n); \
+ } \
+ } \
+ (a) += z1; \
+ (r) += z2; \
+ if ((r) >= (n)) { \
+ (r) -= (n); \
+ (a)++; \
+ } \
+ } while (0)
+
+#define AVERAGE_ITER_FLOAT(TYPE, x, a, n) \
+ do { \
+ (n)++; \
+ if (((a) > 0) == ((x) > 0)) { \
+ /* same sign */ \
+ (a) += ((x) - (a)) / (SBUN) (n); \
+ } else { \
+ /* no overflow at the cost of an */ \
+ /* extra division and slight loss of */ \
+ /* precision */ \
+ (a) = (a) - (a) / (SBUN) (n) + (x) / (SBUN) (n); \
+ } \
+ } while (0)
+
#define AGGR_AVG(TYPE) \
do { \
const TYPE *vals = (const TYPE *) Tloc(b, BUNfirst(b)); \
@@ -1227,6 +1287,142 @@ BATgroupavg(BAT *b, BAT *g, BAT *e, BAT
return NULL;
}
+#define AVERAGE_TYPE(TYPE) \
+ do { \
+ TYPE x, a; \
+ \
+ /* first try to calculate the sum of all values into a */ \
+ /* lng */ \
+ for (i = start; i < end; i++) { \
+ if (cand) { \
+ if (i < *cand - b->H->seq) { \
+ continue; \
+ } \
+ assert(i == *cand - b->H->seq); \
+ if (++cand == candend) \
+ end = i + 1; \
+ } \
+ x = ((const TYPE *) src)[i]; \
+ if (x == TYPE##_nil) \
+ continue; \
+ ADD_WITH_CHECK(TYPE, x, \
+ lng, sum, \
+ lng, sum, \
+ goto overflow##TYPE); \
+ /* don't count value until after overflow check */ \
+ n++; \
+ } \
+ /* the sum fit, so now we can calculate the average */ \
+ *avg = (dbl) sum / n; \
+ if (0) { \
+ overflow##TYPE: \
+ /* we get here if sum(x[0],...,x[i]) doesn't */ \
+ /* fit in a lng but sum(x[0],...,x[i-1]) did */ \
+ /* the variable sum contains that sum */ \
+ /* the rest of the calculation is done */ \
+ /* according to the loop invariant described */ \
+ /* in the below loop */ \
+ if (sum >= 0) { \
+ a = (TYPE) (sum / (lng) n); /* this fits */ \
+ r = (BUN) (sum % (SBUN) n); \
+ } else { \
+ sum = -sum; \
+ a = - (TYPE) (sum / (lng) n); /* this fits */ \
+ r = (BUN) (sum % (SBUN) n); \
+ if (r) { \
+ a--; \
+ r = n - r; \
+ } \
+ } \
+ if (cand) \
+ --cand; \
+ \
+ for (; i < end; i++) { \
+ /* loop invariant: */ \
+ /* a + r/n == average(x[0],...,x[n]); */ \
+ /* 0 <= r < n (if n > 0) */ \
+ /* or if n == 0: a == 0; r == 0 */ \
+ if (cand) { \
+ if (i < *cand - b->H->seq) \
+ continue; \
+ assert(i == *cand - b->H->seq); \
+ if (++cand == candend) \
+ end = i + 1; \
+ } \
+ x = ((const TYPE *) src)[i]; \
+ if (x == TYPE##_nil) \
+ continue; \
+ AVERAGE_ITER(TYPE, x, a, r, n); \
+ } \
+ *avg = n > 0 ? a + (dbl) r / n : dbl_nil; \
+ } \
+ } while (0)
+
+#define AVERAGE_FLOATTYPE(TYPE) \
+ do { \
+ double a = 0; \
+ TYPE x; \
+ for (i = start; i < end; i++) { \
+ if (cand) { \
+ if (i < *cand - b->H->seq) \
+ continue; \
+ assert(i == *cand - b->H->seq); \
+ if (++cand == candend) \
+ end = i + 1; \
+ } \
+ x = ((const TYPE *) src)[i]; \
+ if (x == TYPE##_nil) \
+ continue; \
+ AVERAGE_ITER_FLOAT(TYPE, x, a, n); \
+ } \
+ *avg = n > 0 ? a : dbl_nil; \
+ } while (0)
+
+int
+BATcalcavg(BAT *b, BAT *s, dbl *avg, BUN *vals)
+{
+ BUN n = 0, r = 0, i = 0;
+ lng sum = 0;
+ BUN start, end, cnt;
+ const oid *cand = NULL, *candend = NULL;
+ const void *src;
+ /* these two needed for ADD_WITH_CHECK macro */
+ int abort_on_error = 1;
+ BUN nils = 0;
+
+ CANDINIT(b, s);
+
+ src = Tloc(b, b->U->first);
+
+ switch (b->T->type) {
+ case TYPE_bte:
+ AVERAGE_TYPE(bte);
+ break;
+ case TYPE_sht:
+ AVERAGE_TYPE(sht);
+ break;
+ case TYPE_int:
+ AVERAGE_TYPE(int);
+ break;
+ case TYPE_lng:
+ AVERAGE_TYPE(lng);
+ break;
+ case TYPE_flt:
+ AVERAGE_FLOATTYPE(flt);
+ break;
+ case TYPE_dbl:
+ AVERAGE_FLOATTYPE(dbl);
+ break;
+ default:
+ GDKerror("BATcalcavg: average of type %s unsupported.\n",
+ ATOMname(b->T->type));
+ return GDK_FAIL;
+ }
+ if (vals)
+ *vals = n;
+ return GDK_SUCCEED;
+}
+
/* ---------------------------------------------------------------------- */
/* count */
diff --git a/gdk/gdk_calc.c b/gdk/gdk_calc.c
--- a/gdk/gdk_calc.c
+++ b/gdk/gdk_calc.c
@@ -9813,142 +9813,3 @@ VARconvert(ValPtr ret, const ValRecord *
}
return nils == BUN_NONE ? GDK_FAIL : GDK_SUCCEED;
}
-
-/* ---------------------------------------------------------------------- */
-/* average (any numeric type) */
-
-#define AVERAGE_TYPE(TYPE) \
- do { \
- TYPE x, a; \
- \
- /* first try to calculate the sum of all values into a */ \
- /* lng */ \
- for (i = start; i < end; i++) { \
- if (cand) { \
- if (i < *cand - b->H->seq) { \
- continue; \
- } \
- assert(i == *cand - b->H->seq); \
- if (++cand == candend) \
- end = i + 1; \
- } \
- x = ((const TYPE *) src)[i]; \
- if (x == TYPE##_nil) \
- continue; \
- ADD_WITH_CHECK(TYPE, x, \
- lng, sum, \
- lng, sum, \
- goto overflow##TYPE); \
- /* don't count value until after overflow check */ \
- n++; \
- } \
- /* the sum fit, so now we can calculate the average */ \
- *avg = (dbl) sum / n; \
- if (0) { \
- overflow##TYPE: \
- /* we get here if sum(x[0],...,x[i]) doesn't */ \
- /* fit in a lng but sum(x[0],...,x[i-1]) did */ \
- /* the variable sum contains that sum */ \
- /* the rest of the calculation is done */ \
- /* according to the loop invariant described */ \
- /* in the below loop */ \
- if (sum >= 0) { \
- a = (TYPE) (sum / (lng) n); /* this fits */ \
- r = (BUN) (sum % (SBUN) n); \
- } else { \
- sum = -sum; \
- a = - (TYPE) (sum / (lng) n); /* this fits */ \
- r = (BUN) (sum % (SBUN) n); \
- if (r) { \
- a--; \
- r = n - r; \
- } \
- } \
- if (cand) \
- --cand; \
- \
- for (; i < end; i++) { \
- /* loop invariant: */ \
- /* a + r/n == average(x[0],...,x[n]); */ \
- /* 0 <= r < n (if n > 0) */ \
- /* or if n == 0: a == 0; r == 0 */ \
- if (cand) { \
- if (i < *cand - b->H->seq) \
- continue; \
- assert(i == *cand - b->H->seq); \
- if (++cand == candend) \
- end = i + 1; \
- } \
- x = ((const TYPE *) src)[i]; \
- if (x == TYPE##_nil) \
- continue; \
- AVERAGE_ITER(TYPE, x, a, r, n); \
- } \
- *avg = n > 0 ? a + (dbl) r / n : dbl_nil; \
- } \
- } while (0)
-
-#define AVERAGE_FLOATTYPE(TYPE) \
- do { \
- double a = 0; \
- TYPE x; \
- for (i = start; i < end; i++) { \
_______________________________________________
checkin-list mailing list
[email protected]
http://mail.monetdb.org/mailman/listinfo/checkin-list
