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 hh_base.h 00024 \brief File for householder solver 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 Desc 00038 */ 00039 template<class mat_t, class vec_t> 00040 int HH_solve(size_t n, mat_t &A, const vec_t &b, vec_t &x) { 00041 for(size_t i=0;i<n;i++) O2SCL_IX(x,i)=O2SCL_IX(b,i); 00042 return HH_svx(n,n,A,x); 00043 } 00044 00045 /** 00046 \brief Desc 00047 */ 00048 template<class mat_t, class vec_t> 00049 int HH_svx(size_t N, size_t M, mat_t &A, vec_t &x) { 00050 size_t i, j, k; 00051 00052 double *d=(double *)malloc(N*sizeof(double)); 00053 if (d == 0) { 00054 set_err_ret("Could not allocate memory for workspace for HH_svx().", 00055 o2scl::gsl_enomem); 00056 } 00057 00058 /* Perform Householder transformation. */ 00059 00060 for (i = 0; i < N; i++) { 00061 const double aii = O2SCL_IX2(A,i,i); 00062 double alpha; 00063 double f; 00064 double ak; 00065 double max_norm = 0.0; 00066 double r = 0.0; 00067 00068 for (k = i; k < M; k++) { 00069 double aki = O2SCL_IX2(A,k,i); 00070 r += aki * aki; 00071 } 00072 00073 if (r == 0.0) { 00074 /* Rank of matrix is less than size1. */ 00075 free(d); 00076 set_err_ret("Matrix is rank deficient in HH_svx().",o2scl::gsl_esing); 00077 } 00078 00079 alpha = sqrt (r) * GSL_SIGN (aii); 00080 00081 ak = 1.0 / (r + alpha * aii); 00082 O2SCL_IX2(A,i,i)=aii+alpha; 00083 00084 d[i] = -alpha; 00085 00086 for (k = i + 1; k < N; k++) { 00087 double norm = 0.0; 00088 f = 0.0; 00089 for (j = i; j < M; j++) { 00090 double ajk = O2SCL_IX2(A,j,k); 00091 double aji = O2SCL_IX2(A,j,i); 00092 norm += ajk * ajk; 00093 f += ajk * aji; 00094 } 00095 max_norm = GSL_MAX (max_norm, norm); 00096 00097 f *= ak; 00098 00099 for (j = i; j < M; j++) { 00100 double ajk = O2SCL_IX2(A,j,k); 00101 double aji = O2SCL_IX2(A,j,i); 00102 O2SCL_IX2(A,j,k)=ajk-f*aji; 00103 } 00104 } 00105 00106 if (fabs (alpha) < 2.0 * GSL_DBL_EPSILON * sqrt (max_norm)) { 00107 /* Apparent singularity. */ 00108 free(d); 00109 set_err_ret("Apparent singularity in HH_svx().",o2scl::gsl_esing); 00110 } 00111 00112 /* Perform update of RHS. */ 00113 00114 f = 0.0; 00115 for (j = i; j < M; j++) { 00116 f += O2SCL_IX(x,j)*O2SCL_IX2(A,j,i); 00117 } 00118 f *= ak; 00119 for (j = i; j < M; j++) { 00120 double xj = O2SCL_IX(x,j); 00121 double aji = O2SCL_IX2(A,j,i); 00122 O2SCL_IX(x,j)=xj - f * aji; 00123 } 00124 } 00125 00126 /* Perform back-substitution. */ 00127 00128 for (i = N; i > 0 && i--;) { 00129 double xi = O2SCL_IX(x,i); 00130 double sum = 0.0; 00131 for (k = i + 1; k < N; k++) { 00132 sum += O2SCL_IX2(A,i,k)*O2SCL_IX(x,k); 00133 } 00134 00135 O2SCL_IX(x,i)=(xi - sum) / d[i]; 00136 } 00137 00138 free(d); 00139 00140 return o2scl::gsl_success; 00141 } 00142 00143 #ifdef DOXYGENP 00144 } 00145 #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