-4

I came across this piece of code to compute least common factor of all numbers in an array but could not understand the algorithm used. What is the use of __builtin_popcount here which is used to count the number of set bits?

pair<long long, int> pre[200000];
long long a[25], N;

long long trunc_mul(long long a, long long b)
{
    return a <= INF / b ? a * b : INF;
}
void compute()
{
    int limit = 1 << N;
    limit--;
    for (int i = 1; i <= limit; i++)
    {
        long long lcm = 1;
        pre[i].second = __builtin_popcount(i);
        int k = 1;
        for (int j = N - 1; j >= 0; j--)
        {
            if (k&i)
            {
                lcm = trunc_mul(lcm / __gcd(lcm, a[j]), a[j]);

            }
            k = k << 1;
        }
        pre[i].first = lcm;
    }
    return;
}
Anton Savin
  • 40,838
  • 8
  • 54
  • 90
kolaveri
  • 59
  • 1
  • 2
  • 15
  • Using a `#define` in the middle of all this seems totally uncalled for. That's what `const` is for. As for the rest, what's your problem here? That function isn't shown. – tadman Mar 31 '16 at 22:00
  • You haven't shown us any code that uses the value stashed in `second`. So how could we know what it was stashed there? All of the code shown would behave exactly the same if `pre[i].second = __builtin_popcount(i);` were commented out. – David Schwartz Mar 31 '16 at 22:06

1 Answers1

0

The code snipped you provided is given up to 25 numbers. For each subset of numbers it computes their LCM into pre[i].first and number of them in that subset into pre[i].second. The subset itself is represented as a bitmask, therefore to compute number of elements in the subset the snippet uses __builtin_popcount. It has nothing to do with the computation of the LCM.

LCM is computed using a rather standard approach: LCM of any set of numbers is equal to their product divided by their GCD. This is exactly what this snipped does, using builtin GCD function __gcd.

The k&i and k = k<<1 part is to figure out what numbers belong to a set represented by a bitmask. If you don't fully understand it, try to see what happens if i = 0b11010, by running this loop on a piece of paper or in the debugger. You will notice that k&i condition will be true on the second, fourth and fifth iteration, precisely the positions at which i has ones in its binary representation.

Ishamael
  • 12,583
  • 4
  • 34
  • 52