/*
 * $Id: Space2PEBlock.java,v 1.4 1999/10/05 14:25:16 yamauchi Exp $
 *     (M\pi)^2 : Block Allocation Implementation
 *	Copyright 1999 By YAMAUCHI Hitoshi 山内 斉 
 *	@author YAMAUCHI Hitoshi 山内 斉
 *	
 * original source spc2PE.h spc2PE.cc
 *
 *	部分空間と PE のマッピング : Block 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 Space2PEBlock extends Space2PE {
    public Space2PEBlock()
    {
	super();
	this.mNumberOfPE 	= new int[3];
	this.mNumberOfSPCof1PE	= new int[3];
    }

    public Space2PEBlock(Space2PEBlock 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)
    {
	// block allocation に次元は関係ないが確認
	this.mSystemDimension = Space2PE.getSystemDimension(numberOfPEs); 
	this.mSubDivNum	      = subdivnum;    
	if(subdivnum < 1)
	{
	    throw new RuntimeException("Error! : illegal subdivnum " +
				       "Space2PEBlock.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 PE or space num PE ["
				       + numberOfPEs + "], spacenum [" +
				       this.mSubDivNum + "]" + 
				       " Space2PEBlock::init");
	    // 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, "SystemDimension must be > 0 "
		   + "Space2PEBlock.getPEIDfromSpcPos");
	// spcpos * PEnum / subdivnum
	int []  pe_id = new int[3];
	for(int i = 0; i < 3; i++)
	{
	    Assert.out(spcPos.get(i) >= 0, "element of spcpos must be >= 0 "
		       + "Space2PEBlock.getPEIDfromSpcPos");
	    pe_id[i] = 
		(spcPos.get(i) * this.mNumberOfPE[i]) / this.mSubDivNum;
	}

	IntVec3 PEid = new IntVec3(pe_id[0], pe_id[1], pe_id[2]);
	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.mNumberOfSPCof1PE[i] * this.mPEID.get(i));
	    if(!((0 <= local_idx[i]) && 
		 (local_idx[i] < this.mNumberOfSPCof1PE[i])))
	    {
		System.out.println(this.baseString());
		throw new RuntimeException("DEBUG : spcpos " + spcPos);
	    }
	}
	IntVec3 localIdx = 
	    new IntVec3(local_idx[0], local_idx[1], local_idx[2]);
	return(localIdx);
    }	
}
