You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
AQuery/monetdb/msvc/gdk_cand.h

215 lines
6.7 KiB

/*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* Copyright 1997 - July 2008 CWI, August 2008 - 2022 MonetDB B.V.
*/
#ifndef _GDK_CAND_H_
#define _GDK_CAND_H_
/* candidates by design are ordered oid lists, besides native oid bats
* there are
* void bats for dense oid lists,
* negative oid lists
* masked oid lists
*/
#define CAND_NEGOID 0
#define CAND_MSK 1
typedef struct {
uint64_t
type:1,
// mask:1,
firstbit:48;
} ccand_t;
#define CCAND(b) ((ccand_t *) (b)->tvheap->base)
#define complex_cand(b) ((b)->ttype == TYPE_void && (b)->tvheap != NULL)
#define negoid_cand(b) (complex_cand(b) && CCAND(b)->type == CAND_NEGOID)
#define mask_cand(b) (complex_cand(b) && CCAND(b)->type == CAND_MSK)
#define ccand_first(b) ((b)->tvheap->base + sizeof(ccand_t))
#define ccand_free(b) ((b)->tvheap->free - sizeof(ccand_t))
struct canditer {
BAT *s; /* candidate BAT the iterator is based on */
union {
struct { /* for all except cand_mask */
const oid *oids; /* candidate or exceptions for non-dense */
BUN offset; /* how much of candidate list BAT we skipped */
oid add; /* value to add because of exceptions seen */
};
struct { /* only for cand_mask */
const uint32_t *mask; /* bitmask */
BUN nextmsk;
oid mskoff;
uint8_t nextbit;
uint8_t firstbit;
uint8_t lastbit;
};
};
oid seq; /* first candidate */
oid hseq; /* hseqbase from s/b for first candidate */
BUN nvals; /* number of values in .oids/.mask */
BUN ncand; /* number of candidates */
BUN next; /* next BUN to return value for */
enum {
cand_dense, /* simple dense BAT, i.e. no look ups */
cand_materialized, /* simple materialized OID list */
cand_except, /* list of exceptions in vheap */
cand_mask, /* bitmask (TYPE_msk) bat as candidate list */
} tpe;
};
/* returns the position of the lowest order bit in x, i.e. the
* smallest n such that (x & (1<<n)) != 0; must not be called with 0 */
static inline int __attribute__((__const__))
candmask_lobit(uint32_t x)
{
assert(x != 0);
#if defined(__GNUC__)
return __builtin_ctz(x) /* ffs(x) - 1 */;
#elif defined(_MSC_VER)
unsigned long idx;
if (_BitScanForward(&idx, x))
return (int) idx;
return -1;
#else
/* use binary search for the lowest set bit */
int n = 1;
if ((x & 0x0000FFFF) == 0) { n += 16; x >>= 16; }
if ((x & 0x000000FF) == 0) { n += 8; x >>= 8; }
if ((x & 0x0000000F) == 0) { n += 4; x >>= 4; }
if ((x & 0x00000003) == 0) { n += 2; x >>= 2; }
return n - (x & 1);
#endif
}
/* population count: count number of 1 bits in a value */
static inline uint32_t __attribute__((__const__))
candmask_pop(uint32_t x)
{
#if defined(__GNUC__)
return (uint32_t) __builtin_popcount(x);
#elif defined(_MSC_VER)
return (uint32_t) __popcnt((unsigned int) (x));
#else
/* divide and conquer implementation (the two versions are
* essentially equivalent, but the first version is written a
* bit smarter) */
#if 1
x -= (x >> 1) & ~0U/3 /* 0x55555555 */; /* 3-1=2; 2-1=1; 1-0=1; 0-0=0 */
x = (x & ~0U/5) + ((x >> 2) & ~0U/5) /* 0x33333333 */;
x = (x + (x >> 4)) & ~0UL/0x11 /* 0x0F0F0F0F */;
x = (x + (x >> 8)) & ~0UL/0x101 /* 0x00FF00FF */;
x = (x + (x >> 16)) & 0xFFFF /* ~0UL/0x10001 */;
#else
x = (x & 0x55555555) + ((x >> 1) & 0x55555555);
x = (x & 0x33333333) + ((x >> 2) & 0x33333333);
x = (x & 0x0F0F0F0F) + ((x >> 4) & 0x0F0F0F0F);
x = (x & 0x00FF00FF) + ((x >> 8) & 0x00FF00FF);
x = (x & 0x0000FFFF) + ((x >> 16) & 0x0000FFFF);
#endif
return x;
#endif
}
#define canditer_next_dense(ci) ((ci)->seq + (ci)->next++)
#define canditer_next_mater(ci) ((ci)->oids[(ci)->next++])
static inline oid
canditer_next_except(struct canditer *ci)
{
oid o = ci->seq + ci->add + ci->next++;
while (ci->add < ci->nvals && o == ci->oids[ci->add]) {
ci->add++;
o++;
}
return o;
}
static inline oid
canditer_next_mask(struct canditer *ci)
{
/* since .next < .ncand, we know there must be another
* candidate */
while ((ci->mask[ci->nextmsk] >> ci->nextbit) == 0) {
ci->nextmsk++;
ci->nextbit = 0;
}
ci->nextbit += candmask_lobit(ci->mask[ci->nextmsk] >> ci->nextbit);
oid o = ci->mskoff + ci->nextmsk * 32 + ci->nextbit;
if (++ci->nextbit == 32) {
ci->nextbit = 0;
ci->nextmsk++;
}
ci->next++;
return o;
}
static inline oid
canditer_next(struct canditer *ci)
{
if (ci->next == ci->ncand)
return oid_nil;
switch (ci->tpe) {
case cand_dense:
return canditer_next_dense(ci);
case cand_materialized:
assert(ci->next < ci->nvals);
return canditer_next_mater(ci);
case cand_except:
return canditer_next_except(ci);
case cand_mask:
/* work around compiler error: control reaches end of
* non-void function */
break;
}
assert(ci->tpe == cand_mask);
return canditer_next_mask(ci);
}
#define canditer_search_dense(ci, o, next) ((o) < (ci)->seq ? next ? 0 : BUN_NONE : (o) >= (ci)->seq + (ci)->ncand ? next ? (ci)->ncand : BUN_NONE : (o) - (ci)->seq)
gdk_export BUN canditer_init(struct canditer *ci, BAT *b, BAT *s);
gdk_export oid canditer_peek(struct canditer *ci);
gdk_export oid canditer_last(const struct canditer *ci);
gdk_export oid canditer_prev(struct canditer *ci);
gdk_export oid canditer_peekprev(struct canditer *ci);
gdk_export oid canditer_idx(const struct canditer *ci, BUN p);
#define canditer_idx_dense(ci, p) ((p >= (ci)->ncand)?oid_nil:((ci)->seq + p))
gdk_export void canditer_setidx(struct canditer *ci, BUN p);
gdk_export void canditer_reset(struct canditer *ci);
gdk_export BUN canditer_search(const struct canditer *ci, oid o, bool next);
static inline bool
canditer_contains(struct canditer *ci, oid o)
{
if (ci->tpe == cand_mask) {
if (o < ci->mskoff)
return false;
o -= ci->mskoff;
BUN p = o / 32;
if (p >= ci->nvals)
return false;
o %= 32;
if (p == ci->nvals - 1 && o >= ci->lastbit)
return false;
return ci->mask[p] & (1U << o);
}
return canditer_search(ci, o, false) != BUN_NONE;
}
gdk_export oid canditer_mask_next(const struct canditer *ci, oid o, bool next);
gdk_export BAT *canditer_slice(const struct canditer *ci, BUN lo, BUN hi);
gdk_export BAT *canditer_sliceval(const struct canditer *ci, oid lo, oid hi);
gdk_export BAT *canditer_slice2(const struct canditer *ci, BUN lo1, BUN hi1, BUN lo2, BUN hi2);
gdk_export BAT *canditer_slice2val(const struct canditer *ci, oid lo1, oid hi1, oid lo2, oid hi2);
gdk_export BAT *BATnegcands(BUN nr, BAT *odels);
gdk_export BAT *BATmaskedcands(oid hseq, BUN nr, BAT *masked, bool selected);
gdk_export BAT *BATunmask(BAT *b);
gdk_export BAT *BATmergecand(BAT *a, BAT *b);
gdk_export BAT *BATintersectcand(BAT *a, BAT *b);
gdk_export BAT *BATdiffcand(BAT *a, BAT *b);
#endif /* _GDK_CAND_H_ */