Cdf2rdf.java

/*
 * $Id: Cdf2rdf.java,v 1.20 2008/03/26 14:31:23 koga Exp $
 * 
 * Copyright (C) 2004 Koga Laboratory. All rights reserved.
 */
package org.mklab.tool.matrix;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import org.mklab.nfc.matrix.DoubleComplexMatrix;
import org.mklab.nfc.matrix.DoubleMatrix;
import org.mklab.nfc.matrix.IntMatrix;
import org.mklab.nfc.scalar.DoubleComplexNumber;


/**
 * 複素対角行列から実ブロック対角行列を求めるクラスです。
 * 
 * <p>Complex diagonal form to real diagonal form
 * 
 * @author koga
 * @version $Revision: 1.20 $
 */
public class Cdf2rdf {

  /**
   * 複素対角行列を実ブロック対角行列に変換します。
   * 
   * <p>与えられた複素対角行列 <code>Dc</code> の対角成分について、複素共役対は離れずに並んでいて、行列 <code>Vc</code> には、固有値に対応する固有ベクトルが含まれていなければなりません。
   * 
   * @param Vc 固有ベクトルからなる行列
   * @param Dc 固有値が対角に並ぶ対角行列
   * @return 実ブロック対角行列 (real diagonal form)
   */
  public static List<DoubleMatrix> cdf2rdf(DoubleComplexMatrix Vc, DoubleComplexMatrix Dc) {
    final DoubleComplexNumber j = new DoubleComplexNumber(0,1);

    final DoubleComplexMatrix jj = j.createGrid(new DoubleComplexNumber[] {j.createUnit(), j.createUnit()}).appendDown(j.createGrid(new DoubleComplexNumber[] {j, j.unaryMinus()}));

    final DoubleComplexMatrix T = jj.createUnit(Dc.getRowSize());

    IntMatrix idx = Dc.vectorToDiagonal().getImaginaryPart().transpose().compareElementWise(".!=", 0).find(); //$NON-NLS-1$
    final int n = idx.length();
    idx = idx.getSubVector(1, n, 2);

    for (int k = 1; k <= n; k++) {
      int i = idx.getIntElement(k);
      T.setSubMatrix(i, i + 1, i, i + 1, jj);
    }

    final DoubleMatrix Vr = Vc.divide(T).getRealPart();
    final DoubleMatrix Dr = T.multiply(Dc).divide(T).getRealPart();
    return new ArrayList<>(Arrays.asList(new DoubleMatrix[] {Vr, Dr}));
  }

}