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 Desc 00056 */ 00057 template<class mat_t, class vec_t> 00058 int HH_solve(size_t n, mat_t &A, const vec_t &b, vec_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 Desc 00065 */ 00066 template<class mat_t, class vec_t> 00067 int HH_svx(size_t N, size_t M, mat_t &A, vec_t &x) { 00068 size_t i, j, k; 00069 00070 double *d=(double *)malloc(N*sizeof(double)); 00071 if (d == 0) { 00072 O2SCL_ERR_RET("Could not allocate memory for workspace for HH_svx().", 00073 o2scl::gsl_enomem); 00074 } 00075 00076 /* Perform Householder transformation. */ 00077 00078 for (i = 0; i < N; i++) { 00079 const double aii = O2SCL_IX2(A,i,i); 00080 double alpha; 00081 double f; 00082 double ak; 00083 double max_norm = 0.0; 00084 double r = 0.0; 00085 00086 for (k = i; k < M; k++) { 00087 double aki = O2SCL_IX2(A,k,i); 00088 r += aki * aki; 00089 } 00090 00091 if (r == 0.0) { 00092 /* Rank of matrix is less than size1. */ 00093 free(d); 00094 O2SCL_ERR_RET("Matrix is rank deficient in HH_svx().",o2scl::gsl_esing); 00095 } 00096 00097 alpha = sqrt (r) * GSL_SIGN (aii); 00098 00099 ak = 1.0 / (r + alpha * aii); 00100 O2SCL_IX2(A,i,i)=aii+alpha; 00101 00102 d[i] = -alpha; 00103 00104 for (k = i + 1; k < N; k++) { 00105 double norm = 0.0; 00106 f = 0.0; 00107 for (j = i; j < M; j++) { 00108 double ajk = O2SCL_IX2(A,j,k); 00109 double aji = O2SCL_IX2(A,j,i); 00110 norm += ajk * ajk; 00111 f += ajk * aji; 00112 } 00113 max_norm = GSL_MAX (max_norm, norm); 00114 00115 f *= ak; 00116 00117 for (j = i; j < M; j++) { 00118 double ajk = O2SCL_IX2(A,j,k); 00119 double aji = O2SCL_IX2(A,j,i); 00120 O2SCL_IX2(A,j,k)=ajk-f*aji; 00121 } 00122 } 00123 00124 if (fabs (alpha) < 2.0 * GSL_DBL_EPSILON * sqrt (max_norm)) { 00125 /* Apparent singularity. */ 00126 free(d); 00127 O2SCL_ERR_RET("Apparent singularity in HH_svx().",o2scl::gsl_esing); 00128 } 00129 00130 /* Perform update of RHS. */ 00131 00132 f = 0.0; 00133 for (j = i; j < M; j++) { 00134 f += O2SCL_IX(x,j)*O2SCL_IX2(A,j,i); 00135 } 00136 f *= ak; 00137 for (j = i; j < M; j++) { 00138 double xj = O2SCL_IX(x,j); 00139 double aji = O2SCL_IX2(A,j,i); 00140 O2SCL_IX(x,j)=xj - f * aji; 00141 } 00142 } 00143 00144 /* Perform back-substitution. */ 00145 00146 for (i = N; i-- > 0; ) { 00147 double xi = O2SCL_IX(x,i); 00148 double sum = 0.0; 00149 for (k = i + 1; k < N; k++) { 00150 sum += O2SCL_IX2(A,i,k)*O2SCL_IX(x,k); 00151 } 00152 00153 O2SCL_IX(x,i)=(xi - sum) / d[i]; 00154 } 00155 00156 free(d); 00157 00158 return o2scl::gsl_success; 00159 } 00160 00161 #ifdef DOXYGENP 00162 } 00163 #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