libsepol: make ebitmap_cardinality() of linear complexity
As ebitmap_get_bit() complexity is linear in the size of the bitmap, the complexity of ebitmap_cardinality() is quadratic. This can be optimized by browsing the nodes of the bitmap directly in ebitmap_cardinality(). While at it, use built-in function __builtin_popcountll() to count the ones in the 64-bit value n->map for each bitmap node. This seems better suited than "count++". This seems to work on gcc and clang on x86, x86_64, ARM and ARM64 but if it causes compatibility issues with some compilers or architectures (or with older versions of gcc or clang), the use of __builtin_popcountll() can be replaced by a C implementation of a popcount algorithm. Signed-off-by: Nicolas Iooss <nicolas.iooss@m4x.org>
This commit is contained in:
parent
a41dfeb55d
commit
6968ea9775
1 changed files with 5 additions and 4 deletions
|
@ -128,14 +128,15 @@ int ebitmap_andnot(ebitmap_t *dst, ebitmap_t *e1, ebitmap_t *e2, unsigned int ma
|
|||
|
||||
unsigned int ebitmap_cardinality(ebitmap_t *e1)
|
||||
{
|
||||
unsigned int i, count = 0;
|
||||
unsigned int count = 0;
|
||||
ebitmap_node_t *n;
|
||||
|
||||
if (e1->cardinality || e1->highbit == 0)
|
||||
return e1->cardinality;
|
||||
|
||||
for (i=ebitmap_startbit(e1); i < ebitmap_length(e1); i++)
|
||||
if (ebitmap_get_bit(e1, i))
|
||||
count++;
|
||||
for (n = e1->node; n; n = n->next) {
|
||||
count += __builtin_popcountll(n->map);
|
||||
}
|
||||
e1->cardinality = count;
|
||||
return count;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue