Question

According to Wikipedia (http://en.wikipedia.org/wiki/Binary_GCD_algorithm) I was trying to write binary GCD for bignums (up to 5000 digits).

My GCD itself looks like this:

bitset<N> gcd(bitset<N> u, bitset<N> v) {
    bitset<N> one (string("1"));
    bitset<N> zero (string("0"));

    int shift;

    if (u == 0) return v;
    if (v == 0) return u;

    for (shift = 0; ((u | v) & one) == zero; ++shift) {
        u >>= 1;
        v >>= 1;
    }

    while ((u & one) == zero) u >>= 1;

    do {
        while ((v & one) == zero) v >>= 1;

        if (u.to_string() > v.to_string()) {
            bitset<N> t = v;
            v = u;
            u = t;
        }

        bitsetSubtract(v,u);
    } while (v != 0);

    return u << shift;
}

I'm also using own bitset subtraction function:

void bitsetSubtract(bitset<N> &x, const bitset<N> &y) {
    bool borrow = false;

    for (int i = 0; i < N; i++) {
        if (borrow) {
            if (x[i]) {
                x[i] = y[i];
                borrow = y[i];
            } else {
                x[i] = !y[i];
                borrow = true;
            }
        } else {
            if (x[i]) {
                x[i] = !y[i];
                borrow = false;
            } else {
                x[i] = y[i];
                borrow = y[i];
            }
        }
    }
}

I don't see any place to improve speed of this algorithm (binary GCD is fast itself), but I'm getting feedback that my program is too slow.

Was it helpful?

Solution

You've represented a bignum as an array of base-2 (binary) digits.

Real bignum libraries don't use a base of 2. They use a much larger base, because CPUs have instructions that operate on more than one bit at a time. Typically you would use a base of 256 (28), 65536 (216), 4294967296 (232), or 18446744073709551616 (264) if your goal is maximum speed and minimum size, or a base of 100 (with one byte per digit), 10000 (with two bytes per digit), 1000000000 (with four bytes per digit), or 10000000000000000000 (with eight bytes per digit) if you must store precise decimal fractions.

You need to use something like vector<uint32_t> or vector<uint64_t> as your bignum, and operate on 32 or 64 bits at a time instead of just 1 bit at a time.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top