Ejemplo n.º 1
0
// Returns a / b.
Integer Integer::divide(Integer& a, Integer& b) const
{
    Integer q, row;
    int asign = a.sign();
    int bsign = b.sign();
    int i;
    q.set_size(a.size());
    a.set_sign(PLUS);
    b.set_sign(PLUS);

    for (i = a.size() - 1; i >= 0; i--) {
        row <<= 1;
        row[0] = a[i];
        q[i] = 0;

        while (row >= b) {
            q[i]++;
            row -= b;
        }
    }

    q.adjust();

    if (q == ZERO)
        q.set_sign(PLUS);
    else
        q.set_sign(asign * bsign);

    a.set_sign(asign);
    b.set_sign(bsign);

    return q;
}
Ejemplo n.º 2
0
//  Compare a with b, possible results are:
//  0         : a and b are equals.
//  PLUS(1)   : b > a
//  MINUS(-1) : b < a
int Integer::compare(const Integer& a, const Integer& b) const
{
    if (a.sign() == MINUS && b.sign() == PLUS) {
        return PLUS;
    }

    if (a.sign() == PLUS && b.sign() == MINUS) {
        return MINUS;
    }

    if (b.size() > a.size()) {
        return PLUS * a.sign();
    }

    if (a.size() > b.size()) {
        return MINUS * a.sign();
    }

    for (int i = a.size() - 1; i >= 0; i--) {
        if (a[i] > b[i]) {
            return MINUS * a.sign();
        }

        if (b[i] > a[i]) {
            return PLUS * a.sign();
        }
    }

    return 0;
}
Ejemplo n.º 3
0
// Return a * b. This method is known as "Long Multiplication".
// Complexity: O(n^2)
Integer Integer::multiply(Integer& a, Integer& b) const
{
    Integer ans;
    unsigned int i, j, k, n, carry_mult, carry_sum;

    for (i = 0; i < a.size(); i++) {
        carry_mult = carry_sum = 0;
        k = i; // Shifting

        for (j = 0; j < b.size(); j++) {
            n = a[i] * b[j] + carry_mult;
            carry_mult = n / BASE;

            n = ans[k] + n % BASE + carry_sum;
            carry_sum = n / BASE;

            ans[k] = n % BASE;
            k++;
        }

        if (carry_sum > 0 || carry_mult > 0) {
            ans[k++] = carry_sum + carry_mult;
        }

        ans.set_size(k);
    }

    if (ans == ZERO)
        ans.set_sign(PLUS);
    else
        ans.set_sign(a.sign() * b.sign());

    return ans;
}
Ejemplo n.º 4
0
Integer Integer::add_if_different_sign(const Integer &arg) const {
	if (abs(*this) == abs(arg))
		return 0;

	Integer res;

	// atgaa -> abs (of) this (is) greater (than) abs (of) arg: 1 or -1
	int atgaa = (abs(*this) > abs(arg)) * 2 - 1;

	do res.push_back(0);
	while (res.size() < std::max(size(), arg.size()));

	for (size_t i = 0; i < res.size(); ++i) {
		if (i < size())
			res[i] += (*this)[i] * atgaa;

		if (i < arg.size())
			res[i] += arg[i] * -atgaa;

		if (res[i] < 0) {
			res[i] += 10;
			res[i + 1]--;
		}
	}

	res.sign = (atgaa == 1 ? sign : arg.sign);

	while (!res[-1])
		res.vec->pop_back();

	return res;
}
Ejemplo n.º 5
0
// Returns n >> p => n / 10^p.
Integer Integer::right_shift(const Integer& n, long long p) const
{
    Integer ans = n;

    if (ans == ZERO) {
        return ZERO;
    }

    for (unsigned int i = 0; i + p < ans.size(); i++) {
        ans[i] = ans[i + p];
    }

    ans.set_size(ans.size() - p);
    return ans;

}
Ejemplo n.º 6
0
// Calculate a + b and store the result in c. a and b are positive.
void Integer::add(Integer& a, Integer& b, Integer& c) const
{
    int carry = 0, n, i;
    int max = std::max(a.size(), b.size());

    for (i = 0; i < max; i++) {
        n = a[i] + b[i] + carry;
        carry = n / BASE;
        c[i] = n % BASE;
    }

    if (carry > 0) {
        c[i++] = carry;
    }

    c.set_size(i);
    c.adjust();
}
Ejemplo n.º 7
0
// Returns n << p => n * 10^p.
Integer Integer::left_shift(const Integer& n, long long p) const
{
    Integer ans = n;

    if (ans == ZERO) {
        return ZERO;
    }

    for (int i = ans.size() - 1; i >= 0; i--) {
        ans[i + p] = ans[i];
    }

    for (int i = 0; i < p; i++) {
        ans[i] = 0;
    }

    ans.set_size(ans.size() + p);
    return ans;
}
Ejemplo n.º 8
0
// Returns (*this)^2.
Integer Integer::square()
{
    if (size() < MIN_KARATSUBA_SQUARE) {
        return multiply(*this, *this);
    }

    unsigned int i, half = (size() + 1) / 2;
    Integer a0, a1;
    split(*this, a0, a1, half);
    Integer square0 = a0.square();
    Integer square1 = a1.square();
    Integer ans;
    ans.set_size(size() + size());

    for (i = 0; i < 2 * half; i++) {
        ans[i] = square0[i];
    }

    for (i = 2 * half; i < ans.size(); i++) {
        ans[i] = square1[i - 2 * half];
    }

    Integer square2 = (a0 + a1).square();
    square2 -= square0;
    square2 -= square1;
    int n, carry = 0;

    for (i = half; i < ans.size(); i++) {
        n = ans[i] + square2[i - half] + carry;
        carry = n / BASE;
        ans[i] = n % BASE;
    }

    if (carry > 0) {
        ans[i++] = carry;
    }

    ans.adjust();

    return ans;
}
Ejemplo n.º 9
0
// Returns a new integer c = a + b
Integer Integer::add(Integer &a, Integer &b) const
{
    Integer c;
    int carry = 0, i;

    if (a.sign() == b.sign()) {
        c.set_sign(a.sign());
    } else {
        if (a.sign() == MINUS) {
            a.set_sign(PLUS);
            c = subtract(b, a);
            a.set_sign(MINUS);
        } else {
            b.set_sign(PLUS);
            c = subtract(a, b);
            b.set_sign(MINUS);
        }

        return c;
    }

    int max = std::max(a.size(), b.size());
    int n;

    for (i = 0; i < max; i++) {
        n = carry + a[i] + b[i];
        c[i] = n % BASE;
        carry = n / BASE;
    }

    if (carry > 0) {
        c[i++] = carry;
    }

    c.set_size(i);
    c.adjust();
    return c;
}
Ejemplo n.º 10
0
// a and b are positive integers.
Integer Integer::subtract(Integer& a, Integer& b) const
{
    Integer ans;
    int borrow = 0, n;

    // Three special cases:
    //  a - (-b) ==  a + b
    // -a - b    == -a + (-b)
    // -a - (-b) == -a + b
    if (a.sign() == MINUS || b.sign() == MINUS) {  
        b.set_sign(MINUS * b.sign());
        ans = add(a, b);
        b.set_sign(MINUS * b.sign());
        return ans;
    }

    if (a == b) {
        return ZERO;
    }

    if (a < b) {
        ans = subtract(b, a);
        ans.set_sign(MINUS);
        return ans;
    }

    unsigned int i;

    for (i = 0; i < a.size(); i++) {
        n = a[i] - b[i] - borrow;
        borrow = (n < 0) ? 1 : 0;

        if (n < 0) {
            n += BASE;
        }

        ans[i] = n;
    }

    ans.set_size(i);
    ans.adjust();
    ans.set_sign(PLUS);

    return ans;
}
Ejemplo n.º 11
0
// a and b are positive and a > b
void Integer::subtract(Integer& a, Integer& b, Integer& c) const
{
    int n, borrow = 0;
    unsigned int i;

    for (i = 0; i < a.size(); i++) {
        n = a[i] - b[i] - borrow;

        if (n < 0) {
            n += BASE;
        }

        borrow = (n < 0) ? 1 : 0;
        c[i] = n;
    }

    c.set_size(i);
    c.adjust();
    c.set_sign(PLUS);
}
Ejemplo n.º 12
0
// Return a * b. This method is known as Karatsuba algorithm.
// Complexity: O(n^(log_2 3)) ~ O(n^1.585)
// References:
// [1]  Algorithms and Data Structures: The Basic Toolbox, Kurt Hehlhorn, et al.
// [2]  en.wikipedia.org/wiki/Karatsuba_algorithm
Integer Integer::karatsuba(Integer& a, Integer& b)
{
    unsigned int alength = a.size();
    unsigned int blength = b.size();

    unsigned int half = (max(alength, blength) + 1) / 2;

    // For small numbers the long multiplication is more efficient
    if (max(alength, blength) < MIN_KARATSUBA) {
        return multiply(a, b);
    }

    Integer a0, a1, b0, b1;
    split(a, a0, a1, half);
    split(b, b0, b1, half);

    Integer p1 = karatsuba(a1, b1);
    Integer p0 = karatsuba(a0, b0);

    Integer sum1, sum2;
    add(a0, a1, sum1);
    add(b0, b1, sum2);

    Integer p2 = karatsuba(sum1, sum2);

    unsigned int i;
    int n, carry = 0;

    Integer ans;
    ans.set_size(alength + blength);

    for (i = 0; i < 2 * half; i++) {
        ans[i] = p0[i];
    }

    for (i = 2 * half; i < ans.size(); i++) {
        ans[i] = p1[i - 2 * half];
    }

    // Subtracts
    for (i = 0; i < p2.size(); i++) {
        n = p2[i] - p0[i] - carry;
        carry = (n < 0) ? 1 : 0;

        if (n < 0) {
            n += BASE;
        }

        p2[i] = n;
    }

    p2.adjust();

    for (i = 0; i < p2.size(); i++) {
        n = p2[i] - p1[i] - carry;
        carry = (n < 0) ? 1 : 0;

        if (n < 0) {
            n += BASE;
        }

        p2[i] = n;
    }

    p2.adjust();


    for (i = half; i < ans.size(); i++) {
        n = ans[i] + p2[i - half] + carry;
        carry = n / BASE;
        ans[i] = n % BASE;
    }

    ans.adjust();

    return ans;
}