str DCsliceStrict(int *ret, bat *bid, lng *start, lng *end) { BAT *b, *bn = NULL; if ((b = BATdescriptor(*bid)) == NULL) { throw(MAL, "dcoperator.sliceStrict", "Cannot access descriptor"); } assert(*start >= 0); assert(*end >= 0); assert(*start <= (lng) BUN_MAX); assert(*end < (lng) BUN_MAX); assert(*start <= *end); if ((BUN) ((*end - *start) + 1) > BATcount(b)) { bn = BATnew(b->htype, b->ttype, 0); BATsetcount(bn, 0); *ret = bn->batCacheid; BBPkeepref(*ret); return MAL_SUCCEED; } bn = BATslice(b, (BUN) *start, (BUN) *end + 1); BBPreleaseref(b->batCacheid); if (bn != NULL) { if (!(bn->batDirty & 2)) bn = BATsetaccess(bn, BAT_READ); *ret = bn->batCacheid; BBPkeepref(*ret); return MAL_SUCCEED; } throw(MAL, "dcoperator.sliceStrict", "GDKerror"); }
static str MATpackSliceInternal(MalBlkPtr mb, MalStkPtr stk, InstrPtr p) { int i, i1 = p->argc, i2 = -1, *ret = (int*) getArgReference(stk,p,0); BAT *b, *bn; BUN cap = 0, fst, lst, cnt, c; int ht = TYPE_any, tt = TYPE_any; assert(p->argc > 3); switch getArgType(mb,p,1) { case TYPE_wrd: fst = (BUN) *(wrd*) getArgReference(stk,p,1); break; case TYPE_lng: fst = (BUN) *(lng*) getArgReference(stk,p,1); break; case TYPE_int: fst = (BUN) *(int*) getArgReference(stk,p,1); break; default: throw(MAL, "mat.packSlice", "wrong type for lower bound"); } switch getArgType(mb,p,2) { case TYPE_wrd: { wrd l = *(wrd*) getArgReference(stk,p,2); if (l == wrd_nil) lst = BUN_MAX; /* no upper bound */ else lst = (BUN) l; break; } case TYPE_lng: { lng l = *(lng*) getArgReference(stk,p,2); if (l == lng_nil) lst = BUN_MAX; /* no upper bound */ else lst = (BUN) l; break; } case TYPE_int: { int l = *(int*) getArgReference(stk,p,2); if (l == int_nil) lst = BUN_MAX; /* no upper bound */ else lst = (BUN) l; break; } default: throw(MAL, "mat.packSlice", "wrong type for upper bound"); } if (lst < BUN_MAX) lst++; /* inclusive -> exclusive upper bound */ if (lst < fst) lst = fst; cnt = lst - fst; for (i = 3; i < p->argc && cap < lst; i++) { int bid = stk->stk[getArg(p,i)].val.ival; b = BBPquickdesc(abs(bid),FALSE); if (b && bid < 0) b = BATmirror(b); if (b == NULL) throw(MAL, "mat.packSlice", RUNTIME_OBJECT_MISSING); if (ht == TYPE_any){ ht = b->htype; tt = b->ttype; } c = BATcount(b); if (cap <= fst) { /* The optimal case is when the requested slice falls completely in one BAT. * In that case, we can simply return a slice (view) of that BAT. * (A pitty that we have calculated the other slices as well.) */ if (lst <= cap + c) { b = BATdescriptor(bid); if( b){ bn = BATslice(b, fst - cap, lst - cap); BBPunfix(b->batCacheid); BBPkeepref(*ret = bn->batCacheid); } else throw(MAL, "mat.packSlice", RUNTIME_OBJECT_MISSING); return MAL_SUCCEED; } if (fst < cap + c) { /* fst falls in BAT i1 == i */ i1 = i; fst -= cap; lst -= cap; cap = 0; } } cap += c; } /* lst falls in BAT i2 == i-1 */ i2 = i - 1; if (cap <= fst) /* i.e., (i1 > i2) */ cap = 0; else cap -= fst; cnt = MIN(cnt, cap); assert(ht== TYPE_void); bn = BATnew(TYPE_void, tt, cnt, TRANSIENT); if (bn == NULL) throw(MAL, "mat.packSlice", MAL_MALLOC_FAIL); /* must set seqbase or else BATins will not materialize column */ BATseqbase(bn, 0); if (tt == TYPE_void) BATseqbase(BATmirror(bn), 0); for (i = i1; i <= i2; i++) { b = BATdescriptor(stk->stk[getArg(p,i)].val.ival); if (b == NULL){ BBPreleaseref(bn->batCacheid); throw(MAL, "mat.packSlice", RUNTIME_OBJECT_MISSING); } c = BATcount(b); /* use the right oid ranges, don't change the input */ if (i == i1 && fst > 0) { BAT *bb = b; b = BATslice(bb, fst, c); BBPunfix(bb->batCacheid); } else if (i == i2 && lst < c) { BAT *bb = b; b = BATslice(bb, 0, lst); BBPunfix(bb->batCacheid); } BATins(bn,b,FALSE); lst -= c; BBPunfix(b->batCacheid); } BBPkeepref(*ret = bn->batCacheid); return MAL_SUCCEED; }
/* * grouped aggregates */ static str AGGRgrouped(bat *retval1, bat *retval2, BAT *b, BAT *g, BAT *e, int tp, BAT *(*grpfunc1)(BAT *, BAT *, BAT *, BAT *, int, int, int), gdk_return (*grpfunc2)(BAT **, BAT **, BAT *, BAT *, BAT *, BAT *, int, int, int), BAT *(*quantilefunc)(BAT *, BAT *, BAT *, BAT *, int, double, int, int), BAT *quantile, int skip_nils, const char *malfunc) { BAT *bn, *cnts = NULL, *t, *map; double qvalue; /* one of grpfunc1, grpfunc2 and quantilefunc is non-NULL and the others are */ assert((grpfunc1 != NULL && grpfunc2 == NULL && quantilefunc == NULL) || (grpfunc1 == NULL && grpfunc2 != NULL && quantilefunc == NULL) || (grpfunc1 == NULL && grpfunc2 == NULL && quantilefunc != NULL) ); /* if retval2 is non-NULL, we must have grpfunc2 */ assert(retval2 == NULL || grpfunc2 != NULL); assert(quantile == NULL || quantilefunc != NULL); if (b == NULL || g == NULL || e == NULL) { if (b) BBPreleaseref(b->batCacheid); if (g) BBPreleaseref(g->batCacheid); if (e) BBPreleaseref(e->batCacheid); throw(MAL, malfunc, RUNTIME_OBJECT_MISSING); } if (tp == TYPE_any && (grpfunc1 == BATgroupmedian || quantilefunc == BATgroupquantile)) tp = b->ttype; if (!BAThdense(b) || !BAThdense(g)) { /* if b or g don't have a dense head, replace the head with a * dense sequence */ t = BATjoin(BATmirror(b), g, MIN(BATcount(b), BATcount(g))); BBPreleaseref(b->batCacheid); BBPreleaseref(g->batCacheid); b = BATmirror(BATmark(t, 0)); g = BATmirror(BATmark(BATmirror(t), 0)); BBPreleaseref(t->batCacheid); } if (b->hseqbase != g->hseqbase || BATcount(b) != BATcount(g)) { /* b and g are not aligned: align them by creating a view on * one or the other */ oid min; /* lowest common oid */ oid max; /* highest common oid */ min = b->hseqbase; if (min < g->hseqbase) min = g->hseqbase; max = b->hseqbase + BATcount(b); if (g->hseqbase + BATcount(g) < max) max = g->hseqbase + BATcount(g); if (b->hseqbase != min || b->hseqbase + BATcount(b) != max) { if (min >= max) min = max = b->hseqbase; t = BATslice(b, BUNfirst(b) + (BUN) (min - b->hseqbase), BUNfirst(b) + (BUN) (max - b->hseqbase)); BBPreleaseref(b->batCacheid); b = t; } if (g->hseqbase != min || g->hseqbase + BATcount(g) != max) { if (min >= max) min = max = g->hseqbase; t = BATslice(g, BUNfirst(g) + (BUN) (min - g->hseqbase), BUNfirst(g) + (BUN) (max - g->hseqbase)); BBPreleaseref(g->batCacheid); g = t; } } if (!BAThdense(e)) { /* if e doesn't have a dense head, renumber the group ids with * a dense sequence at the cost of some left joins */ map = BATmark(e, 0); /* [gid,newgid(dense)] */ BBPreleaseref(e->batCacheid); e = BATmirror(map); /* [newgid(dense),gid] */ t = BATleftjoin(g, map, BATcount(g)); /* [oid,newgid] */ BBPreleaseref(g->batCacheid); g = t; } else { map = NULL; } if (grpfunc1) bn = (*grpfunc1)(b, g, e, NULL, tp, skip_nils, 1); if (quantilefunc) { assert(BATcount(quantile)>0); assert(quantile->ttype == TYPE_dbl); qvalue = ((const double *)Tloc(quantile, BUNfirst(quantile)))[0]; if (qvalue < 0|| qvalue > 1) { char *s; s = createException(MAL, malfunc, "quantile value of %f is not in range [0,1]", qvalue); return s; } bn = (*quantilefunc)(b, g, e, NULL, tp, qvalue, skip_nils, 1); } if (grpfunc2 && (*grpfunc2)(&bn, retval2 ? &cnts : NULL, b, g, e, NULL, tp, skip_nils, 1) == GDK_FAIL) bn = NULL; if (bn != NULL && (grpfunc1 == BATgroupmin || grpfunc1 == BATgroupmax)) { t = BATproject(bn, b); BBPreleaseref(bn->batCacheid); bn = t; } BBPreleaseref(b->batCacheid); BBPreleaseref(g->batCacheid); if (map == NULL) /* if map!=NULL, e is mirror of map */ BBPreleaseref(e->batCacheid); if (bn == NULL) { char *errbuf = GDKerrbuf; char *s; if (map) BBPreleaseref(map->batCacheid); if (errbuf && *errbuf) { if (strncmp(errbuf, "!ERROR: ", 8) == 0) errbuf += 8; if (strchr(errbuf, '!') == errbuf + 5) { s = createException(MAL, malfunc, "%s", errbuf); } else if ((s = strchr(errbuf, ':')) != NULL && s[1] == ' ') { s = createException(MAL, malfunc, "%s", s + 2); } else { s = createException(MAL, malfunc, "%s", errbuf); } *GDKerrbuf = 0; return s; } throw(MAL, malfunc, OPERATION_FAILED); } if (map) { t = BATleftjoin(map, bn, BATcount(bn)); BBPreleaseref(bn->batCacheid); bn = t; if (cnts) { t = BATleftjoin(map, cnts, BATcount(cnts)); BBPreleaseref(cnts->batCacheid); cnts = t; } BBPreleaseref(map->batCacheid); } *retval1 = bn->batCacheid; BBPkeepref(bn->batCacheid); if (retval2) { *retval2 = cnts->batCacheid; BBPkeepref(cnts->batCacheid); } return MAL_SUCCEED; }
/* * grouped aggregates */ static str AGGRgrouped(bat *retval, BAT *b, BAT *g, BAT *e, int tp, BAT *(*grpfunc)(BAT *, BAT *, BAT *, BAT *, int, int, int), int skip_nils, const char *malfunc) { BAT *bn, *t, *map; if (b == NULL || g == NULL || e == NULL) { if (b) BBPreleaseref(b->batCacheid); if (g) BBPreleaseref(g->batCacheid); if (e) BBPreleaseref(e->batCacheid); throw(MAL, malfunc, RUNTIME_OBJECT_MISSING); } if (tp == TYPE_any && grpfunc == BATgroupmedian) tp = b->ttype; if (!BAThdense(b) || !BAThdense(g)) { /* if b or g don't have a dense head, replace the head with a * dense sequence */ t = BATjoin(BATmirror(b), g, MIN(BATcount(b), BATcount(g))); BBPreleaseref(b->batCacheid); BBPreleaseref(g->batCacheid); b = BATmirror(BATmark(t, 0)); g = BATmirror(BATmark(BATmirror(t), 0)); BBPreleaseref(t->batCacheid); } if (b->hseqbase != g->hseqbase || BATcount(b) != BATcount(g)) { /* b and g are not aligned: align them by creating a view on * one or the other */ oid min; /* lowest common oid */ oid max; /* highest common oid */ min = b->hseqbase; if (min < g->hseqbase) min = g->hseqbase; max = b->hseqbase + BATcount(b); if (g->hseqbase + BATcount(g) < max) max = g->hseqbase + BATcount(g); if (b->hseqbase != min || b->hseqbase + BATcount(b) != max) { if (min >= max) min = max = b->hseqbase; t = BATslice(b, BUNfirst(b) + (BUN) (min - b->hseqbase), BUNfirst(b) + (BUN) (max - b->hseqbase)); BBPreleaseref(b->batCacheid); b = t; } if (g->hseqbase != min || g->hseqbase + BATcount(g) != max) { if (min >= max) min = max = g->hseqbase; t = BATslice(g, BUNfirst(g) + (BUN) (min - g->hseqbase), BUNfirst(g) + (BUN) (max - g->hseqbase)); BBPreleaseref(g->batCacheid); g = t; } } if (!BAThdense(e)) { /* if e doesn't have a dense head, renumber the group ids with * a dense sequence at the cost of some left joins */ map = BATmark(e, 0); /* [gid,newgid(dense)] */ BBPreleaseref(e->batCacheid); e = BATmirror(map); /* [newgid(dense),gid] */ t = BATleftjoin(g, map, BATcount(g)); /* [oid,newgid] */ BBPreleaseref(g->batCacheid); g = t; } else { map = NULL; } bn = (*grpfunc)(b, g, e, NULL, tp, skip_nils, 1); if (bn != NULL && (grpfunc == BATgroupmin || grpfunc == BATgroupmax)) { BAT *bnn = BATouterjoin(bn, b, BATcount(bn)); BBPreleaseref(bn->batCacheid); bn = bnn; } BBPreleaseref(b->batCacheid); BBPreleaseref(g->batCacheid); if (map == NULL) /* if map!=NULL, e is mirror of map */ BBPreleaseref(e->batCacheid); if (bn == NULL) { char *errbuf = GDKerrbuf; char *s; if (map) BBPreleaseref(map->batCacheid); if (errbuf && *errbuf) { if (strncmp(errbuf, "!ERROR: ", 8) == 0) errbuf += 8; if (strchr(errbuf, '!') == errbuf + 5) { s = createException(MAL, malfunc, "%s", errbuf); } else if ((s = strchr(errbuf, ':')) != NULL && s[1] == ' ') { s = createException(MAL, malfunc, "%s", s + 2); } else { s = createException(MAL, malfunc, "%s", errbuf); } *GDKerrbuf = 0; return s; } throw(MAL, malfunc, OPERATION_FAILED); } if (map) { t = BATleftjoin(map, bn, BATcount(bn)); BBPreleaseref(map->batCacheid); BBPreleaseref(bn->batCacheid); bn = t; } *retval = bn->batCacheid; BBPkeepref(bn->batCacheid); return MAL_SUCCEED; }