Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>Let me try - how about:</p> <pre><code>class bitIterator{ unsigned char* farray; int foffset; public: bitIterator(unsigned char* array, int offset) :farray(array), foffset(offset) {} bool operator*() const { return (farray[foffset/8] &gt;&gt; (7 - foffset%8)) &amp; 1; } bitIterator&amp; operator++(){ foffset++; return *this; } int offset() const { return foffset; } }; // Just to demonstrate how to call it int find_first_n(unsigned char* buffer, int length, int n){ return std::search_n(bitIterator(buffer, 0), bitIterator(buffer, length*8), n, 0).offset(); } </code></pre> <p>That was just for fun...</p> <p>Now if you really want to squeeze some performance out of it, I will suggset</p> <pre><code>int find_first_n(unsigned char* buffer, int length, int n){ int prev_trail = 0; unsigned int* buf = reinterpret_cast&lt;unsigned int*&gt;(buffer); int len = length/sizeof(int); // Last few bytes will need special treatment if your array is not multple of int-size length. // However last bytes should not influence overall performance of code - assuming it is used on rather long arrays. // If you plan using rather short arrays (20-50 bytes?) you will probably be better off just using plain char. for (int i=0; i&lt;len; i++){ if (!buf[i]) return i*sizeof(int)*8-prev_trail; // __builtin_clz and __builtin_ctz are undefined on zero ; // EDIT: if (!~buf[i]){ prev_trail = 0; continue; } // END EDIT! int shft = __builtin_clz(buf[i]); if (shft + prev_trail &gt;= n) return i*sizeof(int)*8-prev_trail; // Leading + previous trailing &lt;= n // Not enough leading zeros, continue search. prev_trail = __builtin_ctz(buf[i]); // Store it to use for next int in array unsigned int tmp =0; while(shft &lt; sizeof(int)*8-prev_trail){ // While we haven't got to trailing zeros in this uint tmp = buf[i] &lt;&lt; shft; // Shift-out leading zeros; shft += (__builtin_clz(~tmp)); tmp = buf[i] &lt;&lt; shft; // Shift-out leading ones; lead_zeros = __builtin_clz(tmp); if (lead_zeros &gt;= n) // and see if have enough leading zeros. return i*sizeof(int)*8+shft; shft += lead_zeros; } return length*8; // Not found :( } </code></pre> <p>This is rather difficult to read, but concept is simple - just iterate over every int-sized block, and for each see if leading zeros + trailing zeros from previous one are >= n. If not just repeatedly shift-out leading zeros and following ones (set bits), and check again for trailing zeroes >= n, as long as we didn't got to trailing bytes.</p> <p>And just one more idea:</p> <pre><code>int find_first_n(unsigned char* buffer, int length, int n){ union { unsigned char chr[2]; unsigned int uit; }; unsigned int onemask = 0x8000; for (int i = 1 ; i&lt;n; i++) onemask = onemask | (onemask &gt;&gt; 1); int* masks = new int[8]; for (int i = 0; i&lt;8; i++){ masks[i]=onemask &gt;&gt; i; } // generating masks - eg. for n == 3 would be: // [ 1110 0000 0000 0000 ] // [ 0111 0000 0000 0000 ] // [ 0011 1000 0000 0000 ] // [ 0001 1100 0000 0000 ] // [ ... ] // [ 0000 0001 1100 0000 ] uit = 0; for (int i=0; i&lt;length-1; i++){ chr[0] = buffer[i]; chr[1] = buffer[i+1]; for (int j=0; j&lt;8; j++){ if (!(uit &amp; masks[j])) return i*8+j; } } chr[0] = buffer[length-1]; chr[1] = 0xff; // Fill with ones at the end. for (int j=0; j&lt;8; j++){ if (!(uit &amp; masks[j])) return (length-1)*8+j; } return length*8; // Not found :( } </code></pre> <p>You might be tempted to cast pointer to variables still in buffer directly to word (<code>reinterpret_cast&lt;unsigned short int*&gt;(buffer[i])</code>) and apply masks without using union. Note however that half of such operations would use unaligned variables, which can degrade performance, and on some platforms even generate exceptions.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload