1*b1cdbd2cSJim Jagielski /**************************************************************
2*b1cdbd2cSJim Jagielski *
3*b1cdbd2cSJim Jagielski * Licensed to the Apache Software Foundation (ASF) under one
4*b1cdbd2cSJim Jagielski * or more contributor license agreements. See the NOTICE file
5*b1cdbd2cSJim Jagielski * distributed with this work for additional information
6*b1cdbd2cSJim Jagielski * regarding copyright ownership. The ASF licenses this file
7*b1cdbd2cSJim Jagielski * to you under the Apache License, Version 2.0 (the
8*b1cdbd2cSJim Jagielski * "License"); you may not use this file except in compliance
9*b1cdbd2cSJim Jagielski * with the License. You may obtain a copy of the License at
10*b1cdbd2cSJim Jagielski *
11*b1cdbd2cSJim Jagielski * http://www.apache.org/licenses/LICENSE-2.0
12*b1cdbd2cSJim Jagielski *
13*b1cdbd2cSJim Jagielski * Unless required by applicable law or agreed to in writing,
14*b1cdbd2cSJim Jagielski * software distributed under the License is distributed on an
15*b1cdbd2cSJim Jagielski * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*b1cdbd2cSJim Jagielski * KIND, either express or implied. See the License for the
17*b1cdbd2cSJim Jagielski * specific language governing permissions and limitations
18*b1cdbd2cSJim Jagielski * under the License.
19*b1cdbd2cSJim Jagielski *
20*b1cdbd2cSJim Jagielski *************************************************************/
21*b1cdbd2cSJim Jagielski
22*b1cdbd2cSJim Jagielski
23*b1cdbd2cSJim Jagielski
24*b1cdbd2cSJim Jagielski /** This method eliminates elements below main diagonal in the given
25*b1cdbd2cSJim Jagielski matrix by gaussian elimination.
26*b1cdbd2cSJim Jagielski
27*b1cdbd2cSJim Jagielski @param matrix
28*b1cdbd2cSJim Jagielski The matrix to operate on. Last column is the result vector (right
29*b1cdbd2cSJim Jagielski hand side of the linear equation). After successful termination,
30*b1cdbd2cSJim Jagielski the matrix is upper triangular. The matrix is expected to be in
31*b1cdbd2cSJim Jagielski row major order.
32*b1cdbd2cSJim Jagielski
33*b1cdbd2cSJim Jagielski @param rows
34*b1cdbd2cSJim Jagielski Number of rows in matrix
35*b1cdbd2cSJim Jagielski
36*b1cdbd2cSJim Jagielski @param cols
37*b1cdbd2cSJim Jagielski Number of columns in matrix
38*b1cdbd2cSJim Jagielski
39*b1cdbd2cSJim Jagielski @param minPivot
40*b1cdbd2cSJim Jagielski If the pivot element gets lesser than minPivot, this method fails,
41*b1cdbd2cSJim Jagielski otherwise, elimination succeeds and true is returned.
42*b1cdbd2cSJim Jagielski
43*b1cdbd2cSJim Jagielski @return true, if elimination succeeded.
44*b1cdbd2cSJim Jagielski */
45*b1cdbd2cSJim Jagielski template <class Matrix, typename BaseType>
eliminate(Matrix & matrix,int rows,int cols,const BaseType & minPivot)46*b1cdbd2cSJim Jagielski bool eliminate( Matrix& matrix,
47*b1cdbd2cSJim Jagielski int rows,
48*b1cdbd2cSJim Jagielski int cols,
49*b1cdbd2cSJim Jagielski const BaseType& minPivot )
50*b1cdbd2cSJim Jagielski {
51*b1cdbd2cSJim Jagielski BaseType temp;
52*b1cdbd2cSJim Jagielski int max, i, j, k; /* *must* be signed, when looping like: j>=0 ! */
53*b1cdbd2cSJim Jagielski
54*b1cdbd2cSJim Jagielski /* eliminate below main diagonal */
55*b1cdbd2cSJim Jagielski for(i=0; i<cols-1; ++i)
56*b1cdbd2cSJim Jagielski {
57*b1cdbd2cSJim Jagielski /* find best pivot */
58*b1cdbd2cSJim Jagielski max = i;
59*b1cdbd2cSJim Jagielski for(j=i+1; j<rows; ++j)
60*b1cdbd2cSJim Jagielski if( fabs(matrix[ j*cols + i ]) > fabs(matrix[ max*cols + i ]) )
61*b1cdbd2cSJim Jagielski max = j;
62*b1cdbd2cSJim Jagielski
63*b1cdbd2cSJim Jagielski /* check pivot value */
64*b1cdbd2cSJim Jagielski if( fabs(matrix[ max*cols + i ]) < minPivot )
65*b1cdbd2cSJim Jagielski return false; /* pivot too small! */
66*b1cdbd2cSJim Jagielski
67*b1cdbd2cSJim Jagielski /* interchange rows 'max' and 'i' */
68*b1cdbd2cSJim Jagielski for(k=0; k<cols; ++k)
69*b1cdbd2cSJim Jagielski {
70*b1cdbd2cSJim Jagielski temp = matrix[ i*cols + k ];
71*b1cdbd2cSJim Jagielski matrix[ i*cols + k ] = matrix[ max*cols + k ];
72*b1cdbd2cSJim Jagielski matrix[ max*cols + k ] = temp;
73*b1cdbd2cSJim Jagielski }
74*b1cdbd2cSJim Jagielski
75*b1cdbd2cSJim Jagielski /* eliminate column */
76*b1cdbd2cSJim Jagielski for(j=i+1; j<rows; ++j)
77*b1cdbd2cSJim Jagielski for(k=cols-1; k>=i; --k)
78*b1cdbd2cSJim Jagielski matrix[ j*cols + k ] -= matrix[ i*cols + k ] *
79*b1cdbd2cSJim Jagielski matrix[ j*cols + i ] / matrix[ i*cols + i ];
80*b1cdbd2cSJim Jagielski }
81*b1cdbd2cSJim Jagielski
82*b1cdbd2cSJim Jagielski /* everything went well */
83*b1cdbd2cSJim Jagielski return true;
84*b1cdbd2cSJim Jagielski }
85*b1cdbd2cSJim Jagielski
86*b1cdbd2cSJim Jagielski
87*b1cdbd2cSJim Jagielski /** Retrieve solution vector of linear system by substituting backwards.
88*b1cdbd2cSJim Jagielski
89*b1cdbd2cSJim Jagielski This operation _relies_ on the previous successful
90*b1cdbd2cSJim Jagielski application of eliminate()!
91*b1cdbd2cSJim Jagielski
92*b1cdbd2cSJim Jagielski @param matrix
93*b1cdbd2cSJim Jagielski Matrix in upper diagonal form, as e.g. generated by eliminate()
94*b1cdbd2cSJim Jagielski
95*b1cdbd2cSJim Jagielski @param rows
96*b1cdbd2cSJim Jagielski Number of rows in matrix
97*b1cdbd2cSJim Jagielski
98*b1cdbd2cSJim Jagielski @param cols
99*b1cdbd2cSJim Jagielski Number of columns in matrix
100*b1cdbd2cSJim Jagielski
101*b1cdbd2cSJim Jagielski @param result
102*b1cdbd2cSJim Jagielski Result vector. Given matrix must have space for one column (rows entries).
103*b1cdbd2cSJim Jagielski
104*b1cdbd2cSJim Jagielski @return true, if back substitution was possible (i.e. no division
105*b1cdbd2cSJim Jagielski by zero occured).
106*b1cdbd2cSJim Jagielski */
107*b1cdbd2cSJim Jagielski template <class Matrix, class Vector, typename BaseType>
substitute(const Matrix & matrix,int rows,int cols,Vector & result)108*b1cdbd2cSJim Jagielski bool substitute( const Matrix& matrix,
109*b1cdbd2cSJim Jagielski int rows,
110*b1cdbd2cSJim Jagielski int cols,
111*b1cdbd2cSJim Jagielski Vector& result )
112*b1cdbd2cSJim Jagielski {
113*b1cdbd2cSJim Jagielski BaseType temp;
114*b1cdbd2cSJim Jagielski int j,k; /* *must* be signed, when looping like: j>=0 ! */
115*b1cdbd2cSJim Jagielski
116*b1cdbd2cSJim Jagielski /* substitute backwards */
117*b1cdbd2cSJim Jagielski for(j=rows-1; j>=0; --j)
118*b1cdbd2cSJim Jagielski {
119*b1cdbd2cSJim Jagielski temp = 0.0;
120*b1cdbd2cSJim Jagielski for(k=j+1; k<cols-1; ++k)
121*b1cdbd2cSJim Jagielski temp += matrix[ j*cols + k ] * result[k];
122*b1cdbd2cSJim Jagielski
123*b1cdbd2cSJim Jagielski if( matrix[ j*cols + j ] == 0.0 )
124*b1cdbd2cSJim Jagielski return false; /* imminent division by zero! */
125*b1cdbd2cSJim Jagielski
126*b1cdbd2cSJim Jagielski result[j] = (matrix[ j*cols + cols-1 ] - temp) / matrix[ j*cols + j ];
127*b1cdbd2cSJim Jagielski }
128*b1cdbd2cSJim Jagielski
129*b1cdbd2cSJim Jagielski /* everything went well */
130*b1cdbd2cSJim Jagielski return true;
131*b1cdbd2cSJim Jagielski }
132*b1cdbd2cSJim Jagielski
133*b1cdbd2cSJim Jagielski
134*b1cdbd2cSJim Jagielski /** This method determines solution of given linear system, if any
135*b1cdbd2cSJim Jagielski
136*b1cdbd2cSJim Jagielski This is a wrapper for eliminate and substitute, given matrix must
137*b1cdbd2cSJim Jagielski contain right side of equation as the last column.
138*b1cdbd2cSJim Jagielski
139*b1cdbd2cSJim Jagielski @param matrix
140*b1cdbd2cSJim Jagielski The matrix to operate on. Last column is the result vector (right
141*b1cdbd2cSJim Jagielski hand side of the linear equation). After successful termination,
142*b1cdbd2cSJim Jagielski the matrix is upper triangular. The matrix is expected to be in
143*b1cdbd2cSJim Jagielski row major order.
144*b1cdbd2cSJim Jagielski
145*b1cdbd2cSJim Jagielski @param rows
146*b1cdbd2cSJim Jagielski Number of rows in matrix
147*b1cdbd2cSJim Jagielski
148*b1cdbd2cSJim Jagielski @param cols
149*b1cdbd2cSJim Jagielski Number of columns in matrix
150*b1cdbd2cSJim Jagielski
151*b1cdbd2cSJim Jagielski @param minPivot
152*b1cdbd2cSJim Jagielski If the pivot element gets lesser than minPivot, this method fails,
153*b1cdbd2cSJim Jagielski otherwise, elimination succeeds and true is returned.
154*b1cdbd2cSJim Jagielski
155*b1cdbd2cSJim Jagielski @return true, if elimination succeeded.
156*b1cdbd2cSJim Jagielski */
157*b1cdbd2cSJim Jagielski template <class Matrix, class Vector, typename BaseType>
solve(Matrix & matrix,int rows,int cols,Vector & result,BaseType minPivot)158*b1cdbd2cSJim Jagielski bool solve( Matrix& matrix,
159*b1cdbd2cSJim Jagielski int rows,
160*b1cdbd2cSJim Jagielski int cols,
161*b1cdbd2cSJim Jagielski Vector& result,
162*b1cdbd2cSJim Jagielski BaseType minPivot )
163*b1cdbd2cSJim Jagielski {
164*b1cdbd2cSJim Jagielski if( eliminate<Matrix,BaseType>(matrix, rows, cols, minPivot) )
165*b1cdbd2cSJim Jagielski return substitute<Matrix,Vector,BaseType>(matrix, rows, cols, result);
166*b1cdbd2cSJim Jagielski
167*b1cdbd2cSJim Jagielski return false;
168*b1cdbd2cSJim Jagielski }
169