仿射变换的一个练习题!

问题:已知坐标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 }
文章未经说明均属原创,学习笔记可能有大段的引用,一般会注明参考文献。 欢迎大家留言交流,转载请注明出处。
原文地址:https://www.cnblogs.com/yhlx125/p/2425566.html