#include "mylib.h"
#include <fstream>
#include <iostream>
#include <omp.h>
#include <vector>
using namespace std;


int main()
{
    // read vector from file
    vector<size_t> data_vector = {};

    ifstream input_stream("data_1.txt"); 

    size_t line;
    while(input_stream >> line)
    {
        data_vector.push_back(line);
    }
    data_vector.shrink_to_fit();




    // specify loops
    size_t NLOOPS = 10000;



    // ############# Parallelization with openMP #############
    // calculate arithmetic mean, geometric mean and harmonic mean
    double am_omp, gm_omp, hm_omp;

    double tstart = omp_get_wtime();

    for (size_t i = 0; i < NLOOPS; ++i)
        means_omp(data_vector, am_omp, gm_omp, hm_omp);

    double t_means_omp = (omp_get_wtime() - tstart)/NLOOPS;

    // calculate minimum and maximum
    size_t min, max;

    tstart = omp_get_wtime();

    for (size_t i = 0; i < NLOOPS; ++i)
        minmax_omp(data_vector, min, max);

    double t_minmax_omp = (omp_get_wtime() - tstart)/NLOOPS;



    


    // ############# Parallelization with C++ algorithms #############
    // calculate arithmetic mean, geometric mean and harmonic mean
    double am_cpp, gm_cpp, hm_cpp;

    tstart = omp_get_wtime();

    for (size_t i = 0; i < NLOOPS; ++i)
        means_cpp(data_vector, am_cpp, gm_cpp, hm_cpp);

    double t_means_cpp = (omp_get_wtime() - tstart)/NLOOPS;

    // calculate minimum and maximum
    size_t min_cpp, max_cpp;

    tstart = omp_get_wtime();

    for (size_t i = 0; i < NLOOPS; ++i)
        minmax_cpp(data_vector, min_cpp, max_cpp);

    double t_minmax_cpp = (omp_get_wtime() - tstart)/NLOOPS;





    // print results
    cout << "####### OpenMP #######" << endl;
    cout << "minimum: " << min << endl;
    cout << "maximum: " << max << endl;
    cout << "duration: " << t_minmax_omp << endl << endl;

    cout << "arithmetic mean: " << am_omp << endl;
    cout << "geometric mean: " << gm_omp << endl;
    cout << "harmonic mean: " << hm_omp << endl;
    cout << "duration: " << t_means_omp << endl << endl;


    cout << "####### C++ #######" << endl;
    cout << "minimum: " << min_cpp << endl;
    cout << "maximum: " << max_cpp << endl;
    cout << "duration: " << t_minmax_cpp << endl << endl;

    cout << "arithmetic mean: " << am_cpp << endl;
    cout << "geometric mean: " << gm_cpp << endl;
    cout << "harmonic mean: " << hm_cpp << endl;
    cout << "duration: " << t_means_cpp << endl << endl;



    // ####### OpenMP #######
    // minimum: 1
    // maximum: 1000
    // duration: 3.52086e-06

    // arithmetic mean: 498.184
    // geometric mean: 364.412
    // harmonic mean: 95.6857
    // duration: 5.90171e-06

    // ####### C++ #######
    // minimum: 1
    // maximum: 1000
    // duration: 1.76816e-05

    // arithmetic mean: 498.184
    // geometric mean: 364.412
    // harmonic mean: 95.6857
    // duration: 2.35728e-05

    // --> the openMP variant is faster in both cases


    return 0;
}
