diff --git a/Long-Algebra/BigNumber/BigNumber.cpp b/Long-Algebra/BigNumber/BigNumber.cpp index 513e1da..e69de29 100644 --- a/Long-Algebra/BigNumber/BigNumber.cpp +++ b/Long-Algebra/BigNumber/BigNumber.cpp @@ -1,2 +0,0 @@ -include "BigNumber.h" - diff --git a/Long-Algebra/BigNumber/BigNumber.h b/Long-Algebra/BigNumber/BigNumber.h index f5edcf6..bc9c30b 100644 --- a/Long-Algebra/BigNumber/BigNumber.h +++ b/Long-Algebra/BigNumber/BigNumber.h @@ -76,6 +76,7 @@ class BigNumber { } N = "0"; } + BigNumber(const BigNumber& to_copy) : chunks(to_copy.chunks), N(to_copy.N), sign(to_copy.sign), BASE(to_copy.BASE) {} ~BigNumber() {} /*GETTERS SETTERS*/ @@ -101,7 +102,7 @@ class BigNumber { vector getChunks() const { return this->chunks; } /*OUTPUT*/ - friend std::ostream & operator << (std::ostream &out, const BigNumber &num) { + friend std::ostream& operator << (std::ostream& out, const BigNumber& num) { for (int i = num.chunks.size() - 1; i >= 0; i--) { out << num.chunks[i]; } @@ -129,20 +130,22 @@ class BigNumber { /* #1 */ BigNumber operator - () const; - void operator = (const BigNumber &num); - bool operator == (const BigNumber &num) const; - bool operator != (const BigNumber & num) const; - bool operator >= (const BigNumber &num) const; - bool operator > (const BigNumber &num) const; - BigNumber operator % (const BigNumber &num) const; - BigNumber operator + (const BigNumber &num) const; - BigNumber operator - (const BigNumber &num) const; - BigNumber operator * (const BigNumber &num) const; - BigNumber operator / (const BigNumber & num) const; + void operator = (const BigNumber& num); + bool operator == (const BigNumber& num) const; + bool operator != (const BigNumber& num) const; + bool operator >= (const BigNumber& num) const; + bool operator > (const BigNumber& num) const; + BigNumber operator % (const BigNumber& num) const; + BigNumber operator + (const BigNumber& num) const; + BigNumber operator - (const BigNumber& num) const; + BigNumber operator * (const BigNumber& num) const; + BigNumber operator / (const BigNumber& num) const; BigNumber inverse() const; /* #2 */ + BigNumber montgomery_mult(const BigNumber& a, const BigNumber& b, const BigNumber& n1) const; BigNumber operator ^ (const BigNumber& num) const; + BigNumber euclid_alg(const BigNumber& a, const BigNumber& b, BigNumber* x, BigNumber* y) const; /* #3 */ @@ -182,47 +185,47 @@ class BigNumber { * @return 1 if it is and return -1 otherwise */ int Jacobi(); - - /** - * #4 - * @brief Euclidean algorithm - * @param take 2 numbers a, b - * @return vector {d, x, y} such that ax + by = d, where d = GCD(a, b) - */ - vector Euclidean_algorithm(BigNumber a, BigNumber b); - /** - * #4 - * @brief square root - * @return square roots if the number has it and N is a prime number - * return empty vector otherwise - */ - vector sqrt(); // - + /** + * #4 + * @brief Euclidean algorithm + * @param take 2 numbers a, b + * @return vector {d, x, y} such that ax + by = d, where d = GCD(a, b) + */ + vector Euclidean_algorithm(BigNumber a, BigNumber b) const; - /* #5 */ + /** + * #4 + * @brief square root + * @return square roots if the number has it and N is a prime number + * return empty vector otherwise + */ + vector sqrt(); // - /* #6 */ + /* #5 */ - /* #7 */ + /* #6 */ - /* #8 */ + /* #7 */ - /* #9 */ + /* #8 */ - /* #10 */ + /* #9 */ - /** - * # - * !!!!!!!!!!!!!!!! - */ - void set(BigNumber &x, BigNumber &a, BigNumber &b); + /* #10 */ + + + /** + * # + * !!!!!!!!!!!!!!!! + */ + void set(BigNumber& x, BigNumber& a, BigNumber& b); /** * # @@ -342,7 +345,7 @@ string BigNumber::to_string() const } // operator > -bool BigNumber::operator > (const BigNumber &num) const { +bool BigNumber::operator > (const BigNumber& num) const { if (sign > num.sign) { return true; } @@ -367,7 +370,7 @@ bool BigNumber::operator > (const BigNumber &num) const { } // operator >= -bool BigNumber::operator >= (const BigNumber &num) const { +bool BigNumber::operator >= (const BigNumber& num) const { if (sign > num.sign) { return true; } @@ -401,13 +404,13 @@ BigNumber BigNumber::operator - () const } // operator = -void BigNumber::operator = (const BigNumber &num) +void BigNumber::operator = (const BigNumber& num) { this->setBigNumber(num); } // operator == -bool BigNumber::operator == (const BigNumber &num) const { +bool BigNumber::operator == (const BigNumber& num) const { if ((sign != num.sign) || (this->chunks.size() != num.chunks.size())) { return false; } @@ -418,7 +421,7 @@ bool BigNumber::operator == (const BigNumber &num) const { } // operator != -bool BigNumber::operator != (const BigNumber &num) const { +bool BigNumber::operator != (const BigNumber& num) const { return !(*this == num); } @@ -478,7 +481,7 @@ void BigNumber::modN(string N) { * @details for faster division * (used in inverse()) */ -void BigNumber::decrease(const BigNumber & a, BigNumber & b, const BigNumber& a_count_in_a, BigNumber& a_count_in_b) const +void BigNumber::decrease(const BigNumber& a, BigNumber& b, const BigNumber& a_count_in_a, BigNumber& a_count_in_b) const { if (b.getN() == "0") { string N = a.getN(); @@ -510,14 +513,14 @@ void BigNumber::decrease(const BigNumber & a, BigNumber & b, const BigNumber& a_ * @brief division not under field * (used in division /) */ -BigNumber BigNumber::simple_division(const BigNumber & b) const +BigNumber BigNumber::simple_division(const BigNumber& b) const { BigNumber res("0"); vector reschunks; BigNumber ten("10"); BigNumber temp("0"); for (int i = chunks.size() - 1; i >= 0;) { - while (b > temp && i >= 0) { + while (b > temp&& i >= 0) { temp = temp * ten + BigNumber(std::to_string(chunks[i])); i--; } @@ -526,7 +529,7 @@ BigNumber BigNumber::simple_division(const BigNumber & b) const temp = temp - b; count++; } - cout << count << endl; + //cout << count << endl; reschunks.push_back(count); } if (!reschunks.empty()) { @@ -540,7 +543,7 @@ BigNumber BigNumber::simple_division(const BigNumber & b) const * #1 * @brief operator + */ -BigNumber BigNumber::operator + (const BigNumber &num) const { +BigNumber BigNumber::operator + (const BigNumber& num) const { BigNumber res("0", N); vector reschunks; @@ -609,7 +612,7 @@ BigNumber BigNumber::operator + (const BigNumber &num) const { * #1 * @brief operator - */ -BigNumber BigNumber::operator - (const BigNumber &num) const { +BigNumber BigNumber::operator - (const BigNumber& num) const { BigNumber res("0", N); vector reschunks; @@ -675,9 +678,10 @@ BigNumber BigNumber::operator - (const BigNumber &num) const { * #1 * @brief operator * */ -BigNumber BigNumber::operator * (const BigNumber &num) const { +BigNumber BigNumber::operator * (const BigNumber& num) const { BigNumber res("0", N); + res.sign = this->sign * num.sign; vector res_chunks; res_chunks.resize(this->chunks.size() + num.chunks.size() + 1); for (int i = 0; i < this->chunks.size(); i++) { @@ -735,10 +739,10 @@ BigNumber BigNumber::inverse() const { * @brief operator / * if one of module == 0 do standart division */ -BigNumber BigNumber::operator / (const BigNumber &num) const { +BigNumber BigNumber::operator / (const BigNumber& num) const { BigNumber res("0"); - if (this->getN() != "0"&&num.getN() != "0") { - res = (*this)*(num.inverse()); + if (this->getN() != "0" && num.getN() != "0") { + res = (*this) * (num.inverse()); } else { res = simple_division(num); @@ -750,7 +754,7 @@ BigNumber BigNumber::operator / (const BigNumber &num) const { * #1 * @brief operator % */ -BigNumber BigNumber::operator % (const BigNumber & num) const +BigNumber BigNumber::operator % (const BigNumber& num) const { BigNumber res = BigNumber("0", N); res.setChunks(chunks); @@ -762,34 +766,129 @@ BigNumber BigNumber::operator % (const BigNumber & num) const /* #2 */ + +BigNumber BigNumber::montgomery_mult(const BigNumber& a, const BigNumber& b, const BigNumber& n1)const { + BigNumber x = a * b; + BigNumber s = x * n1; + + if (s.chunks.size() && N.size() < s.chunks.size()) { + s.chunks.erase(s.chunks.begin() + N.size(), s.chunks.end()); + } + + if (s.chunks.size() > 0) { + int it = s.chunks.size() - 1; + while (it>=0 && s.chunks[it--] == 0) { + s.chunks.erase(s.chunks.end() - 1); + } + if (s.chunks.size() == 0) + s.chunks.push_back(0); + } + + + BigNumber t = x + s * N; + BigNumber u = t; + if (u.chunks.size()) + u.chunks.erase(u.chunks.begin(), u.chunks.begin() + N.size()); + + BigNumber c1 = (BigNumber(N) > u) ? u : u - BigNumber(N); + //c1.setN(N); + return c1; +} + +BigNumber BigNumber::euclid_alg(const BigNumber& a, const BigNumber& b, BigNumber* x, BigNumber* y)const { + // Base Case + BigNumber one("1"); + BigNumber zero("0"); + if (a == zero) + { + *x = zero; + *y = one; + return b; + } + + BigNumber x1("0"), y1("0"); // To store results of recursive call + BigNumber gcd = euclid_alg(b % a, a, &x1, &y1); + + // Update x and y using results of + // recursive call + *x = y1 - (b / a) * x1; + *y = x1; + + return gcd; +} + + /** * #2 * @brief operator ^ */ BigNumber BigNumber::operator ^ (const BigNumber& pow) const { - //x^pow % N - BigNumber one("1"); - if (pow == one) - return *this; - if (pow == BigNumber("0")) - return one; - - BigNumber res = *this; - BigNumber two("2"); + char check; + if (N.size() && ((check = N[N.size() - 1]) == '1' || check == '3' || check == '7' || check == '9')) { + //std::string; + BigNumber r("0"); + r.chunks.resize(N.size());// = this->chunks.size(); + r.chunks.push_back(1); + + BigNumber a = *this; + a.setN(pow.N); + + //BigNumber n1("0"), rr("0"); + BigNumber n = N; + n.setN("0"); + + //r*rr + n*n1 = 1 + BigNumber rr("0"), n1("0"); + euclid_alg(n, r, &n1, &rr); + n1 = -n1; + + BigNumber a1("0", N); + a1.chunks.reserve(N.size() - 1 + a.chunks.size()); + for (size_t i = 0, size = N.size() - 1; i < size; ++i) + a1.chunks.push_back(0); + for (size_t i = 0, size = a.chunks.size(); i < size; ++i) + a1.chunks.push_back(a.chunks[i]); + + a1.setN(N); + + + BigNumber one("1", N); + BigNumber i("0"); + BigNumber c1 = a1; + + n1.setN("0"); + a1.setN("0"); + c1.setN("0"); + i.chunks.reserve(N.size()); + for (BigNumber size = pow - one; size > i; i = i + one) { + c1 = montgomery_mult(a1, c1, n1); + } - BigNumber i("1"); + c1.setN(N); + rr.setN(N); + BigNumber c = c1 * rr; - for (; pow > i*two;) { - res = res * res; - i = i * two; + return c; } + else { + ////x^pow % N + BigNumber one("1"); + if (pow == one) + return *this; + if (pow == BigNumber("0")) + return one; - while (i != pow) { - res = res * *this; - i = i + one; - } + BigNumber res = *this; - return res; + BigNumber i("1"); + + while (i != pow) { + res = res * *this; + i = i + one; + } + + return res; + } } /* #3 */ @@ -877,7 +976,7 @@ BigNumber BigNumber::_factorize_pollard(string _c) { BigNumber one = BigNumber("1", this->to_string()); BigNumber two = BigNumber("2", this->to_string()); - if (two > *this) { + if (two > * this) { return zero; } @@ -948,7 +1047,7 @@ factorization BigNumber::factorize_pollard() { BigNumber one = BigNumber("1", N); BigNumber two = BigNumber("2", N); BigNumber divided = *this; - if (two > *this) { + if (two > * this) { cout << "This number is less than two. *This cout is used to developers. " "Comment it if u dont need it*" << endl; out.base.push_back(one); @@ -1013,7 +1112,7 @@ factorization BigNumber::factorize_pollard() { * @param take 2 numbers a, b * @return vector {d, x, y} such that ax + by = d, where d = GCD(a, b) */ -vector BigNumber::Euclidean_algorithm(BigNumber a, BigNumber b) +vector BigNumber::Euclidean_algorithm(BigNumber a, BigNumber b) const { vector answer; answer.push_back(BigNumber("0")); @@ -1161,7 +1260,7 @@ vector BigNumber::sqrt() r = r ^ new_number; for (BigNumber i = BigNumber("1", "0"); s >= i + BigNumber("1", "0"); i = i + BigNumber("1", "0")) { - BigNumber d = (r*r*inv) ^ (BigNumber("2") ^ (s - i - BigNumber("1"))); + BigNumber d = (r * r * inv) ^ (BigNumber("2") ^ (s - i - BigNumber("1"))); if (d == BigNumber(N) - BigNumber("1")) { r = r * c; @@ -1195,7 +1294,7 @@ vector BigNumber::sqrt() * # * @brief !!!!!!!!!!!!!! */ -void BigNumber::set(BigNumber &x, BigNumber &a, BigNumber &b) +void BigNumber::set(BigNumber& x, BigNumber& a, BigNumber& b) { BigNumber N = BigNumber(this->N); BigNumber zero = BigNumber("0", this->N); diff --git a/Long-Algebra/BigNumber/BigNumber.sln b/Long-Algebra/BigNumber/BigNumber.sln new file mode 100644 index 0000000..a9fb535 --- /dev/null +++ b/Long-Algebra/BigNumber/BigNumber.sln @@ -0,0 +1,31 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.29519.87 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BigNumber", "BigNumber.vcxproj", "{EEF8A747-9027-47FB-90E5-719A64E4AF13}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {EEF8A747-9027-47FB-90E5-719A64E4AF13}.Debug|x64.ActiveCfg = Debug|x64 + {EEF8A747-9027-47FB-90E5-719A64E4AF13}.Debug|x64.Build.0 = Debug|x64 + {EEF8A747-9027-47FB-90E5-719A64E4AF13}.Debug|x86.ActiveCfg = Debug|Win32 + {EEF8A747-9027-47FB-90E5-719A64E4AF13}.Debug|x86.Build.0 = Debug|Win32 + {EEF8A747-9027-47FB-90E5-719A64E4AF13}.Release|x64.ActiveCfg = Release|x64 + {EEF8A747-9027-47FB-90E5-719A64E4AF13}.Release|x64.Build.0 = Release|x64 + {EEF8A747-9027-47FB-90E5-719A64E4AF13}.Release|x86.ActiveCfg = Release|Win32 + {EEF8A747-9027-47FB-90E5-719A64E4AF13}.Release|x86.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {A907FA89-88E4-4C47-9E0C-8620C443CF31} + EndGlobalSection +EndGlobal diff --git a/Long-Algebra/BigNumber/BigNumber.vcxproj b/Long-Algebra/BigNumber/BigNumber.vcxproj new file mode 100644 index 0000000..a655492 --- /dev/null +++ b/Long-Algebra/BigNumber/BigNumber.vcxproj @@ -0,0 +1,135 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 16.0 + {EEF8A747-9027-47FB-90E5-719A64E4AF13} + BigNumber + 10.0 + + + + Application + true + v142 + MultiByte + + + Application + false + v142 + true + MultiByte + + + Application + true + v142 + MultiByte + + + Application + false + v142 + true + MultiByte + + + + + + + + + + + + + + + + + + + + + + + Level3 + Disabled + true + true + + + Console + + + + + Level3 + Disabled + true + true + + + Console + + + + + Level3 + MaxSpeed + true + true + true + true + + + Console + true + true + + + + + Level3 + MaxSpeed + true + true + true + true + + + Console + true + true + + + + + + + + + + + + + \ No newline at end of file diff --git a/Long-Algebra/BigNumber/BigNumber.vcxproj.filters b/Long-Algebra/BigNumber/BigNumber.vcxproj.filters new file mode 100644 index 0000000..dabc18f --- /dev/null +++ b/Long-Algebra/BigNumber/BigNumber.vcxproj.filters @@ -0,0 +1,30 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;ipp;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Source Files + + + Source Files + + + + + Header Files + + + \ No newline at end of file diff --git a/Long-Algebra/BigNumber/Source.cpp b/Long-Algebra/BigNumber/Source.cpp new file mode 100644 index 0000000..5722666 --- /dev/null +++ b/Long-Algebra/BigNumber/Source.cpp @@ -0,0 +1,52 @@ +#include "BigNumber.h" +#include +#include + +BigNumber test_case_1(){ + BigNumber cur("122", "2001"); + std::cout << "122 ^ 54573 mod 2001\n"; + std::cout << "Expected value: " << 296<<'\n'; + return (cur ^ (BigNumber("54573", "0"))); +} + +BigNumber test_case_2(){ + BigNumber cur("13", "23"); + std::cout << "13 ^ 426 mod 23\n"; + std::cout << "Expected value: " << 2 << '\n'; + return (cur ^ (BigNumber("426", "0"))); +} + +BigNumber test_case_3(){ + BigNumber cur("543", "563"); + std::cout << "543 ^ 493 mod 563\n"; + std::cout << "Expected value: " << 330 << '\n'; + return (cur ^ (BigNumber("493", "0"))); +} + +BigNumber test_case_4(){ + BigNumber cur("9", "7"); + std::cout << "9 ^ 12 mod 7\n"; + std::cout << "Expected value: " << 1 << '\n'; + return (cur ^ (BigNumber("12", "0"))); +} + +BigNumber test_case_5(){ + BigNumber cur("394", "598"); + std::cout << "394 ^ 293 mod 598\n"; + std::cout << "Expected value: " << 140 << '\n'; + return (cur ^ (BigNumber("293", "0"))); +} + +int main() { + BigNumber temp("0"); + temp = test_case_1(); + std::cout << "Current value: " << temp << "\n\n"; + temp = test_case_2(); + std::cout << "Current value: " << temp << "\n\n"; + temp = test_case_3(); + std::cout << "Current value: " << temp << "\n\n"; + temp = test_case_4(); + std::cout << "Current value: " << temp << "\n\n"; + temp = test_case_5(); + std::cout << "Current value: " << temp << "\n\n"; +} \ No newline at end of file