Changeset: aef5ee377e9f for MonetDB URL: https://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=aef5ee377e9f Modified Files: gdk/gdk.h gdk/gdk_cand.c gdk/gdk_cand.h gdk/gdk_project.c monetdb5/modules/mal/batMask.c Branch: unlock Log Message:
Convert msk bat to oid bat in BATprojectchain. This gives us the possibility to use a msk bat in the chain, and circumvents the problem where we would have to count set bits in the msk bat many for each projected value. diffs (188 lines): diff --git a/gdk/gdk.h b/gdk/gdk.h --- a/gdk/gdk.h +++ b/gdk/gdk.h @@ -1011,7 +1011,7 @@ BUNtoid(BAT *b, BUN p) if (b->ttype == TYPE_oid || b->tvheap == NULL) { return o; } - /* only exceptions allowed on transient BATs */ + /* exceptions only allowed on transient BATs */ assert(b->batRole == TRANSIENT); /* make sure exception area is a reasonable size */ assert(b->tvheap->free % SIZEOF_OID == 0); diff --git a/gdk/gdk_cand.c b/gdk/gdk_cand.c --- a/gdk/gdk_cand.c +++ b/gdk/gdk_cand.c @@ -1285,3 +1285,40 @@ BATnegcands(BAT *dense_cands, BAT *odels ALGOBATPAR(odels)); return GDK_SUCCEED; } + +BAT * +BATunmask(BAT *b) +{ + BAT *bn = COLnew(0, TYPE_oid, 1024, TRANSIENT); + if (bn == NULL) + return NULL; + + BUN cnt = BATcount(b) / 32; + const uint32_t *src = (const uint32_t *) Tloc(b, 0); + oid *dst = (oid *) Tloc(bn, 0); + BUN n = 0; + + for (BUN p = 0; p < cnt; p++) { + if (src[p] == 0) + continue; + for (uint32_t i = 0; i < 32; i++) { + if (src[p] & (1U << i)) { + if (n == BATcapacity(bn)) { + if (BATextend(bn, BATgrows(bn)) != GDK_SUCCEED) { + BBPreclaim(bn); + return NULL; + } + dst = (oid *) Tloc(bn, 0); + } + dst[n++] = b->hseqbase + p * 32 + i; + } + } + } + BATsetcount(bn, n); + bn->tkey = true; + bn->tsorted = true; + bn->trevsorted = n <= 1; + bn->tnil = false; + bn->tnonil = true; + return virtualize(bn); +} diff --git a/gdk/gdk_cand.h b/gdk/gdk_cand.h --- a/gdk/gdk_cand.h +++ b/gdk/gdk_cand.h @@ -149,5 +149,6 @@ gdk_export BAT *canditer_sliceval(struct gdk_export BAT *canditer_slice2(struct canditer *ci, BUN lo1, BUN hi1, BUN lo2, BUN hi2); gdk_export BAT *canditer_slice2val(struct canditer *ci, oid lo1, oid hi1, oid lo2, oid hi2); gdk_export gdk_return BATnegcands( BAT *cands, BAT *odels); +gdk_export BAT *BATunmask(BAT *b); #endif /* _GDK_CAND_H_ */ diff --git a/gdk/gdk_project.c b/gdk/gdk_project.c --- a/gdk/gdk_project.c +++ b/gdk/gdk_project.c @@ -495,7 +495,7 @@ BATproject(BAT *restrict l, BAT *restric * bn = BATproject(bn, bats[n-1]); * return bn; * where none of the intermediates are actually produced (and bats[n]==NULL). - * Note that all BATs except the last must have type oid/void. + * Note that all BATs except the last must have type oid/void or msk. */ BAT * BATprojectchain(BAT **bats) @@ -507,8 +507,10 @@ BATprojectchain(BAT **bats) oid *t; struct canditer ci; /* used if .ci.s != NULL */ } *ba; + BAT **tobedeleted = NULL; + int ndelete = 0; int n; - BAT *b = NULL, *bn; + BAT *b = NULL, *bn = NULL; bool allnil = false; bool issorted = true; bool nonil = true; @@ -522,6 +524,7 @@ BATprojectchain(BAT **bats) * temporary work space */ for (n = 0; bats[n]; n++) { b = bats[n]; + ndelete += (b->ttype == TYPE_msk); TRC_DEBUG(ALGO, "arg %d: " ALGOBATFMT "\n", n + 1, ALGOBATPAR(b)); } @@ -537,12 +540,24 @@ BATprojectchain(BAT **bats) return bn; } + if (ndelete > 0 && + (tobedeleted = GDKmalloc(sizeof(BAT *) * ndelete)) == NULL) + return NULL; ba = GDKmalloc(sizeof(*ba) * n); - if (ba == NULL) + if (ba == NULL) { + GDKfree(tobedeleted); return NULL; + } + ndelete = 0; for (n = 0; bats[n]; n++) { b = bats[n]; + if (b->ttype == TYPE_msk) { + if ((b = BATunmask(b)) == NULL) { + goto bunins_failed; + } + tobedeleted[ndelete++] = b; + } ba[n] = (struct ba) { .b = b, .hlo = b->hseqbase, @@ -564,6 +579,9 @@ BATprojectchain(BAT **bats) if (allnil || ba[0].cnt == 0) { bn = BATconstant(ba[0].hlo, tpe == TYPE_oid ? TYPE_void : tpe, nil, ba[0].cnt, TRANSIENT); + while (ndelete-- > 0) + BBPreclaim(tobedeleted[ndelete]); + GDKfree(tobedeleted); GDKfree(ba); TRC_DEBUG(ALGO, "with %d bats: nil/empty -> " ALGOOPTBATFMT " " LLFMT " usec\n", @@ -578,8 +596,7 @@ BATprojectchain(BAT **bats) bn = COLnew(ba[0].hlo, tpe, ba[0].cnt, TRANSIENT); if (bn == NULL) { - GDKfree(ba); - return NULL; + goto bunins_failed; } if (ATOMtype(b->ttype) == TYPE_oid) { @@ -693,6 +710,9 @@ BATprojectchain(BAT **bats) } n++; /* undo for debug print */ } + while (ndelete-- > 0) + BBPreclaim(tobedeleted[ndelete]); + GDKfree(tobedeleted); BATsetcount(bn, ba[0].cnt); bn->tsorted = (ba[0].cnt <= 1) | issorted; bn->trevsorted = ba[0].cnt <= 1; @@ -704,6 +724,9 @@ BATprojectchain(BAT **bats) return bn; bunins_failed: + while (ndelete-- > 0) + BBPreclaim(tobedeleted[ndelete]); + GDKfree(tobedeleted); GDKfree(ba); BBPreclaim(bn); TRC_DEBUG(ALGO, "failed " LLFMT "usec\n", GDKusec() - t0); diff --git a/monetdb5/modules/mal/batMask.c b/monetdb5/modules/mal/batMask.c --- a/monetdb5/modules/mal/batMask.c +++ b/monetdb5/modules/mal/batMask.c @@ -104,19 +104,11 @@ MSKumask(Client cntxt, MalBlkPtr mb, Mal bid = getArgReference_bat(stk, pci, 1); if ((b = BATdescriptor(*bid)) == NULL) throw(SQL, "bat.umask", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING); - dst = COLnew(0, TYPE_oid, BATcount(b), TRANSIENT); + dst = BATunmask(b); if (dst == NULL) { BBPunfix(b->batCacheid); throw(MAL, "mask.umask", GDK_EXCEPTION); } - for (BUN p = 0; p < BATcount(b); p++) { - if (mskGetVal(b, p) && - BUNappend(dst, &(oid){p + b->hseqbase}, false) != GDK_SUCCEED) { - BBPunfix(b->batCacheid); - throw(MAL, "mask.umask", GDK_EXCEPTION); - } - } - *ret= dst->batCacheid; BBPkeepref(*ret); return MAL_SUCCEED; _______________________________________________ checkin-list mailing list checkin-list@monetdb.org https://www.monetdb.org/mailman/listinfo/checkin-list