1 /* -*- c++ -*- (enables emacs c++ mode) */
2 /*===========================================================================
3 
4  Copyright (C) 2002-2020 Yves Renard
5 
6  This file is a part of GetFEM
7 
8  GetFEM  is  free software;  you  can  redistribute  it  and/or modify it
9  under  the  terms  of the  GNU  Lesser General Public License as published
10  by  the  Free Software Foundation;  either version 3 of the License,  or
11  (at your option) any later version along with the GCC Runtime Library
12  Exception either version 3.1 or (at your option) any later version.
13  This program  is  distributed  in  the  hope  that it will be useful,  but
14  WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15  or  FITNESS  FOR  A PARTICULAR PURPOSE.  See the GNU Lesser General Public
16  License and GCC Runtime Library Exception for more details.
17  You  should  have received a copy of the GNU Lesser General Public License
18  along  with  this program;  if not, write to the Free Software Foundation,
19  Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA.
20 
21  As a special exception, you  may use  this file  as it is a part of a free
22  software  library  without  restriction.  Specifically,  if   other  files
23  instantiate  templates  or  use macros or inline functions from this file,
24  or  you compile this  file  and  link  it  with other files  to produce an
25  executable, this file  does  not  by itself cause the resulting executable
26  to be covered  by the GNU Lesser General Public License.  This   exception
27  does not  however  invalidate  any  other  reasons why the executable file
28  might be covered by the GNU Lesser General Public License.
29 
30 ===========================================================================*/
31 
32 /**@file gmm_tri_solve.h
33    @author Yves Renard
34    @date October 13, 2002.
35    @brief Solve triangular linear system for dense matrices.
36 */
37 
38 #ifndef GMM_TRI_SOLVE_H__
39 #define GMM_TRI_SOLVE_H__
40 
41 #include "gmm_interface.h"
42 
43 namespace gmm {
44 
45   template <typename TriMatrix, typename VecX>
upper_tri_solve__(const TriMatrix & T,VecX & x,size_t k,col_major,abstract_sparse,bool is_unit)46   void upper_tri_solve__(const TriMatrix& T, VecX& x, size_t k,
47 			 col_major, abstract_sparse, bool is_unit) {
48     typename linalg_traits<TriMatrix>::value_type x_j;
49     for (int j = int(k) - 1; j >= 0; --j) {
50       typedef typename linalg_traits<TriMatrix>::const_sub_col_type COL;
51       COL c = mat_const_col(T, j);
52       typename linalg_traits<typename org_type<COL>::t>::const_iterator
53 	it = vect_const_begin(c), ite = vect_const_end(c);
54       if (!is_unit) x[j] /= c[j];
55       for (x_j = x[j]; it != ite ; ++it)
56 	if (int(it.index()) < j) x[it.index()] -= x_j * (*it);
57     }
58   }
59 
60   template <typename TriMatrix, typename VecX>
upper_tri_solve__(const TriMatrix & T,VecX & x,size_t k,col_major,abstract_dense,bool is_unit)61   void upper_tri_solve__(const TriMatrix& T, VecX& x, size_t k,
62 			 col_major, abstract_dense, bool is_unit) {
63     typename linalg_traits<TriMatrix>::value_type x_j;
64     for (int j = int(k) - 1; j >= 0; --j) {
65       typedef typename linalg_traits<TriMatrix>::const_sub_col_type COL;
66       COL c = mat_const_col(T, j);
67       typename linalg_traits<typename org_type<COL>::t>::const_iterator
68 	it = vect_const_begin(c), ite = it + j;
69       typename linalg_traits<VecX>::iterator itx = vect_begin(x);
70       if (!is_unit) x[j] /= c[j];
71       for (x_j = x[j]; it != ite ; ++it, ++itx) *itx -= x_j * (*it);
72     }
73   }
74 
75   template <typename TriMatrix, typename VecX>
lower_tri_solve__(const TriMatrix & T,VecX & x,size_t k,col_major,abstract_sparse,bool is_unit)76   void lower_tri_solve__(const TriMatrix& T, VecX& x, size_t k,
77 			 col_major, abstract_sparse, bool is_unit) {
78     typename linalg_traits<TriMatrix>::value_type x_j;
79     // cout << "(lower col)The Tri Matrix = " << T << endl;
80     // cout << "k = " << endl;
81     for (int j = 0; j < int(k); ++j) {
82       typedef typename linalg_traits<TriMatrix>::const_sub_col_type COL;
83       COL c = mat_const_col(T, j);
84       typename linalg_traits<typename org_type<COL>::t>::const_iterator
85 	it = vect_const_begin(c), ite = vect_const_end(c);
86       if (!is_unit) x[j] /= c[j];
87       for (x_j = x[j]; it != ite ; ++it)
88 	if (int(it.index()) > j && it.index() < k) x[it.index()] -= x_j*(*it);
89     }
90   }
91 
92   template <typename TriMatrix, typename VecX>
lower_tri_solve__(const TriMatrix & T,VecX & x,size_t k,col_major,abstract_dense,bool is_unit)93   void lower_tri_solve__(const TriMatrix& T, VecX& x, size_t k,
94 			 col_major, abstract_dense, bool is_unit) {
95     typename linalg_traits<TriMatrix>::value_type x_j;
96     for (int j = 0; j < int(k); ++j) {
97       typedef typename linalg_traits<TriMatrix>::const_sub_col_type COL;
98       COL c = mat_const_col(T, j);
99       typename linalg_traits<typename org_type<COL>::t>::const_iterator
100 	it = vect_const_begin(c) + (j+1), ite = vect_const_begin(c) + k;
101       typename linalg_traits<VecX>::iterator itx = vect_begin(x) + (j+1);
102       if (!is_unit) x[j] /= c[j];
103       for (x_j = x[j]; it != ite ; ++it, ++itx) *itx -= x_j * (*it);
104     }
105   }
106 
107 
108   template <typename TriMatrix, typename VecX>
upper_tri_solve__(const TriMatrix & T,VecX & x,size_t k,row_major,abstract_sparse,bool is_unit)109   void upper_tri_solve__(const TriMatrix& T, VecX& x, size_t k,
110 			 row_major, abstract_sparse, bool is_unit) {
111     typedef typename linalg_traits<TriMatrix>::const_sub_row_type ROW;
112     typename linalg_traits<TriMatrix>::value_type t;
113     typename linalg_traits<TriMatrix>::const_row_iterator
114       itr = mat_row_const_end(T);
115     for (int i = int(k) - 1; i >= 0; --i) {
116       --itr;
117       ROW c = linalg_traits<TriMatrix>::row(itr);
118       typename linalg_traits<typename org_type<ROW>::t>::const_iterator
119 	it = vect_const_begin(c), ite = vect_const_end(c);
120       for (t = x[i]; it != ite; ++it)
121 	if (int(it.index()) > i && it.index() < k) t -= (*it) * x[it.index()];
122       if (!is_unit) x[i] = t / c[i]; else x[i] = t;
123     }
124   }
125 
126   template <typename TriMatrix, typename VecX>
upper_tri_solve__(const TriMatrix & T,VecX & x,size_t k,row_major,abstract_dense,bool is_unit)127   void upper_tri_solve__(const TriMatrix& T, VecX& x, size_t k,
128 			 row_major, abstract_dense, bool is_unit) {
129     typename linalg_traits<TriMatrix>::value_type t;
130 
131     for (int i = int(k) - 1; i >= 0; --i) {
132       typedef typename linalg_traits<TriMatrix>::const_sub_row_type ROW;
133       ROW c = mat_const_row(T, i);
134       typename linalg_traits<typename org_type<ROW>::t>::const_iterator
135 	it = vect_const_begin(c) + (i + 1), ite = vect_const_begin(c) + k;
136       typename linalg_traits<VecX>::iterator itx = vect_begin(x) + (i+1);
137 
138       for (t = x[i]; it != ite; ++it, ++itx) t -= (*it) * (*itx);
139       if (!is_unit) x[i] = t / c[i]; else x[i] = t;
140     }
141   }
142 
143   template <typename TriMatrix, typename VecX>
lower_tri_solve__(const TriMatrix & T,VecX & x,size_t k,row_major,abstract_sparse,bool is_unit)144   void lower_tri_solve__(const TriMatrix& T, VecX& x, size_t k,
145 			 row_major, abstract_sparse, bool is_unit) {
146     typename linalg_traits<TriMatrix>::value_type t;
147 
148     for (int i = 0; i < int(k); ++i) {
149       typedef typename linalg_traits<TriMatrix>::const_sub_row_type ROW;
150       ROW c = mat_const_row(T, i);
151       typename linalg_traits<typename org_type<ROW>::t>::const_iterator
152 	it = vect_const_begin(c), ite = vect_const_end(c);
153 
154       for (t = x[i]; it != ite; ++it)
155 	if (int(it.index()) < i) t -= (*it) * x[it.index()];
156       if (!is_unit) x[i] = t / c[i]; else x[i] = t;
157     }
158   }
159 
160   template <typename TriMatrix, typename VecX>
lower_tri_solve__(const TriMatrix & T,VecX & x,size_t k,row_major,abstract_dense,bool is_unit)161   void lower_tri_solve__(const TriMatrix& T, VecX& x, size_t k,
162 			 row_major, abstract_dense, bool is_unit) {
163     typename linalg_traits<TriMatrix>::value_type t;
164 
165     for (int i = 0; i < int(k); ++i) {
166       typedef typename linalg_traits<TriMatrix>::const_sub_row_type ROW;
167       ROW c = mat_const_row(T, i);
168       typename linalg_traits<typename org_type<ROW>::t>::const_iterator
169 	it = vect_const_begin(c), ite = it + i;
170       typename linalg_traits<VecX>::iterator itx = vect_begin(x);
171 
172       for (t = x[i]; it != ite; ++it, ++itx) t -= (*it) * (*itx);
173       if (!is_unit) x[i] = t / c[i]; else x[i] = t;
174     }
175   }
176 
177 
178 // Triangular Solve:  x <-- T^{-1} * x
179 
180   template <typename TriMatrix, typename VecX> inline
181   void upper_tri_solve(const TriMatrix& T, VecX &x_, bool is_unit = false)
182   { upper_tri_solve(T, x_, mat_nrows(T), is_unit); }
183 
184   template <typename TriMatrix, typename VecX> inline
185   void lower_tri_solve(const TriMatrix& T, VecX &x_, bool is_unit = false)
186   { lower_tri_solve(T, x_, mat_nrows(T), is_unit); }
187 
188   template <typename TriMatrix, typename VecX> inline
upper_tri_solve(const TriMatrix & T,VecX & x_,size_t k,bool is_unit)189   void upper_tri_solve(const TriMatrix& T, VecX &x_, size_t k,
190 		       bool is_unit) {
191     VecX& x = const_cast<VecX&>(x_);
192     GMM_ASSERT2(mat_nrows(T) >= k && vect_size(x) >= k
193 		&& mat_ncols(T) >= k && !is_sparse(x_), "dimensions mismatch");
194     upper_tri_solve__(T, x, k,
195 		      typename principal_orientation_type<typename
196 		      linalg_traits<TriMatrix>::sub_orientation>::potype(),
197 		      typename linalg_traits<TriMatrix>::storage_type(),
198 		      is_unit);
199   }
200 
201   template <typename TriMatrix, typename VecX> inline
lower_tri_solve(const TriMatrix & T,VecX & x_,size_t k,bool is_unit)202   void lower_tri_solve(const TriMatrix& T, VecX &x_, size_t k,
203 		       bool is_unit) {
204     VecX& x = const_cast<VecX&>(x_);
205     GMM_ASSERT2(mat_nrows(T) >= k && vect_size(x) >= k
206 		&& mat_ncols(T) >= k && !is_sparse(x_), "dimensions mismatch");
207     lower_tri_solve__(T, x, k,
208 		      typename principal_orientation_type<typename
209 		      linalg_traits<TriMatrix>::sub_orientation>::potype(),
210 		      typename linalg_traits<TriMatrix>::storage_type(),
211 		      is_unit);
212   }
213 
214 
215 
216 
217 
218 
219 }
220 
221 
222 #endif //  GMM_TRI_SOLVE_H__
223