/****************************************************************************
**  SCALASCA    http://www.scalasca.org/                                   **
*****************************************************************************
**  Copyright (c) 1998-2012                                                **
**  Forschungszentrum Juelich GmbH, Juelich Supercomputing Centre          **
**                                                                         **
**  Copyright (c) 2003-2008                                                **
**  University of Tennessee, Innovative Computing Laboratory               **
**                                                                         **
**  See the file COPYRIGHT in the package base directory for details       **
****************************************************************************/

#include "elg_defs.h"
#include "elg_error.h"
#include "elg_topol.h"
#include "esd_def.h"

#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>


#define F_elg_cart_create_U F_ELG_CART_CREATE
#define F_elg_cart_create_L f_elg_cart_create
#define F_elg_cart_coords_U F_ELG_CART_COORDS
#define F_elg_cart_coords_L f_elg_cart_coords

#include "epk_fwrapper_def.h"


/************* GLOBAL VARIABLES  ************/

elg_ui4 ndims = 0;
elg_ui4 topid = ELG_NO_ID;
elg_ui4 cid = ELG_NO_ID;

/*******************************************/

void elg_cart_create   ( elg_ui4 dim0, 
			 elg_ui4 dim1, 
			 elg_ui4 dim2,
			 elg_ui1 period0, 
			 elg_ui1 period1, 
			 elg_ui1 period2 ) 
{
  elg_ui4  *dimv, *temp_dimv; 
  elg_ui1  *periodv, *temp_periodv; 
  int      i;

  /* allocate space for temporary arrays to store 
     the required parameters */
  temp_dimv = calloc(3, sizeof(elg_ui4));
  if ( temp_dimv == NULL ) 
    elg_error();
  
  temp_periodv = calloc(3, sizeof(elg_ui1));
  if ( temp_periodv == NULL ) 
    elg_error();
 
  /* check the parameters and calculate ndims */
  if ( dim0 == 0 ) 
    elg_error_msg("Incorrect dimension specification");
  else if ( dim0 > 0 && dim1 == 0 && dim2 == 0 )
    {
      ndims = 1;
      temp_dimv[0] = dim0; 
      temp_periodv[0] = period0;      
    }
  else if ( dim0 > 0 && dim1 > 0 && dim2 == 0 ) 
    {
      ndims = 2;
      temp_dimv[0] = dim0; 
      temp_dimv[1] = dim1; 
      if ( period0 == 0 ) temp_periodv[0] = ELG_FALSE; else temp_periodv[0] = ELG_TRUE;
      if ( period1 == 0 ) temp_periodv[1] = ELG_FALSE; else temp_periodv[1] = ELG_TRUE;
    }
  else
    {
      ndims = 3;
      temp_dimv[0] = dim0; 
      temp_dimv[1] = dim1; 
      temp_dimv[2] = dim2; 
      if ( period0 == 0 ) temp_periodv[0] = ELG_FALSE; else temp_periodv[0] = ELG_TRUE;
      if ( period1 == 0 ) temp_periodv[1] = ELG_FALSE; else temp_periodv[1] = ELG_TRUE;
      if ( period2 == 0 ) temp_periodv[2] = ELG_FALSE; else temp_periodv[2] = ELG_TRUE;
    }
  
  /* allocate space for dimv and periodv depending on ndims */
  dimv = calloc(ndims, sizeof(elg_ui4));
  if ( dimv == NULL ) 
    elg_error();
  
  periodv = calloc(ndims, sizeof(elg_ui1));
  if ( periodv == NULL ) 
    elg_error();

  /* fill the dimv and periodv arrays */
  for ( i = 0 ; i < ndims ; i++ ) 
    {
      dimv[i] = temp_dimv[i];
      periodv[i] = temp_periodv[i];
    }
  
  topid = esd_def_cart(cid, ndims, dimv, periodv);

  /* free up the space used by arrays */
  free(dimv); free(temp_dimv);
  free(periodv); free(temp_periodv);
}

void elg_cart_coords    ( elg_ui4 coord0, 
			  elg_ui4 coord1, 
			  elg_ui4 coord2 ) 
{
  elg_ui4 *coordv;
  
  /* allocate space for coordv */
  coordv = calloc(ndims, sizeof(elg_ui4));
  if ( coordv == NULL ) 
    elg_error();

  /* fill in coordv  */
  if ( ndims == 0 ) 
    elg_error_msg("Incorrect topology dimension specification");
  else if ( ndims == 1 ) 
    coordv[0] = coord0;
  else if ( ndims == 2 ) 
    {
      coordv[0] = coord0; coordv[1] = coord1;
    }
  else
    {
      coordv[0] = coord0; coordv[1] = coord1; coordv[2] = coord2;
    }

  esd_def_coords(topid, ndims, coordv);

  /* free up the space used by array */
  free(coordv);
}

#define FSUB FSUB1
#include "elg_ftopol.c"

#undef FSUB
#define FSUB FSUB2
#include "elg_ftopol.c"

#undef FSUB
#define FSUB FSUB3
#include "elg_ftopol.c"

#undef FSUB
#define FSUB FSUB4
#include "elg_ftopol.c"
