OpendTect-6_4  6.4
qrsolv.h
Go to the documentation of this file.
1 #ifndef qrsolv_h
2 #define qrsolv_h
3 
4 /*@+
5 ________________________________________________________________________
6 
7  (C) dGB Beheer B.V.; (LICENSE) http://opendtect.org/OpendTect_license.txt
8  Author: Arnaud Huck
9  Date: April 2015
10  RCS: $Id$
11 ________________________________________________________________________
12 
13 @$
14 */
15 
16 #include "arrayndimpl.h"
17 
18 #define TINY 1.0e-20
19 
27 template <class T>
29 {
30 public:
31  QRSolver(const Array2D<T>& A);
32  ~QRSolver();
33 
34  bool isFullRank() { return isfullrank_; }
35 
36  const Array1DImpl<T>* apply(const Array1D<T>& B) const;
37  const Array1DImpl<T>* apply(const Array2D<T>& B) const;
38  const Array2DImpl<T>* getQ() const;
39  const Array2DImpl<T>* getR() const;
40 
41 protected:
44  int m_;
45  int n_;
47 
48 };
49 
50 
51 template <class T> inline
53  : qr_(A)
54  , m_(A.info().getSize(0))
55  , n_(A.info().getSize(1))
56  , isfullrank_(true)
57 {
58  if ( A.info().getSize(0) < A.info().getSize(1) )
59  return;
60 
61  rdiag_ = new Array1DImpl<T>( n_ );
62  for ( int k=0; k<n_; ++k )
63  {
64  double norm = 0.;
65  for ( int i=k; i<m_; ++i )
66  norm = Math::Sqrt( norm*norm + qr_.get( i, k )*qr_.get( i, k ) );
67 
68  if ( mIsZero(norm,TINY) )
69  {
70  rdiag_->set( k, 0. );
71  isfullrank_ = false;
72  continue;
73  }
74 
75  if ( qr_.get( k, k ) < TINY )
76  norm *= -1.;
77 
78  for ( int i=k; i<m_; ++i )
79  qr_.set( i, k, qr_.get( i, k )/norm );
80 
81  qr_.set( k, k, qr_.get( k, k ) + 1. );
82 
83  for ( int j=k+1; j<n_; ++j )
84  {
85  double s = 0.;
86  for ( int i=k; i<m_; ++i )
87  s += qr_.get( i, k ) * qr_.get( i, j );
88 
89  s = -s / qr_.get( k, k );
90  for ( int i=k; i<m_; ++i )
91  qr_.set( i, j, qr_.get( i, j ) + s * qr_.get( i, k ) );
92  }
93 
94  rdiag_->set( k, -norm );
95  }
96 }
97 
98 
99 template <class T> inline
101 {
102  delete rdiag_;
103 }
104 
105 
106 template <class T> inline
108 {
109  if( !rdiag_ )
110  return 0;
111 
112  const int sz = b.info().getSize(0);
113  Array2DImpl<T>* arr = new Array2DImpl<T>( sz, 1 );
114  for ( int idx=0; idx<sz; idx++ )
115  arr->set( idx, 0, b.get( idx ) );
116 
117  const Array1DImpl<T>* out = apply( *arr );
118  delete arr;
119  return out;
120 }
121 
122 
123 template <class T> inline
125 {
126  if ( b.info().getSize(0) != m_ || !isfullrank_ || !rdiag_ )
127  return 0;
128 
129  const int nx = b.info().getSize(1);
130  Array2DImpl<T>* arr = new Array2DImpl<T>( b );
131 
132  // Compute Y = transpose(Q)*B.
133  for ( int k=0; k<n_; ++k )
134  {
135  for ( int j=0; j<nx; ++j )
136  {
137  double s = 0.;
138  for ( int i=k; i<m_; ++i )
139  s += qr_.get( i, k ) * arr->get( i, j );
140 
141  s = -s / qr_.get( k, k );
142  for ( int i=k; i<m_; ++i )
143  arr->set( i, j, arr->get( i, j ) + s * qr_.get( i, k ) );
144  }
145  }
146 
147  // Solve R*X = Y
148  for ( int k=n_-1; k>=0; --k )
149  {
150  for ( int j=0; j<nx; ++j )
151  arr->set( k, j, arr->get( k, j ) / rdiag_->get( k ) );
152 
153  for ( int i=0; i<k; ++i )
154  for ( int j=0; j<nx; ++j )
155  arr->set( i, j, arr->get( i, j ) -
156  arr->get( k, j ) * qr_.get( i, k ) );
157  }
158 
159 
160  Array1DImpl<T>* out = new Array1DImpl<T>( n_ );
161  for ( int idx=0; idx<n_; idx++ )
162  out->set( idx, arr->get(idx,0) );
163 
164  delete arr;
165  return out;
166 }
167 
168 
169 template <class T> inline
171 {
172  if( !rdiag_ )
173  return 0;
174 
175  Array2DImpl<T>* arr = new Array2DImpl<T>( m_, n_ );
176  for ( int k=n_-1; k>=0; --k )
177  {
178  for ( int i=0; i<m_; ++i )
179  arr->set( i, k, 0. );
180 
181  arr->set( k, k, 1. );
182  for ( int j=k; j<n_; ++j )
183  {
184  if ( mIsZero(qr_.get( k, k ),TINY) )
185  continue;
186 
187  double s = 0.;
188  for ( int i=k; i<m_; ++i )
189  s += qr_.get( i, k) * arr->get( i, j );
190 
191  s = -s / qr_.get( k, k );
192  for ( int i=k; i<m_; ++i )
193  arr->set( i, j, arr->get( i, j ) + s * qr_.get( i, k ) );
194  }
195  }
196 
197  return arr;
198 }
199 
200 #undef TINY
201 
202 
203 template <class T> inline
205 {
206  if( !rdiag_ )
207  return 0;
208 
209  Array2DImpl<T>* arr = new Array2DImpl<T>( n_, n_ );
210  for ( int i=0; i<n_; ++i )
211  {
212  arr->set( i, i, rdiag_->get( i ) );
213  for ( int j=i+1; j<n_; ++j )
214  arr->set( i, j, qr_.get( i, j ) );
215  }
216 
217  return arr;
218 }
219 
220 #endif
const Array2DImpl< T > * getQ() const
Definition: qrsolv.h:170
Array1D ( Subclass of ArrayND ) is a one dimensional array.
Definition: arraynd.h:101
~QRSolver()
Definition: qrsolv.h:100
Array2DImpl< T > qr_
Definition: qrsolv.h:42
Array1DImpl< T > * rdiag_
Definition: qrsolv.h:43
#define mIsZero(x, eps)
Definition: commondefs.h:53
#define TINY
Definition: qrsolv.h:18
Implementation of Array2D.
Definition: arrayndimpl.h:102
int n_
Definition: qrsolv.h:45
T get(int, int) const
Definition: arrayndimpl.h:470
void set(int pos, T)
Definition: arrayndimpl.h:360
bool isfullrank_
Definition: qrsolv.h:46
int m_
Definition: qrsolv.h:44
virtual int getSize(int dim) const =0
Array2D ( Subclass of ArrayND ) is a two dimensional array.
Definition: arraynd.h:131
QRSolver(const Array2D< T > &A)
Definition: qrsolv.h:52
const Array1DImpl< T > * apply(const Array1D< T > &B) const
Definition: qrsolv.h:107
const Array2DImpl< T > * getR() const
Definition: qrsolv.h:204
QRSolver - QR decomposition of a matrix A For an m-by-n matrix A, with m>=n, the QR decomposition is ...
Definition: qrsolv.h:28
virtual const Array1DInfo & info() const =0
bool isFullRank()
Definition: qrsolv.h:34
virtual T get(int) const =0
void set(int, int, T)
Definition: arrayndimpl.h:448
Implementation of Array1D.
Definition: arrayndimpl.h:52
#define mClass(module)
Definition: commondefs.h:164
virtual const Array2DInfo & info() const =0
float Sqrt(float)

Generated at for the OpendTect seismic interpretation project. Copyright (C): dGB Beheer B. V. 2019