Changeset: b88aa1522373 for MonetDB
URL: http://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=b88aa1522373
Modified Files:
clients/Tests/exports.stable.out
gdk/gdk_calc.c
gdk/gdk_calc.h
gdk/gdk_calc_compare.h
monetdb5/modules/mal/batcalc.c
Branch: batcalc-candidates
Log Message:
Rewrote gdk_calc.c to change semantics when candidate lists are present.
If a candidate list is present in a calculation, we now produce a
result that is aligned with the candidate list (before, then result
was aligned with the input(s)). If there are two inputs to an
operation, one of them may be aligned with the candidate list so that
cascading operations are possible. Which input is aligned with the
candidate list is indicated with the new argument "projected" (0:
neither operand is aligned with the candidate list; 1: the first
operand is aligned with the candidate list; 2: the second operand is
aligned with the candidate list). If both operands are aligned with
the candidate list, don't use a candidate list. Note that in
operations with more than two operands (ifthenelse, between), the
second and third operand are treated in the same way (if they are both
BATs).
diffs (truncated from 20012 to 300 lines):
diff --git a/clients/Tests/exports.stable.out b/clients/Tests/exports.stable.out
--- a/clients/Tests/exports.stable.out
+++ b/clients/Tests/exports.stable.out
@@ -25,16 +25,16 @@ atomDesc BATatoms[];
BAT *BATattach(int tt, const char *heapfile, int role);
gdk_return BATbandjoin(BAT **r1p, BAT **r2p, BAT *l, BAT *r, BAT *sl, BAT *sr,
const void *c1, const void *c2, int li, int hi, BUN estimate);
BAT *BATcalcabsolute(BAT *b, BAT *s);
-BAT *BATcalcadd(BAT *b1, BAT *b2, BAT *s, int tp, int abort_on_error);
+BAT *BATcalcadd(BAT *b1, BAT *b2, BAT *s, int tp, int abort_on_error, int
projected);
BAT *BATcalcaddcst(BAT *b, const ValRecord *v, BAT *s, int tp, int
abort_on_error);
-BAT *BATcalcand(BAT *b1, BAT *b2, BAT *s);
+BAT *BATcalcand(BAT *b1, BAT *b2, BAT *s, int projected);
BAT *BATcalcandcst(BAT *b, const ValRecord *v, BAT *s);
gdk_return BATcalcavg(BAT *b, BAT *s, dbl *avg, BUN *vals);
-BAT *BATcalcbetween(BAT *b, BAT *lo, BAT *hi, BAT *s, int sym);
-BAT *BATcalcbetweenbatcst(BAT *b, BAT *lo, const ValRecord *hi, BAT *s, int
sym);
-BAT *BATcalcbetweencstbat(BAT *b, const ValRecord *lo, BAT *hi, BAT *s, int
sym);
-BAT *BATcalcbetweencstcst(BAT *b, const ValRecord *lo, const ValRecord *hi,
BAT *s, int sym);
-BAT *BATcalccmp(BAT *b1, BAT *b2, BAT *s);
+BAT *BATcalcbetween(BAT *b, BAT *lo, BAT *hi, BAT *s, int symmetric, int
projected);
+BAT *BATcalcbetweenbatcst(BAT *b, BAT *lo, const ValRecord *hi, BAT *s, int
symmetric, int projected);
+BAT *BATcalcbetweencstbat(BAT *b, const ValRecord *lo, BAT *hi, BAT *s, int
symmetric, int projected);
+BAT *BATcalcbetweencstcst(BAT *b, const ValRecord *lo, const ValRecord *hi,
BAT *s, int symmetric);
+BAT *BATcalccmp(BAT *b1, BAT *b2, BAT *s, int projected);
BAT *BATcalccmpcst(BAT *b, const ValRecord *v, BAT *s);
BAT *BATcalccstadd(const ValRecord *v, BAT *b, BAT *s, int tp, int
abort_on_error);
BAT *BATcalccstand(const ValRecord *v, BAT *b, BAT *s);
@@ -54,52 +54,52 @@ BAT *BATcalccstrsh(const ValRecord *v, B
BAT *BATcalccstsub(const ValRecord *v, BAT *b, BAT *s, int tp, int
abort_on_error);
BAT *BATcalccstxor(const ValRecord *v, BAT *b, BAT *s);
BAT *BATcalcdecr(BAT *b, BAT *s, int abort_on_error);
-BAT *BATcalcdiv(BAT *b1, BAT *b2, BAT *s, int tp, int abort_on_error);
+BAT *BATcalcdiv(BAT *b1, BAT *b2, BAT *s, int tp, int abort_on_error, int
projected);
BAT *BATcalcdivcst(BAT *b, const ValRecord *v, BAT *s, int tp, int
abort_on_error);
-BAT *BATcalceq(BAT *b1, BAT *b2, BAT *s);
+BAT *BATcalceq(BAT *b1, BAT *b2, BAT *s, int projected);
BAT *BATcalceqcst(BAT *b, const ValRecord *v, BAT *s);
-BAT *BATcalcge(BAT *b1, BAT *b2, BAT *s);
+BAT *BATcalcge(BAT *b1, BAT *b2, BAT *s, int projected);
BAT *BATcalcgecst(BAT *b, const ValRecord *v, BAT *s);
-BAT *BATcalcgt(BAT *b1, BAT *b2, BAT *s);
+BAT *BATcalcgt(BAT *b1, BAT *b2, BAT *s, int projected);
BAT *BATcalcgtcst(BAT *b, const ValRecord *v, BAT *s);
-BAT *BATcalcifthencstelse(BAT *b, const ValRecord *c1, BAT *b2);
-BAT *BATcalcifthencstelsecst(BAT *b, const ValRecord *c1, const ValRecord *c2);
-BAT *BATcalcifthenelse(BAT *b, BAT *b1, BAT *b2);
-BAT *BATcalcifthenelsecst(BAT *b, BAT *b1, const ValRecord *c2);
+BAT *BATcalcifthencstelse(BAT *b, const ValRecord *c1, BAT *b2, BAT *s, int
projected);
+BAT *BATcalcifthencstelsecst(BAT *b, const ValRecord *c1, const ValRecord *c2,
BAT *s);
+BAT *BATcalcifthenelse(BAT *b, BAT *b1, BAT *b2, BAT *s, int projected);
+BAT *BATcalcifthenelsecst(BAT *b, BAT *b1, const ValRecord *c2, BAT *s, int
projected);
BAT *BATcalcincr(BAT *b, BAT *s, int abort_on_error);
BAT *BATcalcisnil(BAT *b, BAT *s);
BAT *BATcalcisnotnil(BAT *b, BAT *s);
BAT *BATcalciszero(BAT *b, BAT *s);
-BAT *BATcalcle(BAT *b1, BAT *b2, BAT *s);
+BAT *BATcalcle(BAT *b1, BAT *b2, BAT *s, int projected);
BAT *BATcalclecst(BAT *b, const ValRecord *v, BAT *s);
-BAT *BATcalclsh(BAT *b1, BAT *b2, BAT *s, int abort_on_error);
+BAT *BATcalclsh(BAT *b1, BAT *b2, BAT *s, int abort_on_error, int projected);
BAT *BATcalclshcst(BAT *b, const ValRecord *v, BAT *s, int abort_on_error);
-BAT *BATcalclt(BAT *b1, BAT *b2, BAT *s);
+BAT *BATcalclt(BAT *b1, BAT *b2, BAT *s, int projected);
BAT *BATcalcltcst(BAT *b, const ValRecord *v, BAT *s);
-BAT *BATcalcmax(BAT *b1, BAT *b2, BAT *s);
-BAT *BATcalcmax_no_nil(BAT *b1, BAT *b2, BAT *s);
-BAT *BATcalcmin(BAT *b1, BAT *b2, BAT *s);
-BAT *BATcalcmin_no_nil(BAT *b1, BAT *b2, BAT *s);
-BAT *BATcalcmod(BAT *b1, BAT *b2, BAT *s, int tp, int abort_on_error);
+BAT *BATcalcmax(BAT *b1, BAT *b2, BAT *s, int projected);
+BAT *BATcalcmax_no_nil(BAT *b1, BAT *b2, BAT *s, int projected);
+BAT *BATcalcmin(BAT *b1, BAT *b2, BAT *s, int projected);
+BAT *BATcalcmin_no_nil(BAT *b1, BAT *b2, BAT *s, int projected);
+BAT *BATcalcmod(BAT *b1, BAT *b2, BAT *s, int tp, int abort_on_error, int
projected);
BAT *BATcalcmodcst(BAT *b, const ValRecord *v, BAT *s, int tp, int
abort_on_error);
-BAT *BATcalcmul(BAT *b1, BAT *b2, BAT *s, int tp, int abort_on_error);
+BAT *BATcalcmul(BAT *b1, BAT *b2, BAT *s, int tp, int abort_on_error, int
projected);
BAT *BATcalcmulcst(BAT *b, const ValRecord *v, BAT *s, int tp, int
abort_on_error);
-BAT *BATcalcne(BAT *b1, BAT *b2, BAT *s);
+BAT *BATcalcne(BAT *b1, BAT *b2, BAT *s, int projected);
BAT *BATcalcnecst(BAT *b, const ValRecord *v, BAT *s);
BAT *BATcalcnegate(BAT *b, BAT *s);
BAT *BATcalcnot(BAT *b, BAT *s);
-BAT *BATcalcor(BAT *b1, BAT *b2, BAT *s);
+BAT *BATcalcor(BAT *b1, BAT *b2, BAT *s, int projected);
BAT *BATcalcorcst(BAT *b, const ValRecord *v, BAT *s);
-BAT *BATcalcrsh(BAT *b1, BAT *b2, BAT *s, int abort_on_error);
+BAT *BATcalcrsh(BAT *b1, BAT *b2, BAT *s, int abort_on_error, int projected);
BAT *BATcalcrshcst(BAT *b, const ValRecord *v, BAT *s, int abort_on_error);
BAT *BATcalcsign(BAT *b, BAT *s);
dbl BATcalcstdev_population(dbl *avgp, BAT *b);
dbl BATcalcstdev_sample(dbl *avgp, BAT *b);
-BAT *BATcalcsub(BAT *b1, BAT *b2, BAT *s, int tp, int abort_on_error);
+BAT *BATcalcsub(BAT *b1, BAT *b2, BAT *s, int tp, int abort_on_error, int
projected);
BAT *BATcalcsubcst(BAT *b, const ValRecord *v, BAT *s, int tp, int
abort_on_error);
dbl BATcalcvariance_population(dbl *avgp, BAT *b);
dbl BATcalcvariance_sample(dbl *avgp, BAT *b);
-BAT *BATcalcxor(BAT *b1, BAT *b2, BAT *s);
+BAT *BATcalcxor(BAT *b1, BAT *b2, BAT *s, int projected);
BAT *BATcalcxorcst(BAT *b, const ValRecord *v, BAT *s);
gdk_return BATclear(BAT *b, int force);
void BATcommit(BAT *b);
@@ -332,7 +332,7 @@ ValPtr VALset(ValPtr v, int t, ptr p);
gdk_return VARcalcabsolute(ValPtr ret, const ValRecord *v);
gdk_return VARcalcadd(ValPtr ret, const ValRecord *lft, const ValRecord *rgt,
int abort_on_error);
gdk_return VARcalcand(ValPtr ret, const ValRecord *lft, const ValRecord *rgt);
-gdk_return VARcalcbetween(ValPtr ret, const ValRecord *v, const ValRecord *lo,
const ValRecord *hi, int sym);
+gdk_return VARcalcbetween(ValPtr ret, const ValRecord *v, const ValRecord *lo,
const ValRecord *hi, int symmetric);
gdk_return VARcalccmp(ValPtr ret, const ValRecord *lft, const ValRecord *rgt);
gdk_return VARcalcdecr(ValPtr ret, const ValRecord *v, int abort_on_error);
gdk_return VARcalcdiv(ValPtr ret, const ValRecord *lft, const ValRecord *rgt,
int abort_on_error);
diff --git a/gdk/gdk_calc.c b/gdk/gdk_calc.c
--- a/gdk/gdk_calc.c
+++ b/gdk/gdk_calc.c
@@ -19,12 +19,6 @@
* (if available) for +, -, *. For division the output type can be
* either input type of flt or dbl. */
-/* Generally, the functions return a new BAT aligned with the input
- * BAT(s). If there are multiple input BATs, they must be aligned.
- * If there is a candidate list, the calculations are only done for
- * the candidates, all other values are NIL (so that the output is
- * still aligned). */
-
/* format strings for the seven/eight basic types we deal with */
#define FMTbte "%d"
#define FMTsht "%d"
@@ -50,135 +44,255 @@
#define CSTdbl
#define CSToid
-/* Most of the internal routines return a count of the number of NIL
- * values they produced. They indicate an error by returning a value
- * >= BUN_NONE. BUN_NONE means that the error was dealt with by
- * calling GDKerror (generally for overflow or conversion errors).
- * BUN_NONE+1 is returned by the DIV and MOD functions to indicate
- * division by zero. */
-
-static gdk_return
-checkbats(BAT *b1, BAT *b2, const char *func)
-{
- if (b2 != NULL) {
- if (b1->batCount != b2->batCount) {
- GDKerror("%s: inputs not the same size.\n", func);
- return GDK_FAIL;
- }
- }
- return GDK_SUCCEED;
-}
-
-#define CHECKCAND(dst, i, candoff, NIL) \
- /* cannot use do/while trick because of continue */ \
- /* NOTE: because of the continue, you *must* use the */ \
- /* index (i) to index src/dst */ \
- if (cand) { \
- if ((i) < *cand - (candoff)) { \
- nils++; \
- (dst)[i] = (NIL); \
- continue; \
- } \
- assert((i) == *cand - (candoff)); \
- if (++cand == (candend)) \
- end = (i) + 1; \
- }
-
-/* fill in NILs from low to high, used to write NILs before and after
- * the range that the candidates list covers */
-#define CANDLOOP(dst, i, NIL, low, high) \
- do { \
- for ((i) = (low); (i) < (high); (i)++) \
- (dst)[i] = NIL; \
- nils += (high) - (low); \
+#define CMP(a, b) ((bte) (((a) > (b)) - ((a) < (b))))
+#define LE(a, b) ((bit) ((a) <= (b)))
+#define GE(a, b) ((bit) ((a) >= (b)))
+#define EQ(a, b) ((bit) ((a) == (b)))
+#define NE(a, b) ((bit) ((a) != (b)))
+#define LSH(a, b) ((a) << (b))
+#define RSH(a, b) ((a) >> (b))
+
+#define CALC_DECL \
+ BUN start, cnt; \
+ const oid *restrict cand; \
+ oid hseq; /* seq base for result */ \
+ BUN nils; /* # nils in result */ \
+ oid hoff /* offset */
+
+#define CALC_PREINIT(b1, b2, bn) \
+ do { \
+ if (projected != 0 && s == NULL) { \
+ assert(0); \
+ GDKerror("%s: candidate list missing\n", \
+ __func__); \
+ return NULL; \
+ } \
+ switch (projected) { \
+ case 0: /* neither operand was projected */ \
+ if (b1->hseqbase != b2->hseqbase || \
+ BATcount(b1) != BATcount(b2)) { \
+ GDKerror("%s: operands are not aligned\n", \
+ __func__); \
+ return NULL; \
+ } \
+ bn = b1; \
+ break; \
+ case 1: \
+ bn = b1; \
+ break; \
+ case 2: \
+ bn = b2; \
+ break; \
+ default: \
+ assert(0); \
+ GDKerror("%s: illegal projected argument\n", \
+ __func__); \
+ return NULL; \
+ } \
+ } while (0)
+
+#define CALC_INIT(b) \
+ do { \
+ start = 0; \
+ cnt = BATcount(b); \
+ cand = NULL; \
+ hoff = hseq = b->hseqbase; \
+ nils = 0; \
+ \
+ if (s) { \
+ hseq = s->hseqbase; \
+ if (BATcount(s) == 0) { \
+ cnt = 0; \
+ } else if (BATtdense(s)) { \
+ start = s->tseqbase; \
+ cnt = BATcount(s); \
+ if (start <= b->hseqbase) { \
+ hseq += b->hseqbase - start; \
+ cnt -= b->hseqbase - start; \
+ start = 0; \
+ } else if (start >= b->hseqbase + BATcount(b))
{ \
+ cnt = 0; \
+ start = 0; \
+ } else { \
+ start -= b->hseqbase; \
+ } \
+ if (start + cnt > BATcount(b)) \
+ cnt = BATcount(b) - start; \
+ } else { \
+ oid x = b->hseqbase; \
+ \
+ start = SORTfndfirst(s, &x); \
+ hseq += start; \
+ x += BATcount(b); \
+ cnt = SORTfndfirst(s, &x) - start; \
+ if (cnt > 0) \
+ cand = (const oid *) Tloc(s, start); \
+ start = 0; \
+ } \
+ } \
+ } while (0)
+
+#define CALC_POSTINIT(b1, b2) \
+ do { \
+ switch (projected) { \
+ case 1: \
+ if (b2->hseqbase != hseq || BATcount(b2) != cnt) { \
+ GDKerror("%s: projected operand not " \
+ "aligned with result\n", \
+ __func__); \
+ return NULL; \
+ } \
+ break; \
+ case 2: \
+ if (b1->hseqbase != hseq || BATcount(b1) != cnt) { \
+ GDKerror("%s: projected operand not " \
+ "aligned with result\n", \
+ __func__); \
+ return NULL; \
+ } \
+ break; \
+ default: \
+ break; \
+ } \
} while (0)
#define UNARY_2TYPE_FUNC(TYPE1, TYPE2, FUNC) \
do { \
- const TYPE1 *restrict src = (const TYPE1 *) Tloc(b, 0); \
+ const TYPE1 *restrict src = (const TYPE1 *) Tloc(b, 0); \
TYPE2 *restrict dst = (TYPE2 *) Tloc(bn, 0); \
- CANDLOOP(dst, i, TYPE2##_nil, 0, start); \
- if (b->tnonil && cand == NULL) { \
- for (i = start; i < end; i++) \
- dst[i] = FUNC(src[i]); \
+ TYPE1 v; \
+ BUN i; \
+ \
+ if (b->tnonil) { \
+ if (cand) { \
+ for (i = 0; i < cnt; i++) { \
+ v = src[cand[i] - hoff]; \
_______________________________________________
checkin-list mailing list
[email protected]
https://www.monetdb.org/mailman/listinfo/checkin-list