c# - find set bits positions in a byte -
i tyring create sparse octree implementation people @ nvidia ("efficient sparse voxel octrees") doing voxel things when came across issue:
i have bitfield of type byte (so 8 bits only) tells me leafs of octree (1 says leaf, 0 means no leaf, 8 nodes attached --> 8 bit). want returning array of leaf positions. current implementation using while loop find out if lsb set. input shifted 1 afterwards. here's how that:
int leafposition = _leafmask & _validmask; int[] result = new int[8]; int arrayposition = 0; int iteration = 0; while ( leafposition > 0 ) { iteration++; //nodes not zero-indexed ... ? if ( (leafposition & 1) == 1 ) // lsb set? { result.setvalue( iteration, arrayposition ); arrayposition++; }; leafposition = leafposition >> 1; } return result;
this not looking elegant , has 2 things disturbing:
- this while loop mimics loop
- the result array smaller 8 values, resizing costly
i expect result [2,4,6]
42 (0010 1010)
.
can provide more elegant solution still readable?
result
i using function octree leaf count implemented earlier set array appropriate size.
if you're going after code conciseness, use this:
int[] result = new int[8]; byte leafposition = 42; int arrayposition = 0; (int iteration = 0; iteration < 8; ++iteration) if ((leafposition & (1 << iteration)) != 0) result[arrayposition++] = iteration + 1; // one-indexed
if you're going after performance, use pre-populated array (of 256 entries). can either generate statically (at compile-time) or lazily (before calling method first time).
int[][] leaves = { /* 00000000 */ new int[] { }, /* 00000001 */ new int[] { 1 }, /* 00000010 */ new int[] { 2 }, /* 00000011 */ new int[] { 1, 2 }, /* 00000100 */ new int[] { 3 }, /* 00000101 */ new int[] { 1, 3 }, /* 00000110 */ new int[] { 2, 3 }, /* 00000111 */ new int[] { 1, 2, 3 }, /* 00001000 */ new int[] { 4 }, /* 00001001 */ new int[] { 1, 4 }, /* ... */ }; byte leafposition = 42; int[] result = leaves[leafposition];
edit: if you're using lookup table , can afford one-time initialization (that amortized through many subsequent uses), suggest creating dynamically (rather bloating source code). here's sample code in linq; can use loop version instead.
int[][] leaves = new int[256][]; (int = 0; < 256; ++i) leaves[i] = enumerable.range(0, 8) .where(b => (i & (1 << b)) != 0) .select(b => b + 1) .toarray();
Comments
Post a Comment