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 #ifndef __RVL_LINOP_APPS
00034 #define __RVL_LINOP_APPS
00035
00036 #include "op.hh"
00037
00038 namespace RVL {
00039
00045 template<class Scalar>
00046 class CompLinearOp: public LinearOp<Scalar> {
00047
00048 private:
00049
00050 std::vector<LinearOp<Scalar> const *> ops;
00051 mutable bool applied;
00052
00053 protected:
00054
00055 virtual LinearOp<Scalar> * clone() const {
00056 return new CompLinearOp<Scalar>(*this);
00057 }
00058
00059 void apply(const Vector<Scalar> & x,
00060 Vector<Scalar> & y) const {
00061 try {
00062 applied=true;
00063 if (ops.size()==0) {
00064 RVLException e;
00065 e<<"ERROR: CompLinearOp::apply\n";
00066 e<<" attempted with unitialized factors\n";
00067 throw e;
00068 }
00069 else if (ops.size()==1) ops[0]->applyOp(x,y);
00070 else if (ops.size()==2) {
00071 Vector<Scalar> z(ops[0]->getRange());
00072 ops[0]->applyOp(x,z);
00073 ops[1]->applyOp(z,y);
00074 }
00075 else {
00076 shared_ptr<Vector<Scalar> > z;
00077 shared_ptr<Vector<Scalar> > w = RVL::Vector<Scalar>::newPtr(ops[0]->getRange());
00078 ops[0]->applyOp(x,*w);
00079 for (size_t i=1; i<ops.size()-1; i++) {
00080 z=RVL::Vector<Scalar>::newPtr(ops[i]->getRange());
00081 ops[i]->applyOp(*w,*z);
00082 w=z;
00083 }
00084 ops[ops.size()-1]->applyOp(*w,y);
00085 }
00086 }
00087 catch (RVLException & e) {
00088 e<<"\ncalled from CompLinearOp::apply\n";
00089 throw e;
00090 }
00091 }
00092
00093 void applyAdj(const Vector<Scalar> & x,
00094 Vector<Scalar> & y) const {
00095 try {
00096 applied=true;
00097 if (ops.size()==0) {
00098 RVLException e;
00099 e<<"ERROR: CompLinearOp::applyAdj\n";
00100 e<<" attempted with unitialized factors\n";
00101 throw e;
00102 }
00103 else if (ops.size()==1) ops[0]->applyAdjOp(x,y);
00104 else if (ops.size()==2) {
00105 Vector<Scalar> z(ops[0]->getRange());
00106 ops[1]->applyAdjOp(x,z);
00107 ops[0]->applyAdjOp(z,y);
00108 }
00109 else {
00110 shared_ptr<Vector<Scalar> > z = RVL::Vector<Scalar>::newPtr(ops[ops.size()-1]->getDomain());
00111 shared_ptr<Vector<Scalar> > w;
00112 ops[ops.size()-1]->applyAdjOp(x,*z);
00113 for (size_t i=ops.size()-2; i>=1; i--) {
00114 w=z;
00115 z=RVL::Vector<Scalar>::newPtr(ops[i]->getDomain());
00116 ops[i]->applyAdjOp(*w,*z);
00117 }
00118 ops[0]->applyAdjOp(*z,y);
00119 }
00120 }
00121 catch (RVLException & e) {
00122 e<<"\ncalled from CompLinearOp::applyAdj\n";
00123 throw e;
00124 }
00125 }
00126
00127 public:
00128
00129 CompLinearOp(): ops(0), applied(false) {}
00130
00131 CompLinearOp(LinearOp<Scalar> const & _op1,
00132 LinearOp<Scalar> const & _op2): applied(false) {
00133 try {
00134
00135 ops.push_back(dynamic_cast<RVL::LinearOp<float> const *>
00136 (RVL::Operator<float>::export_clone(_op1)));
00137 ops.push_back(dynamic_cast<RVL::LinearOp<float> const *>
00138 (RVL::Operator<float>::export_clone(_op2)));
00139 if (!ops[0] || !ops[1]) {
00140 RVLException e;
00141 e<<"ERROR: CompLinearOp constructor\n";
00142 e<<" something seriously wrong - failed to record inputs as LinearOps\n";
00143 throw e;
00144 }
00145
00146 if (ops[1]->getDomain() != ops[0]->getRange()) {
00147 RVLException e;
00148 e<<"Error: CompLinearOp constructor\n";
00149 e<<" incompatible domains or ranges\n";
00150 e<<"\n";
00151 e<<" **** operator 1:\n";
00152 ops[0]->write(e);
00153 e<<"\n";
00154 e<<" **** operator 2:\n";
00155 ops[1]->write(e);
00156 e<<"\n";
00157 throw e;
00158 }
00159 }
00160 catch (RVLException & e) {
00161 e<<"\ncalled from CompLinearOp::CompLinearOp\n";
00162 throw e;
00163 }
00164 }
00165
00166 CompLinearOp(CompLinearOp const & op): applied(op.applied) {
00167 for (size_t i=0; i<op.ops.size();i++) {
00168 ops.push_back(dynamic_cast<LinearOp<Scalar> const *>
00169 (RVL::Operator<float>::export_clone(*(op.ops[i]))));
00170 }
00171 }
00172
00173 void setNext(LinearOp<Scalar> const & lop) {
00174 if (applied) {
00175 RVLException e;
00176 e<<"ERROR: CompLinearOp::setNext\n";
00177 e<<" already initialized, used - effectively const\n";
00178 throw e;
00179 }
00180 if (ops.size()>0) {
00181 if (ops[ops.size()-1]->getRange() != lop.getDomain()) {
00182 RVLException e;
00183 e<<"ERROR: CompLinearOp::setNext\n";
00184 e<<" input operator domain not same as last added operator range\n";
00185 e<<" domain:\n";
00186 lop.getDomain().write(e);
00187 e<<" range:\n";
00188 ops[ops.size()-1]->getRange().write(e);
00189 throw e;
00190 }
00191 }
00192 ops.push_back(dynamic_cast<RVL::LinearOp<float> const *>
00193 (RVL::Operator<float>::export_clone(lop)));
00194 }
00195
00196 const Space<Scalar> & getDomain() const {
00197 return ops[0]->getDomain();
00198 }
00199
00200 const Space<Scalar> & getRange() const {
00201 return ops[ops.size()-1]->getRange();
00202 }
00203
00204 ostream & write(ostream & str) const {
00205 str<<"CompLinearOp - composition of linear ops\n";
00206 str<<"\n";
00207 str<<"in order of application:\n";
00208 for (size_t i=0; i<ops.size()-1; i++) {
00209 str<<"**** operator "<<i<<"\n";
00210 ops[i]->write(str);
00211 str<<"\n";
00212 }
00213 return str;
00214 }
00215 };
00216 }
00217
00218 #endif