/*
** User-defined reduce function to check a sorted list
** This one uses the pre-defined MPI_2INT type. This
** works under the assumption that MPI does the reduction
** from reight to left, which may or may not be true.
** Copyright Rolf Riesen 2008
**
*/
#include <stdio.h>
#include <mpi.h>

#define TRUE	(1)
#define FALSE	(0)
#define ELTS	(3) /* # elements in data structure */


/*
** Local functions
*/
void my_func(void *invec, void *inoutvec, int *len, MPI_Datatype *dt);


/*
** Globals
*/
int my_rank, nproc;



int
main(int argc, char *argv[])
{

int my_value[2];
int result[2];
int root;
int count;
MPI_Op my_op;



    MPI_Init(&argc, &argv);
    MPI_Comm_size(MPI_COMM_WORLD, &nproc);
    MPI_Comm_rank(MPI_COMM_WORLD, &my_rank);

    /* Each node contributes its own node number */
    my_value[0]= my_rank;
    my_value[1]= FALSE;

    #ifdef DEBUG
    if (my_rank == (nproc - 1))   {
	my_value[0]= 0;
    }
    #endif /* DEBUG */

    root= 0;
    count= 1;

    MPI_Op_create(my_func, FALSE, &my_op);


    /* Do the reduction */
    MPI_Reduce(&my_value, &result, count, MPI_2INT, my_op, root,
            MPI_COMM_WORLD);

    if (my_rank == root)   {
	printf("[%3d] root received val %d, sorted %d\n",
	    my_rank, result[0], result[1]);
    }

    MPI_Op_free(&my_op);
    MPI_Finalize();
    return 0;

}  /* end of main() */



void
my_func(void *invec, void *inoutvec, int *len, MPI_Datatype *dt)
{

int *left, *right;
int *out;


    left= (int *)invec;
    right= (int *)inoutvec;
    out= (int *)inoutvec;

    if (left[1] || right[1])   {
	/* We're not sorted */
	out[1]= TRUE;
	printf("[%3d] Not sorted (from flag)\n", my_rank);
	return;
    }

    if (left[0]<= right[0])   {
	out[0]= left[0];
    }   else   {
	/* We're not sorted */
	out[1]= TRUE;
	printf("[%3d] Not sorted (from values)\n", my_rank);
    }

    printf("my_func() rank %d, val %d, sorted %d\n", my_rank, out[0], out[1]);

}  /* end of my_func() */
