AbstractIntervalRealNumericalMatrix.java

/*
 * Created on 2003/07/29
 *
 * Copyright (C) 2004 Koga Laboratory. All rights reserved.
 */
package org.mklab.cga.interval.matrix;

import java.io.Writer;

import org.mklab.cga.eigen.RealEigenVerifier;
import org.mklab.cga.eigen.RealRumpMethod;
import org.mklab.cga.interval.scalar.DoubleIntervalNumber;
import org.mklab.cga.interval.scalar.IntervalComplexNumericalScalar;
import org.mklab.cga.interval.scalar.IntervalRealNumericalScalar;
import org.mklab.cga.linear.LinearEquationVerifier;
import org.mklab.cga.linear.RealIntlabMethod;
import org.mklab.cga.util.IntervalUtil;
import org.mklab.nfc.matrix.BooleanMatrix;
import org.mklab.nfc.matrix.ComplexNumericalMatrix;
import org.mklab.nfc.matrix.IntMatrix;
import org.mklab.nfc.matrix.NormType;
import org.mklab.nfc.matrix.RealNumericalMatrix;
import org.mklab.nfc.scalar.ComplexNumericalScalar;
import org.mklab.nfc.scalar.RealNumericalScalar;
import org.mklab.nfc.util.RoundMode;
import org.mklab.nfc.util.RoundModeManager;


/**
 * 実区間行列を表すクラスです。
 * 
 * @author Hiroki
 * @version $Revision: 1.72 $. 2004/07/01
 * @param <RIS> 実区間スカラーの型
 * @param <RIM> 実区間行列の型
 * @param <CIS> 複素区間スカラーの型
 * @param <CIM> 複素区間行列の型
 * @param <RS> 実スカラーの型
 * @param <RM> 実行列の型
 * @param <CS> 複素スカラーの型
 * @param <CM> 複素行列の型
 */
public abstract class AbstractIntervalRealNumericalMatrix<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>>
    extends AbstractIntervalNumericalMatrix<RIS, RIM, RS, RM> implements IntervalRealNumericalMatrix<RIS, RIM, CIS, CIM, RS, RM, CS, CM> {

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

  /** 区間の下限 */
  protected RM infimum;

  /** 区間の上限 */
  protected RM supremum;

  /** 区間の中心 */
  protected RM middle;

  /** 区間の半径 */
  protected RM radius;
  
  /**
   * 新しく生成された{@link AbstractIntervalRealNumericalMatrix}オブジェクトを初期化します。
   */
  public AbstractIntervalRealNumericalMatrix() {
    super();
  }

  /**
   * 区間の配列から区間行列を作成します。
   * 
   * @param intervals 行列の要素(区間)
   */
  public AbstractIntervalRealNumericalMatrix(RIS[][] intervals) {
    super(intervals.length, intervals.length == 0 ? 0 : intervals[0].length);

    int rowSize = intervals.length;
    int columnSize = intervals[0].length;

    RS unit = intervals[0][0].getMiddle();
    RS[][] infElements = unit.createArray(rowSize, columnSize);
    RS[][] supElements = unit.createArray(rowSize, columnSize);

    for (int i = 0; i < rowSize; i++) {
      for (int j = 0; j < columnSize; j++) {
        final RIS interval = intervals[i][j];
        infElements[i][j] = interval.getInfimum();
        supElements[i][j] = interval.getSupremum();
      }
    }

    RM inf = infElements[0][0].createGrid(rowSize, columnSize, infElements);
    RM sup = supElements[0][0].createGrid(rowSize, columnSize, supElements);

    this.infimum = inf;
    this.supremum = sup;
    this.middle = mid(inf, sup);
    this.radius = rad(this.middle, inf);
  }

  /**
   * 区間の配列から区間行列を作成します
   * 
   * @param intervals 行列の要素(区間)
   */
  public AbstractIntervalRealNumericalMatrix(RIS[] intervals) {
    super(intervals.length, 1);

    final int size = intervals.length;

    RS unit = intervals[0].getMiddle();
    RS[][] infElements = unit.createArray(size, 1);
    RS[][] supElements = unit.createArray(size, 1);

    for (int i = 0; i < size; i++) {
      final RIS interval = intervals[i];
      infElements[i][0] = interval.getInfimum();
      supElements[i][0] = interval.getSupremum();
    }

    RM inf = infElements[0][0].createGrid(size, 1, infElements);
    RM sup = supElements[0][0].createGrid(size, 1, supElements);

    this.infimum = inf;
    this.supremum = sup;
    this.middle = mid(inf, sup);
    this.radius = rad(this.middle, inf);
  }

  //  /**
  //   * 指定された中心と半径をもつ実区間行列を生成します。
  //   * 
  //   * @param <T> 成分の型
  //   * 
  //   * @param middle 中心
  //   * @param radius 半径
  //   * @return 実区間行列
  //   */
  //  public static <T extends NumericalScalar<T>> AbstractIntervalRealNumericalMatrix<T> createWithMiddleRadius(NumericalMatrix<T> middle, NumericalMatrix<T> radius) {
  //    if (middle.isReal() == false || radius.isReal() == false) {
  //      throw new IllegalArgumentException("Not a real matrix"); //$NON-NLS-1$
  //    }
  //
  //    final AbstractIntervalRealNumericalMatrix<T> ans = new AbstractIntervalRealNumericalMatrix<>();
  //    ans.middle = middle;
  //    ans.radius = radius;
  //    ans.infimum = ans.inf(middle, radius);
  //    ans.supremum = ans.sup(middle, radius);
  //    return ans;
  //  }

  //  /**
  //   * 指定された下限と上限をもつ実区間行列を生成します。
  //   * 
  //   * @param infimum 下限
  //   * @param supremum 上限
  //   * @return 実区間行列
  //   */
  //  public static RealIntervalMatrix createWithInfimumSupremum(NumericalMatrixOperator<?> infimum, NumericalMatrixOperator<?> supremum) {
  //    if (infimum.isReal() == false || supremum.isReal() == false) {
  //      throw new IllegalArgumentException("Not a real matrix"); //$NON-NLS-1$
  //    }
  //
  //    final RealIntervalMatrix ans = new RealIntervalMatrix();
  //    
  //    ans.infimum = infimum;
  //    ans.supremum = supremum;
  //    ans.middle = ans.mid(infimum, supremum);
  //    ans.radius = ans.rad(ans.middle, infimum);
  //    return ans;
  //  }

  /**
   * 指定された上限と下限をもつ実区間行列を生成します。
   * 
   * @param infimum 下限
   * @param supremum 上限
   */
  public AbstractIntervalRealNumericalMatrix(final RM infimum, final RM supremum) {
    super(infimum.getRowSize(), infimum.getColumnSize());

    this.infimum = infimum;
    this.supremum = supremum;
    this.middle = mid(infimum, supremum);
    this.radius = rad(this.middle, infimum);
  }

  /**
   * 指定された行列を上限と下限とする実区間行列を生成します。
   * 
   * @param middle 行列
   */
  public AbstractIntervalRealNumericalMatrix(final RM middle) {
    super(middle.getRowSize(), middle.getColumnSize());

    this.middle = middle;
    this.radius = middle.createZero();
    this.infimum = middle.createClone();
    this.supremum = middle.createClone();
  }

//  /**
//   * Sets eigen verifier.
//   * 
//   * @param verifier eigen verifier.
//   */
//  public void setEigenVerifier(RealEigenVerifier<RIS,RIM,CIS,CIM,RS,RM,CS,CM> verifier) {
//    this.eigenVerifier = verifier;
//  }
//  
//  /**
//   * Returns eigen verifier.
//   * 
//   * @return eigen verifier
//   */
//  public RealEigenVerifier<RIS,RIM,CIS,CIM,RS,RM,CS,CM> getEigenVerifier() {
//    return this.eigenVerifier;
//  }
  
  /**
   * {@inheritDoc}
   */
  public RIM createZero(final int rowSize, final int columnSize) {
    return create(this.radius.createZero(rowSize, columnSize));
  }

  /**
   * {@inheritDoc}
   */
  public RIM createOnes(final int rowSize, final int columnSize) {
    return create(this.middle.createOnes(rowSize, columnSize));
  }

  /**
   * {@inheritDoc}
   */
  public RIM createUnit(final int rowSize, final int columnSize) {
    return create(this.middle.createUnit(rowSize, columnSize));
  }

  /**
   * {@inheritDoc}
   */
  public RIM add(final RIM y) {
    RoundModeManager manager = RoundModeManager.getManager();
    RoundMode oldRoundMode = manager.getRoundMode();

    manager.setRoundMode(RoundMode.ROUND_DOWN);
    RM inf = this.infimum.add(y.getInfimum());

    manager.setRoundMode(RoundMode.ROUND_UP);
    RM sup = this.supremum.add(y.getSupremum());

    manager.setRoundMode(oldRoundMode);
    return createInfSup(inf, sup);
  }

  /**
   * {@inheritDoc}
   */
  public RIM addElementWise(final RIS y) {// IRM+IR, IRM+IC
    RoundModeManager manager = RoundModeManager.getManager();
    RoundMode oldRoundMode = manager.getRoundMode();

    manager.setRoundMode(RoundMode.ROUND_DOWN);
    RM inf = this.infimum.addElementWise(y.getInfimum());

    manager.setRoundMode(RoundMode.ROUND_UP);
    RM sup = this.supremum.addElementWise(y.getSupremum());

    manager.setRoundMode(oldRoundMode);
    return createInfSup(inf, sup);
  }

  /**
   * {@inheritDoc}
   */
  public RIM add(final RM y) {
    RoundModeManager manager = RoundModeManager.getManager();
    RoundMode oldRoundMode = manager.getRoundMode();

    manager.setRoundMode(RoundMode.ROUND_DOWN);
    RM inf = this.infimum.add(y);

    manager.setRoundMode(RoundMode.ROUND_UP);
    RM sup = this.supremum.add(y);

    manager.setRoundMode(oldRoundMode);
    return createInfSup(inf, sup);
  }

  /**
   * {@inheritDoc}
   */
  public RIM addElementWise(final int y) {
    RoundModeManager manager = RoundModeManager.getManager();
    RoundMode oldRoundMode = manager.getRoundMode();

    manager.setRoundMode(RoundMode.ROUND_DOWN);
    RM inf = this.infimum.addElementWise(y);

    manager.setRoundMode(RoundMode.ROUND_UP);
    RM sup = this.supremum.addElementWise(y);

    manager.setRoundMode(oldRoundMode);
    return createInfSup(inf, sup);
  }

  /**
   * {@inheritDoc}
   */
  public RIM addElementWise(final double y) {
    RoundModeManager manager = RoundModeManager.getManager();
    RoundMode oldRoundMode = manager.getRoundMode();

    manager.setRoundMode(RoundMode.ROUND_DOWN);
    RM inf = this.infimum.addElementWise(y);

    manager.setRoundMode(RoundMode.ROUND_UP);
    RM sup = this.supremum.addElementWise(y);

    manager.setRoundMode(oldRoundMode);
    return createInfSup(inf, sup);
  }

  /**
   * @param y y
   * @return result
   */
  public RIM addElementWise(final RS y) {
    RoundModeManager manager = RoundModeManager.getManager();
    RoundMode oldRoundMode = manager.getRoundMode();

    manager.setRoundMode(RoundMode.ROUND_DOWN);
    RM inf = this.infimum.addElementWise(y);

    manager.setRoundMode(RoundMode.ROUND_UP);
    RM sup = this.supremum.addElementWise(y);

    manager.setRoundMode(oldRoundMode);
    return createInfSup(inf, sup);
  }

  /**
   * {@inheritDoc}
   */
  public RIM subtract(final RIM y) {
    RoundModeManager manager = RoundModeManager.getManager();
    RoundMode oldRoundMode = manager.getRoundMode();

    manager.setRoundMode(RoundMode.ROUND_DOWN);
    RM inf = this.infimum.subtract(y.getSupremum());

    manager.setRoundMode(RoundMode.ROUND_UP);
    RM sup = this.supremum.subtract(y.getInfimum());

    manager.setRoundMode(oldRoundMode);
    return createInfSup(inf, sup);
  }

  /**
   * {@inheritDoc}
   */
  public RIM subtractElementWise(final RIS y) {
    RoundModeManager manager = RoundModeManager.getManager();
    RoundMode oldRoundMode = manager.getRoundMode();

    manager.setRoundMode(RoundMode.ROUND_DOWN);
    RM inf = this.infimum.subtractElementWise(y.getSupremum());

    manager.setRoundMode(RoundMode.ROUND_UP);
    RM sup = this.supremum.subtractElementWise(y.getInfimum());

    manager.setRoundMode(oldRoundMode);
    return createInfSup(inf, sup);
  }

  /**
   * {@inheritDoc}
   */
  public RIM subtract(final RM y) {
    RoundModeManager manager = RoundModeManager.getManager();
    RoundMode oldRoundMode = manager.getRoundMode();

    manager.setRoundMode(RoundMode.ROUND_DOWN);
    RM inf = this.infimum.subtract(y);

    manager.setRoundMode(RoundMode.ROUND_UP);
    RM sup = this.supremum.subtract(y);

    manager.setRoundMode(oldRoundMode);
    return createInfSup(inf, sup);
  }

  /**
   * {@inheritDoc}
   */
  public RIM subtractElementWise(final int y) {
    RoundModeManager manager = RoundModeManager.getManager();
    RoundMode oldRoundMode = manager.getRoundMode();

    manager.setRoundMode(RoundMode.ROUND_DOWN);
    RM inf = this.infimum.subtractElementWise(y);

    manager.setRoundMode(RoundMode.ROUND_UP);
    RM sup = this.supremum.subtractElementWise(y);

    manager.setRoundMode(oldRoundMode);
    return createInfSup(inf, sup);
  }

  /**
   * {@inheritDoc}
   */
  public RIM subtractElementWise(final double y) {
    RoundModeManager manager = RoundModeManager.getManager();
    RoundMode oldRoundMode = manager.getRoundMode();

    manager.setRoundMode(RoundMode.ROUND_DOWN);
    RM inf = this.infimum.subtractElementWise(y);

    manager.setRoundMode(RoundMode.ROUND_UP);
    RM sup = this.supremum.subtractElementWise(y);

    manager.setRoundMode(oldRoundMode);
    return createInfSup(inf, sup);
  }

  /**
   * @param y y
   * @return result
   */
  public RIM subtractElementWise(final RS y) {
    RoundModeManager manager = RoundModeManager.getManager();
    RoundMode oldRoundMode = manager.getRoundMode();

    manager.setRoundMode(RoundMode.ROUND_DOWN);
    RM inf = this.infimum.subtractElementWise(y);

    manager.setRoundMode(RoundMode.ROUND_UP);
    RM sup = this.supremum.subtractElementWise(y);

    manager.setRoundMode(oldRoundMode);
    return createInfSup(inf, sup);
  }

  /**
   * {@inheritDoc}
   */
  public RIM multiply(final RIM y) {
    RoundModeManager manager = RoundModeManager.getManager();
    RoundMode oldRoundMode = manager.getRoundMode();

    manager.setRoundMode(RoundMode.ROUND_UP);
    RM xc = this.supremum.add(this.infimum).divide(2);
    RM xr = xc.subtract(this.infimum);
    RM yc = y.getSupremum().add(y.getInfimum()).divide(2);
    RM yr = yc.subtract(y.getInfimum());
    RM sup = (xc.multiply(yc)).add((xc).absElementWise().multiply(yr)).add(xr.multiply((yc).absElementWise())).add(xr.multiply(yr));

    manager.setRoundMode(RoundMode.ROUND_DOWN);
    RM inf = (xc.multiply(yc)).add((xc).absElementWise().unaryMinus().multiply(yr).add(xr.multiply((yc).absElementWise().unaryMinus()).add(xr.unaryMinus().multiply(yr))));

    manager.setRoundMode(oldRoundMode);
    return createInfSup(inf, sup);
  }

  /**
   * {@inheritDoc}
   */
  public RIM multiply(final RM y) {
    RoundModeManager manager = RoundModeManager.getManager();
    RoundMode oldRoundMode = manager.getRoundMode();

    manager.setRoundMode(RoundMode.ROUND_UP);
    RM rad = this.radius.multiply((y).absElementWise());
    RM sup = this.middle.multiply(y).add(rad);

    manager.setRoundMode(RoundMode.ROUND_DOWN);
    RM inf = this.middle.multiply(y).subtract(rad);

    manager.setRoundMode(oldRoundMode);
    return createInfSup(inf, sup);
  }

  /**
   * {@inheritDoc}
   */
  public RIM multiplyElementWise(final RIM b) {
    RoundModeManager manager = RoundModeManager.getManager();
    RoundMode oldRoundMode = manager.getRoundMode();

    manager.setRoundMode(RoundMode.ROUND_DOWN);
    RM inf = (this.infimum.multiplyElementWise(b.getInfimum())).minElementWise(this.infimum.multiplyElementWise(b.getSupremum()));
    inf = (inf).minElementWise(this.supremum.multiplyElementWise(b.getInfimum()));
    inf = (inf).minElementWise(this.supremum.multiplyElementWise(b.getSupremum()));

    manager.setRoundMode(RoundMode.ROUND_UP);
    RM sup = (this.infimum.multiplyElementWise(b.getInfimum())).maxElementWise(this.infimum.multiplyElementWise(b.getSupremum()));
    sup = (sup).maxElementWise(this.supremum.multiplyElementWise(b.getInfimum()));
    sup = (sup).maxElementWise(this.supremum.multiplyElementWise(b.getSupremum()));

    manager.setRoundMode(oldRoundMode);
    return createInfSup(inf, sup);
  }

  /**
   * {@inheritDoc}
   */
  public RIM multiply(final RIS b) {
    RoundModeManager manager = RoundModeManager.getManager();
    RoundMode oldRoundMode = manager.getRoundMode();

    manager.setRoundMode(RoundMode.ROUND_DOWN);
    RM inf = (this.infimum.multiply(b.getInfimum())).minElementWise(this.getInfimum().multiply(b.getSupremum()));
    inf = (inf).minElementWise(this.supremum.multiply(b.getInfimum()));
    inf = (inf).minElementWise(this.supremum.multiply(b.getSupremum()));

    manager.setRoundMode(RoundMode.ROUND_UP);
    RM sup = (this.infimum.multiply(b.getInfimum())).maxElementWise(this.infimum.multiply(b.getSupremum()));
    sup = (sup).maxElementWise(this.supremum.multiply(b.getInfimum()));
    sup = (sup).maxElementWise(this.supremum.multiply(b.getSupremum()));

    manager.setRoundMode(oldRoundMode);
    return createInfSup(inf, sup);
  }

  /**
   * @param y y
   * @return result
   */
  public RIM multiplyElementWise(final RM y) {
    RoundModeManager manager = RoundModeManager.getManager();
    RoundMode oldRoundMode = manager.getRoundMode();

    manager.setRoundMode(RoundMode.ROUND_DOWN);
    RM inf = (this.infimum.multiplyElementWise(y)).minElementWise(this.supremum.multiplyElementWise(y));

    manager.setRoundMode(RoundMode.ROUND_UP);
    RM sup = (this.infimum.multiplyElementWise(y)).maxElementWise(this.supremum.multiplyElementWise(y));

    manager.setRoundMode(oldRoundMode);
    return createInfSup(inf, sup);
  }

  /**
   * {@inheritDoc}
   */
  public RIM multiply(final int y) {// IR*R
    RoundModeManager manager = RoundModeManager.getManager();
    RoundMode oldRoundMode = manager.getRoundMode();

    manager.setRoundMode(RoundMode.ROUND_DOWN);
    RM inf = (this.infimum.multiply(y)).minElementWise(this.supremum.multiply(y));

    manager.setRoundMode(RoundMode.ROUND_UP);
    RM sup = (this.infimum.multiply(y)).maxElementWise(this.supremum.multiply(y));

    manager.setRoundMode(oldRoundMode);
    return createInfSup(inf, sup);
  }

  /**
   * {@inheritDoc}
   */
  public RIM multiply(final double y) {// IR*R
    RoundModeManager manager = RoundModeManager.getManager();
    RoundMode oldRoundMode = manager.getRoundMode();

    manager.setRoundMode(RoundMode.ROUND_DOWN);
    RM inf = (this.infimum.multiply(y)).minElementWise(this.supremum.multiply(y));

    manager.setRoundMode(RoundMode.ROUND_UP);
    RM sup = (this.infimum.multiply(y)).maxElementWise(this.supremum.multiply(y));

    manager.setRoundMode(oldRoundMode);
    return createInfSup(inf, sup);
  }

  /**
   * @param d d
   * @return result
   */
  public RIM multiply(final RS d) {
    RoundModeManager manager = RoundModeManager.getManager();
    RoundMode oldRoundMode = manager.getRoundMode();

    manager.setRoundMode(RoundMode.ROUND_DOWN);
    RM inf = (this.infimum.multiply(d)).minElementWise(this.supremum.multiply(d));

    manager.setRoundMode(RoundMode.ROUND_UP);
    RM sup = (this.infimum.multiply(d)).maxElementWise(this.supremum.multiply(d));

    manager.setRoundMode(oldRoundMode);
    return createInfSup(inf, sup);
  }

  /**
   * @param b b
   * @return result
   */
  public RIM divideElementWise(final RM b) {
    throw new RuntimeException("Not implemented."); //$NON-NLS-1$
  }

  /**
   * {@inheritDoc}
   */
  public RIM divideElementWise(final RIM b) {
    RoundModeManager manager = RoundModeManager.getManager();
    RoundMode oldRoundMode = manager.getRoundMode();

    RIM bb = b;

    manager.setRoundMode(RoundMode.ROUND_DOWN);
    RM inf = (this.infimum.divideElementWise(bb.getInfimum())).minElementWise(this.infimum.divideElementWise(bb.getSupremum()));
    inf = (inf).minElementWise(this.supremum.divideElementWise(bb.getInfimum()));
    inf = (inf).minElementWise(this.supremum.divideElementWise(bb.getSupremum()));

    manager.setRoundMode(RoundMode.ROUND_UP);
    RM sup = (this.infimum.divideElementWise(bb.getInfimum())).maxElementWise(this.infimum.divideElementWise(bb.getSupremum()));
    sup = (sup).maxElementWise(this.supremum.divideElementWise(bb.getInfimum()));
    sup = (sup).maxElementWise(this.supremum.divideElementWise(bb.getSupremum()));

    manager.setRoundMode(oldRoundMode);
    return createInfSup(inf, sup);
  }

  /**
   * {@inheritDoc}
   */
  public RIM divide(final int value) {
    RoundModeManager manager = RoundModeManager.getManager();
    RoundMode oldRoundMode = manager.getRoundMode();

    manager.setRoundMode(RoundMode.ROUND_DOWN);
    RM inf = (this.infimum.divide(value)).minElementWise(this.supremum.divide(value));

    manager.setRoundMode(RoundMode.ROUND_UP);
    RM sup = (this.infimum.divide(value)).maxElementWise(this.supremum.divide(value));

    RIM c = createInfSup(inf, sup);
    manager.setRoundMode(oldRoundMode);
    return c;
  }

  /**
   * {@inheritDoc}
   */
  public RIM divide(final double value) {
    RoundModeManager manager = RoundModeManager.getManager();
    RoundMode oldRoundMode = manager.getRoundMode();

    manager.setRoundMode(RoundMode.ROUND_DOWN);
    RM inf = (this.infimum.divide(value)).minElementWise(this.supremum.divide(value));

    manager.setRoundMode(RoundMode.ROUND_UP);
    RM sup = (this.infimum.divide(value)).maxElementWise(this.supremum.divide(value));

    RIM c = createInfSup(inf, sup);
    manager.setRoundMode(oldRoundMode);
    return c;
  }

  /**
   * {@inheritDoc}
   */
  public RIM divide(final RIS b) {
    RoundModeManager manager = RoundModeManager.getManager();
    RoundMode oldRoundMode = manager.getRoundMode();

    manager.setRoundMode(RoundMode.ROUND_DOWN);
    RM inf = (this.infimum.divide((b.getInfimum()))).minElementWise(this.infimum.divide((b.getSupremum())));
    inf = (inf).minElementWise(this.supremum.divide((b.getInfimum())));
    inf = (inf).minElementWise(this.supremum.divide((b.getSupremum())));

    manager.setRoundMode(RoundMode.ROUND_UP);
    RM sup = (this.infimum.divide((b.getInfimum()))).maxElementWise(this.infimum.divide((b.getSupremum())));
    sup = (sup).maxElementWise(this.supremum.divide((b.getInfimum())));
    sup = (sup).maxElementWise(this.supremum.divide((b.getSupremum())));

    manager.setRoundMode(oldRoundMode);
    return createInfSup(inf, sup);
  }

  /**
   * {@inheritDoc}
   */
  public RIM inverse(double tolerance, boolean stopIfSingular) {
    throw new UnsupportedOperationException();
  }

  /**
   * {@inheritDoc}
   */
  public RIM inverseElementWise() {
    RM infInverse = this.infimum.inverseElementWise();
    RM supInverse = this.supremum.inverseElementWise();
    RM inf = infInverse.minElementWise(supInverse);
    RM sup = infInverse.maxElementWise(supInverse);
    return createInfSup(inf, sup);
  }

  /**
   * {@inheritDoc}
   */
  public RIM diagonalToVector() {
    final RM inf = this.infimum.diagonalToVector();
    final RM sup = this.supremum.diagonalToVector();
    return createInfSup(inf, sup);
  }

  /**
   * {@inheritDoc}
   */
  public RIM vectorToDiagonal() {
    final RM inf = this.infimum.vectorToDiagonal();
    final RM sup = this.supremum.vectorToDiagonal();
    return createInfSup(inf, sup);
  }

  /**
   * {@inheritDoc}
   */
  public RIM reshape(int newRowSize, int newColumnSize) {
    final RM inf = this.infimum.reshape(newRowSize, newColumnSize);
    final RM sup = this.supremum.reshape(newRowSize, newColumnSize);
    return createInfSup(inf, sup);
  }

  /**
   * {@inheritDoc}
   */
  public RIM resize(int newRowSize, int newColumnSize) {
    final RM inf = this.infimum.resize(newRowSize, newColumnSize);
    final RM sup = this.supremum.resize(newRowSize, newColumnSize);
    return createInfSup(inf, sup);
  }

  /**
   * {@inheritDoc}
   */
  public RM migElementWise() {
    BooleanMatrix B = this.infimum.compareElementWise(".<=", this.middle.createZero(this.infimum.getRowSize(), this.infimum.getColumnSize())).andElementWise( //$NON-NLS-1$
        this.supremum.compareElementWise(".>=", this.middle.createZero(this.supremum.getRowSize(), this.supremum.getColumnSize()))).notElementWise(); //$NON-NLS-1$
    IntMatrix zoB = IntervalUtil.toZOMatrix(B);

    RM C = (this.infimum).absElementWise().minElementWise(this.supremum);

    for (int i = 0; i < getRowSize(); i++) {
      for (int j = 0; j < getColumnSize(); j++) {
        if (zoB.getIntElement(i + 1, j + 1) == 0) {
          C.setElement(i + 1, j + 1, 0);
        }
      }
    }

    return C;
  }

  /**
   * {@inheritDoc}
   */
  public RM comparisonMatrix() {
    RM Ac = abssElementWise().unaryMinus();
    RM D = Ac.diagonalToVector();
    RM M = (diagonalToVector()).migElementWise();

    RS cUnit = Ac.getElement(1, 1);
    RS rUnit = M.getElement(1, 1);
    RS[] d1 = cUnit.createArray(D.length());
    RS[] d2 = rUnit.createArray(M.length());

    for (int i = 0; i < D.length(); i++) {
      d1[i] = D.getElement(i + 1, 1);
      d2[i] = M.getElement(i + 1, 1);
    }

    Ac = Ac.subtract(d1[0].createGrid(d1).vectorToDiagonal()).add(d2[0].createGrid(d2).vectorToDiagonal());
    return Ac;
  }

  /**
   * {@inheritDoc}
   */
  public RM abssElementWise() {
    RoundModeManager manager = RoundModeManager.getManager();
    RoundMode oldRoundMode = manager.getRoundMode();

    manager.setRoundMode(RoundMode.ROUND_UP);
    RM mid = mid(this.infimum, this.supremum);
    RM abss = mid.absElementWise().add(rad(mid, this.infimum));

    manager.setRoundMode(oldRoundMode);
    return abss;
  }

  /**
   * 下限を返します。
   * 
   * @param mid 中心
   * @param rad 半径
   * @return 下限
   */
  public RM inf(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 mid 中心
   * @param radus 半径
   * @return 上限
   */
  public RM sup(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;
  }

  /**
   * 区間の中心を求めます。 区間内のすべての点は、 &lt;中心(mid), 半径rad&gt;にあります。
   * 
   * @param inf 上限
   * @param sup 下限
   * 
   * @return 区間の中心
   */
  public RM mid(RM inf, RM sup) {
    RoundModeManager manager = RoundModeManager.getManager();
    RoundMode oldRoundMode = manager.getRoundMode();

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

    manager.setRoundMode(oldRoundMode);
    return mid;
  }

  /**
   * 区間の半径を求めます。 区間内のすべての点は、 &lt;中心(mid), 半径rad&gt;にあります。
   * 
   * @param mid 中心
   * @param inf 下限
   * 
   * @return 区間の半径
   */
  public RM rad(RM mid, RM inf) {
    RoundModeManager manager = RoundModeManager.getManager();
    RoundMode oldRoundMode = manager.getRoundMode();

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

    manager.setRoundMode(oldRoundMode);
    return rad;
  }

  /**
   * {@inheritDoc}
   */
  public boolean isZero(final double tolerance) {
    return this.infimum.isZero(tolerance) && this.supremum.isZero(tolerance);
  }

  /**
   * {@inheritDoc}
   */
  public boolean isUnit(final double tolerance) {
    return this.infimum.isUnit(tolerance) && this.supremum.isUnit(tolerance);
  }

  /**
   * {@inheritDoc}
   */
  public BooleanMatrix isNanElementWise() {
    return this.infimum.isNanElementWise().orElementWise(this.supremum.isNanElementWise());
  }

  /**
   * {@inheritDoc}
   */
  public BooleanMatrix isInfiniteElementWise() {
    return this.infimum.isInfiniteElementWise().orElementWise(this.supremum.isInfiniteElementWise());
  }

  /**
   * {@inheritDoc}
   */
  public BooleanMatrix isFiniteElementWise() {
    return this.infimum.isFiniteElementWise().andElementWise(this.supremum.isFiniteElementWise());
  }

  /**
   * {@inheritDoc}
   */
  public boolean isReal() {
    return true;
  }

  /**
   * {@inheritDoc}
   */
  public boolean isComplex() {
    return false;
  }

  /**
   * 区間行列の上下限に対してぞれぞれの絶対値をとり、 上下限の絶対値最大の要素を行列として返します。
   * 
   * @return 上下限の各要素の絶対最大をもつ行列。
   */
  private RM absMax() {
    RIM abs = absElementWise();
    return (abs.getInfimum()).maxElementWise(abs.getSupremum());
  }

  /**
   * {@inheritDoc}
   */
  public RM getError() {
    RoundModeManager manager = RoundModeManager.getManager();
    RoundMode oldRoundMode = manager.getRoundMode();

    manager.setRoundMode(RoundMode.ROUND_UP);
    RM error = this.supremum.subtract(this.infimum);

    manager.setRoundMode(oldRoundMode);
    return error;
  }

  /**
   * {@inheritDoc}
   */
  public RIM transpose() {
    RM inf = this.infimum.transpose();
    RM sup = this.supremum.transpose();
    return createInfSup(inf, sup);
  }

  /**
   * {@inheritDoc}
   */
  public boolean equals(RIM opponent, double tolerance) {
    return this.infimum.equals(opponent.getInfimum(), tolerance) && this.supremum.equals(opponent.getSupremum(), tolerance);
  }

  //  /**
  //   * @see org.mklab.cga.interval.IntervalMatrix#copy(org.mklab.nfc.matrix.Matrix)
  //   */
  //  public void copy(final Matrix source) {
  //    if (isSameSize(source) == false) {
  //      throw new ConflictionException();
  //    }
  //    
  //    if (source instanceof IntMatrix) {
  //      copy((IntMatrix)source);
  //      return;
  //    }
  //    if (source instanceof DoubleMatrix) {
  //      copy(source);
  //      return;
  //    }
  //    if (source instanceof IntervalMatrix) {
  //      copy((IntervalMatrix)source);
  //      return;
  //    }
  //
  //    throw new RuntimeException("Not Implemented."); //$NON-NLS-1$
  //  }

  /**
   * {@inheritDoc}
   */
  public void copy(final RIM source) {
    this.infimum.copy(source.getInfimum());
    this.supremum.copy(source.getSupremum());
    updateMiddleRadius();
  }

//  /**
//   * {@inheritDoc}
//   */
//  public void copy(final IntMatrix source) {
//    this.infimum.copy(source);
//    this.supremum.copy(source);
//    updateMiddleRadius();
//  }
//
//  /**
//   * {@inheritDoc}
//   */
//  public void copy(final DoubleMatrix source) {
//    this.infimum.copy(source);
//    this.supremum.copy(source);
//    updateMiddleRadius();
//  }
  
  /**
   * {@inheritDoc}
   */
  @Override
  public Object clone() {
    AbstractIntervalRealNumericalMatrix<RIS, RIM, CIS, CIM, RS, RM, CS, CM> ans = (AbstractIntervalRealNumericalMatrix<RIS, RIM, CIS, CIM, RS, RM, CS, CM>)super.clone();
    ans.infimum = this.infimum.createClone();
    ans.supremum= this.supremum.createClone();
    ans.middle = this.middle.createClone();
    ans.radius = this.radius.createClone();
    return ans;
  }

  /* Setter */

  /**
   * {@inheritDoc}
   */
  public void setElement(final int index, final int value) {
    this.infimum.setElement(index, value);
    this.supremum.setElement(index, value);
    updateMiddleRadius();
  }

  /**
   * {@inheritDoc}
   */
  public void setElement(final int index, final double value) {
    this.infimum.setElement(index, value);
    this.supremum.setElement(index, value);
    updateMiddleRadius();
  }

  /**
   * @param index index
   * @param value value
   */
  public void setElement(final int index, final RS value) {
    if (value.isReal() == false) {
      throw new RuntimeException("Not Implemented."); //$NON-NLS-1$
    }
    this.infimum.setElement(index, value);
    this.supremum.setElement(index, value);
    updateMiddleRadius();
  }

  /**
   * {@inheritDoc}
   */
  public void setElement(final int index, final RIS value) {
    if (value.isReal() == false) {
      throw new RuntimeException("Not Implemented."); //$NON-NLS-1$
    }
    this.infimum.setElement(index, value.getInfimum());
    this.supremum.setElement(index, value.getSupremum());
    updateMiddleRadius();
  }

  /**
   * {@inheritDoc}
   */
  public void setElement(final int row, final int column, final int value) {
    this.infimum.setElement(row, column, value);
    this.supremum.setElement(row, column, value);
    updateMiddleRadius();
  }

  /**
   * {@inheritDoc}
   */
  public void setElement(final int row, final int column, final double value) {
    this.infimum.setElement(row, column, value);
    this.supremum.setElement(row, column, value);
    updateMiddleRadius();
  }

  /**
   * @param row row
   * @param column column
   * @param value value
   */
  public void setElement(final int row, final int column, final RS value) {
    if (value.isReal() == false) {
      throw new RuntimeException("Not Implemented."); //$NON-NLS-1$
    }
    this.infimum.setElement(row, column, value);
    this.supremum.setElement(row, column, value);
    updateMiddleRadius();
  }

  /**
   * {@inheritDoc}
   */
  public void setElement(final int row, final int column, final RIS value) {
    if (value.isReal() == false) {
      throw new RuntimeException("Not Implemented."); //$NON-NLS-1$
    }
    this.infimum.setElement(row, column, value.getInfimum());
    this.supremum.setElement(row, column, value.getSupremum());
    updateMiddleRadius();
  }

  /**
   * {@inheritDoc}
   */
  public void setSubMatrix(int rowMinimum, int rowMaximum, int columnMinimum, int columnMaximum, RIM source) {
    if (source instanceof AbstractIntervalRealNumericalMatrix == false) {
      throw new RuntimeException("Not implemented"); //$NON-NLS-1$
    }
    this.infimum.setSubMatrix(rowMinimum, rowMaximum, columnMinimum, columnMaximum, source.getInfimum());
    this.supremum.setSubMatrix(rowMinimum, rowMaximum, columnMinimum, columnMaximum, source.getSupremum());
    updateMiddleRadius();
  }

  /**
   * @param rowMinimum minimum row
   * @param rowMaximum maximum row
   * @param columnMinimum minimum column
   * @param columnMaximum maximum column
   * @param source source
   */
  public void setSubMatrix(int rowMinimum, int rowMaximum, int columnMinimum, int columnMaximum, RM source) {
    this.infimum.setSubMatrix(rowMinimum, rowMaximum, columnMinimum, columnMaximum, source);
    this.supremum.setSubMatrix(rowMinimum, rowMaximum, columnMinimum, columnMaximum, source);
    updateMiddleRadius();
  }

  /**
   * {@inheritDoc}
   */
  public void setSubMatrix(IntMatrix rowIndex, int columnMinimum, int columnMaximum, RIM source) {
    if (source instanceof AbstractIntervalRealNumericalMatrix == false) {
      throw new RuntimeException("Not implemented"); //$NON-NLS-1$
    }
    this.infimum.setSubMatrix(rowIndex, columnMinimum, columnMaximum, source.getInfimum());
    this.supremum.setSubMatrix(rowIndex, columnMinimum, columnMaximum, source.getSupremum());
    updateMiddleRadius();
  }

  /**
   * @param rowIndex row index
   * @param columnMinimum minimum column
   * @param columnMaximum maximum column
   * @param source source
   */
  public void setSubMatrix(IntMatrix rowIndex, int columnMinimum, int columnMaximum, RM source) {
    this.infimum.setSubMatrix(rowIndex, columnMinimum, columnMaximum, source);
    this.supremum.setSubMatrix(rowIndex, columnMinimum, columnMaximum, source);
    updateMiddleRadius();
  }

  /**
   * {@inheritDoc}
   */
  public void setSubMatrix(int rowMinimum, int rowMaximum, IntMatrix columnIndex, RIM source) {
    if (source instanceof AbstractIntervalRealNumericalMatrix == false) {
      throw new RuntimeException("Not implemented"); //$NON-NLS-1$
    }
    this.infimum.setSubMatrix(rowMinimum, rowMaximum, columnIndex, source.getInfimum());
    this.supremum.setSubMatrix(rowMinimum, rowMaximum, columnIndex, source.getSupremum());
    updateMiddleRadius();
  }

  /**
   * @param rowMinimum minimum row
   * @param rowMaximum maximum row
   * @param columnIndex column index
   * @param source source
   */
  public void setSubMatrix(int rowMinimum, int rowMaximum, IntMatrix columnIndex, RM source) {
    this.infimum.setSubMatrix(rowMinimum, rowMaximum, columnIndex, source);
    this.supremum.setSubMatrix(rowMinimum, rowMaximum, columnIndex, source);
    updateMiddleRadius();
  }

  /**
   * {@inheritDoc}
   */
  public void setSubMatrix(IntMatrix rowIndex, IntMatrix columnIndex, RIM source) {
    if (source instanceof AbstractIntervalRealNumericalMatrix == false) {
      throw new RuntimeException("Not implemented"); //$NON-NLS-1$
    }
    this.infimum.setSubMatrix(rowIndex, columnIndex, source.getInfimum());
    this.supremum.setSubMatrix(rowIndex, columnIndex, source.getSupremum());
    updateMiddleRadius();
  }

  /**
   * @param rowIndex row index
   * @param columnIndex column index
   * @param source source
   */
  public void setSubMatrix(IntMatrix rowIndex, IntMatrix columnIndex, RM source) {
    this.infimum.setSubMatrix(rowIndex, columnIndex, source);
    this.supremum.setSubMatrix(rowIndex, columnIndex, source);
    updateMiddleRadius();
  }

  /**
   * @param min min
   * @param max max
   * @param source source
   */
  public void setSubVector(int min, int max, RM source) {
    this.infimum.setSubVector(min, max, source);
    this.supremum.setSubVector(min, max, source);
    updateMiddleRadius();
  }

  /**
   * {@inheritDoc}
   */
  public void setSubVector(int minimum, int maximum, RIM source) {
    if (source instanceof AbstractIntervalRealNumericalMatrix == false) {
      throw new RuntimeException("Not implemented"); //$NON-NLS-1$
    }
    this.infimum.setSubVector(minimum, maximum, source.getInfimum());
    this.supremum.setSubVector(minimum, maximum, source.getSupremum());
    updateMiddleRadius();
  }

  /**
   * {@inheritDoc}
   */
  public void setSubVector(IntMatrix index, RIM source) {
    if (source instanceof AbstractIntervalRealNumericalMatrix == false) {
      throw new RuntimeException("Not implemented"); //$NON-NLS-1$
    }
    this.infimum.setSubVector(index, source.getInfimum());
    this.supremum.setSubVector(index, source.getSupremum());
    updateMiddleRadius();
  }

  /**
   * @param index index
   * @param source source
   */
  public void setSubVector(IntMatrix index, RM source) {
    this.infimum.setSubVector(index, source);
    this.supremum.setSubVector(index, source);
    updateMiddleRadius();
  }

  /**
   * {@inheritDoc}
   */
  public BooleanMatrix compareElementWise(String operator, RIM opponent) {
    if (operator.equals(".==")) { //$NON-NLS-1$
      return this.infimum.compareElementWise(operator, opponent.getInfimum()).andElementWise(this.supremum.compareElementWise(operator, opponent.getSupremum()));
    }

    if (operator.equals(".!=")) { //$NON-NLS-1$
      return this.infimum.compareElementWise(operator, opponent.getInfimum()).andElementWise(this.supremum.compareElementWise(operator, opponent.getSupremum()));
    }

    if (operator.equals(".<")) { //$NON-NLS-1$
      return this.supremum.compareElementWise(operator, opponent.getInfimum());
    }

    if (operator.equals(".<=")) { //$NON-NLS-1$
      return this.supremum.compareElementWise(operator, opponent.getInfimum());
    }

    if (operator.equals(".>")) { //$NON-NLS-1$
      return this.infimum.compareElementWise(operator, opponent.getSupremum());
    }

    if (operator.equals(".>=")) { //$NON-NLS-1$
      return this.infimum.compareElementWise(operator, opponent.getSupremum());
    }

    throw new UnsupportedOperationException();
  }

  /**
   * {@inheritDoc}
   */
  public RIM getSubVector(final IntMatrix index) {
    final RM inf = this.infimum.getSubVector(index);
    final RM sup = this.supremum.getSubVector(index);
    return createInfSup(inf, sup);
  }

  /**
   * {@inheritDoc}
   */
  public RIM getSubMatrix(final int rowMinimum, final int rowMaximum, final int columnMinimum, final int columnMaximum) {
    final RM inf = this.infimum.getSubMatrix(rowMinimum, rowMaximum, columnMinimum, columnMaximum);
    final RM sup = this.supremum.getSubMatrix(rowMinimum, rowMaximum, columnMinimum, columnMaximum);
    return createInfSup(inf, sup);
  }

  /**
   * {@inheritDoc}
   */
  public RIM getSubMatrix(int rowMinimum, int rowMaximum, IntMatrix columnIndex) {
    final RM inf = this.infimum.getSubMatrix(rowMinimum, rowMaximum, columnIndex);
    final RM sup = this.supremum.getSubMatrix(rowMinimum, rowMaximum, columnIndex);
    return createInfSup(inf, sup);
  }

  /**
   * {@inheritDoc}
   */
  public RIM getSubMatrix(IntMatrix rowIndex, int columnMinimum, int columnMaximum) {
    final RM inf = this.infimum.getSubMatrix(rowIndex, columnMinimum, columnMaximum);
    final RM sup = this.supremum.getSubMatrix(rowIndex, columnMinimum, columnMaximum);
    return createInfSup(inf, sup);
  }

  /**
   * {@inheritDoc}
   */
  public RIM getSubMatrix(IntMatrix rowIndex, IntMatrix columnIndex) {
    final RM inf = this.infimum.getSubMatrix(rowIndex, columnIndex);
    final RM sup = this.supremum.getSubMatrix(rowIndex, columnIndex);
    return createInfSup(inf, sup);
  }

  /**
   * {@inheritDoc}
   */
  public RIM appendRight(RIM b) {
    RM inf = this.infimum.appendRight((b).getInfimum());
    RM sup = this.supremum.appendRight((b).getSupremum());
    return createInfSup(inf, sup);
  }

  /**
   * {@inheritDoc}
   */
  public RIM appendDown(RIM b) {
    RM inf = this.infimum.appendDown((b).getInfimum());
    RM sup = this.supremum.appendDown((b).getSupremum());
    return createInfSup(inf, sup);
  }

  /**
   * {@inheritDoc}
   */
  public RIM conjugate() {
    RM inf = this.infimum.conjugate();
    RM sup = this.supremum.conjugate();
    return createInfSup(inf, sup);
  }

  /**
   * {@inheritDoc}
   */
  public RIM conjugateTranspose() {
    RM inf = this.infimum.conjugateTranspose();
    RM sup = this.supremum.conjugateTranspose();
    return createInfSup(inf, sup);
  }

  /**
   * {@inheritDoc}
   */
  public RIM sqrtElementWise() {
    RoundModeManager manager = RoundModeManager.getManager();
    RoundMode oldRoundMode = manager.getRoundMode();

    manager.setRoundMode(RoundMode.ROUND_DOWN);
    RM inf = (this.infimum).sqrtElementWise();

    manager.setRoundMode(RoundMode.ROUND_UP);
    RM sup = (this.supremum).sqrtElementWise();

    manager.setRoundMode(oldRoundMode);
    return createInfSup(inf, sup);
  }

  /**
   * 中心と半径を更新します。
   */
  private void updateMiddleRadius() {
    this.middle = mid(this.infimum, this.supremum);
    this.radius = rad(this.middle, this.infimum);
  }

  /**
   * 要素に区間内の浮動小数点数の個数を持つ整数行列を返します。
   * 
   * @return 要素に区間内の浮動小数点数の個数を持つ整数行列
   */
  public long[][] getPointsNumber() {
    long[][] count = new long[getRowSize()][getColumnSize()];

    for (int row = 0; row < getRowSize(); row++) {
      for (int column = 0; column < getColumnSize(); column++) {
        count[row][column] = ((DoubleIntervalNumber)getElement((row + 1) * (column + 1))).getPointsNumber();
      }
    }
    // TODO nfcのMatrixで返したい
    // return new IntegerMatrix(count);
    return count;
  }

  /**
   * index番目の要素の区間の値が何番目の浮動小数点かを返します。
   * 
   * @param index 要素の番号
   * @param value 要素の区間内の値
   * @return index要素の区間内での浮動小数点の番号
   */
  public long getPointOfValue(int index, double value) {
    return ((DoubleIntervalNumber)getElement(index)).getPointOfValue(value);
  }

  /**
   * {@inheritDoc}
   */
  public RIS getElement(int index) {
    return getElement((index-1)/getColumnSize()+1, (index-1)%getColumnSize()+1);  
  }

//  /**
//   * {@inheritDoc}
//   */
//  public RIS getElement(int row, int column) {
//    return createInfSup(this.infimum.getElement(row, column), this.supremum.getElement(row, column));
//  }

  /**
   * {@inheritDoc}
   */
  public RIS infNorm() {
    RoundModeManager manager = RoundModeManager.getManager();
    RoundMode oldMode = manager.getRoundMode();

    RM absMatrix = this.absMax();
    manager.setRoundMode(RoundMode.ROUND_UP);
    RS norm = absMatrix.norm(NormType.INFINITY);

    manager.setRoundMode(oldMode);

    return getElement(1, 1).create(norm);
  }

  /**
   * 有効桁数を返します。
   * 
   * @return 有効桁数
   */
  public RM getNumberOfSignifcantFigures() {
    RM elements = this.middle.absElementWise().log10ElementWise().subtract(this.radius.absElementWise().log10ElementWise());
    //    int rowSize = elements.getRowSize();
    //    int columnSize = elements.getColumnSize();
    //    int[][] intElements = new int[rowSize][columnSize];
    //    for (int i = 0; i < rowSize; i++) {
    //      for (int j = 0; j < columnSize; j++) {
    //        intElements[i][j] = elements.getElement(i + 1, j + 1);
    //      }
    //    }
    //    return new IntMatrix(intElements);

    return elements;
  }

  /**
   * {@inheritDoc}
   */
  public void printElements(Writer output) {
    throw new UnsupportedOperationException();
  }

  /**
   * {@inheritDoc}
   */
  public void printElements(Writer output, int maxColumnSize) {
    throw new UnsupportedOperationException();
  }

  /**
   * {@inheritDoc}
   */
  public RIM sumRowWise() {
    RoundModeManager manager = RoundModeManager.getManager();
    RoundMode oldRoundMode = manager.getRoundMode();

    manager.setRoundMode(RoundMode.ROUND_DOWN);
    RM inf = this.infimum.sumRowWise();

    manager.setRoundMode(RoundMode.ROUND_UP);
    RM sup = this.supremum.sumRowWise();

    manager.setRoundMode(oldRoundMode);

    return createInfSup(inf, sup);
  }

  /**
   * {@inheritDoc}
   */
  public RIM sumColumnWise() {
    RoundModeManager manager = RoundModeManager.getManager();
    RoundMode oldRoundMode = manager.getRoundMode();

    manager.setRoundMode(RoundMode.ROUND_DOWN);
    RM inf = this.infimum.sumColumnWise();

    manager.setRoundMode(RoundMode.ROUND_UP);
    RM sup = this.supremum.sumColumnWise();

    manager.setRoundMode(oldRoundMode);

    return createInfSup(inf, sup);
  }

  /**
   * {@inheritDoc}
   */
  public RIM cumulativeSumRowWise() {
    RoundModeManager manager = RoundModeManager.getManager();
    RoundMode oldRoundMode = manager.getRoundMode();

    manager.setRoundMode(RoundMode.ROUND_DOWN);
    RM inf = this.infimum.cumulativeSumRowWise();

    manager.setRoundMode(RoundMode.ROUND_UP);
    RM sup = this.supremum.cumulativeSumRowWise();

    manager.setRoundMode(oldRoundMode);

    return createInfSup(inf, sup);
  }

  /**
   * {@inheritDoc}
   */
  public RIM cumulativeSumColumnWise() {
    RoundModeManager manager = RoundModeManager.getManager();
    RoundMode oldRoundMode = manager.getRoundMode();

    manager.setRoundMode(RoundMode.ROUND_DOWN);
    RM inf = this.infimum.cumulativeSumColumnWise();

    manager.setRoundMode(RoundMode.ROUND_UP);
    RM sup = this.supremum.cumulativeSumColumnWise();

    manager.setRoundMode(oldRoundMode);

    return createInfSup(inf, sup);
  }

  /**
   * {@inheritDoc}
   */
  public RIM floorElementWise() {
    RM inf = this.infimum.floorElementWise();
    RM sup = this.supremum.floorElementWise();
    return createInfSup(inf, sup);
  }

  /**
   * {@inheritDoc}
   */
  public RIM ceilElementWise() {
    RM inf = this.infimum.ceilElementWise();
    RM sup = this.supremum.ceilElementWise();
    return createInfSup(inf, sup);
  }

  /**
   * {@inheritDoc}
   */
  public RIM fixElementWise() {
    RM inf = this.infimum.fixElementWise();
    RM sup = this.supremum.fixElementWise();
    return createInfSup(inf, sup);
  }

  /**
   * {@inheritDoc}
   */
  public RIM roundElementWise() {
    RM inf = this.infimum.roundElementWise();
    RM sup = this.supremum.roundElementWise();
    return createInfSup(inf, sup);
  }

  /**
   * {@inheritDoc}
   */
  public RIM roundToZeroElementWise(double tolerance) {
    RM inf = this.infimum.roundToZeroElementWise(tolerance);
    RM sup = this.supremum.roundToZeroElementWise(tolerance);
    return createInfSup(inf, sup);
  }

  /**
   * @param d d
   * @return result
   */
  public RIM divide(RS d) {
    RoundModeManager manager = RoundModeManager.getManager();
    RoundMode oldRoundMode = manager.getRoundMode();

    manager.setRoundMode(RoundMode.ROUND_DOWN);
    RM inf = (this.infimum.divide(d)).minElementWise(this.supremum.divide(d));

    manager.setRoundMode(RoundMode.ROUND_UP);
    RM sup = (this.infimum.divide(d)).maxElementWise(this.supremum.divide(d));

    manager.setRoundMode(oldRoundMode);
    return createInfSup(inf, sup);
  }

  /**
   * {@inheritDoc}
   */
  public BooleanMatrix compareElementWise(String operator, int value) {
    if (operator.equals(".==")) { //$NON-NLS-1$
      return this.infimum.compareElementWise(operator, value).andElementWise(this.supremum.compareElementWise(operator, value));
    }

    if (operator.equals(".!=")) { //$NON-NLS-1$
      return this.infimum.compareElementWise(operator, value).andElementWise(this.supremum.compareElementWise(operator, value));
    }

    if (operator.equals(".<")) { //$NON-NLS-1$
      return this.supremum.compareElementWise(operator, value);
    }

    if (operator.equals(".<=")) { //$NON-NLS-1$
      return this.supremum.compareElementWise(operator, value);
    }

    if (operator.equals(".>")) { //$NON-NLS-1$
      return this.infimum.compareElementWise(operator, value);
    }

    if (operator.equals(".>=")) { //$NON-NLS-1$
      return this.infimum.compareElementWise(operator, value);
    }

    throw new UnsupportedOperationException();
  }

  /**
   * {@inheritDoc}
   */
  public BooleanMatrix compareElementWise(String operator, double value) {
    if (operator.equals(".==")) { //$NON-NLS-1$
      return this.infimum.compareElementWise(operator, value).andElementWise(this.supremum.compareElementWise(operator, value));
    }

    if (operator.equals(".!=")) { //$NON-NLS-1$
      return this.infimum.compareElementWise(operator, value).andElementWise(this.supremum.compareElementWise(operator, value));
    }

    if (operator.equals(".<")) { //$NON-NLS-1$
      return this.supremum.compareElementWise(operator, value);
    }

    if (operator.equals(".<=")) { //$NON-NLS-1$
      return this.supremum.compareElementWise(operator, value);
    }

    if (operator.equals(".>")) { //$NON-NLS-1$
      return this.infimum.compareElementWise(operator, value);
    }

    if (operator.equals(".>=")) { //$NON-NLS-1$
      return this.infimum.compareElementWise(operator, value);
    }

    throw new UnsupportedOperationException();
  }

  /**
   * @param operator operator
   * @param value value
   * @return result
   */
  public BooleanMatrix compareElementWise(String operator, RS value) {
    if (operator.equals(".==")) { //$NON-NLS-1$
      return this.infimum.compareElementWise(operator, value).andElementWise(this.supremum.compareElementWise(operator, value));
    }

    if (operator.equals(".!=")) { //$NON-NLS-1$
      return this.infimum.compareElementWise(operator, value).andElementWise(this.supremum.compareElementWise(operator, value));
    }

    if (operator.equals(".<")) { //$NON-NLS-1$
      return this.supremum.compareElementWise(operator, value);
    }

    if (operator.equals(".<=")) { //$NON-NLS-1$
      return this.supremum.compareElementWise(operator, value);
    }

    if (operator.equals(".>")) { //$NON-NLS-1$
      return this.infimum.compareElementWise(operator, value);
    }

    if (operator.equals(".>=")) { //$NON-NLS-1$
      return this.infimum.compareElementWise(operator, value);
    }

    throw new UnsupportedOperationException();
  }

  /**
   * {@inheritDoc}
   */
  public void exchangeRow(int row1, int row2) {
    this.infimum.exchangeRow(row1, row2);
    this.supremum.exchangeRow(row1, row2);
    this.middle.exchangeRow(row1, row2);
    this.radius.exchangeRow(row1, row2);
  }

  /**
   * {@inheritDoc}
   */
  public void exchangeColumn(int column1, int column2) {
    this.infimum.exchangeColumn(column1, column2);
    this.supremum.exchangeColumn(column1, column2);
    this.middle.exchangeColumn(column1, column2);
    this.radius.exchangeColumn(column1, column2);
  }

  /**
   * {@inheritDoc}
   */
  public void removeRowVectors(int rowMinimum, int rowMaximum) {
    this.infimum.removeRowVectors(rowMinimum, rowMaximum);
    this.supremum.removeRowVectors(rowMinimum, rowMaximum);
    this.middle.removeRowVectors(rowMinimum, rowMaximum);
    this.radius.removeRowVectors(rowMinimum, rowMaximum);
  }

  /**
   * {@inheritDoc}
   */
  public void removeRowVectors(IntMatrix rowIndex) {
    this.infimum.removeRowVectors(rowIndex);
    this.supremum.removeRowVectors(rowIndex);
    this.middle.removeRowVectors(rowIndex);
    this.radius.removeRowVectors(rowIndex);
  }

  /**
   * {@inheritDoc}
   */
  public void removeColumnVectors(int columnMinimum, int columnMaximum) {
    this.infimum.removeColumnVectors(columnMinimum, columnMaximum);
    this.supremum.removeColumnVectors(columnMinimum, columnMaximum);
    this.middle.removeColumnVectors(columnMinimum, columnMaximum);
    this.radius.removeColumnVectors(columnMinimum, columnMaximum);
  }

  /**
   * {@inheritDoc}
   */
  public void removeColumnVectors(IntMatrix columnIndex) {
    this.infimum.removeColumnVectors(columnIndex);
    this.supremum.removeColumnVectors(columnIndex);
    this.middle.removeColumnVectors(columnIndex);
    this.radius.removeColumnVectors(columnIndex);
  }

  /**
   * {@inheritDoc}
   */
  public RM getInfimum() {
    return this.infimum;
  }

  /**
   * {@inheritDoc}
   */
  public RM getSupremum() {
    return this.supremum;
  }

  /**
   * {@inheritDoc}
   */
  public RM getMiddle() {
    return this.middle;
  }
  
  /**
   * {@inheritDoc}
   */
  public RM getRadius() {
    return this.radius;
  }


  /**
   * {@inheritDoc}
   */
  public boolean isPointMatrix() {
    return this.radius.isZero();
  }

  /**
   * {@inheritDoc}
   */
  public void printInfSup(String name, Writer output) {
    //TODO
    this.infimum.setElementFormat("%26.30E"); //$NON-NLS-1$
    this.supremum.setElementFormat("%26.30E"); //$NON-NLS-1$

    this.infimum.print(name + Messages.getString("RealIntervalMatrix.2"), output); //$NON-NLS-1$
    this.supremum.print(name + Messages.getString("RealIntervalMatrix.3"), output); //$NON-NLS-1$
  }

  /**
   * {@inheritDoc}
   */
  public void printMidRad(String name, Writer output) {
    //TODO
    this.middle.setElementFormat("%26.30E"); //$NON-NLS-1$
    this.radius.setElementFormat("%26.30E"); //$NON-NLS-1$

    this.middle.print(name + Messages.getString("RealIntervalMatrix.4"), output); //$NON-NLS-1$
    this.radius.print(name + Messages.getString("RealIntervalMatrix.5"), output); //$NON-NLS-1$
  }

  /**
   * 行列を1行の文字列に変換します。
   * 
   * @param elementFormat 成分の出力フォーマット
   * @return 1行の文字列
   */
  public String toString(final String elementFormat) {
    final int rowSize = getRowSize();
    final int columnSize = getColumnSize();

    final StringBuffer sb = new StringBuffer();

    if (rowSize == 0 || columnSize == 0) {
      return "[[]]"; //$NON-NLS-1$
    }

    if (columnSize == 1 && rowSize != 1) {
      return transpose().toString(elementFormat) + "'"; //$NON-NLS-1$
    }

    if (rowSize != 1) {
      sb.append("["); //$NON-NLS-1$
    }

    final int displayColumnSize = 1;

    for (int i = 0; i < rowSize; i++) {
      if (i != 0) {
        sb.append(" "); //$NON-NLS-1$
      }

      for (int k = 0; k < columnSize;) {
        if (k == 0) {
          sb.append("["); //$NON-NLS-1$
        } else {
          sb.append(" "); //$NON-NLS-1$ 
          if (rowSize != 1) {
            sb.append(" "); //$NON-NLS-1$ 
          }
        }

        int j;
        for (j = k; j < k + displayColumnSize && j < columnSize; j++) {
          sb.append((getElement(i + 1, j + 1)).toString(elementFormat));
          if (j != columnSize - 1) {
            sb.append(","); //$NON-NLS-1$
          }
        }

        if (j == columnSize) {
          sb.append("]"); //$NON-NLS-1$
        }

        k += displayColumnSize;
      }
    }

    if (rowSize != 1) {
      sb.append("]"); //$NON-NLS-1$
    }

    return sb.toString();
  }

  /**
   * {@inheritDoc}
   */
  public boolean contains(final RM point) {
    for (int row = 1; row <= getRowSize(); row++) {
      for (int column = 1; column <= getColumnSize(); column++) {
        final RS pointElement = point.getElement(row, column);
        final RS elementInfimum = getInfimum().getElement(row, column);
        if (elementInfimum.isGreaterThan(pointElement)) {
          return false;
        }
        final RS elementSupremum = getSupremum().getElement(row, column);
        if (elementSupremum.isLessThan(pointElement)) {
          return false;
        }
      }
    }
    
    return true;
  }

  /**
   * {@inheritDoc}
   */
  public RIM inverse() {
    final LinearEquationVerifier<RIS,RIM,RS,RM> verifier = new RealIntlabMethod<>((RIM)this, createUnit());
    verifier.solve();
    return verifier.getSolution();
  }

  /**
   * {@inheritDoc}
   */
  public RIM divide(final RM value) {
    if (value instanceof IntervalMatrix) {
      return divide(value);
    }

    LinearEquationVerifier<RIS,RIM,RS,RM> verifier = new RealIntlabMethod<>(create(value), (RIM)this);
    verifier.solve();
    return verifier.getSolution();
  }

  /**
   * {@inheritDoc}
   */
  public RIM divide(final RIM value) {
    LinearEquationVerifier<RIS,RIM,RS,RM> verifier = new RealIntlabMethod<>(value, (RIM)this);
    verifier.solve();
    return verifier.getSolution();
  }

  /**
   * {@inheritDoc}
   */
  public RIM leftDivide(final RM value) {
    if (value instanceof IntervalMatrix) {
      return leftDivide(value);
    }

    LinearEquationVerifier<RIS,RIM,RS,RM> verifier = new RealIntlabMethod<>((RIM)this, create(value));
    verifier.solve();
    return verifier.getSolution();
  }

  /**
   * {@inheritDoc}
   */
  public RIM leftDivide(final RIM value) {
    LinearEquationVerifier<RIS,RIM,RS,RM> verifier = new RealIntlabMethod<>((RIM)this, value);
    verifier.solve();
    return verifier.getSolution();
  }

  
  /**
   * {@inheritDoc}
   */
  public RIM productRowWise() {
    RIM vector = getColumnVector(1);
    for (int column = 2; column <= getColumnSize(); column++) {
      vector = vector.multiplyElementWise(getColumnVector(column));
    }
    return vector;
  }

  /**
   * {@inheritDoc}
   */
  public RIM productColumnWise() {
    RIM vector = getRowVector(1);
    for (int row = 2; row <= getRowSize(); row++) {
      vector = vector.multiplyElementWise(getRowVector(row));
    }
    return vector;
  }

  /**
   * {@inheritDoc}
   */
  public RIM cumulativeProductRowWise() {
    RIM ans = createZero();
    RIM vector = getColumnVector(1);
    ans.setColumnVector(1, vector);
    for (int column = 2; column <= getColumnSize(); column++) {
      vector = vector.multiplyElementWise(getColumnVector(column));
      ans.setColumnVector(column, vector);
    }
    return ans;
  }

  /**
   * {@inheritDoc}
   */
  public RIM cumulativeProductColumnWise() {
    RIM ans = createZero();
    RIM vector = getRowVector(1);
    ans.setRowVector(1, vector);
    for (int row = 2; row <= getRowSize(); row++) {
      vector = vector.multiplyElementWise(getRowVector(row));
      ans.setRowVector(row, vector);
    }
    return ans;
  }
  
  /**
   * {@inheritDoc}
   */
  public RIM absElementWise() {
    RoundModeManager manager = RoundModeManager.getManager();
    RoundMode oldRoundMode = manager.getRoundMode();

    manager.setRoundMode(RoundMode.ROUND_UP);
    RM sup = (this.supremum).absElementWise();

    manager.setRoundMode(RoundMode.ROUND_DOWN);
    RM inf = (this.infimum).absElementWise();

    RIM ans = createInfSup(inf, sup);
    manager.setRoundMode(oldRoundMode);
    return ans;
  }
  
  /**
   * {@inheritDoc}
   */
  public RIM singularValue() {
    RIM matrix = this.conjugateTranspose().multiply((RIM)this);
    //EigenVerifier<RIS,RIM,CIS,CIM,RS,RM,CS,CM> verifier = RealEigenVerifierFactory.getDefaultVerifier();

    /** eigen verifier */
    RealEigenVerifier<RIS,RIM,CIS,CIM,RS,RM,CS,CM> eigenVerifier = new RealRumpMethod<>(matrix);
    eigenVerifier.solve();
    CIM eigenValue = eigenVerifier.getEigenValue();
    RIS[] singularValue = eigenValue.getElement(1,1).getRealPart().createArray(eigenValue.getRowSize());

    for (int row = 1; row <= eigenValue.getRowSize(); row++) {
      RIS value = eigenValue.getElement(row).getRealPart();
      RS inf = value.getInfimum().sqrt();
      RS sup = value.getSupremum().sqrt();
      singularValue[row-1] =  value.createInfSup(inf, sup);
    }
    
    return singularValue[0].createGrid(singularValue);
  }

  /**
   * {@inheritDoc}
   */
  public int rank() {
    int rowSize = this.infimum.getRowSize();
    int columnSize = rowSize == 0 ? 0 : this.infimum.getColumnSize();

    RIM a;
    if (rowSize > columnSize) {
      a = transpose();
    } else {
      a = (RIM)this;
    }

    RIM values = a.singularValue();

    int rank = 0;
    for (int row = 1; row <= values.getRowSize(); row++) {
      RIS value = values.getElement(row);
      if (value.getInfimum().isGreaterThan(0)) {
        rank++;
      }
    }

    return rank;
  }
  
  /**
   * {@inheritDoc}
   */
  public RIM createMidRad(RM middle, RM radius) {
    return createInfSup(AbstractIntervalMatrix.infimum(middle, radius), AbstractIntervalMatrix.supremum(middle, radius));
  }

  /**
   * {@inheritDoc}
   */
  public CIM createInfSup(CM inf, CM sup) {
    return createMidRad(AbstractIntervalMatrix.middle(inf, sup), AbstractIntervalMatrix.radius(inf, sup)); 
  }

  /**
   * {@inheritDoc}
   */
  public RIS[][] getElements() {
    throw new UnsupportedOperationException();
  }

  /**
   * {@inheritDoc}
   */
  public void setElements(RIS[][] elements) {
    throw new UnsupportedOperationException();
  }

  /**
   * {@inheritDoc}
   */
  public CIM add(CIM value) {
    return toComplex().add(value);
  }

  /**
   * {@inheritDoc}
   */
  public CIM subtract(CIM value) {
    return toComplex().subtract(value);
  }

  /**
   * {@inheritDoc}
   */
  public CIM multiply(CIM value) {
    return toComplex().multiply(value);
  }

  /**
   * {@inheritDoc}
   */
  public CIM divide(CIM value) {
    return toComplex().divide(value);
  }

  /**
   * {@inheritDoc}
   */
  public CIM leftDivide(CIM value) {
    return toComplex().leftDivide(value);
  }

  /**
   * {@inheritDoc}
   */
  public CIM appendDown(CIM value) {
    return toComplex().appendDown(value);
  }

  /**
   * {@inheritDoc}
   */
  public CIM appendRight(CIM value) {
    return toComplex().appendRight(value);
  }
  
  /**
   * {@inheritDoc}
   */
  public CIM multiply(CIS value) {
    return toComplex().multiply(value);
  }

  /**
   * {@inheritDoc}
   */
  public CIM divide(CIS value) {
    return toComplex().divide(value);
  }

  /**
   * {@inheritDoc}
   */
  public CIM leftDivide(CIS value) {
    return toComplex().leftDivide(value);
  }


}