//HOW TO RUN IT ON MY TERMINAL (MAC)
//export PATH="/opt/homebrew/opt/llvm/bin:$PATH"
//export CPPFLAGS="-I/opt/homebrew/opt/libomp/include"
//export LDFLAGS="-L/opt/homebrew/opt/libomp/lib"
//clang++ -std=c++17 -O2 -Xpreprocessor -fopenmp $CPPFLAGS mainEx2.cpp $LDFLAGS -lomp -o Ex2
//./Ex2

#include <iostream>
#include <fstream>
#include <vector>
#include <cmath>
#include <algorithm>
#include <omp.h> //for parallelization functions 

using namespace std;

// compute arithmetic, geometric, harmonic means (safe geometric mean)
void computeMeansVector(const vector<int> &v, double &arith, double &geom, double &harm) {
    int n = v.size(); 
    double sum = 0.0, logSum = 0.0, recSum = 0.0;

    for (int x : v) { 
        sum += x; 
        logSum += log(x);       // accumulate logarithms instead of multiplying
        recSum += 1.0 / x; 
    }
    arith = sum / n;
    geom  = exp(logSum / n);    // geometric mean using exponent of average log
    harm  = n / recSum;
}

// compute standard deviation
double computeStdDev(const vector<int> &v, double mean) {
    double sumSq = 0.0;
    for (int x : v) {
        sumSq += (x - mean) * (x - mean);
    }
    return sqrt(sumSq / v.size());
}

int main() {
    vector<int> v;
    ifstream fin("data_1.txt"); //opens data for reading 
    int x; 
    while (fin >> x) {
        v.push_back(x);
    }
    double t_start = omp_get_wtime();

    // OpenMP threads check
    #pragma omp parallel
    {
        #pragma omp single
        cout << "Using " << omp_get_num_threads() 
            << " OpenMP threads\n";
    }

    int minVal = *min_element(v.begin(), v.end());
    int maxVal = *max_element(v.begin(), v.end());

    double arith, geom, harm;
    computeMeansVector(v, arith, geom, harm);

    double stddev = computeStdDev(v, arith);

    ofstream fout("out_1.txt");
    fout << "Min: " << minVal << "\nMax: " << maxVal
         << "\nArithmetic mean: " << arith
         << "\nGeometric mean: " << geom
         << "\nHarmonic mean: " << harm
         << "\nStandard deviation: " << stddev << "\n";

    cout << "Min: " << minVal << "\nMax: " << maxVal
         << "\nArithmetic mean: " << arith
         << "\nGeometric mean: " << geom
         << "\nHarmonic mean: " << harm
         << "\nStandard deviation: " << stddev << endl;

    cout << "Elapsed time (s): " << omp_get_wtime() - t_start << endl;
}
