/* -*- Mode: c -*-

  $Id: Allgatherv_int_xover,v 1.2 1999/07/20 15:25:43 wgeorge Exp $

   This script tests the crossover from the short message algorithm
   to the long message algorithm in MPI_Allgatherv.  

   This test assumes the crossover value (IMPI_COLL_CROSSOVER) is
   set at the default 1024 bytes (256 MPI_INTs).

   The outer loop increments the size of the largest message
   from 254 to 258 MPI_INTs. All other messages are of size
   r+2 where r is the rank.
   
   For each iteration it fills each rank's send buffer with a
   set of values unique to that rank.  Each rank gets a different
   number of values.  MPI_Allgatherv is called, and each rank verifies
   that the content of the receive buffer is correct.
   
*/

{
  int sendbuf[260]; /* max message size */

  /* SUM i= 0 to 99 of (i) = (99)(100)/2 = 4950 */
  /*  200 (2 extra for each rank)           200 */
  /*  260 for message at rank 0             260 */
  /*                                      ----- */
  /*                                       5410 */
  int recvbuf[5410]; /* max receive buffer needed (for 100 proc test). */
  int i;
  int num_errors;
  int nprocs;
  int my_rank;
  int irank; 
  int recvcounts[100];
  int displs[100];
  int pos;
  int maxCount;
  int count;
  int total_errors;
  int maxErrsReported;
  

  MPI_Comm_size(MPI_COMM_WORLD, nprocs);
  maxErrsReported = 10;

  if (nprocs > 100) {
    report_info (
                 "There are more than 100 processes; this test cannot be run.");
    report_indeterminate ( "Unable to determine test success or failure.");
    return;
  }

  MPI_Comm_rank(MPI_COMM_WORLD, my_rank);
  maxErrsReported = 10;

  total_errors = 0;

  /* From just below the crossover to just above it. */
  for (maxCount=254; maxCount<=258; maxCount=maxCount+1 ) {
    num_errors = 0;
    report_info("Allgatherv int xover: message size: %.0f.", maxCount);
    for (irank = 0; irank < nprocs; irank = irank + 1) {
      if (irank == 0) {
	recvcounts[irank] = maxCount;
      } else {
	recvcounts[irank] = 2 + irank;
      }

      if (irank == 0) {
	displs[irank] = 0;
      } else {
	displs[irank] = displs[irank-1] + recvcounts[irank-1];
      }
    }

    if (my_rank == 0) {
      for (i = 0; i < maxCount; i = i+1) {
	sendbuf[i] = (i+1) * (my_rank+1);
      }
    } else {
      for (i = 0; i < 2+my_rank; i = i+1) {
	sendbuf[i] = (i+1) * (my_rank+1);
      }
    }
    for (i = 0; i < 5410; i = i + 1) {
      recvbuf[i] = -1;
    }

    if (my_rank == 0) {
      MPI_Allgatherv (sendbuf, maxCount, MPI_INT, recvbuf, recvcounts, displs, 
		   MPI_INT, MPI_COMM_WORLD);

    } else {
      MPI_Allgatherv (sendbuf, 2+my_rank, MPI_INT, recvbuf, recvcounts, displs, 
		   MPI_INT, MPI_COMM_WORLD);
    }

    pos = 0;
    for (irank = 0; irank < nprocs; irank = irank+1) {
      count = recvcounts[irank];
      for (i = 0; i < count; i=i+1) {
	if (recvbuf[displs[irank] + i] != (i+1) * (irank+1)) {
	  if (num_errors < maxErrsReported) {
	    report_error ("Allgatherv int xover: maxCount:%.0f, Expected %.0f, received %.0f.", 
			  maxCount,
			  ((i+1) * (irank+1)), 
			  recvbuf[displs[irank] + i]);
	    if (num_errors == (maxErrsReported-1)) {
	      report_info("Allgatherv int xover: skipping further errors");
	    }
	  }
	  num_errors = num_errors + 1;
	}
      }
    }
    if (num_errors > 0) {
      report_info("Allgatherv int xover: %.0f errors", num_errors);
    }
    total_errors = total_errors + num_errors;

  }
  

  if (total_errors == 0) {
    report_pass ("Allgatherv int xover: Test succeeded in rank %.0f; no errors detected.", 
                 my_rank);
  } else {
    report_fail ( "Allgatherv int xover: Test failed in rank %.0f with %.0f errors.", my_rank, total_errors);
  }

  return;
}