Changeset: f3c7044d813f for MonetDB
URL: http://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=f3c7044d813f
Modified Files:
        gdk/gdk_select.c
Branch: default
Log Message:

fully type-expanded scan-select implementation


keeping Sjoerd's general code "architecture",
but avoiding generic BUN access and comparison functions
(function pointers) where ever possible;
also wrapping core loop per type in separate function
to simplify optimization for compilers


diffs (truncated from 305 to 300 lines):

diff --git a/gdk/gdk_select.c b/gdk/gdk_select.c
--- a/gdk/gdk_select.c
+++ b/gdk/gdk_select.c
@@ -169,66 +169,139 @@ BAT_hashselect(BAT *b, BAT *s, BAT *bn, 
        return bn;
 }
 
-/* scan select loop with candidates */
-#define candscanloop(TEST)                                             \
-       do {                                                            \
-               ALGODEBUG fprintf(stderr,                               \
-                           "#BATsubselect(b=%s#"BUNFMT",s=%s,anti=%d): " \
-                           "scanselect %s\n", BATgetId(b), BATcount(b), \
-                           s ? BATgetId(s) : "NULL", anti, #TEST);     \
-               r = p;                                                  \
+
+/* core scan select loop with & without candidates */
+#define scanloop(CAND,READ,TEST)                                       \
+do {                                                                   \
+       ALGODEBUG fprintf(stderr,                                       \
+                       "#BATsubselect(b=%s#"BUNFMT",s=%s,anti=%d): "   \
+                       "scanselect %s\n", BATgetId(b), BATcount(b),    \
+                       s ? BATgetId(s) : "NULL", anti, #TEST);         \
+       if (BATcapacity(bn) < maximum) {                                \
                while (p < q) {                                         \
-                       o = *candlist++;                                \
-                       v = BUNtail(bi, o - off);                       \
+                       CAND;                                           \
+                       READ;                                           \
                        if (TEST) {                                     \
                                buninsfix(bn, T, dst, cnt, oid, o,      \
                                          (BUN) ((dbl) cnt / (dbl) (p-r)\
                                                 * (dbl) (q-p) * 1.1),  \
-                                         maximum, NULL);               \
+                                         maximum, BUN_NONE);           \
                                cnt++;                                  \
                        }                                               \
                        p++;                                            \
                }                                                       \
-       } while (0)
-
-/* scan select loop without candidates */
-#define scanloop(TEST)                                                 \
-       do {                                                            \
-               ALGODEBUG fprintf(stderr,                               \
-                           "#BATsubselect(b=%s#"BUNFMT",s=%s,anti=%d): " \
-                           "scanselect %s\n", BATgetId(b), BATcount(b), \
-                           s ? BATgetId(s) : "NULL", anti, #TEST);     \
-               r = p;                                                  \
+       } else {                                                        \
                while (p < q) {                                         \
-                       v = BUNtail(bi, p);                             \
+                       CAND;                                           \
+                       READ;                                           \
                        if (TEST) {                                     \
-                               o = (oid) p + off;                      \
-                               buninsfix(bn, T, dst, cnt, oid, o,      \
-                                         (BUN) ((dbl) cnt / (dbl) (p-r)\
-                                                * (dbl) (q-p) * 1.1),  \
-                                         maximum, NULL);               \
+                               dst[cnt] = o;                           \
                                cnt++;                                  \
                        }                                               \
                        p++;                                            \
                }                                                       \
-       } while (0)
+       }                                                               \
+} while (0)
+
+/* scan select predicate switch */
+#define scantest(CAND,READ,COMP)                               \
+do {                                                           \
+       if (equi) {                                             \
+               scanloop ( CAND , READ , COMP(v,==,vl) );       \
+       } else                                                  \
+       if (anti) {                                             \
+               scanloop ( CAND , READ ,                        \
+                         (b->T->nonil || COMP(v,!=,nil)) &&    \
+                         ((lval && (COMP(v,<,vl) ||            \
+                           (!li && COMP(v,==,vl)))) ||         \
+                          (hval && (COMP(v,>,vh) ||            \
+                           (!hi && COMP(v,==,vh))))) );        \
+       } else {                                                \
+               scanloop ( CAND , READ ,                        \
+                         (b->T->nonil || COMP(v,!=,nil)) &&    \
+                         ((!lval ||  COMP(v,>,vl) ||           \
+                           (li && COMP(v,==,vl))) &&           \
+                          (!hval ||  COMP(v,<,vh) ||           \
+                           (hi && COMP(v,==,vh)))) );          \
+       }                                                       \
+} while (0)
+
+/* local variables for known fixed-width types */
+#define scaninit_fix(TYPE)                             \
+       TYPE vl = *(TYPE *) tl;                         \
+       TYPE vh = *(TYPE *) th;                         \
+       TYPE v;                                         \
+       TYPE nil = TYPE##_nil;                          \
+       const TYPE *src = (const TYPE *) Tloc(b, 0);
+
+/* local variables for generic types */
+#define scaninit_var(TYPE)                                             \
+       const void *vl = tl;                                            \
+       const void *vh = th;                                            \
+       const void *v;                                                  \
+       const void *nil = ATOMnilptr(b->ttype);                         \
+       int (*cmp)(const void *, const void *) = BATatoms[b->ttype].atomCmp;\
+       BATiter bi = bat_iterator(b);                                   \
+
+/* various comparison calls for known fixed-width types */
+#define scancomp_fix(l,o,r)    (l) o (r)
+
+/* various comparison calls for generic types */
+#define scancomp_var(l,o,r)    (*cmp)((l),(r)) o 0
+
+/* argument list for type-specific core scan select function call */
+#define scanargs       \
+       b, s, bn, tl, th, li, hi, equi, anti, lval, hval, \
+       p, q, cnt, off, dst, candlist, maximum
+
+/* definition of type-specific core scan select function */
+#define scanfunc(NAME,WHAT,TYPE,CAND,READ)                             \
+static BUN                                                             \
+NAME##_##TYPE (BAT *b, BAT *s, BAT *bn, const void *tl, const void *th,        
\
+               int li, int hi, int equi, int anti, int lval, int hval, \
+               BUN r, BUN q, BUN cnt, wrd off, oid *dst,               \
+               const oid *candlist, BUN maximum)                       \
+{                                                                      \
+       scaninit_##WHAT ( TYPE )                                        \
+       oid o;                                                          \
+       BUN p = r;                                                      \
+       (void) candlist;                                                \
+       scantest(CAND, READ, scancomp_##WHAT);                          \
+       return cnt;                                                     \
+}
+
+/* scan select type switch */
+#define scan_sel(NAME,CAND)                                            \
+       scanfunc ( NAME , fix , bte , CAND , v = src[o-off]        )    \
+       scanfunc ( NAME , fix , sht , CAND , v = src[o-off]        )    \
+       scanfunc ( NAME , fix , int , CAND , v = src[o-off]        )    \
+       scanfunc ( NAME , fix , flt , CAND , v = src[o-off]        )    \
+       scanfunc ( NAME , fix , dbl , CAND , v = src[o-off]        )    \
+       scanfunc ( NAME , fix , lng , CAND , v = src[o-off]        )    \
+       scanfunc ( NAME , var , any , CAND , v = BUNtail(bi,o-off) )
+
+/* scan select with candidates */
+scan_sel ( candscan , o = *candlist++ )
+/* scan select without candidates */
+scan_sel ( fullscan , o = p + off     )
+
 
 static BAT *
 BAT_scanselect(BAT *b, BAT *s, BAT *bn, const void *tl, const void *th,
               int li, int hi, int equi, int anti, int lval, int hval,
               BUN maximum)
 {
-       BATiter bi = bat_iterator(b);
+#ifndef NDEBUG
        int (*cmp)(const void *, const void *);
-       BUN p, q, r, cnt;
+#endif
+       BUN p, q, cnt;
        oid o, *dst;
        /* off must be signed as it can be negative,
         * e.g., if b->hseqbase == 0 and b->U->first > 0;
         * instead of wrd, we could also use ssize_t or int/lng with
         * 32/64-bit OIDs */
        wrd off;
-       const void *nil, *v;
-       int c;
+       const oid *candlist;
 
        assert(b != NULL);
        assert(bn != NULL);
@@ -237,18 +310,22 @@ BAT_scanselect(BAT *b, BAT *s, BAT *bn, 
        assert(anti == 0 || anti == 1);
        assert(!lval || tl != NULL);
        assert(!hval || th != NULL);
+       assert(!equi || (li && hi && !anti));
+       assert(!anti || lval || hval);
+       assert( anti || lval || hval || !b->T->nonil);
+       assert(b->ttype != TYPE_oid || equi || b->T->nonil);
 
+#ifndef NDEBUG
        cmp = BATatoms[b->ttype].atomCmp;
+#endif
 
        assert(!lval || !hval || (*cmp)(tl, th) <= 0);
 
-       nil = b->T->nonil ? NULL : ATOMnilptr(b->ttype);
        off = b->hseqbase - BUNfirst(b);
        dst = (oid*) Tloc(bn, BUNfirst(bn));
        cnt = 0;
 
        if (s && !BATtdense(s)) {
-               const oid *candlist;
 
                assert(s->tsorted);
                assert(s->tkey);
@@ -260,27 +337,31 @@ BAT_scanselect(BAT *b, BAT *s, BAT *bn, 
                /* should we return an error if p > BUNfirst(s) || q <
                 * BUNlast(s) (i.e. s not fully used)? */
                candlist = (const oid *) Tloc(s, p);
-               if (equi) {
-                       assert(li && hi);
-                       assert(!anti);
-                       candscanloop((*cmp)(tl, v) == 0);
-               } else if (anti) {
-                       candscanloop((nil == NULL || (*cmp)(v, nil) != 0) &&
-                                    ((lval &&
-                                      ((c = (*cmp)(tl, v)) > 0 ||
-                                       (!li && c == 0))) ||
-                                     (hval &&
-                                      ((c = (*cmp)(th, v)) < 0 ||
-                                       (!hi && c == 0)))));
-               } else {
-                       candscanloop((nil == NULL || (*cmp)(v, nil) != 0) &&
-                                    ((!lval ||
-                                      (c = cmp(tl, v)) < 0 ||
-                                      (li && c == 0)) &&
-                                     (!hval ||
-                                      (c = cmp(th, v)) > 0 ||
-                                      (hi && c == 0))));
+               /* call type-specific core scan select function */
+               switch (ATOMstorage(b->ttype)) {
+               case TYPE_bte:
+                       cnt = candscan_bte(scanargs);
+                       break;
+               case TYPE_sht:
+                       cnt = candscan_sht(scanargs);
+                       break;
+               case TYPE_int:
+                       cnt = candscan_int(scanargs);
+                       break;
+               case TYPE_flt:
+                       cnt = candscan_flt(scanargs);
+                       break;
+               case TYPE_dbl:
+                       cnt = candscan_dbl(scanargs);
+                       break;
+               case TYPE_lng:
+                       cnt = candscan_lng(scanargs);
+                       break;
+               default:
+                       cnt = candscan_any(scanargs);
                }
+               if (cnt == BUN_NONE)
+                       return NULL;
        } else {
                if (s) {
                        assert(BATtdense(s));
@@ -296,27 +377,32 @@ BAT_scanselect(BAT *b, BAT *s, BAT *bn, 
                        p = BUNfirst(b);
                        q = BUNlast(b);
                }
-               if (equi) {
-                       assert(li && hi);
-                       assert(!anti);
-                       scanloop((*cmp)(tl, v) == 0);
-               } else if (anti) {
-                       scanloop((nil == NULL || (*cmp)(v, nil) != 0) &&
-                                ((lval &&
-                                  ((c = (*cmp)(tl, v)) > 0 ||
-                                   (!li && c == 0))) ||
-                                 (hval &&
-                                  ((c = (*cmp)(th, v)) < 0 ||
-                                   (!hi && c == 0)))));
-               } else {
-                       scanloop((nil == NULL || (*cmp)(v, nil) != 0) &&
-                                ((!lval ||
-                                  (c = cmp(tl, v)) < 0 ||
-                                  (li && c == 0)) &&
-                                 (!hval ||
-                                  (c = cmp(th, v)) > 0 ||
-                                  (hi && c == 0))));
+               candlist = NULL;
+               /* call type-specific core scan select function */
+               switch (ATOMstorage(b->ttype)) {
+               case TYPE_bte:
+                       cnt = fullscan_bte(scanargs);
+                       break;
+               case TYPE_sht:
+                       cnt = fullscan_sht(scanargs);
+                       break;
+               case TYPE_int:
+                       cnt = fullscan_int(scanargs);
+                       break;
+               case TYPE_flt:
+                       cnt = fullscan_flt(scanargs);
+                       break;
+               case TYPE_dbl:
+                       cnt = fullscan_dbl(scanargs);
+                       break;
+               case TYPE_lng:
+                       cnt = fullscan_lng(scanargs);
+                       break;
+               default:
+                       cnt = fullscan_any(scanargs);
                }
_______________________________________________
checkin-list mailing list
[email protected]
http://mail.monetdb.org/mailman/listinfo/checkin-list

Reply via email to