zoukankan      html  css  js  c++  java
  • 仿射变换的一个练习题!

    问题:已知坐标A(0,2,sqrt(2))、B(1,1,sqrt(2))、C(2,0,sqrt(2))连接成直线,希望围绕其在XOY平面内投影旋转90度,求新的坐标点A'B’C'。

    解决方案:仿射变换(参考书籍《交互式计算机图形学——基于OpenGL的自顶向下方法》154——163)

    (1)    (2)

    这里出现两次错误,首先是T-1表示的是T(-AXOY),即将A的投影点AXOY移到原点,视AXOY为中心和不动点。第二处T中第二行第三列不是2,应该是0,这个中间结果表示正确。

    中间结果:

     实现函数:

    变换函数
     1 public static IPolyline Polyline_3D_2D(IPolyline m_Polyline, double m_BaseHeight, double zFactor)
     2         {
     3             IPolyline m_2DPolyline = new PolylineClass();
     4             IPointCollection m_2DPointCollection = m_2DPolyline as IPointCollection;
     5 
     6             IPointCollection m3dPtCol = m_Polyline as IPointCollection;
     7             Matrix m_P_Matrix = new Matrix(4, m3dPtCol.PointCount);
     8             for (int i = 0; i < m3dPtCol.PointCount; i++)
     9             {
    10                 IPoint pt = m3dPtCol.get_Point(i);
    11                 m_P_Matrix[0, i] = pt.X;
    12                 m_P_Matrix[1, i] = pt.Y;
    13                 m_P_Matrix[2, i] = (pt.Z - m_BaseHeight) * zFactor;
    14                 m_P_Matrix[3, i] = 1;
    15             }
    16             Matrix m_U_Matrix = new Matrix(4, 1);//旋转方向向量U
    17             m_U_Matrix[0, 0] = m3dPtCol.get_Point(m3dPtCol.PointCount - 1).X - m3dPtCol.get_Point(0).X;
    18             m_U_Matrix[1, 0] = m3dPtCol.get_Point(m3dPtCol.PointCount - 1).Y - m3dPtCol.get_Point(0).Y;
    19             m_U_Matrix[2, 0] = 0;
    20             m_U_Matrix[3, 0] = 0;
    21             Matrix m_V_Matrix = new Matrix(4, 1);//旋转方向向量U的基V
    22             double d2 = m_U_Matrix[0, 0] * m_U_Matrix[0, 0] + m_U_Matrix[1, 0] * m_U_Matrix[1, 0] + m_U_Matrix[2, 0] * m_U_Matrix[2, 0] + m_U_Matrix[3, 0] * m_U_Matrix[3, 0];
    23             m_V_Matrix[0, 0] = m_U_Matrix[0, 0] / Math.Sqrt(d2);
    24             m_V_Matrix[1, 0] = m_U_Matrix[1, 0] / Math.Sqrt(d2);
    25             m_V_Matrix[2, 0] = m_U_Matrix[2, 0] / Math.Sqrt(d2);
    26             m_V_Matrix[3, 0] = m_U_Matrix[3, 0] / Math.Sqrt(d2);
    27 
    28             Matrix m_T_matrix = new Matrix(4);//平移矩阵T(-pf)
    29             m_T_matrix.MakeUnitMatrix(4);
    30             m_T_matrix[0, 3] = -m_P_Matrix[0, 0];
    31             m_T_matrix[1, 3] = -m_P_Matrix[1, 0];
    32             m_T_matrix[2, 3] = 0;
    33 
    34             double dd = m_V_Matrix[2, 0] * m_V_Matrix[2, 0] + m_V_Matrix[1, 0] * m_V_Matrix[1, 0];
    35             Matrix m_Rx_matrix = new Matrix(4);//x旋转
    36             m_Rx_matrix.MakeUnitMatrix(4);
    37             m_Rx_matrix[1, 1] = m_V_Matrix[2, 0] / Math.Sqrt(dd);
    38             m_Rx_matrix[1, 2] = -m_V_Matrix[1, 0] / Math.Sqrt(dd);
    39             m_Rx_matrix[2, 1] = m_V_Matrix[1, 0] / Math.Sqrt(dd);
    40             m_Rx_matrix[2, 2] = m_V_Matrix[2, 0] / Math.Sqrt(dd);
    41 
    42             Matrix m_Ry_matrix = new Matrix(4);//y旋转
    43             m_Ry_matrix.MakeUnitMatrix(4);
    44             m_Ry_matrix[0, 0] = Math.Sqrt(dd);
    45             m_Ry_matrix[0, 2] = -m_V_Matrix[0, 0];
    46             m_Ry_matrix[2, 0] = m_V_Matrix[0, 0];
    47             m_Ry_matrix[2, 2] = Math.Sqrt(dd);
    48 
    49             Matrix m_Rz_matrix = new Matrix(4);//z旋转
    50             m_Rz_matrix.MakeUnitMatrix(4);
    51             m_Rz_matrix[0, 0] = Math.Cos(Math.PI / 2);
    52             m_Rz_matrix[0, 1] = -Math.Sin(Math.PI / 2);
    53             m_Rz_matrix[1, 0] = Math.Sin(Math.PI / 2);
    54             m_Rz_matrix[1, 1] = Math.Cos(Math.PI / 2);
    55 
    56             Matrix m_M_Matrix = new Matrix(4);//级联变换矩阵
    57             Matrix m_Tr_matrix = new Matrix(m_T_matrix);
    58             m_Tr_matrix.InvertGaussJordan();//平移矩阵的逆
    59             Matrix m_Rxr_matrix = new Matrix(m_Rx_matrix);
    60             m_Rxr_matrix.InvertGaussJordan();//x旋转的逆
    61             Matrix m_Ryr_matrix = new Matrix(m_Ry_matrix);
    62             m_Ryr_matrix.InvertGaussJordan();//y旋转的逆
    63             m_M_Matrix = m_Tr_matrix * m_Rxr_matrix * m_Ryr_matrix * m_Rz_matrix * m_Ry_matrix * m_Rx_matrix * m_T_matrix;
    64             Matrix m_Pnew_Matrix = new Matrix(4, m3dPtCol.PointCount);
    65             m_Pnew_Matrix = m_M_Matrix * m_P_Matrix;//实现旋转
    66 
    67             for (int k = 0; k < m_Pnew_Matrix.Columns; k++)
    68             {
    69                 IPoint pt3d = new PointClass();
    70 
    71                 pt3d.X = m_Pnew_Matrix[0, k];
    72                 pt3d.Y = m_Pnew_Matrix[1, k];
    73                 pt3d.Z = m_Pnew_Matrix[2, k];
    74                 m_2DPointCollection.AddPoint(pt3d, ref mis, ref mis);
    75             }
    76 
    77             return m_2DPolyline;
    78         }

    矩阵类:

    矩阵类
       1 using System;
       2 
       3 namespace CMathematics.MatrixAlgebra
       4 {
       5     /// <summary>
       6     /// C#数值计算算法编程
       7     /// 矩阵类,操作矩阵的了Matrix
       8     /// 矩阵的赋值是用一维数组,用行列控制
       9     /// </summary>
      10     public class Matrix : CMathematics.MatrixAlgebra.IMatrix
      11     {
      12         private int numColumns = 0;         //矩阵列数
      13         private int numRows = 0;            //矩阵行数
      14         private double eps = 0.0;           //缺省精度
      15         private double[] elements = null;   //矩阵数据缓冲区
      16 
      17         /// <summary>
      18         /// 属性:矩阵列数
      19         /// </summary>
      20         public int Columns
      21         {
      22             get
      23             {
      24                 return numColumns;
      25             }
      26         }
      27 
      28         /// <summary>
      29         ///属性:矩阵行数
      30         /// </summary>
      31         public int Rows
      32         {
      33             get
      34             {
      35                 return numRows;
      36             }
      37         }
      38 
      39         /// <summary>
      40         /// 索引器:访问矩阵元素
      41         /// </summary>
      42         /// <param name="row">元素的行</param>
      43         /// <param name="col">元素的列</param>
      44         /// <returns></returns>
      45         public double this[int row, int col]
      46         {
      47             get
      48             {
      49                 return elements[col + row * numColumns];
      50             }
      51             set
      52             {
      53                 elements[col + row * numColumns] = value;
      54             }
      55         }
      56 
      57         /// <summary>
      58         /// 属性:Eps,矩阵运算的精度
      59         /// </summary>
      60         public double Eps
      61         {
      62             get
      63             {
      64                 return eps;
      65             }
      66             set
      67             {
      68                 eps = value;
      69             }
      70         }
      71         /// <summary>
      72         /// 基本构造函数
      73         /// </summary>
      74 
      75         public Matrix()
      76         {
      77             numColumns = 1;
      78             numRows = 1;
      79             Init(numRows, numColumns);
      80         }
      81 
      82         /// <summary>
      83         /// 指定行列构造函数
      84         /// </summary>
      85         /// <param name="nRows">指定的矩阵行数</param>
      86         /// <param name="nCols">指定的矩阵列数</param>
      87         public Matrix(int nRows, int nCols)
      88         {
      89             numRows = nRows;
      90             numColumns = nCols;
      91             Init(numRows, numColumns);
      92         }
      93 
      94         /// <summary>
      95         /// 指定值构造函数
      96         /// </summary>
      97         /// <param name="nRows">-指定的矩阵行数</param>
      98         /// <param name="nCols">指定的矩阵列数</param>
      99         /// <param name="value">一维数组,长度为nRows*nCols,存储矩阵各元素的值</param>
     100         public Matrix(int nRows, int nCols, double[] value)
     101         {
     102             numRows = nRows;
     103             numColumns = nCols;
     104             Init(numRows, numColumns);
     105             SetData(value);
     106         }
     107 
     108         /// <summary>
     109         /// 方阵构造函数
     110         /// </summary>
     111         /// <param name="nSize">方阵行列数</param>
     112         public Matrix(int nSize)
     113         {
     114             numRows = nSize;
     115             numColumns = nSize;
     116             Init(nSize, nSize);
     117         }
     118         /// <summary>
     119         /// 方阵构造函数
     120         /// </summary>
     121         /// <param name="nSize">方阵行列数</param>
     122         /// <param name="value">维数组,长度为nRows*nRows,存储方阵各元素的值</param>
     123         public Matrix(int nSize, double[] value)
     124         {
     125             numRows = nSize;
     126             numColumns = nSize;
     127             Init(nSize, nSize);
     128             SetData(value);
     129         }
     130 
     131         /// <summary>
     132         /// 拷贝构造函数
     133         /// </summary>
     134         /// <param name="other">源矩阵</param>
     135         public Matrix(Matrix other)
     136         {
     137             numColumns = other.GetNumColumns();
     138             numRows = other.GetNumRows();
     139             Init(numRows, numColumns);
     140             SetData(other.elements);
     141         }
     142         /// <summary>
     143         /// 初始化函数
     144         /// </summary>
     145         /// <param name="nRows">指定的矩阵行数</param>
     146         /// <param name="nCols">指定的矩阵列数</param>
     147         /// <returns>bool,成功返回true,否则返回false</returns>
     148         public bool Init(int nRows, int nCols)
     149         {
     150             numRows = nRows;
     151             numColumns = nCols;
     152             int nSize = nCols * nRows;
     153             if (nSize < 0)
     154                 return false;
     155             //分配内存
     156             elements = new double[nSize];
     157 
     158             return true;
     159         }
     160 
     161         /// <summary>
     162         /// 设置矩阵运算的精度
     163         /// </summary>
     164         /// <param name="newEps">新的精度值</param>
     165         public void SetEps(double newEps)
     166         {
     167             eps = newEps;
     168         }
     169 
     170         /// <summary>
     171         /// 取矩阵的精度值
     172         /// </summary>
     173         /// <returns>double型,矩阵的精度值</returns>
     174         public double GetEps()
     175         {
     176             return eps;
     177         }
     178         /// <summary>
     179         /// 重载+运算符
     180         /// </summary>
     181         /// <param name="m1"></param>
     182         /// <param name="m2"></param>
     183         /// <returns>Matrix对象</returns>
     184         public static Matrix operator +(Matrix m1, Matrix m2)
     185         {
     186             return m1.Add(m2);
     187 
     188         }
     189         /// <summary>
     190         /// 重载-运算符
     191         /// </summary>
     192         /// <param name="m1"></param>
     193         /// <param name="m2"></param>
     194         /// <returns>Matrix对象</returns>
     195         public static Matrix operator -(Matrix m1, Matrix m2)
     196         {
     197             return m1.Subtract(m2);
     198         }
     199         /// <summary>
     200         /// 重载*运算符
     201         /// </summary>
     202         /// <param name="m1"></param>
     203         /// <param name="m2"></param>
     204         /// <returns>Matrix对象</returns>
     205         public static Matrix operator *(Matrix m1, Matrix m2)
     206         {
     207             return m1.Multiply(m2);
     208         }
     209         /// <summary>
     210         /// 重载double[]运算符
     211         /// </summary>
     212         /// <param name="m"></param>
     213         /// <returns>double[]对象</returns>
     214         public static implicit operator double[](Matrix m)
     215         {
     216             return m.elements;
     217         }
     218         /// <summary>
     219         /// 将方阵初始化为单位矩阵
     220         /// </summary>
     221         /// <param name="nSize">方阵行列数</param>
     222         /// <returns>bool型,初始化是否成功</returns>
     223         public bool MakeUnitMatrix(int nSize)
     224         {
     225             if (!Init(nSize, nSize))
     226                 return false;
     227             for (int i = 0; i < nSize; ++i)
     228                 for (int j = 0; j < nSize; ++j)
     229                     if (i == j)
     230                         SetElement(i, j, 1);
     231             return true;
     232         }
     233         /// <summary>
     234         /// 将矩阵各元素的值转化为字符型,元素之间的分隔符为",",行与行之间有回车换行符
     235         /// </summary>
     236         /// <returns>string型,转换得到的字符串</returns>
     237         public override string ToString()
     238         {
     239             return ToString(",", true);
     240         }
     241         /// <summary>
     242         /// 将矩阵各元素的值转化为字符串
     243         /// </summary>
     244         /// <param name="sDelim">元素之间的分隔符</param>
     245         /// <param name="bLineBreak">行与行之间是否有回车换行符</param>
     246         /// <returns>string型,转换得到的字符串</returns>
     247         public string ToString(string sDelim, bool bLineBreak)
     248         {
     249             string s = "";
     250 
     251             for (int i = 0; i < numRows; ++i)
     252             {
     253                 for (int j = 0; j < numColumns; ++j)
     254                 {
     255                     string ss = GetElement(i, j).ToString("F8");
     256                     s += ss;
     257 
     258                     if (bLineBreak)
     259                     {
     260                         if (j != numColumns - 1)
     261                             s += sDelim;
     262                     }
     263                     else
     264                     {
     265                         if (i != numRows - 1 || j != numColumns - 1)
     266                             s += sDelim;
     267                     }
     268                 }
     269                 if (bLineBreak)
     270                     if (i != numRows - 1)
     271                         s += "\r\n";
     272             }
     273             return s;
     274         }
     275         /// <summary>
     276         /// 将矩阵指定行中各元素的值转化为字符串
     277         /// </summary>
     278         /// <param name="nRow">指定的矩阵行,nRows=0表示第一行</param>
     279         /// <param name="sDelim">元素之间的分隔符</param>
     280         /// <returns>string型,转换得到的字符串</returns>
     281         public string ToStringRow(int nRow, string sDelim)
     282         {
     283             string s = "";
     284             if (nRow >= numRows)
     285                 return s;
     286 
     287             for (int j = 0; j < numColumns; ++j)
     288             {
     289                 string ss = GetElement(nRow, j).ToString("F8");
     290                 s += ss;
     291                 if (j != numColumns - 1)
     292                     s += sDelim;
     293             }
     294             return s;
     295         }
     296         /// <summary>
     297         /// 将矩阵指定列中各元素的值转化为字符串
     298         /// </summary>
     299         /// <param name="nCol">指定的矩阵列,nCol=0表示第一列</param>
     300         /// <param name="sDelim">元素之间的分隔符</param>
     301         /// <returns>string型,转换得到的字符串</returns>
     302         public string ToStringCol(int nCol, string sDelim)
     303         {
     304             string s = "";
     305 
     306             if (nCol >= numColumns)
     307                 return s;
     308 
     309             for (int i = 0; i < numRows; ++i)
     310             {
     311                 string ss = GetElement(i, nCol).ToString("F8");
     312                 s += ss;
     313                 if (i != numRows - 1)
     314                     s += sDelim;
     315             }
     316             return s;
     317         }
     318         /// <summary>
     319         /// 设置矩阵各元素的值
     320         /// </summary>
     321         /// <param name="value">一维数组,长度numColumns*numRows,存储矩阵各元素的值</param>
     322         public void SetData(double[] value)
     323         {
     324             elements = (double[])value.Clone();
     325         }
     326         /// <summary>
     327         /// 设置指定元素的值
     328         /// </summary>
     329         /// <param name="nRow">元素的行</param>
     330         /// <param name="nCol">元素的列</param>
     331         /// <param name="value">指定元素的值</param>
     332         /// <returns>bool型,说明设置是否成功</returns>
     333         public bool SetElement(int nRow, int nCol, double value)
     334         {
     335             if (nCol < 0 || nCol >= numColumns || nRow < 0 || nRow >= numRows)
     336                 return false;
     337 
     338             elements[nCol + nRow * numColumns] = value;
     339 
     340             return true;
     341         }
     342 
     343         /// <summary>
     344         /// 获取指定元素的值
     345         /// </summary>
     346         /// <param name="nRow">元素的行</param>
     347         /// <param name="nCol">元素的列</param>
     348         /// <returns>double型,指定元素的值</returns>
     349         public double GetElement(int nRow, int nCol)
     350         {
     351             return elements[nCol + nRow * numColumns];
     352         }
     353 
     354         /// <summary>
     355         /// 获取矩阵的列数
     356         /// </summary>
     357         /// <returns>int型,矩阵的列数</returns>
     358         public int GetNumColumns()
     359         {
     360             return numColumns;
     361         }
     362         /// <summary>
     363         /// 获取矩阵的行数
     364         /// </summary>
     365         /// <returns>int型,矩阵的行数</returns>
     366         public int GetNumRows()
     367         {
     368             return numRows;
     369         }
     370         /// <summary>
     371         /// 获取矩阵的数据
     372         /// </summary>
     373         /// <returns>double型数组,指向矩阵各元素的数据缓冲区</returns>
     374         public double[] GetData()
     375         {
     376             return elements;
     377         }
     378         /// <summary>
     379         /// 获取指定行的向量
     380         /// </summary>
     381         /// <param name="nRow">向量所在的行</param>
     382         /// <param name="pVector">指向向量中各元素的缓冲区</param>
     383         /// <returns>int型,向量中元素的个数,即矩阵的列数</returns>
     384         public int GetRowVector(int nRow, double[] pVector)
     385         {
     386             for (int j = 0; j < numColumns; ++j)
     387                 pVector[j] = GetElement(nRow, j);
     388 
     389             return numColumns;
     390         }
     391 
     392         /// <summary>
     393         /// 获取指定列的向量
     394         /// </summary>
     395         /// <param name="nCol">向量所在的列</param>
     396         /// <param name="pVector">指向向量中各元素的缓冲区</param>
     397         /// <returns>int型,向量中元素的个数,即矩阵的行数</returns>
     398         public int GetColVector(int nCol, double[] pVector)
     399         {
     400             for (int i = 0; i < numRows; ++i)
     401                 pVector[i] = GetElement(i, nCol);
     402 
     403             return numRows;
     404         }
     405         /// <summary>
     406         /// 给矩阵赋值
     407         /// </summary>
     408         /// <param name="other">用于给矩阵赋值的源矩阵</param>
     409         /// <returns>Matrix型,矩阵与other相等</returns>
     410         public Matrix SetValue(Matrix other)
     411         {
     412             if (other != this)
     413             {
     414                 Init(other.GetNumRows(), other.GetNumColumns());
     415                 SetData(other.elements);
     416             }
     417 
     418             return this;
     419         }
     420         /// <summary>
     421         /// 判断矩阵是否相等
     422         /// </summary>
     423         /// <param name="other">用于比较的矩阵</param>
     424         /// <returns>bool型,两个矩阵相等则为true,否则为false</returns>
     425         public override bool Equals(object other)
     426         {
     427             Matrix matrix = other as Matrix;
     428             if (matrix == null)
     429                 return false;
     430 
     431             //首先检查行列数是否相等
     432             if (numColumns != matrix.GetNumColumns() || numRows != matrix.GetNumRows())
     433                 return false;
     434 
     435             for (int i = 0; i < numRows; ++i)
     436             {
     437                 for (int j = 0; j < numColumns; ++j)
     438                 {
     439                     if (Math.Abs(GetElement(i, j) - matrix.GetElement(i, j)) > eps)
     440                         return false;
     441                 }
     442             }
     443             return true;
     444 
     445 
     446 
     447         }
     448 
     449         /// <summary>
     450         /// 因为重写了Equals,因此必须重写GetHashCode
     451         /// </summary>
     452         /// <returns>int型返回复数对象散列码</returns>
     453         public override int GetHashCode()
     454         {
     455             double sum = 0;
     456             for (int i = 0; i < numRows; ++i)
     457             {
     458                 for (int j = 0; j < numColumns; ++j)
     459                 {
     460                     sum += Math.Abs(GetElement(i, j));
     461                 }
     462             }
     463             return (int)Math.Sqrt(sum);
     464 
     465         }
     466         /// <summary>
     467         /// 实现矩阵的加法 
     468         /// </summary>
     469         /// <param name="other">other--与指定矩阵相加的矩阵</param>
     470         /// <returns>Matrix型,指定矩阵与other相加之和</returns>
     471         public Matrix Add(Matrix other)
     472         {
     473             //首先检查行列数是否相等
     474             if (numColumns != other.GetNumColumns() || numRows != other.GetNumRows())
     475                 throw new Exception("矩阵的行/列数不匹配。");
     476 
     477             //构造结果矩阵
     478             Matrix result = new Matrix(this);   //拷贝构造
     479 
     480             //矩阵加法
     481             for (int i = 0; i < numRows; ++i)
     482             {
     483                 for (int j = 0; j < numColumns; ++j)
     484                     result.SetElement(i, j, result.GetElement(i, j) + other.GetElement(i, j));
     485             }
     486             return result;
     487 
     488         }
     489         /// <summary>
     490         /// 实现矩阵的减法
     491         /// </summary>
     492         /// <param name="other">与指定矩阵相减的矩阵</param>
     493         /// <returns>Matrix型,指定矩阵与other相减之差</returns>
     494         public Matrix Subtract(Matrix other)
     495         {
     496             if (numColumns != other.GetNumColumns() || numRows != other.GetNumRows())
     497                 throw new Exception("矩阵的行/列数不匹配。");
     498 
     499             //构造结果矩阵
     500             Matrix result = new Matrix(this);  //拷贝构造
     501 
     502             //进行减法操作
     503             for (int i = 0; i < numRows; ++i)
     504             {
     505                 for (int j = 0; j < numColumns; ++j)
     506                     result.SetElement(i, j, result.GetElement(i, j) - other.GetElement(i, j));
     507             }
     508 
     509             return result;
     510         }
     511 
     512         /// <summary>
     513         /// 实现矩阵的数乘
     514         /// </summary>
     515         /// <param name="value">与指定矩阵相乘的实数</param>
     516         /// <returns>Matrix型,指定矩阵与value相乘之积</returns>
     517         public Matrix Multiply(double value)
     518         {
     519             //构造目标矩阵
     520             Matrix result = new Matrix(this);
     521 
     522             //进行数乘
     523             for (int i = 0; i < numRows; ++i)
     524             {
     525                 for (int j = 0; j < numColumns; ++j)
     526                     result.SetElement(i, j, result.GetElement(i, j) * value);
     527             }
     528             return result;
     529 
     530         }
     531         /// <summary>
     532         /// 矩阵的乘法
     533         /// </summary>
     534         /// <param name="other">与指定矩阵相乘的矩</param>
     535         /// <returns>Matrix型,指定矩阵与other相乘之积</returns>
     536         public Matrix Multiply(Matrix other)
     537         {
     538             //首先检查行列是否符合要求
     539             if (numColumns != other.GetNumRows())
     540                 throw new Exception("矩阵的行/列数不匹配。");
     541             //ruct the object we are going to return
     542             Matrix result = new Matrix(numRows, other.GetNumColumns());
     543             //矩阵乘法,即
     544             //
     545             //[A][B][C] [G][H]   [A*G+B*I+C*K][A*H+B*J+C*L]
     546             //[D][E][F]*[I][J] = [D*G+E*I+F*K][D*H+E*J+F*L]
     547             //          [K][L]
     548             double value;
     549             for (int i = 0; i < result.GetNumRows(); ++i)
     550             {
     551                 for (int j = 0; j < other.GetNumColumns(); ++j)
     552                 {
     553                     value = 0.0;
     554                     for (int k = 0; k < numColumns; ++k)
     555                     {
     556                         value += GetElement(i, k) * other.GetElement(k, j);
     557                     }
     558                     result.SetElement(i, j, value);
     559 
     560                 }
     561             }
     562             return result;
     563         }
     564 
     565         /// <summary>
     566         /// 复矩阵的乘法
     567         /// </summary>
     568         /// <param name="AR">左边复矩阵的实部矩阵</param>
     569         /// <param name="AI">左边复矩阵的虚部矩阵</param>
     570         /// <param name="BR">右边复矩阵的实部矩阵</param>
     571         /// <param name="BI">右边复矩阵的虚部矩阵</param>
     572         /// <param name="CR">乘积复矩阵的实部矩阵</param>
     573         /// <param name="CI">乘积复矩阵的虚部矩阵</param>
     574         /// <returns>bool型,复矩阵乘法是否成功</returns>
     575         public bool Multiply(Matrix AR, Matrix AI, Matrix BR, Matrix BI, Matrix CR, Matrix CI)
     576         {
     577             //首先检查行列数是否符合要求
     578             if (AR.GetNumColumns() != AI.GetNumColumns() || AR.GetNumRows() != AI.GetNumRows() || BR.GetNumColumns() != BI.GetNumColumns() || BR.GetNumRows() != BI.GetNumRows() || AR.GetNumColumns() != BR.GetNumRows())
     579                 return false;
     580 
     581             //构造乘积矩阵实部和虚部矩阵
     582             Matrix mtxCR = new Matrix(AR.GetNumRows(), BR.GetNumColumns());
     583             Matrix mtxCI = new Matrix(AR.GetNumRows(), BR.GetNumColumns());
     584             //复矩阵相乘
     585             for (int i = 0; i < AR.GetNumRows(); ++i)
     586             {
     587                 for (int j = 0; j < BR.GetNumColumns(); ++j)
     588                 {
     589                     double vr = 0;
     590                     double vi = 0;
     591                     for (int k = 0; k < AR.GetNumColumns(); ++k)
     592                     {
     593                         double p = AR.GetElement(i, k) * BR.GetElement(k, j);
     594                         double q = AI.GetElement(i, k) * BI.GetElement(k, j);
     595                         double s = (AR.GetElement(i, k) + AI.GetElement(i, k)) * (BR.GetElement(k, j) + BI.GetElement(k, j));
     596                         vr += p - q;
     597                         vi += s - p - q;
     598                     }
     599                     mtxCR.SetElement(i, j, vr);
     600                     mtxCI.SetElement(i, j, vi);
     601                 }
     602             }
     603             CR = mtxCR;
     604             CI = mtxCI;
     605 
     606             return true;
     607 
     608 
     609         }
     610 
     611         /// <summary>
     612         /// 矩阵的转置 
     613         /// </summary>
     614         /// <returns>Matrix型,指定矩阵转置矩阵</returns>
     615         public Matrix Transpose()
     616         {
     617             //构造目标矩阵
     618             Matrix Trans = new Matrix(numColumns, numRows);
     619 
     620             //转置各元素
     621             for (int i = 0; i < numRows; ++i)
     622             {
     623                 for (int j = 0; j < numColumns; ++j)
     624                     Trans.SetElement(j, i, GetElement(i, j));
     625             }
     626             return Trans;
     627         }
     628         /// <summary>
     629         /// 实矩阵求逆的全选主元高斯-约当法
     630         /// </summary>
     631         /// <returns>bool型,求逆是否成功</returns>
     632         public bool InvertGaussJordan()
     633         {
     634             int i, j, k, l, u, v;
     635             double d = 0, p = 0;
     636 
     637             //分配内存
     638             int[] pnRow = new int[numColumns];
     639             int[] pnCol = new int[numColumns];
     640 
     641             //消元
     642             for (k = 0; k <= numColumns - 1; k++)
     643             {
     644                 d = 0.0;
     645                 for (i = k; i <= numColumns - 1; i++)
     646                 {
     647                     for (j = k; j <= numColumns - 1; j++)
     648                     {
     649                         l = i * numColumns + j; p = Math.Abs(elements[l]);
     650                         if (p > d)
     651                         {
     652                             d = p;
     653                             pnRow[k] = i;
     654                             pnCol[k] = j;
     655                         }
     656                     }
     657                 }
     658                 //失败
     659                 if (d == 0.0)
     660                 {
     661                     return false;
     662                 }
     663 
     664                 if (pnRow[k] != k)
     665                 {
     666                     for (j = 0; j <= numColumns - 1; j++)
     667                     {
     668                         u = k * numColumns + j;
     669                         v = pnRow[k] * numColumns + j;
     670                         p = elements[u];
     671                         elements[u] = elements[v];
     672                         elements[v] = p;
     673                     }
     674                 }
     675                 if (pnCol[k] != k)
     676                 {
     677                     for (i = 0; i <= numColumns - 1; i++)
     678                     {
     679                         u = i * numColumns + k;
     680                         v = i * numColumns + pnCol[k];
     681                         p = elements[u];
     682                         elements[u] = elements[v];
     683                         elements[v] = p;
     684                     }
     685                 }
     686                 l = k * numColumns + k;
     687                 elements[l] = 1.0 / elements[l];
     688                 for (j = 0; j <= numColumns - 1; j++)
     689                 {
     690                     if (j != k)
     691                     {
     692                         u = k * numColumns + j;
     693                         elements[u] = elements[u] * elements[l];
     694                     }
     695                 }
     696 
     697                 for (i = 0; i <= numColumns - 1; i++)
     698                 {
     699                     if (i != k)
     700                     {
     701                         for (j = 0; j <= numColumns - 1; j++)
     702                         {
     703                             if (j != k)
     704                             {
     705                                 u = i * numColumns + j;
     706                                 elements[u] = elements[u] - elements[i * numColumns + k] * elements[k * numColumns + j];
     707                             }
     708                         }
     709                     }
     710                 }
     711                 for (i = 0; i <= numColumns - 1; i++)
     712                 {
     713                     if (i != k)
     714                     {
     715                         u = i * numColumns + k;
     716                         elements[u] = -elements[u] * elements[l];
     717                     }
     718                 }
     719             }
     720 
     721             //调整恢复行列次序
     722             for (k = numColumns - 1; k >= 0; k--)
     723             {
     724                 if (pnCol[k] != k)
     725                 {
     726                     for (j = 0; j <= numColumns - 1; j++)
     727                     {
     728                         u = k * numColumns + j;
     729                         v = pnCol[k] * numColumns + j;
     730                         p = elements[u];
     731                         elements[u] = elements[v];
     732                         elements[v] = p;
     733                     }
     734                 }
     735                 if (pnRow[k] != k)
     736                 {
     737                     for (i = 0; i <= numColumns - 1; i++)
     738                     {
     739                         u = i * numColumns + k;
     740                         v = i * numColumns + pnRow[k];
     741                         p = elements[u];
     742                         elements[u] = elements[v];
     743                         elements[v] = p;
     744                     }
     745                 }
     746             }
     747             //成功返回
     748             return true;
     749 
     750 
     751         }
     752         /// <summary>
     753         /// 复矩阵求逆的全选主元高斯--约当法
     754         /// </summary>
     755         /// <param name="mtxImag">复矩阵的虚部矩阵,当前矩阵为复矩阵的实部</param>
     756         /// <returns>bool型号,求逆是否成功</returns>
     757         public bool InvertGaussJordan(Matrix mtxImag)
     758         {
     759             int i, j, k, l, u, v, w;
     760             double p, q, s, t, d, b;
     761 
     762             // 分配内存
     763             int[] pnRow = new int[numColumns];
     764             int[] pnCol = new int[numColumns];
     765 
     766             // 消元
     767             for (k = 0; k <= numColumns - 1; k++)
     768             {
     769                 d = 0.0;
     770                 for (i = k; i <= numColumns - 1; i++)
     771                 {
     772                     for (j = k; j <= numColumns - 1; j++)
     773                     {
     774                         u = i * numColumns + j;
     775                         p = elements[u] * elements[u] + mtxImag.elements[u] * mtxImag.elements[u];
     776                         if (p > d)
     777                         {
     778                             d = p;
     779                             pnRow[k] = i;
     780                             pnCol[k] = j;
     781                         }
     782                     }
     783                 }
     784 
     785                 // 失败
     786                 if (d == 0.0)
     787                 {
     788                     return false;
     789                 }
     790 
     791                 if (pnRow[k] != k)
     792                 {
     793                     for (j = 0; j <= numColumns - 1; j++)
     794                     {
     795                         u = k * numColumns + j;
     796                         v = pnRow[k] * numColumns + j;
     797                         t = elements[u];
     798                         elements[u] = elements[v];
     799                         elements[v] = t;
     800                         t = mtxImag.elements[u];
     801                         mtxImag.elements[u] = mtxImag.elements[v];
     802                         mtxImag.elements[v] = t;
     803                     }
     804                 }
     805 
     806                 if (pnCol[k] != k)
     807                 {
     808                     for (i = 0; i <= numColumns - 1; i++)
     809                     {
     810                         u = i * numColumns + k;
     811                         v = i * numColumns + pnCol[k];
     812                         t = elements[u];
     813                         elements[u] = elements[v];
     814                         elements[v] = t;
     815                         t = mtxImag.elements[u];
     816                         mtxImag.elements[u] = mtxImag.elements[v];
     817                         mtxImag.elements[v] = t;
     818                     }
     819                 }
     820 
     821                 l = k * numColumns + k;
     822                 elements[l] = elements[l] / d; mtxImag.elements[l] = -mtxImag.elements[l] / d;
     823                 for (j = 0; j <= numColumns - 1; j++)
     824                 {
     825                     if (j != k)
     826                     {
     827                         u = k * numColumns + j;
     828                         p = elements[u] * elements[l];
     829                         q = mtxImag.elements[u] * mtxImag.elements[l];
     830                         s = (elements[u] + mtxImag.elements[u]) * (elements[l] + mtxImag.elements[l]);
     831                         elements[u] = p - q;
     832                         mtxImag.elements[u] = s - p - q;
     833                     }
     834                 }
     835 
     836                 for (i = 0; i <= numColumns - 1; i++)
     837                 {
     838                     if (i != k)
     839                     {
     840                         v = i * numColumns + k;
     841                         for (j = 0; j <= numColumns - 1; j++)
     842                         {
     843                             if (j != k)
     844                             {
     845                                 u = k * numColumns + j;
     846                                 w = i * numColumns + j;
     847                                 p = elements[u] * elements[v];
     848                                 q = mtxImag.elements[u] * mtxImag.elements[v];
     849                                 s = (elements[u] + mtxImag.elements[u]) * (elements[v] + mtxImag.elements[v]);
     850                                 t = p - q;
     851                                 b = s - p - q;
     852                                 elements[w] = elements[w] - t;
     853                                 mtxImag.elements[w] = mtxImag.elements[w] - b;
     854                             }
     855                         }
     856                     }
     857                 }
     858 
     859                 for (i = 0; i <= numColumns - 1; i++)
     860                 {
     861                     if (i != k)
     862                     {
     863                         u = i * numColumns + k;
     864                         p = elements[u] * elements[l];
     865                         q = mtxImag.elements[u] * mtxImag.elements[l];
     866                         s = (elements[u] + mtxImag.elements[u]) * (elements[l] + mtxImag.elements[l]);
     867                         elements[u] = q - p;
     868                         mtxImag.elements[u] = p + q - s;
     869                     }
     870                 }
     871             }
     872 
     873             // 调整恢复行列次序
     874             for (k = numColumns - 1; k >= 0; k--)
     875             {
     876                 if (pnCol[k] != k)
     877                 {
     878                     for (j = 0; j <= numColumns - 1; j++)
     879                     {
     880                         u = k * numColumns + j;
     881                         v = pnCol[k] * numColumns + j;
     882                         t = elements[u];
     883                         elements[u] = elements[v];
     884                         elements[v] = t;
     885                         t = mtxImag.elements[u];
     886                         mtxImag.elements[u] = mtxImag.elements[v];
     887                         mtxImag.elements[v] = t;
     888                     }
     889                 }
     890 
     891                 if (pnRow[k] != k)
     892                 {
     893                     for (i = 0; i <= numColumns - 1; i++)
     894                     {
     895                         u = i * numColumns + k;
     896                         v = i * numColumns + pnRow[k];
     897                         t = elements[u];
     898                         elements[u] = elements[v];
     899                         elements[v] = t;
     900                         t = mtxImag.elements[u];
     901                         mtxImag.elements[u] = mtxImag.elements[v];
     902                         mtxImag.elements[v] = t;
     903                     }
     904                 }
     905             }
     906 
     907             // 成功返回
     908             return true;
     909         }
     910         /// <summary>
     911         /// 对称正定矩阵的求逆
     912         /// </summary>
     913         /// <returns>bool型,求逆是否成功</returns>
     914         public bool InvertSsgj()
     915         {
     916             int i, j, k, m;
     917             double w, g;
     918 
     919             //临时内存
     920             double[] pTmp = new double[numColumns];
     921 
     922             //逐行处理
     923             for (k = 0; k <= numColumns - 1; k++)
     924             {
     925                 w = elements[0];
     926                 if (w == 0.0)
     927                 {
     928                     return false;
     929                 }
     930 
     931                 m = numColumns - k - 1;
     932                 for (i = 1; i <= numColumns - 1; i++)
     933                 {
     934                     g = elements[i * numColumns];
     935                     pTmp[i] = g / w;
     936                     if (i <= m)
     937                         pTmp[i] = -pTmp[i];
     938                     for (j = 1; j <= i; j++)
     939                         elements[(i - 1) * numColumns + j - 1] = elements[i * numColumns + j] + g * pTmp[j];
     940                 }
     941 
     942                 elements[numColumns * numColumns - 1] = 1.0 / w;
     943                 for (i = 1; i <= numColumns - 1; i++)
     944                     elements[(numColumns - 1) * numColumns + i - 1] = pTmp[i];
     945             }
     946 
     947             //行列调整
     948             for (i = 0; i <= numColumns - 2; i++)
     949                 for (j = i + 1; j <= numColumns - 1; j++)
     950                     elements[i * numColumns + j] = elements[j * numColumns + i];
     951 
     952             return true;
     953 
     954         }
     955 
     956         //托伯利慈矩阵求逆的埃兰特方法
     957         //@return bool型,求逆是否成功
     958 
     959         public bool InvertTrench()
     960         {
     961             int i, j, k;
     962             double a, s;
     963 
     964             // 上三角元素
     965             double[] t = new double[numColumns];
     966             // 下三角元素
     967             double[] tt = new double[numColumns];
     968 
     969             // 上、下三角元素赋值
     970             for (i = 0; i < numColumns; ++i)
     971             {
     972                 t[i] = GetElement(0, i);
     973                 tt[i] = GetElement(i, 0);
     974             }
     975 
     976             // 临时缓冲区
     977             double[] c = new double[numColumns];
     978             double[] r = new double[numColumns];
     979             double[] p = new double[numColumns];
     980 
     981             // 非Toeplitz矩阵,返回
     982             if (t[0] == 0.0)
     983             {
     984                 return false;
     985             }
     986 
     987             a = t[0];
     988             c[0] = tt[1] / t[0];
     989             r[0] = t[1] / t[0];
     990 
     991             for (k = 0; k <= numColumns - 3; k++)
     992             {
     993                 s = 0.0;
     994                 for (j = 1; j <= k + 1; j++)
     995                     s = s + c[k + 1 - j] * tt[j];
     996 
     997                 s = (s - tt[k + 2]) / a;
     998                 for (i = 0; i <= k; i++)
     999                     p[i] = c[i] + s * r[k - i];
    1000 
    1001                 c[k + 1] = -s;
    1002                 s = 0.0;
    1003                 for (j = 1; j <= k + 1; j++)
    1004                     s = s + r[k + 1 - j] * t[j];
    1005 
    1006                 s = (s - t[k + 2]) / a;
    1007                 for (i = 0; i <= k; i++)
    1008                 {
    1009                     r[i] = r[i] + s * c[k - i];
    1010                     c[k - i] = p[k - i];
    1011                 }
    1012 
    1013                 r[k + 1] = -s;
    1014                 a = 0.0;
    1015                 for (j = 1; j <= k + 2; j++)
    1016                     a = a + t[j] * c[j - 1];
    1017 
    1018                 a = t[0] - a;
    1019 
    1020                 // 求解失败
    1021                 if (a == 0.0)
    1022                 {
    1023                     return false;
    1024                 }
    1025             }
    1026 
    1027             elements[0] = 1.0 / a;
    1028             for (i = 0; i <= numColumns - 2; i++)
    1029             {
    1030                 k = i + 1;
    1031                 j = (i + 1) * numColumns;
    1032                 elements[k] = -r[i] / a;
    1033                 elements[j] = -c[i] / a;
    1034             }
    1035 
    1036             for (i = 0; i <= numColumns - 2; i++)
    1037             {
    1038                 for (j = 0; j <= numColumns - 2; j++)
    1039                 {
    1040                     k = (i + 1) * numColumns + j + 1;
    1041                     elements[k] = elements[i * numColumns + j] - c[i] * elements[j + 1];
    1042                     elements[k] = elements[k] + c[numColumns - j - 2] * elements[numColumns - i - 1];
    1043                 }
    1044             }
    1045 
    1046             return true;
    1047         }
    1048 
    1049         //求行列式值的全选主元高斯消去法
    1050         //@return double型,行列式的值
    1051         public double ComputeDetGauss()
    1052         {
    1053             int i, j, k, nis = 0, js = 0, l, u, v;
    1054             double f, det, q, d;
    1055 
    1056             //初值
    1057             f = 1.0;
    1058             det = 1.0;
    1059 
    1060             //消元
    1061             for (k = 0; k <= numColumns - 2; k++)
    1062             {
    1063                 q = 0.0;
    1064                 for (i = k; i <= numColumns - 1; i++)
    1065                 {
    1066                     for (j = k; j <= numColumns - 1; j++)
    1067                     {
    1068                         l = i * numColumns + j;
    1069                         d = Math.Abs(elements[l]);
    1070                         if (d > q)
    1071                         {
    1072                             q = d;
    1073                             nis = i;
    1074                             js = j;
    1075                         }
    1076                     }
    1077                 }
    1078 
    1079                 if (q == 0.0)
    1080                 {
    1081                     det = 0.0;
    1082                     return (det);
    1083                 }
    1084 
    1085                 if (nis != k)
    1086                 {
    1087                     f = -f;
    1088                     for (j = k; j <= numColumns - 1; j++)
    1089                     {
    1090                         u = k * numColumns + j;
    1091                         v = nis * numColumns + j;
    1092                         d = elements[u];
    1093                         elements[u] = elements[v];
    1094                         elements[v] = d;
    1095                     }
    1096                 }
    1097 
    1098                 if (js != k)
    1099                 {
    1100                     f = -f;
    1101                     for (i = k; i <= numColumns - 1; i++)
    1102                     {
    1103                         u = i * numColumns + js;
    1104                         v = i * numColumns + k;
    1105                         d = elements[u];
    1106                         elements[u] = elements[v];
    1107                         elements[v] = d;
    1108 
    1109                     }
    1110                 }
    1111                 l = k * numColumns + k;
    1112                 det = det * elements[l];
    1113                 for (i = k + 1; i <= numColumns - 1; i++)
    1114                 {
    1115                     d = elements[i * numColumns + k] / elements[l];
    1116                     for (j = k + 1; j <= numColumns - 1; j++)
    1117                     {
    1118                         u = i * numColumns + j;
    1119                         elements[u] = elements[u] - d * elements[k * numColumns + j];
    1120                     }
    1121                 }
    1122             }
    1123 
    1124             //求值
    1125             det = f * det * elements[numColumns * numColumns - 1];
    1126 
    1127             return (det);
    1128         }
    1129         //求矩阵秩的全选主元高斯消去法
    1130         //@return int型,矩阵的秩
    1131         public int ComputeRankGauss()
    1132         {
    1133             int i, j, k, nn, nis = 0, js = 0, l, ll, u, v;
    1134             double q, d;
    1135 
    1136             //秩小于等于行列数
    1137             nn = numRows;
    1138             if (numRows >= numColumns)
    1139                 nn = numColumns;
    1140             k = 0;
    1141 
    1142             //消元求解
    1143             for (l = 0; l <= nn - 1; l++)
    1144             {
    1145                 q = 0.0;
    1146                 for (i = 1; i <= numRows - 1; i++)
    1147                 {
    1148                     for (j = 1; j <= numColumns - 1; j++)
    1149                     {
    1150                         ll = i * numColumns + j;
    1151                         d = Math.Abs(elements[ll]);
    1152                         if (d > q)
    1153                         {
    1154                             q = d;
    1155                             nis = i;
    1156                             js = j;
    1157                         }
    1158                     }
    1159                 }
    1160 
    1161                 if (q == 0.0)
    1162                     return (k);
    1163 
    1164                 k = k + 1;
    1165                 if (nis != 1)
    1166                 {
    1167                     for (j = 1; j <= numColumns - 1; j++)
    1168                     {
    1169                         u = l * numColumns + j;
    1170                         v = nis * numColumns + j;
    1171                         d = elements[u];
    1172                         elements[u] = elements[v];
    1173                         elements[v] = d;
    1174                     }
    1175                 }
    1176                 if (js != 1)
    1177                 {
    1178                     for (i = 1; i <= numRows - 1; i++)
    1179                     {
    1180                         u = i * numColumns + js;
    1181                         v = i * numColumns + l;
    1182                         d = elements[u];
    1183                         elements[u] = elements[v];
    1184                         elements[v] = d;
    1185                     }
    1186                 }
    1187 
    1188                 ll = l * numColumns + l;
    1189                 for (i = l + 1; i <= numColumns - 1; i++)
    1190                 {
    1191                     d = elements[i * numColumns + l] / elements[ll];
    1192                     for (j = l + 1; j <= numColumns - 1; j++)
    1193                     {
    1194                         u = i * numColumns + j;
    1195                         elements[u] = elements[u] - d * elements[l * numColumns + j];
    1196                     }
    1197                 }
    1198 
    1199 
    1200             }
    1201             return (k);
    1202         }
    1203 
    1204         //对称正定矩阵的乔里斯基分解与行列式的求值
    1205         //@param realDetValue---返回行列式的值
    1206         //@return bool型,求解是否成功
    1207         public bool ComputeDetCholesky(ref double realDetValue)
    1208         {
    1209             int i, j, k, u, l;
    1210             double d;
    1211 
    1212             //不满足求解要求
    1213             if (elements[0] <= 0.0)
    1214                 return false;
    1215 
    1216             //乔里斯基分解
    1217 
    1218             elements[0] = Math.Sqrt(elements[0]);
    1219             d = elements[0];
    1220 
    1221             for (i = 1; i <= numColumns - 1; i++)
    1222             {
    1223                 u = i * numColumns;
    1224                 elements[u] = elements[u] / elements[0];
    1225             }
    1226 
    1227             for (j = 1; j <= numColumns - 1; j++)
    1228             {
    1229                 l = j * numColumns + j;
    1230                 for (k = 0; k <= j - 1; k++)
    1231                 {
    1232                     u = j * numColumns + k;
    1233                     elements[l] = elements[l] - elements[u] * elements[u];
    1234 
    1235 
    1236                 }
    1237 
    1238                 if (elements[l] <= 0.0)
    1239                     return false;
    1240 
    1241                 elements[l] = Math.Sqrt(elements[l]);
    1242                 d = d * elements[l];
    1243 
    1244                 for (i = j + 1; i <= numColumns - 1; i++)
    1245                 {
    1246                     u = i * numColumns + j;
    1247                     for (k = 0; k <= j - 1; k++)
    1248                         elements[u] = elements[u] - elements[i * numColumns + k] * elements[j * numColumns + k];
    1249                     elements[u] = elements[u] / elements[l];
    1250                 }
    1251 
    1252             }
    1253 
    1254             //行列式求值
    1255             realDetValue = d * d;
    1256 
    1257             //下三角矩阵
    1258             for (i = 0; i <= numColumns - 2; i++)
    1259                 for (j = i + 1; j <= numColumns - 1; j++)
    1260                     elements[i * numColumns + j] = 0.0;
    1261 
    1262             return true;
    1263 
    1264         }
    1265 
    1266 
    1267         //矩阵的三角分解,分解成功后,原矩阵将成为Q矩阵
    1268         //@param mtxL---返回分解后的L矩阵
    1269         //@param mtxU---返回分解后的U矩阵
    1270         //@return bool型,求解是否成功
    1271         public bool SpiltLU(Matrix mtxL, Matrix mtxU)
    1272         {
    1273             int i, j, k, w, v, ll;
    1274 
    1275             //初始化结果矩阵
    1276             if (!mtxL.Init(numColumns, numColumns) || !mtxU.Init(numColumns, numColumns))
    1277                 return false;
    1278 
    1279             for (k = 0; k <= numColumns - 2; k++)
    1280             {
    1281                 ll = k * numColumns + k;
    1282                 if (elements[ll] == 0.0)
    1283                     return false;
    1284 
    1285                 for (i = k + 1; i <= numColumns - 1; i++)
    1286                 {
    1287                     w = i * numColumns + k;
    1288                     elements[w] = elements[w] / elements[ll];
    1289                 }
    1290 
    1291                 for (i = k + 1; i <= numColumns - 1; i++)
    1292                 {
    1293                     w = i * numColumns + k;
    1294                     for (j = k + 1; j <= numColumns - 1; j++)
    1295                     {
    1296                         v = i * numColumns + j;
    1297                         elements[v] = elements[v] - elements[w] * elements[k * numColumns + j];
    1298                     }
    1299                 }
    1300             }
    1301 
    1302             for (i = 0; i <= numColumns - 1; i++)
    1303             {
    1304                 for (j = 0; j < i; j++)
    1305                 {
    1306                     w = i * numColumns + j;
    1307                     mtxL.elements[w] = elements[w];
    1308                     mtxU.elements[w] = 0.0;
    1309                 }
    1310 
    1311                 w = i * numColumns + i;
    1312                 mtxL.elements[w] = 1.0;
    1313                 mtxU.elements[w] = elements[w];
    1314 
    1315                 for (j = i + 1; j <= numColumns - 1; j++)
    1316                 {
    1317                     w = i * numColumns + j;
    1318                     mtxL.elements[w] = 0.0;
    1319                     mtxU.elements[w] = elements[w];
    1320                 }
    1321             }
    1322 
    1323             return true;
    1324         }
    1325 
    1326         //一般实矩阵的QR分解,分解成功后,原矩阵将成为R矩阵
    1327         //@param mtxQ---返回分解后的Q矩阵
    1328         //@return bool型,求解是否成功
    1329         public bool SplitQR(Matrix mtxQ)
    1330         {
    1331             int i, j, k, l, nn, p, jj;
    1332             double u, alpha, w, t;
    1333 
    1334             if (numRows < numColumns)
    1335                 return false;
    1336 
    1337             // 初始化Q矩阵
    1338             if (!mtxQ.Init(numRows, numRows))
    1339                 return false;
    1340 
    1341             // 对角线元素单位化
    1342             for (i = 0; i <= numRows - 1; i++)
    1343             {
    1344                 for (j = 0; j <= numRows - 1; j++)
    1345                 {
    1346                     l = i * numRows + j;
    1347                     mtxQ.elements[l] = 0.0;
    1348                     if (i == j)
    1349                         mtxQ.elements[l] = 1.0;
    1350                 }
    1351             }
    1352 
    1353             // 开始分解
    1354 
    1355             nn = numColumns;
    1356             if (numRows == numColumns)
    1357                 nn = numRows - 1;
    1358 
    1359             for (k = 0; k <= nn - 1; k++)
    1360             {
    1361                 u = 0.0;
    1362                 l = k * numColumns + k;
    1363                 for (i = k; i <= numRows - 1; i++)
    1364                 {
    1365                     w = Math.Abs(elements[i * numColumns + k]);
    1366                     if (w > u)
    1367                         u = w;
    1368                 }
    1369 
    1370                 alpha = 0.0;
    1371                 for (i = k; i <= numRows - 1; i++)
    1372                 {
    1373                     t = elements[i * numColumns + k] / u;
    1374                     alpha = alpha + t * t;
    1375                 }
    1376 
    1377                 if (elements[l] > 0.0)
    1378                     u = -u;
    1379 
    1380                 alpha = u * Math.Sqrt(alpha);
    1381                 if (alpha == 0.0)
    1382                     return false;
    1383 
    1384                 u = Math.Sqrt(2.0 * alpha * (alpha - elements[l]));
    1385                 if ((u + 1.0) != 1.0)
    1386                 {
    1387                     elements[l] = (elements[l] - alpha) / u;
    1388                     for (i = k + 1; i <= numRows - 1; i++)
    1389                     {
    1390                         p = i * numColumns + k;
    1391                         elements[p] = elements[p] / u;
    1392                     }
    1393 
    1394                     for (j = 0; j <= numRows - 1; j++)
    1395                     {
    1396                         t = 0.0;
    1397                         for (jj = k; jj <= numRows - 1; jj++)
    1398                             t = t + elements[jj * numColumns + k] * mtxQ.elements[jj * numRows + j];
    1399 
    1400                         for (i = k; i <= numRows - 1; i++)
    1401                         {
    1402                             p = i * numRows + j;
    1403                             mtxQ.elements[p] = mtxQ.elements[p] - 2.0 * t * elements[i * numColumns + k];
    1404                         }
    1405                     }
    1406 
    1407                     for (j = k + 1; j <= numColumns - 1; j++)
    1408                     {
    1409                         t = 0.0;
    1410 
    1411                         for (jj = k; jj <= numRows - 1; jj++)
    1412                             t = t + elements[jj * numColumns + k] * elements[jj * numColumns + j];
    1413 
    1414                         for (i = k; i <= numRows - 1; i++)
    1415                         {
    1416                             p = i * numColumns + j;
    1417                             elements[p] = elements[p] - 2.0 * t * elements[i * numColumns + k];
    1418                         }
    1419                     }
    1420 
    1421                     elements[l] = alpha;
    1422                     for (i = k + 1; i <= numRows - 1; i++)
    1423                         elements[i * numColumns + k] = 0.0;
    1424                 }
    1425             }
    1426 
    1427             // 调整元素
    1428             for (i = 0; i <= numRows - 2; i++)
    1429             {
    1430                 for (j = i + 1; j <= numRows - 1; j++)
    1431                 {
    1432                     p = i * numRows + j;
    1433                     l = j * numRows + i;
    1434                     t = mtxQ.elements[p];
    1435                     mtxQ.elements[p] = mtxQ.elements[l];
    1436                     mtxQ.elements[l] = t;
    1437                 }
    1438             }
    1439 
    1440             return true;
    1441         }
    1442 
    1443         //一般实矩阵的奇异值分解,分解成功后,原矩阵对角线元素就是矩阵的奇异值
    1444         //@param mtxU--返回分解后的U矩阵
    1445         //@param mtxV--返回分解后的V矩阵
    1446         //@param eps---计算精度
    1447         //@return bool型,求解是否成功
    1448         public bool SplitUV(Matrix mtxU, Matrix mtxV, double eps)
    1449         {
    1450             int i, j, k, l, it, ll, kk, ix, iy, mm, nn, iz, m1, ks;
    1451             double d, dd, t, sm, sm1, em1, sk, ek, b, c, shh;
    1452             double[] fg = new double[2];
    1453             double[] cs = new double[2];
    1454 
    1455             int m = numRows;
    1456             int n = numColumns;
    1457 
    1458             // 初始化U, V矩阵
    1459             if (!mtxU.Init(m, m) || !mtxV.Init(n, n))
    1460                 return false;
    1461 
    1462             // 临时缓冲区
    1463             int ka = Math.Max(m, n) + 1;
    1464             double[] s = new double[ka];
    1465             double[] e = new double[ka];
    1466             double[] w = new double[ka];
    1467 
    1468             // 指定迭代次数为60
    1469             it = 60;
    1470             k = n;
    1471 
    1472             if (m - 1 < n)
    1473                 k = m - 1;
    1474 
    1475             l = m;
    1476             if (n - 2 < m)
    1477                 l = n - 2;
    1478             if (l < 0)
    1479                 l = 0;
    1480 
    1481             // 循环迭代计算
    1482             ll = k;
    1483             if (l > k)
    1484                 ll = l;
    1485             if (ll >= 1)
    1486             {
    1487                 for (kk = 1; kk <= ll; kk++)
    1488                 {
    1489                     if (kk <= k)
    1490                     {
    1491                         d = 0.0;
    1492                         for (i = kk; i <= m; i++)
    1493                         {
    1494                             ix = (i - 1) * n + kk - 1;
    1495                             d = d + elements[ix] * elements[ix];
    1496                         }
    1497 
    1498                         s[kk - 1] = Math.Sqrt(d);
    1499                         if (s[kk - 1] != 0.0)
    1500                         {
    1501                             ix = (kk - 1) * n + kk - 1;
    1502                             if (elements[ix] != 0.0)
    1503                             {
    1504                                 s[kk - 1] = Math.Abs(s[kk - 1]);
    1505                                 if (elements[ix] < 0.0)
    1506                                     s[kk - 1] = -s[kk - 1];
    1507                             }
    1508 
    1509                             for (i = kk; i <= m; i++)
    1510                             {
    1511                                 iy = (i - 1) * n + kk - 1;
    1512                                 elements[iy] = elements[iy] / s[kk - 1];
    1513                             }
    1514 
    1515                             elements[ix] = 1.0 + elements[ix];
    1516                         }
    1517 
    1518                         s[kk - 1] = -s[kk - 1];
    1519                     }
    1520 
    1521                     if (n >= kk + 1)
    1522                     {
    1523                         for (j = kk + 1; j <= n; j++)
    1524                         {
    1525                             if ((kk <= k) && (s[kk - 1] != 0.0))
    1526                             {
    1527                                 d = 0.0;
    1528                                 for (i = kk; i <= m; i++)
    1529                                 {
    1530                                     ix = (i - 1) * n + kk - 1;
    1531                                     iy = (i - 1) * n + j - 1;
    1532                                     d = d + elements[ix] * elements[iy];
    1533                                 }
    1534 
    1535                                 d = -d / elements[(kk - 1) * n + kk - 1];
    1536                                 for (i = kk; i <= m; i++)
    1537                                 {
    1538                                     ix = (i - 1) * n + j - 1;
    1539                                     iy = (i - 1) * n + kk - 1;
    1540                                     elements[ix] = elements[ix] + d * elements[iy];
    1541                                 }
    1542                             }
    1543 
    1544                             e[j - 1] = elements[(kk - 1) * n + j - 1];
    1545                         }
    1546                     }
    1547 
    1548                     if (kk <= k)
    1549                     {
    1550                         for (i = kk; i <= m; i++)
    1551                         {
    1552                             ix = (i - 1) * m + kk - 1;
    1553                             iy = (i - 1) * n + kk - 1;
    1554                             mtxU.elements[ix] = elements[iy];
    1555                         }
    1556                     }
    1557 
    1558                     if (kk <= l)
    1559                     {
    1560                         d = 0.0;
    1561                         for (i = kk + 1; i <= n; i++)
    1562                             d = d + e[i - 1] * e[i - 1];
    1563 
    1564                         e[kk - 1] = Math.Sqrt(d);
    1565                         if (e[kk - 1] != 0.0)
    1566                         {
    1567                             if (e[kk] != 0.0)
    1568                             {
    1569                                 e[kk - 1] = Math.Abs(e[kk - 1]);
    1570                                 if (e[kk] < 0.0)
    1571                                     e[kk - 1] = -e[kk - 1];
    1572                             }
    1573 
    1574                             for (i = kk + 1; i <= n; i++)
    1575                                 e[i - 1] = e[i - 1] / e[kk - 1];
    1576 
    1577                             e[kk] = 1.0 + e[kk];
    1578                         }
    1579 
    1580                         e[kk - 1] = -e[kk - 1];
    1581                         if ((kk + 1 <= m) && (e[kk - 1] != 0.0))
    1582                         {
    1583                             for (i = kk + 1; i <= m; i++)
    1584                                 w[i - 1] = 0.0;
    1585 
    1586                             for (j = kk + 1; j <= n; j++)
    1587                                 for (i = kk + 1; i <= m; i++)
    1588                                     w[i - 1] = w[i - 1] + e[j - 1] * elements[(i - 1) * n + j - 1];
    1589 
    1590                             for (j = kk + 1; j <= n; j++)
    1591                             {
    1592                                 for (i = kk + 1; i <= m; i++)
    1593                                 {
    1594                                     ix = (i - 1) * n + j - 1;
    1595                                     elements[ix] = elements[ix] - w[i - 1] * e[j - 1] / e[kk];
    1596                                 }
    1597                             }
    1598                         }
    1599 
    1600                         for (i = kk + 1; i <= n; i++)
    1601                             mtxV.elements[(i - 1) * n + kk - 1] = e[i - 1];
    1602                     }
    1603                 }
    1604             }
    1605 
    1606             mm = n;
    1607             if (m + 1 < n)
    1608                 mm = m + 1;
    1609             if (k < n)
    1610                 s[k] = elements[k * n + k];
    1611             if (m < mm)
    1612                 s[mm - 1] = 0.0;
    1613             if (l + 1 < mm)
    1614                 e[l] = elements[l * n + mm - 1];
    1615 
    1616             e[mm - 1] = 0.0;
    1617             nn = m;
    1618             if (m > n)
    1619                 nn = n;
    1620             if (nn >= k + 1)
    1621             {
    1622                 for (j = k + 1; j <= nn; j++)
    1623                 {
    1624                     for (i = 1; i <= m; i++)
    1625                         mtxU.elements[(i - 1) * m + j - 1] = 0.0;
    1626                     mtxU.elements[(j - 1) * m + j - 1] = 1.0;
    1627                 }
    1628             }
    1629 
    1630             if (k >= 1)
    1631             {
    1632                 for (ll = 1; ll <= k; ll++)
    1633                 {
    1634                     kk = k - ll + 1;
    1635                     iz = (kk - 1) * m + kk - 1;
    1636                     if (s[kk - 1] != 0.0)
    1637                     {
    1638                         if (nn >= kk + 1)
    1639                         {
    1640                             for (j = kk + 1; j <= nn; j++)
    1641                             {
    1642                                 d = 0.0;
    1643                                 for (i = kk; i <= m; i++)
    1644                                 {
    1645                                     ix = (i - 1) * m + kk - 1;
    1646                                     iy = (i - 1) * m + j - 1;
    1647                                     d = d + mtxU.elements[ix] * mtxU.elements[iy] / mtxU.elements[iz];
    1648                                 }
    1649 
    1650                                 d = -d;
    1651                                 for (i = kk; i <= m; i++)
    1652                                 {
    1653                                     ix = (i - 1) * m + j - 1;
    1654                                     iy = (i - 1) * m + kk - 1;
    1655                                     mtxU.elements[ix] = mtxU.elements[ix] + d * mtxU.elements[iy];
    1656                                 }
    1657                             }
    1658                         }
    1659 
    1660                         for (i = kk; i <= m; i++)
    1661                         {
    1662                             ix = (i - 1) * m + kk - 1;
    1663                             mtxU.elements[ix] = -mtxU.elements[ix];
    1664                         }
    1665 
    1666                         mtxU.elements[iz] = 1.0 + mtxU.elements[iz];
    1667                         if (kk - 1 >= 1)
    1668                         {
    1669                             for (i = 1; i <= kk - 1; i++)
    1670                                 mtxU.elements[(i - 1) * m + kk - 1] = 0.0;
    1671                         }
    1672                     }
    1673                     else
    1674                     {
    1675                         for (i = 1; i <= m; i++)
    1676                             mtxU.elements[(i - 1) * m + kk - 1] = 0.0;
    1677                         mtxU.elements[(kk - 1) * m + kk - 1] = 1.0;
    1678                     }
    1679                 }
    1680             }
    1681 
    1682             for (ll = 1; ll <= n; ll++)
    1683             {
    1684                 kk = n - ll + 1;
    1685                 iz = kk * n + kk - 1;
    1686 
    1687                 if ((kk <= l) && (e[kk - 1] != 0.0))
    1688                 {
    1689                     for (j = kk + 1; j <= n; j++)
    1690                     {
    1691                         d = 0.0;
    1692                         for (i = kk + 1; i <= n; i++)
    1693                         {
    1694                             ix = (i - 1) * n + kk - 1;
    1695                             iy = (i - 1) * n + j - 1;
    1696                             d = d + mtxV.elements[ix] * mtxV.elements[iy] / mtxV.elements[iz];
    1697                         }
    1698 
    1699                         d = -d;
    1700                         for (i = kk + 1; i <= n; i++)
    1701                         {
    1702                             ix = (i - 1) * n + j - 1;
    1703                             iy = (i - 1) * n + kk - 1;
    1704                             mtxV.elements[ix] = mtxV.elements[ix] + d * mtxV.elements[iy];
    1705                         }
    1706                     }
    1707                 }
    1708 
    1709                 for (i = 1; i <= n; i++)
    1710                     mtxV.elements[(i - 1) * n + kk - 1] = 0.0;
    1711 
    1712                 mtxV.elements[iz - n] = 1.0;
    1713             }
    1714 
    1715             for (i = 1; i <= m; i++)
    1716                 for (j = 1; j <= n; j++)
    1717                     elements[(i - 1) * n + j - 1] = 0.0;
    1718 
    1719             m1 = mm;
    1720             it = 60;
    1721             while (true)
    1722             {
    1723                 if (mm == 0)
    1724                 {
    1725                     ppp(elements, e, s, mtxV.elements, m, n);
    1726                     return true;
    1727                 }
    1728                 if (it == 0)
    1729                 {
    1730                     ppp(elements, e, s, mtxV.elements, m, n);
    1731                     return false;
    1732                 }
    1733 
    1734                 kk = mm - 1;
    1735                 while ((kk != 0) && (Math.Abs(e[kk - 1]) != 0.0))
    1736                 {
    1737                     d = Math.Abs(s[kk - 1]) + Math.Abs(s[kk]);
    1738                     dd = Math.Abs(e[kk - 1]);
    1739                     if (dd > eps * d)
    1740                         kk = kk - 1;
    1741                     else
    1742                         e[kk - 1] = 0.0;
    1743                 }
    1744 
    1745                 if (kk == mm - 1)
    1746                 {
    1747                     kk = kk + 1;
    1748                     if (s[kk - 1] < 0.0)
    1749                     {
    1750                         s[kk - 1] = -s[kk - 1];
    1751                         for (i = 1; i <= n; i++)
    1752                         {
    1753                             ix = (i - 1) * n + kk - 1;
    1754                             mtxV.elements[ix] = -mtxV.elements[ix];
    1755                         }
    1756                     }
    1757 
    1758                     while ((kk != m1) && (s[kk - 1] < s[kk]))
    1759                     {
    1760                         d = s[kk - 1];
    1761                         s[kk - 1] = s[kk];
    1762                         s[kk] = d;
    1763                         if (kk < n)
    1764                         {
    1765                             for (i = 1; i <= n; i++)
    1766                             {
    1767                                 ix = (i - 1) * n + kk - 1;
    1768                                 iy = (i - 1) * n + kk;
    1769                                 d = mtxV.elements[ix];
    1770                                 mtxV.elements[ix] = mtxV.elements[iy];
    1771                                 mtxV.elements[iy] = d;
    1772                             }
    1773                         }
    1774 
    1775                         if (kk < m)
    1776                         {
    1777                             for (i = 1; i <= m; i++)
    1778                             {
    1779                                 ix = (i - 1) * m + kk - 1;
    1780                                 iy = (i - 1) * m + kk;
    1781                                 d = mtxU.elements[ix];
    1782                                 mtxU.elements[ix] = mtxU.elements[iy];
    1783                                 mtxU.elements[iy] = d;
    1784                             }
    1785                         }
    1786 
    1787                         kk = kk + 1;
    1788                     }
    1789 
    1790                     it = 60;
    1791                     mm = mm - 1;
    1792                 }
    1793                 else
    1794                 {
    1795                     ks = mm;
    1796                     while ((ks > kk) && (Math.Abs(s[ks - 1]) != 0.0))
    1797                     {
    1798                         d = 0.0;
    1799                         if (ks != mm)
    1800                             d = d + Math.Abs(e[ks - 1]);
    1801                         if (ks != kk + 1)
    1802                             d = d + Math.Abs(e[ks - 2]);
    1803 
    1804                         dd = Math.Abs(s[ks - 1]);
    1805                         if (dd > eps * d)
    1806                             ks = ks - 1;
    1807                         else
    1808                             s[ks - 1] = 0.0;
    1809                     }
    1810 
    1811                     if (ks == kk)
    1812                     {
    1813                         kk = kk + 1;
    1814                         d = Math.Abs(s[mm - 1]);
    1815                         t = Math.Abs(s[mm - 2]);
    1816                         if (t > d)
    1817                             d = t;
    1818 
    1819                         t = Math.Abs(e[mm - 2]);
    1820                         if (t > d)
    1821                             d = t;
    1822 
    1823                         t = Math.Abs(s[kk - 1]);
    1824                         if (t > d)
    1825                             d = t;
    1826 
    1827                         t = Math.Abs(e[kk - 1]);
    1828                         if (t > d)
    1829                             d = t;
    1830 
    1831                         sm = s[mm - 1] / d;
    1832                         sm1 = s[mm - 2] / d;
    1833                         em1 = e[mm - 2] / d;
    1834                         sk = s[kk - 1] / d;
    1835                         ek = e[kk - 1] / d;
    1836                         b = ((sm1 + sm) * (sm1 - sm) + em1 * em1) / 2.0;
    1837                         c = sm * em1;
    1838                         c = c * c;
    1839                         shh = 0.0;
    1840 
    1841                         if ((b != 0.0) || (c != 0.0))
    1842                         {
    1843                             shh = Math.Sqrt(b * b + c);
    1844                             if (b < 0.0)
    1845                                 shh = -shh;
    1846 
    1847                             shh = c / (b + shh);
    1848                         }
    1849 
    1850                         fg[0] = (sk + sm) * (sk - sm) - shh;
    1851                         fg[1] = sk * ek;
    1852                         for (i = kk; i <= mm - 1; i++)
    1853                         {
    1854                             sss(fg, cs);
    1855                             if (i != kk)
    1856                                 e[i - 2] = fg[0];
    1857 
    1858                             fg[0] = cs[0] * s[i - 1] + cs[1] * e[i - 1];
    1859                             e[i - 1] = cs[0] * e[i - 1] - cs[1] * s[i - 1];
    1860                             fg[1] = cs[1] * s[i];
    1861                             s[i] = cs[0] * s[i];
    1862 
    1863                             if ((cs[0] != 1.0) || (cs[1] != 0.0))
    1864                             {
    1865                                 for (j = 1; j <= n; j++)
    1866                                 {
    1867                                     ix = (j - 1) * n + i - 1;
    1868                                     iy = (j - 1) * n + i;
    1869                                     d = cs[0] * mtxV.elements[ix] + cs[1] * mtxV.elements[iy];
    1870                                     mtxV.elements[iy] = -cs[1] * mtxV.elements[ix] + cs[0] * mtxV.elements[iy];
    1871                                     mtxV.elements[ix] = d;
    1872                                 }
    1873                             }
    1874 
    1875                             sss(fg, cs);
    1876                             s[i - 1] = fg[0];
    1877                             fg[0] = cs[0] * e[i - 1] + cs[1] * s[i];
    1878                             s[i] = -cs[1] * e[i - 1] + cs[0] * s[i];
    1879                             fg[1] = cs[1] * e[i];
    1880                             e[i] = cs[0] * e[i];
    1881 
    1882                             if (i < m)
    1883                             {
    1884                                 if ((cs[0] != 1.0) || (cs[1] != 0.0))
    1885                                 {
    1886                                     for (j = 1; j <= m; j++)
    1887                                     {
    1888                                         ix = (j - 1) * m + i - 1;
    1889                                         iy = (j - 1) * m + i;
    1890                                         d = cs[0] * mtxU.elements[ix] + cs[1] * mtxU.elements[iy];
    1891                                         mtxU.elements[iy] = -cs[1] * mtxU.elements[ix] + cs[0] * mtxU.elements[iy];
    1892                                         mtxU.elements[ix] = d;
    1893                                     }
    1894                                 }
    1895                             }
    1896                         }
    1897 
    1898                         e[mm - 2] = fg[0];
    1899                         it = it - 1;
    1900                     }
    1901                     else
    1902                     {
    1903                         if (ks == mm)
    1904                         {
    1905                             kk = kk + 1;
    1906                             fg[1] = e[mm - 2];
    1907                             e[mm - 2] = 0.0;
    1908                             for (ll = kk; ll <= mm - 1; ll++)
    1909                             {
    1910                                 i = mm + kk - ll - 1;
    1911                                 fg[0] = s[i - 1];
    1912                                 sss(fg, cs);
    1913                                 s[i - 1] = fg[0];
    1914                                 if (i != kk)
    1915                                 {
    1916                                     fg[1] = -cs[1] * e[i - 2];
    1917                                     e[i - 2] = cs[0] * e[i - 2];
    1918                                 }
    1919 
    1920                                 if ((cs[0] != 1.0) || (cs[1] != 0.0))
    1921                                 {
    1922                                     for (j = 1; j <= n; j++)
    1923                                     {
    1924                                         ix = (j - 1) * n + i - 1;
    1925                                         iy = (j - 1) * n + mm - 1;
    1926                                         d = cs[0] * mtxV.elements[ix] + cs[1] * mtxV.elements[iy];
    1927                                         mtxV.elements[iy] = -cs[1] * mtxV.elements[ix] + cs[0] * mtxV.elements[iy];
    1928                                         mtxV.elements[ix] = d;
    1929                                     }
    1930                                 }
    1931                             }
    1932                         }
    1933                         else
    1934                         {
    1935                             kk = ks + 1;
    1936                             fg[1] = e[kk - 2];
    1937                             e[kk - 2] = 0.0;
    1938                             for (i = kk; i <= mm; i++)
    1939                             {
    1940                                 fg[0] = s[i - 1];
    1941                                 sss(fg, cs);
    1942                                 s[i - 1] = fg[0];
    1943                                 fg[1] = -cs[1] * e[i - 1];
    1944                                 e[i - 1] = cs[0] * e[i - 1];
    1945                                 if ((cs[0] != 1.0) || (cs[1] != 0.0))
    1946                                 {
    1947                                     for (j = 1; j <= m; j++)
    1948                                     {
    1949                                         ix = (j - 1) * m + i - 1;
    1950                                         iy = (j - 1) * m + kk - 2;
    1951                                         d = cs[0] * mtxU.elements[ix] + cs[1] * mtxU.elements[iy];
    1952                                         mtxU.elements[iy] = -cs[1] * mtxU.elements[ix] + cs[0] * mtxU.elements[iy];
    1953                                         mtxU.elements[ix] = d;
    1954                                     }
    1955                                 }
    1956                             }
    1957                         }
    1958                     }
    1959                 }
    1960             }
    1961         }
    1962 
    1963         /**
    1964          * 内部函数,由SplitUV函数调用
    1965          */
    1966         private void ppp(double[] a, double[] e, double[] s, double[] v, int m, int n)
    1967         {
    1968             int i, j, p, q;
    1969             double d;
    1970 
    1971             if (m >= n)
    1972                 i = n;
    1973             else
    1974                 i = m;
    1975 
    1976             for (j = 1; j <= i - 1; j++)
    1977             {
    1978                 a[(j - 1) * n + j - 1] = s[j - 1];
    1979                 a[(j - 1) * n + j] = e[j - 1];
    1980             }
    1981 
    1982             a[(i - 1) * n + i - 1] = s[i - 1];
    1983             if (m < n)
    1984                 a[(i - 1) * n + i] = e[i - 1];
    1985 
    1986             for (i = 1; i <= n - 1; i++)
    1987             {
    1988                 for (j = i + 1; j <= n; j++)
    1989                 {
    1990                     p = (i - 1) * n + j - 1;
    1991                     q = (j - 1) * n + i - 1;
    1992                     d = v[p];
    1993                     v[p] = v[q];
    1994                     v[q] = d;
    1995                 }
    1996             }
    1997         }
    1998 
    1999         /**
    2000          * 内部函数,由SplitUV函数调用
    2001          */
    2002         private void sss(double[] fg, double[] cs)
    2003         {
    2004             double r, d;
    2005 
    2006             if ((Math.Abs(fg[0]) + Math.Abs(fg[1])) == 0.0)
    2007             {
    2008                 cs[0] = 1.0;
    2009                 cs[1] = 0.0;
    2010                 d = 0.0;
    2011             }
    2012             else
    2013             {
    2014                 d = Math.Sqrt(fg[0] * fg[0] + fg[1] * fg[1]);
    2015                 if (Math.Abs(fg[0]) > Math.Abs(fg[1]))
    2016                 {
    2017                     d = Math.Abs(d);
    2018                     if (fg[0] < 0.0)
    2019                         d = -d;
    2020                 }
    2021                 if (Math.Abs(fg[1]) >= Math.Abs(fg[0]))
    2022                 {
    2023                     d = Math.Abs(d);
    2024                     if (fg[1] < 0.0)
    2025                         d = -d;
    2026                 }
    2027 
    2028                 cs[0] = fg[0] / d;
    2029                 cs[1] = fg[1] / d;
    2030             }
    2031 
    2032             r = 1.0;
    2033             if (Math.Abs(fg[0]) > Math.Abs(fg[1]))
    2034                 r = cs[1];
    2035             else if (cs[0] != 0.0)
    2036                 r = 1.0 / cs[0];
    2037 
    2038             fg[0] = d;
    2039             fg[1] = r;
    2040         }
    2041 
    2042         /**
    2043          * 求广义逆的奇异值分解法,分解成功后,原矩阵对角线元素就是矩阵的奇异值
    2044          * 
    2045          * @param mtxAP - 返回原矩阵的广义逆矩阵
    2046          * @param mtxU - 返回分解后的U矩阵
    2047          * @param mtxV - 返回分解后的V矩阵
    2048          * @param eps - 计算精度
    2049          * @return bool型,求解是否成功
    2050          */
    2051         public bool InvertUV(Matrix mtxAP, Matrix mtxU, Matrix mtxV, double eps)
    2052         {
    2053             int i, j, k, l, t, p, q, f;
    2054 
    2055             // 调用奇异值分解
    2056             if (!SplitUV(mtxU, mtxV, eps))
    2057                 return false;
    2058 
    2059             int m = numRows;
    2060             int n = numColumns;
    2061 
    2062             // 初始化广义逆矩阵
    2063             if (!mtxAP.Init(n, m))
    2064                 return false;
    2065 
    2066             // 计算广义逆矩阵
    2067 
    2068             j = n;
    2069             if (m < n)
    2070                 j = m;
    2071             j = j - 1;
    2072             k = 0;
    2073             while ((k <= j) && (elements[k * n + k] != 0.0))
    2074                 k = k + 1;
    2075 
    2076             k = k - 1;
    2077             for (i = 0; i <= n - 1; i++)
    2078             {
    2079                 for (j = 0; j <= m - 1; j++)
    2080                 {
    2081                     t = i * m + j;
    2082                     mtxAP.elements[t] = 0.0;
    2083                     for (l = 0; l <= k; l++)
    2084                     {
    2085                         f = l * n + i;
    2086                         p = j * m + l;
    2087                         q = l * n + l;
    2088                         mtxAP.elements[t] = mtxAP.elements[t] + mtxV.elements[f] * mtxU.elements[p] / elements[q];
    2089                     }
    2090                 }
    2091             }
    2092 
    2093             return true;
    2094         }
    2095 
    2096         /**
    2097          * 约化对称矩阵为对称三对角阵的豪斯荷尔德变换法
    2098          * 
    2099          * @param mtxQ - 返回豪斯荷尔德变换的乘积矩阵Q
    2100          * @param mtxT - 返回求得的对称三对角阵
    2101          * @param dblB - 一维数组,长度为矩阵的阶数,返回对称三对角阵的主对角线元素
    2102          * @param dblC - 一维数组,长度为矩阵的阶数,前n-1个元素返回对称三对角阵的
    2103          *               次对角线元素
    2104          * @return bool型,求解是否成功
    2105          */
    2106         public bool MakeSymTri(Matrix mtxQ, Matrix mtxT, double[] dblB, double[] dblC)
    2107         {
    2108             int i, j, k, u;
    2109             double h, f, g, h2;
    2110 
    2111             // 初始化矩阵Q和T
    2112             if (!mtxQ.Init(numColumns, numColumns) ||
    2113                 !mtxT.Init(numColumns, numColumns))
    2114                 return false;
    2115 
    2116             if (dblB == null || dblC == null)
    2117                 return false;
    2118 
    2119             for (i = 0; i <= numColumns - 1; i++)
    2120             {
    2121                 for (j = 0; j <= numColumns - 1; j++)
    2122                 {
    2123                     u = i * numColumns + j;
    2124                     mtxQ.elements[u] = elements[u];
    2125                 }
    2126             }
    2127 
    2128             for (i = numColumns - 1; i >= 1; i--)
    2129             {
    2130                 h = 0.0;
    2131                 if (i > 1)
    2132                 {
    2133                     for (k = 0; k <= i - 1; k++)
    2134                     {
    2135                         u = i * numColumns + k;
    2136                         h = h + mtxQ.elements[u] * mtxQ.elements[u];
    2137                     }
    2138                 }
    2139 
    2140                 if (h == 0.0)
    2141                 {
    2142                     dblC[i] = 0.0;
    2143                     if (i == 1)
    2144                         dblC[i] = mtxQ.elements[i * numColumns + i - 1];
    2145                     dblB[i] = 0.0;
    2146                 }
    2147                 else
    2148                 {
    2149                     dblC[i] = Math.Sqrt(h);
    2150                     u = i * numColumns + i - 1;
    2151                     if (mtxQ.elements[u] > 0.0)
    2152                         dblC[i] = -dblC[i];
    2153 
    2154                     h = h - mtxQ.elements[u] * dblC[i];
    2155                     mtxQ.elements[u] = mtxQ.elements[u] - dblC[i];
    2156                     f = 0.0;
    2157                     for (j = 0; j <= i - 1; j++)
    2158                     {
    2159                         mtxQ.elements[j * numColumns + i] = mtxQ.elements[i * numColumns + j] / h;
    2160                         g = 0.0;
    2161                         for (k = 0; k <= j; k++)
    2162                             g = g + mtxQ.elements[j * numColumns + k] * mtxQ.elements[i * numColumns + k];
    2163 
    2164                         if (j + 1 <= i - 1)
    2165                             for (k = j + 1; k <= i - 1; k++)
    2166                                 g = g + mtxQ.elements[k * numColumns + j] * mtxQ.elements[i * numColumns + k];
    2167 
    2168                         dblC[j] = g / h;
    2169                         f = f + g * mtxQ.elements[j * numColumns + i];
    2170                     }
    2171 
    2172                     h2 = f / (h + h);
    2173                     for (j = 0; j <= i - 1; j++)
    2174                     {
    2175                         f = mtxQ.elements[i * numColumns + j];
    2176                         g = dblC[j] - h2 * f;
    2177                         dblC[j] = g;
    2178                         for (k = 0; k <= j; k++)
    2179                         {
    2180                             u = j * numColumns + k;
    2181                             mtxQ.elements[u] = mtxQ.elements[u] - f * dblC[k] - g * mtxQ.elements[i * numColumns + k];
    2182                         }
    2183                     }
    2184 
    2185                     dblB[i] = h;
    2186                 }
    2187             }
    2188 
    2189             for (i = 0; i <= numColumns - 2; i++)
    2190                 dblC[i] = dblC[i + 1];
    2191 
    2192             dblC[numColumns - 1] = 0.0;
    2193             dblB[0] = 0.0;
    2194             for (i = 0; i <= numColumns - 1; i++)
    2195             {
    2196                 if ((dblB[i] != (double)0.0) && (i - 1 >= 0))
    2197                 {
    2198                     for (j = 0; j <= i - 1; j++)
    2199                     {
    2200                         g = 0.0;
    2201                         for (k = 0; k <= i - 1; k++)
    2202                             g = g + mtxQ.elements[i * numColumns + k] * mtxQ.elements[k * numColumns + j];
    2203 
    2204                         for (k = 0; k <= i - 1; k++)
    2205                         {
    2206                             u = k * numColumns + j;
    2207                             mtxQ.elements[u] = mtxQ.elements[u] - g * mtxQ.elements[k * numColumns + i];
    2208                         }
    2209                     }
    2210                 }
    2211 
    2212                 u = i * numColumns + i;
    2213                 dblB[i] = mtxQ.elements[u]; mtxQ.elements[u] = 1.0;
    2214                 if (i - 1 >= 0)
    2215                 {
    2216                     for (j = 0; j <= i - 1; j++)
    2217                     {
    2218                         mtxQ.elements[i * numColumns + j] = 0.0;
    2219                         mtxQ.elements[j * numColumns + i] = 0.0;
    2220                     }
    2221                 }
    2222             }
    2223 
    2224             // 构造对称三对角矩阵
    2225             for (i = 0; i < numColumns; ++i)
    2226             {
    2227                 for (j = 0; j < numColumns; ++j)
    2228                 {
    2229                     mtxT.SetElement(i, j, 0);
    2230                     k = i - j;
    2231                     if (k == 0)
    2232                         mtxT.SetElement(i, j, dblB[j]);
    2233                     else if (k == 1)
    2234                         mtxT.SetElement(i, j, dblC[j]);
    2235                     else if (k == -1)
    2236                         mtxT.SetElement(i, j, dblC[i]);
    2237                 }
    2238             }
    2239 
    2240             return true;
    2241         }
    2242 
    2243         /**
    2244          * 实对称三对角阵的全部特征值与特征向量的计算
    2245          * 
    2246          * @param dblB - 一维数组,长度为矩阵的阶数,传入对称三对角阵的主对角线元素;
    2247          *                 返回时存放全部特征值。
    2248          * @param dblC - 一维数组,长度为矩阵的阶数,前n-1个元素传入对称三对角阵的
    2249          *               次对角线元素
    2250          * @param mtxQ - 如果传入单位矩阵,则返回实对称三对角阵的特征值向量矩阵;
    2251          *                 如果传入MakeSymTri函数求得的矩阵A的豪斯荷尔德变换的乘积
    2252          *               矩阵Q,则返回矩阵A的特征值向量矩阵。其中第i列为与数组dblB
    2253          *               中第j个特征值对应的特征向量。
    2254          * @param nMaxIt - 迭代次数
    2255          * @param eps - 计算精度
    2256          * @return bool型,求解是否成功
    2257          */
    2258         public bool ComputeEvSymTri(double[] dblB, double[] dblC, Matrix mtxQ, int nMaxIt, double eps)
    2259         {
    2260             int i, j, k, m, it, u, v;
    2261             double d, f, h, g, p, r, e, s;
    2262 
    2263             // 初值
    2264             int n = mtxQ.GetNumColumns();
    2265             dblC[n - 1] = 0.0;
    2266             d = 0.0;
    2267             f = 0.0;
    2268 
    2269             // 迭代计算
    2270 
    2271             for (j = 0; j <= n - 1; j++)
    2272             {
    2273                 it = 0;
    2274                 h = eps * (Math.Abs(dblB[j]) + Math.Abs(dblC[j]));
    2275                 if (h > d)
    2276                     d = h;
    2277 
    2278                 m = j;
    2279                 while ((m <= n - 1) && (Math.Abs(dblC[m]) > d))
    2280                     m = m + 1;
    2281 
    2282                 if (m != j)
    2283                 {
    2284                     do
    2285                     {
    2286                         if (it == nMaxIt)
    2287                             return false;
    2288 
    2289                         it = it + 1;
    2290                         g = dblB[j];
    2291                         p = (dblB[j + 1] - g) / (2.0 * dblC[j]);
    2292                         r = Math.Sqrt(p * p + 1.0);
    2293                         if (p >= 0.0)
    2294                             dblB[j] = dblC[j] / (p + r);
    2295                         else
    2296                             dblB[j] = dblC[j] / (p - r);
    2297 
    2298                         h = g - dblB[j];
    2299                         for (i = j + 1; i <= n - 1; i++)
    2300                             dblB[i] = dblB[i] - h;
    2301 
    2302                         f = f + h;
    2303                         p = dblB[m];
    2304                         e = 1.0;
    2305                         s = 0.0;
    2306                         for (i = m - 1; i >= j; i--)
    2307                         {
    2308                             g = e * dblC[i];
    2309                             h = e * p;
    2310                             if (Math.Abs(p) >= Math.Abs(dblC[i]))
    2311                             {
    2312                                 e = dblC[i] / p;
    2313                                 r = Math.Sqrt(e * e + 1.0);
    2314                                 dblC[i + 1] = s * p * r;
    2315                                 s = e / r;
    2316                                 e = 1.0 / r;
    2317                             }
    2318                             else
    2319                             {
    2320                                 e = p / dblC[i];
    2321                                 r = Math.Sqrt(e * e + 1.0);
    2322                                 dblC[i + 1] = s * dblC[i] * r;
    2323                                 s = 1.0 / r;
    2324                                 e = e / r;
    2325                             }
    2326 
    2327                             p = e * dblB[i] - s * g;
    2328                             dblB[i + 1] = h + s * (e * g + s * dblB[i]);
    2329                             for (k = 0; k <= n - 1; k++)
    2330                             {
    2331                                 u = k * n + i + 1;
    2332                                 v = u - 1;
    2333                                 h = mtxQ.elements[u];
    2334                                 mtxQ.elements[u] = s * mtxQ.elements[v] + e * h;
    2335                                 mtxQ.elements[v] = e * mtxQ.elements[v] - s * h;
    2336                             }
    2337                         }
    2338 
    2339                         dblC[j] = s * p;
    2340                         dblB[j] = e * p;
    2341 
    2342                     } while (Math.Abs(dblC[j]) > d);
    2343                 }
    2344 
    2345                 dblB[j] = dblB[j] + f;
    2346             }
    2347 
    2348             for (i = 0; i <= n - 1; i++)
    2349             {
    2350                 k = i;
    2351                 p = dblB[i];
    2352                 if (i + 1 <= n - 1)
    2353                 {
    2354                     j = i + 1;
    2355                     while ((j <= n - 1) && (dblB[j] <= p))
    2356                     {
    2357                         k = j;
    2358                         p = dblB[j];
    2359                         j = j + 1;
    2360                     }
    2361                 }
    2362 
    2363                 if (k != i)
    2364                 {
    2365                     dblB[k] = dblB[i];
    2366                     dblB[i] = p;
    2367                     for (j = 0; j <= n - 1; j++)
    2368                     {
    2369                         u = j * n + i;
    2370                         v = j * n + k;
    2371                         p = mtxQ.elements[u];
    2372                         mtxQ.elements[u] = mtxQ.elements[v];
    2373                         mtxQ.elements[v] = p;
    2374                     }
    2375                 }
    2376             }
    2377 
    2378             return true;
    2379         }
    2380 
    2381         /**
    2382          * 约化一般实矩阵为赫申伯格矩阵的初等相似变换法
    2383          */
    2384         public void MakeHberg()
    2385         {
    2386             int i = 0, j, k, u, v;
    2387             double d, t;
    2388 
    2389             for (k = 1; k <= numColumns - 2; k++)
    2390             {
    2391                 d = 0.0;
    2392                 for (j = k; j <= numColumns - 1; j++)
    2393                 {
    2394                     u = j * numColumns + k - 1;
    2395                     t = elements[u];
    2396                     if (Math.Abs(t) > Math.Abs(d))
    2397                     {
    2398                         d = t;
    2399                         i = j;
    2400                     }
    2401                 }
    2402 
    2403                 if (d != 0.0)
    2404                 {
    2405                     if (i != k)
    2406                     {
    2407                         for (j = k - 1; j <= numColumns - 1; j++)
    2408                         {
    2409                             u = i * numColumns + j;
    2410                             v = k * numColumns + j;
    2411                             t = elements[u];
    2412                             elements[u] = elements[v];
    2413                             elements[v] = t;
    2414                         }
    2415 
    2416                         for (j = 0; j <= numColumns - 1; j++)
    2417                         {
    2418                             u = j * numColumns + i;
    2419                             v = j * numColumns + k;
    2420                             t = elements[u];
    2421                             elements[u] = elements[v];
    2422                             elements[v] = t;
    2423                         }
    2424                     }
    2425 
    2426                     for (i = k + 1; i <= numColumns - 1; i++)
    2427                     {
    2428                         u = i * numColumns + k - 1;
    2429                         t = elements[u] / d;
    2430                         elements[u] = 0.0;
    2431                         for (j = k; j <= numColumns - 1; j++)
    2432                         {
    2433                             v = i * numColumns + j;
    2434                             elements[v] = elements[v] - t * elements[k * numColumns + j];
    2435                         }
    2436 
    2437                         for (j = 0; j <= numColumns - 1; j++)
    2438                         {
    2439                             v = j * numColumns + k;
    2440                             elements[v] = elements[v] + t * elements[j * numColumns + i];
    2441                         }
    2442                     }
    2443                 }
    2444             }
    2445         }
    2446 
    2447         /**
    2448          * 求赫申伯格矩阵全部特征值的QR方法
    2449          * 
    2450          * @param dblU - 一维数组,长度为矩阵的阶数,返回时存放特征值的实部
    2451          * @param dblV - 一维数组,长度为矩阵的阶数,返回时存放特征值的虚部
    2452          * @param nMaxIt - 迭代次数
    2453          * @param eps - 计算精度
    2454          * @return bool型,求解是否成功
    2455          */
    2456         public bool ComputeEvHBerg(double[] dblU, double[] dblV, int nMaxIt, double eps)
    2457         {
    2458             int m, it, i, j, k, l, ii, jj, kk, ll;
    2459             double b, c, w, g, xy, p, q, r, x, s, e, f, z, y;
    2460 
    2461             int n = numColumns;
    2462 
    2463             it = 0;
    2464             m = n;
    2465             while (m != 0)
    2466             {
    2467                 l = m - 1;
    2468                 while ((l > 0) && (Math.Abs(elements[l * n + l - 1]) >
    2469                     eps * (Math.Abs(elements[(l - 1) * n + l - 1]) + Math.Abs(elements[l * n + l]))))
    2470                     l = l - 1;
    2471 
    2472                 ii = (m - 1) * n + m - 1;
    2473                 jj = (m - 1) * n + m - 2;
    2474                 kk = (m - 2) * n + m - 1;
    2475                 ll = (m - 2) * n + m - 2;
    2476                 if (l == m - 1)
    2477                 {
    2478                     dblU[m - 1] = elements[(m - 1) * n + m - 1];
    2479                     dblV[m - 1] = 0.0;
    2480                     m = m - 1;
    2481                     it = 0;
    2482                 }
    2483                 else if (l == m - 2)
    2484                 {
    2485                     b = -(elements[ii] + elements[ll]);
    2486                     c = elements[ii] * elements[ll] - elements[jj] * elements[kk];
    2487                     w = b * b - 4.0 * c;
    2488                     y = Math.Sqrt(Math.Abs(w));
    2489                     if (w > 0.0)
    2490                     {
    2491                         xy = 1.0;
    2492                         if (b < 0.0)
    2493                             xy = -1.0;
    2494                         dblU[m - 1] = (-b - xy * y) / 2.0;
    2495                         dblU[m - 2] = c / dblU[m - 1];
    2496                         dblV[m - 1] = 0.0; dblV[m - 2] = 0.0;
    2497                     }
    2498                     else
    2499                     {
    2500                         dblU[m - 1] = -b / 2.0;
    2501                         dblU[m - 2] = dblU[m - 1];
    2502                         dblV[m - 1] = y / 2.0;
    2503                         dblV[m - 2] = -dblV[m - 1];
    2504                     }
    2505 
    2506                     m = m - 2;
    2507                     it = 0;
    2508                 }
    2509                 else
    2510                 {
    2511                     if (it >= nMaxIt)
    2512                         return false;
    2513 
    2514                     it = it + 1;
    2515                     for (j = l + 2; j <= m - 1; j++)
    2516                         elements[j * n + j - 2] = 0.0;
    2517                     for (j = l + 3; j <= m - 1; j++)
    2518                         elements[j * n + j - 3] = 0.0;
    2519                     for (k = l; k <= m - 2; k++)
    2520                     {
    2521                         if (k != l)
    2522                         {
    2523                             p = elements[k * n + k - 1];
    2524                             q = elements[(k + 1) * n + k - 1];
    2525                             r = 0.0;
    2526                             if (k != m - 2)
    2527                                 r = elements[(k + 2) * n + k - 1];
    2528                         }
    2529                         else
    2530                         {
    2531                             x = elements[ii] + elements[ll];
    2532                             y = elements[ll] * elements[ii] - elements[kk] * elements[jj];
    2533                             ii = l * n + l;
    2534                             jj = l * n + l + 1;
    2535                             kk = (l + 1) * n + l;
    2536                             ll = (l + 1) * n + l + 1;
    2537                             p = elements[ii] * (elements[ii] - x) + elements[jj] * elements[kk] + y;
    2538                             q = elements[kk] * (elements[ii] + elements[ll] - x);
    2539                             r = elements[kk] * elements[(l + 2) * n + l + 1];
    2540                         }
    2541 
    2542                         if ((Math.Abs(p) + Math.Abs(q) + Math.Abs(r)) != 0.0)
    2543                         {
    2544                             xy = 1.0;
    2545                             if (p < 0.0)
    2546                                 xy = -1.0;
    2547                             s = xy * Math.Sqrt(p * p + q * q + r * r);
    2548                             if (k != l)
    2549                                 elements[k * n + k - 1] = -s;
    2550                             e = -q / s;
    2551                             f = -r / s;
    2552                             x = -p / s;
    2553                             y = -x - f * r / (p + s);
    2554                             g = e * r / (p + s);
    2555                             z = -x - e * q / (p + s);
    2556                             for (j = k; j <= m - 1; j++)
    2557                             {
    2558                                 ii = k * n + j;
    2559                                 jj = (k + 1) * n + j;
    2560                                 p = x * elements[ii] + e * elements[jj];
    2561                                 q = e * elements[ii] + y * elements[jj];
    2562                                 r = f * elements[ii] + g * elements[jj];
    2563                                 if (k != m - 2)
    2564                                 {
    2565                                     kk = (k + 2) * n + j;
    2566                                     p = p + f * elements[kk];
    2567                                     q = q + g * elements[kk];
    2568                                     r = r + z * elements[kk];
    2569                                     elements[kk] = r;
    2570                                 }
    2571 
    2572                                 elements[jj] = q; elements[ii] = p;
    2573                             }
    2574 
    2575                             j = k + 3;
    2576                             if (j >= m - 1)
    2577                                 j = m - 1;
    2578 
    2579                             for (i = l; i <= j; i++)
    2580                             {
    2581                                 ii = i * n + k;
    2582                                 jj = i * n + k + 1;
    2583                                 p = x * elements[ii] + e * elements[jj];
    2584                                 q = e * elements[ii] + y * elements[jj];
    2585                                 r = f * elements[ii] + g * elements[jj];
    2586                                 if (k != m - 2)
    2587                                 {
    2588                                     kk = i * n + k + 2;
    2589                                     p = p + f * elements[kk];
    2590                                     q = q + g * elements[kk];
    2591                                     r = r + z * elements[kk];
    2592                                     elements[kk] = r;
    2593                                 }
    2594 
    2595                                 elements[jj] = q;
    2596                                 elements[ii] = p;
    2597                             }
    2598                         }
    2599                     }
    2600                 }
    2601             }
    2602 
    2603             return true;
    2604         }
    2605 
    2606         /**
    2607          * 求实对称矩阵特征值与特征向量的雅可比法
    2608          * 
    2609          * @param dblEigenValue - 一维数组,长度为矩阵的阶数,返回时存放特征值
    2610          * @param mtxEigenVector - 返回时存放特征向量矩阵,其中第i列为与数组
    2611          *                         dblEigenValue中第j个特征值对应的特征向量
    2612          * @param nMaxIt - 迭代次数
    2613          * @param eps - 计算精度
    2614          * @return bool型,求解是否成功
    2615          */
    2616         public bool ComputeEvJacobi(double[] dblEigenValue, Matrix mtxEigenVector, int nMaxIt, double eps)
    2617         {
    2618             int i, j, p = 0, q = 0, u, w, t, s, l;
    2619             double fm, cn, sn, omega, x, y, d;
    2620 
    2621             if (!mtxEigenVector.Init(numColumns, numColumns))
    2622                 return false;
    2623 
    2624             l = 1;
    2625             for (i = 0; i <= numColumns - 1; i++)
    2626             {
    2627                 mtxEigenVector.elements[i * numColumns + i] = 1.0;
    2628                 for (j = 0; j <= numColumns - 1; j++)
    2629                     if (i != j)
    2630                         mtxEigenVector.elements[i * numColumns + j] = 0.0;
    2631             }
    2632 
    2633             while (true)
    2634             {
    2635                 fm = 0.0;
    2636                 for (i = 1; i <= numColumns - 1; i++)
    2637                 {
    2638                     for (j = 0; j <= i - 1; j++)
    2639                     {
    2640                         d = Math.Abs(elements[i * numColumns + j]);
    2641                         if ((i != j) && (d > fm))
    2642                         {
    2643                             fm = d;
    2644                             p = i;
    2645                             q = j;
    2646                         }
    2647                     }
    2648                 }
    2649 
    2650                 if (fm < eps)
    2651                 {
    2652                     for (i = 0; i < numColumns; ++i)
    2653                         dblEigenValue[i] = GetElement(i, i);
    2654                     return true;
    2655                 }
    2656 
    2657                 if (l > nMaxIt)
    2658                     return false;
    2659 
    2660                 l = l + 1;
    2661                 u = p * numColumns + q;
    2662                 w = p * numColumns + p;
    2663                 t = q * numColumns + p;
    2664                 s = q * numColumns + q;
    2665                 x = -elements[u];
    2666                 y = (elements[s] - elements[w]) / 2.0;
    2667                 omega = x / Math.Sqrt(x * x + y * y);
    2668 
    2669                 if (y < 0.0)
    2670                     omega = -omega;
    2671 
    2672                 sn = 1.0 + Math.Sqrt(1.0 - omega * omega);
    2673                 sn = omega / Math.Sqrt(2.0 * sn);
    2674                 cn = Math.Sqrt(1.0 - sn * sn);
    2675                 fm = elements[w];
    2676                 elements[w] = fm * cn * cn + elements[s] * sn * sn + elements[u] * omega;
    2677                 elements[s] = fm * sn * sn + elements[s] * cn * cn - elements[u] * omega;
    2678                 elements[u] = 0.0;
    2679                 elements[t] = 0.0;
    2680                 for (j = 0; j <= numColumns - 1; j++)
    2681                 {
    2682                     if ((j != p) && (j != q))
    2683                     {
    2684                         u = p * numColumns + j; w = q * numColumns + j;
    2685                         fm = elements[u];
    2686                         elements[u] = fm * cn + elements[w] * sn;
    2687                         elements[w] = -fm * sn + elements[w] * cn;
    2688                     }
    2689                 }
    2690 
    2691                 for (i = 0; i <= numColumns - 1; i++)
    2692                 {
    2693                     if ((i != p) && (i != q))
    2694                     {
    2695                         u = i * numColumns + p;
    2696                         w = i * numColumns + q;
    2697                         fm = elements[u];
    2698                         elements[u] = fm * cn + elements[w] * sn;
    2699                         elements[w] = -fm * sn + elements[w] * cn;
    2700                     }
    2701                 }
    2702 
    2703                 for (i = 0; i <= numColumns - 1; i++)
    2704                 {
    2705                     u = i * numColumns + p;
    2706                     w = i * numColumns + q;
    2707                     fm = mtxEigenVector.elements[u];
    2708                     mtxEigenVector.elements[u] = fm * cn + mtxEigenVector.elements[w] * sn;
    2709                     mtxEigenVector.elements[w] = -fm * sn + mtxEigenVector.elements[w] * cn;
    2710                 }
    2711             }
    2712         }
    2713 
    2714         /**
    2715          * 求实对称矩阵特征值与特征向量的雅可比过关法
    2716          * 
    2717          * @param dblEigenValue - 一维数组,长度为矩阵的阶数,返回时存放特征值
    2718          * @param mtxEigenVector - 返回时存放特征向量矩阵,其中第i列为与数组
    2719          *                         dblEigenValue中第j个特征值对应的特征向量
    2720          * @param eps - 计算精度
    2721          * @return bool型,求解是否成功
    2722          */
    2723         public bool ComputeEvJacobi(double[] dblEigenValue, Matrix mtxEigenVector, double eps)
    2724         {
    2725             int i, j, p, q, u, w, t, s;
    2726             double ff, fm, cn, sn, omega, x, y, d;
    2727 
    2728             if (!mtxEigenVector.Init(numColumns, numColumns))
    2729                 return false;
    2730 
    2731             for (i = 0; i <= numColumns - 1; i++)
    2732             {
    2733                 mtxEigenVector.elements[i * numColumns + i] = 1.0;
    2734                 for (j = 0; j <= numColumns - 1; j++)
    2735                     if (i != j)
    2736                         mtxEigenVector.elements[i * numColumns + j] = 0.0;
    2737             }
    2738 
    2739             ff = 0.0;
    2740             for (i = 1; i <= numColumns - 1; i++)
    2741             {
    2742                 for (j = 0; j <= i - 1; j++)
    2743                 {
    2744                     d = elements[i * numColumns + j];
    2745                     ff = ff + d * d;
    2746                 }
    2747             }
    2748 
    2749             ff = Math.Sqrt(2.0 * ff);
    2750             ff = ff / (1.0 * numColumns);
    2751 
    2752             bool nextLoop = false;
    2753             while (true)
    2754             {
    2755                 for (i = 1; i <= numColumns - 1; i++)
    2756                 {
    2757                     for (j = 0; j <= i - 1; j++)
    2758                     {
    2759                         d = Math.Abs(elements[i * numColumns + j]);
    2760                         if (d > ff)
    2761                         {
    2762                             p = i;
    2763                             q = j;
    2764 
    2765                             u = p * numColumns + q;
    2766                             w = p * numColumns + p;
    2767                             t = q * numColumns + p;
    2768                             s = q * numColumns + q;
    2769                             x = -elements[u];
    2770                             y = (elements[s] - elements[w]) / 2.0;
    2771                             omega = x / Math.Sqrt(x * x + y * y);
    2772                             if (y < 0.0)
    2773                                 omega = -omega;
    2774 
    2775                             sn = 1.0 + Math.Sqrt(1.0 - omega * omega);
    2776                             sn = omega / Math.Sqrt(2.0 * sn);
    2777                             cn = Math.Sqrt(1.0 - sn * sn);
    2778                             fm = elements[w];
    2779                             elements[w] = fm * cn * cn + elements[s] * sn * sn + elements[u] * omega;
    2780                             elements[s] = fm * sn * sn + elements[s] * cn * cn - elements[u] * omega;
    2781                             elements[u] = 0.0; elements[t] = 0.0;
    2782 
    2783                             for (j = 0; j <= numColumns - 1; j++)
    2784                             {
    2785                                 if ((j != p) && (j != q))
    2786                                 {
    2787                                     u = p * numColumns + j;
    2788                                     w = q * numColumns + j;
    2789                                     fm = elements[u];
    2790                                     elements[u] = fm * cn + elements[w] * sn;
    2791                                     elements[w] = -fm * sn + elements[w] * cn;
    2792                                 }
    2793                             }
    2794 
    2795                             for (i = 0; i <= numColumns - 1; i++)
    2796                             {
    2797                                 if ((i != p) && (i != q))
    2798                                 {
    2799                                     u = i * numColumns + p;
    2800                                     w = i * numColumns + q;
    2801                                     fm = elements[u];
    2802                                     elements[u] = fm * cn + elements[w] * sn;
    2803                                     elements[w] = -fm * sn + elements[w] * cn;
    2804                                 }
    2805                             }
    2806 
    2807                             for (i = 0; i <= numColumns - 1; i++)
    2808                             {
    2809                                 u = i * numColumns + p;
    2810                                 w = i * numColumns + q;
    2811                                 fm = mtxEigenVector.elements[u];
    2812                                 mtxEigenVector.elements[u] = fm * cn + mtxEigenVector.elements[w] * sn;
    2813                                 mtxEigenVector.elements[w] = -fm * sn + mtxEigenVector.elements[w] * cn;
    2814                             }
    2815 
    2816                             nextLoop = true;
    2817                             break;
    2818                         }
    2819                     }
    2820 
    2821                     if (nextLoop)
    2822                         break;
    2823                 }
    2824 
    2825                 if (nextLoop)
    2826                 {
    2827                     nextLoop = false;
    2828                     continue;
    2829                 }
    2830 
    2831                 nextLoop = false;
    2832 
    2833                 // 如果达到精度要求,退出循环,返回结果
    2834                 if (ff < eps)
    2835                 {
    2836                     for (i = 0; i < numColumns; ++i)
    2837                         dblEigenValue[i] = GetElement(i, i);
    2838                     return true;
    2839                 }
    2840 
    2841                 ff = ff / (1.0 * numColumns);
    2842             }
    2843         }
    2844 
    2845 
    2846 
    2847 
    2848     }
    2849 }
    文章未经说明均属原创,学习笔记可能有大段的引用,一般会注明参考文献。 欢迎大家留言交流,转载请注明出处。
  • 相关阅读:
    【HDU5015】233 Matrix
    【POJ3233】Matrix Power Series
    【POJ3070】Fibonacci
    【NOIP模拟】奇怪的字符串
    【NOIP模拟】超级跳棋
    【NOIP模拟】玛雅文字
    【NOIP模拟】距离
    【闲聊】关于本BLOG
    【NOIP模拟】树
    【NOIP模拟】机器人
  • 原文地址:https://www.cnblogs.com/yhlx125/p/2425566.html
Copyright © 2011-2022 走看看