STK++ 1.0
STK_Householder.h
Go to the documentation of this file.
00001 /*--------------------------------------------------------------------*/
00002 /*     Copyright (C) 2004-2007  Serge Iovleff
00003 
00004     This program is free software; you can redistribute it and/or modify
00005     it under the terms of the GNU Lesser General Public License as
00006     published by the Free Software Foundation; either version 2 of the
00007     License, or (at your option) any later version.
00008 
00009     This program is distributed in the hope that it will be useful,
00010     but WITHOUT ANY WARRANTY; without even the implied warranty of
00011     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012     GNU Lesser General Public License for more details.
00013 
00014     You should have received a copy of the GNU Lesser General Public
00015     License along with this program; if not, write to the
00016     Free Software Foundation, Inc.,
00017     59 Temple Place,
00018     Suite 330,
00019     Boston, MA 02111-1307
00020     USA
00021 
00022     Contact : Serge.Iovleff@stkpp.org
00023 */
00024 
00025 /*
00026  * Project:  Algebra
00027  * Purpose:  Define Householder methods for Algebra classes.
00028  * Author:   Serge Iovleff, serge.iovleff@stkpp.org
00029  *
00030  **/
00031 
00036 #ifndef STK_HOUSEHOLDER_H
00037 #define STK_HOUSEHOLDER_H
00038 
00039 // Matrix class
00040 #include "../../Arrays/include/STK_Matrix.h"
00041 
00042 // for normInf
00043 #include "STK_LinAlgebra1D.h"
00044 
00045 namespace STK
00046 {
00059 template <class TContainer1D>
00060 Real house(ITContainer1D<Real, TContainer1D>& x)
00061 {
00062   // compute L^{\infty} norm of X
00063   Real scale  = normInf(x);
00064   // first and last index fo the essential Householder vector
00065   Integer first = x.first()+1, last = x.last();
00066   // result and norm2 of X
00067   Real v1, norm2 = 0.0;
00068   // normalize the vector 
00069   if (scale)  // if not 0.0
00070   {
00071     for (Integer i=first; i<=last; i++)
00072     { x[i] /= scale; norm2 += x[i]*x[i];}
00073   }
00074   // check if the lower part is significative
00075   if (norm2 < Arithmetic<Real>::epsilon())
00076   {
00077     v1 = x.front(); x.front() = 0.0; // beta = 0.0
00078   }
00079   else
00080   {
00081     Real s, aux1 = x.front() / scale;
00082     // compute v1 = P_v X and beta of the Householder vector
00083     v1 =  (norm2 = sign(aux1, sqrt(aux1*aux1+norm2))) * scale;
00084     // compute and save beta
00085     x.front() = (s = aux1-norm2)/norm2;
00086     // comp v and save it
00087     for (Integer i=first; i<=last; i++) x[i] /= s;
00088   }
00089   return v1;
00090 }
00091 
00100 template< class TContainer1D_1
00101         , class TContainer1D_2
00102         >
00103 Real dotHouse( const ITContainer1D<Real, TContainer1D_1>& x
00104              , const ITContainer1D<Real, TContainer1D_2>& v
00105              )
00106 {
00107   // first and last index fo the essential Householder vector
00108   const Integer first = v.first()+1, last = v.last();
00109   // compute the product
00110   Real sum = x[first-1] /* *1.0 */;
00111   for (Integer i=first; i<=last; i++) sum += x[i] * v[i];
00112   // return <x,v>
00113   return(sum);
00114 }
00115 
00124 template < class TContainer2D, class TContainer1D>
00125 void leftHouseholder( ITContainer2D< Real, TContainer2D> const& M
00126                     , ITContainer1D< Real, TContainer1D> const& v
00127                     )
00128 {
00129   // get beta
00130   Real beta = v.front();
00131   if (beta)
00132   {
00133     // get range of the Householder vector
00134     Range range_ve = v.range();
00135     // Multiplication of the cols by P=I+beta vv'
00136     for (Integer j=M.firstCol(); j<=M.lastCol(); j++)
00137     {
00138       // a ref on the jth column of M
00139       typename TContainer2D::TContainerVe Mj(M.asLeaf(), range_ve, j);
00140       // Computation of aux=beta* <v,M^j>
00141       Real aux =  dotHouse( Mj, v) * beta;
00142       // updating row X.first()
00143       Mj.front() += aux;
00144       // essential range of v
00145       const Integer first =  v.first()+1, last = v.last();
00146       // Computation of M^j + beta <v,M^j>  v = M^j + aux v
00147       for (Integer i=first; i<=last; i++)
00148         Mj[i] +=  v[i] * aux;
00149     }
00150   }
00151 }
00152 
00162 template < class TContainer2D, class TContainer1D>
00163 void rightHouseholder( ITContainer2D< Real, TContainer2D> const& M
00164                      , ITContainer1D< Real, TContainer1D> const& v
00165                      )
00166 {
00167   // get beta
00168   Real beta = v.front();
00169   if (beta)
00170   {
00171     // Multiplication of the cols by P=I+beta vv'
00172     for (Integer i=M.firstRow(); i<=M.lastRow(); i++)
00173     {
00174       // a ref on the ith row of M
00175       typename TContainer2D::TContainerHo Mi(M.asLeaf(), v.range(), i);
00176       // Computation of aux=beta* <v,M_i>
00177       Real aux =  dotHouse( Mi, v) * beta;
00178       // updating column X.first()
00179       Mi.front() += aux;
00180       // essential range of v
00181       const Integer first =  v.first()+1, last = v.last();
00182       // Computation of M_i + beta <v,M_i>  v = M_i + aux v'
00183       for (Integer i=first; i<=last; i++)
00184         Mi[i] +=  v[i] * aux;
00185     }
00186   }
00187 }
00188 
00199 template < class TContainer2D>
00200 void leftHouseholder( ITContainer2D< Real, TContainer2D> const& M
00201                     , Matrix const& H
00202                     )
00203 {
00204   // compute the number of iterations
00205   Integer first = H.firstCol(), last = min( H.lastCol(), H.lastRow());
00206   // get range of the first Householder vector
00207   Range range_ve(last, H.lastRow());
00208   // iterations
00209   for (Integer j=last; j>=first; j--)
00210   {
00211     // apply left Householder vector to M
00212     leftHouseholder(M, H(range_ve, j));
00213     // decrease range of the Householder vector
00214     range_ve.decFirst();
00215   }
00216 }
00217 
00228 template < class TContainer2D>
00229 void rightHouseholder( ITContainer2D< Real, TContainer2D> const& M
00230                      , Matrix const& H
00231                      )
00232 {
00233   // compute the number of iterations
00234   Integer first = H.firstCol(), last = min( H.lastCol(), H.lastRow());
00235   // get range of the first Householder vector
00236   Range range_ve(last, H.lastRow());
00237   // iterations
00238   for (Integer j=last; j>=first; j--)
00239   {
00240     // apply left Householder vector to M
00241     rightHouseholder(M, H(range_ve, j));
00242     // decrease range of the Householder vector
00243     range_ve.decFirst();
00244   }
00245 }
00246 
00247 } // namespace STK
00248 
00249 #endif /*STK_HOUSEHOLDER_H*/