#include <iostream>
#include <cstdlib>
#include <string>
#include <vector>
#include <omp.h>

#define NUM_ACCOUNTS 2
#define NUM_TRANSACTION 10
#define INIT_BALANCE 0

int main(int argc, char *argv[])
{
    int i;
    double start_time, final_time;

    /* Balance of account numbers 0 - (NUM_ACCOUNTS - 1) */
    std::vector<long> balance(NUM_ACCOUNTS, INIT_BALANCE);
    std::vector<long> balance_ser(NUM_ACCOUNTS, INIT_BALANCE);

    int trans[] = {10, 20, 30, -40, -50, 80, -10, -50, 100, 90};
    std::vector<int> transaction(trans, trans + NUM_TRANSACTION);

    /*
     * This part of the code is run in serial to get the correct result.
     * We will use this result to check with our multithreaded solution
     * even indexed (including 0) transaction goes to account 0,
     * odd indexed transaction goes to account 1
     */
    for(i=0; i < NUM_TRANSACTION ; i++) {
        balance_ser[i % 2] += transaction[i];
    }

    start_time = omp_get_wtime();

    /* Parallelized version */
    /*
     * Parallelized account balance update part,
     * we used 'omp atomic' to upadate, it is to avoid race condition
     */
    #pragma omp parallel for
    for(i=0; i < NUM_TRANSACTION ; i++) {
        #pragma omp atomic
        balance[i % 2] += transaction[i];
    }

    final_time = omp_get_wtime() - start_time;
    std::cout.precision(10);
    std::cout << "Total time using omp atomic: " << std::fixed << final_time << std::endl;
    std::cout << "Final account balance is following..." << std::endl;

    for( i=0; i < NUM_ACCOUNTS; i++) {
        std::cout << "Account No. = " << i <<", actual balance = " <<
            balance[i] << " correct balance should be = " <<
            balance_ser[i] << std::endl;
    }

    return 0;
}
