AbstractIntervalRealNumericalScalar.java

/*
 * Created on 2008/02/01
 * 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.IntervalNumericalMatrix;
import org.mklab.cga.interval.matrix.IntervalRealNumericalMatrix;
import org.mklab.nfc.matrix.ComplexNumericalMatrix;
import org.mklab.nfc.matrix.NumericalMatrix;
import org.mklab.nfc.matrix.RealNumericalMatrix;
import org.mklab.nfc.scalar.ComplexNumericalScalar;
import org.mklab.nfc.scalar.NumericalScalar;
import org.mklab.nfc.scalar.RealNumericalScalar;
import org.mklab.nfc.util.RoundMode;
import org.mklab.nfc.util.RoundModeManager;


/**
 * {@link NumericalScalar}を要素とする実区間を表すクラスです。
 * 
 * @author yano
 * @version $Revision: 1.7 $, 2008/02/01
 * @param <RIS> 実区間スカラーの型
 * @param <RIM> 実区間行列の型
 * @param <CIS> 複素区間スカラーの型
 * @param <CIM> 複素区間行列の型
 * @param <RS> 実スカラーの型
 * @param <RM> 実行列の型
 * @param <CS> 複素スカラーの型
 * @param <CM> 複素行列の型
 */
public abstract class AbstractIntervalRealNumericalScalar<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<RIS, RIM, RS, RM> implements IntervalRealNumericalScalar<RIS, RIM, CIS, CIM, RS, RM, CS, CM> {

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

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

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

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

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

  /**
   * 新しく生成された{@link AbstractIntervalRealNumericalScalar}オブジェクトを初期化します。
   * 
   * 同じ値が上限、下限、中心に設定されます。 また、半径は0に設定されます。
   * 
   * @param middle 点
   */
  public AbstractIntervalRealNumericalScalar(final RS middle) {
    this.infimum = middle;
    this.supremum = middle;
    this.middle = middle;
    this.radius = middle.createZero();
  }

  /**
   * 新しく生成された{@link AbstractIntervalRealNumericalScalar}オブジェクトを初期化します。
   * 
   * 上限と下限を設定します。 中心と半径は、上限と下限から計算されます。
   * 
   * @param infimum 下限
   * @param supremum 上限
   */
  public AbstractIntervalRealNumericalScalar(final RS infimum, final RS supremum) {
    this.infimum = infimum;
    this.supremum = supremum;
    this.middle = middle(infimum, supremum);
    this.radius = radius(infimum, supremum);
  }

  /**
   * {@inheritDoc}
   */
  public RIS create(final int value) {
    RS point = this.middle.create(value);
    return createInfSup(point, point);
  }

  /**
   * 区間の半径を求めます。
   * 
   * @param <IS> 区間スカラーの型
   * @param <IM> 区間行列の型
   * @param <S> スカラーの型
   * @param <M> 行列の型
   * 
   * @param inf infimum
   * @param sup supremum
   * 
   * @return 区間の半径
   */
  public static <IS extends IntervalNumericalScalar<IS, IM, S, M>, IM extends IntervalNumericalMatrix<IS, IM, S, M>, S extends NumericalScalar<S, M>, M extends NumericalMatrix<S, M>> S radius(
      S inf, S sup) {
    RoundModeManager manager = RoundModeManager.getManager();
    RoundMode oldRoundMode = manager.getRoundMode();

    manager.setRoundMode(RoundMode.ROUND_UP);
    S mid = middle(inf, sup);
    S rad = mid.subtract(inf);

    manager.setRoundMode(oldRoundMode);
    return rad;
  }

  /**
   * 区間の中心を求めます。
   * 
   * @param <IS> 区間スカラーの型
   * @param <IM> 区間行列の型
   * @param <S> スカラーの型
   * @param <M> 行列の型
   * 
   * @param inf infimum
   * @param sup supremum
   * 
   * @return 区間の中心
   */
  public static <IS extends IntervalNumericalScalar<IS, IM, S, M>, IM extends IntervalNumericalMatrix<IS, IM, S, M>, S extends NumericalScalar<S, M>, M extends NumericalMatrix<S, M>> S middle(
      S inf, S sup) {
    RoundModeManager manager = RoundModeManager.getManager();
    RoundMode oldRoundMode = manager.getRoundMode();

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

    manager.setRoundMode(oldRoundMode);
    return mid;
  }

  /**
   * {@inheritDoc}
   */
  public RIS add(RIS interval) {
    RoundModeManager manager = RoundModeManager.getManager();
    RoundMode oldRoundMode = manager.getRoundMode();

    manager.setRoundMode(RoundMode.ROUND_DOWN);
    RS inf = this.infimum.add(interval.getInfimum());

    manager.setRoundMode(RoundMode.ROUND_UP);
    RS sup = this.supremum.add(interval.getSupremum());

    manager.setRoundMode(oldRoundMode);

    manager.setRoundMode(oldRoundMode);

    return createInfSup(inf, sup);

    //    if (interval.isComplex()) {
    //      manager.setRoundMode(RoundMode.ROUND_DOWN);
    //      S c1 = (S)interval.getMiddle().createUnit().multiply(this.middle).add(interval.getMiddle());
    //
    //      manager.setRoundMode(RoundMode.ROUND_UP);
    //      ComplexScalar<?> mid = (ComplexScalar<?>)interval.getMiddle().createUnit().multiply(this.middle).add(interval.getMiddle());
    //      S rad = (S)mid.subtract(c1).add(this.radius).getRealPart();
    //      rad = (S)rad.add(this.radius);
    //      rad = (S)rad.add(interval.getRadius());
    //
    //      manager.setRoundMode(oldRoundMode);
    //      return new AbstractComplexIntervalScalar(mid, rad);
    //    }
  }

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

    manager.setRoundMode(RoundMode.ROUND_DOWN);
    RS inf = this.infimum.add(d);

    manager.setRoundMode(RoundMode.ROUND_UP);
    RS sup = this.supremum.add(d);

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

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

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

    if (interval.isReal()) {// IR/IR
      manager.setRoundMode(RoundMode.ROUND_DOWN);
      RS cinf1 = this.infimum.divide(interval.getInfimum());
      RS cinf2 = this.infimum.divide(interval.getSupremum());
      RS cinf3 = this.supremum.divide(interval.getInfimum());
      RS cinf4 = this.supremum.divide(interval.getSupremum());

      RS cinf = cinf1.isLessThanOrEquals(cinf2) ? cinf1.clone() : cinf2.clone();
      cinf = cinf.isLessThanOrEquals(cinf3) ? cinf.clone() : cinf3.clone();
      cinf = cinf.isLessThanOrEquals(cinf4) ? cinf.clone() : cinf4.clone();

      manager.setRoundMode(RoundMode.ROUND_UP);
      RS csup1 = this.infimum.divide(interval.getInfimum());
      RS csup2 = this.infimum.divide(interval.getSupremum());
      RS csup3 = this.supremum.divide(interval.getInfimum());
      RS csup4 = this.supremum.divide(interval.getSupremum());

      RS csup = csup1.isLessThanOrEquals(csup2) ? csup1.clone() : csup2.clone();
      csup = csup.isLessThanOrEquals(csup3) ? csup.clone() : csup3.clone();
      csup = csup.isLessThanOrEquals(csup4) ? csup.clone() : csup4.clone();

      manager.setRoundMode(oldRoundMode);
      return createInfSup(cinf, csup);
    }

    if (interval.isComplex()) {// IR/IC
      // TODO 複素数区間の時のメソッドを作成する(精度関係無しで?)
      manager.setRoundMode(oldRoundMode);
      return divide(interval);
    }

    manager.setRoundMode(oldRoundMode);
    throw new RuntimeException("Not implemented."); //$NON-NLS-1$
  }

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

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

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

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

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

    if (interval.isReal()) {// IR*IR
      RS xd = this.infimum;
      RS xu = this.supremum;

      RS yd = interval.getInfimum();
      RS yu = interval.getSupremum();

      manager.setRoundMode(RoundMode.ROUND_UP);

      RS xc = xu.add(xd).divide(2); // アルファ中心
      RS xr = xc.subtract(xd); // シータ半径
      RS yc = yu.add(yd).divide(2); // ベータ
      RS yr = yc.subtract(yd); // ガンマ

      RS sup = xc.multiply(yc).add(xc.abs().multiply(yr)).add(yc.abs().multiply(xr)).add(xr.multiply(yr));

      manager.setRoundMode(RoundMode.ROUND_DOWN);

      RS inf = xc.multiply(yc).add(xc.abs().unaryMinus().multiply(yr).add(yc.abs().unaryMinus().multiply(xr).add(xr.unaryMinus().add(yr))));

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

    if (interval.isComplex()) {// IR*IC
      manager.setRoundMode(oldRoundMode);
      throw new RuntimeException("Not implemented."); //$NON-NLS-1$
    }

    manager.setRoundMode(oldRoundMode);
    throw new RuntimeException("Not implemented."); //$NON-NLS-1$
  }

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

    manager.setRoundMode(RoundMode.ROUND_UP);
    RS rad = this.radius.multiply(Math.abs(d));
    RS sup = this.middle.multiply(d).add(rad);

    manager.setRoundMode(RoundMode.ROUND_DOWN);
    RS inf = this.middle.multiply(d).subtract(rad);

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

  //  /**
  //   * {@inheritDoc}
  //   */
  //  public AbstractComplexIntervalScalar<?> multiply(DoubleComplexNumber c) {
  //    RoundModeManager manager = RoundModeManager.getManager();
  //    RoundMode oldRoundMode = manager.getRoundMode();
  //
  //    manager.setRoundMode(RoundMode.ROUND_DOWN);
  //    ComplexScalar<?> c1 = (ComplexScalar<?>)this.middle.multiply(c);
  //
  //    manager.setRoundMode(RoundMode.ROUND_UP);
  //    ComplexScalar<?> c2 = (ComplexScalar<?>)this.middle.multiply(c);
  //    ComplexScalar<?> mid = (ComplexScalar<?>)c1.add(c2.subtract(c1)).divide(2);
  //    S rad = (S)((ComplexScalar<?>)mid.subtract(c1)).abs().add(this.radius.multiply(c.abs()));
  //
  //    manager.setRoundMode(oldRoundMode);
  //    return new AbstractComplexIntervalScalar(mid, rad);
  //  }

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

    manager.setRoundMode(RoundMode.ROUND_UP);
    RS ans = this.supremum.subtract(this.infimum);

    manager.setRoundMode(oldRoundMode);
    return ans;
  }

  /**
   * {@inheritDoc}
   */
  public void printInfSup(String messe) {
    System.out.println(messe + Messages.getString("NumericalScalarInterval.0") + this.infimum); //$NON-NLS-1$
    System.out.println(messe + Messages.getString("NumericalScalarInterval.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 RIS subtract(RIS interval) {// IR-IR
    RoundModeManager manager = RoundModeManager.getManager();
    RoundMode oldRoundMode = manager.getRoundMode();

    manager.setRoundMode(RoundMode.ROUND_DOWN);
    RS inf = this.infimum.subtract(interval.getSupremum());

    manager.setRoundMode(RoundMode.ROUND_UP);
    RS sup = this.supremum.subtract(interval.getInfimum());

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

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

    manager.setRoundMode(RoundMode.ROUND_DOWN);
    RS inf = this.infimum.subtract(d);

    manager.setRoundMode(RoundMode.ROUND_UP);
    RS sup = this.supremum.subtract(d);

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

  //  /**
  //   * {@inheritDoc}
  //   */
  //  public AbstractComplexIntervalScalar<?> subtract(DoubleComplexNumber c) {
  //    RoundModeManager manager = RoundModeManager.getManager();
  //    RoundMode oldRoundMode = manager.getRoundMode();
  //
  //    manager.setRoundMode(RoundMode.ROUND_DOWN);
  //    ComplexScalar<?> c1 = (ComplexScalar<?>)this.middle.subtract(c);
  //
  //    manager.setRoundMode(RoundMode.ROUND_UP);
  //    ComplexScalar<?> mid = (ComplexScalar<?>)this.middle.subtract(c);
  //    S rad = (S)((ComplexScalar<?>)mid.subtract(c1)).abs().add(this.radius);
  //
  //    manager.setRoundMode(oldRoundMode);
  //    return new AbstractComplexIntervalScalar(mid, rad);
  //  }

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

    manager.setRoundMode(RoundMode.ROUND_DOWN);
    RS inf = this.infimum.add(value);

    manager.setRoundMode(RoundMode.ROUND_UP);
    RS sup = this.supremum.add(value);

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

  //  /**
  //   * @see org.mklab.nfc.scalar.Scalar#addSelf(org.mklab.nfc.scalar.Scalar)
  //   */
  //  public NumericalIntervalScalar<?> addSelf(Scalar<?> value) {
  //    RoundModeManager manager = RoundModeManager.getManager();
  //    RoundMode oldRoundMode = manager.getRoundMode();
  //    
  //    manager.setRoundMode(RoundMode.ROUND_DOWN);
  //    this.infimum = (T)this.infimum.add(((NumericalIntervalScalar)value).getInfimum());
  //    
  //    manager.setRoundMode(RoundMode.ROUND_UP);
  //    this.supremum = (T)this.supremum.add(((NumericalIntervalScalar)value).getSupremum());
  //
  //    manager.setRoundMode(oldRoundMode);
  //    return this;
  //  }

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

    return false;
  }

  /**
   * {@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)) && this.supremum.equals(this.supremum.create(opponent))) {
        return true;
      }
    } else if (operator.equals(".<")) { //$NON-NLS-1$
      if (this.supremum.isLessThan(opponent)) {
        return true;
      }
    } else if (operator.equals(".<=")) { //$NON-NLS-1$
      if (this.supremum.isLessThanOrEquals(opponent)) {
        return true;
      }
    } else if (operator.equals(".>")) { //$NON-NLS-1$
      if (this.infimum.isGreaterThan(opponent)) {
        return true;
      }
    } else if (operator.equals(".>=")) { //$NON-NLS-1$
      if (this.infimum.isGreaterThanOrEquals(opponent)) {
        return true;
      }
    } else {
      throw new UnsupportedOperationException();
    }

    return false;
  }

  /**
   * {@inheritDoc}
   */
  public boolean equals(RIS opponent, double tolerance) {
    return this.infimum.subtract(opponent.getInfimum()).abs().compare("<=", tolerance) && this.supremum.subtract(opponent.getSupremum()).abs().compare("<=", tolerance); //$NON-NLS-1$ //$NON-NLS-2$
  }

  /**
   * {@inheritDoc}
   */
  public RIS conjugate() {
    return this.clone();
  }

  /**
   * {@inheritDoc}
   */
  public RIS createUnit() {
    return create(this.middle.createUnit());
  }

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

    manager.setRoundMode(RoundMode.ROUND_DOWN);
    // TODO NumericalScalar用のminとmaxを比較演算子を使ってプライベートで作って実行可能にする
    RS cinf1 = this.infimum.divide(value);
    RS cinf2 = this.supremum.divide(value);
    RS cinf = cinf1.isLessThanOrEquals(cinf2) ? cinf1.clone() : cinf2.clone();

    manager.setRoundMode(RoundMode.ROUND_UP);
    RS csup1 = this.infimum.divide(value);
    RS csup2 = this.supremum.divide(value);
    RS csup = csup1.isGreaterThanOrEquals(csup2) ? csup1.clone() : csup2.clone();

    manager.setRoundMode(oldRoundMode);
    return createInfSup(cinf, csup);
  }

  /**
   * {@inheritDoc}
   */
  public RIS divide(double value) {
    // TODO Auto-generated method stub
    throw new UnsupportedOperationException();
  }

  //  /**
  //   * @see org.mklab.nfc.scalar.Scalar#getImaginaryPart()
  //   */
  //  public IS getImaginaryPart() {
  //    return this.createZero();
  //  }
  //
  //  /**
  //   * @see org.mklab.nfc.scalar.Scalar#getRealPart()
  //   */
  //  public IS getRealPart() {
  //    return (IS)this.clone();
  //  }
  //
  //  /**
  //   * @see org.mklab.nfc.scalar.Scalar#setRealPart(int)
  //   */
  //  public void setRealPart(int realPart) {
  //    throw new UnsupportedOperationException("Not a complex number"); //$NON-NLS-1$
  //  }
  //
  //  /**
  //   * @see org.mklab.nfc.scalar.Scalar#setRealPart(double)
  //   */
  //  public void setRealPart(double realPart) {
  //    throw new UnsupportedOperationException("Not a complex number"); //$NON-NLS-1$
  //  }
  //
  //  /**
  //   * @see org.mklab.nfc.scalar.Scalar#setRealPart(org.mklab.nfc.scalar.Scalar)
  //   */
  //  public void setRealPart(Scalar<?> realPart) {
  //    throw new UnsupportedOperationException("Not a complex number"); //$NON-NLS-1$
  //  }
  //
  //  /**
  //   * @see org.mklab.nfc.scalar.Scalar#setImaginaryPart(int)
  //   */
  //  public void setImaginaryPart(int imagPart) {
  //    throw new UnsupportedOperationException("Not a complex number"); //$NON-NLS-1$
  //  }
  //
  //  /**
  //   * @see org.mklab.nfc.scalar.Scalar#setImaginaryPart(double)
  //   */
  //  public void setImaginaryPart(double imagPart) {
  //    throw new UnsupportedOperationException("Not a complex number"); //$NON-NLS-1$
  //  }
  //
  //  /**
  //   * @see org.mklab.nfc.scalar.Scalar#setImaginaryPart(org.mklab.nfc.scalar.Scalar)
  //   */
  //  public void setImaginaryPart(Scalar<?> imagPart) {
  //    throw new UnsupportedOperationException("Not a complex number"); //$NON-NLS-1$
  //  }

  /**
   * {@inheritDoc}
   */
  public RIS inverse() {
    RS infInverse = this.supremum.inverse();
    RS supInverse = this.infimum.inverse();
    return createInfSup(infInverse.min(supInverse), infInverse.max(supInverse));
  }

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

  /**
   * {@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 true;
  }

  /**
   * {@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(RIS 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(RIS tolerance) {
    return this.infimum.isZero(tolerance.getMiddle()) && this.supremum.isZero(tolerance.getMiddle());
  }

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

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

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

    RS localMiddle = this.middle.multiply(value);

    manager.setRoundMode(RoundMode.ROUND_DOWN);
    RS localInfimum = localMiddle.add(this.radius);

    manager.setRoundMode(RoundMode.ROUND_UP);
    RS localSupremum = localMiddle.add(this.radius);

    manager.setRoundMode(oldRoundMode);
    return createInfSup(localInfimum, localSupremum);
  }

  /**
   * {@inheritDoc}
   */
  public RIS power(int scalar) {
    RIS value = this.create(1);
    if (scalar == 0) {
      return value;
    }
    for (int i = 0; i < scalar; i++) {
      value = value.multiply((RIS)this);
    }
    return value;
  }

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

    manager.setRoundMode(RoundMode.ROUND_DOWN);
    RS inf = this.infimum.subtract(value);

    manager.setRoundMode(RoundMode.ROUND_UP);
    RS sup = this.supremum.subtract(value);

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

  //  /**
  //   * @see org.mklab.nfc.scalar.Scalar#toComplex()
  //   */
  //  public IntervalScalar<?> toComplex() {
  //    // TODO Complex側のコンストラクタ追加・変更が必要
  //    return null;
  //  }

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

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

  /**
   * {@inheritDoc}
   */
  public String toString(String valueFormat) {
    return String.format("(" + valueFormat + "," + valueFormat + ")", this.infimum, this.supremum); //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$
  }

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

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

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

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

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

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

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

  /**
   * {@inheritDoc}
   */
  public RIS abs() {
    // TODO minとmaxを実装して実行できるようにする
    RS inf_abs = this.infimum.abs();
    RS sup_abs = this.supremum.abs();

    RS min;
    RS max;
    if (sup_abs.isGreaterThanOrEquals(inf_abs)) {
      min = inf_abs;
      max = sup_abs;
    } else {
      min = sup_abs;
      max = inf_abs;
    }

    return createInfSup(min, max);
  }

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

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

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

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

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

    manager.setRoundMode(RoundMode.ROUND_DOWN);
    RS inf = this.infimum.acos();

    manager.setRoundMode(RoundMode.ROUND_UP);
    RS sup = this.supremum.acos();

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

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

    manager.setRoundMode(RoundMode.ROUND_DOWN);
    RS inf = this.infimum.asin();

    manager.setRoundMode(RoundMode.ROUND_UP);
    RS sup = this.supremum.asin();

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

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

    manager.setRoundMode(RoundMode.ROUND_DOWN);
    RS inf = this.infimum.atan();

    manager.setRoundMode(RoundMode.ROUND_UP);
    RS sup = this.supremum.atan();

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

  /**
   * {@inheritDoc}
   */
  public RIS sqr() {
    RIS abs = this.abs();
    return createInfSup(abs.getInfimum().multiply(abs.getInfimum()), abs.getSupremum().multiply(abs.getSupremum()));
  }

  /**
   * {@inheritDoc}
   */
  public RIS sqrt() {
    // TODO IEEE754なら平方根の精度は保証されてるけど、これは大丈夫なの?
    RoundModeManager manager = RoundModeManager.getManager();
    RoundMode oldRoundMode = manager.getRoundMode();

    manager.setRoundMode(RoundMode.ROUND_DOWN);
    RS inf = this.infimum.sqrt();

    manager.setRoundMode(RoundMode.ROUND_UP);
    RS sup = this.supremum.sqrt();

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

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

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

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

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

  //  /**
  //   * 中心と半径を設定し、区間を作成します。
  //   * @param <IS> 区間スカラーの型
  //   * @param <IM> 区間行列の型
  //   * @param <S> スカラーの型
  //   * @param <M> 行列の型
  //   * 
  //   * @param mid 中心
  //   * @param rad 半径
  //   * @return 区間
  //   */
  //  public static <IS extends IntervalScalar<IS,IM,S,M>, IM extends IntervalMatrix<IS,IM,S,M>,  S extends NumericalScalar<S,M>, M extends NumericalMatrix<S,M>> IS createWithMiddleRadius(S mid, S rad) {
  //    RoundModeManager manager = RoundModeManager.getManager();
  //    RoundMode oldRoundMode = manager.getRoundMode();
  //
  //    manager.setRoundMode(RoundMode.ROUND_DOWN);
  //    S inf = mid.subtract(rad);
  //
  //    manager.setRoundMode(RoundMode.ROUND_UP);
  //    S sup = mid.add(rad);
  //
  //    manager.setRoundMode(oldRoundMode);
  //    return (IntervalScalar<S>)IntervalScalarFactory.createWithInfimumSupremum(inf, sup);
  //    //return new NumericalIntervalScalar<E>(inf, sup);
  //  }

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

  /**
   * {@inheritDoc}
   */
  public boolean contains(final double point) {
    if (getInfimum().isGreaterThan(point)) {
      return false;
    }
    
    if (getSupremum().isLessThan(point)) {
      return false;
    }

    return true;
  }

  /**
   * {@inheritDoc}
   */
  public boolean contains(final RS point) {
    if (getInfimum().isGreaterThan(point)) {
      return false;
    }
    
    if (getSupremum().isLessThan(point)) {
      return false;
    }

    return true;
  }
  

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

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

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

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

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