fix & make faster binsearch infilter case

This commit is contained in:
cathugger 2017-10-11 20:36:43 +00:00
parent f862c7897e
commit ecd7e37967

171
main.c
View file

@ -117,15 +117,6 @@ static inline int ifilter_conflict(struct intfilter *o,struct intfilter *n)
return -1; return -1;
return 1; return 1;
} }
#else // BINSEARCH
static inline int ifilter_conflict(struct intfilter *o,struct intfilter *n,IFT mask)
{
if ((o->f & mask) != (n->f & ifiltermask))
return 0;
if (ifiltermask <= mask)
return -1;
return 1;
}
#endif // BINSEARCH #endif // BINSEARCH
#else // INTFILTER #else // INTFILTER
// o - old filter, n - new // o - old filter, n - new
@ -209,18 +200,75 @@ static inline int bfilter_conflict(struct binfilter *o,struct binfilter *n)
* 0x0000800f ^ 0x00008000 -> 0x0000000f <- dmask * 0x0000800f ^ 0x00008000 -> 0x0000000f <- dmask
*/ */
static const int littleendian = 1;
static int ifilter_compare(const void *p1,const void *p2)
{
if (((const struct intfilter *)p1)->f < ((const struct intfilter *)p2)->f) return -1;
if (((const struct intfilter *)p1)->f > ((const struct intfilter *)p2)->f) return 1;
return 0;
}
static void ifilter_sort()
{
qsort(&VEC_BUF(ifilters,0),VEC_LENGTH(ifilters),sizeof(struct intfilter),ifilter_compare);
}
// if res1==res2 then no results found but res1 tells where it should be inserted
static void ifilter_find(IFT fltr,size_t start,size_t end,size_t *res1,size_t *res2)
{
size_t it;
for (size_t down = start, up = end;it = (up + down) / 2, down < up;) {
if (fltr < VEC_BUF(ifilters,it).f)
up = it;
else if (fltr > VEC_BUF(ifilters,it).f)
down = it + 1;
else
break;
}
*res1 = it;
while (*res1 > start && VEC_BUF(ifilters,*res1 - 1).f == fltr)
--*res1;
*res2 = it;
while (*res2 < end && VEC_BUF(ifilters,*res2).f == fltr)
++*res2;
}
#define EXPVAL(init,j,dmask,smask,ishift,rshift) \
((init) | ((((j) & (dmask)) | (((j) << (rshift)) & (smask))) << (ishift)))
// add expanded set of values // add expanded set of values
// space for that must already be allocated // allocates space on its own
static void ifilter_addexpanded( static void ifilter_addexpanded(
size_t n,struct intfilter *ifltr, struct intfilter *ifltr,
IFT dmask,IFT smask,IFT cmask, IFT dmask,IFT smask,IFT cmask,
int ishift,int rshift) int ishift,int rshift)
{ {
for (size_t j = 0;;++j) { if (*(const u8 *)&littleendian) {
VEC_BUF(ifilters,n + j).f = for (size_t j = 0,r1,r2 = 0;;++j,++r2) {
ifltr->f | (((j & dmask) | ((j << rshift) & smask)) << ishift); IFT cval = EXPVAL(ifltr->f,j,dmask,smask,ishift,rshift);
if (j == cmask) ifilter_find(cval,r2,VEC_LENGTH(ifilters),&r1,&r2);
break; if (r1 != r2) {
continue;
// already exists
}
VEC_INSERT1(ifilters,r1);
VEC_BUF(ifilters,r1).f = cval;
if (j == cmask)
break;
}
}
else {
size_t r1,r2,r3,r4;
ifilter_find(ifltr->f,0,VEC_LENGTH(ifilters),&r1,&r2);
ifilter_find(EXPVAL(ifltr->f,cmask,dmask,smask,ishift,rshift),r2,VEC_LENGTH(ifilters),&r3,&r4);
if (r4 - r1 >= cmask + 1)
return; // already have all of needed stuff
VEC_INSERTN(ifilters,r4,cmask + 1 - (r4 - r1));
for (size_t j = 0;;++j) {
VEC_BUF(ifilters,r1 + j).f = EXPVAL(ifltr->f,j,dmask,smask,ishift,rshift);
if (j == cmask)
break;
}
} }
} }
@ -233,9 +281,7 @@ static void ifilter_expand(IFT dmask,IFT smask,IFT cmask,int ishift,int rshift)
size_t esz = cmask + 1; // size of expanded elements size_t esz = cmask + 1; // size of expanded elements
for (size_t i = len - 1;;--i) { for (size_t i = len - 1;;--i) {
for (IFT j = 0;;++j) { for (IFT j = 0;;++j) {
VEC_BUF(ifilters,i * esz + j).f = VEC_BUF(ifilters,i * esz + j).f = EXPVAL(VEC_BUF(ifilters,i).f,j,dmask,smask,ishift,rshift);
VEC_BUF(ifilters,i).f |
(((j & dmask) | ((j << rshift) & smask)) << ishift);
if (j == cmask) if (j == cmask)
break; break;
} }
@ -254,13 +300,13 @@ static inline void ifilter_addflatten(struct intfilter *ifltr,IFT mask)
} }
if (ifiltermask == mask) { if (ifiltermask == mask) {
// lucky, only need to insert at the right place // lucky, only need to insert at the right place
VEC_FOR(ifilters,i) { size_t r1,r2;
if (VEC_BUF(ifilters,i).f > ifltr->f) { ifilter_find(ifltr->f,0,VEC_LENGTH(ifilters),&r1,&r2);
VEC_INSERT(ifilters,i,*ifltr); if (r1 != r2) {
return; // duplicate
} return;
} }
VEC_ADD(ifilters,*ifltr); VEC_INSERT(ifilters,r1,*ifltr);
return; return;
} }
IFT cross = ifiltermask ^ mask; IFT cross = ifiltermask ^ mask;
@ -279,34 +325,46 @@ static inline void ifilter_addflatten(struct intfilter *ifltr,IFT mask)
if (ifiltermask > mask) { if (ifiltermask > mask) {
// already existing stuff has more precise mask than we // already existing stuff has more precise mask than we
// so we need to expand our stuff // so we need to expand our stuff
// first find where we should insert ifilter_addexpanded(ifltr,dmask,smask,cmask,ishift,rshift);
VEC_FOR(ifilters,i) {
if (VEC_BUF(ifilters,i).f > ifltr->f) {
// there
VEC_INSERTN(ifilters,i,cmask + 1);
ifilter_addexpanded(i,ifltr,dmask,smask,cmask,ishift,rshift);
return;
}
}
size_t i = VEC_LENGTH(ifilters);
VEC_ADDN(ifilters,cmask + 1);
ifilter_addexpanded(i,ifltr,dmask,smask,cmask,ishift,rshift);
} }
else { else {
size_t r1,r2;
// check if not already exists
ifilter_find(ifltr->f & ifiltermask,0,VEC_LENGTH(ifilters),&r1,&r2);
if (r1 != r2) {
// this filter alreaedy exists in wider form
return;
}
// adjust existing mask // adjust existing mask
ifiltermask = mask; ifiltermask = mask;
// already existing stuff needs to be expanded // already existing stuff needs to be expanded
ifilter_expand(dmask,smask,cmask,ishift,rshift); ifilter_expand(dmask,smask,cmask,ishift,rshift);
// now just insert our stuff in the right place if (*(const u8 *)&littleendian) {
VEC_FOR(ifilters,i) { VEC_ADD(ifilters,*ifltr);
if (VEC_BUF(ifilters,i).f > ifltr->f) { ifilter_sort();
VEC_INSERT(ifilters,i,*ifltr); }
return; else {
} // we already know place to insert
// well except this time it gon b expanded a bit
VEC_INSERT(ifilters,r1 * (cmask + 1),*ifltr);
} }
VEC_ADD(ifilters,*ifltr);
} }
} }
#if 0
static int ifilter_check()
{
for (size_t i = 1;i < VEC_LENGTH(ifilters);++i) {
if (VEC_BUF(ifilters,i - 1).f == VEC_BUF(ifilters,i).f) {
return 1;
}
if (VEC_BUF(ifilters,i - 1).f > VEC_BUF(ifilters,i).f) {
return 2;
}
}
return 0;
}
#endif // 0
#endif // BINSEARCH #endif // BINSEARCH
#endif // INTFILTER #endif // INTFILTER
@ -359,13 +417,22 @@ static void filters_add(const char *filter)
.m = mc.i, .m = mc.i,
#endif #endif
}; };
#ifdef BINSEARCH
ifilter_addflatten(&ifltr,mc.i);
#if 0
int ifiltererr = ifilter_check();
if (ifiltererr != 0) {
if (ifiltererr == 1)
fprintf(stderr,"bug: duplicate filter found!\n");
else if (ifiltererr == 2)
fprintf(stderr,"bug: ifilters aint sorted!\n");
abort();
}
#endif // 0
#else // BINSEARCH
VEC_FOR(ifilters,i) { VEC_FOR(ifilters,i) {
int c; int c;
#ifndef BINSEARCH
c = ifilter_conflict(&VEC_BUF(ifilters,i),&ifltr); c = ifilter_conflict(&VEC_BUF(ifilters,i),&ifltr);
#else
c = ifilter_conflict(&VEC_BUF(ifilters,i),&ifltr,mc.i);
#endif
if (c < 0) if (c < 0)
return; // old filter eats us return; // old filter eats us
else if (c > 0) { else if (c > 0) {
@ -374,9 +441,6 @@ static void filters_add(const char *filter)
// we eat old filter // we eat old filter
} }
} }
#ifdef BINSEARCH
ifilter_addflatten(&ifltr,mc.i);
#else
VEC_FOR(ifilters,i) { VEC_FOR(ifilters,i) {
// filter with least bits first // filter with least bits first
if (VEC_BUF(ifilters,i).m > ifltr.m) { if (VEC_BUF(ifilters,i).m > ifltr.m) {
@ -463,11 +527,12 @@ static size_t filters_count()
#else // BINSEARCH #else // BINSEARCH
#define DOFILTER(it,pk,code) { \ #define DOFILTER(it,pk,code) { \
register IFT maskedpk = *(IFT *)(pk) & ifiltermask; \
for (size_t down = 0,up = VEC_LENGTH(ifilters);down < up;) { \ for (size_t down = 0,up = VEC_LENGTH(ifilters);down < up;) { \
it = (up + down) / 2; \ it = (up + down) / 2; \
if ((*(IFT *)(pk) & ifiltermask) < VEC_BUF(ifilters,it).f) \ if (maskedpk < VEC_BUF(ifilters,it).f) \
up = it; \ up = it; \
else if ((*(IFT *)(pk) & ifiltermask) > VEC_BUF(ifilters,it).f) \ else if (maskedpk > VEC_BUF(ifilters,it).f) \
down = it + 1; \ down = it + 1; \
else { \ else { \
code; \ code; \