There is this great post https://stackoverflow.com/a/3143594/6589735 outlining an algorithm of ranking/unranking combinations. Also, there are concrete implementations in C++, e.g. here https://people.sc.fsu.edu/~jburkardt/cpp_src/combo/combo.cpp
I am in need of a very fast implementation in C++, that does rank/unrank combinations encoded as unsigned long long
on a x64 Haswell CPU.
My attempt is in great need of improvement.
unsigned long long rank(unsigned long long comb, int card)
{
unsigned long long rank = 0;
for (int i = 1; i <= card; i++)
{
unsigned long index;
_BitScanForward64(&index, comb);
rank += binCoef[index][i]; // the binCoef table is precomputed
comb &= (comb - 1);
}
return rank;
}
unsigned long long unrank(unsigned long long rank, int card)
{
unsigned long long comb = 0;
unsigned long long m = rank;
for (int i = card - 1; i >= 0; i--)
{
int p = i;
while (binCoef[p + 1][i + 1] <= m)
p++;
m -= binCoef[p][i + 1];
comb |= (1 << p);
}
return comb;
}