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