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;
}