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

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