// 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; }