#include <iostream>
#include <mpi.h>
#include <pthread.h>

void* myApp(void* x) {
    int* k = ((int*)x);
    switch (k[0]) {
        case 0:
            pthread_exit((void*)(k[1] + k[2]));
            break;
        case 1:
            pthread_exit((void*)(k[1] * k[2]));
            break;
        case 2:
            pthread_exit((void*)(k[1]-k[2]));
            break;
    }
    return NULL;
}

int main(int argc, char* argv[]) {
    #define N 9

    int array[N];
    int i;
    int id;
    int ierr;
    int master = 0;
    int p;
    static int r8_pi = 3;
    MPI_Status status;
    int Rt, R;
    int S = 0;

    ierr = MPI_Init(&argc, &argv);
    MPI_Comm_size(MPI_COMM_WORLD, &p);
    MPI_Comm_rank(MPI_COMM_WORLD, &id);

    if (id == 0) {
        for (i = 0; i < N; i++) {
            array[i] = i * r8_pi;
        }
    }

    MPI_Bcast(array, N, MPI_INT, master, MPI_COMM_WORLD);
    int x[3];
    pthread_t th;

    for (int i = id; i < N - 2; i += 3) {
        x[0] = i % 3;
        if (i % 3 != 0)
            x[i % 3] = array[i];
        if ((i + 1) % 3 != 0)
            x[(i + 1) % 3] = array[i + 1];
        if ((i + 2) % 3 != 0)
            x[(i + 2) % 3] = array[i + 2];

        pthread_create(&th, NULL, myApp, (void *)x);
        pthread_join(th, (void **)&Rt);
        S += Rt;
    }

    if (id != 0) {
        printf("P= %d, S= %d\n", id, S);
        MPI_Send(&S, 1, MPI_INT, master, 1, MPI_COMM_WORLD);
    } else {
        R = S;
        printf("P= %d, S= %d\n", id, S);
        for (i = 1; i < p; i++) {
            MPI_Recv(&S, 1, MPI_INT, MPI_ANY_SOURCE, 1, MPI_COMM_WORLD, &status);
            R += S;
        }
    }

    system("pause");
    MPI_Finalize();
    return 0;

    #undef N
}

