00001 /* 00002 ------------------------------------------------------------------- 00003 00004 Copyright (C) 2006, 2007, 2008, Andrew W. Steiner 00005 00006 This file is part of O2scl. 00007 00008 O2scl is free software; you can redistribute it and/or modify 00009 it under the terms of the GNU General Public License as published by 00010 the Free Software Foundation; either version 3 of the License, or 00011 (at your option) any later version. 00012 00013 O2scl is distributed in the hope that it will be useful, 00014 but WITHOUT ANY WARRANTY; without even the implied warranty of 00015 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00016 GNU General Public License for more details. 00017 00018 You should have received a copy of the GNU General Public License 00019 along with O2scl. If not, see <http://www.gnu.org/licenses/>. 00020 00021 ------------------------------------------------------------------- 00022 */ 00023 /** \file householder_base.h 00024 \brief File for Householder transformations 00025 */ 00026 00027 #include <o2scl/err_hnd.h> 00028 #include <o2scl/cblas.h> 00029 #include <o2scl/permutation.h> 00030 #include <o2scl/vec_arith.h> 00031 00032 #ifdef DOXYGENP 00033 namespace o2scl_linalg { 00034 #endif 00035 00036 /** 00037 \brief Replace the vector \c v with a householder vector and a 00038 coefficient tau that annihilates the last \c n-1 elements of 00039 \c v. 00040 */ 00041 template<class vec_t> 00042 double householder_transform(const size_t n, vec_t &v) { 00043 00044 if (n == 1) { 00045 /* tau = 0 */ 00046 return 0.0; 00047 } else { 00048 double alpha, beta, tau ; 00049 00050 double xnorm = o2scl_cblas::dnrm2_subvec(n,v,1); 00051 00052 if (xnorm == 0) { 00053 /* tau = 0 */ 00054 return 0.0; 00055 } 00056 00057 alpha = O2SCL_IX(v,0); 00058 beta = - (alpha >= 0.0 ? +1.0 : -1.0) * hypot(alpha, xnorm) ; 00059 tau = (beta - alpha) / beta ; 00060 00061 o2scl_cblas::dscal_subvec(n,1.0/(alpha-beta),v,1); 00062 O2SCL_IX(v,0)=beta; 00063 00064 return tau; 00065 } 00066 } 00067 00068 /** 00069 \brief Compute the householder transform of a vector 00070 formed with the last \c n rows of a column of a matrix 00071 00072 Used in QR_decomp(). 00073 */ 00074 template<class mat_t> 00075 double householder_transform_subcol(mat_t &A, const size_t ir, 00076 const size_t ic, const size_t n) { 00077 00078 if (n == 1) { 00079 /* tau = 0 */ 00080 return 0.0; 00081 } else { 00082 double alpha, beta, tau ; 00083 00084 double xnorm = o2scl_cblas::dnrm2_subcol(A,ir+1,ic,n-1); 00085 00086 if (xnorm == 0) { 00087 /* tau = 0 */ 00088 return 0.0; 00089 } 00090 00091 alpha=O2SCL_IX2(A,ir,ic); 00092 beta = - (alpha >= 0.0 ? +1.0 : -1.0) * hypot(alpha, xnorm) ; 00093 tau = (beta - alpha) / beta ; 00094 00095 o2scl_cblas::dscal_subcol(A,ir+1,ic,n-1,1.0/(alpha-beta)); 00096 O2SCL_IX2(A,ir,ic)=beta; 00097 00098 return tau; 00099 } 00100 } 00101 00102 /** \brief Apply a householder transformation v,tau to matrix m */ 00103 template<class vec_t, class mat_t> 00104 int householder_hm(const size_t M, const size_t N, 00105 double tau, const vec_t &v, mat_t &A) { 00106 00107 if (tau == 0.0) { 00108 return o2scl::gsl_success; 00109 } 00110 00111 size_t i, j; 00112 00113 for (j = 0; j < N; j++) { 00114 00115 /* Compute wj = Akj vk */ 00116 double wj = O2SCL_IX2(A,0,j); 00117 00118 for (i = 1; i < M; i++) { 00119 wj += O2SCL_IX2(A,i,j)*O2SCL_IX(v,i); 00120 } 00121 00122 /* Aij = Aij - tau vi wj */ 00123 00124 /* i = 0 */ 00125 O2SCL_IX2(A,0,j)-=tau*wj; 00126 00127 /* i = 1 .. M-1 */ 00128 for (i = 1; i < M; i++) { 00129 double Aij = O2SCL_IX2(A,i,j); 00130 double vi = O2SCL_IX(v,i); 00131 O2SCL_IX2(A,i,j)=Aij - tau * vi * wj; 00132 } 00133 } 00134 return o2scl::gsl_success; 00135 } 00136 00137 /** \brief Apply a householder transformation \c v, \c tau 00138 to submatrix of m 00139 00140 Used in QR_decomp(). 00141 */ 00142 template<class mat_t> 00143 int householder_hm_sub(mat_t &M, const size_t ir, 00144 const size_t ic, const size_t nr, 00145 const size_t nc, const mat_t &M2, 00146 const size_t ir2, const size_t ic2, 00147 double tau) { 00148 00149 if (tau == 0.0) { 00150 return o2scl::gsl_success; 00151 } 00152 00153 size_t i, j; 00154 00155 for (j = ic; j < ic+nc; j++) { 00156 00157 /* Compute wj = Akj vk */ 00158 double wj = O2SCL_IX2(M,ir,j); 00159 00160 for (i = ir+1; i < ir+nr; i++) { 00161 wj += O2SCL_IX2(M,i,j)*O2SCL_IX2(M2,i-ir+ir2,ic2); 00162 } 00163 00164 /* Aij = Aij - tau vi wj */ 00165 00166 /* i = 0 */ 00167 O2SCL_IX2(M,ir,j)-=tau*wj; 00168 00169 /* i = 1 .. M-1 */ 00170 for (i = ir+1; i < ir+nr; i++) { 00171 double Aij = O2SCL_IX2(M,i,j); 00172 double vi = O2SCL_IX2(M2,i-ir+ir2,ic2); 00173 O2SCL_IX2(M,i,j)=Aij - tau * vi * wj; 00174 } 00175 } 00176 return o2scl::gsl_success; 00177 } 00178 00179 /** 00180 \brief Apply a householder transformation \c v to vector \c w 00181 */ 00182 template<class vec_t> 00183 int householder_hv(const size_t N, double tau, const vec_t &v, vec_t &w) { 00184 00185 if (tau==0) return o2scl::gsl_success; 00186 00187 // compute d=v'w 00188 00189 double d0=O2SCL_IX(w,0); 00190 double d1, d; 00191 00192 d1=o2scl_cblas::ddot_subvec(N,v,w,1); 00193 00194 d=d0+d1; 00195 00196 // compute w=w-tau(v)(v'w) 00197 double w0=O2SCL_IX(w,0); 00198 O2SCL_IX(w,0)=w0-tau*d; 00199 00200 o2scl_cblas::daxpy_subvec(N,-tau*d,v,w,1); 00201 00202 return o2scl::gsl_success; 00203 } 00204 00205 /** 00206 \brief Apply a householder transformation \c v to vector \c w 00207 00208 Used in QR_QTvec(). 00209 */ 00210 template<class mat_t, class vec_t> 00211 int householder_hv_sub(const mat_t &M, vec_t &w, double tau, 00212 const size_t ie, const size_t N) { 00213 00214 if (tau==0) return o2scl::gsl_success; 00215 00216 // compute d=v'w 00217 00218 double d0=O2SCL_IX(w,ie); 00219 double d1, d; 00220 00221 d1=o2scl_cblas::ddot_hv_sub(N,M,w,ie); 00222 00223 d=d0+d1; 00224 00225 // compute w=w-tau(v)(v'w) 00226 double w0=O2SCL_IX(w,ie); 00227 O2SCL_IX(w,ie)=w0-tau*d; 00228 00229 o2scl_cblas::daxpy_hv_sub(N,-tau*d,M,w,ie); 00230 00231 return o2scl::gsl_success; 00232 } 00233 00234 /** 00235 \brief Special version of householder transformation for 00236 QR_unpack() 00237 */ 00238 template<class mat1_t, class mat2_t> 00239 int householder_hm_sub2(const size_t M, const size_t ic, 00240 double tau, const mat1_t &mv, mat2_t &A) { 00241 00242 if (tau == 0.0) { 00243 return o2scl::gsl_success; 00244 } 00245 00246 size_t i, j; 00247 00248 for (j = ic; j < M; j++) { 00249 00250 /* Compute wj = Akj vk */ 00251 double wj = O2SCL_IX2(A,ic,j); 00252 00253 for (i = ic+1; i < M; i++) { 00254 wj += O2SCL_IX2(A,i,j)*O2SCL_IX2(mv,i,ic); 00255 } 00256 00257 /* Aij = Aij - tau vi wj */ 00258 00259 /* i = 0 */ 00260 O2SCL_IX2(A,ic,j)-=tau*wj; 00261 00262 /* i = 1 .. M-1 */ 00263 for (i = ic+1; i < M; i++) { 00264 double Aij = O2SCL_IX2(A,i,j); 00265 double vi = O2SCL_IX2(mv,i,ic); 00266 O2SCL_IX2(A,i,j)=Aij - tau * vi * wj; 00267 } 00268 } 00269 return o2scl::gsl_success; 00270 } 00271 00272 #ifdef DOXYGENP 00273 } 00274 #endif
Documentation generated with Doxygen and provided under the GNU Free Documentation License. See License Information for details.
Project hosting provided by
,
O2scl Sourceforge Project Page