Algorithm 查找整数中的第n个集合位

Algorithm 查找整数中的第n个集合位,algorithm,function,binary,Algorithm,Function,Binary,我想找到nth最低设置位的位置,而不仅仅是最低设置位。(我不是在谈论nth位位置上的值) 例如,假设我有: 0000 1101 1000 0100 1100 1000 1010 0000 我想找到设置的第四位。然后我希望它返回: 0000 0000 0100 0000 0000 如果popcnt(v)1; pos++; } 之后,pos将保持第n个最低值设定位的位置 我能想到的另一件事是分而治之的方法,它可能会产生O(log(n))而不是O(n)…但可能不会 编辑:你说过任何行为,所以不终止是

我想找到
n
th最低设置位的位置,而不仅仅是最低设置位。(我不是在谈论
n
th位位置上的值)

例如,假设我有:
0000 1101 1000 0100 1100 1000 1010 0000

我想找到设置的第四位。然后我希望它返回:
0000 0000 0100 0000 0000

如果
popcnt(v)
,则此函数返回
0
是有意义的,但这种情况下的任何行为对我来说都是可以接受的


如果可能的话,我正在寻找比循环更快的方法。

我看不到没有循环的方法,我会想到什么

int set = 0;
int pos = 0;
while(set < n) {
   if((bits & 0x01) == 1) set++;
   bits = bits >> 1;
   pos++;
}
int set=0;
int pos=0;
while(设置>1;
pos++;
}
之后,pos将保持第n个最低值设定位的位置

我能想到的另一件事是分而治之的方法,它可能会产生O(log(n))而不是O(n)…但可能不会


编辑:你说过任何行为,所以不终止是可以的,对吗P

v-1
有一个零,其中
v
有其最低有效“一”位,而所有更高有效位是相同的。这将导致以下功能:

int ffsn(unsigned int v, int n) {
   for (int i=0; i<n-1; i++) {
      v &= v-1; // remove the least significant bit
   }
   return v & ~(v-1); // extract the least significant bit
}
int-ffsn(无符号int-v,int-n){
对于(int i=0;i
一种递归方法(在scala中)。减量i,位置,如果模2为1。返回时,乘以2。由于乘法是作为最后一个操作进行的,它不是尾部递归的,但由于long的大小事先已知,因此最大堆栈不会太大

scala> n.toBinaryString.replaceAll ("(.{8})", "$1 ")
res117: java.lang.String = 10110011 11101110 01011110 01111110 00111101 11100101 11101011 011000

scala> bitN (n, 40) .toBinaryString.replaceAll ("(.{8})", "$1 ")
res118: java.lang.String = 10000000 00000000 00000000 00000000 00000000 00000000 00000000 000000

事实证明,在没有循环的情况下确实可以做到这一点。预计算(至少)8位版本的问题是最快的。当然,这些表会占用缓存空间,但在几乎所有现代pc场景中都应该有净加速。在这段代码中,n=0返回最小设置位,n=1是第二位,以此类推

使用popcnt的解决方案

有一种解决方案使用了uuuPopCnt内在特性(您需要uuPopCnt非常快,否则简单循环解决方案的任何性能增益都将是毫无意义的。幸运的是,大多数SSE4+era处理器都支持它)

//子问题查找表:8位v
字节预编译[256][8]={….}//v<256和n<8的预编译[v][n]
ulong nthSetBit(ulong v,ulong n){
ulong p=uu popcnt(v&0xFFFF);
ulong移位=0;
如果(p>=16;
移位+=16;
n-=p;
}
p=uu-popcnt(v&0xFF);
如果(p>=8;
n-=p;
}
如果(n>=8),则返回0;//可选安全性,如果设置位为n>#
返回预编译[v&0xFF][n]=8;
p=POPCNT[v&0xFF];
如果(p>=8;
}
}
}
如果(n>=8),则返回0;//可选安全性,如果设置位为n>#

返回预编译[v&0xFF][n]现在,使用来自的
PDEP
非常容易。下面是一个64位版本,并提供了一些示例:

#include <cassert>
#include <cstdint>
#include <x86intrin.h>

inline uint64_t nthset(uint64_t x, unsigned n) {
    return _pdep_u64(1ULL << n, x);
}

int main() {
    assert(nthset(0b0000'1101'1000'0100'1100'1000'1010'0000, 0) ==
                  0b0000'0000'0000'0000'0000'0000'0010'0000);
    assert(nthset(0b0000'1101'1000'0100'1100'1000'1010'0000, 1) ==
                  0b0000'0000'0000'0000'0000'0000'1000'0000);
    assert(nthset(0b0000'1101'1000'0100'1100'1000'1010'0000, 3) ==
                  0b0000'0000'0000'0000'0100'0000'0000'0000);
    assert(nthset(0b0000'1101'1000'0100'1100'1000'1010'0000, 9) ==
                  0b0000'1000'0000'0000'0000'0000'0000'0000);
    assert(nthset(0b0000'1101'1000'0100'1100'1000'1010'0000, 10) ==
                  0b0000'0000'0000'0000'0000'0000'0000'0000);
}
#包括
#包括
#包括
内联uint64\u t n集(uint64\u t x,无符号n){

返回_pdep_u64(1All基于Jukka Suomela给出的答案,该答案使用可能不一定可用的特定于机器的指令,也可以编写一个与
\u pdep\u u64
完全相同的函数,而不依赖任何机器。它必须循环一个参数中的设置位,但仍然可以是described作为C++11的constexpr函数

constexpr inline uint64_t deposit_bits(uint64_t x, uint64_t mask, uint64_t b, uint64_t res) {
    return mask != 0 ? deposit_bits(x, mask & (mask - 1), b << 1, ((x & b) ? (res | (mask & (-mask))) : res)) : res;
}

constexpr inline uint64_t nthset(uint64_t x, unsigned n)  {
    return deposit_bits(1ULL << n, x, 1, 0);
}
constexpr内联uint64存储位(uint64存储位x、uint64存储位掩码、uint64存储位b、uint64存储位res){

返回掩码!=0?存储位(x,掩码和(掩码-1),b基于Juha Järvi在《著名》杂志上发表的方法,我测试了此实现,其中使用了
n
I
,如问题所示:

    a = i - (i >> 1 & 0x55555555);
    b = (a & 0x33333333) + (a >> 2 & 0x33333333);
    c = b + (b >> 4) & 0x0f0f0f0f;

    r = n + 1;
    s = 0;
    t = c + (c >> 8) & 0xff;

    if (r > t) {
        s += 16;
        r -= t;
    }

    t = c >> s & 0xf;

    if (r > t) {
        s += 8;
        r -= t;
    }

    t = b >> s & 0x7;

    if (r > t) {
        s += 4;
        r -= t;
    }

    t = a >> s & 0x3;

    if (r > t) {
        s += 2;
        r -= t;
    }

    t = i >> s & 0x1;

    if (r > t)
        s++;

    return (s);
根据我自己的测试,这大约与x86上的循环速度一样快,而在arm64上则快了20%,而且由于快速条件指令,在arm上可能快得多,但我现在无法测试这一点。

Edit

经过仔细考虑并使用
\uuuu builtin\u popcount
函数后,我认为最好确定相关字节,然后计算整个结果,而不是递增地加/减数字。以下是更新版本:

int GetBitAtPosition(unsigned i, unsigned n)
{
    unsigned bitCount;

    bitCount = __builtin_popcount(i & 0x00ffffff);
    if (bitCount <= n)
    {
        return (24 + LUT_BitPosition[i >> 24][n - bitCount]);
    }

    bitCount = __builtin_popcount(i & 0x0000ffff);
    if (bitCount <= n)
    {
        return (16 + LUT_BitPosition[(i >> 16) & 0xff][n - bitCount]);
    }

    bitCount = __builtin_popcount(i & 0x000000ff);
    if (bitCount <= n)
    {
        return (8 + LUT_BitPosition[(i >> 8) & 0xff][n - bitCount]);
    }

    return LUT_BitPosition[i & 0xff][n];
}
字节内位位置的LUT:

unsigned LUT_BitPosition[][8] = {
    // 0-7
    {UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {1,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,1,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {2,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,2,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {1,2,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,1,2,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},

    // 8-15
    {3,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,3,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {1,3,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,1,3,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {2,3,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,2,3,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {1,2,3,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,1,2,3,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},

    // 16-31
    {4,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,4,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {1,4,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,1,4,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {2,4,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,2,4,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {1,2,4,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,1,2,4,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {3,4,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,3,4,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {1,3,4,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,1,3,4,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {2,3,4,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,2,3,4,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {1,2,3,4,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,1,2,3,4,UINT_MAX,UINT_MAX,UINT_MAX},

    // 32-63
    {5,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,5,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {1,5,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,1,5,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {2,5,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,2,5,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {1,2,5,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,1,2,5,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {3,5,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,3,5,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {1,3,5,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,1,3,5,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {2,3,5,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,2,3,5,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {1,2,3,5,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,1,2,3,5,UINT_MAX,UINT_MAX,UINT_MAX},
    {4,5,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,4,5,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {1,4,5,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,1,4,5,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {2,4,5,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,2,4,5,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {1,2,4,5,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,1,2,4,5,UINT_MAX,UINT_MAX,UINT_MAX},
    {3,4,5,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,3,4,5,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {1,3,4,5,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,1,3,4,5,UINT_MAX,UINT_MAX,UINT_MAX},
    {2,3,4,5,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,2,3,4,5,UINT_MAX,UINT_MAX,UINT_MAX},
    {1,2,3,4,5,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,1,2,3,4,5,UINT_MAX,UINT_MAX},

    // 64-127
    {6,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,6,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {1,6,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,1,6,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {2,6,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,2,6,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {1,2,6,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,1,2,6,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {3,6,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,3,6,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {1,3,6,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,1,3,6,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {2,3,6,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,2,3,6,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {1,2,3,6,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,1,2,3,6,UINT_MAX,UINT_MAX,UINT_MAX},
    {4,6,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,4,6,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {1,4,6,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,1,4,6,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {2,4,6,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,2,4,6,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {1,2,4,6,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,1,2,4,6,UINT_MAX,UINT_MAX,UINT_MAX},
    {3,4,6,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,3,4,6,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {1,3,4,6,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,1,3,4,6,UINT_MAX,UINT_MAX,UINT_MAX},
    {2,3,4,6,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,2,3,4,6,UINT_MAX,UINT_MAX,UINT_MAX},
    {1,2,3,4,6,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,1,2,3,4,6,UINT_MAX,UINT_MAX},
    {5,6,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,5,6,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {1,5,6,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,1,5,6,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {2,5,6,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,2,5,6,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {1,2,5,6,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,1,2,5,6,UINT_MAX,UINT_MAX,UINT_MAX},
    {3,5,6,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,3,5,6,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {1,3,5,6,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,1,3,5,6,UINT_MAX,UINT_MAX,UINT_MAX},
    {2,3,5,6,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,2,3,5,6,UINT_MAX,UINT_MAX,UINT_MAX},
    {1,2,3,5,6,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,1,2,3,5,6,UINT_MAX,UINT_MAX},
    {4,5,6,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,4,5,6,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {1,4,5,6,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,1,4,5,6,UINT_MAX,UINT_MAX,UINT_MAX},
    {2,4,5,6,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,2,4,5,6,UINT_MAX,UINT_MAX,UINT_MAX},
    {1,2,4,5,6,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,1,2,4,5,6,UINT_MAX,UINT_MAX},
    {3,4,5,6,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,3,4,5,6,UINT_MAX,UINT_MAX,UINT_MAX},
    {1,3,4,5,6,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,1,3,4,5,6,UINT_MAX,UINT_MAX},
    {2,3,4,5,6,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,2,3,4,5,6,UINT_MAX,UINT_MAX},
    {1,2,3,4,5,6,UINT_MAX,UINT_MAX},
    {0,1,2,3,4,5,6,UINT_MAX},

    // 128-255
    {7,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,7,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {1,7,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,1,7,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {2,7,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,2,7,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {1,2,7,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,1,2,7,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {3,7,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,3,7,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {1,3,7,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,1,3,7,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {2,3,7,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,2,3,7,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {1,2,3,7,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,1,2,3,7,UINT_MAX,UINT_MAX,UINT_MAX},
    {4,7,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,4,7,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {1,4,7,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,1,4,7,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {2,4,7,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,2,4,7,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {1,2,4,7,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,1,2,4,7,UINT_MAX,UINT_MAX,UINT_MAX},
    {3,4,7,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,3,4,7,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {1,3,4,7,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,1,3,4,7,UINT_MAX,UINT_MAX,UINT_MAX},
    {2,3,4,7,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,2,3,4,7,UINT_MAX,UINT_MAX,UINT_MAX},
    {1,2,3,4,7,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,1,2,3,4,7,UINT_MAX,UINT_MAX},
    {5,7,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,5,7,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {1,5,7,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,1,5,7,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {2,5,7,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,2,5,7,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {1,2,5,7,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,1,2,5,7,UINT_MAX,UINT_MAX,UINT_MAX},
    {3,5,7,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,3,5,7,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {1,3,5,7,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,1,3,5,7,UINT_MAX,UINT_MAX,UINT_MAX},
    {2,3,5,7,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,2,3,5,7,UINT_MAX,UINT_MAX,UINT_MAX},
    {1,2,3,5,7,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,1,2,3,5,7,UINT_MAX,UINT_MAX},
    {4,5,7,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,4,5,7,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {1,4,5,7,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,1,4,5,7,UINT_MAX,UINT_MAX,UINT_MAX},
    {2,4,5,7,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,2,4,5,7,UINT_MAX,UINT_MAX,UINT_MAX},
    {1,2,4,5,7,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,1,2,4,5,7,UINT_MAX,UINT_MAX},
    {3,4,5,7,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,3,4,5,7,UINT_MAX,UINT_MAX,UINT_MAX},
    {1,3,4,5,7,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,1,3,4,5,7,UINT_MAX,UINT_MAX},
    {2,3,4,5,7,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,2,3,4,5,7,UINT_MAX,UINT_MAX},
    {1,2,3,4,5,7,UINT_MAX,UINT_MAX},
    {0,1,2,3,4,5,7,UINT_MAX},
    {6,7,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,6,7,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {1,6,7,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,1,6,7,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {2,6,7,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,2,6,7,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {1,2,6,7,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,1,2,6,7,UINT_MAX,UINT_MAX,UINT_MAX},
    {3,6,7,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,3,6,7,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {1,3,6,7,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,1,3,6,7,UINT_MAX,UINT_MAX,UINT_MAX},
    {2,3,6,7,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,2,3,6,7,UINT_MAX,UINT_MAX,UINT_MAX},
    {1,2,3,6,7,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,1,2,3,6,7,UINT_MAX,UINT_MAX},
    {4,6,7,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,4,6,7,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {1,4,6,7,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,1,4,6,7,UINT_MAX,UINT_MAX,UINT_MAX},
    {2,4,6,7,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,2,4,6,7,UINT_MAX,UINT_MAX,UINT_MAX},
    {1,2,4,6,7,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,1,2,4,6,7,UINT_MAX,UINT_MAX},
    {3,4,6,7,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,3,4,6,7,UINT_MAX,UINT_MAX,UINT_MAX},
    {1,3,4,6,7,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,1,3,4,6,7,UINT_MAX,UINT_MAX},
    {2,3,4,6,7,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,2,3,4,6,7,UINT_MAX,UINT_MAX},
    {1,2,3,4,6,7,UINT_MAX,UINT_MAX},
    {0,1,2,3,4,6,7,UINT_MAX},
    {5,6,7,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,5,6,7,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {1,5,6,7,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,1,5,6,7,UINT_MAX,UINT_MAX,UINT_MAX},
    {2,5,6,7,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,2,5,6,7,UINT_MAX,UINT_MAX,UINT_MAX},
    {1,2,5,6,7,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,1,2,5,6,7,UINT_MAX,UINT_MAX},
    {3,5,6,7,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,3,5,6,7,UINT_MAX,UINT_MAX,UINT_MAX},
    {1,3,5,6,7,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,1,3,5,6,7,UINT_MAX,UINT_MAX},
    {2,3,5,6,7,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,2,3,5,6,7,UINT_MAX,UINT_MAX},
    {1,2,3,5,6,7,UINT_MAX,UINT_MAX},
    {0,1,2,3,5,6,7,UINT_MAX},
    {4,5,6,7,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,4,5,6,7,UINT_MAX,UINT_MAX,UINT_MAX},
    {1,4,5,6,7,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,1,4,5,6,7,UINT_MAX,UINT_MAX},
    {2,4,5,6,7,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,2,4,5,6,7,UINT_MAX,UINT_MAX},
    {1,2,4,5,6,7,UINT_MAX,UINT_MAX},
    {0,1,2,4,5,6,7,UINT_MAX},
    {3,4,5,6,7,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,3,4,5,6,7,UINT_MAX,UINT_MAX},
    {1,3,4,5,6,7,UINT_MAX,UINT_MAX},
    {0,1,3,4,5,6,7,UINT_MAX},
    {2,3,4,5,6,7,UINT_MAX,UINT_MAX},
    {0,2,3,4,5,6,7,UINT_MAX},
    {1,2,3,4,5,6,7,UINT_MAX},
    {0,1,2,3,4,5,6,7},
};

我的答案主要是基于64位单词选择方法(提示:仅查看MARISA_USE_POPCNT、MARISA_X64、MARISA_USE_SSE3代码路径):

它分两步工作,首先选择包含第n个设置位的字节,然后在字节内使用查找表:

  • 提取每个字节的低位和高位半字节(位掩码0xF、0xF0,将高位半字节下移)
  • 将半字节值替换为其popcount(_mm_shuffle_epi8 with)
  • 将低位和高位半字节的popcounts相加(正常SSE加法)得到字节popcounts
  • 计算所有字节数的前缀和(与0x01010101相乘…)
  • 将位置
    n
    传播到所有字节(SSE广播或再次与0x01010101相乘…)
  • 进行字节比较(\u mm\u cmpgt\u epi8在每个小于
    n
    的字节中留下0xFF)
  • 通过对结果进行popcount计算字节偏移量
现在我们知道哪个字节包含位,一个简单的字节查找表(如grek40的答案)就足以得到结果


但是请注意,我并没有将这个结果与其他实现进行真正的基准测试,只是看到它非常有效(而且没有分支)

我的方法是并行计算32位整数的每个8位四分之一的总计数,然后找出哪个四分之一包含第n位。低于找到的四分之一的总计数可以总结为以后计算的初始值

在该计数之后,逐个设置位,直到t
constexpr inline uint64_t deposit_bits(uint64_t x, uint64_t mask, uint64_t b, uint64_t res) {
    return mask != 0 ? deposit_bits(x, mask & (mask - 1), b << 1, ((x & b) ? (res | (mask & (-mask))) : res)) : res;
}

constexpr inline uint64_t nthset(uint64_t x, unsigned n)  {
    return deposit_bits(1ULL << n, x, 1, 0);
}
    a = i - (i >> 1 & 0x55555555);
    b = (a & 0x33333333) + (a >> 2 & 0x33333333);
    c = b + (b >> 4) & 0x0f0f0f0f;

    r = n + 1;
    s = 0;
    t = c + (c >> 8) & 0xff;

    if (r > t) {
        s += 16;
        r -= t;
    }

    t = c >> s & 0xf;

    if (r > t) {
        s += 8;
        r -= t;
    }

    t = b >> s & 0x7;

    if (r > t) {
        s += 4;
        r -= t;
    }

    t = a >> s & 0x3;

    if (r > t) {
        s += 2;
        r -= t;
    }

    t = i >> s & 0x1;

    if (r > t)
        s++;

    return (s);
int GetBitAtPosition(unsigned i, unsigned n)
{
    unsigned bitCount;

    bitCount = __builtin_popcount(i & 0x00ffffff);
    if (bitCount <= n)
    {
        return (24 + LUT_BitPosition[i >> 24][n - bitCount]);
    }

    bitCount = __builtin_popcount(i & 0x0000ffff);
    if (bitCount <= n)
    {
        return (16 + LUT_BitPosition[(i >> 16) & 0xff][n - bitCount]);
    }

    bitCount = __builtin_popcount(i & 0x000000ff);
    if (bitCount <= n)
    {
        return (8 + LUT_BitPosition[(i >> 8) & 0xff][n - bitCount]);
    }

    return LUT_BitPosition[i & 0xff][n];
}
unsigned i = 0x000006B5;
unsigned n = 4;
unsigned result = 0;
unsigned bitCount;
while (i)
{
    bitCount = LUT_BitCount[i & 0xff];
    if (n < bitCount)
    {
        result += LUT_BitPosition[i & 0xff][n];
        break; // found
    }
    else
    {
        n -= bitCount;
        result += 8;
        i >>= 8;
    }
}
unsigned LUT_BitCount[] = {
    0, 1, 1, 2, 1, 2, 2, 3, // 0-7

    1, 2, 2, 3, 2, 3, 3, 4, // 8-15

    1, 2, 2, 3, 2, 3, 3, 4, // 16-23
    2, 3, 3, 4, 3, 4, 4, 5, // 24-31

    1, 2, 2, 3, 2, 3, 3, 4, // 32-39
    2, 3, 3, 4, 3, 4, 4, 5, // 40-47
    2, 3, 3, 4, 3, 4, 4, 5, // 48-55
    3, 4, 4, 5, 4, 5, 5, 6, // 56-63

    1, 2, 2, 3, 2, 3, 3, 4, // 64-71
    2, 3, 3, 4, 3, 4, 4, 5, // 72-79
    2, 3, 3, 4, 3, 4, 4, 5, // 80-87
    3, 4, 4, 5, 4, 5, 5, 6, // 88-95
    2, 3, 3, 4, 3, 4, 4, 5, // 96-103
    3, 4, 4, 5, 4, 5, 5, 6, // 104-111
    3, 4, 4, 5, 4, 5, 5, 6, // 112-119
    4, 5, 5, 6, 5, 6, 6, 7, // 120-127

    1, 2, 2, 3, 2, 3, 3, 4, // 128
    2, 3, 3, 4, 3, 4, 4, 5, // 136
    2, 3, 3, 4, 3, 4, 4, 5, // 144
    3, 4, 4, 5, 4, 5, 5, 6, // 152
    2, 3, 3, 4, 3, 4, 4, 5, // 160
    3, 4, 4, 5, 4, 5, 5, 6, // 168
    3, 4, 4, 5, 4, 5, 5, 6, // 176
    4, 5, 5, 6, 5, 6, 6, 7, // 184
    2, 3, 3, 4, 3, 4, 4, 5, // 192
    3, 4, 4, 5, 4, 5, 5, 6, // 200
    3, 4, 4, 5, 4, 5, 5, 6, // 208
    4, 5, 5, 6, 5, 6, 6, 7, // 216
    3, 4, 4, 5, 4, 5, 5, 6, // 224
    4, 5, 5, 6, 5, 6, 6, 7, // 232
    4, 5, 5, 6, 5, 6, 6, 7, // 240
    5, 6, 6, 7, 6, 7, 7, 8, // 248-255
};
unsigned LUT_BitPosition[][8] = {
    // 0-7
    {UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {1,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,1,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {2,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,2,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {1,2,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,1,2,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},

    // 8-15
    {3,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,3,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {1,3,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,1,3,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {2,3,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,2,3,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {1,2,3,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,1,2,3,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},

    // 16-31
    {4,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,4,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {1,4,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,1,4,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {2,4,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,2,4,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {1,2,4,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,1,2,4,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {3,4,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,3,4,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {1,3,4,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,1,3,4,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {2,3,4,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,2,3,4,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {1,2,3,4,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,1,2,3,4,UINT_MAX,UINT_MAX,UINT_MAX},

    // 32-63
    {5,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,5,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {1,5,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,1,5,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {2,5,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,2,5,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {1,2,5,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,1,2,5,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {3,5,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,3,5,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {1,3,5,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,1,3,5,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {2,3,5,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,2,3,5,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {1,2,3,5,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,1,2,3,5,UINT_MAX,UINT_MAX,UINT_MAX},
    {4,5,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,4,5,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {1,4,5,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,1,4,5,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {2,4,5,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,2,4,5,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {1,2,4,5,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,1,2,4,5,UINT_MAX,UINT_MAX,UINT_MAX},
    {3,4,5,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,3,4,5,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {1,3,4,5,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,1,3,4,5,UINT_MAX,UINT_MAX,UINT_MAX},
    {2,3,4,5,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,2,3,4,5,UINT_MAX,UINT_MAX,UINT_MAX},
    {1,2,3,4,5,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,1,2,3,4,5,UINT_MAX,UINT_MAX},

    // 64-127
    {6,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,6,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {1,6,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,1,6,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {2,6,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,2,6,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {1,2,6,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,1,2,6,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {3,6,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,3,6,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {1,3,6,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,1,3,6,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {2,3,6,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,2,3,6,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {1,2,3,6,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,1,2,3,6,UINT_MAX,UINT_MAX,UINT_MAX},
    {4,6,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,4,6,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {1,4,6,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,1,4,6,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {2,4,6,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,2,4,6,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {1,2,4,6,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,1,2,4,6,UINT_MAX,UINT_MAX,UINT_MAX},
    {3,4,6,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,3,4,6,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {1,3,4,6,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,1,3,4,6,UINT_MAX,UINT_MAX,UINT_MAX},
    {2,3,4,6,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,2,3,4,6,UINT_MAX,UINT_MAX,UINT_MAX},
    {1,2,3,4,6,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,1,2,3,4,6,UINT_MAX,UINT_MAX},
    {5,6,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,5,6,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {1,5,6,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,1,5,6,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {2,5,6,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,2,5,6,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {1,2,5,6,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,1,2,5,6,UINT_MAX,UINT_MAX,UINT_MAX},
    {3,5,6,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,3,5,6,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {1,3,5,6,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,1,3,5,6,UINT_MAX,UINT_MAX,UINT_MAX},
    {2,3,5,6,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,2,3,5,6,UINT_MAX,UINT_MAX,UINT_MAX},
    {1,2,3,5,6,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,1,2,3,5,6,UINT_MAX,UINT_MAX},
    {4,5,6,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,4,5,6,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {1,4,5,6,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,1,4,5,6,UINT_MAX,UINT_MAX,UINT_MAX},
    {2,4,5,6,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,2,4,5,6,UINT_MAX,UINT_MAX,UINT_MAX},
    {1,2,4,5,6,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,1,2,4,5,6,UINT_MAX,UINT_MAX},
    {3,4,5,6,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,3,4,5,6,UINT_MAX,UINT_MAX,UINT_MAX},
    {1,3,4,5,6,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,1,3,4,5,6,UINT_MAX,UINT_MAX},
    {2,3,4,5,6,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,2,3,4,5,6,UINT_MAX,UINT_MAX},
    {1,2,3,4,5,6,UINT_MAX,UINT_MAX},
    {0,1,2,3,4,5,6,UINT_MAX},

    // 128-255
    {7,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,7,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {1,7,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,1,7,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {2,7,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,2,7,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {1,2,7,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,1,2,7,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {3,7,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,3,7,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {1,3,7,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,1,3,7,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {2,3,7,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,2,3,7,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {1,2,3,7,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,1,2,3,7,UINT_MAX,UINT_MAX,UINT_MAX},
    {4,7,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,4,7,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {1,4,7,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,1,4,7,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {2,4,7,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,2,4,7,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {1,2,4,7,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,1,2,4,7,UINT_MAX,UINT_MAX,UINT_MAX},
    {3,4,7,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,3,4,7,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {1,3,4,7,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,1,3,4,7,UINT_MAX,UINT_MAX,UINT_MAX},
    {2,3,4,7,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,2,3,4,7,UINT_MAX,UINT_MAX,UINT_MAX},
    {1,2,3,4,7,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,1,2,3,4,7,UINT_MAX,UINT_MAX},
    {5,7,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,5,7,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {1,5,7,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,1,5,7,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {2,5,7,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,2,5,7,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {1,2,5,7,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,1,2,5,7,UINT_MAX,UINT_MAX,UINT_MAX},
    {3,5,7,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,3,5,7,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {1,3,5,7,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,1,3,5,7,UINT_MAX,UINT_MAX,UINT_MAX},
    {2,3,5,7,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,2,3,5,7,UINT_MAX,UINT_MAX,UINT_MAX},
    {1,2,3,5,7,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,1,2,3,5,7,UINT_MAX,UINT_MAX},
    {4,5,7,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,4,5,7,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {1,4,5,7,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,1,4,5,7,UINT_MAX,UINT_MAX,UINT_MAX},
    {2,4,5,7,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,2,4,5,7,UINT_MAX,UINT_MAX,UINT_MAX},
    {1,2,4,5,7,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,1,2,4,5,7,UINT_MAX,UINT_MAX},
    {3,4,5,7,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,3,4,5,7,UINT_MAX,UINT_MAX,UINT_MAX},
    {1,3,4,5,7,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,1,3,4,5,7,UINT_MAX,UINT_MAX},
    {2,3,4,5,7,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,2,3,4,5,7,UINT_MAX,UINT_MAX},
    {1,2,3,4,5,7,UINT_MAX,UINT_MAX},
    {0,1,2,3,4,5,7,UINT_MAX},
    {6,7,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,6,7,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {1,6,7,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,1,6,7,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {2,6,7,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,2,6,7,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {1,2,6,7,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,1,2,6,7,UINT_MAX,UINT_MAX,UINT_MAX},
    {3,6,7,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,3,6,7,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {1,3,6,7,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,1,3,6,7,UINT_MAX,UINT_MAX,UINT_MAX},
    {2,3,6,7,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,2,3,6,7,UINT_MAX,UINT_MAX,UINT_MAX},
    {1,2,3,6,7,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,1,2,3,6,7,UINT_MAX,UINT_MAX},
    {4,6,7,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,4,6,7,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {1,4,6,7,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,1,4,6,7,UINT_MAX,UINT_MAX,UINT_MAX},
    {2,4,6,7,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,2,4,6,7,UINT_MAX,UINT_MAX,UINT_MAX},
    {1,2,4,6,7,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,1,2,4,6,7,UINT_MAX,UINT_MAX},
    {3,4,6,7,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,3,4,6,7,UINT_MAX,UINT_MAX,UINT_MAX},
    {1,3,4,6,7,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,1,3,4,6,7,UINT_MAX,UINT_MAX},
    {2,3,4,6,7,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,2,3,4,6,7,UINT_MAX,UINT_MAX},
    {1,2,3,4,6,7,UINT_MAX,UINT_MAX},
    {0,1,2,3,4,6,7,UINT_MAX},
    {5,6,7,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,5,6,7,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {1,5,6,7,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,1,5,6,7,UINT_MAX,UINT_MAX,UINT_MAX},
    {2,5,6,7,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,2,5,6,7,UINT_MAX,UINT_MAX,UINT_MAX},
    {1,2,5,6,7,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,1,2,5,6,7,UINT_MAX,UINT_MAX},
    {3,5,6,7,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,3,5,6,7,UINT_MAX,UINT_MAX,UINT_MAX},
    {1,3,5,6,7,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,1,3,5,6,7,UINT_MAX,UINT_MAX},
    {2,3,5,6,7,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,2,3,5,6,7,UINT_MAX,UINT_MAX},
    {1,2,3,5,6,7,UINT_MAX,UINT_MAX},
    {0,1,2,3,5,6,7,UINT_MAX},
    {4,5,6,7,UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,4,5,6,7,UINT_MAX,UINT_MAX,UINT_MAX},
    {1,4,5,6,7,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,1,4,5,6,7,UINT_MAX,UINT_MAX},
    {2,4,5,6,7,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,2,4,5,6,7,UINT_MAX,UINT_MAX},
    {1,2,4,5,6,7,UINT_MAX,UINT_MAX},
    {0,1,2,4,5,6,7,UINT_MAX},
    {3,4,5,6,7,UINT_MAX,UINT_MAX,UINT_MAX},
    {0,3,4,5,6,7,UINT_MAX,UINT_MAX},
    {1,3,4,5,6,7,UINT_MAX,UINT_MAX},
    {0,1,3,4,5,6,7,UINT_MAX},
    {2,3,4,5,6,7,UINT_MAX,UINT_MAX},
    {0,2,3,4,5,6,7,UINT_MAX},
    {1,2,3,4,5,6,7,UINT_MAX},
    {0,1,2,3,4,5,6,7},
};
#include <stdio.h>
#include <stdint.h>

int main() {
    uint32_t n = 10, test = 3124375902u; /* 10111010001110100011000101011110 */
    uint32_t index, popcnt, quarter = 0, q_popcnt;

    /* count set bits of each quarter of 32-bit integer in parallel */
    q_popcnt = test - ((test >> 1) & 0x55555555);
    q_popcnt = (q_popcnt & 0x33333333) + ((q_popcnt >> 2) & 0x33333333);
    q_popcnt = (q_popcnt + (q_popcnt >> 4)) & 0x0F0F0F0F;

    popcnt = q_popcnt;

    /* find which quarters can be summarized and summarize them */
    quarter += (n + 1 >= (q_popcnt & 0xff));
    quarter += (n + 1 >= ((q_popcnt += q_popcnt >> 8) & 0xff));
    quarter += (n + 1 >= ((q_popcnt += q_popcnt >> 16) & 0xff));
    quarter += (n + 1 >= ((q_popcnt += q_popcnt >> 24) & 0xff));

    popcnt &= (UINT32_MAX >> (8 * quarter));
    popcnt = (popcnt * 0x01010101) >> 24;

    /* find the index of nth bit in quarter where it should be */
    index = 8 * quarter;
    index += ((popcnt += (test >> index) & 1) <= n);
    index += ((popcnt += (test >> index) & 1) <= n);
    index += ((popcnt += (test >> index) & 1) <= n);
    index += ((popcnt += (test >> index) & 1) <= n);
    index += ((popcnt += (test >> index) & 1) <= n);
    index += ((popcnt += (test >> index) & 1) <= n);
    index += ((popcnt += (test >> index) & 1) <= n);
    index += ((popcnt += (test >> index) & 1) <= n);

    printf("index = %u\n", index);
    return 0;
}
#include <stdio.h>
#include <stdint.h>

int main() {
    uint32_t n = 11, test = 3124375902u; /* 10111010001110100011000101011110 */
    uint32_t popcnt = 0, index = 0;
    while(popcnt += ((test >> index) & 1), popcnt <= n && ++index < 32);

    printf("index = %u\n", index);
    return 0;
}
unsigned int nth_bit_set(uint32_t value, unsigned int n)
{
    const uint32_t  pop2  = (value & 0x55555555u) + ((value >> 1) & 0x55555555u);
    const uint32_t  pop4  = (pop2  & 0x33333333u) + ((pop2  >> 2) & 0x33333333u);
    const uint32_t  pop8  = (pop4  & 0x0f0f0f0fu) + ((pop4  >> 4) & 0x0f0f0f0fu);
    const uint32_t  pop16 = (pop8  & 0x00ff00ffu) + ((pop8  >> 8) & 0x00ff00ffu);
    const uint32_t  pop32 = (pop16 & 0x000000ffu) + ((pop16 >>16) & 0x000000ffu);
    unsigned int    rank  = 0;
    unsigned int    temp;

    if (n++ >= pop32)
        return 32;

    temp = pop16 & 0xffu;
    /* if (n > temp) { n -= temp; rank += 16; } */
    rank += ((temp - n) & 256) >> 4;
    n -= temp & ((temp - n) >> 8);

    temp = (pop8 >> rank) & 0xffu;
    /* if (n > temp) { n -= temp; rank += 8; } */
    rank += ((temp - n) & 256) >> 5;
    n -= temp & ((temp - n) >> 8);

    temp = (pop4 >> rank) & 0x0fu;
    /* if (n > temp) { n -= temp; rank += 4; } */
    rank += ((temp - n) & 256) >> 6;
    n -= temp & ((temp - n) >> 8);

    temp = (pop2 >> rank) & 0x03u;
    /* if (n > temp) { n -= temp; rank += 2; } */
    rank += ((temp - n) & 256) >> 7;
    n -= temp & ((temp - n) >> 8);

    temp = (value >> rank) & 0x01u;
    /* if (n > temp) rank += 1; */
    rank += ((temp - n) & 256) >> 8;

    return rank;
}
00400a40 <nth_bit_set>:
  400a40: 89 f9                   mov    %edi,%ecx
  400a42: 89 f8                   mov    %edi,%eax
  400a44: 55                      push   %rbp
  400a45: 40 0f b6 f6             movzbl %sil,%esi
  400a49: d1 e9                   shr    %ecx
  400a4b: 25 55 55 55 55          and    $0x55555555,%eax
  400a50: 53                      push   %rbx
  400a51: 81 e1 55 55 55 55       and    $0x55555555,%ecx
  400a57: 01 c1                   add    %eax,%ecx
  400a59: 41 89 c8                mov    %ecx,%r8d
  400a5c: 89 c8                   mov    %ecx,%eax
  400a5e: 41 c1 e8 02             shr    $0x2,%r8d
  400a62: 25 33 33 33 33          and    $0x33333333,%eax
  400a67: 41 81 e0 33 33 33 33    and    $0x33333333,%r8d
  400a6e: 41 01 c0                add    %eax,%r8d
  400a71: 45 89 c1                mov    %r8d,%r9d
  400a74: 44 89 c0                mov    %r8d,%eax
  400a77: 41 c1 e9 04             shr    $0x4,%r9d
  400a7b: 25 0f 0f 0f 0f          and    $0xf0f0f0f,%eax
  400a80: 41 81 e1 0f 0f 0f 0f    and    $0xf0f0f0f,%r9d
  400a87: 41 01 c1                add    %eax,%r9d
  400a8a: 44 89 c8                mov    %r9d,%eax
  400a8d: 44 89 ca                mov    %r9d,%edx
  400a90: c1 e8 08                shr    $0x8,%eax
  400a93: 81 e2 ff 00 ff 00       and    $0xff00ff,%edx
  400a99: 25 ff 00 ff 00          and    $0xff00ff,%eax
  400a9e: 01 d0                   add    %edx,%eax
  400aa0: 0f b6 d8                movzbl %al,%ebx
  400aa3: c1 e8 10                shr    $0x10,%eax
  400aa6: 0f b6 d0                movzbl %al,%edx
  400aa9: b8 20 00 00 00          mov    $0x20,%eax
  400aae: 01 da                   add    %ebx,%edx
  400ab0: 39 f2                   cmp    %esi,%edx
  400ab2: 77 0c                   ja     400ac0 <nth_bit_set+0x80>
  400ab4: 5b                      pop    %rbx
  400ab5: 5d                      pop    %rbp
  400ab6: c3                      retq   

  400ac0: 83 c6 01                add    $0x1,%esi
  400ac3: 89 dd                   mov    %ebx,%ebp
  400ac5: 29 f5                   sub    %esi,%ebp
  400ac7: 41 89 ea                mov    %ebp,%r10d
  400aca: c1 ed 08                shr    $0x8,%ebp
  400acd: 41 81 e2 00 01 00 00    and    $0x100,%r10d
  400ad4: 21 eb                   and    %ebp,%ebx
  400ad6: 41 c1 ea 04             shr    $0x4,%r10d
  400ada: 29 de                   sub    %ebx,%esi
  400adc: c4 42 2b f7 c9          shrx   %r10d,%r9d,%r9d
  400ae1: 41 0f b6 d9             movzbl %r9b,%ebx
  400ae5: 89 dd                   mov    %ebx,%ebp
  400ae7: 29 f5                   sub    %esi,%ebp
  400ae9: 41 89 e9                mov    %ebp,%r9d
  400aec: 41 81 e1 00 01 00 00    and    $0x100,%r9d
  400af3: 41 c1 e9 05             shr    $0x5,%r9d
  400af7: 47 8d 14 11             lea    (%r9,%r10,1),%r10d
  400afb: 41 89 e9                mov    %ebp,%r9d
  400afe: 41 c1 e9 08             shr    $0x8,%r9d
  400b02: c4 42 2b f7 c0          shrx   %r10d,%r8d,%r8d
  400b07: 41 83 e0 0f             and    $0xf,%r8d
  400b0b: 44 21 cb                and    %r9d,%ebx
  400b0e: 45 89 c3                mov    %r8d,%r11d
  400b11: 29 de                   sub    %ebx,%esi
  400b13: 5b                      pop    %rbx
  400b14: 41 29 f3                sub    %esi,%r11d
  400b17: 5d                      pop    %rbp
  400b18: 44 89 da                mov    %r11d,%edx
  400b1b: 41 c1 eb 08             shr    $0x8,%r11d
  400b1f: 81 e2 00 01 00 00       and    $0x100,%edx
  400b25: 45 21 d8                and    %r11d,%r8d
  400b28: c1 ea 06                shr    $0x6,%edx
  400b2b: 44 29 c6                sub    %r8d,%esi
  400b2e: 46 8d 0c 12             lea    (%rdx,%r10,1),%r9d
  400b32: c4 e2 33 f7 c9          shrx   %r9d,%ecx,%ecx
  400b37: 83 e1 03                and    $0x3,%ecx
  400b3a: 41 89 c8                mov    %ecx,%r8d
  400b3d: 41 29 f0                sub    %esi,%r8d
  400b40: 44 89 c0                mov    %r8d,%eax
  400b43: 41 c1 e8 08             shr    $0x8,%r8d
  400b47: 25 00 01 00 00          and    $0x100,%eax
  400b4c: 44 21 c1                and    %r8d,%ecx
  400b4f: c1 e8 07                shr    $0x7,%eax
  400b52: 29 ce                   sub    %ecx,%esi
  400b54: 42 8d 14 08             lea    (%rax,%r9,1),%edx
  400b58: c4 e2 6b f7 c7          shrx   %edx,%edi,%eax
  400b5d: 83 e0 01                and    $0x1,%eax
  400b60: 29 f0                   sub    %esi,%eax
  400b62: 25 00 01 00 00          and    $0x100,%eax
  400b67: c1 e8 08                shr    $0x8,%eax
  400b6a: 01 d0                   add    %edx,%eax
  400b6c: c3                      retq
unsigned int nth_bit_set(uint32_t value, unsigned int n)
{
    uint32_t      mask = 0x0000FFFFu;
    unsigned int  size = 16u;
    unsigned int  base = 0u;

    if (n++ >= __builtin_popcount(value))
        return 32;

    while (size > 0) {
        const unsigned int  count = __builtin_popcount(value & mask);
        if (n > count) {
            base += size;
            size >>= 1;
            mask |= mask << size;
        } else {
            size >>= 1;
            mask >>= size;
        }
    }

    return base;
}
00400ba0 <nth_bit_set>:
  400ba0: 83 c6 01                add    $0x1,%esi
  400ba3: 31 c0                   xor    %eax,%eax
  400ba5: b9 10 00 00 00          mov    $0x10,%ecx
  400baa: ba ff ff 00 00          mov    $0xffff,%edx
  400baf: 45 31 db                xor    %r11d,%r11d
  400bb2: 66 0f 1f 44 00 00       nopw   0x0(%rax,%rax,1)
  400bb8: 41 89 c9                mov    %ecx,%r9d
  400bbb: 41 89 f8                mov    %edi,%r8d
  400bbe: 41 d0 e9                shr    %r9b
  400bc1: 41 21 d0                and    %edx,%r8d
  400bc4: c4 62 31 f7 d2          shlx   %r9d,%edx,%r10d
  400bc9: f3 45 0f b8 c0          popcnt %r8d,%r8d
  400bce: 41 09 d2                or     %edx,%r10d
  400bd1: 44 38 c6                cmp    %r8b,%sil
  400bd4: 41 0f 46 cb             cmovbe %r11d,%ecx
  400bd8: c4 e2 33 f7 d2          shrx   %r9d,%edx,%edx
  400bdd: 41 0f 47 d2             cmova  %r10d,%edx
  400be1: 01 c8                   add    %ecx,%eax
  400be3: 44 89 c9                mov    %r9d,%ecx
  400be6: 45 84 c9                test   %r9b,%r9b
  400be9: 75 cd                   jne    400bb8 <nth_bit_set+0x18>
  400beb: c3                      retq   
int findNthBit(unsigned int n, int v)
{
    int next;
    if (n > __builtin_popcount(v)) return 0;
    while (next = v&v-1, --n) 
    {
        v = next;
    }
    return v ^ next;
}
#include "stdio.h"
#include "assert.h"

// function here

int main() {
    assert(findNthBit(1, 0)==0);
    assert(findNthBit(1, 0xf0f)==1<<0);
    assert(findNthBit(2, 0xf0f)==1<<1);
    assert(findNthBit(3, 0xf0f)==1<<2);
    assert(findNthBit(4, 0xf0f)==1<<3);
    assert(findNthBit(5, 0xf0f)==1<<8);
    assert(findNthBit(6, 0xf0f)==1<<9);
    assert(findNthBit(7, 0xf0f)==1<<10);
    assert(findNthBit(8, 0xf0f)==1<<11);
    assert(findNthBit(9, 0xf0f)==0);
    printf("looks good\n");
}
if (n > 8) return findNthBit(n-__builtin_popcount(v&0xff), v>>8)  << 8;
 if (n > 12) return findNthBit(n - __builtin_popcount(v&0xfff),  v>>12) << 12;
if (n > 7) return findNthBit(n - __builtin_popcount(v & ((1<<(n-1))-1)), v>>(n-1)) << (n-1);
int findNthBit(unsigned int n, int v)
{
    int next;
    if (n > __builtin_popcount(v)) return 0;
    if (n > 7) return findNthBit(n - __builtin_popcount(v & ((1<<(n-1))-1)), v>>(n-1)) << (n-1);
    while (next = v&v-1, --n) 
    {
        v = next;
    }
    return v ^ next;
}
int findNthBit(unsigned int n, int v)
{
    int shifted = 0; // running total
    int nBits;       // value for this iteration

    // handle no solution
    if (n > __builtin_popcount(v)) return 0;

    while (n > 7) 
    {
        // for large n shift out lower n-1 bits from v. 
        nBits = n-1;
        n -= __builtin_popcount(v & ((1<<nBits)-1));
        v >>= nBits;
        shifted += nBits;
    }

    int next;
    // n is now small, clear out n-1 bits and return the next bit
    // v&(v-1): a well known software trick to remove the lowest set bit.
    while (next = v&(v-1), --n) 
    {
        v = next;
    }
    return (v ^ next) << shifted;
}