00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037 #ifndef __RVL_POWALG
00038 #define __RVL_POWALG
00039
00040 #include "alg.hh"
00041 #include "linop.hh"
00042 #include "ioterm.hh";
00043
00044 namespace RVLUmin {
00045
00046 using namespace RVL;
00047 using namespace RVLAlg;
00048
00055 template <class Scalar>
00056 class PowerStep: public Algorithm {
00057
00058 typedef typename ScalarFieldTraits<Scalar>::AbsType AScalar;
00059
00060 private:
00061
00062 Vector<Scalar> & x;
00063 const LinearOp<Scalar> & A;
00064 Vector<Scalar> p;
00065 Vector<Scalar> w;
00066 AScalar & sig;
00067 AScalar & err;
00068 AScalar rq;
00069 AScalar sx;
00070
00071 PowerStep();
00072 PowerStep(PowerStep< Vector<Scalar> > const &);
00073
00074 public:
00075
00082 PowerStep( RVL::Vector<Scalar> & _x, const LinearOp<Scalar> & _A,
00083 AScalar & _sig, AScalar & _err )
00084 : x(_x),
00085 A(_A),
00086 p(A.getDomain()),
00087 w(A.getRange()),
00088 sig(_sig),
00089 err(_err),
00090 sx(ScalarFieldTraits<AScalar>::One())
00091 {
00092 AScalar one = ScalarFieldTraits<AScalar>::One();
00093 AScalar sx = one;
00094 if (ProtectedDivision<AScalar>(one,x.norm(),sx)) {
00095 RVLException e;
00096 e<<"Error: RVLUmin::PowerStep::constructor\n";
00097 e<<"zerodivide\n";
00098 throw e;
00099 }
00100 x.scale(sx);
00101 }
00102
00106 void run() {
00107
00108 try {
00109 AScalar one = ScalarFieldTraits<AScalar>::One();
00110 A.applyOp(x,w);
00111 rq = w.normsq();
00112 if (rq < ScalarFieldTraits<AScalar>::Zero()) {
00113 RVLException e;
00114 e<<"Error: PowerMethod::run\n";
00115 e<<"computed apparently negative Rayleigh quotient\n";
00116 throw e;
00117 }
00118 sig=sqrt(rq);
00119 if (ProtectedDivision<AScalar>(one,rq,err)) {
00120 sig=ScalarFieldTraits<AScalar>::Zero();
00121 err=ScalarFieldTraits<AScalar>::One();
00122 }
00123 else {
00124 A.applyAdjOp(w,p);
00125
00126 p.linComb(-rq,x);
00127
00128 err*=p.norm();
00129
00130 p.linComb(rq,x);
00131
00132 if (ProtectedDivision<AScalar>(one,p.norm(),sx)) {
00133 RVLException e;
00134 e<<"Error: RVLUmin::PowerStep::run\n";
00135 e<<"zerodivide\n";
00136 throw e;
00137 }
00138
00139 x.scale(sx,p);
00140 }
00141 }
00142
00143 catch (RVLException & e) {
00144 e<<"\ncalled from PowerStep::run\n";
00145 throw e;
00146 }
00147 }
00148 };
00149
00180 template<typename Scalar>
00181 class PowerMethod: public Algorithm {
00182
00183 typedef typename ScalarFieldTraits<Scalar>::AbsType AScalar;
00184
00185 private:
00186
00187 AScalar err;
00188 PowerStep<Scalar> step;
00189 std::vector<std::string> names;
00190 std::vector<AScalar *> nums;
00191 std::vector<AScalar> tols;
00192 int _nstep;
00193 int it;
00194 ostream & _str;
00195
00196 public:
00197
00206 PowerMethod(Vector<Scalar> & x,
00207 AScalar & sig,
00208 LinearOp<Scalar> const & A,
00209 int nstep, AScalar tol, ostream & str)
00210 : err(ScalarFieldTraits<AScalar>::One()),
00211 step(x,A,sig,err),_nstep(nstep),_str(str),
00212 names(2),nums(2),tols(2), it(0) {
00213 names[0]="Relative Residual"; nums[0]=&err; tols[0]=tol;
00214 names[1]="Est Singular Value"; nums[1]=&sig; tols[1]=ScalarFieldTraits<AScalar>::Zero();
00215 }
00216
00217 void run() {
00218 try {
00219 VectorCountingThresholdIterationTable<Scalar> term(_nstep,names, nums, tols,_str);
00220 term.init();
00221 LoopAlg l(step,term);
00222 l.run();
00223 it=term.getCount();
00224 }
00225 catch (RVLException & e) {
00226 e<<"\ncalled from PowerMethod::run\n";
00227 throw e;
00228 }
00229 }
00230
00231 int getCount() { return it; }
00232 };
00233
00234 }
00235
00236 #endif