/*
 * @Description: 电量采集模块-svc层-矩阵计算子模块
 * @Author: yangsw
 * @Date: 2021-06-08 09:42:17
 * @LastEditTime: 2021-06-25 09:36:13
 * @LastEditors: yangsw
 * @Reference:
 */
#include "svc_bat_matrix.h"
#include "stdio.h"
#include "../../log/svc/svc_log.h"

/**
 * @brief: 按第一行展开计算A的行列式|A|
 * @return {double} A的行列式
 * @note:
 * @see:
 * @param {double} arcs 待求矩阵，DEGREE为矩阵阶数
 * @param {matInt32} n 待求矩阵阶数
 */
double getA(double arcs[DEGREE][DEGREE], matInt32 n) // 按第一行展开计算|A|
{
    if (n == 1)
    {
        return arcs[0][0];
    }
    double ans = 0;
    double temp[DEGREE][DEGREE];
    matInt32 i, j, k;
    for (i = 0; i < n; i++)
    {
        for (j = 0; j < n - 1; j++)
        {
            for (k = 0; k < n - 1; k++)
            {
                temp[j][k] = arcs[j + 1][(k >= i) ? k + 1 : k];
            }
        }
        double t = getA(temp, n - 1);
        if (i % 2 == 0)
        {
            ans += arcs[0][i] * t;
        }
        else
        {
            ans -= arcs[0][i] * t;
        }
    }
    return ans;
}

/**
 * @brief: 计算每一行每一列的每个元素所对应的代数余子式，组成伴随矩阵A*
 * @return {void}
 * @note:
 * @see:
 * @param {double} arcs 输入矩阵
 * @param {int} n   矩阵阶数
 * @param {double} ans 输出伴随矩阵A*
 */
void getAStart(double arcs[DEGREE][DEGREE], int n, double ans[DEGREE][DEGREE])
{
    if (n == 1)
    {
        ans[0][0] = 1;
        return;
    }
    matInt32 i, j, k, t;
    double temp[DEGREE][DEGREE];
    for (i = 0; i < n; i++)
    {
        for (j = 0; j < n; j++)
        {
            for (k = 0; k < n - 1; k++)
            {
                for (t = 0; t < n - 1; t++)
                {
                    temp[k][t] = arcs[k >= i ? k + 1 : k][t >= j ? t + 1 : t];
                }
            }

            ans[j][i] = getA(temp, n - 1);
            if ((i + j) % 2 == 1)
            {
                ans[j][i] = -ans[j][i];
            }
        }
    }
}

/**
 * @brief: 计算A的逆矩阵
 * @return {void}
 * @note: A-1=A*除于|A|     A的逆矩阵=A的伴随矩阵/A的行列式
 * 由于怕精度丢失，这里的所求的逆矩阵并没有除于A的行列式|A|，所以实际输出的是伴随矩阵A*
 * @see:
 * @param {double} arcs 输入矩阵A
 * @param {double} astar A的逆矩阵A-1
 * @param {matInt32} n 矩阵阶数
 */
double getInverseMatrix(double arcs[DEGREE][DEGREE], double astar[DEGREE][DEGREE], matInt32 n) //
{
    matInt32 i, j;
    double a = getA(arcs, n);
    if (a == 0)
    {
        Svc_Log_Printf(LOG_ERROR, "can not transform!\n");
    }
    else
    {
        getAStart(arcs, n, astar);
    }
    return a;
}