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/hh.c 00024 * 00025 * Copyright (C) 1996, 1997, 1998, 1999, 2000, 2007 Gerard Jungman, Brian Gough 00026 * 00027 * This program is free software; you can redistribute it and/or modify 00028 * it under the terms of the GNU General Public License as published by 00029 * the Free Software Foundation; either version 3 of the License, or (at 00030 * your option) any later version. 00031 * 00032 * This program is distributed in the hope that it will be useful, but 00033 * WITHOUT ANY WARRANTY; without even the implied warranty of 00034 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00035 * General Public License for more details. 00036 * 00037 * You should have received a copy of the GNU General Public License 00038 * along with this program; if not, write to the Free Software 00039 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 00040 * 02110-1301, USA. 00041 */ 00042 /** \file hh_base.h 00043 \brief File for householder solver 00044 */ 00045 #include <o2scl/err_hnd.h> 00046 #include <o2scl/cblas.h> 00047 #include <o2scl/permutation.h> 00048 #include <o2scl/vec_arith.h> 00049 00050 #ifdef DOXYGENP 00051 namespace o2scl_linalg { 00052 #endif 00053 00054 /** 00055 \brief Solve linear system after Householder decomposition 00056 */ 00057 template<class mat_t, class vec_t, class vec2_t> 00058 int HH_solve(size_t n, mat_t &A, const vec_t &b, vec2_t &x) { 00059 for(size_t i=0;i<n;i++) O2SCL_IX(x,i)=O2SCL_IX(b,i); 00060 return HH_svx(n,n,A,x); 00061 } 00062 00063 /** 00064 \brief Solve a linear system after Householder decomposition in place 00065 00066 \future Allow the user to pre-allocate the workspace memory 00067 */ 00068 template<class mat_t, class vec_t> 00069 int HH_svx(size_t N, size_t M, mat_t &A, vec_t &x) { 00070 size_t i, j, k; 00071 00072 double *d=(double *)malloc(N*sizeof(double)); 00073 if (d == 0) { 00074 O2SCL_ERR_RET("Could not allocate memory for workspace for HH_svx().", 00075 o2scl::gsl_enomem); 00076 } 00077 00078 /* Perform Householder transformation. */ 00079 00080 for (i = 0; i < N; i++) { 00081 const double aii = O2SCL_IX2(A,i,i); 00082 double alpha; 00083 double f; 00084 double ak; 00085 double max_norm = 0.0; 00086 double r = 0.0; 00087 00088 for (k = i; k < M; k++) { 00089 double aki = O2SCL_IX2(A,k,i); 00090 r += aki * aki; 00091 } 00092 00093 if (r == 0.0) { 00094 /* Rank of matrix is less than size1. */ 00095 free(d); 00096 O2SCL_ERR_RET("Matrix is rank deficient in HH_svx().", 00097 o2scl::gsl_esing); 00098 } 00099 00100 alpha = sqrt (r) * GSL_SIGN (aii); 00101 00102 ak = 1.0 / (r + alpha * aii); 00103 O2SCL_IX2(A,i,i)=aii+alpha; 00104 00105 d[i] = -alpha; 00106 00107 for (k = i + 1; k < N; k++) { 00108 double norm = 0.0; 00109 f = 0.0; 00110 for (j = i; j < M; j++) { 00111 double ajk = O2SCL_IX2(A,j,k); 00112 double aji = O2SCL_IX2(A,j,i); 00113 norm += ajk * ajk; 00114 f += ajk * aji; 00115 } 00116 max_norm = GSL_MAX (max_norm, norm); 00117 00118 f *= ak; 00119 00120 for (j = i; j < M; j++) { 00121 double ajk = O2SCL_IX2(A,j,k); 00122 double aji = O2SCL_IX2(A,j,i); 00123 O2SCL_IX2(A,j,k)=ajk-f*aji; 00124 } 00125 } 00126 00127 if (fabs (alpha) < 2.0 * GSL_DBL_EPSILON * sqrt (max_norm)) { 00128 /* Apparent singularity. */ 00129 free(d); 00130 O2SCL_ERR_RET("Apparent singularity in HH_svx().",o2scl::gsl_esing); 00131 } 00132 00133 /* Perform update of RHS. */ 00134 00135 f = 0.0; 00136 for (j = i; j < M; j++) { 00137 f += O2SCL_IX(x,j)*O2SCL_IX2(A,j,i); 00138 } 00139 f *= ak; 00140 for (j = i; j < M; j++) { 00141 double xj = O2SCL_IX(x,j); 00142 double aji = O2SCL_IX2(A,j,i); 00143 O2SCL_IX(x,j)=xj - f * aji; 00144 } 00145 } 00146 00147 /* Perform back-substitution. */ 00148 00149 for (i = N; i-- > 0; ) { 00150 double xi = O2SCL_IX(x,i); 00151 double sum = 0.0; 00152 for (k = i + 1; k < N; k++) { 00153 sum += O2SCL_IX2(A,i,k)*O2SCL_IX(x,k); 00154 } 00155 00156 O2SCL_IX(x,i)=(xi - sum) / d[i]; 00157 } 00158 00159 free(d); 00160 00161 return o2scl::gsl_success; 00162 } 00163 00164 #ifdef DOXYGENP 00165 } 00166 #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