Vector.java

package org.mklab.sdpj.datastructure;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.PrintStream;

import org.mklab.nfc.matrix.ComplexNumericalMatrix;
import org.mklab.nfc.matrix.RealNumericalMatrix;
import org.mklab.nfc.scalar.ComplexNumericalScalar;
import org.mklab.nfc.scalar.RealNumericalScalar;
import org.mklab.sdpj.gpack.atlas.ATLAS;
import org.mklab.sdpj.iocenter.IO;
import org.mklab.sdpj.tool.Tools;


/**
 * Class vector is saving data by 1-dimension array. <br>ベクトルを表すクラスです。
 * 
 * @author koga
 * @version $Revision$, 2009/04/24
 * @param <RS> type of real scalar
 * @param <RM> type of real matrix
 * @param <CS> type of complex scalar
 * @param <CM> type of complex Matrix
 */
public class Vector<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>> {

  /** 単位数 */
  private RS unit;
  /** 次数 */
  private int dimension;
  /** 要素 */
  private RS[] elements;

  /**
   * 新しく生成された<code>Vector</code>オブジェクトを初期化します。
   * 
   * @param elements 成分
   */
  public Vector(RS[] elements) {
    if (elements == null) {
      throw new IllegalArgumentException();
    }
    this.elements = elements;
    this.dimension = elements.length;
    this.unit = elements[0].createUnit();
  }

  /**
   * 新しく生成された<code>Vector</code>オブジェクトを初期化します。
   * 
   * @param dimension 次数
   * @param value 設定する値
   */
  public Vector(int dimension, RS value) {
    this.unit = value.create(1);
    initialize(dimension, value);
  }

  /**
   * 初期化します。
   * 
   * @param dimension 次数
   * @param value 設定する値
   */
  private void initialize(int dimension, RS value) {
    this.dimension = dimension;

    if (this.dimension < 0) {
      Tools.error("sdpa/data/Vector$initialize(value): nDim is nonpositive"); //$NON-NLS-1$
    }

    this.elements = value.createArray(this.dimension);
    ATLAS.<RS, RM, CS, CM> setValue(this.dimension, value, this.elements, 1);
  }

  /**
   * 初期化します。
   * 
   * @param dimension 次数
   */
  public void initialize(int dimension) {
    initialize(dimension, this.unit.create(0));
  }

  /**
   * 出力します。
   * 
   * @param out 出力先
   */
  public void display(PrintStream out) {
    out.print("{ "); //$NON-NLS-1$

    for (int i = 0; i < this.elements.length - 1; i++) {
      out.printf("%s, ", this.elements[i].toString("%+4.16e")); //$NON-NLS-1$ //$NON-NLS-2$
    }

    if (this.dimension > 0) {
      out.printf("%s", this.elements[this.elements.length - 1].toString("%+4.16e")); //$NON-NLS-1$ //$NON-NLS-2$
    }
    out.print(" }\n"); //$NON-NLS-1$
  }

  /**
   * Matlab形式で出力します。
   * 
   * @param out 出力先
   */
  public void displayAsMatlabformat(PrintStream out) {
    out.print("[\n"); //$NON-NLS-1$

    for (int i = 0; i < this.dimension - 1; i++) {
      out.printf("%s;\n", this.elements[i].toString("%+4.16e")); //$NON-NLS-1$ //$NON-NLS-2$
    }

    if (this.dimension > 0) {
      out.printf("%s;\n", this.elements[this.dimension - 1].toString("%+4.16e")); //$NON-NLS-1$ //$NON-NLS-2$
    }
    out.print("];\n\n"); //$NON-NLS-1$
  }

  /**
   * @see java.lang.Object#toString()
   */
  @Override
  public String toString() {
    StringBuffer buff = new StringBuffer();
    buff.append("{"); //$NON-NLS-1$

    for (int i = 0; i < this.dimension - 1; i++) {
      buff.append(this.elements[i].toString() + ","); //$NON-NLS-1$
    }

    if (this.dimension > 0) {
      buff.append(this.elements[this.dimension - 1] + "}\n"); //$NON-NLS-1$
    } else {
      buff.append("  }\n"); //$NON-NLS-1$
    }
    return buff.toString();
  }

  /**
   * 文字列を返します。
   * 
   * @param valueFormat 表示形式
   * @return 文字列
   */
  public String toString(String valueFormat) {
    StringBuffer buff = new StringBuffer();
    buff.append("{"); //$NON-NLS-1$

    for (int i = 0; i < this.elements.length - 1; ++i) {
      buff.append(this.elements[i].toString(valueFormat) + ","); //$NON-NLS-1$
    }

    if (this.dimension > 0) {
      buff.append(this.elements[this.elements.length - 1].toString(valueFormat) + "}\n"); //$NON-NLS-1$
    } else {
      buff.append("  }\n"); //$NON-NLS-1$
    }
    return buff.toString();
  }

  /**
   * 成分の数を返します。
   * 
   * @return 成分の数
   */
  public int getDimension() {
    return this.elements.length;
  }

  /**
   * 成分を返します。
   * 
   * @param index 指数
   * @return 成分
   */
  public RS getElement(int index) {
    return this.elements[index];
  }

  /**
   * 成分の単位を返します。
   * 
   * @return 成分の単位
   */
  public RS getElementUnit() {
    return this.elements[0].create(1);
  }

  /**
   * 成分を設定します。
   * 
   * @param index 指数
   * @param value 設定する値
   */
  public void setElement(int index, RS value) {
    this.elements[index] = value;
  }

  /**
   * 符号を反転したベクトルを返します。
   * 
   * @return 符号を反転したベクトル
   */
  public Vector<RS, RM, CS, CM> unaryMinus() {
    final RS[] results = this.elements[0].createArray(this.elements.length);
    for (int i = 0; i < this.elements.length; i++) {
      results[i] = this.elements[i].unaryMinus();
    }
    return new Vector<>(results);
  }

  /**
   * Return a copy of vector
   * 
   * @return a copy of vector
   */
  public Vector<RS, RM, CS, CM> createClone() {
    if (this.elements != null) {
      RS[] elementsClone = this.elements[0].createArray(this.elements.length);
      System.arraycopy(this.elements, 0, elementsClone, 0, this.elements.length);
      return new Vector<>(elementsClone);
    }

    return new Vector<>(0, this.unit);
  }

  /**
   * Return a vector
   * 
   * @return a vector
   */
  public RS[] getElements() {
    return this.elements;
  }

  /**
   * Set variable elements
   * 
   * @param data a vector
   */
  public void setElements(RS[] data) {
    this.elements = data;
  }

  /**
   * Read a vector data from a inputting data file.
   * 
   * @param <RS> type of real scalar
   * @param <RM> type of real matrix
   * @param <CS> type of complex scalar
   * @param <CM> type of complex Matrix
   * @param reader instance of class <code>BufferedReader</code>
   * @param dimension dimension of the vector
   * @param unit unit
   * @return a vector
   * @throws IOException If I/O exception occurs
   */
  public static <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>> Vector<RS, RM, CS, CM> read(
      BufferedReader reader, int dimension, RS unit) throws IOException {
    //final RS unit = Tools.getUnitNumber();
    final Vector<RS, RM, CS, CM> vector = new Vector<>(dimension, unit);

    StringBuffer buff = new StringBuffer(reader.readLine());
    for (int i = 0; i < dimension; i++) {
      vector.setElement(i, unit.valueOf(IO.readOtherStringRealNumber(buff)));
    }

    return vector;
  }
}