From 0ef267c6e018ee9f7996898d4e93b118c27dcdd9 Mon Sep 17 00:00:00 2001 From: "lisa.pizzo" Date: Thu, 4 Dec 2025 11:48:27 +0100 Subject: [PATCH] Main file - Exercise 3 --- Sheet5/mainEx3.cpp | 135 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 135 insertions(+) create mode 100644 Sheet5/mainEx3.cpp diff --git a/Sheet5/mainEx3.cpp b/Sheet5/mainEx3.cpp new file mode 100644 index 0000000..0c8a9f6 --- /dev/null +++ b/Sheet5/mainEx3.cpp @@ -0,0 +1,135 @@ +// HOW TO COMPILE ON MAC +// export LDFLAGS="-L/opt/homebrew/opt/libomp/lib" +// export CPPFLAGS="-I/opt/homebrew/opt/libomp/include" +// clang++ -std=c++17 -O3 -Xpreprocessor -fopenmp $CPPFLAGS MainEx3.cpp -L/opt/homebrew/opt/libomp/lib -lomp -o Ex3 +// ./Ex3 + +#include +#include +#include +#include +#include +#include +#include +#include +#include "mayer_primes.h" + +using namespace std; + +int single_goldbach(int k, const vector& primes, const vector& is_prime) +{ + int count = 0; + + #pragma omp parallel for reduction(+:count) + for (size_t i = 0; i < primes.size(); ++i) + { + int p = primes[i]; + if (p > k / 2) continue; + int q = k - p; + if (q >= 0 && q < (int)is_prime.size() && is_prime[q]) + count += 1; + } + return count; +} + +vector> count_goldbach(int n, const vector& primes, const vector& is_prime) +{ + vector> results(n/2 - 1); // exact size + + #pragma omp parallel for + for (int j = 0; j < (int)results.size(); ++j) + { + int k = 4 + 2*j; + int c = single_goldbach(k, primes, is_prime); + results[j] = {k, c}; + } + return results; +} + +vector>> all_decompositions(int n, const vector& primes, const vector& is_prime) +{ + vector>> out(n/2 - 1); + + #pragma omp parallel for + for (int j = 0; j < (int)out.size(); ++j) + { + int k = 4 + 2*j; + vector> local; + + for (size_t i = 0; i < primes.size(); ++i) + { + int p = primes[i]; + if (p > k / 2) break; + int q = k - p; + if (q >= 0 && q < (int)is_prime.size() && is_prime[q]) + local.push_back({p, q}); + } + + out[j] = std::move(local); + } + return out; +} + +vector make_is_prime(int n, const vector& primes) +{ + vector is_prime(n + 1, 0); + for (int p : primes) + if (p <= n) is_prime[p] = 1; + return is_prime; +} + +int main() +{ + vector test_ns = {10000, 100000, 400000}; + + for (int n : test_ns) + { + cout << "Computing Goldbach up to n = " << n << "\n"; + + // CHECKS to see if I'm actually paralellizing + #pragma omp parallel + { + #pragma omp single + cout << "Using " << omp_get_num_threads() + << " OpenMP threads\n"; + } + + // Generate primes + auto t0 = chrono::system_clock::now(); + vector primes = get_primes(n); + auto t1 = chrono::system_clock::now(); + chrono::duration gen_time = t1 - t0; + + cout << "Generated " << primes.size() + << " primes in " << gen_time.count() << " s\n"; + + vector is_prime = make_is_prime(n, primes); + + // Count Goldbach decompositions + auto start = chrono::system_clock::now(); + vector> results = count_goldbach(n, primes, is_prime); + auto end = chrono::system_clock::now(); + chrono::duration elapsed = end - start; + + // Find k with maximum decompositions + int max_k = 0; + int max_count = 0; + + for (auto &pr : results) + { + if (pr.second > max_count) + { + max_k = pr.first; + max_count = pr.second; + } + } + + cout << "Max decompositions: k = " << max_k + << " with " << max_count << " decompositions\n"; + + cout << "Time to count decompositions: " + << elapsed.count() << " s\n"; + } + + return 0; +}