AbstractIntervalMatrix.java

/*
 * Created on 2010/01/20
 * Copyright (C) 2010 Koga Laboratory. All rights reserved.
 *
 */
package org.mklab.cga.interval.matrix;

import java.io.OutputStreamWriter;

import org.mklab.cga.interval.scalar.IntervalComplexNumericalScalar;
import org.mklab.cga.interval.scalar.IntervalRealNumericalScalar;
import org.mklab.cga.interval.scalar.IntervalScalar;
import org.mklab.nfc.matrix.AbstractMatrix;
import org.mklab.nfc.matrix.ComplexNumericalMatrix;
import org.mklab.nfc.matrix.Matrix;
import org.mklab.nfc.matrix.MatrixSizeException;
import org.mklab.nfc.matrix.RealNumericalMatrix;
import org.mklab.nfc.scalar.ComplexNumericalScalar;
import org.mklab.nfc.scalar.RealNumericalScalar;
import org.mklab.nfc.scalar.Scalar;
import org.mklab.nfc.util.RoundMode;
import org.mklab.nfc.util.RoundModeManager;


/**
 * 区間行列を表す抽象クラスです。
 * 
 * @author koga
 * @version $Revision$, 2010/01/20
 * @param <IS> 区間スカラーの型
 * @param <IM> 区間行列の型
 * @param <S> スカラーの型
 * @param <M> 行列の型
 */
public abstract class AbstractIntervalMatrix<IS extends IntervalScalar<IS,IM,S,M>, IM extends IntervalMatrix<IS,IM,S,M>, S extends Scalar<S,M>, M extends Matrix<S,M> > extends AbstractMatrix<IS,IM> implements IntervalMatrix<IS,IM,S,M> {

  /** シリアル番号 */
  private static final long serialVersionUID = -8627760351748300972L;

  
  /**
   * 新しく生成された<code>AbstractIntervalMatrix</code>オブジェクトを初期化します。
   */
  public AbstractIntervalMatrix() {
    this(0, 0);
  }

  /**
   * 新しく生成された<code>AbstractIntervalMatrix</code>オブジェクトを初期化します。
   * 
   * @param rowSize 行の数
   * @param columnSize 列の数
   */
  public AbstractIntervalMatrix(final int rowSize, final int columnSize) {
    super(rowSize, columnSize);
  }


  /**
   * {@inheritDoc}
   */
  @Override
  public Object clone() {
    IM ans = (IM)super.clone();
    return ans;
  }


  /**
   * {@inheritDoc}
   */
  public IM unaryMinus() {
    return multiply(-1);
  }

  /**
   * {@inheritDoc}
   */
  public IM meanRowWise() {
    return sumRowWise().divide(getColumnSize());
  }

  /**
   * {@inheritDoc}
   */
  public IM meanColumnWise() {
    return sumColumnWise().divide(getRowSize());
  }

  /**
   * {@inheritDoc}
   */
  public IM cumulativeSum() {
    IM vector = reshape(1, getRowSize() * getColumnSize());
    IM cumulative = vector.cumulativeSumRowWise();
    return cumulative.reshape(getRowSize(), getColumnSize());
  }

  /**
   * {@inheritDoc}
   */
  public IM cumulativeProduct() {
    IM vector = reshape(1, getRowSize() * getColumnSize());
    IM cumulative = vector.cumulativeProductRowWise();
    return cumulative.reshape(getRowSize(), getColumnSize());
  }


  /**
   * {@inheritDoc}
   */
  public void printInfSup() {
    printInfSup("ans"); //$NON-NLS-1$
  }

  /**
   * {@inheritDoc}
   */
  public void printInfSup(final String name) {
    printInfSup(name, new OutputStreamWriter(System.out));
  }


  /**
   * {@inheritDoc}
   */
  public void printMidRad() {
    printMidRad("ans"); //$NON-NLS-1$
  }

  /**
   * {@inheritDoc}
   */
  public void printMidRad(final String name) {
    printMidRad(name, new OutputStreamWriter(System.out));
  }

  /**
   * {@inheritDoc}
   */
  public IM covariance(IM value) {
    if (hasSameRowSize(value) == false || hasSameColumnSize(value) == false) {
      throw new MatrixSizeException(MatrixSizeException.INCONSISTENT_COLUMN_NUMBER);
    }

    int size = getRowSize() * getColumnSize();
    IM x = reshape(size, 1);
    IM y = value.reshape(size, 1);
    IM xy = x.appendRight(y);

    IM xyZeroMean = xy.subtract(xy.createOnes(size, 1).multiply(xy.meanColumnWise()));
    return xyZeroMean.conjugateTranspose().multiply(xyZeroMean).divide(size - 1);
  }
  
  /**
   * 区間の中心を求めます。
   * 
   * @param <RIS> 実区間スカラーの型
   * @param <RIM> 実区間行列の型
   * @param <CIS> 複素区間スカラーの型
   * @param <CIM> 複素区間行列の型
   * @param <RS> 実スカラーの型
   * @param <RM> 実行列の型
   * @param <CS> 複素スカラーの型
   * @param <CM> 複素行列の型
   * @param inf infimum
   * @param sup supremum
   * @return 区間の中心。
   */
  public static <RIS extends IntervalRealNumericalScalar<RIS, RIM, CIS, CIM, RS, RM, CS, CM>, RIM extends IntervalRealNumericalMatrix<RIS, RIM, CIS, CIM, RS, RM, CS, CM>, CIS extends IntervalComplexNumericalScalar<RIS, RIM, CIS, CIM, RS, RM, CS, CM>, CIM extends IntervalComplexNumericalMatrix<RIS, RIM, CIS, CIM, RS, RM, CS, CM>, RS extends RealNumericalScalar<RS, RM, CS, CM>, RM extends RealNumericalMatrix<RS, RM, CS, CM>, CS extends ComplexNumericalScalar<RS, RM, CS, CM>, CM extends ComplexNumericalMatrix<RS, RM, CS, CM>> CM middle(
      CM inf, CM sup) {
    RoundModeManager manager = RoundModeManager.getManager();
    RoundMode oldRoundMode = manager.getRoundMode();

    manager.setRoundMode(RoundMode.ROUND_UP);
    CM mid = inf.add(sup.subtract(inf).divide(2));

    manager.setRoundMode(oldRoundMode);
    return mid;
  }
  
  /**
   * 区間の半径を求めます。
   * 
   * @param <RIS> 実区間スカラーの型
   * @param <RIM> 実区間行列の型
   * @param <CIS> 複素区間スカラーの型
   * @param <CIM> 複素区間行列の型
   * @param <RS> 実スカラーの型
   * @param <RM> 実行列の型
   * @param <CS> 複素スカラーの型
   * @param <CM> 複素行列の型
   * @param inf infimum
   * @param sup supremum
   * @return 区間の半径。
   */
  public static <RIS extends IntervalRealNumericalScalar<RIS, RIM, CIS, CIM, RS, RM, CS, CM>, RIM extends IntervalRealNumericalMatrix<RIS, RIM, CIS, CIM, RS, RM, CS, CM>, CIS extends IntervalComplexNumericalScalar<RIS, RIM, CIS, CIM, RS, RM, CS, CM>, CIM extends IntervalComplexNumericalMatrix<RIS, RIM, CIS, CIM, RS, RM, CS, CM>, RS extends RealNumericalScalar<RS, RM, CS, CM>, RM extends RealNumericalMatrix<RS, RM, CS, CM>, CS extends ComplexNumericalScalar<RS, RM, CS, CM>, CM extends ComplexNumericalMatrix<RS, RM, CS, CM>> RM radius(CM inf, CM sup) {
    RoundModeManager manager = RoundModeManager.getManager();
    RoundMode oldRoundMode = manager.getRoundMode();

    manager.setRoundMode(RoundMode.ROUND_UP);
    CM mid = middle(inf, sup);
    RM rad = mid.subtract(inf).absElementWise().getRealPart();

    manager.setRoundMode(oldRoundMode);
    return rad;
  }
  
  /**
   * 下限を返します。
   * 
   * @param <RIS> 実区間スカラーの型
   * @param <RIM> 実区間行列の型
   * @param <CIS> 複素区間スカラーの型
   * @param <CIM> 複素区間行列の型
   * @param <RS> 実スカラーの型
   * @param <RM> 実行列の型
   * @param <CS> 複素スカラーの型
   * @param <CM> 複素行列の型
   * @param mid 中心
   * @param rad 半径
   * @return 下限
   */
  public static <RIS extends IntervalRealNumericalScalar<RIS, RIM, CIS, CIM, RS, RM, CS, CM>, RIM extends IntervalRealNumericalMatrix<RIS, RIM, CIS, CIM, RS, RM, CS, CM>, CIS extends IntervalComplexNumericalScalar<RIS, RIM, CIS, CIM, RS, RM, CS, CM>, CIM extends IntervalComplexNumericalMatrix<RIS, RIM, CIS, CIM, RS, RM, CS, CM>, RS extends RealNumericalScalar<RS, RM, CS, CM>, RM extends RealNumericalMatrix<RS, RM, CS, CM>, CS extends ComplexNumericalScalar<RS, RM, CS, CM>, CM extends ComplexNumericalMatrix<RS, RM, CS, CM>> RM infimum(RM mid, RM rad) {
    RoundModeManager manager = RoundModeManager.getManager();
    RoundMode oldRoundMode = manager.getRoundMode();

    manager.setRoundMode(RoundMode.ROUND_DOWN);
    RM inf = mid.subtract(rad);

    manager.setRoundMode(oldRoundMode);
    return inf;
  }

  /**
   * 上限を返します。
   * 
   * @param <RIS> 実区間スカラーの型
   * @param <RIM> 実区間行列の型
   * @param <CIS> 複素区間スカラーの型
   * @param <CIM> 複素区間行列の型
   * @param <RS> 実スカラーの型
   * @param <RM> 実行列の型
   * @param <CS> 複素スカラーの型
   * @param <CM> 複素行列の型
   * @param mid 中心
   * @param radus 半径
   * @return 上限
   */
  public static <RIS extends IntervalRealNumericalScalar<RIS, RIM, CIS, CIM, RS, RM, CS, CM>, RIM extends IntervalRealNumericalMatrix<RIS, RIM, CIS, CIM, RS, RM, CS, CM>, CIS extends IntervalComplexNumericalScalar<RIS, RIM, CIS, CIM, RS, RM, CS, CM>, CIM extends IntervalComplexNumericalMatrix<RIS, RIM, CIS, CIM, RS, RM, CS, CM>, RS extends RealNumericalScalar<RS, RM, CS, CM>, RM extends RealNumericalMatrix<RS, RM, CS, CM>, CS extends ComplexNumericalScalar<RS, RM, CS, CM>, CM extends ComplexNumericalMatrix<RS, RM, CS, CM>> RM supremum(RM mid, RM radus) {
    RoundModeManager manager = RoundModeManager.getManager();
    RoundMode oldRoundMode = manager.getRoundMode();

    manager.setRoundMode(RoundMode.ROUND_UP);
    RM sup = mid.add(radus);

    manager.setRoundMode(oldRoundMode);
    return sup;
  }
}