/* AUTO-GENERATED */
package jsci.maths.matrices;

import jsci.maths.ArrayMath;
import jsci.maths.Complex;
import jsci.maths.ComplexMapping;
import jsci.maths.DimensionException;
import jsci.maths.LinearMath;
import jsci.maths.MaximumIterationsExceededException;
import jsci.maths.vectors.AbstractComplexVector;
import jsci.maths.vectors.ComplexVector;

/**
* The ComplexTridiagonalMatrix class provides an object for encapsulating tridiagonal matrices containing complex numbers.
* Uses compressed diagonal storage.
* @version 2.2
* @author Mark Hale
*/
public class ComplexTridiagonalMatrix extends AbstractComplexSquareMatrix implements TridiagonalMatrix {
        /**
        * Tridiagonal data.
        */
        protected final double ldiagRe[],ldiagIm[];
        protected final double diagRe[],diagIm[];
        protected final double udiagRe[],udiagIm[];
        /**
        * Constructs an empty matrix.
        * @param size the number of rows/columns
        */
        public ComplexTridiagonalMatrix(final int size) {
                super(size);
                ldiagRe=new double[size];
                ldiagIm=new double[size];
                diagRe=new double[size];
                diagIm=new double[size];
                udiagRe=new double[size];
                udiagIm=new double[size];
        }
        /**
        * Constructs a matrix from an array.
        * Any non-tridiagonal elements in the array are ignored.
        * @param array an assigned value
        * @exception MatrixDimensionException If the array is not square.
        */
        public ComplexTridiagonalMatrix(final Complex array[][]) {
                this(array.length);
                if(!ArrayMath.isSquare(array))
                        throw new MatrixDimensionException("Array is not square.");
                diagRe[0]=array[0][0].real();
                diagIm[0]=array[0][0].imag();
                udiagRe[0]=array[0][1].real();
                udiagIm[0]=array[0][1].imag();
                int i=1;
                for(;i=0 && i=0 && j=0 && i=0 && j=0 && i=0 && j=0 && i=0 && j=0 && i=0 && jinfinity-norm.
        * @author Taber Smith
        */
        public double infNorm() {
                double result = Math.sqrt((diagRe[0]*diagRe[0] + diagIm[0]*diagIm[0])) + Math.sqrt((udiagRe[0]*udiagRe[0] + udiagIm[0]*udiagIm[0]));
                double tmpResult;
                int i=1;
                for(;iresult)
                                result=tmpResult;
                }
                tmpResult = Math.sqrt((ldiagRe[i]*ldiagRe[i] + ldiagIm[i]*ldiagIm[i])) + Math.sqrt((diagRe[i]*diagRe[i] + diagIm[i]*diagIm[i]));
                if(tmpResult>result)
                        result=tmpResult;
                return result;
        }
        /**
        * Returns the Frobenius (l2) norm.
        * @author Taber Smith
        */
        public double frobeniusNorm() {
                double result=diagRe[0]*diagRe[0]+diagIm[0]*diagIm[0]+
                        udiagRe[0]*udiagRe[0]+udiagIm[0]*udiagIm[0];
                int i=1;
                for(;i3) {
                                arrayRe[1][0]=(ldiagRe[1]*m.diagRe[0] - ldiagIm[1]*m.diagIm[0])+(diagRe[1]*m.ldiagRe[1] - diagIm[1]*m.ldiagIm[1]);
                                arrayIm[1][0]=(ldiagIm[1]*m.diagRe[0] + ldiagRe[1]*m.diagIm[0])+(diagIm[1]*m.ldiagRe[1] + diagRe[1]*m.ldiagIm[1]);
                                arrayRe[1][1]=(ldiagRe[1]*m.udiagRe[0] - ldiagIm[1]*m.udiagIm[0])+(diagRe[1]*m.diagRe[1] - diagIm[1]*m.diagIm[1])+(udiagRe[1]*m.ldiagRe[2] - udiagIm[1]*m.ldiagIm[2]);
                                arrayIm[1][1]=(ldiagIm[1]*m.udiagRe[0] + ldiagRe[1]*m.udiagIm[0])+(diagIm[1]*m.diagRe[1] + diagRe[1]*m.diagIm[1])+(udiagIm[1]*m.ldiagRe[2] + udiagRe[1]*m.ldiagIm[2]);
                                arrayRe[1][2]=(diagRe[1]*m.udiagRe[1] - diagIm[1]*m.udiagIm[1])+(udiagRe[1]*m.diagRe[2] - udiagIm[1]*m.diagIm[2]);
                                arrayIm[1][2]=(diagIm[1]*m.udiagRe[1] + diagRe[1]*m.udiagIm[1])+(udiagIm[1]*m.diagRe[2] + udiagRe[1]*m.diagIm[2]);
                                arrayRe[1][3]=(udiagRe[1]*m.udiagRe[2] - udiagIm[1]*m.udiagIm[2]);
                                arrayIm[1][3]=(udiagIm[1]*m.udiagRe[2] + udiagRe[1]*m.udiagIm[2]);
                        }
                        if(mRow==3) {
                                arrayRe[1][0]=(ldiagRe[1]*m.diagRe[0] - ldiagIm[1]*m.diagIm[0])+(diagRe[1]*m.ldiagRe[1] - diagIm[1]*m.ldiagIm[1]);
                                arrayIm[1][0]=(ldiagIm[1]*m.diagRe[0] + ldiagRe[1]*m.diagIm[0])+(diagIm[1]*m.ldiagRe[1] + diagRe[1]*m.ldiagIm[1]);
                                arrayRe[1][1]=(ldiagRe[1]*m.udiagRe[0] - ldiagIm[1]*m.udiagIm[0])+(diagRe[1]*m.diagRe[1] - diagIm[1]*m.diagIm[1])+(udiagRe[1]*m.ldiagRe[2] - udiagIm[1]*m.ldiagIm[2]);
                                arrayIm[1][1]=(ldiagIm[1]*m.udiagRe[0] + ldiagRe[1]*m.udiagIm[0])+(diagIm[1]*m.diagRe[1] + diagRe[1]*m.diagIm[1])+(udiagIm[1]*m.ldiagRe[2] + udiagRe[1]*m.ldiagIm[2]);
                                arrayRe[1][2]=(diagRe[1]*m.udiagRe[1] - diagIm[1]*m.udiagIm[1])+(udiagRe[1]*m.diagRe[2] - udiagIm[1]*m.diagIm[2]);
                                arrayIm[1][2]=(diagIm[1]*m.udiagRe[1] + diagRe[1]*m.udiagIm[1])+(udiagIm[1]*m.diagRe[2] + udiagRe[1]*m.diagIm[2]);
                        } else if(mRow>4) {
                                for(int i=2;i3) {
                                arrayRe[mRow-2][mRow-4]=(ldiagRe[mRow-2]*m.ldiagRe[mRow-3] - ldiagIm[mRow-2]*m.ldiagIm[mRow-3]);
                                arrayIm[mRow-2][mRow-4]=(ldiagIm[mRow-2]*m.ldiagRe[mRow-3] + ldiagRe[mRow-2]*m.ldiagIm[mRow-3]);
                                arrayRe[mRow-2][mRow-3]=(ldiagRe[mRow-2]*m.diagRe[mRow-3] - ldiagIm[mRow-2]*m.diagIm[mRow-3])+(diagRe[mRow-2]*m.ldiagRe[mRow-2] - diagIm[mRow-2]*m.ldiagIm[mRow-2]);
                                arrayIm[mRow-2][mRow-3]=(ldiagIm[mRow-2]*m.diagRe[mRow-3] + ldiagRe[mRow-2]*m.diagIm[mRow-3])+(diagIm[mRow-2]*m.ldiagRe[mRow-2] + diagRe[mRow-2]*m.ldiagIm[mRow-2]);
                                arrayRe[mRow-2][mRow-2]=(ldiagRe[mRow-2]*m.udiagRe[mRow-3] - ldiagIm[mRow-2]*m.udiagIm[mRow-3])+(diagRe[mRow-2]*m.diagRe[mRow-2] - diagIm[mRow-2]*m.diagIm[mRow-2])+(udiagRe[mRow-2]*m.ldiagRe[mRow-1] - udiagIm[mRow-2]*m.ldiagIm[mRow-1]);
                                arrayIm[mRow-2][mRow-2]=(ldiagIm[mRow-2]*m.udiagRe[mRow-3] + ldiagRe[mRow-2]*m.udiagIm[mRow-3])+(diagIm[mRow-2]*m.diagRe[mRow-2] + diagRe[mRow-2]*m.diagIm[mRow-2])+(udiagIm[mRow-2]*m.ldiagRe[mRow-1] + udiagRe[mRow-2]*m.ldiagIm[mRow-1]);
                                arrayRe[mRow-2][mRow-1]=(diagRe[mRow-2]*m.udiagRe[mRow-2] - diagIm[mRow-2]*m.udiagIm[mRow-2])+(udiagRe[mRow-2]*m.diagRe[mRow-1] - udiagIm[mRow-2]*m.diagIm[mRow-1]);
                                arrayIm[mRow-2][mRow-1]=(diagIm[mRow-2]*m.udiagRe[mRow-2] + diagRe[mRow-2]*m.udiagIm[mRow-2])+(udiagIm[mRow-2]*m.diagRe[mRow-1] + udiagRe[mRow-2]*m.diagIm[mRow-1]);
                        }
                        mRow--;
                        arrayRe[mRow][mRow-2]=(ldiagRe[mRow]*m.ldiagRe[mRow-1] - ldiagIm[mRow]*m.ldiagIm[mRow-1]);
                        arrayIm[mRow][mRow-2]=(ldiagIm[mRow]*m.ldiagRe[mRow-1] + ldiagRe[mRow]*m.ldiagIm[mRow-1]);
                        arrayRe[mRow][mRow-1]=(ldiagRe[mRow]*m.diagRe[mRow-1] - ldiagIm[mRow]*m.diagIm[mRow-1])+(diagRe[mRow]*m.ldiagRe[mRow] - diagIm[mRow]*m.ldiagIm[mRow]);
                        arrayIm[mRow][mRow-1]=(ldiagIm[mRow]*m.diagRe[mRow-1] + ldiagRe[mRow]*m.diagIm[mRow-1])+(diagIm[mRow]*m.ldiagRe[mRow] + diagRe[mRow]*m.ldiagIm[mRow]);
                        arrayRe[mRow][mRow]=(ldiagRe[mRow]*m.udiagRe[mRow-1] - ldiagIm[mRow]*m.udiagIm[mRow-1])+(diagRe[mRow]*m.diagRe[mRow] - diagIm[mRow]*m.diagIm[mRow]);
                        arrayIm[mRow][mRow]=(ldiagIm[mRow]*m.udiagRe[mRow-1] + ldiagRe[mRow]*m.udiagIm[mRow-1])+(diagIm[mRow]*m.diagRe[mRow] + diagRe[mRow]*m.diagIm[mRow]);
                        return new ComplexSquareMatrix(arrayRe,arrayIm);
                } else
                        throw new MatrixDimensionException("Incompatible matrices.");
        }
        private ComplexSquareMatrix multiplyTridiagonal(final AbstractComplexSquareMatrix m) {
                int mRow=numRows;
                if(numCols==m.rows()) {
                        final double arrayRe[][]=new double[mRow][mRow];
                        final double arrayIm[][]=new double[mRow][mRow];
                        Complex elem1,elem2,elem3;
                        elem1=m.getElement(0,0);elem2=m.getElement(1,0);
                        arrayRe[0][0]=(diagRe[0]*elem1.real() - diagIm[0]*elem1.imag())+(udiagRe[0]*elem2.real() - udiagIm[0]*elem2.imag());
                        arrayIm[0][0]=(diagIm[0]*elem1.real() + diagRe[0]*elem1.imag())+(udiagIm[0]*elem2.real() + udiagRe[0]*elem2.imag());
                        elem1=m.getElement(0,1);elem2=m.getElement(1,1);
                        arrayRe[0][1]=(diagRe[0]*elem1.real() - diagIm[0]*elem1.imag())+(udiagRe[0]*elem2.real() - udiagIm[0]*elem2.imag());
                        arrayIm[0][1]=(diagIm[0]*elem1.real() + diagRe[0]*elem1.imag())+(udiagIm[0]*elem2.real() + udiagRe[0]*elem2.imag());
                        elem1=m.getElement(1,2);
                        arrayRe[0][2]=(udiagRe[0]*elem1.real() - udiagIm[0]*elem1.imag());
                        arrayIm[0][2]=(udiagIm[0]*elem1.real() + udiagRe[0]*elem1.imag());
                        if(mRow>3) {
                                elem1=m.getElement(0,0);elem2=m.getElement(1,0);
                                arrayRe[1][0]=(ldiagRe[1]*elem1.real() - ldiagIm[1]*elem1.imag())+(diagRe[1]*elem2.real() - diagIm[1]*elem2.imag());
                                arrayIm[1][0]=(ldiagIm[1]*elem1.real() + ldiagRe[1]*elem1.imag())+(diagIm[1]*elem2.real() + diagRe[1]*elem2.imag());
                                elem1=m.getElement(0,1);elem2=m.getElement(1,1);elem3=m.getElement(2,1);
                                arrayRe[1][1]=(ldiagRe[1]*elem1.real() - ldiagIm[1]*elem1.imag())+(diagRe[1]*elem2.real() - diagIm[1]*elem2.imag())+(udiagRe[1]*elem3.real() - udiagIm[1]*elem3.imag());
                                arrayIm[1][1]=(ldiagIm[1]*elem1.real() + ldiagRe[1]*elem1.imag())+(diagIm[1]*elem2.real() + diagRe[1]*elem2.imag())+(udiagIm[1]*elem3.real() + udiagRe[1]*elem3.imag());
                                elem1=m.getElement(1,2);elem2=m.getElement(2,2);
                                arrayRe[1][2]=(diagRe[1]*elem1.real() - diagIm[1]*elem1.imag())+(udiagRe[1]*elem2.real() - udiagIm[1]*elem2.imag());
                                arrayIm[1][2]=(diagIm[1]*elem1.real() + diagRe[1]*elem1.imag())+(udiagIm[1]*elem2.real() + udiagRe[1]*elem2.imag());
                                elem1=m.getElement(2,3);
                                arrayRe[1][3]=(udiagRe[1]*elem1.real() - udiagIm[1]*elem1.imag());
                                arrayIm[1][3]=(udiagIm[1]*elem1.real() + udiagRe[1]*elem1.imag());
                        }
                        if(mRow==3) {
                                elem1=m.getElement(0,0);elem2=m.getElement(1,0);
                                arrayRe[1][0]=(ldiagRe[1]*elem1.real() - ldiagIm[1]*elem1.imag())+(diagRe[1]*elem2.real() - diagIm[1]*elem2.imag());
                                arrayIm[1][0]=(ldiagIm[1]*elem1.real() + ldiagRe[1]*elem1.imag())+(diagIm[1]*elem2.real() + diagRe[1]*elem2.imag());
                                elem1=m.getElement(0,1);elem2=m.getElement(1,1);elem3=m.getElement(2,1);
                                arrayRe[1][1]=(ldiagRe[1]*elem1.real() - ldiagIm[1]*elem1.imag())+(diagRe[1]*elem2.real() - diagIm[1]*elem2.imag())+(udiagRe[1]*elem3.real() - udiagIm[1]*elem3.imag());
                                arrayIm[1][1]=(ldiagIm[1]*elem1.real() + ldiagRe[1]*elem1.imag())+(diagIm[1]*elem2.real() + diagRe[1]*elem2.imag())+(udiagIm[1]*elem3.real() + udiagRe[1]*elem3.imag());
                                elem1=m.getElement(1,2);elem2=m.getElement(2,2);
                                arrayRe[1][2]=(diagRe[1]*elem1.real() - diagIm[1]*elem1.imag())+(udiagRe[1]*elem2.real() - udiagIm[1]*elem2.imag());
                                arrayIm[1][2]=(diagIm[1]*elem1.real() + diagRe[1]*elem1.imag())+(udiagIm[1]*elem2.real() + udiagRe[1]*elem2.imag());
                        } else if(mRow>4) {
                                for(int i=2;i3) {
                                elem1=m.getElement(mRow-3,mRow-4);
                                arrayRe[mRow-2][mRow-4]=(ldiagRe[mRow-2]*elem1.real() - ldiagIm[mRow-2]*elem1.imag());
                                arrayIm[mRow-2][mRow-4]=(ldiagIm[mRow-2]*elem1.real() + ldiagRe[mRow-2]*elem1.imag());
                                elem1=m.getElement(mRow-3,mRow-3);elem2=m.getElement(mRow-2,mRow-3);
                                arrayRe[mRow-2][mRow-3]=(ldiagRe[mRow-2]*elem1.real() - ldiagIm[mRow-2]*elem1.imag())+(diagRe[mRow-2]*elem2.real() - diagIm[mRow-2]*elem2.imag());
                                arrayIm[mRow-2][mRow-3]=(ldiagIm[mRow-2]*elem1.real() + ldiagRe[mRow-2]*elem1.imag())+(diagIm[mRow-2]*elem2.real() + diagRe[mRow-2]*elem2.imag());
                                elem1=m.getElement(mRow-3,mRow-2);elem2=m.getElement(mRow-2,mRow-2);elem3=m.getElement(mRow-1,mRow-2);
                                arrayRe[mRow-2][mRow-2]=(ldiagRe[mRow-2]*elem1.real() - ldiagIm[mRow-2]*elem1.imag())+(diagRe[mRow-2]*elem2.real() - diagIm[mRow-2]*elem2.imag())+(udiagRe[mRow-2]*elem3.real() - udiagIm[mRow-2]*elem3.imag());
                                arrayIm[mRow-2][mRow-2]=(ldiagIm[mRow-2]*elem1.real() + ldiagRe[mRow-2]*elem1.imag())+(diagIm[mRow-2]*elem2.real() + diagRe[mRow-2]*elem2.imag())+(udiagIm[mRow-2]*elem3.real() + udiagRe[mRow-2]*elem3.imag());
                                elem1=m.getElement(mRow-2,mRow-1);elem2=m.getElement(mRow-1,mRow-1);
                                arrayRe[mRow-2][mRow-1]=(diagRe[mRow-2]*elem1.real() - diagIm[mRow-2]*elem1.imag())+(udiagRe[mRow-2]*elem2.real() - udiagIm[mRow-2]*elem2.imag());
                                arrayIm[mRow-2][mRow-1]=(diagIm[mRow-2]*elem1.real() + diagRe[mRow-2]*elem1.imag())+(udiagIm[mRow-2]*elem2.real() + udiagRe[mRow-2]*elem2.imag());
                        }
                        mRow--;
                        elem1=m.getElement(mRow-1,mRow-2);
                        arrayRe[mRow][mRow-2]=(ldiagRe[mRow]*elem1.real() - ldiagIm[mRow]*elem1.imag());
                        arrayIm[mRow][mRow-2]=(ldiagIm[mRow]*elem1.real() + ldiagRe[mRow]*elem1.imag());
                        elem1=m.getElement(mRow-1,mRow-1);elem2=m.getElement(mRow,mRow-1);
                        arrayRe[mRow][mRow-1]=(ldiagRe[mRow]*elem1.real() - ldiagIm[mRow]*elem1.imag())+(diagRe[mRow]*elem2.real() - diagIm[mRow]*elem2.imag());
                        arrayIm[mRow][mRow-1]=(ldiagIm[mRow]*elem1.real() + ldiagRe[mRow]*elem1.imag())+(diagIm[mRow]*elem2.real() + diagRe[mRow]*elem2.imag());
                        elem1=m.getElement(mRow-1,mRow);elem2=m.getElement(mRow,mRow);
                        arrayRe[mRow][mRow]=(ldiagRe[mRow]*elem1.real() - ldiagIm[mRow]*elem1.imag())+(diagRe[mRow]*elem2.real() - diagIm[mRow]*elem2.imag());
                        arrayIm[mRow][mRow]=(ldiagIm[mRow]*elem1.real() + ldiagRe[mRow]*elem1.imag())+(diagIm[mRow]*elem2.real() + diagRe[mRow]*elem2.imag());
                        return new ComplexSquareMatrix(arrayRe,arrayIm);
                } else {
                        throw new MatrixDimensionException("Incompatible matrices.");
                }
        }

// HERMITIAN ADJOINT

        /**
        * Returns the hermitian adjoint of this matrix.
        * @return a complex tridiagonal matrix
        */
        public AbstractComplexMatrix hermitianAdjoint() {
                int mRow=numRows;
                final ComplexTridiagonalMatrix ans=new ComplexTridiagonalMatrix(mRow);
                System.arraycopy(ldiagRe,1,ans.udiagRe,0,ldiagRe.length-1);
                System.arraycopy(diagRe,0,ans.diagRe,0,diagRe.length);
                System.arraycopy(udiagRe,0,ans.ldiagRe,1,udiagRe.length-1);
                ans.diagIm[0]=-diagIm[0];
                ans.ldiagIm[1]=-udiagIm[0];
                mRow--;
                for(int i=1;i 

Ads help maintain this website.