Распаралелить длинную арифметику C++

Недавно сделал свою реализацию длинной целой арифметики. Реализовал функции сравнения, сложения, вычитания, умножения, деления нацело, получения остатка от деления, возведения в степень, подсчета факториала, подсчета НОД, подсчета НОК, получения модуля числа, а также проверки на четность. Все бы хорошо, но вычисления происходят только в одном потоке, а это довольно обидно, ведь современные среднестатистические процессоры имеют от восьми до шестнадцати потоков. Я изучил некоторые материалы в сети и попробовал распаралелить умножение вставив следующее перед главным циклом в своей функции умножения:

omp_set_num_threads(8);
#pragma omp parallel for

Единственное, что дала эта поправка - скорость исполнения кода увеличилась в 6-8 раз и мой процессор стал хрипеть как дикий кашалот. Хотелось бы получить некоторое понятное объяснение и в идеале, пример распараллеливания хотя бы одной из функций. Вот код файла с исходным кодом класса:

#include <iostream>
#include <vector>
#include <cmath>


class inf {
public:
    static std::string to_string(const inf& number);
    inf();
    inf(std::string string);
    inf(signed int number);
    inf(unsigned int number);
    inf(signed long number);
    inf(unsigned long number);
    inf(signed long long number);
    inf(unsigned long long number);
    static inf pow(inf number_thirst, inf number_second);
    static inf factorial(const inf& number);
    static inf gcd(inf number_thirst, inf number_second);
    static inf lcm(inf number_thirst, inf number_second);
    static inf abs(inf number_thirst);
    static bool even(const inf& number);
    friend std::ostream& operator <<(std::ostream& ostream, const inf& number);
    friend bool operator >(const inf& number_thirst, const inf& number_second);
    friend bool operator >=(const inf& number_thirst, const inf& number_second);
    friend bool operator <(const inf& number_thirst, const inf& number_second);
    friend bool operator <=(const inf& number_thirst, const inf& number_second);
    friend bool operator ==(const inf& number_thirst, const inf& number_second);
    friend bool operator !=(const inf& number_thirst, const inf& number_second);
    friend inf operator +(const inf& number_thirst, const inf& number_second);
    friend inf operator -(const inf& number_thirst, const inf& number_second);
    friend inf operator *(const inf& number_thirst, const inf& number_second);
    friend inf operator /(const inf& number_thirst, const inf& number_second);
    friend inf operator %(const inf& number_thirst, const inf& number_second);
    inf operator +=(const inf& number);
    inf operator -=(const inf& number);
    inf operator *=(const inf& number);
    inf operator /=(const inf& number);
    inf operator %=(const inf& number);
    inf operator ++();
    inf operator --();
    inf operator ++(int);
    inf operator --(int);
private:
    std::vector<int> digits;
    bool natural;
    static const int base = 1000000000;
    static const int base_length = 9;
    static std::vector<int> string_convert_to_vector(const std::string& string);
    static inf zeroes_leading_remove(inf number);
    static inf shift_right(inf number, int shift_power);
    static char compare(inf number_thirst, inf number_second);
    static inf subtraction_natural(inf number_thirst, inf number_second);
    static inf sum(inf number_thirst, inf number_second);
    static inf subtraction(inf number_thirst, inf number_second);
    static inf multiply(inf number_thirst, inf number_second);
    static inf division_whole(inf number_thirst, inf number_second);
    static inf division_remainder(inf number_thirst, inf number_second);
    static inf factorial_tree(inf number_thirst, const inf& number_second);
};
std::vector<int> inf::string_convert_to_vector(const std::string &string) {
    std::vector<int> result;
    if (string.size() % base_length == 0) {
        result.resize(string.size() / base_length);
    }
    else {
        result.resize(string.size() / base_length + 1);
    }
    for (int string_position = string.size() - 1, result_position = result.size() - 1; string_position >= 0; string_position = string_position - base_length, result_position = result_position - 1) {
        if ((string_position + 1) - base_length <= 0) {
            result[result_position] = std::stoi(string.substr(0, (string_position + 1)));
        }
        else {
            result[result_position] = std::stoi(string.substr((string_position + 1) - base_length, base_length));
        }
    }
    return result;
}
std::string inf::to_string(const inf& number) {
    std::string result;
    if (number.natural == false) {
        result.append("-");
    }
    result.reserve(number.digits.size() * (base_length - 1));
    std::string tmp;
    result.append(std::to_string(number.digits[0]));
    for (int i = 1; i < number.digits.size(); i = i + 1) {
        tmp = std::to_string(number.digits[i]);
        tmp.reserve(base_length - tmp.size());
        while (tmp.size() < base_length) {
            tmp.insert(tmp.begin() + 0, '0');
        }
        result.append(tmp);
    }
    return result;
}
inf inf::zeroes_leading_remove(inf number) {
    while (number.digits.size() != 1 and number.digits[0] == 0) {
        number.digits.erase(number.digits.begin() + 0);
    }
    return number;
}
inf inf::shift_right(inf number, int shift_power) {
    number.digits.reserve(shift_power);
    for (int i = 0; i < shift_power; i = i + 1) {
        number.digits.insert(number.digits.begin() + 0, 0);
    }
    return number;
}
inf::inf() {
    digits.resize(1);
    digits[0] = 0;
    natural = true;
}
inf::inf(std::string string) {
    if (string.size() == 0 or (string.size() == 1 and string[0] == '-')) {
        throw "Fatal error. Type creation is impossible. String does not contain number.";
    }
    if (string[0] == '-') {
        string.erase(string.begin() + 0);
        natural = false;
    }
    else {
        natural = true;
    }
    for (int i = 0; i < string.size(); i = i + 1) {
        if (string[i] < 48 or string[i] > 57) {
            throw "Fatal error. Type creation is impossible. String contain unknown characters.";
        }
    }
    while (string.size() != 1 and string[0] == '0') {
        string.erase(string.begin() + 0);
    }
    digits = inf::string_convert_to_vector(string);
}
inf::inf(signed int number) {
    if (number < 0) {
        number = number * -1;
        natural = false;
    }
    else {
        natural = true;
    }
    digits = inf::string_convert_to_vector(std::to_string(number));
}
inf::inf(unsigned int number) {
    natural = true;
    digits = inf::string_convert_to_vector(std::to_string(number));
}
inf::inf(signed long number) {
    if (number < 0) {
        number = number * -1;
        natural = false;
    }
    else {
        natural = true;
    }
    digits = inf::string_convert_to_vector(std::to_string(number));
}
inf::inf(unsigned long number) {
    natural = true;
    digits = inf::string_convert_to_vector(std::to_string(number));
}
inf::inf(signed long long number) {
    if (number < 0) {
        number = number * -1;
        natural = false;
    }
    else {
        natural = true;
    }
    digits = inf::string_convert_to_vector(std::to_string(number));
}
inf::inf(unsigned long long number) {
    natural = true;
    digits = inf::string_convert_to_vector(std::to_string(number));
}
char inf::compare(inf number_thirst, inf number_second) {
    if (number_thirst.natural == true and number_second.natural == false) {
        return '>';
    }
    if (number_thirst.natural == false and number_second.natural == true) {
        return '<';
    }
    if (number_thirst.natural == false and number_second.natural == false) {
        number_thirst.natural = true;
        number_second.natural = true;
        char tmp = inf::compare(number_thirst, number_thirst);
        if (tmp == '>') {
            return '<';
        }
        if (tmp == '<') {
            return '>';
        }
        return '=';
    }
    if (number_thirst.digits.size() > number_second.digits.size()) {
        return '>';
    }
    if (number_thirst.digits.size() < number_second.digits.size()) {
        return '<';
    }
    for (int numbers_position = 0; numbers_position < number_thirst.digits.size(); numbers_position = numbers_position + 1) {
        if (number_thirst.digits[numbers_position] > number_second.digits[numbers_position]) {
            return '>';
        }
        if (number_thirst.digits[numbers_position] < number_second.digits[numbers_position]) {
            return '<';
        }
    }
    return '=';
}
inf inf::subtraction_natural(inf number_thirst, inf number_second) {
    number_thirst.natural = true;
    number_second.natural = true;
    if (inf::compare(number_thirst, number_second) == '<') {
        inf tmp = number_thirst;
        number_thirst = number_second;
        number_second = tmp;
        number_thirst.natural = false;
    }
    number_second = inf::shift_right(number_second, number_thirst.digits.size() - number_second.digits.size());
    int different;
    for (int numbers_position1 = number_thirst.digits.size() - 1; numbers_position1 >= 0; numbers_position1 = numbers_position1 - 1) {
        different = number_thirst.digits[numbers_position1] - number_second.digits[numbers_position1];
        if (different >= 0) {
            number_thirst.digits[numbers_position1] = different;
        }
        else {
            number_thirst.digits[numbers_position1] = different + base;
            for (int numbers_position2 = numbers_position1 - 1; true; numbers_position2 = numbers_position2 - 1) {
                if (number_thirst.digits[numbers_position2] == 0) {
                    number_thirst.digits[numbers_position2] = base - 1;
                }
                else {
                    number_thirst.digits[numbers_position2] = number_thirst.digits[numbers_position2] - 1;
                    break;
                }
            }
        }
    }
    return inf::zeroes_leading_remove(number_thirst);
}
inf inf::sum(inf number_thirst, inf number_second) {
    if (number_thirst.natural == true and number_second.natural == false) {
        return inf::subtraction_natural(number_thirst, number_second);
    }
    if (number_thirst.natural == false and number_second.natural == true) {
        return inf::subtraction_natural(number_second, number_thirst);
    }
    if (number_thirst.natural == false and number_second.natural == false) {
        number_second.natural = true;
    }
    if (number_thirst.digits.size() > number_second.digits.size()) {
        number_second = inf::shift_right(number_second, number_thirst.digits.size() - number_second.digits.size());
    }
    else {
        number_thirst = inf::shift_right(number_thirst, number_second.digits.size() - number_thirst.digits.size());
    }
    int sum;
    int in_mind = 0;
    for (int numbers_position = number_thirst.digits.size() - 1; numbers_position >= 0; numbers_position = numbers_position - 1) {
        sum = number_thirst.digits[numbers_position] + number_second.digits[numbers_position] + in_mind;
        in_mind = sum / base;
        number_thirst.digits[numbers_position] = sum % base;
    }
    if (in_mind != 0) {
        number_thirst.digits.insert(number_thirst.digits.begin() + 0, in_mind);
    }
    return number_thirst;
}
inf inf::subtraction(inf number_thirst, inf number_second) {
    if (number_thirst.natural == true and number_second.natural == false) {
        number_second.natural = true;
        return inf::sum(number_thirst, number_second);
    }
    if (number_thirst.natural == false and number_second.natural == true) {
        number_thirst.natural = true;
        inf tmp = inf::sum(number_thirst, number_second);
        tmp.natural = false;
        return tmp;
    }
    if (number_thirst.natural == false and number_second.natural == false) {
        return inf::subtraction_natural(number_second, number_thirst);
    }
    return inf::subtraction_natural(number_thirst, number_second);
}
inf inf::multiply(inf number_thirst, inf number_second) {
    inf result;
    result.digits.resize(number_thirst.digits.size() + number_second.digits.size());
    long long composition;
    for (int number_thirst_position = number_thirst.digits.size() - 1; number_thirst_position >= 0; number_thirst_position = number_thirst_position - 1) {
        for (int number_second_position = number_second.digits.size() - 1; number_second_position >= 0; number_second_position = number_second_position - 1) {
            composition = (long long)number_thirst.digits[number_thirst_position] * (long long)number_second.digits[number_second_position] + result.digits[number_thirst_position + number_second_position + 1];
            result.digits[number_thirst_position + number_second_position + 1] = composition % base;
            result.digits[number_thirst_position + number_second_position + 1 - 1] = result.digits[number_thirst_position + number_second_position + 1 - 1] + (composition / base);
        }
    }
    result.natural = (number_thirst.natural == number_second.natural);
    return inf::zeroes_leading_remove(result);
}
inf inf::division_whole(inf number_thirst, inf number_second) {
    inf zero = 0;
    inf result;
    result.natural = (number_thirst.natural == number_second.natural);
    inf number_thirst_part;
    number_thirst_part.natural = true;
    number_thirst.natural = true;
    number_second.natural = true;
    if (inf::compare(number_second, zero) == '=') {
        throw "Fatal error. Division is impossible. Attempt to divide by zero.";
    }
    if (inf::compare(number_thirst, number_second) == '<') {
        return zero;
    }
    result.digits.resize(0);
    number_thirst_part.digits.resize(0);
    int quotient;
    for (int number_thirst_position = 0; number_thirst_position < number_thirst.digits.size(); number_thirst_position = number_thirst_position + 1) {
        number_thirst_part.digits.push_back(number_thirst.digits[number_thirst_position]);
        quotient = 0;
        for (int step = base_length; step >= 2; step = step - 0) {
            number_thirst_part = inf::subtraction_natural(number_thirst_part, inf::multiply(number_second, (int)std::pow(10, step)));
            if (inf::compare(number_thirst_part, number_second) == '<') {
                number_thirst_part = inf::sum(number_thirst_part, inf::multiply(number_second, (int)std::pow(10, step)));
                step = step - 1;
            }
            else {
                quotient = quotient + std::pow(10, step);
            }
        }
        while (inf::compare(number_thirst_part, number_second) != '<') {
            number_thirst_part = inf::subtraction_natural(number_thirst_part, number_second);
            quotient = quotient + 1;
        }
        if (result.digits.size() != 0 or quotient != 0) {
            result.digits.push_back(quotient);
        }
        if (inf::compare(number_thirst_part, zero) == '=') {
            number_thirst_part.digits.resize(0);
        }
    }
    return result;
}
inf inf::division_remainder(inf number_thirst, inf number_second) {
    inf zero = 0;
    inf number_thirst_part;
    number_thirst_part.natural = true;
    number_thirst.natural = true;
    number_second.natural = true;
    if (inf::compare(number_second, zero) == '=') {
        throw "Fatal error. Division is impossible. Attempt to divide by zero.";
    }
    if (inf::compare(number_thirst, number_second) == '<') {
        return number_thirst;
    }
    number_thirst_part.digits.resize(0);
    for (int number_thirst_position = 0; number_thirst_position < number_thirst.digits.size(); number_thirst_position = number_thirst_position + 1) {
        number_thirst_part.digits.push_back(number_thirst.digits[number_thirst_position]);
        for (int step = base_length; step >= 2; step = step - 0) {
            number_thirst_part = inf::subtraction_natural(number_thirst_part, inf::multiply(number_second, (int)std::pow(10, step)));
            if (inf::compare(number_thirst_part, number_second) == '<') {
                number_thirst_part = inf::sum(number_thirst_part, inf::multiply(number_second, (int)std::pow(10, step)));
                step = step - 1;
            }
        }
        while (inf::compare(number_thirst_part, number_second) != '<') {
            number_thirst_part = inf::subtraction_natural(number_thirst_part, number_second);
        }
        if (inf::compare(number_thirst_part, zero) == '=') {
            number_thirst_part.digits.resize(0);
        }
    }
    if (number_thirst_part.digits.size() == 0) {
        return zero;
    }
    return number_thirst_part;
}
inf inf::pow(inf number_thirst, inf number_second) {
    inf zero = 0;
    inf one = 1;
    inf two = 2;
    if (inf::compare(number_thirst, zero) == '=' and inf::compare(number_second, zero) == '=') {
        throw "Fatal error. Pow calculation is impossible. It is impossible to raise zero to zero degree.";
    }
    if (inf::compare(number_second, zero) == '<') {
        throw "Fatal error. Pow calculation is impossible. This class only support whole numbers, so erection to negative degree is impossible.";
    }
    inf result = one;
    while (inf::compare(number_second, zero) != '=') {
        if (inf::compare(inf::division_remainder(number_second, two), zero) == '=') {
            number_second = inf::division_whole(number_second, two);
            number_thirst = inf::multiply(number_thirst, number_thirst);
        }
        else {
            number_second = inf::subtraction_natural(number_second, one);
            result = inf::multiply(result, number_thirst);
        }
    }
    return result;
}
inf inf::factorial_tree(inf number_thirst, const inf& number_second) {
    inf one = 1;
    inf two = 2;
    if (inf::compare(number_thirst, number_second) == '>') {
        return one;
    }
    if (inf::compare(number_thirst, number_second) == '=') {
        return number_thirst;
    }
    if (inf::compare(inf::subtraction_natural(number_second, number_thirst), one) == '=') {
        return inf::multiply(number_thirst, number_second);
    }
    inf tmp = inf::division_whole(inf::sum(number_thirst, number_second), two);
    return inf::multiply(inf::factorial_tree(number_thirst, tmp), inf::factorial_tree(inf::sum(tmp, one), number_second));
}
inf inf::factorial(const inf& number) {
    inf one = 1;
    inf two = 2;
    if (inf::compare(number, one) == '<') {
        throw "Fatal error. Factorial calculation is impossible. Factorial is defined only for natural numbers.";
    }
    if (inf::compare(number, one) == '=') {
        return one;
    }
    if (inf::compare(number, two) == '=') {
        return two;
    }
    return factorial_tree(two, number);
}
inf inf::gcd(inf number_thirst, inf number_second) {
    inf zero = 0;
    if (inf::compare(number_thirst, zero) == '=' or inf::compare(number_second, zero) == '=') {
        throw "Fatal error. GCD calculation is impossible. One of the numbers is zero.";
    }
    number_thirst.natural = true;
    number_second.natural = true;
    while (inf::compare(number_thirst, zero) != '=' and inf::compare(number_second, zero) != '=') {
        if (inf::compare(number_thirst, number_second) == '>') {
            number_thirst = inf::division_remainder(number_thirst, number_second);
        }
        else {
            number_second = inf::division_remainder(number_second, number_thirst);
        }
    }
    return inf::sum(number_thirst, number_second);
}
inf inf::lcm(inf number_thirst, inf number_second) {
    inf zero = 0;
    if (inf::compare(number_thirst, zero) == '=' or inf::compare(number_second, zero) == '=') {
        throw "Fatal error. LCM calculation is impossible. One of the numbers is zero.";
    }
    number_thirst.natural = true;
    number_second.natural = true;
    return inf::division_whole(inf::multiply(number_thirst, number_second), inf::gcd(number_thirst, number_second));
}
inf inf::abs(inf number) {
    number.natural = true;
    return number;
}
bool inf::even(const inf& number) {
    if (number.digits[number.digits.size() - 1] % 2 == 0) {
        return true;
    }
    return false;
}
std::ostream &operator <<(std::ostream& ostream, const inf& number) {
    std::string string = inf::to_string(number);
    for (int i = 0; i < string.size(); i = i + 1) {
        ostream.put(string[i]);
    }
    return ostream;
}
bool operator >(const inf& number_thirst, const inf& number_second) {
    if (inf::compare(number_thirst, number_second) == '>') {
        return true;
    }
    return false;
}
bool operator >=(const inf& number_thirst, const inf& number_second) {
    if (inf::compare(number_thirst, number_second) != '<') {
        return true;
    }
    return false;
}
bool operator <(const inf& number_thirst, const inf& number_second) {
    if (inf::compare(number_thirst, number_second) == '<') {
        return true;
    }
    return false;
}
bool operator <=(const inf& number_thirst, const inf& number_second) {
    if (inf::compare(number_thirst, number_second) != '>') {
        return true;
    }
    return false;
}
bool operator ==(const inf& number_thirst, const inf& number_second) {
    if (inf::compare(number_thirst, number_second) == '=') {
        return true;
    }
    return false;
}
bool operator !=(const inf& number_thirst, const inf& number_second) {
    if (inf::compare(number_thirst, number_second) != '=') {
        return true;
    }
    return false;
}
inf operator +(const inf& number_thirst, const inf& number_second) {
    return inf::sum(number_thirst, number_second);
}
inf operator -(const inf& number_thirst, const inf& number_second) {
    return inf::subtraction(number_thirst, number_second);
}
inf operator *(const inf& number_thirst, const inf& number_second) {
    return inf::multiply(number_thirst, number_second);
}
inf operator /(const inf& number_thirst, const inf& number_second) {
    return inf::division_whole(number_thirst, number_second);
}
inf operator %(const inf& number_thirst, const inf& number_second) {
    return inf::division_remainder(number_thirst, number_second);
}
inf inf::operator +=(const inf& number) {
    return *this = *this + number;
}
inf inf::operator -=(const inf& number) {
    return *this = *this - number;
}
inf inf::operator *=(const inf& number) {
    return *this = *this * number;
}
inf inf::operator /=(const inf& number) {
    return *this = *this / number;
}
inf inf::operator %=(const inf& number) {
    return *this = *this % number;
}
inf inf::operator ++() {
    return *this = *this + 1;
}
inf inf::operator --() {
    return *this = *this - 1;
}
inf inf::operator ++(int) {
    *this = *this + 1;
    return *this = *this - 1;
}
inf inf::operator --(int) {
    *this = *this - 1;
    return *this = *this + 1;
}

Я рад был бы прикрепить сюда и main.cpp в котором показывается демонстрация функционала (некий консольный калькулятор), но, к сожалению, я не могу это сделать из-за ограничений на максимальный размер вопроса StackOverFlow. Если это нужно, то можете посмотреть мой репозитарий на GitHub --- https://github.com/gth-other/long_arithmetic.


Ответы (0 шт):