/*
 * $Id: Space2PEDistributed.java,v 1.4 1999/10/05 14:25:16 yamauchi Exp $
 *     (M\pi)^2 : Distributed Allocation Implementation
 *	Copyright 1999 By YAMAUCHI Hitoshi 山内 斉 
 *	@author YAMAUCHI Hitoshi 山内 斉
 *	
 * original source spc2PE.h spc2PE.cc
 *
 *	部分空間と PE のマッピング : Distributed Allocation
 * 
 * 1999年8月 3日(火)
 */

package jp.ac.tohoku.is.archi.mpi2.common;

import  jp.ac.tohoku.is.archi.mpi2.util.IntVec3;
import  jp.ac.tohoku.is.archi.mpi2.util.Assert;

public class Space2PEDistributed extends Space2PE {
    public Space2PEDistributed()
    {
	super();
	this.mNumberOfPE 	= new int[3];
	this.mNumberOfSPCof1PE	= new int[3];
    }
    public Space2PEDistributed(Space2PEDistributed rhs)
    {
	this.mSystemDimension = rhs.mSystemDimension;
	this.mNumberOfPE 	= new int[3];
	this.mNumberOfSPCof1PE	= new int[3];
	for(int i = 0; i < 3; i++)
	{
	    this.mNumberOfPE[i]		= rhs.mNumberOfPE[i];
	    this.mNumberOfSPCof1PE[i] 	= rhs.mNumberOfSPCof1PE[i];
	}
	this.mSubDivNum = rhs.mSubDivNum;
	this.mPEID	= new IntVec3(rhs.mPEID);
    }

    /**
     * init
     */
    public void init(IntVec3 numberOfPEs, int subdivnum, IntVec3 PEid)
    {
	// distributed allocation に次元は関係ないが確認
	this.mSystemDimension = getSystemDimension(numberOfPEs);
	this.mSubDivNum	   = subdivnum;    
	if(this.mSubDivNum < 1)
	{
	    throw new RuntimeException("Error! : illegal subdivnum " +
				       "Space2PEDistributed.init(), " 
				       + subdivnum);
	    // commMpi2_exit(1);
	}
	for(int i = 0; i < 3; i++)
	{
	    this.mNumberOfPE[i]  = numberOfPEs.get(i);
	    if((this.mNumberOfPE[i]  < 1)  || 
	       ((this.mSubDivNum % this.mNumberOfPE[i]) != 0))
	    {
		//// 空間分割数(ex.32)PE(2,4,4)のようにsubdiv % pe == 0が正しい
		throw new RuntimeException("Error! : illegal subdivnum " +
					   "Space2PEDistributed.init(), " + 
					   subdivnum);
		// commMpi2_exit(1);
	    }
	    this.mNumberOfSPCof1PE[i] = subdivnum / this.mNumberOfPE[i];
	}
	this.mPEID = new IntVec3(PEid);
    }
    
    public IntVec3 getNewPEIDfromSpcPos(IntVec3 spcPos)
    {
	Assert.out(this.mSystemDimension > 0, 
		   "Distributed.getNewPEIDfromSpcPos: mSystemDimension");
	Assert.out(spcPos.get(IntVec3.X) >= 0,
		   "Distributed.getNewPEIDfromSpcPos: spcPos.X");
	Assert.out(spcPos.get(IntVec3.Y) >= 0, 
		   "Distributed.getNewPEIDfromSpcPos: spcPos.Y");
	Assert.out(spcPos.get(IntVec3.Z) >= 0,
		   "Distributed.getNewPEIDfromSpcPos: spcPos.Z");
	
	int pe_x = spcPos.get(IntVec3.X) % this.mNumberOfPE[0];
	int pe_y = spcPos.get(IntVec3.Y) % this.mNumberOfPE[1];
	int pe_z = spcPos.get(IntVec3.Z) % this.mNumberOfPE[2];
	IntVec3 PEid = new IntVec3(pe_x, pe_y, pe_z);
	return(PEid);
    }

    // local Idx = 物体情報を担当空間分のみとした場合の PE 内部の index
    public IntVec3 getNewLocalIdxFromSpcPos(IntVec3 spcPos)
    {
	int [] local_idx = new int[3];
	for(int i = 0; i < 3; i++)
	{
	    local_idx[i] = spcPos.get(i) / this.mNumberOfPE[i];
	    Assert.out((0 <= local_idx[i]) && 
		       (local_idx[i] < this.mNumberOfSPCof1PE[i]),
		       "Distributed.getNewLocalIdxFromSpcPos");
	}
	IntVec3 localIdx = 
	    new IntVec3(local_idx[0], local_idx[1], local_idx[2]);
	return(localIdx);	
    }	
}








