> Any thoughts on the performance [...]
Well, you might have noticed band[] and bor[] are slow. Very slow:
band:{ 2 sv (0b vs x) & 0b vs y }
bor:{ 2 sv (0b vs x) | 0b vs y }
q)\t exec count i from t where v < 42 / simple comparison
11
q)\t exec count i from t where 37 = band'[v; 42]
12638
Three orders of magnitude slower than simple arithmetic test! But we could do better. The bottleneck here is 2 sv X, but when testing whether a flag is set or not we don't really need to compute a decimal value of and. So:
allset:{[v; mask] m ~/: (0b vs' v) &\: m:0b vs mask} / true if all flags specified by mask are set
anyset:{[v; mask] any each (0b vs' v) &\: 0b vs mask } / true if any flag is set
q)\t exec count i from t where allset[v; 42]473
A bit better, but still significantly slower than our initial arithmetic example. But the good news is that if we have not too many flags, say 8, we could pre-compute x and y for all 0 <= x, y <= 255:
xand:v!band .''v,/:\:v:til 256 / xand[x; y] ~ x AND y
Using this dictionary we can select much faster:
q)\t exec count i from t where 42=xand[v; 42]
79
q)\t exec count i from t where 0<xand[v; 42]
82
Much better!
Hope this helps.