Main file - Exercise 3

This commit is contained in:
Lisa Pizzo 2025-12-04 11:48:27 +01:00
commit 0ef267c6e0

135
Sheet5/mainEx3.cpp Normal file
View file

@ -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 <iostream>
#include <vector>
#include <chrono>
#include <cmath>
#include <algorithm>
#include <utility>
#include <iomanip>
#include <omp.h>
#include "mayer_primes.h"
using namespace std;
int single_goldbach(int k, const vector<int>& primes, const vector<char>& 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<pair<int,int>> count_goldbach(int n, const vector<int>& primes, const vector<char>& is_prime)
{
vector<pair<int,int>> 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<vector<pair<int,int>>> all_decompositions(int n, const vector<int>& primes, const vector<char>& is_prime)
{
vector<vector<pair<int,int>>> out(n/2 - 1);
#pragma omp parallel for
for (int j = 0; j < (int)out.size(); ++j)
{
int k = 4 + 2*j;
vector<pair<int,int>> 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<char> make_is_prime(int n, const vector<int>& primes)
{
vector<char> is_prime(n + 1, 0);
for (int p : primes)
if (p <= n) is_prime[p] = 1;
return is_prime;
}
int main()
{
vector<int> 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<int> primes = get_primes<int>(n);
auto t1 = chrono::system_clock::now();
chrono::duration<double> gen_time = t1 - t0;
cout << "Generated " << primes.size()
<< " primes in " << gen_time.count() << " s\n";
vector<char> is_prime = make_is_prime(n, primes);
// Count Goldbach decompositions
auto start = chrono::system_clock::now();
vector<pair<int,int>> results = count_goldbach(n, primes, is_prime);
auto end = chrono::system_clock::now();
chrono::duration<double> 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;
}