package jp.ac.takushoku_u.cs;

/**
* ArithmeticMatrixクラスではdouble型の要素を持つマトリクスを扱います。<BR>
* マトリクスの分析データを行名と列名を付けて保持できるようになります。
* またマトリクス同士の演算を行うことができます。<BR>
* @version 1.3
* @author 笠島 裕史(Kasajima Hiroshi)
* @see jp.ac.takushoku_u.cs.BooleanMatrix
* @see jp.ac.takushoku_u.cs.StringMatrix
*/
/*
* 最終更新日 2004年11月24日
*/
public class ArithmeticMatrix extends Matrix{
	
/**
* マトリクスをクリアするときの値。
*/
	private static final double MATRIX_CLEAR_VALUE = 0.0;
	
/**
* Falseを取る時の論理値。
*/
	private static final double MATRIX_VALUE_FALSE = 0.0;
	
/**
* Trueを取る時の論理値。
*/
	private static final double MATRIX_VALUE_TRUE = 1.0;


/**
* 設定されているサイズのデータ保存用の2次元配列と行名、列名を入れる配列を生成します。<BR>
* 生成された2次元配列は全て0で初期化されます。
* 行名と列名は行番号と列番号で設定されます。
*/
	public ArithmeticMatrix(){
		super();
		clearMatrix();
	}

/**
* 指定された行サイズと列サイズを元にデータ保存用の2次元配列と行名、列名を入れる配列を生成します。<BR>
* 生成された2次元配列は全て0で初期化されます。
* 行名と列名は行番号と列番号で設定されます。
* @param rowSize 指定する行サイズ
* @param colSize 指定する列サイズ
* @exception NegativeMatrixSizeException 負のサイズのマトリクスが生成しようとした場合
*/
	public ArithmeticMatrix(int rowSize, int colSize){
		super(rowSize, colSize);
		clearMatrix();
	}
	
/**
* 指定された行サイズと列サイズを元にデータ保存用の2次元配列と行名、列名を入れる配列を生成し、
* 指定された番号から順に行名と列名を初期化します。<BR>
* 生成された2次元配列は全て0で初期化されます。
* 行名と列名は nameNumber で指定された番号から順に設定されます。
* @param rowSize 指定する行サイズ
* @param colSize 指定する列サイズ
* @param nameNumber 行名および列名の開始番号
* @exception NegativeMatrixSizeException 負のサイズのマトリクスが生成しようとした場合
*/
	public ArithmeticMatrix(int rowSize, int colSize, int nameNumber){
		super(rowSize, colSize, nameNumber);
		clearMatrix();
	}
	
/**
* 指定された行サイズ、列サイズ、行名、列名を元にデータ保存用の2次元配列と行名、列名を入れる配列を生成します。<BR>
* 生成された2次元配列は全て0で初期化されます。
* @param rowSize 指定する行サイズ
* @param colSize 指定する列サイズ
* @param rowName 指定する行名
* @param colName 指定する列名
* @exception NegativeMatrixSizeException 負のサイズのマトリクスが生成しようとした場合
* @exception IndexOutOfBoundsException コピーによって配列の境界を越えたデータのアクセスが生じた場合
* @exception NullPointerException  rowName または colName が null の場合
*/
	public ArithmeticMatrix(int rowSize, int colSize, String[] rowName, String[] colName){
		super(rowSize, colSize);
		clearMatrix();
		
		//行名および列名のコピー
		nameRowCopy(rowName);
		nameColCopy(colName);
	}
	
/**
* 指定された2次元配列を元にデータ保存用の2次元配列と行名、列名を入れる配列を生成します。<BR>
* 行名と列名は行番号と列番号で設定されます。
* @param originalMatrix 指定する2次元配列
* @exception IndexOutOfBoundsException コピーによって配列の境界を越えたデータのアクセスが生じた場合
* @exception NullPointerException  originalMatrix が null の場合
*/
	public ArithmeticMatrix(double[][] originalMatrix){
		super(originalMatrix.length, originalMatrix[0].length);
		
		//マトリクスのコピー
		for (int i = 0; i < getRowLength(); i++){
			for (int j = 0; j < getColLength(); j++){
				setCell(i, j, originalMatrix[i][j]);
			}
		}
	}

/**
* 指定された2次元配列を元にデータ保存用の2次元配列と行名、列名を入れる配列を生成し、
* 指定された番号から順に行名と列名を初期化します。<BR>
* 行名と列名は nameNumber で指定された番号から順に設定されます。
* @param originalMatrix 指定する2次元配列
* @param nameNumber 行名および列名の開始番号
* @exception IndexOutOfBoundsException コピーによって配列の境界を越えたデータのアクセスが生じた場合
* @exception NullPointerException  originalMatrix が null の場合
*/
	public ArithmeticMatrix(double[][] originalMatrix, int nameNumber){
		super(originalMatrix.length, originalMatrix[0].length, nameNumber);
		
		//マトリクスのコピー
		for (int i = 0; i < getRowLength(); i++){
			for (int j = 0; j < getColLength(); j++){
				setCell(i, j, originalMatrix[i][j]);
			}
		}
	}

/**
* 指定された2次元配列、行名、列名を元にデータ保存用の2次元配列と行名、列名を入れる配列を生成します。
* @param originalMatrix 指定する2次元配列
* @param rowName 指定する行名
* @param colName 指定する列名
* @exception IndexOutOfBoundsException コピーによって配列の境界を越えたデータのアクセスが生じた場合
* @exception NullPointerException  rowName , colName または originalMatrix が null の場合
*/
	public ArithmeticMatrix(double[][] originalMatrix, String[] rowName, String[] colName){
		super(originalMatrix.length, originalMatrix[0].length);
		
		//マトリクスのコピー
		for (int i = 0; i < getRowLength(); i++){
			for (int j = 0; j < getColLength(); j++){
				setCell(i, j, originalMatrix[i][j]);
			}
		}
		
		//行名および列名のコピー
		nameRowCopy(rowName);
		nameColCopy(colName);
	}

/**
* 保持された要素を変更せずにマトリクスの大きさを変更します。
* マトリクスを小さくする場合は指定した要素より大きい部分がなくなります。
* 大きくする場合大きくされた部分は初期値で初期化され、
* 行名と列名はそれぞれ行番号と列番号になります。
* @param rowLength 行サイズ
* @param colLength 列サイズ
* @exception NegativeMatrixSizeException 負のサイズのマトリクスが生成しようとした場合
*/
	public void reSizeMatrix(int rowLength, int colLength){
		int r = getRowLength();
		int c = getColLength();
		super.reSizeMatrix(rowLength, colLength);
		
		
		//マトリクスの要素を入れる
		for (int i = 0; i < rowLength; i++){
			if(i >= r){
				setRowName(i, i+"");
			}
			for (int j = 0; j < colLength; j++){
				if(j >= c){
					setColName(j, j+"");
				}
				if((i >= r) || (j >= c)){
					setCell(i, j, MATRIX_CLEAR_VALUE);
				}
			}
		}
	}
	
/**
* 指定された1点へ値を設定します。
* @param row 指定行番号
* @param col 指定列番号
* @param value 設定値
* @exception NotElementException 指定した点が存在しない場合
*/
	public void setCell(int row,int col,double value){
		if (isMatrixEntityPoint(row, col)){
			Double d = new Double(value);
			super.setCell(row, col, d);
		}
		else{
			throw new NotElementException("Point(" + row + "," + col + ")");
		}
	}

/**
* マトリクスに他のマトリクスの要素、行名、列名の全てをコピーします。<BR>
* コピー元のマトリクスサイズと一致しない場合はコピー元のマトリクスサイズに変更し、コピーを行います。
* @param originalMatrix コピー元のマトリクス
* @see #matrixCopy(ArithmeticMatrix originalMatrix, int baseRow, int baseCol, int copyRow,int copyCol, int rowLength, int colLength)
*/
	public void matrixCopy(ArithmeticMatrix originalMatrix){
		super.matrixCopy(originalMatrix);
	}
	
/**
* 指定位置で開始する指定要素からコピー先のマトリクスの指定位置に要素をコピーします。<BR>
* コピー元の要素( baseRow , baseCol )で指定された要素を開始位置とし、rowLength 行 colLength 列分だけ
* 要素( copyRow , copyCol )から指定される要素から始まる要素にコピーを行います。
* コピー先の範囲に当てはまらない要素と行名、列名は変更されません。
* @param originalMatrix コピー元のマトリクス
* @param baseRow コピー元のマトリクスに対するコピーの行開始位置
* @param baseCol コピー元のマトリクスに対するコピーの列開始位置
* @param copyRow コピーされる行開始位置
* @param copyCol コピーされる列開始位置
* @param rowLength コピーを行う行の要素数
* @param colLength コピーを行う列の要素数
* @exception SetValueOutOfBoundsException コピー先が存在しない範囲にあたる場合
* @see #matrixCopy(ArithmeticMatrix originalMatrix)
*/
	public void matrixCopy(ArithmeticMatrix originalMatrix, int baseRow, int baseCol, int copyRow,
		int copyCol, int rowLength, int colLength){
			super.matrixCopy(originalMatrix, baseRow, baseCol, copyRow,
				copyCol, rowLength, colLength);
	}
	
/**
* マトリクスに存在する要素を全て0にします。
*/
	public void clearMatrix(){
		for (int i = 0 ; i < getRowLength() ; i++){
			for (int j = 0 ; j < getColLength() ; j++){
				setCell(i, j, MATRIX_CLEAR_VALUE);
			}
		}
	}
	
/**
* 指定された1点の値を返します。
* @param row 指定行番号
* @param col 指定列番号
* @return 指定した点の値
* @exception NotElementException 指定された点が存在しない場合
*/
	public double getCell(int row, int col){
		if (isMatrixEntityPoint(row, col)){
			Double d = new Double(0.0);
			d = (Double)getObjectCell(row,col);
			double b = d.doubleValue();
			return b;
			//return matrix[row][col];
		}
		else{
			throw new NotElementException("point(" + row + "," + col + ")");
		}
	}
	
/**
* 指定した行にある値の合計を返します。
* @param row 指定行番号
* @return 指定した行の合計値
* @exception NotElementException 指定した行が存在しない場合
* @see #getColSum(int col)
* @see #getRowSumArray()
*/
	public double getRowSum(int row){
		if (isRowNumber(row)){
			double val = 0.0;
			for (int i = 0; i < getColLength(); i++){
				val = getCell(row, i) + val;
			}
			return val;
		}
		else{
			throw new NotElementException("row("+ row +")");
		}
	}
	
/**
* 各行のそれぞれの合計を配列で返します。
* @return 各行の合計値が入った配列
* @see #getColSumArray()
* @see #getRowSum(int row)
*/
	public double[] getRowSumArray(){
		double[] returnArray = new double[getRowLength()];
		for (int i = 0; i < getRowLength(); i++){
			returnArray[i] = getRowSum(i);
		}
		return returnArray;
	}
	
/**
* 指定した列にある値の合計を返します。
* @param col 指定列番号
* @return 指定した列の合計値
* @exception NotElementException 指定した列が存在しない場合
* @see #getRowSum(int row)
* @see #getColSumArray()
*/
	public double getColSum(int col){
		if (isColNumber(col)){
			double val = 0.0;
			for (int i = 0; i < getRowLength(); i++){
				val = getCell(i, col) + val;
			}
			return val;
		}
		else{
			throw new NotElementException("col("+ col +")");
		}
	}
	
/**
* 各列のそれぞれの合計を配列で返します。
* @return 各列の合計値が入った配列
* @see #getColSum(int col)
* @see #getRowSumArray()
*/
	public double[] getColSumArray(){
		double[] returnArray = new double[getColLength()];
		for (int i = 0; i < getColLength(); i++){
			returnArray[i] = getColSum(i);
		}
		return returnArray;
	}
	
/**
* 指定した行にある値の平均を返します。
* @param row 指定行番号
* @return 指定した行の平均値
* @exception NotElementException 指定した行が存在しない場合
* @see #getColAverage(int col)
* @see #getRowAverageArray()
*/
	public double getRowAverage(int row){
		if (isRowNumber(row)){
			double val;
			val = getRowSum(row) / getColLength();
			return val;
		}
		else{
			throw new NotElementException("row("+ row +")");
		}
	}
	
/**
* 各行のそれぞれの平均を配列で返します。
* @return 各行の平均値が入った配列
* @see #getColAverageArray()
* @see #getRowAverage(int row)
*/
	public double[] getRowAverageArray(){
		double[] returnArray = new double[getRowLength()];
		for (int i = 0; i < getRowLength(); i++){
			returnArray[i] = getRowAverage(i);
		}
		return returnArray;
	}
	
/**
* 指定した列にある値の平均を返します。
* @param col 指定列番号
* @return 指定した列の平均値
* @exception NotElementException 指定された列が存在しない場合
* @see #getRowAverage(int row)
* @see #getColAverageArray()
*/
	public double getColAverage(int col){
		if (isColNumber(col)){
			double val;
			val = getColSum(col) / getRowLength();
			return val;
		}
		else{
			throw new NotElementException("col("+ col +")");
		}
	}
	
/**
* 各列のそれぞれの平均を配列で返します。
* @return 各列の平均値が入った配列
* @see #getRowAverageArray()
* @see #getColAverage(int col)
*/
	public double[] getColAverageArray(){
		double[] returnArray = new double[getColLength()];
		for (int i = 0; i < getColLength(); i++){
			returnArray[i] = getColAverage(i);
		}
		return returnArray;
	}
	
/**
* マトリクスの要素にある値から最大値を返します。
* @return 要素内にある最大値
*/
	public double getMaxCell(){
		double maxValue;
		maxValue = getCell(0,0);		//初期値
		for (int i = 0; i < getRowLength(); i++){		//最大値を調べる
			for (int j = 0; j < getColLength(); j++){
				if (maxValue < getCell(i,j)){
					maxValue = getCell(i, j);
				}
			}
		}
		return maxValue;
	}
	
/**
* マトリクスに存在する要素のうち、要素が0を超える要素の数を返します。
* @return 要素数
*/
	public int getElement(){
		int element = 0;
		for (int i = 0; i < getRowLength(); i++){
			for (int j = 0; j < getColLength(); j++){
				if (getCell(i, j) > 0){		//0を超えた要素数を数える
					element = element + 1;
				}
			}
		}
		return element;
	}
	
/**
* マトリクス内の要素を0と1の2値に変換します。
* 0以下の数は0に、0を越える数は1に変換されます。
*/
	public void convertLogicMatrix(){
		for (int i = 0; i < getRowLength(); i++){
			for (int j = 0; j < getColLength(); j++){
				if (getCell(i, j) <= 0){
					setCell(i, j, MATRIX_VALUE_FALSE);
				}
				else{
					setCell(i, j, MATRIX_VALUE_TRUE);
				}
			}
		}
	}

/**
* ArithmeticMatrixをBooleanMatrix型に変換します。
* 0以下の数はfalseに、0を越える数はtrueとします。
* 変換されたマトリクスには行名と列名は引き継がれます。
* @return 変換されたマトリクス
* @see #toBooleanMatrix(double value)
* @see #toStringMatrix()
*/
	public BooleanMatrix toBooleanMatrix(){
		BooleanMatrix returnMatrix = new BooleanMatrix(getRowLength(), getColLength(),
			getRowNameArray(), getColNameArray());
			for (int i = 0; i < getRowLength(); i++){
				for (int j = 0; j < getColLength(); j++){
					if (getCell(i, j) <= 0){
						returnMatrix.setCell(i, j, false);
					}
					else{
						returnMatrix.setCell(i, j, true);
					}
				}
			}
		return returnMatrix;
	}
	
/**
* ArithmeticMatrixをBooleanMatrix型に変換します。
* しきい値 value 以下の数はfalseに、 value を越える数はtrueとします。<BR>
* 但し、しきい値が0の場合は、0がfalseに、0以外の数がtrueとします。
* 0以下の数をfalseとする場合はtoBooleanMatrix()を利用してください。
* 変換されたマトリクスには行名と列名は引き継がれます。
* @param value しきい値
* @return 変換されたマトリクス
* @see #toBooleanMatrix()
* @see #toStringMatrix()
*/
	public BooleanMatrix toBooleanMatrix(double value){
		BooleanMatrix returnMatrix = new BooleanMatrix(getRowLength(), getColLength(),
			getRowNameArray(), getColNameArray());
		for (int i = 0; i < getRowLength(); i++){
			for (int j = 0; j < getColLength(); j++){
				if(value != 0){
					if (getCell(i, j) <= value){
						returnMatrix.setCell(i, j, false);
					}
					else{
						returnMatrix.setCell(i, j, true);
					}
				}
				else{
					if (getCell(i, j) == value){
						returnMatrix.setCell(i, j, false);
					}
					else{
						returnMatrix.setCell(i, j, true);
					}
				}
			}
		}
		return returnMatrix;
	}
	
/**
* ArithmeticMatrixをStringMatrix型に変換します。
* 各要素の値をそのまま文字列とします。
* 変換されたマトリクスには行名と列名は引き継がれます。
* @return 変換されたMatrix
* @see #toBooleanMatrix()
* @see #toBooleanMatrix(double value)
*/
	public StringMatrix toStringMatrix(){
		StringMatrix returnMatrix = new StringMatrix(getRowLength(), getColLength(),
			getRowNameArray(), getColNameArray());
		for (int i = 0; i < getRowLength(); i++){
			for (int j = 0; j < getColLength(); j++){
					returnMatrix.setCell(i, j, Double.toString(getCell(i, j)));
			}
		}
		return returnMatrix;
	}
	
/**
* 2つのマトリクスのサイズが同じかチェックします。
* @param compareMatrix 調べるマトリクス
* @return サイズが同じであればTrueを、違う場合はFalseを返します。
*/
	public boolean isSameMatrixSize(ArithmeticMatrix compareMatrix){
		return getRowLength() == compareMatrix.getRowLength()
			&& getColLength() == compareMatrix.getColLength();
	}
	
/**
* 2つのマトリクスのサイズが乗算を行うことができるかチェックします。
* @param compareMatrix 調べるマトリクス
* @return サイズが同じであればTrueを、違う場合はFalseを返します。
*/
	private boolean isMultiplyMatrixSize(ArithmeticMatrix compareMatrix){
		return getColLength() == compareMatrix.getRowLength();
	}
	
/**
* 他のマトリクスとの論理積(And)を返します。<BR>
* この演算を正常に行った場合はconvertLogicMatrixメソッドが実行されます。
* @param calculateMatrix 演算対象のマトリクス
* @return 演算結果のマトリクス
* @exception DisagreementMatrixSizeException 演算を行う2つのマトリクスのサイズが異なる場合
* @see #convertLogicMatrix()
* @see #getOrMatrix(ArithmeticMatrix calculateMatrix)
* @see #getXOrMatrix(ArithmeticMatrix calculateMatrix)
* @see #getNotMatrix()
*/
	public ArithmeticMatrix getAndMatrix(ArithmeticMatrix calculateMatrix){
		ArithmeticMatrix returnMatrix = new ArithmeticMatrix(getRowLength(), getColLength(),
			getRowNameArray(), getColNameArray());
		
		//演算が行えるか
		if (isSameMatrixSize(calculateMatrix)){
			
			//論理値のマトリクスに変換
			convertLogicMatrix();
			calculateMatrix.convertLogicMatrix();
			for (int i = 0; i < getRowLength(); i++){
				for (int j = 0; j < getColLength(); j++){
					
					//要素同士の論理積を求める
					returnMatrix.setCell(i, j, (int) getCell(i,j) &
						(int) calculateMatrix.getCell(i,j));
				}
			}
		}
		
		//演算が行えない場合
		else{
			throw new DisagreementMatrixSizeException();
		}
		return returnMatrix;
	}
	
/**
* 他のマトリクスとの論理和(OR)を返します。<BR>
* この演算を正常に行った場合はconvertLogicMatrixメソッドが実行されます。
* @param calculateMatrix 演算対象のマトリクス
* @return 演算結果のマトリクス
* @exception DisagreementMatrixSizeException 演算を行う2つのマトリクスのサイズが異なる場合
* @see #convertLogicMatrix()
* @see #getAndMatrix(ArithmeticMatrix calculateMatrix)
* @see #getXOrMatrix(ArithmeticMatrix calculateMatrix)
* @see #getNotMatrix()
*/
	public ArithmeticMatrix getOrMatrix(ArithmeticMatrix calculateMatrix){
		ArithmeticMatrix returnMatrix = new ArithmeticMatrix(getRowLength(), getColLength(),
			getRowNameArray(), getColNameArray());
		
		//演算が行えるか
		if (isSameMatrixSize(calculateMatrix)){
			
			//論理値のマトリクスに変換
			convertLogicMatrix();
			calculateMatrix.convertLogicMatrix();
			for (int i = 0; i < getRowLength(); i++){
				for (int j = 0; j < getColLength(); j++){
					
					//要素同士の論理和を求める
					returnMatrix.setCell(i, j, (int) getCell(i,j) |
						(int) calculateMatrix.getCell(i,j));
				}
			}
		}
		
		//演算が行えない場合
		else{
			throw new DisagreementMatrixSizeException();
		}
		return returnMatrix;
	}
	
/**
* 他のマトリクスとの排他的論理和(eXclusive OR)を返します。<BR>
* この演算を正常に行った場合はconvertLogicMatrixメソッドが実行されます。
* @param calculateMatrix 演算対象のマトリクス
* @return 演算結果のマトリクス
* @exception DisagreementMatrixSizeException 演算を行う2つのマトリクスのサイズが異なる場合
* @see #convertLogicMatrix()
* @see #getAndMatrix(ArithmeticMatrix calculateMatrix)
* @see #getOrMatrix(ArithmeticMatrix calculateMatrix)
* @see #getNotMatrix()
*/
	public ArithmeticMatrix getXOrMatrix(ArithmeticMatrix calculateMatrix){
		ArithmeticMatrix returnMatrix = new ArithmeticMatrix(getRowLength(), getColLength(),
			getRowNameArray(), getColNameArray());
		
		//演算が行えるかどうか
		if (isSameMatrixSize(calculateMatrix)){
			
			//論理値のマトリクスに変換
			convertLogicMatrix();
			calculateMatrix.convertLogicMatrix();
			for (int i = 0; i < getRowLength(); i++){
				for (int j = 0; j < getColLength(); j++){
					
					//要素同士の排他的論理和を求める
					returnMatrix.setCell(i, j, (int) getCell(i,j) ^
						(int) calculateMatrix.getCell(i,j));
				}
			}
		}
		
		//演算が行えない場合
		else{
			throw new DisagreementMatrixSizeException();
		}
		return returnMatrix;
	}
	
/**
* マトリクスの否定(NOT)を返します。<BR>
* この演算を行った場合はconvertLogicMatrixメソッドが実行されます。
* @return 演算結果のマトリクス
* @see #convertLogicMatrix()
* @see #getAndMatrix(ArithmeticMatrix calculateMatrix)
* @see #getOrMatrix(ArithmeticMatrix calculateMatrix)
* @see #getXOrMatrix(ArithmeticMatrix calculateMatrix)
*/
	public ArithmeticMatrix getNotMatrix(){
		ArithmeticMatrix returnMatrix = new ArithmeticMatrix(getRowLength(), getColLength(),
			getRowNameArray(), getColNameArray());
		
		//論理値のマトリクスに変換
		convertLogicMatrix();
			for (int i = 0; i < getRowLength(); i++){
				for (int j = 0; j < getColLength(); j++){
					
					//否定の演算を行う
					if (getCell(i,j) > 0){
						returnMatrix.setCell(i, j, 0);
					}
					else{
						returnMatrix.setCell(i, j, 1);
					}
				}
			}
		return returnMatrix;
	}
	
/**
* マトリクスをvalue倍したマトリクスを返します。
* マトリクスの全ての要素に対して、value倍したマトリクスが返されます。
* @param value 掛ける数
* @return value倍されたマトリクス
* @see #getMultiplyMatrix(ArithmeticMatrix calculateMatrix)
*/
	public ArithmeticMatrix getTimesMatrix(double value){
		ArithmeticMatrix returnMatrix = new ArithmeticMatrix(getRowLength(), getColLength(),
			getRowNameArray(), getColNameArray());
		for(int i = 0; i < getRowLength(); i++){
			for(int j = 0; j < getColLength(); j++){
				double v = value * getCell(i, j);
				returnMatrix.setCell(i, j, v);
			}
		}
		return returnMatrix;
	}
	
/**
* マトリクス同士の和を計算したマトリクスを返します。<BR>
* 返されるマトリクスの行名と列名はマトリクスと同じものとなります。
* @param calculateMatrix 加算対象のマトリクス
* @return 演算結果のマトリクス
* @exception DisagreementMatrixSizeException 演算を行う2つのマトリクスのサイズが一致しない場合
*/
	public ArithmeticMatrix getAddMatrix(ArithmeticMatrix calculateMatrix){
		ArithmeticMatrix returnMatrix = new ArithmeticMatrix(getRowLength(), getColLength(),
			getRowNameArray(), calculateMatrix.getColNameArray());
		
		//演算が行えるかどうか
		if (isSameMatrixSize(calculateMatrix)){
			for (int i = 0; i < returnMatrix.getRowLength(); i++){
				for (int j = 0; j < returnMatrix.getColLength(); j++){
					double value = 0.0;
					value = getCell(i, j) + calculateMatrix.getCell(i, j);
					returnMatrix.setCell(i, j, value);
				}
			}
		}
		
		//演算が行えない場合
		else{
			throw new DisagreementMatrixSizeException();
		}
			return returnMatrix;
	}
	
/**
* マトリクス同士の積を計算したマトリクスを返します。<BR>
* 演算は マトリクス × calculateMatrix で行われます。
* 返されるマトリクスのサイズは演算元のマトリクスの行サイズ×演算対象のマトリクスの列サイズとなります。
* @param calculateMatrix 乗算対象のマトリクス
* @return 演算結果のマトリクス
* @exception DisagreementMatrixSizeException 演算を行う2つのマトリクスのサイズが演算を行えないサイズの場合
* @see #getTimesMatrix(double value)
*/
	public ArithmeticMatrix getMultiplyMatrix(ArithmeticMatrix calculateMatrix){
		ArithmeticMatrix returnMatrix = new ArithmeticMatrix(getRowLength(), calculateMatrix.getColLength(),
			getRowNameArray(), calculateMatrix.getColNameArray());
		
		//演算が行えるかどうか
		if (isMultiplyMatrixSize(calculateMatrix)){
			for (int i = 0; i < returnMatrix.getRowLength(); i++){
				for (int j = 0; j < returnMatrix.getColLength(); j++){
					
					//行列の乗算を行う
					//計算式は a_i1 * a_1j + a_i2 * a_2j + … + a_in * a_nj
					double value = 0.0;
					for (int k = 0; k < getColLength(); k++){
							value = getCell(i, k) * calculateMatrix.getCell(k, j) + value;
					}
					returnMatrix.setCell(i, j, value);
				}
			}
		}
		
		//演算が行えない場合
		else{
			throw new DisagreementMatrixSizeException();
		}
			return returnMatrix;
	}
	
/**
* exponetを指数としたべき乗を計算したマトリクスを返します。
* @param exponent 累乗の指数
* @return n乗をしたマトリクス
* @exception SetValueOutOfBoundsException 指数に0以下の値を指定した場合
* @exception NotSquareMatrixException マトリクスが正方行列でない場合
*/
	public ArithmeticMatrix getExponentMatrix(int exponent){
		ArithmeticMatrix initMatrix = new ArithmeticMatrix(getMatrix(), getRowNameArray(), getColNameArray());
		ArithmeticMatrix returnMatrix = new ArithmeticMatrix(getMatrix(), getRowNameArray(), getColNameArray());
		
		//正方行列かどうか、また指数に0以下の値を指定された場合
		if (isSquare()){
			if (exponent > 0){
			
				//元のマトリクスをn回乗算する(1乗の場合は元のマトリクスのまま)
				for (int i = 1; i < exponent; i++){
				
					//i乗したマトリクスに元のマトリクスを掛け、i+1乗にする
					returnMatrix.matrixCopy(returnMatrix.getMultiplyMatrix(initMatrix));
				}
			}
			
			//指数に0以下の値を指定された場合
			else{
				throw new SetValueOutOfBoundsException("exponent(" + exponent + ")");
			}
		}
		
		//マトリクスが正方行列でない場合
		else{
			throw new NotSquareMatrixException();
		}
		return returnMatrix;
	}
	
/**
* マトリクスの要素を単位マトリクスに変更します。
* @exception NotSquareMatrixException マトリクスが正方行列でない場合
*/
	public void createElementaryMatrix(){
		if (isSquare()){
			for (int i = 0; i < getRowLength(); i++){
				for (int j = 0; j < getColLength(); j++){
					
					//対角成分のみ1を入れる
					if (i == j){
						setCell(i, j, MATRIX_VALUE_TRUE);
					}
					else{
						setCell(i, j, MATRIX_VALUE_FALSE);
					}
				}
			}
		}
		
		//マトリクスが正方行列でない場合
		else{
			throw new NotSquareMatrixException();
		}
	}
	
/**
* このマトリクスと同じサイズの単位マトリクスを返します。
* @return 単位行列
*/
	private ArithmeticMatrix getElementaryMatrix(){
		ArithmeticMatrix returnMatrix = new ArithmeticMatrix(getRowLength(), getColLength(),
			getRowNameArray(), getColNameArray());
		returnMatrix.createElementaryMatrix();
		return returnMatrix;
	}
	
/**
* マトリクスを隣接マトリクスとした時の可到達マトリクスを返します。<BR>
* この演算を正常に行った場合はconvertLogicMatrixメソッドが実行されます。
* @return 可到達マトリクス
* @exception NotSquareMatrixException マトリクスが正方行列ではない場合
* @see #convertLogicMatrix()
*/
	public ArithmeticMatrix getReachMatrix(){
		
		//正方行列かどうか
		if (isSquare()){
		//このマトリクスを隣接マトリクスとして生成
		ArithmeticMatrix returnMatrix = new ArithmeticMatrix(getMatrix(), getRowNameArray(), getColNameArray());
		
		//論理値のマトリクスに変換
		returnMatrix.convertLogicMatrix();
		
		//単位行列との論理和を取る
		returnMatrix.matrixCopy(returnMatrix.getOrMatrix(getElementaryMatrix()));
		
		//n-1乗する
		//式は (I + A)のn-1乗 Iは単位行列 +は論理和
		returnMatrix.matrixCopy(returnMatrix.getExponentMatrix(getRowLength() - 1));
		
		//論理値のマトリクスに変換
		returnMatrix.convertLogicMatrix();
		return returnMatrix;
		}
		else{
			throw new NotSquareMatrixException();
		}
	}
	
/**
* マトリクスの転置マトリクスを返します。
* 返されたマトリクスの行名と列名はそれぞれが入れ替わったもの（行名が列名に列名が行名に）になります。
* @return 転置マトリクス
*/
	public ArithmeticMatrix getTransposedMatrix(){
		ArithmeticMatrix returnMatrix = new ArithmeticMatrix(getColLength(), getRowLength(),
			getColNameArray(), getRowNameArray());
		for(int i = 0; i < returnMatrix.getRowLength(); i++){
			for(int j = 0; j < returnMatrix.getColLength(); j++){
				returnMatrix.setCell(i, j, getCell(j, i));
			}
		}
		return returnMatrix;
	}
	
/**
* マトリクスの要素を2次元配列で返します。
* @return 要素の2次元配列
*/
	public double[][] getMatrix(){
		Double d[][] = new Double[getRowLength()][getColLength()];
		double dou[][] = new double[getRowLength()][getColLength()];
		Object o[][] = new Object[getRowLength()][getColLength()];
		o = getObjectMatrix();
		for(int i=0; i < getRowLength(); i++){
			for(int j=0; j < getColLength(); j++){
				d[i][j] = (Double)o[i][j];
				dou[i][j] = d[i][j].doubleValue();
			}
		}
		return dou;
	}
	
}