using System;
namespace Zhou.CSharp.Algorithm
{
/// <summary>
/// 矩阵类
/// 作者:周长发
/// 改进:深度混淆
/// https://blog.csdn.net/beijinghorn
/// </summary>
public partial class Matrix
{
/// <summary>
/// 约化对称矩阵为对称三对角阵的豪斯荷尔德Householder变换法
/// </summary>
/// <param name="src">源矩阵</param>
/// <param name="mtxQ">豪斯荷尔德变换的乘积矩阵Q</param>
/// <param name="mtxT">求得的对称三对角阵</param>
/// <param name="dblB">一维数组,长度为矩阵的阶数,返回对称三对角阵的主对角线元素</param>
/// <param name="dblC">一维数组,长度为矩阵的阶数,前n-1个元素返回对称三对角阵的</param>
/// <returns>求解是否成功</returns>
public static bool MakeSymTri(Matrix src, Matrix mtxQ, Matrix mtxT, double[] dblB, double[] dblC)
{
int i, j, k, u;
double h, f, g, h2;
// 初始化矩阵Q和T
if (mtxQ.Init(src.Columns, src.Columns) == false || mtxT.Init(src.Columns, src.Columns) == false)
{
return false;
}
if (dblB == null || dblC == null)
{
return false;
}
for (i = 0; i <= src.Columns - 1; i++)
{
for (j = 0; j <= src.Columns - 1; j++)
{
u = i * src.Columns + j;
mtxQ[u] = src[u];
}
}
for (i = src.Columns - 1; i >= 1; i--)
{
h = 0.0;
if (i > 1)
{
for (k = 0; k <= i - 1; k++)
{
u = i * src.Columns + k;
h = h + mtxQ[u] * mtxQ[u];
}
}
if (Math.Abs(h) < float.Epsilon)
{
dblC[i] = 0.0;
if (i == 1)
{
dblC[i] = mtxQ[i * src.Columns + i - 1];
}
dblB[i] = 0.0;
}
else
{
dblC[i] = Math.Sqrt(h);
u = i * src.Columns + i - 1;
if (mtxQ[u] > 0.0)
{
dblC[i] = -dblC[i];
}
h = h - mtxQ[u] * dblC[i];
mtxQ[u] = mtxQ[u] - dblC[i];
f = 0.0;
for (j = 0; j <= i - 1; j++)
{
mtxQ[j * src.Columns + i] = mtxQ[i * src.Columns + j] / h;
g = 0.0;
for (k = 0; k <= j; k++)
{
g = g + mtxQ[j * src.Columns + k] * mtxQ[i * src.Columns + k];
}
if (j + 1 <= i - 1)
{
for (k = j + 1; k <= i - 1; k++)
{
g = g + mtxQ[k * src.Columns + j] * mtxQ[i * src.Columns + k];
}
}
dblC[j] = g / h;
f = f + g * mtxQ[j * src.Columns + i];
}
h2 = f / (h + h);
for (j = 0; j <= i - 1; j++)
{
f = mtxQ[i * src.Columns + j];
g = dblC[j] - h2 * f;
dblC[j] = g;
for (k = 0; k <= j; k++)
{
u = j * src.Columns + k;
mtxQ[u] = mtxQ[u] - f * dblC[k] - g * mtxQ[i * src.Columns + k];
}
}
dblB[i] = h;
}
}
for (i = 0; i <= src.Columns - 2; i++)
{
dblC[i] = dblC[i + 1];
}
dblC[src.Columns - 1] = 0.0;
dblB[0] = 0.0;
for (i = 0; i <= src.Columns - 1; i++)
{
if ((dblB[i] != (double)0.0) && (i - 1 >= 0))
{
for (j = 0; j <= i - 1; j++)
{
g = 0.0;
for (k = 0; k <= i - 1; k++)
{
g = g + mtxQ[i * src.Columns + k] * mtxQ[k * src.Columns + j];
}
for (k = 0; k <= i - 1; k++)
{
u = k * src.Columns + j;
mtxQ[u] = mtxQ[u] - g * mtxQ[k * src.Columns + i];
}
}
}
u = i * src.Columns + i;
dblB[i] = mtxQ[u]; mtxQ[u] = 1.0;
if (i - 1 >= 0)
{
for (j = 0; j <= i - 1; j++)
{
mtxQ[i * src.Columns + j] = 0.0;
mtxQ[j * src.Columns + i] = 0.0;
}
}
}
// 构造对称三对角矩阵
for (i = 0; i < src.Columns; ++i)
{
for (j = 0; j < src.Columns; ++j)
{
mtxT.SetElement(i, j, 0);
k = i - j;
if (k == 0)
{
mtxT.SetElement(i, j, dblB[j]);
}
else if (k == 1)
{
mtxT.SetElement(i, j, dblC[j]);
}
else if (k == -1)
{
mtxT.SetElement(i, j, dblC[i]);
}
}
}
return true;
}
}
}