1c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath//=====================================================
2c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath// File   :  blitz_LU_solve_interface.hh
3c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath// Author :  L. Plagne <laurent.plagne@edf.fr)>
4c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath// Copyright (C) EDF R&D,  lun sep 30 14:23:31 CEST 2002
5c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath//=====================================================
6c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath//
7c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath// This program is free software; you can redistribute it and/or
8c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath// modify it under the terms of the GNU General Public License
9c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath// as published by the Free Software Foundation; either version 2
10c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath// of the License, or (at your option) any later version.
11c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath//
12c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath// This program is distributed in the hope that it will be useful,
13c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath// but WITHOUT ANY WARRANTY; without even the implied warranty of
14c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath// GNU General Public License for more details.
16c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath// You should have received a copy of the GNU General Public License
17c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath// along with this program; if not, write to the Free Software
18c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
19c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath//
20c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath#ifndef BLITZ_LU_SOLVE_INTERFACE_HH
21c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath#define BLITZ_LU_SOLVE_INTERFACE_HH
22c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
23c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath#include "blitz/array.h"
24c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath#include <vector>
25c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
26c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan KamathBZ_USING_NAMESPACE(blitz)
27c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
28c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathtemplate<class real>
29c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathclass blitz_LU_solve_interface : public blitz_interface<real>
30c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath{
31c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
32c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathpublic :
33c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
34c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  typedef typename blitz_interface<real>::gene_matrix gene_matrix;
35c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  typedef typename blitz_interface<real>::gene_vector gene_vector;
36c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
37c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  typedef blitz::Array<int,1> Pivot_Vector;
38c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
39c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  inline static void new_Pivot_Vector(Pivot_Vector & pivot,int N)
40c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  {
41c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
42c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    pivot.resize(N);
43c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
44c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  }
45c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
46c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  inline static void free_Pivot_Vector(Pivot_Vector & pivot)
47c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  {
48c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
49c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    return;
50c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
51c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  }
52c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
53c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
54c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  static inline real matrix_vector_product_sliced(const gene_matrix & A, gene_vector B, int row, int col_start, int col_end)
55c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  {
56c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
57c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    real somme=0.;
58c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
59c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    for (int j=col_start ; j<col_end+1 ; j++){
60c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
61c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath	somme+=A(row,j)*B(j);
62c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
63c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    }
64c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
65c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    return somme;
66c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
67c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  }
68c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
69c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
70c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
71c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
72c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  static inline real matrix_matrix_product_sliced(gene_matrix & A, int row, int col_start, int col_end, gene_matrix & B, int row_shift, int col )
73c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  {
74c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
75c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    real somme=0.;
76c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
77c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    for (int j=col_start ; j<col_end+1 ; j++){
78c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
79c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath	somme+=A(row,j)*B(j+row_shift,col);
80c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
81c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    }
82c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
83c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    return somme;
84c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
85c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  }
86c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
87c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  inline static void LU_factor(gene_matrix & LU, Pivot_Vector & pivot, int N)
88c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  {
89c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
90c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    ASSERT( LU.rows()==LU.cols() ) ;
91c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    int index_max = 0 ;
92c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    real big = 0. ;
93c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    real theSum = 0. ;
94c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    real dum = 0. ;
95c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    // Get the implicit scaling information :
96c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    gene_vector ImplicitScaling( N ) ;
97c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    for( int i=0; i<N; i++ ) {
98c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      big = 0. ;
99c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      for( int j=0; j<N; j++ ) {
100c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath	if( abs( LU( i, j ) )>=big ) big = abs( LU( i, j ) ) ;
101c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      }
102c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      if( big==0. ) {
103c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath	INFOS( "blitz_LU_factor::Singular matrix" ) ;
104c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath	exit( 0 ) ;
105c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      }
106c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      ImplicitScaling( i ) = 1./big ;
107c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    }
108c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    // Loop over columns of Crout's method :
109c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    for( int j=0; j<N; j++ ) {
110c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      for( int i=0; i<j; i++ ) {
111c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath	theSum = LU( i, j ) ;
112c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath	theSum -= matrix_matrix_product_sliced(LU, i, 0, i-1, LU, 0, j) ;
113c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath	//	theSum -= sum( LU( i, Range( fromStart, i-1 ) )*LU( Range( fromStart, i-1 ), j ) ) ;
114c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath	LU( i, j ) = theSum ;
115c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      }
116c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
117c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      // Search for the largest pivot element :
118c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      big = 0. ;
119c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      for( int i=j; i<N; i++ ) {
120c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath	theSum = LU( i, j ) ;
121c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath	theSum -= matrix_matrix_product_sliced(LU, i, 0, j-1, LU, 0, j) ;
122c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath	//	theSum -= sum( LU( i, Range( fromStart, j-1 ) )*LU( Range( fromStart, j-1 ), j ) ) ;
123c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath	LU( i, j ) = theSum ;
124c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath	if( (ImplicitScaling( i )*abs( theSum ))>=big ) {
125c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath	  dum = ImplicitScaling( i )*abs( theSum ) ;
126c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath	  big = dum ;
127c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath	  index_max = i ;
128c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath	}
129c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      }
130c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      // Interchanging rows and the scale factor :
131c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      if( j!=index_max ) {
132c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath	for( int k=0; k<N; k++ ) {
133c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath	  dum = LU( index_max, k ) ;
134c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath	  LU( index_max, k ) = LU( j, k ) ;
135c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath	  LU( j, k ) = dum ;
136c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath	}
137c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath	ImplicitScaling( index_max ) = ImplicitScaling( j ) ;
138c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      }
139c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      pivot( j ) = index_max ;
140c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      if ( LU( j, j )==0. ) LU( j, j ) = 1.e-20 ;
141c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      // Divide by the pivot element :
142c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      if( j<N ) {
143c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath	dum = 1./LU( j, j ) ;
144c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath	for( int i=j+1; i<N; i++ ) LU( i, j ) *= dum ;
145c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      }
146c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    }
147c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
148c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  }
149c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
150c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  inline static void LU_solve(const gene_matrix & LU, const Pivot_Vector pivot, gene_vector &B, gene_vector X, int N)
151c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  {
152c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
153c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    // Pour conserver le meme header, on travaille sur X, copie du second-membre B
154c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    X = B.copy() ;
155c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    ASSERT( LU.rows()==LU.cols() ) ;
156c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    firstIndex indI ;
157c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    // Forward substitution :
158c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    int ii = 0 ;
159c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    real theSum = 0. ;
160c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    for( int i=0; i<N; i++ ) {
161c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      int ip = pivot( i ) ;
162c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      theSum = X( ip ) ;
163c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      //      theSum = B( ip ) ;
164c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      X( ip ) = X( i ) ;
165c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      //      B( ip ) = B( i ) ;
166c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      if( ii ) {
167c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath	theSum -= matrix_vector_product_sliced(LU, X, i, ii-1, i-1) ;
168c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath	//	theSum -= sum( LU( i, Range( ii-1, i-1 ) )*X( Range( ii-1, i-1 ) ) ) ;
169c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath	//	theSum -= sum( LU( i, Range( ii-1, i-1 ) )*B( Range( ii-1, i-1 ) ) ) ;
170c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      } else if( theSum ) {
171c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath	ii = i+1 ;
172c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      }
173c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      X( i ) = theSum ;
174c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      //      B( i ) = theSum ;
175c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    }
176c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    // Backsubstitution :
177c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    for( int i=N-1; i>=0; i-- ) {
178c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      theSum = X( i ) ;
179c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      //      theSum = B( i ) ;
180c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      theSum -= matrix_vector_product_sliced(LU, X, i, i+1, N) ;
181c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      //      theSum -= sum( LU( i, Range( i+1, toEnd ) )*X( Range( i+1, toEnd ) ) ) ;
182c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      //      theSum -= sum( LU( i, Range( i+1, toEnd ) )*B( Range( i+1, toEnd ) ) ) ;
183c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      // Store a component of the solution vector :
184c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      X( i ) = theSum/LU( i, i ) ;
185c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      //      B( i ) = theSum/LU( i, i ) ;
186c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    }
187c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
188c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  }
189c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
190c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath};
191c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
192c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath#endif
193