📄 gdk_scanselect.mx
字号:
Expanding on whether we created the result BAT (at least) as big as theinput BAT, or not (see BAT_select in gdk_batop.mx). In the first case("nocheck"), we do not have to check for a "BAT overflow" in the inner loop.Further, we need to set bn->batBuns->free only once we're done.@c/* @1: input-tail-type for working function name, prefixed with predicate type (eq,lh,ln,nl,nn) @2: output-tail-type for bunfastins macro name @3: "tloc" / "tvar" specifying how to read the tail-input @4: the predicate @5: the tail to be store, being either the tail read ("v") or in case of equi-str-select the search string ("tl") @6: input-head-type for working function name @7: output-head-type for bunfastins macro name @8: how to access the head-input: "BUNhloc(b,p)", "BUNhvar(b,p)", or the oid counter ("&oid_ctr") in case we generate a void/oid output-head from a void input-head @9: in case we generate a void/oid output-head from a void input-head, this is the statement to inc the oid counter ("oid_ctr++;"), otherwise it's empty*/@= DEFseqscan/* Parameter "oid_ctr" is only used to hand-over the base oid in case we * generate a oid head from a void head. * Parameter "str_idx" is only used to hand-over the integer index for * equi-str-selects. */static BAT *seqscan_@1_@2_@3_@6_@7_nocheck_noinc(BAT* b, BAT* bn, ptr tl, ptr th, oid oid_ctr, var_t str_idx){ REGISTER BUN _p = BUNlast(bn); REGISTER int _bunsize = BUNsize(bn); @:seqscanPrologue@ ALGODEBUG THRprintf(GDKout, "#seqscan_@1_@2_@3_@6_@7_nocheck_noinc[@4,@5,@8,@9](b=%s, bn=%s, tl, th, oid_ctr=" SZFMT ", str_idx=" SZFMT ");\n", BATgetId(b), BATgetId(bn), (size_t) oid_ctr, (size_t) str_idx); BATloopFast(b, p, q, xx) { ptr v = BUN@3(b, p); @4 { @7@2_bunfastins_nocheck_noinc(bn, _p, (void *) (@8), @5); _p += _bunsize; } @9 } bn->batBuns->free = _p - bn->batBuns->base; BATsetcount(bn, bn->batBuns->free/_bunsize); @:seqscanEpilogue@}static BAT *seqscan_@1_@2_@3_@6_@7(BAT* b, BAT* bn, ptr tl, ptr th, oid oid_ctr, var_t str_idx){ @:seqscanPrologue@ ALGODEBUG THRprintf(GDKout, "#seqscan_@1_@2_@3_@6_@7[@4,@5,@8,@9](b=%s, bn=%s, tl, th, oid_ctr=" SZFMT ", str_idx=" SZFMT ");\n", BATgetId(b), BATgetId(bn), (size_t) oid_ctr, (size_t) str_idx); BATloopFast(b, p, q, xx) { ptr v = BUN@3(b, p);; @4 { @7@2_bunfastins(bn, (void *) (@8), @5); } @9 } @:seqscanEpilogue@}@= seqscan if (nocheck) { return seqscan_@1_@2_@3_@6_@7_nocheck_noinc(b, bn, tl, th, oid_ctr, str_idx); } else { return seqscan_@1_@2_@3_@6_@7(b, bn, tl, th, oid_ctr, str_idx); }@-Output-tail-type is either identical to input-tail-type or TYPE_void(uselect).@c/* @1: input-tail-type for working function name, prefixed with predicate type (eq,lh,ln,nl,nn) @2: output-tail-type for bunfastins macro name @3: "tloc" / "tvar" specifying how to read the tail-input @4: the predicate @5: the tail to be store, being either the tail read ("v") or in case of equi-str-select the search string ("tl") @6: input-head-type for working function name @7: output-head-type for bunfastins macro name @8: how to access the head-input: "BUNhloc(b,p)", "BUNhvar(b,p)", or the oid counter ("&oid_ctr") in case we generate a void/oid output-head from a void input-head @9: in case we generate a void/oid output-head from a void input-head, this is the statement to inc the oid counter ("oid_ctr++;"), otherwise it's empty*/@= DEFseqscanTTput @:DEFseqscan(@1,void,@3,@4,@5,@6,@7,@8,@9)@ @:DEFseqscan(@1,@2,@3,@4,@5,@6,@7,@8,@9)@@= seqscanTTput if (bn->ttype == TYPE_void) { @:seqscan(@1,void,@3,@4,@5,@6,@7,@8,@9)@ } else { @:seqscan(@1,@2,@3,@4,@5,@6,@7,@8,@9)@ }@-Expand on output-head-type; usually inherited from input-head-type.@c/* @1: input-tail-type for working function name, prefixed with predicate type (eq,lh,ln,nl,nn) @2: output-tail-type for bunfastins macro name @3: "tloc" / "var" specifying how to read the tail-input @4: the predicate @5: the tail to be store, being either the tail read ("v") or in case of equi-str-select the search string ("tl") @6: input-head-type for working function name @7: output-head-type for bunfastins macro name @8: how to access the head-input: "BUNhloc(b,p)", "BUNhvar(b,p)", or the oid counter ("&oid_ctr") in case we generate a void/oid output-head from a void input-head @9: in case we generate a void/oid output-head from a void input-head, this is the statement to inc the oid counter ("oid_ctr++;"), otherwise it's empty*/@= DEFseqscanHTput#ifndef SKIP_TYPE_EXPANSIONS#ifndef NOEXPAND_CHR @:DEFseqscanTTput(@1,@2,@3,@4,@5,chr,chr,BUNhloc(b,p),)@#endif /* NOEXPAND_CHR */#ifndef NOEXPAND_BTE @:DEFseqscanTTput(@1,@2,@3,@4,@5,bte,bte,BUNhloc(b,p),)@#endif /* NOEXPAND_CHR */#ifndef NOEXPAND_SHT @:DEFseqscanTTput(@1,@2,@3,@4,@5,sht,sht,BUNhloc(b,p),)@#endif /* NOEXPAND_SHT */#ifndef NOEXPAND_INT @:DEFseqscanTTput(@1,@2,@3,@4,@5,int,int,BUNhloc(b,p),)@#endif /* NOEXPAND_INT */#ifndef NOEXPAND_LNG @:DEFseqscanTTput(@1,@2,@3,@4,@5,lng,lng,BUNhloc(b,p),)@#endif /* NOEXPAND_LNG */#endif /* SKIP_TYPE_EXPANSIONS */ @:DEFseqscanTTput(@1,@2,@3,@4,@5,fix,any,BUNhloc(b,p),)@ @:DEFseqscanTTput(@1,@2,@3,@4,@5,var,any,BUNhvar(b,p),)@@= seqscanHTput#ifndef SKIP_TYPE_EXPANSIONS#ifndef NOEXPAND_CHR if (AsHt == TYPE_chr) { @:seqscanTTput(@1,@2,@3,@4,@5,chr,chr,BUNhloc(b,p),)@ } else#endif /* NOEXPAND_CHR */#ifndef NOEXPAND_BTE if (AsHt == TYPE_bte) { @:seqscanTTput(@1,@2,@3,@4,@5,bte,bte,BUNhloc(b,p),)@ } else#endif /* NOEXPAND_BTE */#ifndef NOEXPAND_SHT if (AsHt == TYPE_sht) { @:seqscanTTput(@1,@2,@3,@4,@5,sht,sht,BUNhloc(b,p),)@ } else#endif /* NOEXPAND_SHT */#ifndef NOEXPAND_INT if (bn->htype != TYPE_bat && (AsHt == TYPE_int || AsHt == TYPE_flt)) { /* ensure use of ATOMput for TYPE_bat */ @:seqscanTTput(@1,@2,@3,@4,@5,int,int,BUNhloc(b,p),)@ } else#endif /* NOEXPAND_INT */#ifndef NOEXPAND_LNG if (AsHt == TYPE_dbl || AsHt == TYPE_lng) { @:seqscanTTput(@1,@2,@3,@4,@5,lng,lng,BUNhloc(b,p),)@ } else#endif /* NOEXPAND_LNG */#endif /* SKIP_TYPE_EXPANSIONS */ if (b->hvarsized) { @:seqscanTTput(@1,@2,@3,@4,@5,var,any,BUNhvar(b,p),)@ } else { @:seqscanTTput(@1,@2,@3,@4,@5,fix,any,BUNhloc(b,p),)@ }@-Expanding on input-head-type for data read.Taking special care of void/oid.@c/* @1: input-tail-type for working function name, prefixed with predicate type (eq,lh,ln,nl,nn) @2: output-tail-type for bunfastins macro name @3: "tloc" / "tvar" specifying how to read the tail-input @4: the predicate @5: the tail to be store, being either the tail read ("v") or in case of equi-str-select the search string ("tl")*/@= DEFseqscanHTget @:DEFseqscan(@1,@2,@3,@4,@5,void,void,&oid_ctr,)@#if SIZEOF_OID == SIZEOF_INT && !defined(NOEXPAND_INT) @:DEFseqscanTTput(@1,@2,@3,@4,@5,oid,int,&oid_ctr,oid_ctr++;)@#elif SIZEOF_OID == SIZEOF_LNG && !defined(NOEXPAND_LNG) @:DEFseqscanTTput(@1,@2,@3,@4,@5,oid,lng,&oid_ctr,oid_ctr++;)@#else @:DEFseqscanTTput(@1,@2,@3,@4,@5,oid,any,&oid_ctr,oid_ctr++;)@#endif /* SIZEOF_OID == SIZEOF_INT */ @:DEFseqscanHTput(@1,@2,@3,@4,@5)@@= seqscanHTget if (BAThvoid(b)) { /* input-head is void. we decide here, whether output-head * sould be void or oid, and skip seqscanHTput */ oid_ctr = b->hseqbase; if (oid_ctr == oid_nil) { /* avoid computing BUNpos many times over * output-head is void, hence output-tail cannot be void, * hence we can skip seqscanTTput */ @:seqscan(@1,@2,@3,@4,@5,void,void,&oid_ctr,)@ } else { /* increment instead of compute BUNpos */#if SIZEOF_OID == SIZEOF_INT && !defined(NOEXPAND_INT) @:seqscanTTput(@1,@2,@3,@4,@5,oid,int,&oid_ctr,oid_ctr++;)@#elif SIZEOF_OID == SIZEOF_LNG && !defined(NOEXPAND_LNG) @:seqscanTTput(@1,@2,@3,@4,@5,oid,lng,&oid_ctr,oid_ctr++;)@#else @:seqscanTTput(@1,@2,@3,@4,@5,oid,any,&oid_ctr,oid_ctr++;)@#endif } } else { /* output-head is identical to input-head. */ @:seqscanHTput(@1,@2,@3,@4,@5)@ }@-Expanding on the type of predicate: either equi, or range.The latter with both, one, or none of upper bound and lower bound.In case of a range select we skip all nil.@c/* @1: input-tail-type for working function name @2: output-tail-type for bunfastins macro name @3: "tloc" / "tvar" specifying how to read the tail-input @4: "simple" or "atom" @5: input-tail-type for comparison @6: in case of range selects with lower bound on types where nil != MIN: check for v != nil otherwise empty as then @4_LE(tl ,v,@5) with tl != nil (i.e., tl > nil) already ensures v != nil*/@= DEFseqscanIF @:DEFseqscanHTget(eq_@1,@2,@3,if ( @4_EQ(tl ,v,@5) ),v)@ @:DEFseqscanHTget(LH_@1,@2,@3,if ( @4_LE(tl ,v,@5) && @4_LE(v,th,@5) @6 ),v)@ @:DEFseqscanHTget(Lh_@1,@2,@3,if ( @4_LE(tl ,v,@5) && @4_LT(v,th,@5) @6 ),v)@ @:DEFseqscanHTget(lH_@1,@2,@3,if ( @4_LT(tl ,v,@5) && @4_LE(v,th,@5) @6 ),v)@ @:DEFseqscanHTget(lh_@1,@2,@3,if ( @4_LT(tl ,v,@5) && @4_LT(v,th,@5) @6 ),v)@ @:DEFseqscanHTget(Ln_@1,@2,@3,if ( @4_LE(tl ,v,@5) @6 ),v)@ @:DEFseqscanHTget(ln_@1,@2,@3,if ( @4_LT(tl ,v,@5) @6 ),v)@ @:DEFseqscanHTget(nH_@1,@2,@3,if (!@4_EQ(nil,v,@5) && @4_LE(v,th,@5) ),v)@ @:DEFseqscanHTget(nh_@1,@2,@3,if (!@4_EQ(nil,v,@5) && @4_LT(v,th,@5) ),v)@ @:DEFseqscanHTget(nn_@1,@2,@3,if (!@4_EQ(nil,v,@5) ),v)@@= seqscanIF if (equi) { @:seqscanHTget(eq_@1,@2,@3,if ( @4_EQ(tl ,v,@5) ),v)@ /* rangeselect => we always skip nil * (explicitely by !@4_EQ(nil,v,@5) or @6 * or implicitely by @4_LE(tl,v,@5)) */ } else if (lval && hval) { if (li && hi) { @:seqscanHTget(LH_@1,@2,@3,if ( @4_LE(tl ,v,@5) && @4_LE(v,th,@5) @6 ),v)@ } else if (li && !hi) { @:seqscanHTget(Lh_@1,@2,@3,if ( @4_LE(tl ,v,@5) && @4_LT(v,th,@5) @6 ),v)@ } else if (!li && hi) { @:seqscanHTget(lH_@1,@2,@3,if ( @4_LT(tl ,v,@5) && @4_LE(v,th,@5) @6 ),v)@ } else { @:seqscanHTget(lh_@1,@2,@3,if ( @4_LT(tl ,v,@5) && @4_LT(v,th,@5) @6 ),v)@ } } else if (lval) { if (li) { @:seqscanHTget(Ln_@1,@2,@3,if ( @4_LE(tl ,v,@5) @6 ),v)@ } else { @:seqscanHTget(ln_@1,@2,@3,if ( @4_LT(tl ,v,@5) @6 ),v)@ } } else if (hval) { if (hi) { @:seqscanHTget(nH_@1,@2,@3,if (!@4_EQ(nil,v,@5) && @4_LE(v,th,@5) ),v)@ } else { @:seqscanHTget(nh_@1,@2,@3,if (!@4_EQ(nil,v,@5) && @4_LT(v,th,@5) ),v)@ } } else { @:seqscanHTget(nn_@1,@2,@3,if (!@4_EQ(nil,v,@5) ),v)@ }@-Expanding on input-tail-type for data read and comparison.Most is straight forward.Taking special care of equi selects on str when there are no doubles in theheap.Adding test for v != nil for types where nil != MIN.@= DEFseqscanTTget#ifndef SKIP_TYPE_EXPANSIONS#ifndef NOEXPAND_CHR @:DEFseqscanIF(chr,chr,tloc,simple,chr,)@#endif#ifndef NOEXPAND_BTE @:DEFseqscanIF(bte,bte,tloc,simple,bte,)@#endif#ifndef NOEXPAND_SHT @:DEFseqscanIF(sht,sht,tloc,simple,sht,)@#endif#ifndef NOEXPAND_INT @:DEFseqscanIF(int,int,tloc,simple,int,)@#endif#ifndef NOEXPAND_FLT @:DEFseqscanIF(flt,int,tloc,simple,flt,)@#endif#ifndef NOEXPAND_DBL @:DEFseqscanIF(dbl,lng,tloc,simple,dbl,)@#endif#ifndef NOEXPAND_LNG @:DEFseqscanIF(lng,lng,tloc,simple,lng,)@#endif#endif /* SKIP_TYPE_EXPANSIONS */ @:DEFseqscanHTget(eq_str,any,tloc,if(*(var_t*)v==str_idx),tl)@ @:DEFseqscanIF(fix,any,tloc,atom,t,&&!atom_EQ(nil,v,t))@ @:DEFseqscanIF(var,any,tvar,atom,t,&&!atom_EQ(nil,v,t))@@= seqscanTTget#ifndef SKIP_TYPE_EXPANSIONS#ifndef NOEXPAND_CHR if (AsTt == TYPE_chr) { @:seqscanIF(chr,chr,tloc,simple,chr,)@ } else#endif /* NOEXPAND_CHR */#ifndef NOEXPAND_BTE if (AsTt == TYPE_bte) { @:seqscanIF(bte,bte,tloc,simple,bte,)@ } else#endif /* NOEXPAND_BTE */#ifndef NOEXPAND_SHT if (AsTt == TYPE_sht) { @:seqscanIF(sht,sht,tloc,simple,sht,)@ } else#endif /* NOEXPAND_SHT */#ifndef NOEXPAND_INT if (AsTt == TYPE_int && t != TYPE_bat) { /* ensure use of ATOMput for TYPE_bat */ @:seqscanIF(int,int,tloc,simple,int,)@ } else#endif /* NOEXPAND_INT */#ifndef NOEXPAND_FLT if (AsTt == TYPE_flt) { @:seqscanIF(flt,int,tloc,simple,flt,)@ } else#endif /* NOEXPAND_FLT */#ifndef NOEXPAND_DBL if (AsTt == TYPE_dbl) { @:seqscanIF(dbl,lng,tloc,simple,dbl,)@ } else#endif /* NOEXPAND_DBL */#ifndef NOEXPAND_LNG if (AsTt == TYPE_lng) { @:seqscanIF(lng,lng,tloc,simple,lng,)@ } else#endif /* NOEXPAND_LNG */#endif /* SKIP_TYPE_EXPANSIONS */ if (b->tvarsized) { if (equi && t == TYPE_str && strElimDoubles(b->theap)) { /* Single-valued sequential scans for strings are * optimized when double elemination is in effect, * by scanning for the correct integer index value. * This is an equi select, so we assemble the * predicate here and skip seqscanIF. */ str_idx = strLocate(b->theap, tl); @:seqscanHTget(eq_str,any,tloc,if((*(var_t*)v)==str_idx),tl)@ } else { @:seqscanIF(var,any,tvar,atom,t,&&!atom_EQ(nil,v,t))@ } } else { @:seqscanIF(fix,any,tloc,atom,t,&&!atom_EQ(nil,v,t))@ }@-Generate all working functions.@c@:DEFseqscanTTget@@-The dispatcher, called from BAT_select (gdk_batop.mx).@cBAT *BAT_scanselect(BAT *b, BAT *bn, ptr tl, ptr th, bit li, bit hi, int equi, int lval, int hval, int nocheck){ int t = b->ttype;#ifndef SKIP_TYPE_EXPANSIONS#if !defined(NOEXPAND_CHR) || !defined(NOEXPAND_SHT) || !defined(NOEXPAND_INT) || !defined(NOEXPAND_LNG) int AsHt = ATOMstorage(bn->htype), AsTt = ATOMstorage(t);#endif#endif var_t str_idx = 0; oid oid_ctr = (oid) 0; @:seqscanTTget@ /* return is called in the leave of the decision tree to shortcut * the exit from this dispatcher function. */}@}@-
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -