1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144
|
//======================================
// [m x n] matrices are represented as 1-d arrays
// Row i goes from 0 to m-1.
// Col j goes from 0 to n-1.
// The (i,j) component is stored at 1-d index
// n * i + j
//
// Storage order as for C++ arrays (column index varies fastest);
//======================================
#include <iostream>
#include <fstream>
#include <iomanip>
#include <cmath>
#include <algorithm>
using namespace std;
const double EPS = 1.0e-30;
//======================================
template <class T> bool GaussElimination( int n, T *A, T *B, T *X ) // Solve AX=B
{
// Create copies to avoid overwriting
T *AA = new T[n*n];
T *BB = new T[n];
copy( A, A + n * n, AA );
copy( B, B + n , BB );
// Row operations for i = 0, ,,,, n - 2 (n-1 not needed)
for ( int i = 0; i < n - 1; i++ )
{
// Pivoting; swap rows such that no elements below [i][i] have larger magnitude
int r = i; // Find row r below with largest element in column i
int ii = n * i + i;
T maxA = abs( AA[ii] );
for ( int k = i + 1; k < n; k++ )
{
int ki = n * k + i;
if ( abs( AA[ki] ) > maxA )
{
r = k;
maxA = abs( AA[ki] );
}
}
if ( r != i ) // Swap rows i and r (remains of these rows for AA)
{
for ( int j = i; j < n; j++ ) swap( AA[n*r+j], AA[n*i+j] );
swap( BB[i], BB[r] );
}
// Row operations to make upper-triangular
if ( abs( AA[ii] ) < EPS ) return false; // Singular matrix
for ( int r = i + 1; r < n; r++ ) // On lower rows
{
T multiple = AA[r*n+i] / AA[ii]; // Multiple of ith row necessary to clear element in ith column
for ( int j = i; j < n; j++ ) AA[r*n+j] -= multiple * AA[i*n+j];
BB[r] -= multiple * BB[i];
}
}
// Back-substitute
for ( int i = n - 1; i >= 0; i-- )
{
X[i] = BB[i];
for ( int j = i + 1; j < n; j++ ) X[i] -= AA[n*i+j] * X[j];
X[i] /= AA[n*i+i];
}
delete [] AA;
delete [] BB;
return true;
}
//======================================
template <class T> void matMul( int mA, int nA, int nB, T *A, T *B, T *C ) // Matrix multiply: A * B = C
{
for ( int i = 0; i < mA; i++ )
{
for ( int j = 0; j < nB; j++ )
{
int ij = nB * i + j;
C[ij] = 0.0;
for ( int k = 0; k < nA; k++ ) C[ij] += A[nA*i+k] * B[nB*k+j];
}
}
}
//======================================
template <class T> void showMatrix( int m, int n, T *A )
{
const double ZERO = 1.0e-10;
const string SPACE = " ";
const int w = 12;
const int p = 4;
cout << fixed << setprecision( p );
for ( int i = 0; i < m; i++ )
{
for ( int j = 0; j < n; j++ )
{
T val = A[n*i+j]; if ( abs( val ) < ZERO ) val = 0.0;
cout << setw( w ) << val << SPACE;
}
cout << '\n';
}
}
//======================================
int main()
{
const int N = 4;
double A[N*N] = { 1, 2, 3, 4,
-2, 5, 5, 7,
1, 9, 10, 3,
2, 2, 4, 3 };
double B[N] = { 1, 2, 3, 4 };
double X[N] = { 0 };
// SOLVE
bool ok = GaussElimination( N, A, B, X );
if ( !ok ) { cout << "Can't solve\n"; return 1; }
// SUMMARY
cout << "\n*** Solve AX = B by Gaussian elimination ***\n";
cout << "\nA:\n"; showMatrix( N, N, A );
cout << "\nB:\n"; showMatrix( N, 1, B );
cout << "\nX:\n"; showMatrix( N, 1, X );
// CHECKS
double *AX = new double[N*1];
matMul( N, N, 1, A, X, AX );
cout << "\n\n*** CHECK SOLUTION ***\n";
cout << "\nAX:\n"; showMatrix( N, 1, AX );
cout << "\nB :\n"; showMatrix( N, 1, B );
delete [] AX;
}
|