using System;
namespace Zhou.CSharp.Algorithm
{
/// <summary>
/// 求解线性方程组的类 LEquations
/// 原作 周长发
/// 改编 深度混淆
/// </summary>
public static partial class LEquations
{
/// <summary>
/// 复系数方程组的全选主元高斯消去法
/// </summary>
/// <param name="mtxLECoef">指定的系数矩阵</param>
/// <param name="mtxLEConst">指定的常数矩阵</param>
/// <param name="mtxCoefImag">系数矩阵的虚部矩阵</param>
/// <param name="mtxConstImag">常数矩阵的虚部矩阵</param>
/// <param name="mtxResult">Matrix对象,返回方程组解矩阵的实部矩阵</param>
/// <param name="mtxResultImag">Matrix对象,返回方程组解矩阵的虚部矩阵</param>
/// <return>bool 型,方程组求解是否成功</return>
public static bool GetRootsetGauss(Matrix mtxLECoef, Matrix mtxLEConst, Matrix mtxCoefImag, Matrix mtxConstImag, Matrix mtxResult, Matrix mtxResultImag)
{
int r, k, i, j, nIs = 0, u, v;
double p, q, s, d;
// 方程组的属性,将常数矩阵赋给解矩阵
mtxResult.SetValue(mtxLEConst);
mtxResultImag.SetValue(mtxConstImag);
double[] pDataCoef = mtxLECoef.GetData();
double[] pDataConst = mtxResult.GetData();
double[] pDataCoefImag = mtxCoefImag.GetData();
double[] pDataConstImag = mtxResultImag.GetData();
int n = mtxLECoef.GetNumColumns();
int m = mtxLEConst.GetNumColumns();
// 临时缓冲区,存放变换的列数
int[] pnJs = new int[n];
// 消元
for (k = 0; k <= n - 2; k++)
{
d = 0.0;
for (i = k; i <= n - 1; i++)
{
for (j = k; j <= n - 1; j++)
{
u = i * n + j;
p = pDataCoef[u] * pDataCoef[u] + pDataCoefImag[u] * pDataCoefImag[u];
if (p > d)
{
d = p;
pnJs[k] = j;
nIs = i;
}
}
}
// 求解失败
if (Math.Abs(d) < float.Epsilon)// d == 0.0)
{
return false;
}
if (nIs != k)
{
for (j = k; j <= n - 1; j++)
{
u = k * n + j;
v = nIs * n + j;
p = pDataCoef[u];
pDataCoef[u] = pDataCoef[v];
pDataCoef[v] = p;
p = pDataCoefImag[u];
pDataCoefImag[u] = pDataCoefImag[v];
pDataCoefImag[v] = p;
}
p = pDataConst[k];
pDataConst[k] = pDataConst[nIs];
pDataConst[nIs] = p;
p = pDataConstImag[k];
pDataConstImag[k] = pDataConstImag[nIs];
pDataConstImag[nIs] = p;
}
if (pnJs[k] != k)
{
for (i = 0; i <= n - 1; i++)
{
u = i * n + k;
v = i * n + pnJs[k];
p = pDataCoef[u];
pDataCoef[u] = pDataCoef[v];
pDataCoef[v] = p;
p = pDataCoefImag[u];
pDataCoefImag[u] = pDataCoefImag[v];
pDataCoefImag[v] = p;
}
}
v = k * n + k;
for (j = k + 1; j <= n - 1; j++)
{
u = k * n + j;
p = pDataCoef[u] * pDataCoef[v];
q = -pDataCoefImag[u] * pDataCoefImag[v];
s = (pDataCoef[v] - pDataCoefImag[v]) * (pDataCoef[u] + pDataCoefImag[u]);
pDataCoef[u] = (p - q) / d;
pDataCoefImag[u] = (s - p - q) / d;
}
p = pDataConst[k] * pDataCoef[v];
q = -pDataConstImag[k] * pDataCoefImag[v];
s = (pDataCoef[v] - pDataCoefImag[v]) * (pDataConst[k] + pDataConstImag[k]);
pDataConst[k] = (p - q) / d;
pDataConstImag[k] = (s - p - q) / d;
for (i = k + 1; i <= n - 1; i++)
{
u = i * n + k;
for (j = k + 1; j <= n - 1; j++)
{
v = k * n + j;
r = i * n + j;
p = pDataCoef[u] * pDataCoef[v];
q = pDataCoefImag[u] * pDataCoefImag[v];
s = (pDataCoef[u] + pDataCoefImag[u]) * (pDataCoef[v] + pDataCoefImag[v]);
pDataCoef[u] = pDataCoef[u] - p + q;
pDataCoefImag[u] = pDataCoefImag[u] - s + p + q;
}
p = pDataCoef[u] * pDataConst[k];
q = pDataCoefImag[u] * pDataConstImag[k];
s = (pDataCoef[u] + pDataCoefImag[u]) * (pDataConst[k] + pDataConstImag[k]);
pDataConst[i] = pDataConst[i] - p + q;
pDataConstImag[i] = pDataConstImag[i] - s + p + q;
}
}
u = (n - 1) * n + n - 1;
d = pDataCoef[u] * pDataCoef[u] + pDataCoefImag[u] * pDataCoefImag[u];
// 求解失败
if (Math.Abs(d) < float.Epsilon)// d == 0.0)
{
return false;
}
// 求解
p = pDataCoef[u] * pDataConst[n - 1]; q = -pDataCoefImag[u] * pDataConstImag[n - 1];
s = (pDataCoef[u] - pDataCoefImag[u]) * (pDataConst[n - 1] + pDataConstImag[n - 1]);
pDataConst[n - 1] = (p - q) / d; pDataConstImag[n - 1] = (s - p - q) / d;
for (i = n - 2; i >= 0; i--)
{
for (j = i + 1; j <= n - 1; j++)
{
u = i * n + j;
p = pDataCoef[u] * pDataConst[j];
q = pDataCoefImag[u] * pDataConstImag[j];
s = (pDataCoef[u] + pDataCoefImag[u]) * (pDataConst[j] + pDataConstImag[j]);
pDataConst[i] = pDataConst[i] - p + q;
pDataConstImag[i] = pDataConstImag[i] - s + p + q;
}
}
// 调整位置
pnJs[n - 1] = n - 1;
for (k = n - 1; k >= 0; k--)
{
if (pnJs[k] != k)
{
p = pDataConst[k];
pDataConst[k] = pDataConst[pnJs[k]];
pDataConst[pnJs[k]] = p;
p = pDataConstImag[k];
pDataConstImag[k] = pDataConstImag[pnJs[k]];
pDataConstImag[pnJs[k]] = p;
}
}
return true;
}
}
}