ML Reference
|
00001 // **InsertLicense** code 00002 //===================================================================================== 00004 00009 //===================================================================================== 00010 00011 #ifndef __mlLinearAlgebraTools_H 00012 #define __mlLinearAlgebraTools_H 00013 00014 // Include system independency file and project settings. 00015 #ifndef __mlLinearAlgebraSystem_H 00016 #include "mlLinearAlgebraSystem.h" 00017 #endif 00018 #ifndef __mlLinearAlgebraDefs_H 00019 #include "mlLinearAlgebraDefs.h" 00020 #endif 00021 00022 00023 // All declarations of this header will be in the ML_LA_NAMESPACE namespace. 00024 ML_LA_START_NAMESPACE 00025 00026 //------------------------------------------------------------------- 00029 //------------------------------------------------------------------- 00030 template <class OBJ_TYPE> 00031 void MLSwap(OBJ_TYPE &obj1, OBJ_TYPE &obj2) 00032 { 00033 ML_TRACE_IN_TIME_CRITICAL("mlLinearAlgebraTools.h: MLSwap()"); 00034 00035 OBJ_TYPE buf = obj1; 00036 obj1 = obj2; 00037 obj2 = buf; 00038 } 00039 00040 //------------------------------------------------------------------- 00058 //------------------------------------------------------------------- 00059 template <class BASE_TYPE> 00060 BASE_TYPE MLInverseMatHelper(const BASE_TYPE &origMat, 00061 bool *isInvertible, 00062 const ML_TYPENAME BASE_TYPE::ComponentType /*ZeroEpsilon*/, 00063 const char * const ZeroDetErrString, 00064 const BASE_TYPE &Identity, 00065 const size_t Dim 00066 ) 00067 { 00068 ML_TRACE_IN("mlLinearAlgebraTools.h: MLInverseMatHelper()"); 00069 00070 BASE_TYPE retVal; 00071 ML_TRY 00072 { 00073 00074 00075 BASE_TYPE a(origMat); // As a evolves from original mat into identity 00076 BASE_TYPE b(Identity); // b evolves from identity into inverse(a) 00077 size_t i=0, j=0, i1=0; // Index counters. 00078 00079 // Loop over columns of a from left to right, eliminating above and below diagonal 00080 for (j=0; j<Dim; j++){ 00081 // Find largest pivot in column j among rows j..DIM-1 00082 i1 = j; // Row with largest pivot candidate 00083 for (i=j+1; i<Dim; i++){ 00084 if (MLAbs(a[i][j]) > MLAbs(a[i1][j])){ 00085 i1 = i; 00086 } 00087 } 00088 // Swap rows i1 and j in a and b to put pivot on diagonal 00089 MLSwap(a[i1], a[j]); 00090 MLSwap(b[i1], b[j]); 00091 00092 // Scale row j to have a identity diagonal 00093 const ML_TYPENAME BASE_TYPE::ComponentType avjj = a[j][j]; 00094 if (MLValueIs0WOM(avjj)){ 00095 if (isInvertible == NULL){ 00096 ML_PRINT_ERROR(ZeroDetErrString, 00097 ML_BAD_PARAMETER, 00098 "Returning identity"); 00099 } 00100 else{ 00101 *isInvertible = false; 00102 } 00103 return Identity; 00104 } 00105 b[j] /= avjj; 00106 a[j] /= avjj; 00107 00108 // Eliminate off-diagonal elements in col j of a, 00109 // applying identical operations to b 00110 for (i=0; i<Dim; i++){ 00111 if (i!=j){ 00112 b[i] -= a[i][j]*b[j]; 00113 a[i] -= a[i][j]*a[j]; 00114 } 00115 } 00116 } 00117 00118 // Set state and return inverse. 00119 if (isInvertible != NULL){ *isInvertible = true; } 00120 retVal = b; 00121 } 00122 ML_CATCH_RETHROW; 00123 00124 return retVal; 00125 } 00126 00127 ML_LA_END_NAMESPACE 00128 00129 #endif // __mlLinearAlgebraTools_H