GetFEM  5.5
gmm_condition_number.h
Go to the documentation of this file.
1 /* -*- c++ -*- (enables emacs c++ mode) */
2 /*===========================================================================
3 
4  Copyright (C) 2003-2026 Yves Renard, Julien Pommier
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, see https://www.gnu.org/licenses/.
19 
20  As a special exception, you may use this file as it is a part of a free
21  software library without restriction. Specifically, if other files
22  instantiate templates or use macros or inline functions from this file,
23  or you compile this file and link it with other files to produce an
24  executable, this file does not by itself cause the resulting executable
25  to be covered by the GNU Lesser General Public License. This exception
26  does not however invalidate any other reasons why the executable file
27  might be covered by the GNU Lesser General Public License.
28 
29 ===========================================================================*/
30 
31 /**@file gmm_condition_number.h
32  @author Yves Renard <Yves.Renard@insa-lyon.fr>, Julien Pommier <Julien.Pommier@insa-toulouse.fr>
33  @date August 27, 2003.
34  @brief computation of the condition number of dense matrices.
35 */
36 #ifndef GMM_CONDITION_NUMBER_H__
37 #define GMM_CONDITION_NUMBER_H__
38 
39 #include "gmm_dense_qr.h"
40 
41 namespace gmm {
42 
43  /** computation of the condition number of dense matrices using SVD.
44 
45  Uses symmetric_qr_algorithm => dense matrices only.
46 
47  @param M a matrix.
48  @param emin smallest (in magnitude) eigenvalue
49  @param emax largest eigenvalue.
50  */
51  template <typename MAT>
52  typename number_traits<typename
53  linalg_traits<MAT>::value_type>::magnitude_type
54  condition_number(const MAT& M,
55  typename number_traits<typename
56  linalg_traits<MAT>::value_type>::magnitude_type& emin,
57  typename number_traits<typename
58  linalg_traits<MAT>::value_type>::magnitude_type& emax) {
59  typedef typename linalg_traits<MAT>::value_type T;
60  typedef typename number_traits<T>::magnitude_type R;
61 
62  // Added because of errors in complex with zero det
63  if (sizeof(T) != sizeof(R) && gmm::abs(gmm::lu_det(M)) == R(0))
64  return gmm::default_max(R());
65 
66  size_type m = mat_nrows(M), n = mat_ncols(M);
67  emax = emin = R(0);
68  std::vector<R> eig(m+n);
69 
70  if (m+n == 0) return R(0);
71  if (is_hermitian(M)) {
72  eig.resize(m);
73  gmm::symmetric_qr_algorithm(M, eig);
74  }
75  else {
76  dense_matrix<T> B(m+n, m+n); // not very efficient ??
77  gmm::copy(conjugated(M), sub_matrix(B, sub_interval(m, n), sub_interval(0, m)));
78  gmm::copy(M, sub_matrix(B, sub_interval(0, m),
79  sub_interval(m, n)));
80  gmm::symmetric_qr_algorithm(B, eig);
81  }
82  emin = emax = gmm::abs(eig[0]);
83  for (size_type i = 1; i < eig.size(); ++i) {
84  R e = gmm::abs(eig[i]);
85  emin = std::min(emin, e);
86  emax = std::max(emax, e);
87  }
88  // cout << "emin = " << emin << " emax = " << emax << endl;
89  if (emin == R(0)) return gmm::default_max(R());
90  return emax / emin;
91  }
92 
93  template <typename MAT>
94  typename number_traits<typename
95  linalg_traits<MAT>::value_type>::magnitude_type
96  condition_number(const MAT& M) {
97  typename number_traits<typename
98  linalg_traits<MAT>::value_type>::magnitude_type emax, emin;
99  return condition_number(M, emin, emax);
100  }
101 
102  template <typename MAT>
103  typename number_traits<typename
104  linalg_traits<MAT>::value_type>::magnitude_type
105  Frobenius_condition_number_sqr(const MAT& M) {
106  typedef typename linalg_traits<MAT>::value_type T;
107  typedef typename number_traits<T>::magnitude_type R;
108  size_type m = mat_nrows(M), n = mat_ncols(M);
109  dense_matrix<T> B(std::min(m,n), std::min(m,n));
110  if (m < n) mult(M,gmm::conjugated(M),B);
111  else mult(gmm::conjugated(M),M,B);
112  R trB = abs(mat_trace(B));
113  lu_inverse(B);
114  return trB*abs(mat_trace(B));
115  }
116 
117  template <typename MAT>
118  typename number_traits<typename
119  linalg_traits<MAT>::value_type>::magnitude_type
120  Frobenius_condition_number(const MAT& M)
121  { return sqrt(Frobenius_condition_number_sqr(M)); }
122 
123  /** estimation of the condition number (TO BE DONE...)
124  */
125  template <typename MAT>
126  typename number_traits<typename
127  linalg_traits<MAT>::value_type>::magnitude_type
128  condest(const MAT& M,
129  typename number_traits<typename
130  linalg_traits<MAT>::value_type>::magnitude_type& emin,
131  typename number_traits<typename
132  linalg_traits<MAT>::value_type>::magnitude_type& emax) {
133  return condition_number(M, emin, emax);
134  }
135 
136  template <typename MAT>
137  typename number_traits<typename
138  linalg_traits<MAT>::value_type>::magnitude_type
139  condest(const MAT& M) {
140  typename number_traits<typename
141  linalg_traits<MAT>::value_type>::magnitude_type emax, emin;
142  return condest(M, emin, emax);
143  }
144 }
145 
146 #endif
void copy(const L1 &l1, L2 &l2)
*‍/
Definition: gmm_blas.h:976
linalg_traits< M >::value_type mat_trace(const M &m)
Trace of a matrix.
Definition: gmm_blas.h:527
void mult(const L1 &l1, const L2 &l2, L3 &l3)
*‍/
Definition: gmm_blas.h:1663
bool is_hermitian(const MAT &A, magnitude_of_linalg(MAT) tol=magnitude_of_linalg(MAT)(-1))
*‍/
Definition: gmm_blas.h:2240
number_traits< typename linalg_traits< MAT >::value_type >::magnitude_type condition_number(const MAT &M, typename number_traits< typename linalg_traits< MAT >::value_type >::magnitude_type &emin, typename number_traits< typename linalg_traits< MAT >::value_type >::magnitude_type &emax)
computation of the condition number of dense matrices using SVD.
number_traits< typename linalg_traits< MAT >::value_type >::magnitude_type condest(const MAT &M, typename number_traits< typename linalg_traits< MAT >::value_type >::magnitude_type &emin, typename number_traits< typename linalg_traits< MAT >::value_type >::magnitude_type &emax)
estimation of the condition number (TO BE DONE...)
conjugated_return< L >::return_type conjugated(const L &v)
return a conjugated view of the input matrix or vector.
linalg_traits< DenseMatrixLU >::value_type lu_det(const DenseMatrixLU &LU, const Pvector &pvector)
Compute the matrix determinant (via a LU factorization)
Definition: gmm_dense_lu.h:240
Dense QR factorization.
size_t size_type
used as the common size type in the library
Definition: bgeot_poly.h:48