📄 gauss_elimination.cpp
字号:
#include <hk_math/vecmath.h>
#include <hk_math/gauss_elimination/gauss_elimination.h>
#include <hk_math/vector_fpu/vector_fpu.h>
// add factor * line number j to line number i (j=first i=second)
// the matrix-entries left of j in both lines are zero
void hk_Gauss_Elm_Solver::add_multiple_line(int first,int second,hk_gauss_real factor)
{
hk_gauss_real *first_line=&m_A[first * this->m_aligned_row_len + first];
hk_gauss_real *second_line=&m_A[second * this->m_aligned_row_len + first];
hk_VecFPU::fpu_add_multiple_row(second_line,first_line,factor,m_n_columns-first,HK_FALSE);
m_b[second]+=m_b[first] * factor;
}
hk_result hk_Gauss_Elm_Solver::solve_gauss_elemination( hk_Gauss_Elm_Input &inp, hk_Gauss_Elm_Output &outp) {
m_A=inp.m_A;
m_b=inp.m_b;
m_n_columns=inp.m_n_columns;
m_aligned_row_len=inp.m_aligned_row_len;
m_result=outp.m_result;
transform_to_lower_null_triangle();
hk_result res=solve_lower_null_matrix();
return res;
}
void hk_Gauss_Elm_Solver::find_pivot_in_column(int col)
{
hk_gauss_real best_val = hk_Math::fabsd(m_A[col*m_aligned_row_len+col]);
int pos=-1;
for(int i=m_n_columns-1;i > col;i--) {
hk_gauss_real h=m_A[i*m_aligned_row_len+col];
if( hk_Math::fabsd(h) > best_val ) {
best_val = hk_Math::fabsd(h);
pos=i;
}
}
if(pos>=0) {
exchange_rows(col,pos);
}
}
//optimization: when called from transform_to_lower_null_triangle, begin by 'a' (first values are 0.0f)
void hk_Gauss_Elm_Solver::exchange_rows(int a,int b)
{
hk_gauss_real h;
#if 0 /* without Vector FPU */
for(int i=m_n_columns-1;i>=0;i--) {
h=m_A[a*m_aligned_row_len+i];
m_A[a*m_aligned_row_len+i]=m_A[b*m_aligned_row_len+i];
m_A[b*m_aligned_row_len+i]=h;
}
#endif
hk_VecFPU::fpu_exchange_rows(&m_A[b*m_aligned_row_len],&m_A[a*m_aligned_row_len],m_n_columns,HK_TRUE);
h=m_b[a];
m_b[a]=m_b[b];
m_b[b]=h;
}
// solve with Gauss-Algo. : upper triangle matrix with nulls in lower part
void hk_Gauss_Elm_Solver::transform_to_lower_null_triangle()
{
//matrix_out_before_gauss();
int i,j;
//j is counting m_n_columns, i is counting lines
//walk through m_n_columns
for(j=0;j<m_n_columns;j++)
{
hk_gauss_real diagonal_elem,negativ_inv_diagonal;
#if 0
//not always pivot search
diagonal_elem=m_A[j*m_aligned_row_len+j];
if(hk_Math::fabs(diagonal_elem)<hk_GAUSS_ELM_EPS) {
find_pivot_in_column(j);
diagonal_elem=m_A[j*m_aligned_row_len+j];
if(hk_Math::fabs(diagonal_elem)<hk_GAUSS_ELM_EPS) {
goto column_done;
}
}
#endif
//always pivot search
find_pivot_in_column(j);
diagonal_elem=m_A[j*m_aligned_row_len+j];
if(hk_Math::fabsd(diagonal_elem)<m_gauss_eps) {
goto column_done;
}
negativ_inv_diagonal=-1.0f/diagonal_elem;
//walk through lines
for(i=j+1;i<m_n_columns;i++)
{
hk_gauss_real col_down_elem=m_A[i*m_aligned_row_len+j];
if(hk_Math::fabsd(col_down_elem)>m_gauss_eps)
{
add_multiple_line(j,i,col_down_elem*negativ_inv_diagonal);
}
}
column_done: ;
}
}
// matrix values are in upper triangle form, solve from bottom to top
hk_result hk_Gauss_Elm_Solver::solve_lower_null_matrix()
{
int i;
for(i=m_n_columns-1;i>=0;i--)
{
hk_gauss_real *pointer_in_line=&m_A[i*m_aligned_row_len+m_n_columns-1];
hk_gauss_real right_side=m_b[i];
for(int j=m_n_columns-1;j>i;j--)
{
right_side -= m_b[j] * *pointer_in_line;
pointer_in_line--;
}
hk_gauss_real left_side=*pointer_in_line;
if(hk_Math::fabsd(left_side) < m_gauss_eps){
if(hk_Math::fabsd(right_side) < m_gauss_eps*hk_GAUSS_SOLUTION_TOLERANCE) {
// rang(matrix) is not maximal and result space is greater 1
// choose an arbitrary result element (0.0f)
//printf("got_gauss_null %f %f\n",left_side,right_side);
m_b[i]=0.0f;
} else {
// no result possible
if(1) {
i=m_n_columns-1;
while(i>=0) {
m_result[i]=0.0; //prevent SUN from detecting rui error
i--;
}
}
return HK_FAULT;
}
} else {
m_b[i]=right_side/left_side; // division left_side is not needed, it was done already above (make a vector of inverses)
}
}
for(i=0;i<m_n_columns;i++) {
m_result[i]=m_b[i];
}
return HK_OK;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -