SLIP  1.4
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
gram_schmidt.hpp
Go to the documentation of this file.
1 /*
2  * Copyright(c):
3  * Signal Image and Communications (SIC) Department
4  * http://www.sic.sp2mi.univ-poitiers.fr/
5  * - University of Poitiers, France http://www.univ-poitiers.fr
6  * - XLIM Institute UMR CNRS 7252 http://www.xlim.fr/
7  *
8  * and
9  *
10  * D2 Fluid, Thermic and Combustion
11  * - University of Poitiers, France http://www.univ-poitiers.fr
12  * - PPRIME Institute - UPR CNRS 3346 http://www.pprime.fr
13  * - ISAE-ENSMA http://www.ensma.fr
14  *
15  * Contributor(s):
16  * The SLIP team,
17  * Benoit Tremblais <tremblais_AT_sic.univ-poitiers.fr>,
18  * Laurent David <laurent.david_AT_lea.univ-poitiers.fr>,
19  * Ludovic Chatellier <ludovic.chatellier_AT_univ-poitiers.fr>,
20  * Lionel Thomas <lionel.thomas_AT_univ-poitiers.fr>,
21  * Denis Arrivault <arrivault_AT_sic.univ-poitiers.fr>,
22  * Julien Dombre <julien.dombre_AT_univ-poitiers.fr>.
23  *
24  * Description:
25  * The Simple Library of Image Processing (SLIP) is a new image processing
26  * library. It is written in the C++ language following as much as possible
27  * the ISO/ANSI C++ standard. It is consequently compatible with any system
28  * satisfying the ANSI C++ complience. It works on different Unix , Linux ,
29  * Mircrosoft Windows and Mac OS X plateforms. SLIP is a research library that
30  * was created by the Signal, Image and Communications (SIC) departement of
31  * the XLIM, UMR 7252 CNRS Institute in collaboration with the Fluids, Thermic
32  * and Combustion departement of the P', UPR 3346 CNRS Institute of the
33  * University of Poitiers.
34  *
35  * The SLIP Library source code has been registered to the APP (French Agency
36  * for the Protection of Programs) by the University of Poitiers and CNRS,
37  * under registration number IDDN.FR.001.300034.000.S.P.2010.000.21000.
38 
39  * http://www.sic.sp2mi.univ-poitiers.fr/slip/
40  *
41  * This software is governed by the CeCILL-C license under French law and
42  * abiding by the rules of distribution of free software. You can use,
43  * modify and/ or redistribute the software under the terms of the CeCILL-C
44  * license as circulated by CEA, CNRS and INRIA at the following URL
45  * http://www.cecill.info.
46  * As a counterpart to the access to the source code and rights to copy,
47  * modify and redistribute granted by the license, users are provided only
48  * with a limited warranty and the software's author, the holder of the
49  * economic rights, and the successive licensors have only limited
50  * liability.
51  *
52  * In this respect, the user's attention is drawn to the risks associated
53  * with loading, using, modifying and/or developing or reproducing the
54  * software by the user in light of its specific status of free software,
55  * that may mean that it is complicated to manipulate, and that also
56  * therefore means that it is reserved for developers and experienced
57  * professionals having in-depth computer knowledge. Users are therefore
58  * encouraged to load and test the software's suitability as regards their
59  * requirements in conditions enabling the security of their systems and/or
60  * data to be ensured and, more generally, to use and operate it in the
61  * same conditions as regards security.
62  *
63  * The fact that you are presently reading this means that you have had
64  * knowledge of the CeCILL-C license and that you accept its terms.
65  */
66 
67 
75 #ifndef SLIP_GRAM_SCHMIDT_HPP
76 #define SLIP_GRAM_SCHMIDT_HPP
77 #include <cassert>
78 #include <cmath>
79 #include <numeric>
80 #include "DPoint2d.hpp"
81 #include "linear_algebra.hpp"
83 
84 namespace slip
85 {
86 
124  template<class RandomAccessIterator, class InnerProduct>
125  void gram_schmidt_normalization(RandomAccessIterator init_base_first,
126  RandomAccessIterator init_base_end,
127  RandomAccessIterator ortho_base_first,
128  RandomAccessIterator ortho_base_end,
129  InnerProduct inner_prod)
130 {
131 
132 
133  assert( (init_base_end - init_base_first) == (ortho_base_end - ortho_base_first));
134 
135  typedef typename std::iterator_traits<RandomAccessIterator>::difference_type _Distance;
136  _Distance init_base_first_size = (init_base_end - init_base_first);
137  ortho_base_first[0] = init_base_first[0] / std::sqrt(inner_prod(init_base_first[0],init_base_first[0]));
138  for(_Distance k = 1; k < init_base_first_size; ++k)
139  {
140  typename RandomAccessIterator::value_type sum = (inner_prod(ortho_base_first[0],init_base_first[k]) / inner_prod(ortho_base_first[0],ortho_base_first[0])) * ortho_base_first[0];
141  for(_Distance q = 1; q < k; ++q)
142  {
143  sum += (inner_prod(ortho_base_first[q],init_base_first[k]) / inner_prod(ortho_base_first[q],ortho_base_first[q])) * ortho_base_first[q];
144  }
145  ortho_base_first[k] = init_base_first[k] - sum;
146  ortho_base_first[k] = ortho_base_first[k] / std::sqrt(inner_prod(ortho_base_first[k],ortho_base_first[k]));
147  }
148 }
149 
150 
188  template<class RandomAccessIterator, class InnerProduct>
189  void modified_gram_schmidt_normalization(RandomAccessIterator init_base_first,
190  RandomAccessIterator init_base_end,
191  RandomAccessIterator ortho_base_first,
192  RandomAccessIterator ortho_base_end,
193  InnerProduct inner_prod)
194  {
195 
196  assert( (init_base_end - init_base_first) == (ortho_base_end - ortho_base_first));
197 
198  typedef typename std::iterator_traits<RandomAccessIterator>::difference_type _Distance;
199  _Distance init_base_first_size = (init_base_end - init_base_first);
200 
201  std::copy(init_base_first,init_base_end,ortho_base_first);
202 
203  for(_Distance k = 0; k < init_base_first_size; ++k)
204  {
205  ortho_base_first[k] /= std::sqrt(inner_prod(ortho_base_first[k],ortho_base_first[k]));
206  for(_Distance q = (k + 1); q < init_base_first_size; ++q)
207  {
208  ortho_base_first[q] -= inner_prod(ortho_base_first[q],ortho_base_first[k]) * ortho_base_first[k];
209  }
210  }
211 }
212 
213 
251  template<class RandomAccessIterator, class InnerProduct>
252  void gram_schmidt_orthogonalization(RandomAccessIterator init_base_first,
253  RandomAccessIterator init_base_end,
254  RandomAccessIterator ortho_base_first,
255  RandomAccessIterator ortho_base_end,
256  InnerProduct inner_prod)
257 {
258  assert( (init_base_end - init_base_first) == (ortho_base_end - ortho_base_first));
259  typedef typename std::iterator_traits<RandomAccessIterator>::difference_type _Distance;
260  _Distance init_base_first_size = (init_base_end - init_base_first);
261  ortho_base_first[0] = init_base_first[0];
262  for(_Distance k = 1; k < init_base_first_size; ++k)
263  {
264  typename RandomAccessIterator::value_type sum = (inner_prod(ortho_base_first[0],init_base_first[k]) / inner_prod(ortho_base_first[0],ortho_base_first[0])) * ortho_base_first[0];
265  for(_Distance q = 1; q < k; ++q)
266  {
267  sum += (inner_prod(ortho_base_first[q],init_base_first[k]) / inner_prod(ortho_base_first[q],ortho_base_first[q])) * ortho_base_first[q];
268  }
269  ortho_base_first[k] = init_base_first[k] - sum;
270  }
271 }
272 
273 
311  template<class RandomAccessIterator, class InnerProduct>
312  void modified_gram_schmidt_orthogonalization(RandomAccessIterator init_base_first,
313  RandomAccessIterator init_base_end,
314  RandomAccessIterator ortho_base_first,
315  RandomAccessIterator ortho_base_end,
316  InnerProduct inner_prod)
317  {
318 
319  assert( (init_base_end - init_base_first) == (ortho_base_end - ortho_base_first));
320  typedef typename std::iterator_traits<RandomAccessIterator>::difference_type _Distance;
321  _Distance init_base_first_size = (init_base_end - init_base_first);
322 
323  std::copy(init_base_first,init_base_end,ortho_base_first);
324 
325  for(_Distance k = 0; k < init_base_first_size; ++k)
326  {
327  typedef typename std::iterator_traits<RandomAccessIterator>::value_type BaseElement;
328 
329  BaseElement Bk = ortho_base_first[k] / std::sqrt(inner_prod(ortho_base_first[k],ortho_base_first[k]));
330  for(_Distance q = (k + 1); q < init_base_first_size; ++q)
331  {
332  ortho_base_first[q] -= inner_prod(ortho_base_first[q],Bk) * Bk;
333  }
334  }
335 }
336 
337 
338 
339 
387  template<typename MatrixIterator1,
388  typename MatrixIterator2,
389  typename MatrixIterator3>
390  void modified_gram_schmidt(MatrixIterator1 A_up,
391  MatrixIterator1 A_bot,
392  MatrixIterator2 Q_up,
393  MatrixIterator2 Q_bot,
394  MatrixIterator3 R_up,
395  MatrixIterator3 R_bot)
396 {
397  assert((A_bot - A_up)[0] == (Q_bot - Q_up)[0]);
398  assert((A_bot - A_up)[1] == (Q_bot - Q_up)[1]);
399  assert((R_bot - R_up)[0] == (A_bot - A_up)[1]);
400  assert((R_bot - R_up)[1] == (A_bot - A_up)[1]);
401  assert((A_bot - A_up)[0] >= (A_bot - A_up)[1]);
402 
403  typedef typename std::iterator_traits<MatrixIterator1>::value_type value_type;
404  typedef typename slip::lin_alg_traits<value_type>::value_type norm_type;
405  typedef typename MatrixIterator1::size_type size_type;
406  typename MatrixIterator1::difference_type sizeA = A_bot - A_up;
407  typename MatrixIterator2::difference_type sizeQ = Q_bot - Q_up;
408  typename MatrixIterator3::difference_type sizeR = R_bot - R_up;
409 
410  size_type A_cols = sizeA[1];
411 
412 
413  //init Q with 0
414  std::fill(Q_up,Q_bot,value_type());
415  //copy the first column of A in the first column of Q
416  std::copy(A_up.col_begin(0),A_up.col_end(0),Q_up.col_begin(0));
417  //init R with 0 and R[0][0] with 1
418  std::fill(R_up,R_bot,value_type());
419  *R_up = value_type(1);
420  for(size_type k = 0; k < A_cols; ++k)
421  {
422  slip::DPoint2d<int> d(k,k);
423  norm_type norm_col_k = std::sqrt(slip::L22_norm_cplx(A_up.col_begin(k),
424  A_up.col_end(k)));
425  R_up[d] = norm_col_k;
426  // divides the column k elements of A by norm_col_k and copy the result
427  //in the column k elements of Q
428  std::transform(A_up.col_begin(k),A_up.col_end(k),
429  Q_up.col_begin(k),std::bind2nd(std::divides<value_type>(),norm_col_k));
430  for(size_type q = (k+1); q < A_cols; ++q)
431  {
432  slip::DPoint2d<int> d2(k,q);
433  R_up[d2] = slip::hermitian_inner_product(Q_up.col_begin(k),Q_up.col_end(k),
434  A_up.col_begin(q),value_type());
435  slip::reduction(A_up.col_begin(q),A_up.col_end(q),
436  Q_up.col_begin(k),(-R_up[d2]));
437  }
438 
439  }
440  }
441 
520  template<class RandomAccessIterator, class RandomAccessIterator2d, class InnerProduct>
521  void gram_matrix(RandomAccessIterator init_base_first,
522  RandomAccessIterator init_base_end,
523  RandomAccessIterator2d matrix_upper_left,
524  RandomAccessIterator2d matrix_bottom_right,
525  InnerProduct inner_prod)
526 {
527  assert((matrix_bottom_right - matrix_upper_left)[0] == (init_base_end - init_base_first));
528  assert((matrix_bottom_right - matrix_upper_left)[1] == (init_base_end - init_base_first));
529 
530  typedef typename std::iterator_traits<RandomAccessIterator>::difference_type _Distance;
531  typedef typename std::iterator_traits<RandomAccessIterator2d>::difference_type _Distance2d;
532 
533  _Distance init_base_first_size = (init_base_end - init_base_first);
534  _Distance2d matrix_size2d = (matrix_bottom_right - matrix_upper_left);
535 
536  for(_Distance i = 0 ; i < init_base_first_size; ++i)
537  {
538  for(_Distance j = 0 ; j < init_base_first_size; ++j)
539  {
540  *(matrix_upper_left++) = inner_prod(init_base_first[i],init_base_first[j]);
541  }
542  }
543 
544 }
545 
546 
547 }//slip::
548 
549 
550 #endif //SLIP_GRAM_SCHMIDT_HPP
551 
void gram_schmidt_orthogonalization(RandomAccessIterator init_base_first, RandomAccessIterator init_base_end, RandomAccessIterator ortho_base_first, RandomAccessIterator ortho_base_end, InnerProduct inner_prod)
Gram-Schmidt orthogonalization algorithm.
void reduction(Iterator1 seq1_beg, Iterator1 seq1_end, Iterator2 seq2_beg, U u)
Add u times the second sequence to the first one: seq1 = seq1 + u * seq2.
Provides a class to modelize the difference of slip::Point2d.
void modified_gram_schmidt_normalization(RandomAccessIterator init_base_first, RandomAccessIterator init_base_end, RandomAccessIterator ortho_base_first, RandomAccessIterator ortho_base_end, InnerProduct inner_prod)
Modified Gram-Schmidt orthonormalization algorithm.
slip::lin_alg_traits< typename std::iterator_traits< InputIterator >::value_type >::value_type L22_norm_cplx(InputIterator first, InputIterator last)
Computes the L22 norm of a complex container.
void modified_gram_schmidt(MatrixIterator1 A_up, MatrixIterator1 A_bot, MatrixIterator2 Q_up, MatrixIterator2 Q_bot, MatrixIterator3 R_up, MatrixIterator3 R_bot)
Modified Gram-Schmidt orthogonalization algorithm on a matrix.
Provides common linear algebra algorithms.
void copy(_II first, _II last, _OI output_first)
Copy algorithm optimized for slip iterators.
Definition: copy_ext.hpp:177
Difference of Point2D class, specialization of DPoint<CoordType,DIM> with DIM = 2.
Definition: Array2d.hpp:129
HyperVolume< T > sqrt(const HyperVolume< T > &M)
std::iterator_traits< RandomAccessIterator1 >::value_type hermitian_inner_product(RandomAccessIterator1 first1, RandomAccessIterator1 last1, RandomAccessIterator2 first2, typename std::iterator_traits< RandomAccessIterator1 >::value_type init)
Computes the hermitian inner-product of two ranges X and Y: .
void modified_gram_schmidt_orthogonalization(RandomAccessIterator init_base_first, RandomAccessIterator init_base_end, RandomAccessIterator ortho_base_first, RandomAccessIterator ortho_base_end, InnerProduct inner_prod)
Modified Gram-Schmidt orthogonalization algorithm.
void gram_schmidt_normalization(RandomAccessIterator init_base_first, RandomAccessIterator init_base_end, RandomAccessIterator ortho_base_first, RandomAccessIterator ortho_base_end, InnerProduct inner_prod)
Gram-Schmidt orthonormalization algorithm.
void gram_matrix(RandomAccessIterator init_base_first, RandomAccessIterator init_base_end, RandomAccessIterator2d matrix_upper_left, RandomAccessIterator2d matrix_bottom_right, InnerProduct inner_prod)
Compute the Gram matrix from a base.