/*--------------------------------------------------
  rsdpa_mpicopy.cpp
--------------------------------------------------*/

#include <rsdpa_mpicopy.h>
void rMpiCopy::copy(rParameter& param)
{
  if (rMpiSt::iam == 0) {
    Cigebs2d(rMpiSt::ictxt,"All"," ",1,1,(char*)&param.maxIteration,1);
  }
  else {
    Cigebr2d(rMpiSt::ictxt,"All"," ",1,1,(char*)&param.maxIteration,1,0,0);
  }
  double array[9];
  if (rMpiSt::iam == 0) {
    array[0] = param.epsilonStar;
    array[1] = param.lambdaStar;
    array[2] = param.omegaStar;
    array[3] = param.lowerBound;
    array[4] = param.upperBound;
    array[5] = param.betaStar;
    array[6] = param.betaBar;
    array[7] = param.gammaStar;
    array[8] = param.epsilonDash;
    Cdgebs2d(rMpiSt::ictxt,"All"," ",9,1,(char*)array,9);
  }
  else {
    Cdgebr2d(rMpiSt::ictxt,"All"," ",9,1,(char*)array,9,0,0);
    param.epsilonStar  = array[0];
    param.lambdaStar   = array[1];
    param.omegaStar    = array[2];
    param.lowerBound   = array[3];
    param.upperBound   = array[4];
    param.betaStar     = array[5];
    param.betaBar      = array[6];
    param.gammaStar    = array[7];
    param.epsilonDash  = array[8];
  }
}

void rMpiCopy::copy(int& m, int& n, int*& blockStruct)
{
  int array[2];
  if (rMpiSt::iam == 0) {
    array[0] = m;
    array[1] = n;
    Cigebs2d(rMpiSt::ictxt,"All"," ",2,1,(char*)array,2);
    Cigebs2d(rMpiSt::ictxt,"All"," ",n,1,(char*)blockStruct,n);
  }
  else {
    Cigebr2d(rMpiSt::ictxt,"All"," ",2,1,(char*)array,2,0,0);
    m = array[0];
    n = array[1];
    blockStruct = NULL;
    blockStruct = new int[n];
    if (blockStruct == NULL) {
      rError("memory exhausted in iam = " << rMpiSt::iam);
    }
    Cigebr2d(rMpiSt::ictxt,"All"," ",n,1,(char*)blockStruct,n,0,0);
  }
}

void rMpiCopy::copy(rBlockSparseMatrix& C,int nBlock,
		    int* blockStruct)
{
  if (rMpiSt::iam != 0) {
    C.initialize(nBlock,blockStruct);
  }
  for (int l=0; l<nBlock; ++l) {
    rMpiCopy::copy(C.ele[l],blockStruct[l]);
  }
}

void rMpiCopy::copy(rSparseMatrix& C, int size)
{
  // この状態は Sparse か Diagonal だけでいいはず。
  int array[3];
  if (rMpiSt::iam == 0) {
    array[0] = C.NonZeroNumber;
    array[1] = C.NonZeroCount;
    array[2] = C.NonZeroEffect;

    #if 0
    cout << "C.NonZeroNumber " << C.NonZeroNumber << endl;
    cout << "C.NonZeroCount  " << C.NonZeroCount << endl;
    cout << "C.NonZeroEffect " << C.NonZeroEffect << endl;
    #endif
    
    Cigebs2d(rMpiSt::ictxt,"All"," ",3,1,(char*)array,3);
    if (size > 0) {
      Cigebs2d(rMpiSt::ictxt,"All"," ",C.NonZeroCount,1,
	       (char*)C.row_index,C.NonZeroCount);
      Cigebs2d(rMpiSt::ictxt,"All"," ",C.NonZeroCount,1,
	       (char*)C.column_index,C.NonZeroCount);
      Cdgebs2d(rMpiSt::ictxt,"All"," ",C.NonZeroCount,1,
	       (char*)C.sp_ele,C.NonZeroCount);
    }
    else { // size < 0
      Cdgebs2d(rMpiSt::ictxt,"All"," ",-size,1,
	       (char*)C.di_ele,-size);
    }
  }
  else { // iam != 0
    Cigebr2d(rMpiSt::ictxt,"All"," ",3,1,(char*)array,3,0,0);
    C.NonZeroNumber = array[0];
    C.NonZeroCount  = array[1];
    C.NonZeroEffect = array[2];
    
    #if 0
    cout << "C.NonZeroNumber " << C.NonZeroNumber << endl;
    cout << "C.NonZeroCount  " << C.NonZeroCount << endl;
    cout << "C.NonZeroEffect " << C.NonZeroEffect << endl;
    #endif

    C.de_ele = NULL;
    C.row_index = C.column_index = NULL;
    C.sp_ele = NULL;
    C.di_ele = NULL;

    if (size > 0) {
      C.row_index = new int[C.NonZeroCount];
      if (C.row_index == NULL) {
	rMessage("memory exhausted");
      }
      C.column_index = new int[C.NonZeroCount];
      if (C.column_index == NULL) {
	rMessage("memory exhausted");
      }
      C.sp_ele = new double[C.NonZeroCount];
      if (C.sp_ele == NULL) {
	rMessage("memory exhausted");
      }
      Cigebr2d(rMpiSt::ictxt,"All"," ",C.NonZeroCount,1,
	       (char*)C.row_index,C.NonZeroCount,0,0);
      Cigebr2d(rMpiSt::ictxt,"All"," ",C.NonZeroCount,1,
	       (char*)C.column_index,C.NonZeroCount,0,0);
      Cdgebr2d(rMpiSt::ictxt,"All"," ",C.NonZeroCount,1,
	       (char*)C.sp_ele,C.NonZeroCount,0,0);
      C.nRow = C.nCol = size;
      C.Sp_De_Di = rSparseMatrix::SPARSE;
    }
    else { // size < 0
      C.di_ele = new double[-size];
      if (C.di_ele == NULL) {
	rMessage("memory exhausted");
      }
      Cdgebr2d(rMpiSt::ictxt,"All"," ",-size,1,
	       (char*)C.di_ele,-size,0,0);
      C.nRow = C.nCol = -size;
      C.Sp_De_Di = rSparseMatrix::DIAGONAL;
    }
  }
}    
    
#if 0
class rSolutions
{
public:
  rBlockDenseMatrix xMat;
  rBlockDenseMatrix zMat;
  rVector           yVec;

  rBlockVector xzEigenValues;
  double xzMinEigenValue;

  rBlockDenseMatrix workMat;
  rBlockDenseMatrix workMat2;
  rBlockVector      workVec;
};
#endif

void rMpiCopy::copy(rSolutions& initPt,int m,int nBlock,
		    int* blockStruct)
{
  rMpiCopy::copy(initPt.xMat,nBlock,blockStruct);
  rMpiCopy::copy(initPt.zMat,nBlock,blockStruct);
  rMpiCopy::copy(initPt.yVec,m);
}

void rMpiCopy::copy(rBlockDenseMatrix& xMat,int nBlock,
		    int*blockStruct)
{
  #if 0 // initialize はすでにおわってるはず。
  if (rMpiSt::iam != 0) {
    xMat.initialize(nBlock,blockStruct);
  }
  #endif
  for (int l=0; l<nBlock; ++l) {
    rMpiCopy::copy(xMat.ele[l],blockStruct[l]);
  }
}

void rMpiCopy::copy(rDenseMatrix& xMat,int size)
{
  // この状態は Dense か Diagonal だけでいいはず。
  if (rMpiSt::iam == 0) {
    if (size > 0) {
      Cdgebs2d(rMpiSt::ictxt,"All"," ",size*size,1,
	       (char*)xMat.de_ele,size*size);
    }
    else { // size < 0
      Cdgebs2d(rMpiSt::ictxt,"All"," ",-size,1,
	       (char*)xMat.di_ele,-size);
    }
  }
  else { // iam != 0

    xMat.de_ele = NULL;
    xMat.di_ele = NULL;

    if (size > 0) {
      xMat.de_ele = new double[size*size];
      if (xMat.de_ele == NULL) {
	rMessage("memory exhausted");
      }
      Cdgebr2d(rMpiSt::ictxt,"All"," ",size*size,1,
	       (char*)xMat.de_ele,size*size,0,0);
      xMat.nRow = xMat.nCol = size;
      xMat.De_Di = rDenseMatrix::DENSE;
    }
    else { // size < 0
      xMat.di_ele = new double[-size];
      if (xMat.di_ele == NULL) {
	rMessage("memory exhausted");
      }
      Cdgebr2d(rMpiSt::ictxt,"All"," ",-size,1,
	       (char*)xMat.di_ele,-size,0,0);
      xMat.nRow = xMat.nCol = -size;
      xMat.De_Di = rDenseMatrix::DIAGONAL;
    }
  }
}

void rMpiCopy::copy(rVector& yVec, int m)
{
  if (rMpiSt::iam == 0) {
    Cdgebs2d(rMpiSt::ictxt,"All"," ",m,1,
	     (char*)yVec.ele,m);
  }
  else {
    yVec.initialize(m);
    Cdgebr2d(rMpiSt::ictxt,"All"," ",m,1,
	     (char*)yVec.ele,m,0,0);
    yVec.nDim = m;
  }
}
