00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #ifndef SELDON_FILE_ITERATIVE_LSQR_CXX
00021
00022 namespace Seldon
00023 {
00024
00026
00040 template <class Titer, class Matrix1, class Vector1, class Preconditioner>
00041 int Lsqr(Matrix1& A, Vector1& x, const Vector1& b,
00042 Preconditioner& M, Iteration<Titer> & iter)
00043 {
00044 const int N = A.GetM();
00045 if (N <= 0)
00046 return 0;
00047
00048 typedef typename Vector1::value_type Complexe;
00049 Complexe rho, rho_bar, phi, phi_bar, theta, c, s, tmp;
00050 Titer beta, alpha, rnorm;
00051 Vector1 v(b), v1(b), u(b), u1(b), w(b);
00052
00053 int success_init = iter.Init(b);
00054 if (success_init != 0)
00055 return iter.ErrorCode();
00056
00057 Copy(b, u);
00058 if (!iter.IsInitGuess_Null())
00059 MltAdd(Complexe(-1), A, x, Complexe(1), u);
00060 else
00061 x.Zero();
00062
00063 rnorm = Norm2(u);
00064
00065 Copy(b, u);
00066 beta = Norm2(u);
00067 tmp = 1.0/beta; Mlt(tmp, u);
00068
00069 Mlt(SeldonTrans,A, u, v);
00070 alpha = Norm2(v);
00071 tmp = 1.0/alpha; Mlt(tmp, v);
00072
00073 Copy(v,w); x.Zero();
00074
00075 phi_bar = beta; rho_bar = alpha;
00076
00077 iter.SetNumberIteration(0);
00078
00079 while (! iter.Finished(rnorm))
00080 {
00081
00082 Mlt(A, v, u1);
00083
00084 Add(-alpha, u, u1);
00085 beta = Norm2(u1);
00086 if (beta == Complexe(0) )
00087 {
00088 iter.Fail(1, "Lsqr breakdown #1");
00089 break;
00090 }
00091 tmp = 1.0/beta; Mlt(tmp, u1);
00092
00093
00094 Mlt(SeldonTrans, A, u1, v1);
00095
00096 Add(-beta, v, v1);
00097 alpha = Norm2(v1);
00098 if (alpha == Complexe(0) )
00099 {
00100 iter.Fail(2, "Lsqr breakdown #2");
00101 break;
00102 }
00103 tmp = 1.0/alpha; Mlt(tmp, v1);
00104
00105 rho = sqrt(rho_bar*rho_bar+beta*beta);
00106 if (rho == Complexe(0) )
00107 {
00108 iter.Fail(3, "Lsqr breakdown #3");
00109 break;
00110 }
00111
00112 c = rho_bar/rho;
00113 s = beta / rho;
00114 theta = s*alpha;
00115 rho_bar = -c * alpha;
00116 phi = c * phi_bar;
00117 phi_bar = s * phi_bar;
00118
00119
00120 tmp = phi/rho;
00121 Add(tmp, w, x);
00122
00123 tmp = -theta/rho;
00124 Mlt(tmp,w); Add(Complexe(1), v1, w);
00125
00126 rnorm = abs(phi_bar);
00127
00128 Swap(u1,u); Swap(v1,v);
00129
00130 ++iter;
00131 ++iter;
00132 }
00133
00134 return iter.ErrorCode();
00135 }
00136
00137 }
00138
00139 #define SELDON_FILE_ITERATIVE_LSQR_CXX
00140 #endif