/* Copyright 1995 Jonathan C. Hardwick */

#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
#include <mpi.h>
#include "main.h"
#include "globals.h"
#include "utils.h"


static double mtimeStart;


int 
space_for (int nelt, int nproc)
{
  return (nelt + nproc - 1) / nproc;
}


void 
proc_and_offset (int index, int nelt, int nproc, 
		 int *pproc, int *poffset)
{
  int space = space_for (nelt, nproc);
  int proc  = index / space;
  
  *poffset = index - (proc * space);
  *pproc   = proc;
}


int 
first_on (int proc, int nelt, int nproc)
{
  return (proc * space_for (nelt, nproc));
}


int 
nelt_on_proc (int proc, int nelt, int nproc)
{
  int space	= space_for (nelt, nproc);
  int remaining	= nelt - first_on (proc, nelt, nproc);
  int result;
  
  if (remaining > space) {
    result = space;
  } else {
    if (remaining > 0) {
      result = remaining;
    } else {
      result = 0;
    }
  }
  return result;
}


double *
malloc_double (int ndouble)
{
  double *result;

  if (ndouble == 0) {
    ndouble = 1;
  }

  result = (double *) malloc (ndouble * sizeof(double));

  if (result == NULL) {
    printf ("%d: Couldn't allocate block of size %d bytes\n",
	    grnkWorld, ndouble * (int) sizeof(double));
    MPI_Abort (MPI_COMM_WORLD, 2);
  }
  return result;
}


void
start_logging (void)
{
#ifdef MPILOG
  MPE_Init_log ();
  MPE_Describe_state (PARTN_START, PARTN_END, "Partn",
		      "orange:hlines2"); 
  MPE_Describe_state (COMM_START, COMM_END, "Comm",
		      "green:dllines2");
  MPE_Describe_state (SERIAL_START, SERIAL_END, "Solo",
		      "yellow:vlines3");
  MPE_Describe_state (ASSIGN_START, ASSIGN_END, "Sync",
		      "black:drlines2");
  #ifdef STEAL
    MPE_Describe_state (SEND_START, SEND_END, "Send",
		        "red:vlines2"); 
    MPE_Describe_state (RECV_START, RECV_END, "Recv",
		        "blue:drlines3");
  #endif
  #ifdef OLDCODE
  MPE_Describe_state (GATHER_START, GATHER_END, "Gather",
		      "yellow:vlines2"); 
    MPE_Describe_state (PIVOT_START, PIVOT_END, "Pivot",
		        "red:drlines2");
    MPE_Describe_state (ADD_START, ADD_END, "Add",
		        "yellow:vlines2");
  #endif
#endif
  MPI_Barrier (gcomWorld);
  if (grnkWorld == 0) {
    mtimeStart = MPI_Wtime ();
  }
}


void
stop_logging (int seed)
{
  double timeStop;
#ifdef MPILOG
  char name[20];
#endif
  
  MPI_Barrier (gcomWorld);
  if (grnkWorld == 0) {
    timeStop = MPI_Wtime ();
    printf ("%g\n", timeStop - mtimeStart);
  }

#ifdef MPILOG
  #ifdef TEAMS
    sprintf (name, "q5teams.%02d.log", seed);
  #elif STEAL
    sprintf (name, "q5steal.%02d.log", seed);
  #elif PIVOT
    sprintf (name, "q5pivot.%02d.log", seed);
  #else /* NAIVE */
    sprintf (name, "q5naive.%02d.log", seed);
  #endif
  MPE_Finish_log (name);
#endif /* MPILOG */
}


void 
ckp (char *str)
{
  printf ("%d got to %s\n", grnkWorld, str);
}
