Diff.java

/*
 * $Id: Diff.java,v 1.10 2008/07/16 15:40:00 koga Exp $
 * 
 * Copyright (C) 2004 Koga Laboratory. All rights reserved.
 */
package org.mklab.tool.matrix;

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


/**
 * 列毎や行毎の差を求めるクラスです。
 * 
 * <p>Difference function for each column
 * 
 * @author koga
 * @version $Revision: 1.10 $
 * @see org.mklab.nfc.matrix.Matrix#cumulativeSum
 */
public class Diff {

  /**
   * もし <code>x</code> がベクトルなら、隣り合う成分の差からなるベクトル <code>[x(2)-x(1) x(3)-x(2) ... x(n)-x(n-1)]</code> を返します。
   * 
   * @param x データ
   * @return 差分 (difference)
   */
  public static DoubleMatrix diff(DoubleMatrix x) {
    if (x.getRowSize() == 1 || x.getColumnSize() == 1) {
      return diffColumnWise(x);
    }
    throw new IllegalArgumentException(Messages.getString("Diff.0")); //$NON-NLS-1$
  }

  /**
   * <code>order</code> 階差分を求めます。
   * 
   * @param x データ
   * @param order 階数
   * @return 差分 (difference)
   */
  public static DoubleMatrix diff(DoubleMatrix x, int order) {
    if (x.getRowSize() == 1 || x.getColumnSize() == 1) {
      return diffColumnWise(x, order);
    }
    throw new IllegalArgumentException(Messages.getString("Diff.1")); //$NON-NLS-1$
  }

  /**
   * もし <code>x</code> が行列なら、列毎に差分
   * 
   * <pre><code>
   * 
   * diff_col(x) = x(2:n,:) - x(1:n-1,:).
   * 
   * </code></pre>
   * 
   * を求めます。
   * 
   * @param x データ
   * @return 差分 (difference)
   */
  public static DoubleMatrix diffColumnWise(DoubleMatrix x) {
    return diffColumnWise(x, 1);
  }

  /**
   * <code>order</code> 階差分を求めます。
   * 
   * @param x 対象となる行列
   * @param order 階数
   * @return 差分 (difference)
   */
  public static DoubleMatrix diffColumnWise(DoubleMatrix x, int order) {
    if (order <= 0) {
      throw new IllegalArgumentException(Messages.getString("Diff.2")); //$NON-NLS-1$
    }

    DoubleMatrix mat = x;
    for (int i = 1; i <= order; i++) {
      final int m = mat.getRowSize();
      final int n = mat.getColumnSize();
      if (m == 1) {
        mat = mat.getSubVector(2, n).subtract(mat.getSubVector(1, n - 1));
      } else {
        mat = mat.getRowVectors(2, m).subtract(mat.getRowVectors(1, m - 1));
      }
    }
    return mat;
  }

  /**
   * もし <code>x</code> が行列なら、行毎に差分
   * 
   * <pre><code>
   * 
   * diff_row(x) = x(:,2:n) - x(:,1:n-1).
   * 
   * </code></pre>
   * 
   * を計算します。
   * 
   * @param x データ
   * @return 差分 (difference)
   */
  public static DoubleMatrix diffRowWise(DoubleMatrix x) {
    return diffColumnWise(x.transpose()).transpose();
  }

  /**
   * <code>order</code> 階差分を求めます。
   * 
   * @param x データ
   * @param order 階数
   * @return 差分 (difference)
   */
  public static DoubleMatrix diffRowWise(DoubleMatrix x, int order) {
    return diffColumnWise(x.transpose(), order).transpose();
  }

  /**
   * もし <code>x</code> がベクトルなら、隣り合う成分の差からなるベクトル <code>[x(2)-x(1) x(3)-x(2) ... x(n)-x(n-1)]</code> を返します。
   * 
   * @param x データ
   * @return 差分 (difference)
   * @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 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>> RM diff(
      RM x) {
    if (x.getRowSize() == 1 || x.getColumnSize() == 1) {
      return diffColumnWise(x);
    }
    throw new IllegalArgumentException(Messages.getString("Diff.0")); //$NON-NLS-1$
  }

  /**
   * もし <code>x</code> が行列なら、列毎に差分
   * 
   * <pre><code>
   * 
   * diff_col(x) = x(2:n,:) - x(1:n-1,:).
   * 
   * </code></pre>
   * 
   * を求めます。
   * 
   * @param x データ
   * @return 差分 (difference)
   * @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 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>> RM diffColumnWise(
      RM x) {
    return diffColumnWise(x, 1);
  }

  /**
   * <code>order</code> 階差分を求めます。
   * 
   * @param x 対象となる行列
   * @param order 階数
   * @return 差分 (difference)
   * @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 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>> RM diffColumnWise(
      RM x, int order) {
    if (order <= 0) {
      throw new IllegalArgumentException(Messages.getString("Diff.2")); //$NON-NLS-1$
    }

    RM mat = x;
    for (int i = 1; i <= order; i++) {
      final int m = mat.getRowSize();
      final int n = mat.getColumnSize();
      if (m == 1) {
        mat = mat.getSubVector(2, n).subtract(mat.getSubVector(1, n - 1));
      } else {
        mat = mat.getRowVectors(2, m).subtract(mat.getRowVectors(1, m - 1));
      }
    }
    return mat;
  }

}