DoubleImportSource.java

/*
 * Created on 2007/06/08
 * Copyright (C) 2007 Koga Laboratory. All rights reserved.
 *
 */
package org.mklab.tool.control.system.source;

import org.mklab.nfc.matrix.DoubleMatrix;
import org.mklab.nfc.scalar.DoubleNumber;


/**
 * 信号のインポート元を表わすクラスです。
 * 
 * @author koga
 * @version $Revision: 1.9 $, 2007/06/08
 */
public abstract class DoubleImportSource extends DoubleContinuousSource implements Importer {

  /** データ */
  private DoubleMatrix data;

  /** 最後に出力した時刻の番号 */
  private int last = 1;

  /**
   * 新しく生成された<code>ImportSource</code>オブジェクトを初期化します。
   */
  public DoubleImportSource() {
    super(-1);
  }

  /**
   * データを設定します。
   * 
   * @param data データ
   */
  public void setData(final DoubleMatrix data) {
    if (data == null) {
      this.data = null;
      this.last = 1;
      return;
    }
    checkDataMatrix(data);
    this.data = data.createClone();
    this.last = 1;
    setOutputSize(this.data.getRowSize() - 1);
  }

  /**
   * 行列の検査を行います。
   * 
   * @param m 行列
   * @throws IllegalArgumentException 入力行列の行数、列数が足りない場合、または時間行が単調増加ではない場合
   */
  private void checkDataMatrix(DoubleMatrix m) {
    if (m.getRowSize() < 2) throw new IllegalArgumentException(Messages.getString("ImportSource.0")); //$NON-NLS-1$
    if (m.getColumnSize() == 0) throw new IllegalArgumentException(Messages.getString("ImportSource.1")); //$NON-NLS-1$

    DoubleNumber oldValue = m.getElement(1, 1);
    for (int i = 2; i <= m.getColumnSize(); i++) {
      final DoubleNumber newValue = m.getElement(1, i);
      if (oldValue.isGreaterThan(newValue)) throw new IllegalArgumentException(Messages.getString("ImportSource.2")); //$NON-NLS-1$

      oldValue = newValue;
    }
  }

  /**
   * {@inheritDoc}
   */
  @Override
  public DoubleMatrix outputEquation(final double t) {
    int previous = -1;
    int next = -1;

    final int dataSize = this.data.getColumnSize();

    if (t < this.data.getDoubleElement(1, this.last)) {
      for (int i = this.last; 1 <= i; i--) {
        if (this.data.getDoubleElement(1, i) <= t) {
          previous = i;
          next = i + 1;
          this.last = next;
          break;
        }
      }

      if (previous == -1 || next == -1) {
        final double previousTime = this.data.getDoubleElement(2);
        final double nextTime = this.data.getDoubleElement(1);
        final DoubleMatrix previousData = this.data.getSubMatrix(2, this.data.getRowSize(), 2, 2);
        final DoubleMatrix nextData = this.data.getSubMatrix(2, this.data.getRowSize(), 1, 1);
        return previousData.add(nextData.subtract(previousData).multiply((t - previousTime) / (nextTime - previousTime)));
      }
    } else {
      for (int i = this.last; i <= dataSize; i++) {
        if (t <= this.data.getDoubleElement(1, i)) {
          previous = i - 1;
          next = i;
          this.last = previous;
          break;
        }
      }

      if (previous == -1 || next == -1) {
        final double previousTime = this.data.getDoubleElement(dataSize - 1);
        final double nextTime = this.data.getDoubleElement(dataSize);
        final DoubleMatrix previousData = this.data.getSubMatrix(2, this.data.getRowSize(), dataSize - 1, dataSize - 1);
        final DoubleMatrix nextData = this.data.getSubMatrix(2, this.data.getRowSize(), dataSize, dataSize);
        return previousData.add(nextData.subtract(previousData).multiply((t - previousTime) / (nextTime - previousTime)));
      }
    }

    if (next == 1) {
      this.last = 1;
      return this.data.getSubMatrix(2, this.data.getRowSize(), 1, 1);
    }

    if (previous == dataSize) {
      this.last = dataSize;
      return this.data.getSubMatrix(2, this.data.getRowSize(), dataSize, dataSize);
    }

    final double previousTime = this.data.getDoubleElement(1, previous);
    final double nextTime = this.data.getDoubleElement(1, next);
    final DoubleMatrix previousData = this.data.getSubMatrix(2, this.data.getRowSize(), previous, previous);
    final DoubleMatrix nextData = this.data.getSubMatrix(2, this.data.getRowSize(), next, next);

    return previousData.add(nextData.subtract(previousData).multiply((t - previousTime) / (nextTime - previousTime)));
  }

  /**
   * @see org.mklab.tool.control.system.source.Importer#isActive()
   */
  public boolean isActive() {
    if (this.data != null) {
      return true;
    }

    return false;
  }

  /**
   * @see org.mklab.tool.control.system.continuous.BaseContinuousStaticSystem#initialize()
   */
  @Override
  public void initialize() {
    super.initialize();
    this.last = 1;
  }

  /**
   * @see org.mklab.tool.control.system.SystemOperator#equals(java.lang.Object)
   */
  @Override
  public boolean equals(Object o) {
    if (this == o) {
      return true;
    }
    if (!super.equals(o)) {
      return false;
    }
    if (o == null) {
      return false;
    }
    if (o.getClass() != getClass()) {
      return false;
    }
    DoubleImportSource castedObj = (DoubleImportSource)o;
    return ((this.data == null ? castedObj.data == null : this.data.equals(castedObj.data)) && (this.last == castedObj.last));
  }

  /**
   * @see org.mklab.tool.control.system.SystemOperator#hashCode()
   */
  @Override
  public int hashCode() {
    int hashCode = super.hashCode();
    hashCode = 31 * hashCode + (this.data == null ? 0 : this.data.hashCode());
    hashCode = 31 * hashCode + this.last;
    return hashCode;
  }
}