/*
 * Internal implementation of bigints, for spigot to use when GMP is
 * not available.
 */

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stddef.h>
#include <assert.h>
#include <limits.h>

#include <vector>

#if defined _MSC_VER                   /* no stdint.h, at least in VS2010 */
typedef __int64 signed_dword;
typedef unsigned __int64 dword;
typedef unsigned __int32 word;
#define WORDSIZE 32
#else
#include <stdint.h>
typedef int64_t signed_dword;
typedef uint64_t dword;
typedef uint32_t word;
#define WORDSIZE 32
#endif

#define BIGINT_PROVIDER "internal"

class bigint {
    std::vector<word> v;
    int sign;                          // must be +1 or -1 at all times

    inline word word_at(size_t index) const {
        if (index >= v.size())
            return 0;
        return v[index];
    }

    static inline word add_words(word a, word b, word &carry) {
        dword sum = (dword)a + b + carry;
        carry = sum >> WORDSIZE;
        return sum;
    }

    inline void ensure_index_exists(size_t index) {
        if (index >= v.size())
            v.resize(index + 1, 0);
    }

    inline word add_word_at_pos(size_t index, word a, word carry = 0) {
        ensure_index_exists(index);
        v[index] = add_words(v[index], a, carry);
        return carry;
    }

    inline void normalise() {
        // Normalise by removing leading zero words.
        size_t index;
        for (index = v.size(); index > 0 && v[index-1] == 0; index--)
            /* do nothing */;
        v.resize(index);
    }

    template<class Words>
    inline void mag_add_in_place(Words mag, size_t n, size_t pos = 0) {
        word carry = 0;
        size_t index = 0;
        ensure_index_exists(n + pos + 1);
        while (index < n) {
            carry = add_word_at_pos(index + pos, mag[index], carry);
            index++;
        }
        while (carry) {
            carry = add_word_at_pos(index + pos, 0, carry);
            index++;
        }
        normalise();
    }

    template<class Words>
    inline void mag_sub_in_place(Words mag, size_t n, size_t pos = 0) {
        word carry = 1;
        size_t index = 0;
        ensure_index_exists(n+1);
        while (index < n) {
            carry = add_word_at_pos(index + pos, ~mag[index], carry);
            index++;
        }
        while (!carry && index < v.size()) {
            carry = add_word_at_pos(index + pos, ~(word)0, carry);
            index++;
        }
        if (!carry) {
            // Sign has flipped.
            sign = -sign;
            carry = 1;
            for (index = 0; index < v.size(); ++index)
                v[index] = add_words(0, ~v[index], carry);
        }

        normalise();
    }

    inline void add_in_place(const bigint &that, int that_sign) {
        if (sign == that.sign * that_sign)
            mag_add_in_place(that.v, that.v.size());
        else
            mag_sub_in_place(that.v, that.v.size());
    }

    inline void add_word_in_place(word w, int w_sign) {
        if (sign == w_sign)
            mag_add_in_place(&w, 1);
        else
            mag_sub_in_place(&w, 1);
    }

    inline void add_int_in_place(int i, int i_sign) {
        // current implementation depends on an int fitting in a word
        enum { maxcheck = 1 / (int)(INT_MAX < ~(word)0) };

        if (i < 0)
            add_word_in_place(-i, -i_sign);
        else
            add_word_in_place(+i, +i_sign);
    }

    inline void set_to_int(int i) {
        // current implementation depends on an int fitting in a word
        enum { maxcheck = 1 / (int)(INT_MAX < ~(word)0) };

        if (i == 0) {
            v.resize(0);
            sign = +1;
        } else {
            v.resize(1);
            if (i < 0) {
                v[0] = -i;
                sign = -1;
            } else {
                v[0] = +i;
                sign = +1;
            }
        }
    }

    inline void set_to_word(word w, int input_sign = +1) {
        sign = input_sign;
        if (w) {
            v.resize(1);
            v[0] = w;
        } else {
            v.resize(0);
        }
    }

    inline void set_to_unsigned(unsigned u) {
        // current implementation depends on an unsigned fitting in a word
        enum { maxcheck = 1 / (int)(UINT_MAX <= ~(word)0) };
        set_to_word(u);
    }

    inline void set_to(const bigint &b) {
        v.resize(b.v.size());
        sign = b.sign;
        for (size_t index = 0; index < b.v.size(); ++index)
            v[index] = b.v[index];
    }

    inline void multiply_word_in_place(word w, int w_sign = +1) {
        size_t i;

        if (w == 0) {
            v.resize(0);
            return;
        }

        sign *= w_sign;

        word carry = 0;
        for (i = 0; i < v.size(); ++i) {
            dword product = (dword)v[i] * w + carry;
            v[i] = product;
            carry = product >> WORDSIZE;
        }
        if (carry != 0)
            add_word_at_pos(i, carry);
    }

    inline void multiply_int_in_place(int i, int i_sign = +1) {
        if (i < 0)
            multiply_word_in_place(-i, -i_sign);
        else
            multiply_word_in_place(+i, +i_sign);
    }

    inline void multiply_overwrite_naive(const bigint &a, const bigint &b) {
        size_t maxsize, i, j;

        sign = a.sign * b.sign;

        maxsize = a.v.size() + b.v.size() + 1;
        v.resize(maxsize);
        for (i = 0; i < maxsize; i++)
            v[i] = 0;

        for (i = 0; i < a.v.size(); ++i) {
            word carry = 0;
            for (j = 0; j < b.v.size(); ++j) {
                dword product = (dword)a.v[i] * b.v[j];
                carry = ((product >> WORDSIZE) +
                         add_word_at_pos(i+j, product, carry));
            }
            carry = add_word_at_pos(i+j, carry);
            assert(carry == 0);
        }
        normalise();
    }

    inline void multiply_overwrite(const bigint &a, const bigint &b) {
        size_t asize = a.v.size(), bsize = b.v.size();
        /*
         * Deal with really easy cases.
         */
        if (asize < 2 || bsize < 2) {
            if (asize == 0 || bsize == 0) {
                v.resize(0);
                return;
            }
            if (asize == 1) {
                set_to(b);
                multiply_word_in_place(a.v[0], a.sign);
                return;
            }
            if (bsize == 1) {
                set_to(a);
                multiply_word_in_place(b.v[0], b.sign);
                return;
            }
        }
#if 0
        size_t minsize = (asize < bsize ? asize : bsize);
        if (minsize > 96) {
            /*
             * Karatsuba reduction. Currently conditioned out, because
             * my timings (of 'make test' and 'spigot -d10000 pi')
             * suggested it didn't seem to be helping, no matter what
             * I set the threshold to.
             */
            size_t maxsize = (asize > bsize ? asize : bsize);
            size_t index = maxsize / 2;
            size_t sh = index * WORDSIZE;
            bigint atop = a >> (unsigned)sh, btop = b >> (unsigned)sh;
            bigint abot = a, bbot = b;
            abot.v.resize(index);
            bbot.v.resize(index);
            bigint top = atop * btop;
            bigint bottom = abot * bbot;
            bigint middle = (atop + abot) * (btop + bbot) - top - bottom;
            set_to(bottom);
            mag_add_in_place(middle.v, middle.v.size(), index);
            mag_add_in_place(top.v, top.v.size(), index * 2);
        } else
#endif
        {
            multiply_overwrite_naive(a, b);
        }
    }

    template<class Words>
    inline int compare(Words mag, size_t bsize, int bsign) const {
        size_t asize = v.size();
        if (asize == 0 && bsize == 0)
            return 0;
        if (sign != bsign)
            return sign < bsign ? -1 : +1;
        if (asize != bsize)
            return sign * (asize < bsize ? -1 : +1);
        for (size_t index = asize; index-- > 0 ;) {
            if (v[index] != mag[index])
                return sign * (v[index] < mag[index] ? -1 : +1);
        }
        return 0;
    }

    inline int compare_bigint(const bigint &b) const {
        return compare(b.v, b.v.size(), b.sign);
    }

    inline int compare_int(int i) const {
        // current implementation depends on an int fitting in a word
        enum { maxcheck = 1 / (int)(INT_MAX < ~(word)0) };

        word w;

        if (i < 0) {
            w = -i;
            return compare(&w, 1, -1);
        } else {
            w = +i;
            return compare(&w, i > 0, +1);
        }
    }

    inline word short_divide(word d) {
        /*
         * Writes the quotient in place; returns the remainder.
         * Remainder is the absolute value; it should be given the
         * sign of the input.
         */
        assert(d != 0);
        size_t index = v.size();
        word r = 0;
        while (index >= 1) {
            dword n = ((dword)r << WORDSIZE) + word_at(index-1);
            dword q = n / d;
            r = n % d;
            v[index-1] = q;
            index--;
        }
        normalise();
        return r;
    }

    template<class Words>
    static void debug_pieces(int sign, size_t size, Words data,
                             const char *s = "") {
        printf("%s%+d %3d [", s, sign, (int)size);
        for (size_t i = 0; i < size; ++i) {
            printf("%s%08x", i>0 ? " " : "", data[size-1-i]);
        }
        printf("]\n");
    }

    void debug(const char *s = "") const {
        debug_pieces(sign, v.size(), v, s);
    }

    inline bigint long_divide(const bigint &d) {
        /*
         * Writes the remainder in place; returns the quotient.
         */
        assert(d.v.size() != 0);       /* catch div by zero */
        size_t dsize = d.v.size();
        size_t nsize = v.size();
        bigint q;
        if (nsize > dsize)
            q.v.resize(nsize - dsize + 1, 0); /* just to avoid n increments */
        q.sign = sign * d.sign;

        dword dtop = d.v[dsize - 1];
        dtop <<= WORDSIZE;
        if (dsize > 1)
            dtop |= d.v[dsize - 2];
        unsigned dshift = 0;
        for (int sh = WORDSIZE; sh != 0; sh >>= 1) {
            if (!(dtop >> (2*WORDSIZE-sh))) {
                dtop <<= sh;
                dshift += sh;
            }
        }
        dtop >>= WORDSIZE;

        if (nsize + 2 >= dsize) {      /* otherwise skip this loop entirely */
            for (size_t index = nsize - dsize + 2; index-- > 0 ;) {
                dword ntop = word_at(index + dsize);
                ntop <<= WORDSIZE;
                ntop |= word_at(index + dsize - 1);
                ntop <<= dshift;
                if (dshift > 0 && index + dsize >= 2)
                    ntop |= word_at(index + dsize - 2) >> (WORDSIZE - dshift);
                dword qword = ntop / dtop;
                if (qword > ~(word)0)
                    qword = ~(word)0; /* any apparent overflow will
                                       * not be real */
                dword carry = 1;
                dword product = 0;
                for (size_t j = 0; j < dsize+1 || product; ++j) {
                    product += qword * d.word_at(j);
                    word prodword = product;
                    product >>= WORDSIZE;
                    carry = add_word_at_pos(index + j, ~prodword, carry);
                }
                /*
                 * We might have overestimated qword by one above -
                 * perhaps even by more than one, in some fiddly cases
                 * where the digits after ntop are low and those after
                 * dtop are high. A simple while loop should suffice
                 * to correct it.
                 */
                while (!carry) {
                    carry = 0;
                    for (size_t j = 0; j < dsize+1; ++j) {
                        carry = add_word_at_pos(index + j, d.word_at(j),
                                                carry);
                    }
                    qword--;
                }
                q.add_word_at_pos(index, qword);
            }
        }

        q.normalise();
        normalise();
        return q;
    }

    /* bitpos can be as small as -(WORDSIZE-1) and this function will
     * still be expected to work. */
    inline word word_at_bit_pos(size_t bitpos) const {
        size_t index1 = (bitpos + WORDSIZE) / WORDSIZE;
        size_t sh = (bitpos + WORDSIZE) % WORDSIZE;
        word word0 = index1 > 0 ? word_at(index1 - 1) : 0;
        if (sh == 0)
            return word0;
        word word1 = word_at(index1);
        return (word0 >> sh) | (word1 << (WORDSIZE - sh));
    }

    inline void shift_right_in_place(size_t sh) {
        if (v.size() < sh/WORDSIZE) {
            v.resize(0);
        } else {
            size_t max = v.size() - sh / WORDSIZE;
            for (size_t index = 0; index < max; ++index)
                v[index] = word_at_bit_pos(sh + index * WORDSIZE);
            v.resize(max);
            normalise();
        }
    }

    inline bigint shift_left(size_t sh) const {
        bigint ret;
        ret.sign = sign;
        ret.v.resize(v.size() + (sh + WORDSIZE - 1) / WORDSIZE, 0);
        size_t start = sh / WORDSIZE;
        size_t offset = sh % WORDSIZE;
        for (size_t i = 0; i < v.size() + 1; ++i)
            ret.add_word_at_pos(i + start,
                                word_at_bit_pos(i * WORDSIZE - offset));
        ret.normalise();
        return ret;
    }

  public:
    inline bigint() : sign(+1) { }
    inline bigint(int x) : sign(+1) { set_to_int(x); }
    inline bigint(unsigned x) : sign(+1) { set_to_unsigned(x); }
    inline bigint(const bigint &x) { set_to(x); }
    inline ~bigint() { }

    inline operator int() const {
        // current implementation depends on a word fitting in an unsigned
        enum { maxcheck = 1 / (int)(UINT_MAX >= ~(word)0) };
        return (unsigned)word_at(0) * (unsigned)sign;
    }
    inline operator unsigned() const {
        // current implementation depends on a word fitting in an unsigned
        enum { maxcheck = 1 / (int)(UINT_MAX >= ~(word)0) };
        return (unsigned)word_at(0) * (unsigned)sign;
    }
    inline operator bool() const { return v.size() != 0; }
    inline bigint &operator=(const bigint &a) { set_to(a); return *this; }
    inline bigint &operator+=(const bigint &a) { add_in_place(a, +1); return *this; }
    inline bigint &operator+=(int a) { add_int_in_place(a, +1); return *this; }
    inline bigint &operator-=(const bigint &a) { add_in_place(a, -1); return *this; }
    inline bigint &operator-=(int a) { add_int_in_place(a, -1); return *this; }
    inline bigint &operator*=(const bigint &a) { bigint ret = (*this) * a; set_to(ret); return *this; }
    inline bigint &operator*=(int a) { multiply_int_in_place(a); return *this; }
    inline bigint &operator*=(unsigned a) { multiply_word_in_place(a); return *this; }
    inline bigint &operator/=(const bigint &a) { set_to(long_divide(a)); return *this; }
    inline bigint &operator/=(unsigned a) {
        // current implementation depends on a word fitting in an unsigned
        enum { maxcheck = 1 / (int)(UINT_MAX >= ~(word)0) };
        short_divide(a);
        return *this;
    }
    inline bigint &operator%=(const bigint &a) { long_divide(a); return *this; }
    inline bigint &operator%=(unsigned a) {
        // current implementation depends on a word fitting in an unsigned
        enum { maxcheck = 1 / (int)(UINT_MAX >= ~(word)0) };
        set_to_word(short_divide(a), sign);
        return *this;
    }
    inline bigint &operator<<=(unsigned a) { set_to(shift_left(a)); return *this; }
    inline bigint &operator>>=(unsigned a) { shift_right_in_place(a); return *this; }
    inline bigint &operator++() { add_word_in_place(1, +1); return *this; }
    inline bigint &operator--() { add_word_in_place(1, -1); return *this; }
  private:
    friend bigint operator+(const bigint &a, const bigint &b);
    friend bigint operator+(const bigint &a, int b);
    friend bigint operator+(int a, const bigint &b);
    friend bigint operator-(const bigint &a, const bigint &b);
    friend bigint operator-(const bigint &a, int b);
    friend bigint operator-(int a, const bigint &b);
    friend bigint operator*(const bigint &a, const bigint &b);
    friend bigint operator*(const bigint &a, int b);
    friend bigint operator*(const bigint &a, unsigned b);
    friend bigint operator*(int a, const bigint &b);
    friend bigint operator*(unsigned a, const bigint &b);
    friend bigint operator/(const bigint &a, const bigint &b);
    friend bigint operator/(const bigint &a, unsigned b);
    friend bigint fdiv(const bigint &a, const bigint &b);
    friend bigint operator%(const bigint &a, const bigint &b);
    friend bigint operator%(const bigint &a, unsigned b);
    friend bigint operator<<(const bigint &a, unsigned b);
    friend bigint operator>>(const bigint &a, unsigned b);
    friend bigint operator-(const bigint &a);
    friend bool operator==(const bigint &a, const bigint &b);
    friend bool operator!=(const bigint &a, const bigint &b);
    friend bool operator<(const bigint &a, const bigint &b);
    friend bool operator>(const bigint &a, const bigint &b);
    friend bool operator<=(const bigint &a, const bigint &b);
    friend bool operator>=(const bigint &a, const bigint &b);
    friend bool operator==(const bigint &a, int b);
    friend bool operator!=(const bigint &a, int b);
    friend bool operator<(const bigint &a, int b);
    friend bool operator>(const bigint &a, int b);
    friend bool operator<=(const bigint &a, int b);
    friend bool operator>=(const bigint &a, int b);
    friend bool operator==(int a, const bigint &b);
    friend bool operator!=(int a, const bigint &b);
    friend bool operator<(int a, const bigint &b);
    friend bool operator>(int a, const bigint &b);
    friend bool operator<=(int a, const bigint &b);
    friend bool operator>=(int a, const bigint &b);
    friend bigint bigint_abs(const bigint &a);
    friend int bigint_sign(const bigint &a);
    friend bigint bigint_sqrt(const bigint &a);
    friend char *bigint_decstring(const bigint &a);
    friend char *bigint_hexstring(const bigint &a);
    friend bigint bigint_power(const bigint &x, unsigned y);
    friend unsigned bigint_approxlog2(const bigint &a);
    friend int bigint_bit(const bigint &a, unsigned index);
};

inline bigint operator+(const bigint &a, const bigint &b) { bigint ret = a; return ret += b; }
inline bigint operator+(const bigint &a, int b) { bigint ret = a; return ret += b; }
inline bigint operator+(int a, const bigint &b) { bigint ret = b; return ret += a; }
inline bigint operator-(const bigint &a, const bigint &b) { bigint ret = a; return ret -= b; }
inline bigint operator-(const bigint &a, int b) { bigint ret = a; return ret -= b; }
inline bigint operator-(int a, const bigint &b) { bigint ret = b; ret.sign = -ret.sign; return ret += a; }
inline bigint operator*(const bigint &a, const bigint &b) { bigint ret; ret.multiply_overwrite(a, b); return ret; }
inline bigint operator*(const bigint &a, int b) { bigint ret = a; return ret *= b; }
inline bigint operator*(const bigint &a, unsigned b) { bigint ret = a; return ret *= b; }
inline bigint operator*(int a, const bigint &b) { bigint ret = b; return ret *= a; }
inline bigint operator*(unsigned a, const bigint &b) { bigint ret = b; return ret *= a; }
inline bigint operator/(const bigint &a, const bigint &b) { bigint tmp = a; return tmp.long_divide(b); }
inline bigint operator/(const bigint &a, unsigned b) { bigint ret = a; return ret /= b; }
inline bigint fdiv(const bigint &n, const bigint &d) {
    bigint q, r = n;
    q = r.long_divide(d);
    if (bigint_sign(r) * bigint_sign(d) < 0)
        --q;
    return q;
}
inline bigint operator%(const bigint &a, const bigint &b) { bigint ret = a; ret.long_divide(b); return ret; }
inline bigint operator%(const bigint &a, unsigned b) { bigint ret = a; return ret %= b; }
inline bigint operator<<(const bigint &a, unsigned b) { return a.shift_left(b); }
inline bigint operator>>(const bigint &a, unsigned b) { bigint ret = a; return ret >>= b; }
inline bigint operator-(const bigint &a) { bigint ret = a; ret.sign = -ret.sign; return ret; }
inline bool operator==(const bigint &a, const bigint &b) { return a.compare_bigint(b) == 0; }
inline bool operator!=(const bigint &a, const bigint &b) { return a.compare_bigint(b) != 0; }
inline bool operator<(const bigint &a, const bigint &b) { return a.compare_bigint(b) < 0; }
inline bool operator>(const bigint &a, const bigint &b) { return a.compare_bigint(b) > 0; }
inline bool operator<=(const bigint &a, const bigint &b) { return a.compare_bigint(b) <= 0; }
inline bool operator>=(const bigint &a, const bigint &b) { return a.compare_bigint(b) >= 0; }
inline bool operator==(const bigint &a, int b) { return a.compare_int(b) == 0; }
inline bool operator!=(const bigint &a, int b) { return a.compare_int(b) != 0; }
inline bool operator<(const bigint &a, int b) { return a.compare_int(b) < 0; }
inline bool operator>(const bigint &a, int b) { return a.compare_int(b) > 0; }
inline bool operator<=(const bigint &a, int b) { return a.compare_int(b) <= 0; }
inline bool operator>=(const bigint &a, int b) { return a.compare_int(b) >= 0; }
inline bool operator==(int a, const bigint &b) { return b.compare_int(a) == 0; }
inline bool operator!=(int a, const bigint &b) { return b.compare_int(a) != 0; }
inline bool operator<(int a, const bigint &b) { return b.compare_int(a) > 0; }
inline bool operator>(int a, const bigint &b) { return b.compare_int(a) < 0; }
inline bool operator<=(int a, const bigint &b) { return b.compare_int(a) >= 0; }
inline bool operator>=(int a, const bigint &b) { return b.compare_int(a) <= 0; }
inline bigint bigint_abs(const bigint &a) { bigint ret = a; ret.sign = +1; return ret; }

inline int bigint_sign(const bigint &a) {
    return (a.v.size() == 0) ? 0 : a.sign;
}
inline bigint bigint_sqrt(const bigint &n) {
    bigint d, a, b, di;

    d = n;
    a = 0;
    b = 0;
    b.add_word_at_pos(n.v.size(),
                      (word)1 << ((WORDSIZE-1) & ~1)); /* big power of 4 */
    do {
        a >>= 1;
        di = 2*a + b;
        if (di <= d) {
            d -= di;
            a += b;
        }
        b >>= 2;
    } while (b);

    return a;
}
inline char *bigint_decstring(const bigint &a) {
    if (a.v.size() == 0) {
        char *buf = (char *)malloc(2);
        assert(buf);
        strcpy(buf, "0");
        return buf;
    }

    bigint tmp = a;
    /* 146/485 is an overestimate of log10(2) */
    size_t maxchars = (a.v.size() * WORDSIZE * 146 + 484) / 485;
    char *buf = (char *)malloc(maxchars+2);
    assert(buf);
    int start = 0;
    if (a.sign < 0 && a.v.size() > 0) {
        buf[start++] = '-';
    }
    size_t index = maxchars+1;
    size_t length = 0;
    while (tmp.v.size() != 0) {
        assert(index > 0);
        buf[--index] = '0' + tmp.short_divide(10);
        length++;
    }
    memmove(buf + start, buf + index, length);
    buf[start + length] = '\0';
    return buf;
}
inline void bigint_print(const bigint &a) {
    char *buf = bigint_decstring(a);
    fwrite(buf, 1, strlen(buf), stdout);
    delete[] buf;
}
inline char *bigint_hexstring(const bigint &a) {
    size_t asize = a.v.size();
    if (asize == 0) {
        char *ret = (char *)malloc(2);
        assert(ret);
        strcpy(ret, "0");
        return ret;
    }
    size_t nchars = asize * WORDSIZE / 4;

    word top = a.v[asize - 1];
    for (size_t sh = WORDSIZE - 4; sh > 0; sh -= 4) {
        if (!(top >> sh))
            nchars--;
    }

    if (a.sign < 0 && a.v.size() > 0)
        nchars++;
    char *ret = (char *)malloc(nchars + 1);
    assert(ret);
    ret[nchars] = '\0';
    for (size_t digit = 0; digit < nchars; digit++) {
        word w = a.word_at(digit / (WORDSIZE / 4));
        w >>= 4 * (digit % (WORDSIZE / 4));
        ret[nchars - 1 - digit] = "0123456789abcdef"[w & 0xF];
    }
    if (a.sign < 0 && a.v.size() > 0)
        ret[0] = '-';
    return ret;
}
inline bigint bigint_power(const bigint &x, unsigned y) {
    bigint ret = 1;
    bigint curr = x;
    unsigned bit = 1;
    while (y) {
        if (y & bit) {
            ret *= curr;
            y &= ~bit;
        }
        bit <<= 1;
        curr *= curr;
    }
    return ret;
}
inline unsigned bigint_approxlog2(const bigint &a) {
    if (!a.v.size())
        return 0;
    /* The value we will return if the top bit of the topmost word is set */
    unsigned ret = a.v.size() * WORDSIZE - 1;
    /* Correct for the top bit of the topmost bit not being set */
    word w = a.v[a.v.size() - 1];
    for (unsigned sh = WORDSIZE/2; sh != 0; sh >>= 1) {
        if (!(w >> (WORDSIZE - sh))) {
            w <<= sh;
            ret -= sh;
        }
    }
    return ret;
}
inline int bigint_bit(const bigint &a, unsigned index) {
    word w = a.word_at(index / WORDSIZE);
    w >>= index % WORDSIZE;
    return w & 1;
}
