linop_apps.hh

Go to the documentation of this file.
00001 /*************************************************************************
00002 
00003 Copyright Rice University, 2004, 2005, 2006
00004 All rights reserved.
00005 
00006 Permission is hereby granted, free of charge, to any person obtaining a
00007 copy of this software and associated documentation files (the "Software"),
00008 to deal in the Software without restriction, including without limitation
00009 the rights to use, copy, modify, merge, publish, distribute, and/or sell
00010 copies of the Software, and to permit persons to whom the Software is
00011 furnished to do so, provided that the above copyright notice(s) and this
00012 permission notice appear in all copies of the Software and that both the
00013 above copyright notice(s) and this permission notice appear in supporting
00014 documentation.
00015 
00016 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00017 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00018 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY
00019 RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS
00020 NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL
00021 DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
00022 PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
00023 ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
00024 THIS SOFTWARE.
00025 
00026 Except as contained in this notice, the name of a copyright holder shall
00027 not be used in advertising or otherwise to promote the sale, use or other
00028 dealings in this Software without prior written authorization of the
00029 copyright holder.
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

Generated on 5 Jan 2017 for RVL by  doxygen 1.4.7