AbstractIntervalComplexNumericalScalar.java

/*
 * Created on 2008/02/04
 * Copyright (C) 2008 Koga Laboratory. All rights reserved.
 *
 */
package org.mklab.cga.interval.scalar;

import org.mklab.cga.interval.matrix.IntervalComplexNumericalMatrix;
import org.mklab.cga.interval.matrix.IntervalRealNumericalMatrix;
import org.mklab.nfc.matrix.ComplexNumericalMatrix;
import org.mklab.nfc.matrix.RealNumericalMatrix;
import org.mklab.nfc.random.RandomGenerator;
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 yano
 * @version $Revision: 1.6 $, 2008/02/04
 * @param <RIS> 実区間スカラーの型
 * @param <RIM> 実区間行列の型
 * @param <CIS> 複素区間スカラーの型
 * @param <CIM> 複素区間行列の型
 * @param <RS> 実スカラーの型
 * @param <RM> 実行列の型
 * @param <CS> 複素スカラーの型
 * @param <CM> 複素行列の型
 */
public abstract class AbstractIntervalComplexNumericalScalar<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 AbstractIntervalScalar<CIS, CIM, CS, CM> implements IntervalComplexNumericalScalar<RIS, RIM, CIS, CIM, RS, RM, CS, CM> {

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

  /** 区間の下限 */
  private CS infimum;

  /** 区間の上限 */
  private CS supremum;

  /** 区間の中心 */
  private CS middle;

  /** 区間の半径 */
  private RS radius;

  /**
   * 区間を作成します。複素数の中心を設定します。
   * 
   * @param middle 中心
   */
  public AbstractIntervalComplexNumericalScalar(final CS middle) {
    this.infimum = middle.clone();
    this.supremum = middle.clone();
    this.middle = middle;
    this.radius = middle.getRealPart().createZero();
  }

  /**
   * 新しく生成された<code>ComplexScalarInterval</code>オブジェクトを初期化します。
   * 
   * @param middle 中心
   * @param radius 半径
   */
  public AbstractIntervalComplexNumericalScalar(CS middle, RS radius) {
    this.middle = middle;
    this.radius = radius;
    this.infimum = infimum(middle, radius);
    this.supremum = supremum(middle, radius);
  }

  /**
   * {@inheritDoc}
   */
  public CIS create(final int value) {
    final CS point = this.middle.create(value);
    return createMidRad(point, point.getRealPart().createZero());
  }
  
  /**
   * {@inheritDoc}
   */
  public CIS add(final CIS interval) {// IC+IR, IC+IC
    RoundModeManager manager = RoundModeManager.getManager();
    RoundMode oldRoundMode = manager.getRoundMode();

    manager.setRoundMode(RoundMode.ROUND_DOWN);
    CS c1 = this.middle.add(interval.getMiddle());

    manager.setRoundMode(RoundMode.ROUND_UP);
    CS mid = this.middle.add(interval.getMiddle());

    RS rad = mid.subtract(c1).abs().add(this.radius).add(interval.getRadius()).getRealPart();

    manager.setRoundMode(oldRoundMode);
    return createMidRad(mid, rad);
  }
  
  /**
   * {@inheritDoc}
   */
  public CIS add(RIS value) {
    RoundModeManager manager = RoundModeManager.getManager();
    RoundMode oldRoundMode = manager.getRoundMode();

    manager.setRoundMode(RoundMode.ROUND_DOWN);
    CS c1 = this.middle.add(value.getMiddle());

    manager.setRoundMode(RoundMode.ROUND_UP);
    CS mid = this.middle.add(value.getMiddle());

    RS rad = mid.subtract(c1).abs().add(this.radius).add(value.getRadius()).getRealPart();

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

  /**
   * {@inheritDoc}
   */
  public CIS add(double d) {
    RoundModeManager manager = RoundModeManager.getManager();
    RoundMode oldRoundMode = manager.getRoundMode();

    manager.setRoundMode(RoundMode.ROUND_DOWN);

    CS c1 = this.middle.add(d);

    manager.setRoundMode(RoundMode.ROUND_UP);

    CS mid = this.middle.add(d);
    RS rad;

    if (this.radius.isZero()) {
      rad = mid.subtract(c1).abs().getRealPart();
    } else {
      rad = (mid.subtract(c1)).abs().add(this.radius).getRealPart();
    }

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

  /**
   * {@inheritDoc}
   */
  public CIS add(CS c) {
    RoundModeManager manager = RoundModeManager.getManager();
    RoundMode oldRoundMode = manager.getRoundMode();

    manager.setRoundMode(RoundMode.ROUND_DOWN);

    CS c1 = this.middle.add(c);

    manager.setRoundMode(RoundMode.ROUND_UP);

    CS mid = this.middle.add(c);

    RS rad;
    if (this.radius.isZero()) {
      rad = mid.subtract(c1).abs().getRealPart();
    } else {
      rad = (mid.subtract(c1)).abs().add(this.radius).getRealPart();
    }

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

  /**
   * {@inheritDoc}
   */
  public CIS divide(int value) {
    throw new UnsupportedOperationException();
  }

  /**
   * {@inheritDoc}
   */
  public CIS divide(double value) {
    throw new UnsupportedOperationException();
  }

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

  /**
   * {@inheritDoc}
   */
  public CIS divide(RIS value) {
    throw new UnsupportedOperationException();
  }

  /**
   * {@inheritDoc}
   */
  public CIS divide(CS value) {
    throw new UnsupportedOperationException();
  }

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

  /**
   * {@inheritDoc}
   */
  public CS getMiddle() {
    return this.middle;
  }

  /**
   * {@inheritDoc}
   */
  public RS getRadius() {
    return this.radius;
  }

  /**
   * {@inheritDoc}
   */
  public CS getSupremum() {
    return this.supremum;
  }
  
  /**
   * {@inheritDoc}
   */
  public CIS multiply(final CIS value) {
    RoundModeManager manager = RoundModeManager.getManager();
    RoundMode oldRoundMode = manager.getRoundMode();

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

    RS b_mid_real = value.getMiddle().getRealPart();
    RS b_mid_imag = value.getMiddle().getImaginaryPart();

    manager.setRoundMode(RoundMode.ROUND_DOWN);

    RS c1_real = a_mid_real.multiply(b_mid_real).add(a_mid_imag.unaryMinus().multiply(b_mid_imag));
    RS c1_imag = a_mid_real.multiply(b_mid_imag).add(a_mid_imag.multiply(b_mid_real));
    CS c1 = this.middle.create(c1_real, c1_imag);

    manager.setRoundMode(RoundMode.ROUND_UP);

    RS c2_real = a_mid_real.multiply(b_mid_real).add(a_mid_imag.unaryMinus().multiply(b_mid_imag));
    RS c2_imag = a_mid_real.multiply(b_mid_imag).add(a_mid_imag.multiply(b_mid_real));
    CS c2 = this.middle.create(c2_real, c2_imag);

    CS mid = c1.add(c2.subtract(c1).divide(2));
    RS rad;

    if (this.radius.isZero()) {
      if (value.getRadius().isZero()) {
        rad = mid.subtract(c1).abs().getRealPart();
      } else {
        rad = mid.subtract(c1).abs().getRealPart().add(this.middle.abs().getRealPart()).add(value.getRadius());
      }
    } else if (value.getRadius().isZero()) {
      rad = mid.subtract(c1).abs().getRealPart().add(this.radius.multiply(value.getMiddle().abs().getRealPart()));
    } else {
      rad = mid.subtract(c1).abs().getRealPart().add(this.radius.multiply((value.getMiddle().abs().getRealPart().add(value.getRadius())))).add(this.middle.abs().getRealPart().multiply(value.getRadius()));
    }

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


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

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

    RS b_mid_real = value.getMiddle();
    RS b_mid_imag = value.getMiddle().createZero();

    manager.setRoundMode(RoundMode.ROUND_DOWN);

    RS c1_real = a_mid_real.multiply(b_mid_real).add(a_mid_imag.unaryMinus().multiply(b_mid_imag));
    RS c1_imag = a_mid_real.multiply(b_mid_imag).add(a_mid_imag.multiply(b_mid_real));
    CS c1 = this.middle.create(c1_real, c1_imag);

    manager.setRoundMode(RoundMode.ROUND_UP);

    RS c2_real = a_mid_real.multiply(b_mid_real).add(a_mid_imag.unaryMinus().multiply(b_mid_imag));
    RS c2_imag = a_mid_real.multiply(b_mid_imag).add(a_mid_imag.multiply(b_mid_real));
    CS c2 = this.middle.create(c2_real, c2_imag);

    CS mid = c1.add(c2.subtract(c1).divide(2));
    RS rad;

    if (this.radius.isZero()) {
      if (value.getRadius().isZero()) {
        rad = mid.subtract(c1).abs().getRealPart();
      } else {
        rad = mid.subtract(c1).abs().getRealPart().add(this.middle.abs().getRealPart()).add(value.getRadius());
      }
    } else if (value.getRadius().isZero()) {
      rad = mid.subtract(c1).abs().getRealPart().add(this.radius.multiply(value.getMiddle().abs()));
    } else {
      rad = mid.subtract(c1).abs().getRealPart().add(this.radius.multiply((value.getMiddle().abs().add(value.getRadius())))).add(this.middle.abs().getRealPart().multiply(value.getRadius()));
    }

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


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

    manager.setRoundMode(RoundMode.ROUND_DOWN);
    CS c1 = this.middle.multiply(d);

    manager.setRoundMode(RoundMode.ROUND_UP);
    CS c2 = this.middle.multiply(d);
    CS mid = c1.add(c2.subtract(c1).divide(2));

    RS rad;
    if (this.radius.isZero()) {
      rad = mid.subtract(c1).abs().getRealPart();
    } else {
      rad = (mid.subtract(c1)).abs().add(this.radius.multiply(Math.abs(d))).getRealPart();
    }

    CIS ans = createMidRad(mid, rad);
    manager.setRoundMode(oldRoundMode);
    return ans;
  }
  
  /**
   * {@inheritDoc}
   */
  public CIS multiply(final CS c) {
    RoundModeManager manager = RoundModeManager.getManager();
    RoundMode oldRoundMode = manager.getRoundMode();

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

    RS b_mid_real = c.getRealPart();
    RS b_mid_imag = c.getImaginaryPart();

    manager.setRoundMode(RoundMode.ROUND_DOWN);

    RS c1_real = a_mid_real.multiply(b_mid_real).add(a_mid_imag.unaryMinus().multiply(b_mid_imag));
    RS c1_imag = a_mid_real.multiply(b_mid_imag).add(a_mid_imag.multiply(b_mid_real));

    CS c1 = this.middle.create(c1_real, c1_imag);

    manager.setRoundMode(RoundMode.ROUND_UP);

    RS c2_real = a_mid_real.multiply(b_mid_real).add(a_mid_imag.unaryMinus().multiply(b_mid_imag));
    RS c2_imag = a_mid_real.multiply(b_mid_imag).add(a_mid_imag.multiply(b_mid_real));

    CS c2 = this.middle.create(c2_real, c2_imag);

    CS mid = c1.add(c2.subtract(c1).divide(2));

    RS rad = mid.subtract(c1).abs().getRealPart().add(this.radius.multiply(c.abs().getRealPart()));

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


  //  /**
  //   * {@inheritDoc}
  //   */
  //  @SuppressWarnings("unchecked")
  //  public CIS multiply(DoubleComplexNumber c) {
  //    RoundModeManager manager = RoundModeManager.getManager();
  //    RoundMode oldRoundMode = manager.getRoundMode();
  //
  //    RS a_mid_real = this.middle.getRealPart();
  //    RS a_mid_imag = this.middle.getImaginaryPart();
  //
  //    NumericalScalar<?> b_mid_real = c.getRealPart();
  //    NumericalScalar<?> b_mid_imag = c.getImaginaryPart();
  //
  //    manager.setRoundMode(RoundMode.ROUND_DOWN);
  //    RS c1_real = (S)a_mid_real.multiply(b_mid_real).add(a_mid_imag.unaryMinus()).multiply(b_mid_imag);
  //    RS c1_imag = (S)a_mid_real.multiply(b_mid_imag).add(a_mid_imag.multiply(b_mid_real));
  //    CS c1 = new ComplexScalar<>(c1_real, c1_imag);
  //
  //    manager.setRoundMode(RoundMode.ROUND_UP);
  //    RS c2_real = (S)a_mid_real.multiply(b_mid_real).add(a_mid_imag.unaryMinus().multiply(b_mid_imag));
  //    RS c2_imag = (S)a_mid_real.multiply(b_mid_imag).add(a_mid_imag.multiply(b_mid_real));
  //    CS c2 = new ComplexScalar<>(c2_real, c2_imag);
  //    CS mid = c1.add(c2.subtract(c1).divide(2));
  //
  //    RS rad;
  //    if (this.radius.isZero()) {
  //      rad = mid.subtract(c1).abs();
  //    } else {
  //      rad = (S)mid.subtract(c1).abs().add(this.radius.multiply(c.abs()));
  //    }
  //
  //    CIS ans = new AbstractComplexIntervalScalar<>(mid, rad);
  //    manager.setRoundMode(oldRoundMode);
  //    return ans;
  //  }

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

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

    manager.setRoundMode(oldRoundMode);
    return error;
  }

  /**
   * {@inheritDoc}
   */
  public void printInfSup(String name) {
    System.out.println(name + Messages.getString("ComplexScalarInterval.4") + this.infimum); //$NON-NLS-1$
    System.out.println(name+ Messages.getString("ComplexScalarInterval.1") + this.supremum); //$NON-NLS-1$
  }

  /**
   * {@inheritDoc}
   */
  public void printInfSupByBit(String messe) {
    // TODO Auto-generated method stub
  }

  /**
   * {@inheritDoc}
   */
  public void printInterval(String messe) {
    System.out.println("***** " + messe + " *****"); //$NON-NLS-1$ //$NON-NLS-2$
    System.out.println("[" + this.infimum + ", " + this.supremum + "]"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
  }

  /**
   * {@inheritDoc}
   */
  public void printMidRad(String messe) {
    System.out.println("***** " + messe + " *****"); //$NON-NLS-1$ //$NON-NLS-2$
    System.out.println("<" + this.middle + ", " + this.radius + ">"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
  }

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

    manager.setRoundMode(RoundMode.ROUND_DOWN);
    CS c1 = this.middle.subtract(value.getMiddle());

    manager.setRoundMode(RoundMode.ROUND_UP);
    CS mid = this.middle.subtract(value.getMiddle());
    
    RS rad = mid.subtract(c1).abs().add(this.radius).add(value.getRadius()).getRealPart();

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

  /**
   * {@inheritDoc}
   */
  public CIS subtract(RIS value) {
    RoundModeManager manager = RoundModeManager.getManager();
    RoundMode oldRoundMode = manager.getRoundMode();

    manager.setRoundMode(RoundMode.ROUND_DOWN);
    CS c1 = this.middle.subtract(value.getMiddle());

    manager.setRoundMode(RoundMode.ROUND_UP);
    CS mid = this.middle.subtract(value.getMiddle());
    
    RS rad = mid.subtract(c1).abs().add(this.radius).add(value.getRadius()).getRealPart();

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



  /**
   * {@inheritDoc}
   */
  public CIS subtract(double d) {
    RoundModeManager manager = RoundModeManager.getManager();
    RoundMode oldRoundMode = manager.getRoundMode();

    manager.setRoundMode(RoundMode.ROUND_DOWN);
    CS c1 = this.middle.subtract(d);

    manager.setRoundMode(RoundMode.ROUND_UP);
    CS mid = this.middle.subtract(d);

    RS rad;
    if (this.radius.isZero()) {
      rad = mid.subtract(c1).abs().getRealPart();
    } else {
      rad = mid.subtract(c1).abs().add(this.radius).getRealPart();
    }

    CIS ans = createMidRad(mid, rad);
    manager.setRoundMode(oldRoundMode);
    return ans;
  }
  
  /**
   * {@inheritDoc}
   */
  public CIS subtract(final CS c) {
    RoundModeManager manager = RoundModeManager.getManager();
    RoundMode oldRoundMode = manager.getRoundMode();

    manager.setRoundMode(RoundMode.ROUND_DOWN);
    CS c1 = this.middle.subtract(c);

    manager.setRoundMode(RoundMode.ROUND_UP);
    CS mid = this.middle.subtract(c);

    RS rad = mid.subtract(c1).abs().add(this.radius).getRealPart();

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


  //  /**
  //   * @see org.mklab.cga.interval.scalar.IntervalScalar#subtract(org.mklab.nfc.scalar.DoubleComplexNumber)
  //   */
  //  public CIS subtract(DoubleComplexNumber c) {
  //    RoundModeManager manager = RoundModeManager.getManager();
  //    RoundMode oldRoundMode = manager.getRoundMode();
  //
  //    manager.setRoundMode(RoundMode.ROUND_DOWN);
  //    CS c1 = (CS)this.middle.subtract(c);
  //
  //    manager.setRoundMode(RoundMode.ROUND_UP);
  //    CS mid = (CS)this.middle.subtract(c);
  //
  //    S rad;
  //    if (this.radius.isZero()) {
  //      rad = mid.subtract(c1).abs();
  //    } else {
  //      rad = (mid.subtract(c1)).abs().add(this.radius);
  //    }
  //
  //    CIS ans = new AbstractComplexIntervalScalar<>(mid, rad);
  //    manager.setRoundMode(oldRoundMode);
  //    return ans;
  //  }

  /**
   * {@inheritDoc}
   */
  public CIS add(int value) {
    return createMidRad(this.middle.add(value), this.radius);
  }

  //  /**
  //   * @see org.mklab.nfc.scalar.Scalar#addSelf(org.mklab.nfc.scalar.Scalar)
  //   */
  //  public ComplexIntervalScalar<?> addSelf(Scalar<?> value) {
  //    RoundModeManager manager = RoundModeManager.getManager();
  //    RoundMode oldRoundMode = manager.getRoundMode();
  //    
  //    manager.setRoundMode(RoundMode.ROUND_DOWN);
  //    ComplexScalar<?> c1 = this.middle.add(((ComplexIntervalScalar)value).getMiddle());
  //
  //    manager.setRoundMode(RoundMode.ROUND_UP);
  //    ComplexScalar<?> mid = this.middle.add(((ComplexIntervalScalar)value).getMiddle());
  //    ComplexScalar<?> rad = (ComplexScalar<?>)((ComplexScalar<?>)mid.subtract(c1)).abs();
  //
  //    if (this.radius.isZero() == false) {
  //      rad = (ComplexScalar<?>)rad.add(this.radius);
  //    }
  //
  //    if (((ComplexIntervalScalar<?>)value).getRadius().isZero() == false) {
  //      rad = (ComplexScalar<?>)rad.add(((ComplexIntervalScalar<?>)value).getRadius());
  //    }
  //
  //    ComplexIntervalScalar<?> ans = new ComplexIntervalScalar(mid, rad);
  //    manager.setRoundMode(oldRoundMode);
  //    return ans;
  //  }

  /**
   * {@inheritDoc}
   */
  public boolean compare(String operator, int opponent) {
    if (operator.equals(".==")) { //$NON-NLS-1$
      if (this.infimum.equals(this.infimum.create(opponent)) && this.supremum.equals(this.supremum.create(opponent))) {
        return true;
      }
    } else if (operator.equals(".!=")) { //$NON-NLS-1$
      if (this.infimum.equals(this.infimum.create(opponent)) == false || this.supremum.equals(this.supremum.create(opponent)) == false) {
        return true;
      }
      return false;
    } else if (operator.equals(".<")) { //$NON-NLS-1$
      throw new UnsupportedOperationException();
    } else if (operator.equals(".<=")) { //$NON-NLS-1$
      throw new UnsupportedOperationException();
    } else if (operator.equals(".>")) { //$NON-NLS-1$
      throw new UnsupportedOperationException();
    } else if (operator.equals(".>=")) { //$NON-NLS-1$
      throw new UnsupportedOperationException();
    } else {
      throw new UnsupportedOperationException();
    }

    return true;
  }

  /**
   * {@inheritDoc}
   */
  public boolean compare(String operator, double opponent) {
    if (operator.equals(".==")) { //$NON-NLS-1$
      if (this.infimum.equals(this.infimum.create(opponent)) && this.supremum.equals(this.supremum.create(opponent))) {
        return true;
      }
    } else if (operator.equals(".!=")) { //$NON-NLS-1$
      if (this.infimum.equals(this.infimum.create(opponent)) == false || this.supremum.equals(this.supremum.create(opponent)) == false) {
        return true;
      }
      return false;
    } else if (operator.equals(".<")) { //$NON-NLS-1$
      throw new UnsupportedOperationException();
    } else if (operator.equals(".<=")) { //$NON-NLS-1$
      throw new UnsupportedOperationException();
    } else if (operator.equals(".>")) { //$NON-NLS-1$
      throw new UnsupportedOperationException();
    } else if (operator.equals(".>=")) { //$NON-NLS-1$
      throw new UnsupportedOperationException();
    } else {
      throw new UnsupportedOperationException();
    }

    return true;
  }
  
  /**
   * {@inheritDoc}
   */
  public boolean equals(CIS opponent, double tolerance) {
    final boolean realEquals = this.infimum.getRealPart().equals(opponent.getInfimum().getRealPart(), tolerance) && this.supremum.getRealPart().equals(opponent.getSupremum().getRealPart(), tolerance);
    final boolean imagEquals = this.infimum.getImaginaryPart().equals(opponent.getInfimum().getImaginaryPart(), tolerance) && this.infimum.getImaginaryPart().equals(opponent.getSupremum().getImaginaryPart(), tolerance);
    return realEquals && imagEquals;
  }


  /**
   * {@inheritDoc}
   */
  public CIS conjugate() {
    return createMidRad(this.middle.conjugate(), this.radius);
  }

//  /**
//   * {@inheritDoc}
//   */
//  public CIM createGrid(int rowSize, int columnSize, CIS[][] elements) {
//    // TODO Auto-generated method stub
//    return null;
//  }
//
//  /**
//   * {@inheritDoc}
//   */
//  public CIM createGrid(CIS[] elements) {
//    // TODO Auto-generated method stub
//    return null;
//  }

  /**
   * {@inheritDoc}
   */
  public CIS createUnit() {
    return createMidRad(this.middle.createUnit(), this.radius.createUnit());
  }

  /**
   * {@inheritDoc}
   */
  public RIS getImaginaryPart() {
    return createInfSup(this.infimum.getImaginaryPart(), this.supremum.getImaginaryPart());
  }

  /**
   * {@inheritDoc}
   */
  public RIS getRealPart() {
    return createInfSup(this.infimum.getRealPart(), this.supremum.getRealPart());
  }

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

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

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

  /**
   * {@inheritDoc}
   */
  public void setImaginaryPart(int imagPart) {
    this.infimum.setImaginaryPart(imagPart);
    this.supremum.setImaginaryPart(imagPart);
    this.middle = middle(this.infimum, this.supremum);
    this.radius = radius(this.infimum, this.supremum);
  }

  /**
   * {@inheritDoc}
   */
  public void setImaginaryPart(double imagPart) {
    this.infimum.setImaginaryPart(imagPart);
    this.supremum.setImaginaryPart(imagPart);
    this.middle = middle(this.infimum, this.supremum);
    this.radius = radius(this.infimum, this.supremum);
  }

  /**
   * {@inheritDoc}
   */
  public void setImaginaryPart(RIS imagPart) {
    this.infimum.setImaginaryPart(imagPart.getInfimum());
    this.supremum.setImaginaryPart(imagPart.getSupremum());
    this.middle = middle(this.infimum, this.supremum);
    this.radius = radius(this.infimum, this.supremum);
  }

  /**
   * {@inheritDoc}
   */
    public CIS inverse() {
    CIS conj = this.conjugate();
    RIS den = this.multiply(conj).getRealPart();
    final RIS realPart = conj.getRealPart().divide(den);
    final RIS imagPart = conj.getImaginaryPart().divide(den);
    CS inf = this.middle.create(realPart.getInfimum(), imagPart.getInfimum());
    CS sup = this.middle.create(realPart.getSupremum(), imagPart.getSupremum());
    return createInfSup(inf, sup);
  }

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

  /**
   * {@inheritDoc}
   */
  public boolean isInfinite() {
    return this.infimum.isInfinite() && this.supremum.isInfinite();
  }

  /**
   * {@inheritDoc}
   */
  public boolean isNaN() {
    return this.infimum.isNaN() && this.supremum.isNaN();
  }

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

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

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

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

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

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

  /**
   * {@inheritDoc}
   */
  public CIS leftDivide(int value) {
    return this.inverse().multiply(value);
  }

  /**
   * {@inheritDoc}
   */
  public CIS leftDivide(double value) {
    return this.inverse().multiply(value);
  }

  /**
   * {@inheritDoc}
   */
  public CIS multiply(int value) {
    return createMidRad(this.middle.multiply(value), this.radius);
  }

  /**
   * {@inheritDoc}
   */
  public CIS power(int scalar) {
    // TODO 絶対値と角度の形式に書き直す
    CIS value = this.clone();
    for (int i = 0; i < scalar; i++) {
      value = value.multiply(value);
    }
    return value;
  }

  /**
   * {@inheritDoc}
   */
  public CIS subtract(int value) {
    return createInfSup(this.infimum.subtract(value), this.supremum.subtract(value));
  }

  /**
   * {@inheritDoc}
   */
  public CIS createZero() {
    return create(this.middle.createZero());
  }

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

  /**
   * {@inheritDoc}
   */
  public String toString(String valueFormat) {
    // TODO 下限と上限もメソッド呼び出した方がいい?
    return String.format("(" + valueFormat + "," + valueFormat + ")", this.infimum, this.supremum); //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$
  }

  /**
   * {@inheritDoc}
   */
  public CIS ceil() {
    return createMidRad(this.middle.ceil(), this.radius.ceil());
  }

  /**
   * {@inheritDoc}
   */
  public CIS fix() {
    return createMidRad(this.middle.fix(), this.radius.fix());
  }

  /**
   * {@inheritDoc}
   */
  public CIS floor() {
    return createMidRad(this.middle.floor(), this.radius.floor());
  }

  /**
   * {@inheritDoc}
   */
  public CIS round() {
    return createMidRad(this.middle.round(), this.radius.round());
  }

  /**
   * {@inheritDoc}
   */
  public CIS roundToZero(double tolerance) {
    return createMidRad(this.middle.roundToZero(tolerance), this.radius.roundToZero(tolerance));
  }

  /**
   * {@inheritDoc}
   */
  public CIS roundToZero(CIS tolerance) {
    return createMidRad(this.middle.roundToZero(tolerance.getMiddle()), this.radius.roundToZero(tolerance.getMiddle().getRealPart()));
  }

  /**
   * {@inheritDoc}
   */
  public CIS unaryMinus() {
    return createMidRad(this.middle.unaryMinus(), this.radius);
  }

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

    CS abs = this.middle.abs();

    manager.setRoundMode(RoundMode.ROUND_DOWN);
    CS inf = abs.add(this.radius);

    manager.setRoundMode(RoundMode.ROUND_UP);
    CS sup = abs.add(this.radius);

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

  /**
   * {@inheritDoc}
   */
  public void printInterval() {
    System.out.println("[" + this.infimum + ", " + this.supremum + "]"); //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$

  }

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

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

  // TODO 三角関数の逆関数をちゃんとした精度保証付きで実装する

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

    manager.setRoundMode(RoundMode.ROUND_UP);
    CS mid = this.middle.acos();

    CIS ans = createMidRad(mid, this.radius);
    manager.setRoundMode(oldRoundMode);
    return ans;
  }

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

    manager.setRoundMode(RoundMode.ROUND_UP);
    CS mid = this.middle.acos();

    CIS ans = createMidRad(mid, this.radius);
    manager.setRoundMode(oldRoundMode);
    return ans;
  }

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

    manager.setRoundMode(RoundMode.ROUND_UP);
    CS mid = this.middle.atan();

    CIS ans = createMidRad(mid, this.radius);
    manager.setRoundMode(oldRoundMode);
    return ans;
  }

  /**
   * {@inheritDoc}
   */
  public CIS sqr() {
    // TODO Auto-generated method stub
    return null;
  }

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

    manager.setRoundMode(RoundMode.ROUND_DOWN);
    CS l = this.infimum.sqrt();

    manager.setRoundMode(RoundMode.ROUND_UP);
    CS s = this.supremum.sqrt();

    CS mid = l.add((s.subtract(l)).divide(2));
    RS rad = (mid.subtract(l)).abs().getRealPart();

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

  /**
   * {@inheritDoc}
   */
  public void printInfSupByBit() {
    throw new RuntimeException("Not implemented"); //$NON-NLS-1$
  }

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

    manager.setRoundMode(RoundMode.ROUND_DOWN);

    RS c = this.middle.abs().getRealPart().subtract(this.radius);

    if (c.isGreaterThanOrEquals(0)) {
      c = c.multiply(1);
    } else {
      c = c.multiply(0);
    }

    manager.setRoundMode(oldRoundMode);
    return c;
  }

  /**
   * {@inheritDoc}
   */
  public CIS exp() {
    throw new RuntimeException("Not implemented"); //$NON-NLS-1$
  }

  /**
   * {@inheritDoc}
   */
  public CIS log() {
    throw new RuntimeException("Not implemented"); //$NON-NLS-1$
  }

  /**
   * @see org.mklab.cga.interval.scalar.IntervalScalar#isPointScalar()
   */
  public boolean isPointScalar() {
    return this.radius.isZero();
  }

  /**
   * {@inheritDoc}
   */
  public boolean contains(double point) { 
    if (getMiddle().subtract(point).abs().getRealPart().isGreaterThan(getRadius())) {
      return false;
    }
    
    return true;
  }

  /**
   * {@inheritDoc}
   */
  public boolean contains(CS point) {
    if (getMiddle().subtract(point).abs().getRealPart().isGreaterThan(getRadius())) {
      return false;
    }
    return true;
  }

  /**
   * {@inheritDoc}
   */
  public CIS leftDivide(CIS value) {
    return inverse().multiply(value);
  }

  /**
   * {@inheritDoc}
   */
  public boolean compare(String operator, CIS opponent) {
    if (operator.equals(".!=")) { //$NON-NLS-1$
      if (this.infimum.equals(opponent.getInfimum()) == false || this.supremum.equals(opponent.getSupremum()) == false) {
        return true;
      }
    } else if (operator.equals(".==")) { //$NON-NLS-1$
      if (this.infimum.equals(opponent.getInfimum())  && this.supremum.equals(opponent.getSupremum())) {
        return true;
      }
    } else if (operator.equals(".<")) { //$NON-NLS-1$
      throw new UnsupportedOperationException();
    } else if (operator.equals(".<=")) { //$NON-NLS-1$
      throw new UnsupportedOperationException();
    } else if (operator.equals(".>")) { //$NON-NLS-1$
      throw new UnsupportedOperationException();
    } else if (operator.equals(".>=")) { //$NON-NLS-1$
      throw new UnsupportedOperationException();
    } else {
      throw new UnsupportedOperationException();
    }

    return false;
  }

  /**
   * {@inheritDoc}
   */
  public CIS abs2() {
    CIS abs = abs();
    return abs.multiply(abs);
  }

  /**
   * {@inheritDoc}
   */
  public CIS max(int value) {
    if (this.isGreaterThanOrEquals(value)) {
      return clone();
    }
    return create(value);
  }

  /**
   * {@inheritDoc}
   */
  public CIS max(double value) {
    if (this.isGreaterThanOrEquals(value)) {
      return clone();
    }
    return create(value);
  }

  /**
   * {@inheritDoc}
   */
  public CIS max(CIS value) {
    if (this.isGreaterThanOrEquals(value)) {
      return clone();
    }
    return value.clone();
  }

  /**
   * {@inheritDoc}
   */
  public CIS min(int value) {
    if (this.isLessThanOrEquals(value)) {
      return clone();
    }

    return create(value);
  }

  /**
   * {@inheritDoc}
   */
  public CIS min(double value) {
    if (this.isLessThanOrEquals(value)) {
      return clone();
    }

    return create(value);
  }

  /**
   * {@inheritDoc}
   */
  public CIS min(CIS value) {
    if (this.isLessThanOrEquals(value)) {
      return clone();
    }

    return value.clone();
  }

  /**
   * {@inheritDoc}
   */
  public CIS power(double scalar) {
    throw new UnsupportedOperationException();
  }

  /**
   * {@inheritDoc}
   */
  public CIS power(CIS scalar) {
    throw new UnsupportedOperationException();
  }

  /**
   * {@inheritDoc}
   */
  public CIS sin() {
    throw new UnsupportedOperationException();
  }

  /**
   * {@inheritDoc}
   */
  public CIS sinh() {
    throw new UnsupportedOperationException();
  }

  /**
   * {@inheritDoc}
   */
  public CIS asinh() {
    throw new UnsupportedOperationException();
  }

  /**
   * {@inheritDoc}
   */
  public CIS cos() {
    throw new UnsupportedOperationException();
  }

  /**
   * {@inheritDoc}
   */
  public CIS cosh() {
    throw new UnsupportedOperationException();
  }

  /**
   * {@inheritDoc}
   */
  public CIS acosh() {
    throw new UnsupportedOperationException();
  }

  /**
   * {@inheritDoc}
   */
  public CIS tan() {
    throw new UnsupportedOperationException();
  }

  /**
   * {@inheritDoc}
   */
  public CIS tanh() {
    throw new UnsupportedOperationException();
  }

  /**
   * {@inheritDoc}
   */
  public CIS atan2(CIS scalar) {
    throw new UnsupportedOperationException();
  }

  /**
   * {@inheritDoc}
   */
  public CIS atan2(int scalar) {
    throw new UnsupportedOperationException();
  }

  /**
   * {@inheritDoc}
   */
  public CIS atan2(double scalar) {
    throw new UnsupportedOperationException();
  }

  /**
   * {@inheritDoc}
   */
  public CIS atanh() {
    throw new UnsupportedOperationException();
  }

  /**
   * {@inheritDoc}
   */
  public CIS log10() {
    throw new UnsupportedOperationException();
  }

  /**
   * {@inheritDoc}
   */
  public CIS remainder(CIS value2) {
    throw new UnsupportedOperationException();
  }

  /**
   * {@inheritDoc}
   */
  public CIS remainder(int value2) {
    throw new UnsupportedOperationException();
  }

  /**
   * {@inheritDoc}
   */
  public CIS remainder(double value2) {
    throw new UnsupportedOperationException();
  }

  /**
   * {@inheritDoc}
   */
  public CIS modulus(int value2) {
    throw new UnsupportedOperationException();
  }

  /**
   * {@inheritDoc}
   */
  public CIS modulus(double value2) {
    throw new UnsupportedOperationException();
  }

  /**
   * {@inheritDoc}
   */
  public CIS modulus(CIS value2) {
    throw new UnsupportedOperationException();
  }

  /**
   * {@inheritDoc}
   */
  public boolean isLessThan(CIS opponent) {
    return abs().getRealPart().getSupremum().isLessThan(opponent.abs().getRealPart().getInfimum());
  }

  /**
   * {@inheritDoc}
   */
  public boolean isLessThanOrEquals(CIS opponent) {
    return abs().getRealPart().getSupremum().isLessThanOrEquals(opponent.abs().getRealPart().getInfimum());
  }

  /**
   * {@inheritDoc}
   */
  public boolean isGreaterThan(CIS opponent) {
    return abs().getRadius().getInfinity().isGreaterThan(opponent.abs().getRealPart().getSupremum());
  }

  /**
   * {@inheritDoc}
   */
  public boolean isGreaterThanOrEquals(CIS opponent) {
    return abs().getRadius().getInfinity().isGreaterThanOrEquals(opponent.abs().getRealPart().getSupremum());
  }

  /**
   * {@inheritDoc}
   */
  public boolean isLessThan(int opponent) {
    return abs().getRealPart().getSupremum().isLessThan(opponent);
  }

  /**
   * {@inheritDoc}
   */
  public boolean isLessThan(double opponent) {
    return abs().getRealPart().getSupremum().isLessThan(opponent);
  }

  /**
   * {@inheritDoc}
   */
  public boolean isLessThanOrEquals(int opponent) {
    return abs().getRealPart().getSupremum().isLessThanOrEquals(opponent);
  }

  /**
   * {@inheritDoc}
   */
  public boolean isLessThanOrEquals(double opponent) {
    return abs().getRealPart().getSupremum().isLessThanOrEquals(opponent);
  }

  /**
   * {@inheritDoc}
   */
  public boolean isGreaterThan(int opponent) {
    return abs().getRealPart().getInfimum().isGreaterThan(opponent);
  }

  /**
   * {@inheritDoc}
   */
  public boolean isGreaterThan(double opponent) {
    return abs().getRealPart().getInfimum().isGreaterThan(opponent);
  }

  /**
   * {@inheritDoc}
   */
  public boolean isGreaterThanOrEquals(int opponent) {
    return abs().getRealPart().getInfimum().isGreaterThanOrEquals(opponent);
  }

  /**
   * {@inheritDoc}
   */
  public boolean isGreaterThanOrEquals(double opponent) {
    return abs().getRealPart().getInfimum().isGreaterThanOrEquals(opponent);
  }

  /**
   * {@inheritDoc}
   */
  public boolean equals(CIS opponent, CIS tolerance) {
    boolean re = this.infimum.subtract(opponent.getInfimum()).abs().getRealPart().isLessThan(tolerance.getMiddle().getRealPart());
    boolean im = this.supremum.subtract(opponent.getSupremum()).abs().getRealPart().isLessThan(tolerance.getMiddle().getRealPart());
    return re && im;
  }

  /**
   * {@inheritDoc}
   */
  public boolean equals(CIS opponent, RIS tolerance) {
    boolean re = this.infimum.subtract(opponent.getInfimum()).abs().getRealPart().isLessThan(tolerance.getMiddle());
    boolean im = this.supremum.subtract(opponent.getSupremum()).abs().getRealPart().isLessThan(tolerance.getMiddle());
    return re && im;
  }

  
  /**
   * {@inheritDoc}
   */
  public CIS getMachineEpsilon() {
    return create(this.middle.getMachineEpsilon());
  }

  /**
   * {@inheritDoc}
   */
  public CIS getInfinity() {
    return create(this.middle.getInfinity());
  }

  /**
   * {@inheritDoc}
   */
  public CIS getNaN() {
    return create(this.middle.getNaN());
  }

  /**
   * {@inheritDoc}
   */
  public CIS createPI() {
    return create(this.middle.createPI());
  }

  /**
   * {@inheritDoc}
   */
  public CIS createE() {
    return create(this.middle.createE());
  }

  /**
   * {@inheritDoc}
   */
  public CIS valueOf(String numberString) {
    return create(this.middle.valueOf(numberString));
  }

  /**
   * {@inheritDoc}
   */
  public RandomGenerator<CIS, CIM> createUniformRandomGenerator() {
    throw new UnsupportedOperationException();
  }


  /**
   * {@inheritDoc}
   */
  public RIS arg() {
    throw new UnsupportedOperationException();
  }

  /**
   * {@inheritDoc}
   */
  public CIS create(RIS rePart, RIS imPart) {
    CS inf = this.middle.create(rePart.getInfimum(), imPart.getInfimum());
    CS sup = this.middle.create(rePart.getSupremum(), imPart.getSupremum());
    return createInfSup(inf, sup);
  }

  /**
   * {@inheritDoc}
   */
  public CIS create(RIS rePart) {
    CS inf = this.middle.create(rePart.getInfimum());
    CS sup = this.middle.create(rePart.getSupremum());
    return createInfSup(inf, sup);
  }

  /**
   * {@inheritDoc}
   */
  public CIS leftDivide(RIS value) {
    return inverse().multiply(value);
  }

  /**
   * {@inheritDoc}
   */
  public CIS leftDivide(CS value) {
    return inverse().multiply(value);
  }
}