AbstractIntervalComplexNumericalMatrix.java

/*
 * Created on 2004/08/24
 *
 * $Id: ComplexIntervalMatrix.java,v 1.62 2008/03/15 00:23:51 koga Exp $
 * Copyright (C) 2004 Koga Laboratory. All rights reserved.
 */
package org.mklab.cga.interval.matrix;

import java.io.Writer;

import org.mklab.cga.eigen.ComplexEigenVerifier;
import org.mklab.cga.interval.scalar.IntervalComplexNumericalScalar;
import org.mklab.cga.interval.scalar.IntervalRealNumericalScalar;
import org.mklab.cga.linear.ComplexIntlabMethod;
import org.mklab.cga.linear.LinearEquationVerifier;
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.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.62 $. 2004/08/24
 * @param <RIS> 実区間スカラーの型
 * @param <RIM> 実区間行列の型
 * @param <CIS> 複素区間スカラーの型
 * @param <CIM> 複素区間行列の型
 * @param <RS> 実スカラーの型
 * @param <RM> 実行列の型
 * @param <CS> 複素スカラーの型
 * @param <CM> 複素行列の型
 */
public abstract class AbstractIntervalComplexNumericalMatrix<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<CIS, CIM, CS, CM> implements IntervalComplexNumericalMatrix<RIS, RIM, CIS, CIM, RS, RM, CS, CM> {

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

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

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

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

  /** 区間の半径 */
  protected RM radius;

  /** eigen verifier */
  private ComplexEigenVerifier<RIS, RIM, CIS, CIM, RS, RM, CS, CM> eigenVerifier;

  /**
   * 与えられた行列から区間行列を作成します。与えられた行列を区間の中心に設定します。
   * 
   * @param middle 中心の行列
   */
  public AbstractIntervalComplexNumericalMatrix(final CM middle) {
    super(middle.getRowSize(), middle.getColumnSize());

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

  /**
   * 与えられた行列から区間行列を作成します。与えられた行列を区間の中心と半径に設定します。
   * 
   * @param middle 中心の行列(複素数行列)
   * @param radius 半径の行列(実数行列)
   */
  public AbstractIntervalComplexNumericalMatrix(final CM middle, final RM radius) {
    super(middle.getRowSize(), middle.getColumnSize());

    this.middle = middle;
    this.radius = radius;
    this.infimum = inf(middle, radius);
    this.supremum = sup(middle, radius);
  }
  
  /**
   * 区間の配列から区間行列を作成します。
   * 
   * @param intervals 行列の要素(区間)
   */
  public AbstractIntervalComplexNumericalMatrix(CIS[][] intervals) {
    super(intervals.length, intervals.length == 0 ? 0 : intervals[0].length);

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

    CS unit = intervals[0][0].getMiddle();
    CS[][] midElements = unit.createArray(rowSize, columnSize);
    RS[][] radElements = unit.getRealPart().createArray(rowSize, columnSize);

    for (int i = 0; i < rowSize; i++) {
      for (int j = 0; j < columnSize; j++) {
        final CIS interval = intervals[i][j];
        midElements[i][j] = interval.getMiddle();
        radElements[i][j] = interval.getRadius();
      }
    }

    CM mid = midElements[0][0].createGrid(rowSize, columnSize, midElements);
    RM rad = radElements[0][0].createGrid(rowSize, columnSize, radElements);

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

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

    final int size = intervals.length;

    CS unit = intervals[0].getMiddle();
    CS[][] midElements = unit.createArray(size, 1);
    RS[][] radElements = unit.getRealPart().createArray(size, 1);

    for (int i = 0; i < size; i++) {
      final CIS interval = intervals[i];
      midElements[i][0] = interval.getMiddle();
      radElements[i][0] = interval.getRadius();
    }

    CM mid = midElements[0][0].createGrid(size, 1, midElements);
    RM rad = radElements[0][0].createGrid(size, 1, radElements);

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


  /**
   * Sets eigen verifier.
   * 
   * @param verifier eigen verifier.
   */
  public void setEigenVerifier(ComplexEigenVerifier<RIS, RIM, CIS, CIM, RS, RM, CS, CM> verifier) {
    this.eigenVerifier = verifier;
  }

  /**
   * Returns eigen verifier.
   * 
   * @return eigen verifier
   */
  public ComplexEigenVerifier<RIS, RIM, CIS, CIM, RS, RM, CS, CM> getEigenVerifier() {
    return this.eigenVerifier;
  }

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

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

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

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

  /**
   * {@inheritDoc}
   */
  public boolean isUnit(final double tolerance) {
    return this.middle.isUnit(tolerance) && this.radius.isZero(tolerance);
  }

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

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

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

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

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

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

    manager.setRoundMode(RoundMode.ROUND_DOWN);
    CM c1 = this.middle.add(y.getMiddle());

    manager.setRoundMode(RoundMode.ROUND_UP);
    CM mid = this.middle.add(y.getMiddle());
    RM rad = (mid.subtract(c1)).absElementWise().getRealPart();

    if (isPointMatrix() == false) {
      rad = rad.add(this.radius);
    }

    if (y.isPointMatrix() == false) {
      rad = rad.add(y.getRadius());
    }

    CIM ans = createMidRad(mid, rad);

    manager.setRoundMode(oldRoundMode);
    return ans;
  }

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

    manager.setRoundMode(RoundMode.ROUND_DOWN);
    CM c1 = this.middle.addElementWise(y.getMiddle());

    manager.setRoundMode(RoundMode.ROUND_UP);
    CM mid = this.middle.addElementWise(y.getMiddle());
    RM rad = (mid.subtract(c1)).absElementWise().getRealPart();

    if (isPointMatrix() == false) {
      rad = rad.add(this.radius);
    }

    if (y.isPointScalar() == false) {
      rad = rad.addElementWise(y.getRadius());
    }

    CIM ans = createMidRad(mid, rad);
    manager.setRoundMode(oldRoundMode);
    return ans;
  }

  /**
   * @param y y
   * @return result
   */
  public CIM add(final CM y) {
    RoundModeManager manager = RoundModeManager.getManager();
    RoundMode oldRoundMode = manager.getRoundMode();

    manager.setRoundMode(RoundMode.ROUND_DOWN);
    CM c1 = this.middle.add(y);

    manager.setRoundMode(RoundMode.ROUND_UP);
    CM mid = this.middle.add(y);
    RM rad;
    if (isPointMatrix()) {
      rad = (mid.subtract(c1)).absElementWise().getRealPart();
    } else {
      rad = (mid.subtract(c1)).absElementWise().getRealPart().add(this.radius);
    }

    CIM ans = createMidRad(mid, rad);
    manager.setRoundMode(oldRoundMode);
    return ans;
  }

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

    manager.setRoundMode(RoundMode.ROUND_DOWN);
    CM c1 = this.middle.addElementWise(y);

    manager.setRoundMode(RoundMode.ROUND_UP);
    CM mid = this.middle.addElementWise(y);
    RM rad;
    if (isPointMatrix()) {
      rad = (mid.subtract(c1)).absElementWise().getRealPart();
    } else {
      rad = (mid.subtract(c1)).absElementWise().getRealPart().add(this.radius);
    }

    CIM ans = createMidRad(mid, rad);
    manager.setRoundMode(oldRoundMode);
    return ans;
  }

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

    manager.setRoundMode(RoundMode.ROUND_DOWN);
    CM c1 = this.middle.addElementWise(y);

    manager.setRoundMode(RoundMode.ROUND_UP);
    CM mid = this.middle.addElementWise(y);
    RM rad;
    if (isPointMatrix()) {
      rad = (mid.subtract(c1)).absElementWise().getRealPart();
    } else {
      rad = (mid.subtract(c1)).absElementWise().getRealPart().add(this.radius);
    }

    CIM ans = createMidRad(mid, rad);
    manager.setRoundMode(oldRoundMode);
    return ans;
  }

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

    manager.setRoundMode(RoundMode.ROUND_DOWN);
    CM c1 = this.middle.addElementWise(y);

    manager.setRoundMode(RoundMode.ROUND_UP);
    CM mid = this.middle.addElementWise(y);
    RM rad;
    if (isPointMatrix()) {
      rad = (mid.subtract(c1)).absElementWise().getRealPart();
    } else {
      rad = (mid.subtract(c1)).absElementWise().getRealPart().add(this.radius);
    }

    manager.setRoundMode(oldRoundMode);
    return createMidRad(mid, rad);
  }

  /**
   * {@inheritDoc}
   */
  public CIM subtract(final CIM y) {// IC-IR,
    // IC-IC,
    // (IR-IC)
    RoundModeManager manager = RoundModeManager.getManager();
    RoundMode oldRoundMode = manager.getRoundMode();

    manager.setRoundMode(RoundMode.ROUND_DOWN);
    CM c1 = this.middle.subtract(y.getMiddle());

    manager.setRoundMode(RoundMode.ROUND_UP);
    CM mid = this.middle.subtract(y.getMiddle());
    RM rad = (mid.subtract(c1)).absElementWise().getRealPart();
    if (isPointMatrix() == false) {
      rad = rad.add(this.radius);
    }
    if (y.isPointMatrix() == false) {
      rad = rad.add(y.getRadius());
    }

    CIM ans = createMidRad(mid, rad);
    manager.setRoundMode(oldRoundMode);
    return ans;
  }

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

    manager.setRoundMode(RoundMode.ROUND_DOWN);
    CM c1 = this.middle.subtractElementWise(y.getMiddle());

    manager.setRoundMode(RoundMode.ROUND_UP);
    CM mid = this.middle.subtractElementWise(y.getMiddle());
    RM rad = (mid.subtract(c1)).absElementWise().getRealPart();

    if (isPointMatrix() == false) {
      rad = rad.add(this.radius);
    }
    if (y.isPointScalar() == false) {
      rad = rad.addElementWise(y.getRadius());
    }

    CIM ans = createMidRad(mid, rad);
    manager.setRoundMode(oldRoundMode);
    return ans;
  }

  /**
   * @param y y
   * @return result
   */
  public CIM subtract(final CM y) {
    RoundModeManager manager = RoundModeManager.getManager();
    RoundMode oldRoundMode = manager.getRoundMode();

    manager.setRoundMode(RoundMode.ROUND_DOWN);
    CM c1 = this.middle.subtract(y);

    manager.setRoundMode(RoundMode.ROUND_UP);
    CM mid = this.middle.subtract(y);
    RM rad;
    if (isPointMatrix()) {
      rad = (mid.subtract(c1)).absElementWise().getRealPart();
    } else {
      rad = (mid.subtract(c1)).absElementWise().getRealPart().add(this.radius);
    }

    CIM ans = createMidRad(mid, rad);
    manager.setRoundMode(oldRoundMode);
    return ans;
  }

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

    manager.setRoundMode(RoundMode.ROUND_DOWN);
    CM c1 = this.middle.subtractElementWise(y);

    manager.setRoundMode(RoundMode.ROUND_UP);
    CM mid = this.middle.subtractElementWise(y);
    RM rad;
    if (isPointMatrix()) {
      rad = (mid.subtract(c1)).absElementWise().getRealPart();
    } else {
      rad = (mid.subtract(c1)).absElementWise().getRealPart().add(this.radius);
    }

    CIM ans = createMidRad(mid, rad);
    manager.setRoundMode(oldRoundMode);
    return ans;
  }

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

    manager.setRoundMode(RoundMode.ROUND_DOWN);
    CM c1 = this.middle.subtractElementWise(y);

    manager.setRoundMode(RoundMode.ROUND_UP);
    CM mid = this.middle.subtractElementWise(y);
    RM rad;
    if (isPointMatrix()) {
      rad = (mid.subtract(c1)).absElementWise().getRealPart();
    } else {
      rad = (mid.subtract(c1)).absElementWise().getRealPart().add(this.radius);
    }

    CIM ans = createMidRad(mid, rad);
    manager.setRoundMode(oldRoundMode);
    return ans;
  }

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

    manager.setRoundMode(RoundMode.ROUND_DOWN);
    CM c1 = this.middle.subtractElementWise(y);

    manager.setRoundMode(RoundMode.ROUND_UP);
    CM mid = this.middle.subtractElementWise(y);
    RM rad;
    if (isPointMatrix()) {
      rad = (mid.subtract(c1)).absElementWise().getRealPart();
    } else {
      rad = (mid.subtract(c1)).absElementWise().getRealPart().add(this.radius);
    }

    CIM ans = createMidRad(mid, rad);
    manager.setRoundMode(oldRoundMode);
    return ans;
  }

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

    RM a_mid_real = this.middle.getRealPart();
    RM a_mid_imag = this.middle.getImaginaryPart();

    RM b_mid_real = y.getMiddle().getRealPart();
    RM b_mid_imag = y.getMiddle().getImaginaryPart();

    manager.setRoundMode(RoundMode.ROUND_DOWN);
    RM c1_real = a_mid_real.multiply(b_mid_real).add(a_mid_imag.unaryMinus().multiply(b_mid_imag));
    RM c1_imag = a_mid_real.multiply(b_mid_imag).add(a_mid_imag.multiply(b_mid_real));
    CM c1 = this.radius.createComplex(c1_real, c1_imag);

    manager.setRoundMode(RoundMode.ROUND_UP);
    RM c2_real = a_mid_real.multiply(b_mid_real).add(a_mid_imag.unaryMinus().multiply(b_mid_imag));
    RM c2_imag = a_mid_real.multiply(b_mid_imag).add(a_mid_imag.multiply(b_mid_real));
    CM c2 = this.radius.createComplex(c2_real, c2_imag);

    CM mid = c1.add(c2.subtract(c1).divide(2));
    RM rad;

    if (isPointMatrix()) {
      if (y.isPointMatrix()) {
        rad = (mid.subtract(c1)).absElementWise().getRealPart();
      } else {
        rad = (mid.subtract(c1)).absElementWise().getRealPart().add((this.middle).absElementWise().getRealPart().multiply(y.getRadius()));
      }
    } else if (y.isPointMatrix()) {
      rad = (mid.subtract(c1)).absElementWise().getRealPart().add(this.radius.multiply((y.getMiddle()).absElementWise().getRealPart()));
    } else {
      rad = (mid.subtract(c1)).absElementWise().getRealPart().add(this.radius.multiply((y.getMiddle()).absElementWise().getRealPart().add(y.getRadius())))
          .add((this.middle).absElementWise().getRealPart().multiply(y.getRadius()));
    }

    CIM ans = createMidRad(mid, rad);
    manager.setRoundMode(oldRoundMode);
    return ans;
  }

  /**
   * @param y y
   * @return result
   */
  public CIM multiply(final CM y) {// IC*R, IC*C
    RoundModeManager manager = RoundModeManager.getManager();
    RoundMode oldRoundMode = manager.getRoundMode();

    RM a_mid_real = this.middle.getRealPart();
    RM a_mid_imag = this.middle.getImaginaryPart();

    RM b_real = y.getRealPart();
    RM b_imag = y.getImaginaryPart();

    manager.setRoundMode(RoundMode.ROUND_DOWN);
    RM c1_real = a_mid_real.multiply(b_real).add(a_mid_imag.unaryMinus().multiply(b_imag));
    RM c1_imag = a_mid_real.multiply(b_imag).add(a_mid_imag.multiply(b_real));
    CM c1 = this.radius.createComplex(c1_real, c1_imag);

    manager.setRoundMode(RoundMode.ROUND_UP);
    RM c2_real = a_mid_real.multiply(b_real).add(a_mid_imag.unaryMinus().multiply(b_imag));
    RM c2_imag = a_mid_real.multiply(b_imag).add(a_mid_imag.multiply(b_real));
    CM c2 = this.radius.createComplex(c2_real, c2_imag);

    CM mid = c1.add(c2.subtract(c1).divide(2));
    RM rad;
    if (isPointMatrix()) {
      rad = (mid.subtract(c1)).absElementWise().getRealPart();
    } else {
      rad = (mid.subtract(c1)).absElementWise().getRealPart().add(this.radius.multiply((y).absElementWise().getRealPart()));
    }

    CIM ans = createMidRad(mid, rad);
    manager.setRoundMode(oldRoundMode);
    return ans;
  }

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

    manager.setRoundMode(RoundMode.ROUND_DOWN);
    RM c1_real = this.middle.getRealPart().multiplyElementWise(b.getMiddle().getRealPart()).add(this.middle.getImaginaryPart().unaryMinus().multiplyElementWise(b.getMiddle().getImaginaryPart()));
    RM c1_imag = this.middle.getRealPart().multiplyElementWise(b.getMiddle().getImaginaryPart()).add(this.middle.getImaginaryPart().multiplyElementWise(b.getMiddle().getRealPart()));
    CM c1 = this.radius.createComplex(c1_real, c1_imag);

    manager.setRoundMode(RoundMode.ROUND_UP);
    RM c2_real = this.middle.getRealPart().multiplyElementWise(b.getMiddle().getRealPart()).add(this.middle.getImaginaryPart().unaryMinus().multiplyElementWise(b.getMiddle().getImaginaryPart()));
    RM c2_imag = this.middle.getRealPart().multiplyElementWise(b.getMiddle().getImaginaryPart()).add(this.middle.getImaginaryPart().multiplyElementWise(b.getMiddle().getRealPart()));
    CM c2 = this.radius.createComplex(c2_real, c2_imag);

    CM mid = c1.add(c2.subtract(c1).divide(2));
    RM rad = (mid.multiply(c1)).absElementWise().getRealPart().add(this.radius.multiplyElementWise((b.getMiddle()).absElementWise().getRealPart().add(b.getRadius())))
        .add((this.middle).absElementWise().getRealPart().multiplyElementWise(b.getRadius()));

    CIM ans = createMidRad(c2, rad);
    manager.setRoundMode(oldRoundMode);
    return ans;
  }

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

    manager.setRoundMode(RoundMode.ROUND_DOWN);
    RM c1_real = this.middle.getRealPart().multiply(b.getMiddle().getRealPart()).add(this.middle.getImaginaryPart().unaryMinus().multiply(b.getMiddle().getImaginaryPart()));
    RM c1_imag = this.middle.getRealPart().multiply(b.getMiddle().getImaginaryPart()).add(this.middle.getImaginaryPart().multiply(b.getMiddle().getRealPart()));
    CM c1 = this.radius.createComplex(c1_real, c1_imag);

    manager.setRoundMode(RoundMode.ROUND_UP);
    RM c2_real = this.middle.getRealPart().multiply(b.getMiddle().getRealPart()).add(this.middle.getImaginaryPart().unaryMinus().multiply(b.getMiddle().getImaginaryPart()));
    RM c2_imag = this.middle.getRealPart().multiply(b.getMiddle().getImaginaryPart()).add(this.middle.getImaginaryPart().multiply(b.getMiddle().getRealPart()));
    CM c2 = this.radius.createComplex(c2_real, c2_imag);

    CM mid = c1.add(c2.subtract(c1).divide(2));
    RM rad = (mid.subtract(c1)).absElementWise().getRealPart().add(this.radius.multiply(b.getMiddle().abs().getRealPart().add(b.getRadius())))
        .add((this.middle).absElementWise().getRealPart().multiply(b.getRadius()));

    CIM ans = createMidRad(mid, rad);
    manager.setRoundMode(oldRoundMode);
    return ans;
  }

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

    manager.setRoundMode(RoundMode.ROUND_DOWN);
    RM c1_real = this.middle.getRealPart().multiplyElementWise(y.getRealPart()).add(this.middle.getImaginaryPart().unaryMinus().multiplyElementWise(y.getImaginaryPart()));
    RM c1_imag = this.middle.getRealPart().multiplyElementWise(y.getImaginaryPart()).add(this.middle.getImaginaryPart().multiplyElementWise(y.getRealPart()));

    CM c1 = this.radius.createComplex(c1_real, c1_imag);

    manager.setRoundMode(RoundMode.ROUND_UP);
    RM c2_real = this.middle.getRealPart().multiplyElementWise(y.getRealPart()).add((this.middle).getImaginaryPart().unaryMinus().multiplyElementWise(y.getImaginaryPart()));
    RM c2_imag = this.middle.getRealPart().multiplyElementWise(y.getImaginaryPart()).add(this.middle.getImaginaryPart().multiplyElementWise(y.getRealPart()));

    CM c2 = this.radius.createComplex(c2_real, c2_imag);

    CM mid = c1.add(c2.subtract(c1).divide(2));
    RM rad = (mid.subtract(c1)).absElementWise().getRealPart().add(this.radius.multiplyElementWise((y).absElementWise().getRealPart()));

    CIM ans = createMidRad(mid, rad);
    manager.setRoundMode(oldRoundMode);
    return ans;
  }

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

    manager.setRoundMode(RoundMode.ROUND_DOWN);
    CM c1 = this.middle.multiply(y);

    manager.setRoundMode(RoundMode.ROUND_UP);
    CM c2 = this.middle.multiply(y);

    CM mid = c1.add(c2.subtract(c1).divide(2));
    RM rad = (mid.subtract(c1)).absElementWise().getRealPart().add(this.radius.multiply(Math.abs(y)));

    CIM ans = createMidRad(mid, rad);
    manager.setRoundMode(oldRoundMode);
    return ans;
  }

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

    manager.setRoundMode(RoundMode.ROUND_DOWN);
    CM c1 = this.middle.multiply(value);

    manager.setRoundMode(RoundMode.ROUND_UP);
    CM c2 = this.middle.multiply(value);

    CM mid = c1.add(c2.subtract(c1).divide(2));
    RM rad = (mid.subtract(c1)).absElementWise().getRealPart().add(this.radius.multiply(Math.abs(value)));

    CIM ans = createMidRad(mid, rad);
    manager.setRoundMode(oldRoundMode);
    return ans;
  }

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

    RM a_mid_real = this.middle.getRealPart();
    RM a_mid_imag = this.middle.getImaginaryPart();

    RS b_real = d.getRealPart();
    RS b_imag = d.getImaginaryPart();

    manager.setRoundMode(RoundMode.ROUND_DOWN);
    RM c1_real = a_mid_real.multiply(b_real).add(a_mid_imag.unaryMinus().multiply(b_imag));
    RM c1_imag = a_mid_real.multiply(b_imag).add(a_mid_imag.multiply(b_real));
    CM c1 = this.radius.createComplex(c1_real, c1_imag);

    manager.setRoundMode(RoundMode.ROUND_UP);
    RM c2_real = a_mid_real.multiply(b_real).add(a_mid_imag.unaryMinus().multiply(b_imag));
    RM c2_imag = a_mid_real.multiply(b_imag).add(a_mid_imag.multiply(b_real));
    CM c2 = this.radius.createComplex(c2_real, c2_imag);

    CM mid = c1.add(c2.subtract(c1).divide(2));
    RM rad = (mid.subtract(c1)).absElementWise().getRealPart().add(this.radius.multiply((d).abs().getRealPart()));

    CIM ans = createMidRad(mid, rad);
    manager.setRoundMode(oldRoundMode);
    return ans;
  }

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

    RM x = b.getMiddle().getRealPart();
    RM y = b.getMiddle().getImaginaryPart();

    manager.setRoundMode(RoundMode.ROUND_DOWN);
    RM Ninf = x.multiplyElementWise(x).add(y.multiplyElementWise(y)).add(b.getRadius().unaryMinus().multiplyElementWise(b.getRadius()));

    manager.setRoundMode(RoundMode.ROUND_UP);
    RM Nsup = x.multiplyElementWise(x).add(y.multiplyElementWise(y)).add(b.getRadius().unaryMinus().multiplyElementWise(b.getRadius()));
    RM x2 = (x.multiplyElementWise(Ninf)).maxElementWise(x.multiplyElementWise(Nsup));
    RM y2 = (y.multiplyElementWise(Ninf)).maxElementWise(x.multiplyElementWise(Nsup));

    manager.setRoundMode(RoundMode.ROUND_DOWN);
    RM x1 = (x.multiplyElementWise(Ninf)).maxElementWise(x.multiplyElementWise(Nsup));
    RM y1 = (y.multiplyElementWise(Ninf)).maxElementWise(x.multiplyElementWise(Nsup));
    CM c1 = this.radius.createComplex(x1, y2.unaryMinus());

    manager.setRoundMode(RoundMode.ROUND_UP);
    CM c2 = this.radius.createComplex(x2, y1.unaryMinus());

    CM binvmid = c1.add(c2.subtract(c1).divide(2));
    RM binvrad = (binvmid.subtract(c1)).absElementWise().getRealPart().add(b.getRadius().divideElementWise(Ninf));
    CIM binv = createMidRad(binvmid, binvrad);
    CIM c = this.multiplyElementWise(binv);

    manager.setRoundMode(oldRoundMode);
    return c;
  }

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

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

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

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

  /**
   * {@inheritDoc}
   */
  public CIM diagonalToVector() {
    final CM mid = this.middle.diagonalToVector();
    final RM rad = this.radius.diagonalToVector();
    return createMidRad(mid, rad);
  }

  /**
   * {@inheritDoc}
   */
  public CIM vectorToDiagonal() {
    final CM mid = this.middle.vectorToDiagonal();
    final RM rad = this.radius.vectorToDiagonal();
    return createMidRad(mid, rad);
  }

  /**
   * {@inheritDoc}
   */
  public CIM reshape(int newRowSize, int newColumnSize) {
    final CM mid = this.middle.reshape(newRowSize, newColumnSize);
    final RM rad = this.radius.reshape(newRowSize, newColumnSize);
    return createMidRad(mid, rad);
  }

  /**
   * {@inheritDoc}
   */
  public CIM resize(int newRowSize, int newColumnSize) {
    final CM mid = this.middle.resize(newRowSize, newColumnSize);
    final RM rad = this.radius.resize(newRowSize, newColumnSize);
    return createMidRad(mid, rad);
  }

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

    manager.setRoundMode(RoundMode.ROUND_NEAR);

    CM ans;

    if (isPointMatrix()) {
      ans = (this.middle).absElementWise();
    } else {
      manager.setRoundMode(RoundMode.ROUND_DOWN);
      ans = (this.middle).absElementWise().subtract(this.radius.toComplex());

      manager.setRoundMode(RoundMode.ROUND_NEAR);
    }

    BooleanMatrix B = ans.compareElementWise(".>=", this.infimum.createZero(ans.getRowSize(), ans.getColumnSize())); //$NON-NLS-1$
    IntMatrix zoB = IntervalUtil.toZOMatrix(B);

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

    manager.setRoundMode(oldRoundMode);
    return ans;
  }

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

    CS cUnit = Ac.getElement(1, 1);
    CS rUnit = M.getElement(1, 1);
    CS[] d1 = cUnit.createArray(D.length());
    CS[] 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 CM abssElementWise() {
    RoundModeManager manager = RoundModeManager.getManager();
    RoundMode oldRoundMode = manager.getRoundMode();

    manager.setRoundMode(RoundMode.ROUND_UP);

    CM ans;
    if (isPointMatrix()) {
      ans = (this.middle).absElementWise();
    } else {
      ans = (this.middle).absElementWise().add(this.radius.toComplex());
    }

    manager.setRoundMode(oldRoundMode);
    return ans;
  }

  /**
   * {@inheritDoc}
   */
  public boolean equals(CIM opponent, double tolerance) {
    return this.middle.equals(opponent.getMiddle(), tolerance) && this.radius.equals(opponent.getRadius(), 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((DoubleMatrix)source);
  //      return;
  //    }
  //    if (source instanceof IntervalMatrix) {
  //      copy((IntervalMatrix)source);
  //      return;
  //    }
  //
  //    throw new RuntimeException("Not Implemented."); //$NON-NLS-1$
  //  }

  /**
   * {@inheritDoc}
   */
  public void copy(CIM source) {
    this.middle.copy(source.getMiddle());
    this.radius.copy(source.getRadius());
    updateInfinumSupremum();
  }

//  /**
//   * {@inheritDoc}
//   */
//  public void copy(IntMatrix source) {
//    this.middle.copy(source);
//    this.radius.copy(source.createZero());
//    updateInfinumSupremum();
//  }
//
//  /**
//   * {@inheritDoc}
//   */
//  public void copy(DoubleMatrix source) {
//    this.middle.copy(source);
//    this.radius.copy(source.createZero());
//    updateInfinumSupremum();
//  }

  /**
   * {@inheritDoc}
   */
  @Override
  public Object clone() {
    AbstractIntervalComplexNumericalMatrix<RIS, RIM, CIS, CIM, RS, RM, CS, CM> ans = (AbstractIntervalComplexNumericalMatrix<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;
    //return createMidRad(this.middle.createClone(), this.radius.createClone());
  }

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

    manager.setRoundMode(RoundMode.ROUND_DOWN);
    CM error = sup(this.middle, this.radius).subtract(inf(this.middle, this.radius));

    manager.setRoundMode(oldRoundMode);
    return error;
  }

  /**
   * 区間の半径を求めます。
   * 
   * @param inf infimum
   * @param sup supremum
   * @return 区間の半径。
   */
  public RM rad(CM inf, CM sup) {
    RoundModeManager manager = RoundModeManager.getManager();
    RoundMode oldRoundMode = manager.getRoundMode();

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

    manager.setRoundMode(oldRoundMode);
    return rad;
  }

  /**
   * 区間の半径を求めます。
   * 
   * @param inf infimum
   * @param sup supremum
   * @return 区間の半径。
   */
  public RS rad(CS inf, CS sup) {
    RoundModeManager manager = RoundModeManager.getManager();
    RoundMode oldRoundMode = manager.getRoundMode();

    manager.setRoundMode(RoundMode.ROUND_UP);
    CS mid = mid(inf, sup);
    RS rad = mid.subtract(inf).abs().getRealPart();

    manager.setRoundMode(oldRoundMode);
    return rad;
  }

  /**
   * 区間の中心を求めます。
   * 
   * @param inf infimum
   * @param sup supremum
   * @return 区間の中心。
   */
  public CM mid(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 inf infimum
   * @param sup supremum
   * @return 区間の中心。
   */
  public CS mid(CS inf, CS sup) {
    RoundModeManager manager = RoundModeManager.getManager();
    RoundMode oldRoundMode = manager.getRoundMode();

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

    manager.setRoundMode(oldRoundMode);
    return mid;
  }

  /**
   * 下限を求めます。
   * 
   * @param mid 中心
   * @param rad 半径
   * @return 下限
   */
  public CM inf(CM mid, RM rad) {
    RoundModeManager manager = RoundModeManager.getManager();
    RoundMode oldRoundMode = manager.getRoundMode();

    manager.setRoundMode(RoundMode.ROUND_DOWN);
    RM real = mid.getRealPart().subtract(rad);
    RM imag = mid.getImaginaryPart().subtract(rad);
    CM inf = rad.createComplex(real, imag);

    manager.setRoundMode(oldRoundMode);
    return inf;
  }

  /**
   * 上限を求めます。
   * 
   * @param mid 中心
   * @param rad 半径
   * @return 上限
   */
  public CM sup(CM mid, RM rad) {
    RoundModeManager manager = RoundModeManager.getManager();
    RoundMode oldRoundMode = manager.getRoundMode();

    manager.setRoundMode(RoundMode.ROUND_UP);
    RM real = mid.getRealPart().add(rad);
    RM imag = mid.getImaginaryPart().add(rad);
    CM sup = rad.createComplex(real, imag);

    manager.setRoundMode(oldRoundMode);

    return sup;
  }

  /**
   * {@inheritDoc}
   */
  public void setColumnVector(final int column, final CIM source) {
    this.middle.setColumnVector(column, source.getMiddle());
    this.radius.setColumnVector(column, source.getRadius());
    updateInfinumSupremum();
  }

  /**
   * {@inheritDoc}
   */
  public void setColumnVectors(final int minimum, final int maximum, final CIM source) {
    this.middle.setColumnVectors(minimum, maximum, source.getMiddle());
    this.radius.setColumnVectors(minimum, maximum, source.getRadius());
    updateInfinumSupremum();
  }

  /**
   * {@inheritDoc}
   */
  public void setColumnVectors(final IntMatrix columnIndex, final CIM source) {
    this.middle.setColumnVectors(columnIndex, source.getMiddle());
    this.radius.setColumnVectors(columnIndex, source.getRadius());
    updateInfinumSupremum();
  }

  /**
   * {@inheritDoc}
   */
  public void setRowVector(final int row, final CIM source) {
    this.middle.setRowVector(row, source.getMiddle());
    this.radius.setRowVector(row, source.getRadius());
    updateInfinumSupremum();
  }

  /**
   * {@inheritDoc}
   */
  public void setRowVectors(final IntMatrix rowIndex, final CIM source) {
    this.middle.setRowVectors(rowIndex, source.getMiddle());
    this.radius.setRowVectors(rowIndex, source.getRadius());
    updateInfinumSupremum();
  }

  /**
   * {@inheritDoc}
   */
  public void setRowVectors(final int minimum, final int maximum, final CIM source) {
    this.middle.setRowVectors(minimum, maximum, source.getMiddle());
    this.radius.setRowVectors(minimum, maximum, source.getRadius());
    updateInfinumSupremum();
  }

  /**
   * {@inheritDoc}
   */
  public BooleanMatrix compareElementWise(String operator, CIM opponent) {
    if (operator.equals(".==")) { //$NON-NLS-1$
      return this.middle.compareElementWise(operator, opponent.getMiddle()).andElementWise(this.radius.compareElementWise(operator, opponent.getRadius()));
    }

    if (operator.equals(".!=")) { //$NON-NLS-1$
      return this.middle.compareElementWise(operator, opponent.getMiddle()).andElementWise(this.radius.compareElementWise(operator, opponent.getRadius())).notElementWise();
    }

    throw new UnsupportedOperationException();
  }

  /**
   * {@inheritDoc}
   */
  public void setSubMatrix(int rowMinimum, int rowMaximum, int columnMinimum, int columnMaximum, CIM source) {
    this.middle.setSubMatrix(rowMinimum, rowMaximum, columnMinimum, columnMaximum, source.getMiddle());
    this.radius.setSubMatrix(rowMinimum, rowMaximum, columnMinimum, columnMaximum, source.getRadius());
    updateInfinumSupremum();
  }

  /**
   * {@inheritDoc}
   */
  public void setSubMatrix(IntMatrix rowIndex, int columnMinimum, int columnMaximum, CIM source) {
    if (source instanceof AbstractIntervalComplexNumericalMatrix == false) {
      throw new RuntimeException("Not implemented"); //$NON-NLS-1$
    }

    this.middle.setSubMatrix(rowIndex, columnMinimum, columnMaximum, source.getMiddle());
    this.radius.setSubMatrix(rowIndex, columnMinimum, columnMaximum, source.getRadius());
    updateInfinumSupremum();
  }

  /**
   * {@inheritDoc}
   */
  public void setSubMatrix(int row, IntMatrix columnIndex, CIM source) {
    setSubMatrix(row, row, columnIndex, source);
  }

  /**
   * {@inheritDoc}
   */
  public void setSubMatrix(int rowMinimum, int rowMaximum, IntMatrix columnIndex, CIM source) {
    this.middle.setSubMatrix(rowMinimum, rowMaximum, columnIndex, source.getMiddle());
    this.radius.setSubMatrix(rowMinimum, rowMaximum, columnIndex, source.getRadius());
    updateInfinumSupremum();
  }

  /**
   * {@inheritDoc}
   */
  public void setSubMatrix(IntMatrix rowIndex, IntMatrix columnIndex, CIM source) {
    this.middle.setSubMatrix(rowIndex, columnIndex, source.getMiddle());
    this.radius.setSubMatrix(rowIndex, columnIndex, source.getRadius());
    updateInfinumSupremum();
  }

  /**
   * {@inheritDoc}
   */
  public void setSubVector(int minimum, int maximum, CIM source) {
    this.middle.setSubVector(minimum, maximum, source.getMiddle());
    this.radius.setSubVector(minimum, maximum, source.getRadius());
    updateInfinumSupremum();
  }

  /**
   * {@inheritDoc}
   */
  public void setSubVector(IntMatrix index, CIM source) {
    this.middle.setSubVector(index, source.getMiddle());
    this.radius.setSubVector(index, source.getRadius());
    updateInfinumSupremum();
  }

  /**
   * {@inheritDoc}
   */
  public CIM getSubMatrix(final int rowMinimum, final int rowMaximum, final int columnMinimum, final int columnMaximum) {
    final CM mid = this.middle.getSubMatrix(rowMinimum, rowMaximum, columnMinimum, columnMaximum);
    final RM rad = this.radius.getSubMatrix(rowMinimum, rowMaximum, columnMinimum, columnMaximum);
    return createMidRad(mid, rad);
  }

  /**
   * {@inheritDoc}
   */
  public CIM getSubMatrix(int rowMinimum, int rowMaximum, IntMatrix columnIndex) {
    final CM mid = this.middle.getSubMatrix(rowMinimum, rowMaximum, columnIndex);
    final RM rad = this.radius.getSubMatrix(rowMinimum, rowMaximum, columnIndex);
    return createMidRad(mid, rad);
  }

  /**
   * {@inheritDoc}
   */
  public CIM getSubMatrix(IntMatrix rowIndex, int columnMinimum, int columnMaximum) {
    final CM mid = this.middle.getSubMatrix(rowIndex, columnMinimum, columnMaximum);
    final RM rad = this.radius.getSubMatrix(rowIndex, columnMinimum, columnMaximum);
    return createMidRad(mid, rad);
  }

  /**
   * {@inheritDoc}
   */
  public CIM getSubMatrix(IntMatrix rowIndex, IntMatrix columnIndex) {
    final CM mid = this.middle.getSubMatrix(rowIndex, columnIndex);
    final RM rad = this.radius.getSubMatrix(rowIndex, columnIndex);
    return createMidRad(mid, rad);
  }

  /**
   * @see org.mklab.cga.interval.matrix.IntervalMatrix#getSubVector(org.mklab.nfc.matrix.IntMatrix)
   */
  public CIM getSubVector(final IntMatrix index) {
    final CM mid = this.middle.getSubVector(index);
    final RM rad = this.radius.getSubVector(index);
    return createMidRad(mid, rad);
  }

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

  //  /**
  //   * @see org.mklab.cga.interval.matrix.IntervalMatrix#getRealPart()
  //   */
  //  public RIM getRealPart() {
  //    RM inf = this.infimum.getRealPart();
  //    RM sup = this.supremum.getRealPart();
  //    return createInfSup(infimum, supremum);
  //  }
  //
  //  /**
  //   * @see org.mklab.cga.interval.matrix.IntervalMatrix#getImaginaryPart()
  //   */
  //  public RIM getImaginaryPart() {
  //    CM inf = this.infimum.getImaginaryPart();
  //    CM sup = this.supremum.getImaginaryPart();
  //    return new AbstractIntervalRealNumericalMatrix(inf, sup);
  //  }

  /**
   * {@inheritDoc}
   */
  public void setRealPart(final RIM realPart) {
    this.infimum.setRealPart(realPart.getInfimum());
    this.supremum.setRealPart(realPart.getSupremum());
    this.middle.setRealPart(realPart.getMiddle());
    this.radius = rad(this.infimum, this.supremum);
  }

  /**
   * {@inheritDoc}
   */
  public void setRealPart(final IntMatrix realPart) {
    this.infimum.setRealPart(realPart);
    this.supremum.setRealPart(realPart);
    this.middle.setRealPart(realPart);
    this.radius = rad(this.infimum, this.supremum);
  }

  /**
   * {@inheritDoc}
   */
  public void setImaginaryPart(final RIM imaginaryPart) {
    this.infimum.setImaginaryPart(imaginaryPart.getInfimum());
    this.supremum.setImaginaryPart(imaginaryPart.getSupremum());
    this.middle.setImaginaryPart(imaginaryPart.getMiddle());
    this.radius = rad(this.infimum, this.supremum);
  }

  /**
   * {@inheritDoc}
   */
  public void setImaginaryPart(final IntMatrix imaginaryPart) {
    this.infimum.setImaginaryPart(imaginaryPart);
    this.supremum.setImaginaryPart(imaginaryPart);
    this.middle.setImaginaryPart(imaginaryPart);
    this.radius = rad(this.infimum, this.supremum);
  }

  /**
   * 下限と上限を更新します。
   */
  private void updateInfinumSupremum() {
    this.infimum = inf(this.middle, this.radius);
    this.supremum = sup(this.middle, this.radius);
  }

  /**
   * {@inheritDoc}
   */
  public CIM appendDown(RIM b) {
    CM mid = this.middle.appendDown(b.getMiddle());
    RM rad = this.radius.appendDown(b.getRadius());
    return createMidRad(mid, rad);
  }

  /**
   * {@inheritDoc}
   */
  public CIM appendDown(CIM b) {
    CM mid = this.middle.appendDown(b.getMiddle());
    RM rad = this.radius.appendDown(b.getRadius());
    return createMidRad(mid, rad);
  }

  /**
   * {@inheritDoc}
   */
  public CIM appendRight(CIM b) {
    CM mid = this.middle.appendRight(b.getMiddle());
    RM rad = this.radius.appendRight(b.getRadius());
    return createMidRad(mid, rad);
  }

  /**
   * {@inheritDoc}
   */
  public CIM divide(CIS b) {
    throw new UnsupportedOperationException();
  }

  /**
   * {@inheritDoc}
   */
  public CIM divide(int b) {
    throw new UnsupportedOperationException();
  }

  /**
   * {@inheritDoc}
   */
  public CIM divide(double b) {
    throw new UnsupportedOperationException();
  }

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

  /**
   * {@inheritDoc}
   */
  public CIM inverseElementWise() {
    CIM conj = conjugate();
    RIM den = multiplyElementWise(conj).getRealPart();
    RIM real = conj.getRealPart().divideElementWise(den);
    RIM imag = conj.getImaginaryPart().divideElementWise(den);
    RM rad = real.getRadius().maxElementWise(imag.getRadius());
    RM midReal = real.getInfimum().add(real.getSupremum()).divide(2);
    RM midImag = imag.getInfimum().add(imag.getSupremum()).divide(2);
    CM mid = (rad).createComplex(midReal, midImag);
    return createMidRad(mid, rad);
  }

  /**
   * {@inheritDoc}
   */
  public void setElement(int index, int value) {
    this.middle.setElement(index, value);
    this.radius.setElement(index, 0);
    updateInfinumSupremum();
  }

  /**
   * {@inheritDoc}
   */
  public void setElement(int index, double value) {
    this.middle.setElement(index, value);
    this.radius.setElement(index, 0);
    updateInfinumSupremum();
  }

  /**
   * @param index index
   * @param value value
   */
  public void setElement(final int index, final CS value) {
    this.middle.setElement(index, value);
    this.radius.setElement(index, 0);
    updateInfinumSupremum();
  }

  /**
   * {@inheritDoc}
   */
  public void setElement(final int index, final CIS value) {
    this.middle.setElement(index, value.getMiddle());
    this.radius.setElement(index, value.getRadius());
    updateInfinumSupremum();
  }

  /**
   * {@inheritDoc}
   */
  public void setElement(int row, int column, int value) {
    this.middle.setElement(row, column, value);
    this.radius.setElement(row, column, 0);
    updateInfinumSupremum();
  }

  /**
   * {@inheritDoc}
   */
  public void setElement(int row, int column, double value) {
    this.middle.setElement(row, column, value);
    this.radius.setElement(row, column, 0);
    updateInfinumSupremum();
  }

  /**
   * @param row row
   * @param column column
   * @param value value
   */
  public void setElement(int row, int column, CS value) {
    this.middle.setElement(row, column, value);
    this.radius.setElement(row, column, 0);
    updateInfinumSupremum();
  }

  /**
   * {@inheritDoc}
   */
  public void setElement(final int row, final int column, CIS value) {
    this.middle.setElement(row, column, value.getMiddle());
    this.radius.setElement(row, column, value.getRadius());
    updateInfinumSupremum();
  }

  //  /**
  //   * @see org.mklab.cga.interval.matrix.IntervalMatrix#getElement(int)
  //   */
  //  @SuppressWarnings("unchecked")
  //  public CIS getElement(int i) {
  //    CS mid = this.middle.getElement(i);
  //    return   createMidRad(this.middle.getElement(i), this.radius.getElement(i));
  //  }
  //
  //  /**
  //   * {@inheritDoc}
  //   */
  //  @SuppressWarnings("unchecked")
  //  public CIS getElement(int row, int column) {
  //    return new AbstractIntervalComplexNumericalScalar(this.middle.getElement(row, column), this.radius.getElement(row, column));
  //  }

  /**
   * {@inheritDoc}
   */
  public CIM conjugate() {
    CM mid = this.middle.conjugate();
    RM rad = this.radius.conjugate();
    return createMidRad(mid, rad);
  }

  /**
   * {@inheritDoc}
   */
  public CIM conjugateTranspose() {
    CM mid = this.middle.conjugateTranspose();
    RM rad = this.radius.conjugateTranspose();
    return createMidRad(mid, rad);
  }

  /**
   * {@inheritDoc}
   */
  public CIM transpose() {
    CM mid = this.infimum.transpose();
    RM rad = this.radius.transpose();
    return createMidRad(mid, rad);
  }

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

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

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

    manager.setRoundMode(RoundMode.ROUND_DOWN);
    CM c1 = this.middle.sumRowWise();

    manager.setRoundMode(RoundMode.ROUND_UP);
    CM mid = this.middle.sumRowWise();
    RM rad = (mid.subtract(c1)).absElementWise().getRealPart();

    if (isPointMatrix() == false) {
      rad = rad.add(this.radius.sumRowWise());
    }

    CIM ans = createMidRad(mid, rad);

    manager.setRoundMode(oldRoundMode);
    return ans;
  }

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

    manager.setRoundMode(RoundMode.ROUND_DOWN);
    CM c1 = this.middle.sumColumnWise();

    manager.setRoundMode(RoundMode.ROUND_UP);
    CM mid = this.middle.sumColumnWise();
    RM rad = (mid.subtract(c1)).absElementWise().getRealPart();

    if (isPointMatrix() == false) {
      rad = rad.add(this.radius.sumColumnWise());
    }

    CIM ans = createMidRad(mid, rad);

    manager.setRoundMode(oldRoundMode);
    return ans;
  }

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

    manager.setRoundMode(RoundMode.ROUND_DOWN);
    CM c1 = this.middle.cumulativeSumRowWise();

    manager.setRoundMode(RoundMode.ROUND_UP);
    CM mid = this.middle.cumulativeSumRowWise();
    RM rad = (mid.subtract(c1)).absElementWise().getRealPart();

    if (isPointMatrix() == false) {
      rad = rad.add(this.radius.cumulativeSumRowWise());
    }

    CIM ans = createMidRad(mid, rad);

    manager.setRoundMode(oldRoundMode);
    return ans;
  }

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

    manager.setRoundMode(RoundMode.ROUND_DOWN);
    CM c1 = this.middle.cumulativeSumColumnWise();

    manager.setRoundMode(RoundMode.ROUND_UP);
    CM mid = this.middle.cumulativeSumColumnWise();
    RM rad = (mid.subtract(c1)).absElementWise().getRealPart();

    if (isPointMatrix() == false) {
      rad = rad.add(this.radius.cumulativeSumColumnWise());
    }

    CIM ans = createMidRad(mid, rad);

    manager.setRoundMode(oldRoundMode);
    return ans;
  }

  /**
   * {@inheritDoc}
   */
  public CIM floorElementWise() {
    CM mid = this.middle.floorElementWise();
    RM rad = this.radius.createClone();
    return createMidRad(mid, rad);
  }

  /**
   * {@inheritDoc}
   */
  public CIM ceilElementWise() {
    CM mid = this.middle.ceilElementWise();
    RM rad = this.radius.createClone();
    return createMidRad(mid, rad);
  }

  /**
   * {@inheritDoc}
   */
  public CIM fixElementWise() {
    CM mid = this.middle.fixElementWise();
    RM rad = this.radius.createClone();
    return createMidRad(mid, rad);
  }

  /**
   * {@inheritDoc}
   */
  public CIM roundElementWise() {
    CM mid = this.middle.roundElementWise();
    RM rad = this.radius.createClone();
    return createMidRad(mid, rad);
  }

  /**
   * {@inheritDoc}
   */
  public CIM roundToZeroElementWise(double tolerance) {
    CM mid = this.middle.roundToZeroElementWise(tolerance);
    RM rad = this.radius.createClone();
    return createMidRad(mid, rad);
  }

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

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

    throw new UnsupportedOperationException();
  }

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

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

    throw new UnsupportedOperationException();
  }

  /**
   * @param operator operator
   * @param value value
   * @return result result
   */
  public BooleanMatrix compareElementWise(String operator, CS value) {
    if (operator.equals(".==")) { //$NON-NLS-1$
      return this.middle.compareElementWise(operator, value).andElementWise(this.radius.compareElementWise(operator, value.getRealPart().createZero()));
    }

    if (operator.equals(".!=")) { //$NON-NLS-1$
      return this.middle.compareElementWise(operator, value).andElementWise(this.radius.compareElementWise(operator, value.getRealPart().createZero()).notElementWise());
    }

    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 CM getInfimum() {
    return this.infimum;
  }

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

  /**
   * {@inheritDoc}
   */
  public CM 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 CM point) {
    for (int row = 1; row <= getRowSize(); row++) {
      for (int column = 1; column <= getColumnSize(); column++) {
        final CS pointElement = (point).getElement(row, column);
        final CS elementMiddle = getMiddle().getElement(row, column);
        final RS elementRadius = getRadius().getElement(row, column);
        if ((elementMiddle.subtract(pointElement)).abs().getRealPart().isGreaterThan(elementRadius)) {
          return false;
        }
      }
    }

    return true;
  }

  /**
   * {@inheritDoc}
   */
  public CIM inverse() {
    final LinearEquationVerifier<CIS, CIM, CS, CM> verifier = new ComplexIntlabMethod<>((CIM)this, createUnit());
    verifier.solve();
    return verifier.getSolution();
  }

  /**
   * {@inheritDoc}
   */
  public CIM divide(final CM value) {
    LinearEquationVerifier<CIS, CIM, CS, CM> verifier = new ComplexIntlabMethod<>(create(value), (CIM)this);
    verifier.solve();
    return verifier.getSolution();
  }

  /**
   * {@inheritDoc}
   */
  public CIM divide(final CIM value) {
    LinearEquationVerifier<CIS, CIM, CS, CM> verifier = new ComplexIntlabMethod<>(value, (CIM)this);
    verifier.solve();
    return verifier.getSolution();
  }

  /**
   * {@inheritDoc}
   */
  public CIM leftDivide(final CM value) {
    LinearEquationVerifier<CIS, CIM, CS, CM> verifier = new ComplexIntlabMethod<>((CIM)this, create(value));
    verifier.solve();
    return verifier.getSolution();
  }

  /**
   * {@inheritDoc}
   */
  public CIM leftDivide(final CIM value) {
    LinearEquationVerifier<CIS, CIM, CS, CM> verifier = new ComplexIntlabMethod<>((CIM)this, value);
    verifier.solve();
    return verifier.getSolution();
  }

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

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

  /**
   * {@inheritDoc}
   */
  public CIM cumulativeProductRowWise() {
    CIM ans = createZero();
    CIM 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 CIM cumulativeProductColumnWise() {
    CIM ans = createZero();
    CIM 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 CIM absElementWise() {
    RoundModeManager manager = RoundModeManager.getManager();
    RoundMode oldRoundMode = manager.getRoundMode();

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

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

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

  /**
   * {@inheritDoc}
   */
  public CIM singularValue() {
    CIS element = getElement(1, 1);

    CIM matrix = this.conjugateTranspose().multiply((CIM)this);

    //EigenVerifier<RIS,RIM,CIS,CIM,RS,RM,CS,CM> verifier = new RealEigenVerifierFactory<>(matrix).createVerifier();
    this.eigenVerifier.solve(matrix);
    CIM eigenValue = this.eigenVerifier.getEigenValue();
    CIS[] singularValue = getElement(1, 1).createArray(getRowSize());

    for (int row = 1; row <= eigenValue.getRowSize(); row++) {
      CIS value = eigenValue.getElement(row);
      CS inf = value.getInfimum().sqrt();
      CS sup = value.getSupremum().sqrt();
      CS mid = mid(inf, sup);
      RS rad = rad(inf, sup);
      singularValue[row] = element.createMidRad(mid, rad);
    }

    return singularValue[0].createGrid(singularValue);
  }

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

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

    CIM values = a.singularValue();

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

    return rank;
  }

  //  /**
  //   * 中心と半径により区間を作成します。
  //   * 
  //   * @param middle 中心
  //   * @param radius 半径
  //   * @return 区間
  //   */
  //  public CIS createMiddleRadius(final CS middle, final RS radius) {
  //    RoundModeManager manager = RoundModeManager.getManager();
  //    RoundMode oldRoundMode = manager.getRoundMode();
  //
  //    manager.setRoundMode(RoundMode.ROUND_DOWN);
  //    CS infimum = middle.subtract(radius);
  //
  //    manager.setRoundMode(RoundMode.ROUND_UP);
  //    CS supremum = middle.add(radius);
  //
  //    manager.setRoundMode(oldRoundMode);
  //    return createInfSup(infimum, supremum);
  //  }
  
  /**
   * {@inheritDoc}
   */
  public CIM create(RIM rePart) {
    CM inf = rePart.getInfimum().toComplex();
    CM sup = rePart.getSupremum().toComplex();
    return createInfSup(inf,sup);
  }

  /**
   * {@inheritDoc}
   */
  public CIM create(RIM rePart, RIM imPart) {
    CM inf = rePart.getInfimum().createComplex(rePart.getInfimum(), imPart.getInfimum());
    CM sup = rePart.getSupremum().createComplex(rePart.getSupremum(), imPart.getSupremum());
    return createInfSup(inf,sup);
  }

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


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

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

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

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

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

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

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

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

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

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

}