BlockVector.java

package org.mklab.sdpj.datastructure;

import java.util.Arrays;

import org.mklab.nfc.matrix.ComplexNumericalMatrix;
import org.mklab.nfc.matrix.RealNumericalMatrix;
import org.mklab.nfc.scalar.ComplexNumericalScalar;
import org.mklab.nfc.scalar.RealNumericalScalar;


/**
 * ブロックベクトルを表すクラスです。
 * 
 * @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 BlockVector<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 blockSize;
  /** ブロック構造 */
  private int[] blockStruct;
  /** 成分 */
  private Vector<RS,RM,CS,CM>[] blocks;

  /**
   * 新しく生成された{@link BlockVector}オブジェクトを初期化します。
   * 
   * @param unit 単位数
   */
  public BlockVector(RS unit) {
    this.blockSize = 0;
    this.unit = unit;
  }

  /**
   * 新しく生成された{@link BlockVector}オブジェクトを初期化します。
   * 
   * @param blockSize ブロック数
   * @param blockStruct ブロック構造
   * @param unit 単位数
   */
  public BlockVector(int blockSize, int[] blockStruct, RS unit) {
    this.unit = unit;
    this.initialize(blockSize, blockStruct, unit.create(0));
  }

  /**
   * 初期化します。
   * 
   * @param blockSize1 ブロック数
   * @param blockStruct1 ブロック構造
   * @param value 初期値
   */
  private void initialize(int blockSize1, int[] blockStruct1, RS value) {
    this.blockSize = blockSize1;
    if (blockSize1 <= 0) {
      throw new RuntimeException("BlockVector:nBlock is nonpositive"); //$NON-NLS-1$
    }

    this.blockStruct = new int[this.blockSize];
    System.arraycopy(blockStruct1, 0, this.blockStruct, 0, blockSize1);

    this.blocks = new Vector[this.blockSize];
    RS zero = value.createZero();
    for (int i = 0; i < this.blockSize; i++) {
      int size = this.blockStruct[i];
      if (size < 0) {
        size = (-size);
      }
      this.blocks[i] = new Vector<>(size, zero);
    }
  }

  /**
   * 初期化します。
   * 
   * @param blockSize1 ブロック数
   * @param blockStruct1 ブロック構造
   */
  public void initialize(int blockSize1, int[] blockStruct1) {
    initialize(blockSize1, blockStruct1, this.unit.create(0));
  }

  /**
   * コピーします。
   * 
   * @param source コピー元
   */
  @SuppressWarnings("unchecked")
  public void copyFrom(BlockVector<RS,RM,CS,CM> source) {
    if (source.getBlockSize() < 0) {
      throw new RuntimeException("BlockVector:: nBlock && blockStruct"); //$NON-NLS-1$
    }

    this.blockSize = source.getBlockSize();
    this.blockStruct = new int[source.blockSize];
    System.arraycopy(source.blockStruct, 0, this.blockStruct, 0, source.blockSize);

    this.blocks = new Vector[source.blockSize];
    RS zero = this.unit.create(0);
    for (int i = 0; i < source.blockSize; i++) {
      this.blocks[i] = new Vector<>(0, zero);
    }

    for (int i = 0; i < source.blockSize; i++) {
      this.blocks[i] = source.getBlock(i).createClone();
    }
  }

  /**
   * ブロック数を返します。
   * 
   * @return ブロック数
   */
  public int getBlockSize() {
    return this.blockSize;
  }

  /**
   * ブロックの構造を返します。
   * 
   * @return ブロックの構造
   */
  public int[] getBlockStructs() {
    return Arrays.copyOf(this.blockStruct, this.blockSize);
  }

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

    for (int i = 0; i < this.blockSize; i++) {
      buff.append(this.getBlock(i).toString());
    }

    buff.append("}\n"); //$NON-NLS-1$
    return buff.toString();
  }

  /**
   * ブロック成分を返します。
   * 
   * @param index 指数
   * @return ブロック成分
   */
  public Vector<RS,RM,CS,CM> getBlock(int index) {
    return this.blocks[index];
  }

  /**
   * ブロック成分を設定します。
   * 
   * @param index 指数
   * @param block ブロック成分
   */
  public void setBlock(int index, Vector<RS,RM,CS,CM> block) {
    this.blocks[index] = block;
  }

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

  /**
   * Returns a copy of instance of class <code>BlockVector</code>.
   * 
   * @return a copy of instance of class <code>BlockVector</code>
   */
  public BlockVector<RS,RM,CS,CM> createClone() {
    BlockVector<RS,RM,CS,CM> inst = new BlockVector<>(this.unit);
    inst.unit = this.unit == null ? null : this.unit;
    inst.blockSize = this.blockSize;

    if (this.blockStruct != null) {
      inst.blockStruct = new int[this.blockStruct.length];
      for (int i = 0; i < this.blockStruct.length; i++) {
        inst.blockStruct[i] = this.blockStruct[i];
      }
    } else {
      inst.blockStruct = null;
    }

    if (this.blocks != null) {
      inst.blocks = new Vector[this.blocks.length];
      for (int i = 0; i < this.blocks.length; i++) {
        inst.blocks[i] = this.blocks[i] == null ? null : this.blocks[i].createClone();
      }
    } else {
      inst.blocks = null;
    }
    return inst;
  }
}