#include <mpi.h>
#include <iostream>
#include <cmath>
#include <ctime>
#include <iomanip>

using namespace std

double cpu_time(void);
int prime_number(int n, int id, int numtasks);

int main(int argc, char** argv) {
    int rank, size, n_factor = 2, n_lo = 1, n_hi = 100;
    double start_time, end_time;
    int n, primes, primes_part;

    MPI_Init(&argc, &argv);
    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
    MPI_Comm_size(MPI_COMM_WORLD, &size);

    if (rank == 0) {
        cout << "Pomiar ilosci liczb pierwszych w powiekszajacych sie " << n_factor << "-krotnie podprzedzialach przedzialu [" << n_lo << " , " << n_hi << " ]" << endl;
        cout << "\n";
        cout << "    N_max        Ilosc liczb pierwszych        Czas " << endl;
        cout << "\n";
    }

    n = n_lo;

    while (n <= n_hi) {
        start_time = MPI_Wtime();

        MPI_Bcast(&n, 1, MPI_INT, 0, MPI_COMM_WORLD);
        primes_part = prime_number(n, rank, size);

        MPI_Reduce(&primes_part, &primes, 1, MPI_INT, MPI_SUM, 0, MPI_COMM_WORLD);

        end_time = MPI_Wtime();

        if (rank == 0) {
            cout << "    " << setw(3) << n
                 << "    " << setw(18) << primes
                 << "    " << setw(18) << end_time - start_time << endl;
        }

        n = n * n_factor;
    }

    MPI_Finalize();
    return 0;
}

double cpu_time() {
    return (double)clock() / (double)CLOCKS_PER_SEC;
}

int prime_number(int n, int id, int numtasks) {
    int prime;
    int total = 0;

    for (int i = id + 2; i <= n; i += numtasks) {
        prime = 1;
        for (int j = 2; j < i; j++) {
            if ((i % j) == 0) {
                prime = 0;
                break;
            }
        }
        total = total + prime;
    }
    return total;
}
