From cabd2d32f198613ae99ecdc1784611ba9369adb8 Mon Sep 17 00:00:00 2001 From: RaphaelRevivor Date: Sat, 27 Sep 2025 18:37:26 +0200 Subject: [PATCH 1/6] Add basic folder structure --- .github/workflows/ci.yml | 0 BUILD | 0 LICENSE | 0 MODULE.bazel | 0 docker-compose.yaml | 0 docker/.dockerignore | 0 docker/Dockerfile | 0 docs/api.md | 0 docs/architecture.md | 0 k8s/configmap.yaml | 0 k8s/deployment.yaml | 0 k8s/hpa.yaml | 0 k8s/ingress.yaml | 0 k8s/secret.yaml | 0 k8s/service.yaml | 0 src/BUILD | 0 src/api/BUILD | 0 src/api/rest.cpp | 0 src/api/rest.h | 0 src/api/utils.cpp | 0 src/api/utils.h | 0 src/factor.cpp | 0 src/factor.h | 0 src/main.cpp | 0 src/main.h | 0 src/montecarlo.cpp | 0 src/montecarlo.h | 0 tests/BUILD | 0 tests/api_test.cpp | 0 tests/factor_test.cpp | 0 tests/montecarlo_test.cpp | 0 31 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 .github/workflows/ci.yml create mode 100644 BUILD create mode 100644 LICENSE create mode 100644 MODULE.bazel create mode 100644 docker-compose.yaml create mode 100644 docker/.dockerignore create mode 100644 docker/Dockerfile create mode 100644 docs/api.md create mode 100644 docs/architecture.md create mode 100644 k8s/configmap.yaml create mode 100644 k8s/deployment.yaml create mode 100644 k8s/hpa.yaml create mode 100644 k8s/ingress.yaml create mode 100644 k8s/secret.yaml create mode 100644 k8s/service.yaml create mode 100644 src/BUILD create mode 100644 src/api/BUILD create mode 100644 src/api/rest.cpp create mode 100644 src/api/rest.h create mode 100644 src/api/utils.cpp create mode 100644 src/api/utils.h create mode 100644 src/factor.cpp create mode 100644 src/factor.h create mode 100644 src/main.cpp create mode 100644 src/main.h create mode 100644 src/montecarlo.cpp create mode 100644 src/montecarlo.h create mode 100644 tests/BUILD create mode 100644 tests/api_test.cpp create mode 100644 tests/factor_test.cpp create mode 100644 tests/montecarlo_test.cpp diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..e69de29 diff --git a/BUILD b/BUILD new file mode 100644 index 0000000..e69de29 diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..e69de29 diff --git a/MODULE.bazel b/MODULE.bazel new file mode 100644 index 0000000..e69de29 diff --git a/docker-compose.yaml b/docker-compose.yaml new file mode 100644 index 0000000..e69de29 diff --git a/docker/.dockerignore b/docker/.dockerignore new file mode 100644 index 0000000..e69de29 diff --git a/docker/Dockerfile b/docker/Dockerfile new file mode 100644 index 0000000..e69de29 diff --git a/docs/api.md b/docs/api.md new file mode 100644 index 0000000..e69de29 diff --git a/docs/architecture.md b/docs/architecture.md new file mode 100644 index 0000000..e69de29 diff --git a/k8s/configmap.yaml b/k8s/configmap.yaml new file mode 100644 index 0000000..e69de29 diff --git a/k8s/deployment.yaml b/k8s/deployment.yaml new file mode 100644 index 0000000..e69de29 diff --git a/k8s/hpa.yaml b/k8s/hpa.yaml new file mode 100644 index 0000000..e69de29 diff --git a/k8s/ingress.yaml b/k8s/ingress.yaml new file mode 100644 index 0000000..e69de29 diff --git a/k8s/secret.yaml b/k8s/secret.yaml new file mode 100644 index 0000000..e69de29 diff --git a/k8s/service.yaml b/k8s/service.yaml new file mode 100644 index 0000000..e69de29 diff --git a/src/BUILD b/src/BUILD new file mode 100644 index 0000000..e69de29 diff --git a/src/api/BUILD b/src/api/BUILD new file mode 100644 index 0000000..e69de29 diff --git a/src/api/rest.cpp b/src/api/rest.cpp new file mode 100644 index 0000000..e69de29 diff --git a/src/api/rest.h b/src/api/rest.h new file mode 100644 index 0000000..e69de29 diff --git a/src/api/utils.cpp b/src/api/utils.cpp new file mode 100644 index 0000000..e69de29 diff --git a/src/api/utils.h b/src/api/utils.h new file mode 100644 index 0000000..e69de29 diff --git a/src/factor.cpp b/src/factor.cpp new file mode 100644 index 0000000..e69de29 diff --git a/src/factor.h b/src/factor.h new file mode 100644 index 0000000..e69de29 diff --git a/src/main.cpp b/src/main.cpp new file mode 100644 index 0000000..e69de29 diff --git a/src/main.h b/src/main.h new file mode 100644 index 0000000..e69de29 diff --git a/src/montecarlo.cpp b/src/montecarlo.cpp new file mode 100644 index 0000000..e69de29 diff --git a/src/montecarlo.h b/src/montecarlo.h new file mode 100644 index 0000000..e69de29 diff --git a/tests/BUILD b/tests/BUILD new file mode 100644 index 0000000..e69de29 diff --git a/tests/api_test.cpp b/tests/api_test.cpp new file mode 100644 index 0000000..e69de29 diff --git a/tests/factor_test.cpp b/tests/factor_test.cpp new file mode 100644 index 0000000..e69de29 diff --git a/tests/montecarlo_test.cpp b/tests/montecarlo_test.cpp new file mode 100644 index 0000000..e69de29 From 929b5b29ef6c867f28fa363bdd85bebc70f0cc0d Mon Sep 17 00:00:00 2001 From: RaphaelRevivor Date: Sun, 28 Sep 2025 21:21:27 +0200 Subject: [PATCH 2/6] Implement factorization (PollarsPho) (#2) --- BUILD | 6 ++++ src/BUILD | 20 +++++++++++ src/factor.cpp | 91 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/factor.h | 41 +++++++++++++++++++++++ src/main.cpp | 12 +++++++ src/main.h | 7 ++++ 6 files changed, 177 insertions(+) diff --git a/BUILD b/BUILD index e69de29..8833729 100644 --- a/BUILD +++ b/BUILD @@ -0,0 +1,6 @@ +module( + name = "cpp-analytics-devops", + version = "1.0.0", +) + +bazel_dep(name = "googletest", version = "1.17.0") \ No newline at end of file diff --git a/src/BUILD b/src/BUILD index e69de29..a8965f0 100644 --- a/src/BUILD +++ b/src/BUILD @@ -0,0 +1,20 @@ +cc_library( + name = "factorLib", + srcs = [ + "factor.cpp" + ], + hdrs = [ + "factor.h" + ], +) + +cc_binary( + name = "mainProg", + srcs = [ + "main.cpp", + "main.h", + ], + deps = [ + ":factorLib", + ], +) \ No newline at end of file diff --git a/src/factor.cpp b/src/factor.cpp index e69de29..36701ab 100644 --- a/src/factor.cpp +++ b/src/factor.cpp @@ -0,0 +1,91 @@ +#include "factor.h" + +using namespace std; + +// === member functions for PollardsPho === + +/// @brief constructor +/// @param n the value for fatorization +PollardsPho::PollardsPho(int64_t n) : n(n) +{ + srand(time(0)); +} + +/// @brief the main function to do the calculation +/// @return result +int64_t PollardsPho::calculate() +{ + int64_t d = 1; + int64_t cnt = 0; + int64_t x = selectX0(); + int64_t y = x; + + while(d == 1 || d == n) + { + d = basicIteration(x, y); + + cout << cnt << ":" << endl; + cout << "x, y, d:" << x << "," << y << "," << d << endl; + + if (d == n) + { + failure++; + } + cnt++; + } + + return d; +} + +/// @brief basic iteration of the algorithm +/// @param x x +/// @param y y +/// @return d +int64_t PollardsPho::basicIteration(int64_t &x, int64_t &y) +{ + selectC(c); + x = polyFuncMod(x, c); + y = polyFuncMod(polyFuncMod(y, c), c); + int64_t d = calculateD(x, y); + + return d; +} + +int64_t PollardsPho::selectX0() +{ + return (rand() % (n - 2)) + 2; +} + +/// @brief function to calculate f(x) = x^2 + c +/// @param x x +/// @param c c +/// @return f(x) +int64_t PollardsPho::polyFuncMod(int64_t x, int64_t c) +{ + __int128_t output = (x * x + c) % n; + return output; +} + +/// @brief funtion to calculate D = gcd(abs(x-y), n) +int64_t PollardsPho::calculateD(int64_t x, int64_t y) +{ + return gcd(abs(x-y), n); +} + +/// @brief function to select c +/// @return c +void PollardsPho::selectC(int64_t& input) +{ + if (failure < 100) + input = 1; + else if (failure < 200) + input = 2; + else if (failure < 300) + input = 3; + // choose from [4, n) + else + input = (rand() % (n - 4)) + 4; +} + + +// === member functions for Factorization === \ No newline at end of file diff --git a/src/factor.h b/src/factor.h index e69de29..df120c1 100644 --- a/src/factor.h +++ b/src/factor.h @@ -0,0 +1,41 @@ +#ifndef FACTOR_H +#define FACTOR_H + +#include +#include +#include +#include +#include +#include +#include + +class PollardsPho +{ +public: + PollardsPho(int64_t n); + ~PollardsPho() = default; + int64_t calculate(); + +private: + int64_t n; + int64_t c; + int64_t failure = 0; + int64_t polyFuncMod(int64_t x, int64_t c); + int64_t calculateD(int64_t x, int64_t y); + void selectC(int64_t& input); + int64_t selectX0(); + int64_t basicIteration(int64_t &x, int64_t &y); +}; + +// class Factorization +// { +// public: +// Factorization(int64_t n) : n(n) +// { +// } +// ~Factorization() = default; +// private: +// int64_t n; +// }; + +#endif \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index e69de29..b25fb0b 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -0,0 +1,12 @@ +#include "main.h" + +using namespace std; + +int main() +{ + int64_t n = 10967535067; + auto pollardsPho = PollardsPho(n); + auto result = pollardsPho.calculate(); + + cout << "One factor of " << n << " is: " << result << endl; +} \ No newline at end of file diff --git a/src/main.h b/src/main.h index e69de29..b15201c 100644 --- a/src/main.h +++ b/src/main.h @@ -0,0 +1,7 @@ +#ifndef MAIN_H +#define MAIN_H + +#include +#include "factor.h" + +#endif \ No newline at end of file From 717cd8da9fc9c0f9b4438b7b6f7fc66e95c94dcd Mon Sep 17 00:00:00 2001 From: RaphaelRevivor Date: Mon, 29 Sep 2025 11:39:51 +0200 Subject: [PATCH 3/6] Add basic logging as well as ability to pass n from cli (#2) --- src/factor.cpp | 20 +++++++++++++++----- src/factor.h | 1 + src/main.cpp | 14 ++++++++++++-- src/main.h | 1 + 4 files changed, 29 insertions(+), 7 deletions(-) diff --git a/src/factor.cpp b/src/factor.cpp index 36701ab..373d837 100644 --- a/src/factor.cpp +++ b/src/factor.cpp @@ -3,7 +3,6 @@ using namespace std; // === member functions for PollardsPho === - /// @brief constructor /// @param n the value for fatorization PollardsPho::PollardsPho(int64_t n) : n(n) @@ -23,14 +22,13 @@ int64_t PollardsPho::calculate() while(d == 1 || d == n) { d = basicIteration(x, y); - - cout << cnt << ":" << endl; - cout << "x, y, d:" << x << "," << y << "," << d << endl; - if (d == n) { failure++; } + + basicLogging(x, y, d, cnt); + cnt++; } @@ -51,6 +49,8 @@ int64_t PollardsPho::basicIteration(int64_t &x, int64_t &y) return d; } +/// @brief select the initial x +/// @return x int64_t PollardsPho::selectX0() { return (rand() % (n - 2)) + 2; @@ -87,5 +87,15 @@ void PollardsPho::selectC(int64_t& input) input = (rand() % (n - 4)) + 4; } +/// @brief provides a basic logging showing info for x, y, d, cnt +/// @param x x +/// @param y y +/// @param d d +/// @param cnt cnt +void PollardsPho::basicLogging(int64_t &x, int64_t &y, int64_t &d, int64_t &cnt) +{ + cout << cnt << ":" << endl; + cout << "x, y, d:" << x << "," << y << "," << d << endl; +} // === member functions for Factorization === \ No newline at end of file diff --git a/src/factor.h b/src/factor.h index df120c1..5def679 100644 --- a/src/factor.h +++ b/src/factor.h @@ -25,6 +25,7 @@ class PollardsPho void selectC(int64_t& input); int64_t selectX0(); int64_t basicIteration(int64_t &x, int64_t &y); + void basicLogging(int64_t &x, int64_t &y, int64_t &d, int64_t &cnt); }; // class Factorization diff --git a/src/main.cpp b/src/main.cpp index b25fb0b..4373ab9 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2,9 +2,19 @@ using namespace std; -int main() +int main(int argc, char** argv) { - int64_t n = 10967535067; + string input = ""; + if (argc > 1) + input = argv[1]; + else + { + throw invalid_argument("No argument is passed!"); + } + + // might throw std::invalid_argument or std::out_of_range in case not able to parse + int64_t n = stoll(input); + auto pollardsPho = PollardsPho(n); auto result = pollardsPho.calculate(); diff --git a/src/main.h b/src/main.h index b15201c..8f38a45 100644 --- a/src/main.h +++ b/src/main.h @@ -2,6 +2,7 @@ #define MAIN_H #include +#include #include "factor.h" #endif \ No newline at end of file From 4d6b10970cda43879d4b0467fef30433764bb330 Mon Sep 17 00:00:00 2001 From: RaphaelRevivor Date: Mon, 29 Sep 2025 16:49:51 +0200 Subject: [PATCH 4/6] Add functionality to check prime number (#2) --- src/factor.cpp | 74 ++++++++++++++++++++++++++++++++++++++++++++++++-- src/factor.h | 4 ++- 2 files changed, 74 insertions(+), 4 deletions(-) diff --git a/src/factor.cpp b/src/factor.cpp index 373d837..52468fe 100644 --- a/src/factor.cpp +++ b/src/factor.cpp @@ -19,6 +19,15 @@ int64_t PollardsPho::calculate() int64_t x = selectX0(); int64_t y = x; + // trivial cases + if (n == 1 || n == 2 || n == 3) + return n; + else if (n%2 == 0) + return 2; + // check prime numbers + else if (millerRabin()) + return n; + while(d == 1 || d == n) { d = basicIteration(x, y); @@ -42,8 +51,8 @@ int64_t PollardsPho::calculate() int64_t PollardsPho::basicIteration(int64_t &x, int64_t &y) { selectC(c); - x = polyFuncMod(x, c); - y = polyFuncMod(polyFuncMod(y, c), c); + x = squareMod(x, c); + y = squareMod(squareMod(y, c), c); int64_t d = calculateD(x, y); return d; @@ -60,7 +69,7 @@ int64_t PollardsPho::selectX0() /// @param x x /// @param c c /// @return f(x) -int64_t PollardsPho::polyFuncMod(int64_t x, int64_t c) +int64_t PollardsPho::squareMod(int64_t x, int64_t c) { __int128_t output = (x * x + c) % n; return output; @@ -98,4 +107,63 @@ void PollardsPho::basicLogging(int64_t &x, int64_t &y, int64_t &d, int64_t &cnt) cout << "x, y, d:" << x << "," << y << "," << d << endl; } +/// @brief function to check prime (in the cases of none 1, 2, 3 or even) +/// @return bool result +bool PollardsPho::millerRabin() +{ + int64_t d = n - 1; + int64_t s = 0; + while(d % 2 == 0) + { + d /= 2; + s++; + } + + // enough for 64 bit int + vector bases = {2,3,5,7,11,13,17}; + for(const auto& base : bases) + { + if (base >= n) + continue; + + // calculate x = a^d % n + int64_t x = mod_pow(base, d); + + if (x == 1 || x == n - 1) + continue; + + bool passed = false; + for(int64_t i = 1; i < s; i++) + { + x = x * x % n; + if (x == n - 1) + { + passed = true; + break; + } + } + if (!passed) + return false; + } + return true; +} + +/// @brief internal function to calculate mod power +/// @param b b +/// @param d d +/// @return mod power result +int64_t PollardsPho::mod_pow(int64_t b, int64_t d) +{ + __int128_t result = 1; + b = b % n; + while(d > 0) + { + if (d % 2 == 1) + result = (result * b) % n; + b = b * b % n; + d /= 2; + } + return result; +} + // === member functions for Factorization === \ No newline at end of file diff --git a/src/factor.h b/src/factor.h index 5def679..928fede 100644 --- a/src/factor.h +++ b/src/factor.h @@ -20,11 +20,13 @@ class PollardsPho int64_t n; int64_t c; int64_t failure = 0; - int64_t polyFuncMod(int64_t x, int64_t c); + int64_t squareMod(int64_t x, int64_t c); int64_t calculateD(int64_t x, int64_t y); void selectC(int64_t& input); int64_t selectX0(); int64_t basicIteration(int64_t &x, int64_t &y); + bool millerRabin(); + int64_t mod_pow(int64_t b, int64_t d); void basicLogging(int64_t &x, int64_t &y, int64_t &d, int64_t &cnt); }; From 68f7d816f2bd3ca4560769dc5df250901bc451ec Mon Sep 17 00:00:00 2001 From: RaphaelRevivor Date: Mon, 29 Sep 2025 21:54:03 +0200 Subject: [PATCH 5/6] Only output prime numbers in the generated factorization vector (#2) --- src/factor.cpp | 115 +++++++++++++++++++++++++++++-------------------- src/factor.h | 35 ++++++--------- src/main.cpp | 12 ++++-- 3 files changed, 91 insertions(+), 71 deletions(-) diff --git a/src/factor.cpp b/src/factor.cpp index 52468fe..9fc37ef 100644 --- a/src/factor.cpp +++ b/src/factor.cpp @@ -2,45 +2,66 @@ using namespace std; -// === member functions for PollardsPho === +// === member functions for Factorization === /// @brief constructor /// @param n the value for fatorization -PollardsPho::PollardsPho(int64_t n) : n(n) +Factorization::Factorization(int64_t n) : n(n) { srand(time(0)); } +vector Factorization::getAllFactors() +{ + vector output = {}; + int64_t tmp = n; + while(tmp != 1) + { + auto factor = getFactor(tmp); + output.emplace_back(factor); + tmp = tmp / factor; + } + return output; +} + /// @brief the main function to do the calculation /// @return result -int64_t PollardsPho::calculate() +int64_t Factorization::getFactor(const int64_t& input) { int64_t d = 1; int64_t cnt = 0; - int64_t x = selectX0(); + int64_t x = selectX0(input); int64_t y = x; // trivial cases - if (n == 1 || n == 2 || n == 3) - return n; - else if (n%2 == 0) + if (input == 1 || input == 2 || input == 3) + return input; + else if (input%2 == 0) + { return 2; + } // check prime numbers - else if (millerRabin()) - return n; + else if (millerRabin(input)) + { + return input; + } - while(d == 1 || d == n) + // must have a factor + while(d == 1 || d == input) { - d = basicIteration(x, y); - if (d == n) + d = pollardsPho(x, y, input); + if (d == input) { failure++; } - - basicLogging(x, y, d, cnt); - + // basicLogging(x, y, d, cnt); cnt++; } + if (!millerRabin(d)) + { + d = getFactor(d); + } + return d; } @@ -48,42 +69,42 @@ int64_t PollardsPho::calculate() /// @param x x /// @param y y /// @return d -int64_t PollardsPho::basicIteration(int64_t &x, int64_t &y) +int64_t Factorization::pollardsPho(int64_t &x, int64_t &y, const int64_t& input) { selectC(c); - x = squareMod(x, c); - y = squareMod(squareMod(y, c), c); - int64_t d = calculateD(x, y); - - return d; + x = squareMod(x, c, input); + y = squareMod(squareMod(y, c, input), c, input); + return calculateD(x, y, input); } /// @brief select the initial x /// @return x -int64_t PollardsPho::selectX0() +int64_t Factorization::selectX0(const int64_t& input) { - return (rand() % (n - 2)) + 2; + + int64_t output = (rand() % (input - 2)) + 2; + return output; } /// @brief function to calculate f(x) = x^2 + c /// @param x x /// @param c c /// @return f(x) -int64_t PollardsPho::squareMod(int64_t x, int64_t c) +int64_t Factorization::squareMod(const int64_t& x, const int64_t& c, const int64_t& input) { - __int128_t output = (x * x + c) % n; + __int128_t output = (x * x + c) % input; return output; } /// @brief funtion to calculate D = gcd(abs(x-y), n) -int64_t PollardsPho::calculateD(int64_t x, int64_t y) +int64_t Factorization::calculateD(const int64_t& x, const int64_t& y, const int64_t& input) { - return gcd(abs(x-y), n); + return gcd(abs(x-y), input); } /// @brief function to select c /// @return c -void PollardsPho::selectC(int64_t& input) +void Factorization::selectC(int64_t& input) { if (failure < 100) input = 1; @@ -101,17 +122,17 @@ void PollardsPho::selectC(int64_t& input) /// @param y y /// @param d d /// @param cnt cnt -void PollardsPho::basicLogging(int64_t &x, int64_t &y, int64_t &d, int64_t &cnt) +void Factorization::basicLogging(int64_t &x, int64_t &y, int64_t &d, int64_t &cnt) { cout << cnt << ":" << endl; - cout << "x, y, d:" << x << "," << y << "," << d << endl; + cout << "x, y, d: " << x << "," << y << "," << d << endl; } /// @brief function to check prime (in the cases of none 1, 2, 3 or even) /// @return bool result -bool PollardsPho::millerRabin() +bool Factorization::millerRabin(const int64_t& input) { - int64_t d = n - 1; + int64_t d = input - 1; int64_t s = 0; while(d % 2 == 0) { @@ -123,20 +144,20 @@ bool PollardsPho::millerRabin() vector bases = {2,3,5,7,11,13,17}; for(const auto& base : bases) { - if (base >= n) + if (base >= input) continue; // calculate x = a^d % n - int64_t x = mod_pow(base, d); + __int128_t x = mod_pow(base, d, input); - if (x == 1 || x == n - 1) + if (x == 1 || x == input - 1) continue; bool passed = false; for(int64_t i = 1; i < s; i++) { - x = x * x % n; - if (x == n - 1) + x = x * x % input; + if (x == input - 1) { passed = true; break; @@ -152,18 +173,18 @@ bool PollardsPho::millerRabin() /// @param b b /// @param d d /// @return mod power result -int64_t PollardsPho::mod_pow(int64_t b, int64_t d) +int64_t Factorization::mod_pow(const int64_t& b, const int64_t& d, const int64_t& input) { __int128_t result = 1; - b = b % n; - while(d > 0) + int64_t base = b; + int64_t dd = d; + base = base % input; + while(dd > 0) { - if (d % 2 == 1) - result = (result * b) % n; - b = b * b % n; - d /= 2; + if (dd % 2 == 1) + result = (result * base) % input; + base = base * base % input; + dd /= 2; } return result; -} - -// === member functions for Factorization === \ No newline at end of file +} \ No newline at end of file diff --git a/src/factor.h b/src/factor.h index 928fede..009d4fa 100644 --- a/src/factor.h +++ b/src/factor.h @@ -9,36 +9,29 @@ #include #include -class PollardsPho +using namespace std; + +class Factorization { public: - PollardsPho(int64_t n); - ~PollardsPho() = default; - int64_t calculate(); + Factorization(int64_t n); + ~Factorization() = default; + vector getAllFactors(); + int64_t getFactor(const int64_t& input); private: int64_t n; int64_t c; int64_t failure = 0; - int64_t squareMod(int64_t x, int64_t c); - int64_t calculateD(int64_t x, int64_t y); + vector factors = {}; + int64_t squareMod(const int64_t& x, const int64_t& c, const int64_t& input); + int64_t calculateD(const int64_t& x, const int64_t& y, const int64_t& input); void selectC(int64_t& input); - int64_t selectX0(); - int64_t basicIteration(int64_t &x, int64_t &y); - bool millerRabin(); - int64_t mod_pow(int64_t b, int64_t d); + int64_t selectX0(const int64_t& input); + int64_t pollardsPho(int64_t &x, int64_t &y, const int64_t& input); + bool millerRabin(const int64_t& input); + int64_t mod_pow(const int64_t& b, const int64_t& d, const int64_t& input); void basicLogging(int64_t &x, int64_t &y, int64_t &d, int64_t &cnt); }; -// class Factorization -// { -// public: -// Factorization(int64_t n) : n(n) -// { -// } -// ~Factorization() = default; -// private: -// int64_t n; -// }; - #endif \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index 4373ab9..f084620 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -15,8 +15,14 @@ int main(int argc, char** argv) // might throw std::invalid_argument or std::out_of_range in case not able to parse int64_t n = stoll(input); - auto pollardsPho = PollardsPho(n); - auto result = pollardsPho.calculate(); + auto factorization = Factorization(n); - cout << "One factor of " << n << " is: " << result << endl; + cout << "Factors of " << n << " are: " << endl; + auto results = factorization.getAllFactors(); + + for(const auto& result : results) + { + cout << result << ","; + } + cout << endl; } \ No newline at end of file From be50887d24363c1c41e75f8009405fa712476d89 Mon Sep 17 00:00:00 2001 From: RaphaelRevivor Date: Mon, 29 Sep 2025 21:54:03 +0200 Subject: [PATCH 6/6] Only output prime numbers in the generated factorization vector (#2) --- src/factor.cpp | 115 +++++++++++++++++++++++++++++-------------------- src/factor.h | 36 ++++++---------- src/main.cpp | 12 ++++-- 3 files changed, 91 insertions(+), 72 deletions(-) diff --git a/src/factor.cpp b/src/factor.cpp index 52468fe..e3db641 100644 --- a/src/factor.cpp +++ b/src/factor.cpp @@ -2,45 +2,66 @@ using namespace std; -// === member functions for PollardsPho === +// === member functions for Factorization === /// @brief constructor /// @param n the value for fatorization -PollardsPho::PollardsPho(int64_t n) : n(n) +Factorization::Factorization(int64_t n) : n(n) { srand(time(0)); } +vector Factorization::getAllFactors() +{ + vector output = {}; + int64_t tmp = n; + while(tmp != 1) + { + auto factor = getFactor(tmp); + output.emplace_back(factor); + tmp = tmp / factor; + } + return output; +} + /// @brief the main function to do the calculation /// @return result -int64_t PollardsPho::calculate() +int64_t Factorization::getFactor(const int64_t& input) { int64_t d = 1; int64_t cnt = 0; - int64_t x = selectX0(); + int64_t x = selectX0(input); int64_t y = x; // trivial cases - if (n == 1 || n == 2 || n == 3) - return n; - else if (n%2 == 0) + if (input == 1 || input == 2 || input == 3) + return input; + else if (input%2 == 0) + { return 2; + } // check prime numbers - else if (millerRabin()) - return n; + else if (millerRabin(input)) + { + return input; + } - while(d == 1 || d == n) + // must have a factor + while(d == 1 || d == input) { - d = basicIteration(x, y); - if (d == n) + d = pollardsPho(x, y, input); + if (d == input) { failure++; } - - basicLogging(x, y, d, cnt); - + // basicLogging(x, y, d, cnt); cnt++; } + if (!millerRabin(d)) + { + d = getFactor(d); + } + return d; } @@ -48,42 +69,42 @@ int64_t PollardsPho::calculate() /// @param x x /// @param y y /// @return d -int64_t PollardsPho::basicIteration(int64_t &x, int64_t &y) +int64_t Factorization::pollardsPho(int64_t &x, int64_t &y, const int64_t& input) { selectC(c); - x = squareMod(x, c); - y = squareMod(squareMod(y, c), c); - int64_t d = calculateD(x, y); - - return d; + x = squareMod(x, c, input); + y = squareMod(squareMod(y, c, input), c, input); + return calculateD(x, y, input); } /// @brief select the initial x /// @return x -int64_t PollardsPho::selectX0() +int64_t Factorization::selectX0(const int64_t& input) { - return (rand() % (n - 2)) + 2; + + int64_t output = (rand() % (input - 2)) + 2; + return output; } /// @brief function to calculate f(x) = x^2 + c /// @param x x /// @param c c /// @return f(x) -int64_t PollardsPho::squareMod(int64_t x, int64_t c) +int64_t Factorization::squareMod(const int64_t& x, const int64_t& c, const int64_t& input) { - __int128_t output = (x * x + c) % n; + __int128_t output = (x * x + c) % input; return output; } /// @brief funtion to calculate D = gcd(abs(x-y), n) -int64_t PollardsPho::calculateD(int64_t x, int64_t y) +int64_t Factorization::calculateD(const int64_t& x, const int64_t& y, const int64_t& input) { - return gcd(abs(x-y), n); + return gcd(abs(x-y), input); } /// @brief function to select c /// @return c -void PollardsPho::selectC(int64_t& input) +void Factorization::selectC(int64_t& input) { if (failure < 100) input = 1; @@ -101,17 +122,17 @@ void PollardsPho::selectC(int64_t& input) /// @param y y /// @param d d /// @param cnt cnt -void PollardsPho::basicLogging(int64_t &x, int64_t &y, int64_t &d, int64_t &cnt) +void Factorization::basicLogging(const int64_t &x, const int64_t &y, const int64_t &d, const int64_t &cnt) { cout << cnt << ":" << endl; - cout << "x, y, d:" << x << "," << y << "," << d << endl; + cout << "x, y, d: " << x << "," << y << "," << d << endl; } /// @brief function to check prime (in the cases of none 1, 2, 3 or even) /// @return bool result -bool PollardsPho::millerRabin() +bool Factorization::millerRabin(const int64_t& input) { - int64_t d = n - 1; + int64_t d = input - 1; int64_t s = 0; while(d % 2 == 0) { @@ -123,20 +144,20 @@ bool PollardsPho::millerRabin() vector bases = {2,3,5,7,11,13,17}; for(const auto& base : bases) { - if (base >= n) + if (base >= input) continue; // calculate x = a^d % n - int64_t x = mod_pow(base, d); + __int128_t x = mod_pow(base, d, input); - if (x == 1 || x == n - 1) + if (x == 1 || x == input - 1) continue; bool passed = false; for(int64_t i = 1; i < s; i++) { - x = x * x % n; - if (x == n - 1) + x = x * x % input; + if (x == input - 1) { passed = true; break; @@ -152,18 +173,18 @@ bool PollardsPho::millerRabin() /// @param b b /// @param d d /// @return mod power result -int64_t PollardsPho::mod_pow(int64_t b, int64_t d) +int64_t Factorization::mod_pow(const int64_t& b, const int64_t& d, const int64_t& input) { __int128_t result = 1; - b = b % n; - while(d > 0) + int64_t base = b; + int64_t dd = d; + base = base % input; + while(dd > 0) { - if (d % 2 == 1) - result = (result * b) % n; - b = b * b % n; - d /= 2; + if (dd % 2 == 1) + result = (result * base) % input; + base = base * base % input; + dd /= 2; } return result; -} - -// === member functions for Factorization === \ No newline at end of file +} \ No newline at end of file diff --git a/src/factor.h b/src/factor.h index 928fede..d1a1497 100644 --- a/src/factor.h +++ b/src/factor.h @@ -9,36 +9,28 @@ #include #include -class PollardsPho +using namespace std; + +class Factorization { public: - PollardsPho(int64_t n); - ~PollardsPho() = default; - int64_t calculate(); + Factorization(int64_t n); + ~Factorization() = default; + vector getAllFactors(); + int64_t getFactor(const int64_t& input); private: int64_t n; int64_t c; int64_t failure = 0; - int64_t squareMod(int64_t x, int64_t c); - int64_t calculateD(int64_t x, int64_t y); + int64_t squareMod(const int64_t& x, const int64_t& c, const int64_t& input); + int64_t calculateD(const int64_t& x, const int64_t& y, const int64_t& input); void selectC(int64_t& input); - int64_t selectX0(); - int64_t basicIteration(int64_t &x, int64_t &y); - bool millerRabin(); - int64_t mod_pow(int64_t b, int64_t d); - void basicLogging(int64_t &x, int64_t &y, int64_t &d, int64_t &cnt); + int64_t selectX0(const int64_t& input); + int64_t pollardsPho(int64_t &x, int64_t &y, const int64_t& input); + bool millerRabin(const int64_t& input); + int64_t mod_pow(const int64_t& b, const int64_t& d, const int64_t& input); + void basicLogging(const int64_t &x, const int64_t &y, const int64_t &d, const int64_t &cnt); }; -// class Factorization -// { -// public: -// Factorization(int64_t n) : n(n) -// { -// } -// ~Factorization() = default; -// private: -// int64_t n; -// }; - #endif \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index 4373ab9..f084620 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -15,8 +15,14 @@ int main(int argc, char** argv) // might throw std::invalid_argument or std::out_of_range in case not able to parse int64_t n = stoll(input); - auto pollardsPho = PollardsPho(n); - auto result = pollardsPho.calculate(); + auto factorization = Factorization(n); - cout << "One factor of " << n << " is: " << result << endl; + cout << "Factors of " << n << " are: " << endl; + auto results = factorization.getAllFactors(); + + for(const auto& result : results) + { + cout << result << ","; + } + cout << endl; } \ No newline at end of file