op.hh

Go to the documentation of this file.
00001 /*************************************************************************
00002 
00003 Copyright Rice University, 2004-2015.
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_OP
00034 #define __RVL_OP
00035 
00036 #include "space.hh"
00037 #include "linop_base.hh"
00038 #include "productspace.hh"
00039 #include "write.hh"
00040 
00041 namespace RVL {
00042 
00043   // forward declarations required for extra-class friendships
00044   
00045   template<class Scalar> 
00046   class OperatorEvaluation;
00047 
00048   template<class Scalar> 
00049   class DerivEvaluation;
00050 
00051   template<class Scalar> 
00052   class Deriv2Evaluation;
00053 
00054   template<class Scalar>
00055   class OpComp;
00056 
00057   template<class Scalar>
00058   class FcnlOpComp;
00059 
00111   template<class Scalar> 
00112   class Operator: public Writeable {
00113 
00114     friend class OperatorEvaluation<Scalar>;
00115     friend class FcnlOpComp<Scalar>; 
00116 
00117   protected:
00118 
00124     virtual void apply(const Vector<Scalar> & x, 
00125                Vector<Scalar> & y) const = 0;
00126 
00128     virtual void applyDeriv(const Vector<Scalar> & x, 
00129                 const Vector<Scalar> & dx,
00130                 Vector<Scalar> & dy) const = 0;
00131 
00133     virtual void applyAdjDeriv(const Vector<Scalar> & x, 
00134                    const Vector<Scalar> & dy,
00135                    Vector<Scalar> & dx) const = 0;
00136 
00137     /* \f$ dy=D^2F(x)(dx_0,dx_1) \f$
00138        implemented to throw exception - override in subclasses 
00139        that need 2nd deriv.
00140     */
00141     virtual void applyDeriv2(const Vector<Scalar> &, 
00142                  const Vector<Scalar> &,
00143                  const Vector<Scalar> &,
00144                  Vector<Scalar> &) const {
00145       RVLException e;
00146       e<<"Error: Operator::applyDeriv2 not implemented\n";
00147       throw e;
00148     }
00149 
00157     virtual void applyAdjDeriv2(const Vector<Scalar> &,
00158                 const Vector<Scalar> &,
00159                 const Vector<Scalar> &,
00160                 Vector<Scalar> &) const {
00161       RVLException e;
00162       e<<"Error: Operator::applyAdjDeriv2 not implemented\n";
00163       throw e;
00164     }
00165 
00170     static void export_apply(Operator<Scalar> const & f,
00171                  const Vector<Scalar> & x,
00172                  Vector<Scalar> & y) {
00173       f.apply(x,y);
00174     }
00175 
00176     static void export_applyDeriv(Operator<Scalar> const & f,
00177                   const Vector<Scalar> & x,
00178                   const Vector<Scalar> & dx,
00179                   Vector<Scalar> & dy) {
00180       f.applyDeriv(x,dx,dy);
00181     }
00182 
00183     static void export_applyAdjDeriv(Operator<Scalar> const & f,
00184                      const Vector<Scalar> & x,
00185                      const Vector<Scalar> & dy,
00186                      Vector<Scalar> & dx) {
00187       f.applyAdjDeriv(x,dy,dx);
00188     }
00189 
00190     static void export_applyDeriv2(Operator<Scalar> const & f,
00191                    const Vector<Scalar> & x,
00192                    const Vector<Scalar> & dx0,
00193                    const Vector<Scalar> & dx1,
00194                    Vector<Scalar> & dy) {
00195       f.applyDeriv2(x,dx0,dx1,dy);
00196     }
00197 
00198     static void export_applyAdjDeriv2(Operator<Scalar> const & f,
00199                       const Vector<Scalar> & x,
00200                       const Vector<Scalar> & dx0,
00201                       const Vector<Scalar> & dy,
00202                       Vector<Scalar> & dx1) {
00203       f.applyAdjDeriv2(x,dx0,dy,dx1);
00204     }
00205 
00213 #ifndef RVL_OPERATOR_NEW_ENABLED
00214     void * operator new(size_t size) { 
00215       void * ptr;
00216       ptr = (void *) ::new unsigned char[size]; 
00217       return ptr;
00218     }
00219 #endif
00220 
00225     virtual Operator<Scalar> * clone() const = 0;
00226 
00228     static Operator<Scalar> * export_clone(Operator<Scalar> const & op) {
00229       return op.clone();
00230     }
00231     
00236     DerivEvaluation<Scalar> * 
00237     createDerivEvaluation(OperatorEvaluation<Scalar> & opeval) const {
00238       return new DerivEvaluation<Scalar>(opeval);
00239     }
00240 
00246     Deriv2Evaluation<Scalar> * 
00247     createDeriv2Evaluation(OperatorEvaluation<Scalar> & opeval) const {
00248       return new Deriv2Evaluation<Scalar>(opeval);
00249     }
00250 
00251   public:
00252 
00253     using Writeable::write;
00254 
00255     Operator() {}
00256     Operator(const Operator<Scalar> &) {}
00257     virtual ~Operator() {}
00258 
00260     virtual const Space<Scalar> & getDomain() const = 0;
00261     virtual const Space<Scalar> & getRange() const = 0;
00262 
00264     static std::shared_ptr<Operator<Scalar> > clonePtr(Operator<Scalar> const & op) {
00265       std::shared_ptr<Operator<Scalar> > p(RVL::Operator<Scalar>::export_clone(op));
00266       return p;
00267     }
00268     
00273     virtual typename ScalarFieldTraits<Scalar>::AbsType 
00274     getMaxStep(const Vector<Scalar> &,
00275            const Vector<Scalar> &) const {
00276       return numeric_limits<typename ScalarFieldTraits<Scalar>::AbsType>::max();
00277     }
00278 
00279   };
00280 
00281   template<class Scalar>
00282   class OperatorProductDomainEvaluation;
00283 
00284   template<class Scalar>
00285   class PartialDerivEvaluation;
00286 
00287   template<class Scalar>
00288   class RestrictOp;
00289 
00297   template<class Scalar> 
00298   class OperatorProductDomain: public Operator<Scalar> {
00299 
00300     friend class OperatorEvaluation<Scalar>;
00301     friend class RestrictOp<Scalar>;
00302 
00303   protected:
00304 
00306     virtual void applyPartialDeriv(int i,
00307                    const Vector<Scalar> & x, 
00308                    const Vector<Scalar> & dxi,
00309                    Vector<Scalar> & dy) const = 0;
00310   
00315     virtual void applyDeriv(const Vector<Scalar> & x, 
00316                 const Vector<Scalar> & dx,
00317                 Vector<Scalar> & dy) const {
00318       try {
00319     Components<Scalar> dxc(dx);
00320     applyPartialDeriv(0,x,dxc[0],dy);
00321     Vector<Scalar> tmp(dy);
00322     for (int i=1; i<dxc.getSize(); i++) {
00323       applyPartialDeriv(i,x,dxc[i],tmp);
00324       dy.linComb(1.0,tmp);
00325     }
00326       }
00327       catch (RVLException & e) {
00328     e<<"\ncalled from OperatorProductDomain::applyDeriv\n";
00329     throw e;
00330       }
00331     }
00332 
00334     virtual void applyAdjPartialDeriv(int i,
00335                       const Vector<Scalar> & x, 
00336                       const Vector<Scalar> & dy,
00337                       Vector<Scalar> & dxi) const = 0;
00338 
00342     virtual void applyAdjDeriv(const Vector<Scalar> & x, 
00343                    const Vector<Scalar> & dy,
00344                    Vector<Scalar> & dx) const {
00345       try {
00346     Components<Scalar> dxc(dx);
00347     for (int i=0; i<dxc.getSize(); i++) {
00348       applyAdjPartialDeriv(i,x,dy,dxc[i]);
00349     }
00350       }
00351       catch (RVLException & e) {
00352     e<<"\ncalled from OperatorProductDomain::applyAdjDeriv\n";
00353     throw e;
00354       }
00355     }
00356 
00360     virtual void applyPartialDeriv2(int i, int j,
00361                     const Vector<Scalar> & x, 
00362                     const Vector<Scalar> & dxi,
00363                     const Vector<Scalar> & dxj,
00364                     Vector<Scalar> & dy) const {
00365       RVLException e;
00366       e<<"ERROR: no override for applyPartialDeriv2 supplied for \n";
00367       e<<"OperatorProductDomain:\n";
00368       this->write(e);
00369       throw e;
00370     }
00371 
00376     virtual void applyDeriv2(const Vector<Scalar> & x, 
00377                  const Vector<Scalar> & dx0,
00378                  const Vector<Scalar> & dx1,
00379                  Vector<Scalar> & dy) const {
00380       try {
00381     Components<Scalar> cdx0(dx0);
00382     Components<Scalar> cdx1(dx1);
00383     dy.zero();
00384     Vector<Scalar> tmp(this->getRange());
00385     int dim = (this->getProductDomain()).getSize();
00386     for (int i=0; i<dim; i++) {
00387       for (int j=0; j<dim; j++) {
00388         this->applyPartialDeriv2(i,j,x,cdx0[i],cdx1[j],tmp);
00389         dy.linComb(1.0,tmp);
00390       }
00391     }
00392       }
00393       catch (RVLException & e) {
00394     e<<"\ncalled from OperatorProductDomain::applyDeriv2\n";
00395     throw e;
00396       }
00397     }
00398 
00405     virtual void applyAdjPartialDeriv2(int i, int j,
00406                        const Vector<Scalar> & x, 
00407                        const Vector<Scalar> & dy,
00408                        const Vector<Scalar> & dxj,
00409                        Vector<Scalar> & dxi) const {
00410       RVLException e;
00411       e<<"ERROR: no override for applyAdjPartialDeriv2 supplied for \n";
00412       e<<"OperatorProductDomain:\n";
00413       this->write(e);
00414       throw e;
00415     }
00416 
00421     virtual void applyAdjDeriv2(const Vector<Scalar> & x, 
00422                 const Vector<Scalar> & dy,
00423                 const Vector<Scalar> & dx1,
00424                 Vector<Scalar> & dx0) const {
00425       try {
00426     Components<Scalar> cdx0(dx0);
00427     Components<Scalar> cdx1(dx1);
00428     dx0.zero();
00429     Vector<Scalar> tmp(this->getDomain());
00430     Components<Scalar> ctmp(tmp);
00431     int dim = (this->getProductDomain()).getSize();
00432     for (int i=0; i<dim; i++) {
00433       for (int j=0; j<dim; j++) {
00434         this->applyAdjPartialDeriv2(i,j,x,dy,cdx1[j],ctmp[i]);
00435         cdx0[i].linComb(1.0,ctmp[i]);
00436       }
00437     }
00438       }
00439       catch (RVLException & e) {
00440     e<<"\ncalled from OperatorProductDomain::applyAdjDeriv2\n";
00441     throw e;
00442       }
00443     }
00444 
00445     static void export_applyPartialDeriv(OperatorProductDomain<Scalar> const & f,
00446                      int i,
00447                      const Vector<Scalar> & x,
00448                      const Vector<Scalar> & dxi,
00449                      Vector<Scalar> & dy) {
00450       try {
00451     f.applyPartialDeriv(i,x,dxi,dy);
00452       }
00453       catch (RVLException & e) {
00454     e<<"\ncalled from OperatorProductDomain::export_applyPartialDeriv\n";
00455     throw e;
00456       }
00457     }
00458 
00459     static void export_applyAdjPartialDeriv(OperatorProductDomain<Scalar> const & f,
00460                         int i,
00461                         const Vector<Scalar> & x,
00462                         const Vector<Scalar> & dy,
00463                         Vector<Scalar> & dxi) {
00464       try {
00465     f.applyAdjPartialDeriv(i,x,dy,dxi);
00466       }
00467       catch (RVLException & e) {
00468     e<<"\ncalled from OperatorProductDomain::export_applyAdjPartialDeriv\n";
00469     throw e;
00470       }
00471     }
00472 
00473     static void export_applyPartialDeriv2(OperatorProductDomain<Scalar> const & f,
00474                       int i, int j,
00475                       const Vector<Scalar> & x,
00476                       const Vector<Scalar> & dxi,
00477                       const Vector<Scalar> & dxj,
00478                       Vector<Scalar> & dy) {
00479       try {
00480     f.applyPartialDeriv2(i,j,x,dxi,dxj,dy);
00481       }
00482       catch (RVLException & e) {
00483     e<<"\ncalled from OperatorProductDomain::export_applyPartialDeriv2\n";
00484     throw e;
00485       }
00486     }
00487 
00488     static void export_applyAdjPartialDeriv2(OperatorProductDomain<Scalar> const & f,
00489                          int i, int j,
00490                          const Vector<Scalar> & x,
00491                          const Vector<Scalar> & dy,
00492                          const Vector<Scalar> & dxj,
00493                          Vector<Scalar> & dxi) {
00494       try {
00495     f.applyAdjPartialDeriv2(i,j,x,dy,dxj,dxi);
00496       }
00497       catch (RVLException & e) {
00498     e<<"\ncalled from OperatorProductDomain::export_applyAdjPartialDeriv2\n";
00499     throw e;
00500       }
00501     }
00502 
00505     virtual OperatorProductDomain<Scalar> * clonePD() const = 0;
00506     Operator<Scalar> * clone() const { return clonePD(); }
00507 
00508   public:
00509 
00510     OperatorProductDomain() {}
00511     OperatorProductDomain(const OperatorProductDomain<Scalar> &) {}
00512     virtual ~OperatorProductDomain() {}
00513    
00515     virtual const ProductSpace<Scalar> & getProductDomain() const = 0;
00517     const Space<Scalar> & getDomain() const { 
00518       return getProductDomain(); 
00519     }
00520   
00521   };
00522 
00527   template<typename Scalar>
00528   class RestrictOp: public Operator<Scalar> {
00529 
00530   private: 
00531 
00532     // reference OPD
00533     OperatorProductDomain<Scalar> const & ff;
00534     // fixed vector - in domain, all but ith component fixed
00535     mutable Vector<Scalar> xx;
00536     // components of x
00537     mutable Components<Scalar> cxx;
00538     // index of domain space
00539     int i;
00540     
00541     RestrictOp();
00542 
00543   protected:
00544 
00545     void apply(Vector<Scalar> const & x,
00546            Vector<Scalar> & y) const {
00547       try {
00548     cxx[i].copy(x);
00549     RVL::OperatorProductDomain<Scalar>::export_apply(ff, xx, y);
00550       }
00551       catch (RVLException & e) {
00552     e<<"\ncalled from RestrictOp::apply\n";
00553     throw e;
00554       }
00555     }
00556 
00557     void applyDeriv(Vector<Scalar> const & x,
00558             Vector<Scalar> const & dx,
00559             Vector<Scalar> & dy) const {
00560       try {
00561     cxx[i].copy(x);
00562     RVL::OperatorProductDomain<Scalar>::export_applyPartialDeriv(ff, i, xx, dx, dy);
00563       }
00564       catch (RVLException & e) {
00565     e<<"\ncalled from RestrictOp::applyDeriv\n";
00566     throw e;
00567       }
00568     }
00569 
00570     void applyAdjDeriv(Vector<Scalar> const & x,
00571                Vector<Scalar> const & dy,
00572                Vector<Scalar> & dx) const {
00573       try {
00574     cxx[i].copy(x);
00575     RVL::OperatorProductDomain<Scalar>::export_applyAdjPartialDeriv(ff, i, xx, dy, dx);
00576       }
00577       catch (RVLException & e) {
00578     e<<"\ncalled from RestrictOp::applyAdjDeriv\n";
00579     throw e;
00580       }
00581     }
00582 
00583     void applyDeriv2(Vector<Scalar> const & x,
00584              Vector<Scalar> const & dx0,
00585              Vector<Scalar> const & dx1,
00586              Vector<Scalar> & dy) const {
00587       try {
00588     cxx[i].copy(x);
00589     RVL::OperatorProductDomain<Scalar>::export_applyPartialDeriv2(ff, i, i, xx, dx0, dx1, dy);
00590       }
00591       catch (RVLException & e) {
00592     e<<"\ncalled from RestrictOp::applyDeriv\n";
00593     throw e;
00594       }
00595     }
00596 
00597     void applyAdjDeriv2(Vector<Scalar> const & x,
00598             Vector<Scalar> const & dy,
00599             Vector<Scalar> const & dx1,
00600             Vector<Scalar> & dx0) const {
00601       try {
00602     cxx[i].copy(x);
00603     RVL::OperatorProductDomain<Scalar>::export_applyAdjPartialDeriv2(ff, i,i, xx, dy, dx1, dx0);
00604       }
00605       catch (RVLException & e) {
00606     e<<"\ncalled from RestrictOp::applyAdjDeriv\n";
00607     throw e;
00608       }
00609     }
00610 
00611     Operator<Scalar> * clone() const { 
00612       return new RestrictOp(*this);
00613     }
00614     
00615   public:
00616 
00622     RestrictOp(OperatorProductDomain<Scalar> const & _f,
00623            Vector<Scalar> const & x0, int _i) 
00624       : ff(_f), xx(_f.getDomain()), cxx(xx), i(_i) {
00625       try {
00626     xx.copy(x0);
00627       }
00628       catch (RVLException & e) {
00629     e<<"\ncalled from RestrictOp constructor\n";
00630     //#ifdef IWAVE_USE_MPI
00631     //  int rk;
00632     //  MPI_Comm_rank(MPI_COMM_WORLD,&rk);
00633     //  if (rk==0) {
00634       e<<"  copy x0 to xx:\n";
00635       e<<"  x0 in space:\n";
00636       x0.getSpace().write(e);
00637       e<<"  xx in space:\n";
00638       xx.getSpace().write(e);
00639       //    }
00640       //#endif
00641     throw e;
00642       }
00643     }
00644 
00645     RestrictOp(RestrictOp<Scalar> const & g): ff(g.ff), xx(g.xx), cxx(xx), i(g.i) {}
00646 
00647     ~RestrictOp() {}
00648 
00649     Space<Scalar> const & getDomain() const { return ff.getProductDomain()[i]; }
00650     Space<Scalar> const & getRange() const { return ff.getRange(); }
00651 
00652     Scalar getMaxStep(const Vector<Scalar> & x,
00653               const Vector<Scalar> & dx) const {
00654       try {
00655     // as usual this doesn't really make sense
00656     cxx[i].copy(x);
00657     Vector<Scalar> dxx(ff.getDomain(),true);
00658     Components<Scalar> cdxx(dxx);
00659     cdxx[i].copy(dx);
00660     return ff.getMaxStep(xx,dxx);
00661       }
00662       catch (RVLException & e) {
00663     e<<"\ncalled from RestrictOp::getMaxStep\n";
00664     throw e;
00665       }
00666     }
00667 
00668     ostream & write(ostream & str) const {
00669       str<<"RestrictOp on domain subspace index "<<i<<" with\n";
00670       str<<"  Vector (for fixed components):\n";
00671       xx.write(str);
00672       str<<"  OpProdDom:\n";
00673       ff.write(str);
00674       return str;
00675     }
00676   };
00677 
00678   template<typename Scalar>
00679   class LinearRestrictOp;
00680   
00693   template<class Scalar>
00694   class LinOpValOp: public OperatorProductDomain<Scalar> {
00695 
00696     friend class LinearRestrictOp<Scalar>;
00697     
00698   protected:
00699 
00701     virtual void apply0(const Vector<Scalar> & x0,
00702             const Vector<Scalar> & x1, 
00703             Vector<Scalar> & y) const = 0;
00704     
00706     virtual void applyAdj0(const Vector<Scalar> & x0,
00707                const Vector<Scalar> & y, 
00708                Vector<Scalar> & x1) const = 0;
00709 
00711     virtual void applyPartialDeriv0(const Vector<Scalar> & x0,
00712                     const Vector<Scalar> & x1,
00713                     const Vector<Scalar> & dx0,
00714                     Vector<Scalar> & dy) const = 0;
00715 
00717     virtual void applyAdjPartialDeriv0(const Vector<Scalar> & x0,
00718                        const Vector<Scalar> & x1,
00719                        const Vector<Scalar> & dy,
00720                        Vector<Scalar> & dx0) const = 0;
00721 
00724     virtual void applyAdjPartialDeriv1(const Vector<Scalar> & x0,
00725                        const Vector<Scalar> & dx0,
00726                        const Vector<Scalar> & dy,
00727                        Vector<Scalar> & x1) const {
00728       RVLException e;
00729       e<<"ERROR: LinOpValOp::applyPartialDeriv1\n";
00730       e<<"  not pure virtual and no implementation supplied\n";
00731       throw e;
00732     }
00733 
00734     
00735     virtual void applyPartialDeriv20(const Vector<Scalar> & x0,
00736                      const Vector<Scalar> & x1,
00737                      const Vector<Scalar> & dx00,
00738                      const Vector<Scalar> & dx01,
00739                      Vector<Scalar> & dy) const {
00740       RVLException e;
00741       e<<"ERROR: LinOpValOp::applyPartialDeriv20\n";
00742       e<<"  not pure virtual and no implementation supplied\n";
00743       throw e;
00744     }
00745    
00746     
00747     virtual void applyAdjPartialDeriv20(const Vector<Scalar> & x0,
00748                     const Vector<Scalar> & x1,
00749                     const Vector<Scalar> & dy,
00750                     const Vector<Scalar> & dx01,
00751                     Vector<Scalar> & dx00) const {
00752       RVLException e;
00753       e<<"ERROR: LinOpValOp::applyPartialDeriv20\n";
00754       e<<"  not pure virtual and no implementation supplied\n";
00755       throw e;
00756     }
00757     
00758     static void export_apply0(LinOpValOp<Scalar> const & op,
00759                   const Vector<Scalar> & x0,
00760                   const Vector<Scalar> & x1, 
00761                   Vector<Scalar> & y) {
00762       op.apply0(x0,x1,y);
00763     }
00764     
00765     static void export_applyAdj0(LinOpValOp<Scalar> const & op,
00766                  const Vector<Scalar> & x0,
00767                  const Vector<Scalar> & y, 
00768                  Vector<Scalar> & x1) {
00769       op.applyAdj0(x0,y,x1);
00770     }
00771 
00772     static void export_applyPartialDeriv0(LinOpValOp<Scalar> const & op,
00773                       const Vector<Scalar> & x0,
00774                       const Vector<Scalar> & x1,
00775                       const Vector<Scalar> & dx0,
00776                       Vector<Scalar> & dy) {
00777       op.applyPartialDeriv0(x0,x1,dx0,dy);
00778     }
00779 
00780     static void export_applyAdjPartialDeriv0(LinOpValOp<Scalar> const & op,
00781                          const Vector<Scalar> & x0,
00782                          const Vector<Scalar> & x1,
00783                          const Vector<Scalar> & dy,
00784                          Vector<Scalar> & dx0) {
00785       op.applyAdjPartialDeriv0(x0,x1,dy,dx0);
00786     }
00787 
00788     static void export_applyAdjPartialDeriv1(LinOpValOp<Scalar> const & op,
00789                          const Vector<Scalar> & x0,
00790                          const Vector<Scalar> & x1,
00791                          const Vector<Scalar> & dy,
00792                          Vector<Scalar> & dx0) {
00793       op.applyAdjPartialDeriv1(x0,dx0,dy,x1);
00794     }
00795     
00796     static void export_applyPartialDeriv20(LinOpValOp<Scalar> const & op,
00797                        const Vector<Scalar> & x0,
00798                        const Vector<Scalar> & x1,
00799                        const Vector<Scalar> & dx00,
00800                        const Vector<Scalar> & dx01,
00801                        Vector<Scalar> & dy) {
00802       op.applyPartialDeriv20(x0,x1,dx00,dx01,dy);
00803     }
00804     
00805     static void export_applyAdjPartialDeriv20(LinOpValOp<Scalar> const & op,
00806                           const Vector<Scalar> & x0,
00807                           const Vector<Scalar> & x1,
00808                           const Vector<Scalar> & dy,
00809                           const Vector<Scalar> & dx01,
00810                           Vector<Scalar> & dx00) {
00811       op.applyAdjPartialDeriv20(x0,x1,dy,dx01,dx00);
00812     }
00813 
00814     void apply(Vector<Scalar> const & x,
00815            Vector<Scalar> & y) const {
00816       try {
00817     Components<Scalar> cx(x);
00818     apply0(cx[0],cx[1],y);
00819       }
00820       catch (RVLException & e) {
00821     e<<"\ncalled from LinOpValOp::apply\n";
00822     throw e;
00823       }
00824     }
00825       
00826     void applyPartialDeriv(int i,
00827                const Vector<Scalar> & x, 
00828                const Vector<Scalar> & dxi,
00829                Vector<Scalar> & dy) const {
00830       try {
00831     Components<Scalar> cx(x);
00832     if (i==0) applyPartialDeriv0(cx[0],cx[1],dxi,dy);
00833     else {
00834       apply0(cx[0],dxi,dy);
00835     }
00836       }
00837       catch (RVLException & e) {
00838     e<<"\ncalled from LinOpValOp::applyPartialDeriv\n";
00839     throw e;
00840       }
00841     }
00842 
00843     void applyAdjPartialDeriv(int i,
00844                   const Vector<Scalar> & x, 
00845                   const Vector<Scalar> & dy,
00846                   Vector<Scalar> & dxi) const {
00847       try {
00848     Components<Scalar> cx(x);
00849     if (i==0) applyAdjPartialDeriv0(cx[0],cx[1],dy,dxi);
00850     else {
00851       applyAdj0(cx[0],dy,dxi);
00852     }
00853       }
00854       catch (RVLException & e) {
00855     e<<"\ncalled from LinOpValOp::applyAdjPartialDeriv\n";
00856     throw e;
00857       }
00858     }
00859 
00860     // note that applyAdjPartialDeriv1 is needed only in the case
00861     // i=1, j=0 - which can be avoided for tomo-op like applications,
00862     // as the tomo op involves only i=j=0 case 
00863     void applyPartialDeriv2(int i,
00864                 int j,
00865                 const Vector<Scalar> & x, 
00866                 const Vector<Scalar> & dxi,
00867                 const Vector<Scalar> & dxj,
00868                 Vector<Scalar> & dy) const {
00869       try {
00870     Components<Scalar> cx(x);
00871     if (i==0) {
00872       if (j==0) 
00873         applyPartialDeriv20(cx[0],cx[1],dxi,dxj,dy);
00874       else
00875         // deriv in x0 of f(x0,dxj,y)
00876         applyPartialDeriv0(cx[0],dxj,dxi,dy);
00877     }
00878     else {
00879       if (j==0)
00880         // deriv in x1 of D_0f(x0,x1,dxj,y)
00881         applyPartialDeriv0(cx[0],dxi,dxj,dy);
00882       else 
00883         dy.zero();
00884     }
00885       }
00886       catch (RVLException & e) {
00887     e<<"\ncalled from LinOpValOp::applyAdjPartialDeriv\n";
00888     throw e;
00889       }
00890     }
00891 
00892     void applyAdjPartialDeriv2(int i,
00893                    int j,
00894                    const Vector<Scalar> & x, 
00895                    const Vector<Scalar> & dy,
00896                    const Vector<Scalar> & dxj,
00897                    Vector<Scalar> & dxi) const {
00898       try {
00899     Components<Scalar> cx(x);
00900     if (i==0) {
00901       if (j==0) 
00902         applyAdjPartialDeriv20(cx[0],cx[1],dy,dxj,dxi);
00903       else
00904         applyAdjPartialDeriv0(cx[0],dxj,dy,dxi);
00905     }
00906     else {
00907       if (j==0) 
00908         applyAdjPartialDeriv1(cx[0],dxj,dy,dxi);        
00909       else 
00910         dxi.zero();
00911     }
00912       }
00913       catch (RVLException & e) {
00914     e<<"\ncalled from LinOpValOp::applyAdjPartialDeriv2\n";
00915     throw e;
00916       }      
00917     }
00918   };
00919 
00920 
00929   template<class Scalar>
00930   class ConstLinOpValOp: public LinOpValOp<Scalar> {
00931 
00932   private:
00933     
00934     StdProductSpace<Scalar> dom;
00935     LinearOp<Scalar> const &lop; //linear operator
00936     
00937   protected:
00938 
00939     void apply0(const Vector<Scalar> & x0,
00940         const Vector<Scalar> & x1, 
00941         Vector<Scalar> & y) const {
00942       lop.applyOp(x1,y);
00943     }
00944     
00946     void applyAdj0(const Vector<Scalar> & x0,
00947            const Vector<Scalar> & y, 
00948            Vector<Scalar> & x1) const {
00949       lop.applyAdjOp(y,x1);
00950     }
00951 
00952     void applyPartialDeriv0(const Vector<Scalar> & x0,
00953                 const Vector<Scalar> & x1,
00954                 const Vector<Scalar> & dx0,
00955                 Vector<Scalar> & dy) const {
00956       dy.zero();
00957     }
00958 
00959     void applyAdjPartialDeriv0(const Vector<Scalar> & x0,
00960                    const Vector<Scalar> & x1,
00961                    const Vector<Scalar> & dy,
00962                    Vector<Scalar> & dx0) const {
00963       dx0.zero();
00964     }
00965     
00966     void applyPartialDeriv20(const Vector<Scalar> & x0,
00967                  const Vector<Scalar> & x1,
00968                  const Vector<Scalar> & dx00,
00969                  const Vector<Scalar> & dx01,
00970                  Vector<Scalar> & dy) const {
00971       dy.zero();
00972     }
00973     
00974     void applyAdjPartialDeriv20(const Vector<Scalar> & x0,
00975                 const Vector<Scalar> & x1,
00976                 const Vector<Scalar> & dy,
00977                 const Vector<Scalar> & dx01,
00978                 Vector<Scalar> & dx00) const {
00979       dx00.zero();
00980     }
00981     
00982     OperatorProductDomain<Scalar> * clonePD() const {
00983       return new ConstLinOpValOp<Scalar>(*this);
00984     }
00985     
00986   public:
00987 
00988     ConstLinOpValOp(LinearOp<Scalar> const & _lop, Space<Scalar> const & _NLsp)
00989       : lop(_lop), dom(_NLsp,_lop.getDomain()) {}
00990 
00991     ConstLinOpValOp(ConstLinOpValOp<Scalar> const & lovo)
00992       : lop(lovo.lop), dom(lovo.dom) {}
00993 
00994     ProductSpace<Scalar> const & getProductDomain() const { return dom; }
00995     Space<Scalar> const & getRange() const { return lop.getRange(); }
00996 
00997     ostream & write(ostream & str) const {
00998       str<<"ConstLinOpValOp of \n";
00999       lop.write(str);
01000       return str;
01001     }
01002   };
01003 
01004 
01008   template<class Scalar>
01009   class TangentMap: public LinOpValOp<Scalar> {
01010 
01011   private:
01012 
01013     Operator<Scalar> const & op;
01014     StdProductSpace<Scalar> dom;
01015     
01016   protected:
01017 
01018     void apply0(const Vector<Scalar> & x0,
01019         const Vector<Scalar> & x1, 
01020         Vector<Scalar> & y) const {
01021       try {
01022     RVL::Operator<Scalar>::export_applyDeriv(op,x0,x1,y);
01023       }
01024       catch (RVLException & e) {
01025     e<<"\ncalled from TangentMap::apply0\n";
01026     throw e;
01027       }
01028     }
01029   
01030     void applyAdj0(const Vector<Scalar> & x0,
01031            const Vector<Scalar> & y, 
01032            Vector<Scalar> & x1) const {
01033       try {
01034     RVL::Operator<Scalar>::export_applyAdjDeriv(op,x0,y,x1);
01035       }
01036       catch (RVLException & e) {
01037     e<<"\ncalled from TangentMap::applyAdj0\n";
01038     throw e;
01039       }
01040     }
01041 
01042     void applyPartialDeriv0(const Vector<Scalar> & x0,
01043                 const Vector<Scalar> & x1,
01044                 const Vector<Scalar> & dx0,
01045                 Vector<Scalar> & dy) const {
01046       try {
01047         RVL::Operator<Scalar>::export_applyDeriv2(op,x0,x1,dx0,dy);
01048       }
01049       catch (RVLException & e) {
01050     e<<"\ncalled from TangentMap::applyPartialDeriv0\n";
01051     throw e;
01052       }      
01053     }
01054     
01055     void applyAdjPartialDeriv0(const Vector<Scalar> & x0,
01056                    const Vector<Scalar> & x1,
01057                    const Vector<Scalar> & dy,
01058                    Vector<Scalar> & dx0) const {
01059       try {
01060     RVL::Operator<Scalar>::export_applyAdjDeriv2(op,x0,dy,x1,dx0);
01061       }
01062       catch (RVLException & e) {
01063     e<<"\ncalled from TangentMap::applyPartialDeriv0\n";
01064     throw e;
01065       }
01066     }
01067 
01068     void applyPartialDeriv20(const Vector<Scalar> & x0,
01069                      const Vector<Scalar> & x1,
01070                      const Vector<Scalar> & dx00,
01071                      const Vector<Scalar> & dx01,
01072                      Vector<Scalar> & dy) const {
01073       RVLException e;
01074       e<<"ERROR: TangentMap::applyPartialDeriv20\n";
01075       e<<"  not defined - would involve 3rd order partial of underlying map\n";
01076       throw e;
01077     }
01078     
01079     void applyAdjPartialDeriv20(const Vector<Scalar> & x0,
01080                     const Vector<Scalar> & x1,
01081                     const Vector<Scalar> & dy,
01082                     const Vector<Scalar> & dx01,
01083                     Vector<Scalar> & dx00) const {
01084       RVLException e;
01085       e<<"ERROR: TangentMap::applyPartialDeriv20\n";
01086       e<<"  not defined - would involve 3rd order partial of underlying map\n";
01087       throw e;
01088     }
01089     
01090     OperatorProductDomain<Scalar> * clonePD() const {
01091       return new TangentMap<Scalar>(*this);
01092     }
01093     
01094   public:
01095 
01096     TangentMap(Operator<Scalar> const & _op)
01097       : op(_op), dom(op.getDomain(),op.getDomain()) {}
01098 
01099     TangentMap(TangentMap<Scalar> const & t)
01100       : op(t.op), dom(t.dom) {}
01101 
01102     ProductSpace<Scalar> const & getProductDomain() const { return dom; }
01103     Space<Scalar> const & getRange() const { return op.getRange(); }
01104 
01105     ostream & write(ostream & str) const {
01106       str<<"Tangent Map of \n";
01107       op.write(str);
01108       return str;
01109     }
01110   };
01111     
01118   template<typename Scalar>
01119   class LinearRestrictOp: public LinearOp<Scalar> {
01120 
01121   private: 
01122 
01123     // reference OPD
01124     LinOpValOp<Scalar> const & ff;
01125     // fixed vector - in domain[0]
01126     Vector<Scalar> x0;
01127     
01128     LinearRestrictOp();
01129 
01130   protected:
01131 
01132     void apply(Vector<Scalar> const & x,
01133            Vector<Scalar> & y) const {
01134       try {
01135     ff.apply0(x0,x,y);
01136       }
01137       catch (RVLException & e) {
01138     e<<"\ncalled from LinearRestrictOp::apply\n";
01139     throw e;
01140       }
01141     }
01142 
01143     void applyAdj(Vector<Scalar> const & y,
01144           Vector<Scalar> & x) const {
01145       try {
01146     ff.applyAdj0(x0,y,x);
01147       }
01148       catch (RVLException & e) {
01149     e<<"\ncalled from LinearRestrictOp::applyAdj\n";
01150     throw e;
01151       }
01152     }
01153     
01154     Operator<Scalar> * clone() const { 
01155       return new LinearRestrictOp(*this);
01156     }
01157     
01158   public:
01159 
01164     LinearRestrictOp(LinOpValOp<Scalar> const & _f,
01165              Vector<Scalar> const & _x) 
01166       : ff(_f), x0((_f.getProductDomain())[0]) {
01167       try {
01168     x0.copy(_x);
01169       }
01170       catch (RVLException & e) {
01171     e<<"\ncalled from LinearRestrictOp constructor\n";
01172     throw e;
01173       }
01174     }
01175 
01176     LinearRestrictOp(LinearRestrictOp<Scalar> const & g): ff(g.ff), x0(g.x0) {}
01177 
01178     ~LinearRestrictOp() {}
01179 
01180     Space<Scalar> const & getDomain() const { return ff.getProductDomain()[1]; }
01181     Space<Scalar> const & getRange() const { return ff.getRange(); }
01182 
01183     ostream & write(ostream & str) const {
01184       str<<"LinearRestrictOp with\n";
01185       str<<"  Vector (for 0th fixed component):\n";
01186       x0.write(str);
01187       str<<"  LinOpValOp:\n";
01188       ff.write(str);
01189       return str;
01190     }
01191   };
01192 
01196   template<class Scalar>
01197   class CompLOVOp: public LinOpValOp<Scalar> {
01198 
01199   private:
01200 
01201     std::shared_ptr<Operator<Scalar> > op;
01202     std::shared_ptr<LinOpValOp<Scalar> > lovop;
01203     StdProductSpace<Scalar> dom;
01204     
01205   protected:
01206 
01207     void apply0(const Vector<Scalar> & x0,
01208         const Vector<Scalar> & x1, 
01209         Vector<Scalar> & y) const {
01210       try {
01211     Vector<Scalar> z(op->getRange());
01212     RVL::Operator<Scalar>::export_apply(*op,x0,z);
01213     RVL::LinOpValOp<Scalar>::export_apply0(*lovop,z,x1,y);
01214       }
01215       catch (RVLException & e) {
01216     e<<"\ncalled from CompLOVOp::apply0\n";
01217     throw e;
01218       }
01219     }
01220   
01221     void applyAdj0(const Vector<Scalar> & x0,
01222            const Vector<Scalar> & y, 
01223            Vector<Scalar> & x1) const {
01224       try {
01225     Vector<Scalar> z(op->getRange());
01226     RVL::Operator<Scalar>::export_apply(*op,x0,z);
01227     RVL::LinOpValOp<Scalar>::export_applyAdj0(*lovop,z,y,x1);
01228       }
01229       catch (RVLException & e) {
01230     e<<"\ncalled from CompLOVOp::applyAdj0\n";
01231     throw e;
01232       }
01233     }
01234 
01235     void applyPartialDeriv0(const Vector<Scalar> & x0,
01236                 const Vector<Scalar> & x1,
01237                 const Vector<Scalar> & dx0,
01238                 Vector<Scalar> & dy) const {
01239       try {
01240     Vector<Scalar> z0(op->getRange());
01241     RVL::Operator<Scalar>::export_apply(*op,x0,z0);
01242     Vector<Scalar> dz(op->getRange());
01243     RVL::Operator<Scalar>::export_applyDeriv(*op,x0,dx0,dz);
01244     RVL::LinOpValOp<Scalar>::export_applyPartialDeriv0(*lovop,z0,x1,dz,dy);
01245       }
01246       catch (RVLException & e) {
01247     e<<"\ncalled from CompLOVOp::applyPartialDeriv0\n";
01248     throw e;
01249       }      
01250     }
01251     
01252     void applyAdjPartialDeriv0(const Vector<Scalar> & x0,
01253                    const Vector<Scalar> & x1,
01254                    const Vector<Scalar> & dy,
01255                    Vector<Scalar> & dx0) const {
01256       try {
01257     Vector<Scalar> z0(op->getRange());
01258     RVL::Operator<Scalar>::export_apply(*op,x0,z0);
01259     Vector<Scalar> dz(op->getRange());
01260     RVL::LinOpValOp<Scalar>::export_applyAdjPartialDeriv0(*lovop,z0,x1,dy,dz);
01261     RVL::Operator<Scalar>::export_applyDeriv(*op,x0,dz,dx0);
01262       }
01263       catch (RVLException & e) {
01264     e<<"\ncalled from CompLOVOp::applyAdjPartialDeriv0\n";
01265     throw e;
01266       }
01267     }
01268 
01269     void applyPartialDeriv20(const Vector<Scalar> & x0,
01270                  const Vector<Scalar> & x1,
01271                  const Vector<Scalar> & dx00,
01272                  const Vector<Scalar> & dx01,
01273                  Vector<Scalar> & dy) const {
01274       try {
01275     Vector<Scalar> z0(op->getRange());
01276     RVL::Operator<Scalar>::export_apply(*op,x0,z0);
01277     Vector<Scalar> dz0(op->getRange());
01278     Vector<Scalar> dz1(op->getRange());
01279     RVL::Operator<Scalar>::export_applyDeriv(*op,x0,dx00,dz0);
01280     RVL::Operator<Scalar>::export_applyDeriv(*op,x0,dx01,dz1);
01281     RVL::LinOpValOp<Scalar>::export_applyPartialDeriv20(*lovop,z0,x1,dz0,dz1,dy);
01282       }
01283       catch (RVLException & e) {
01284     e<<"\ncalled from CompLOVOp::applyPartialDeriv20\n";
01285     throw e;
01286       }
01287 
01288     }
01289     
01290     void applyAdjPartialDeriv20(const Vector<Scalar> & x0,
01291                 const Vector<Scalar> & x1,
01292                 const Vector<Scalar> & dy,
01293                 const Vector<Scalar> & dx01,
01294                 Vector<Scalar> & dx00) const {
01295       try {
01296     Vector<Scalar> z0(op->getRange());
01297     RVL::Operator<Scalar>::export_apply(*op,x0,z0);
01298     Vector<Scalar> dz0(op->getRange());
01299     Vector<Scalar> dz1(op->getRange());
01300     RVL::Operator<Scalar>::export_applyDeriv(*op,x0,dx01,dz1);
01301     RVL::LinOpValOp<Scalar>::export_applyAdjPartialDeriv20(*lovop,z0,x1,dy,dz1,dz0);
01302     RVL::Operator<Scalar>::export_applyDeriv(*op,x0,dz0,dx00);
01303       }
01304       catch (RVLException & e) {
01305     e<<"\ncalled from CompLOVOp::applyAdjPartialDeriv20\n";
01306     throw e;
01307       }
01308     }
01309     
01310     OperatorProductDomain<Scalar> * clonePD() const {
01311       return new CompLOVOp<Scalar>(*this);
01312     }
01313     
01314   public:
01315 
01316     CompLOVOp(Operator<Scalar> const & _op,
01317           LinOpValOp<Scalar> const & _lovop)
01318       : dom(_op.getDomain(),_lovop.getProductDomain()[1]) {
01319       op = RVL::Operator<Scalar>::clonePtr(_op);
01320       std::shared_ptr<RVL::Operator<Scalar> > tmp = RVL::Operator<Scalar>::clonePtr(_lovop);
01321       lovop = dynamic_pointer_cast<RVL::LinOpValOp<Scalar> >(tmp);
01322       if (!(lovop.get())) {
01323     RVLException e;
01324     e<<"ERROR: CompLOVOp constructor\n";
01325     e<<"  bad, bad, bad...\n";
01326     throw e;
01327       }
01328     }
01329     
01330 
01331     CompLOVOp(CompLOVOp<Scalar> const & t)
01332       : op(t.op), lovop(t.lovop), dom(t.dom) {}
01333 
01334     ProductSpace<Scalar> const & getProductDomain() const { return dom; }
01335     Space<Scalar> const & getRange() const { return lovop->getRange(); }
01336 
01337     ostream & write(ostream & str) const {
01338       str<<"Composition of Operator followed by LinOpValOp\n";
01339       str<<"Operator acts only on first component of LOVO domain\n";
01340       str<<"Operator (first factor):\n";
01341       op->write(str);
01342       str<<"LinOpValOp (second factor):\n";
01343       lovop->write(str);
01344       return str;
01345     }
01346   };
01347 
01351   template<class Scalar>
01352   class LinCompLOVOp: public LinOpValOp<Scalar> {
01353 
01354   private:
01355 
01356     std::shared_ptr<LinearOp<Scalar> > lop;
01357     std::shared_ptr<LinOpValOp<Scalar> > lovop;
01358     StdProductSpace<Scalar> dom;
01359     
01360   protected:
01361 
01362     void apply0(const Vector<Scalar> & x0,
01363         const Vector<Scalar> & x1, 
01364         Vector<Scalar> & y) const {
01365       try {
01366     Vector<Scalar> z(lop->getRange());
01367     lop->applyOp(x1,z);
01368     RVL::LinOpValOp<Scalar>::export_apply0(*lovop,x0,z,y);
01369       }
01370       catch (RVLException & e) {
01371     e<<"\ncalled from LinCompLOVOp::apply0\n";
01372     throw e;
01373       }
01374     }
01375   
01376     void applyAdj0(const Vector<Scalar> & x0,
01377            const Vector<Scalar> & y, 
01378            Vector<Scalar> & x1) const {
01379       try {
01380     Vector<Scalar> z(lop->getRange());
01381     RVL::LinOpValOp<Scalar>::export_applyAdj0(*lovop,x0,y,z);
01382     lop->applyAdjOp(z,x1);
01383       }
01384       catch (RVLException & e) {
01385     e<<"\ncalled from LinCompLOVOp::applyAdj0\n";
01386     throw e;
01387       }
01388     }
01389 
01390     void applyPartialDeriv0(const Vector<Scalar> & x0,
01391                 const Vector<Scalar> & x1,
01392                 const Vector<Scalar> & dx0,
01393                 Vector<Scalar> & dy) const {
01394       try {
01395     Vector<Scalar> z(lop->getRange());
01396     lop->applyOp(x1,z);
01397     RVL::LinOpValOp<Scalar>::export_applyPartialDeriv0(*lovop,x0,z,dx0,dy);
01398       }
01399       catch (RVLException & e) {
01400     e<<"\ncalled from LinCompLOVOp::applyPartialDeriv0\n";
01401     throw e;
01402       }      
01403     }
01404     
01405     void applyAdjPartialDeriv0(const Vector<Scalar> & x0,
01406                    const Vector<Scalar> & x1,
01407                    const Vector<Scalar> & dy,
01408                    Vector<Scalar> & dx0) const {
01409       try {
01410     Vector<Scalar> z(lop->getRange());
01411     lop->applyOp(x1,z);
01412     RVL::LinOpValOp<Scalar>::export_applyAdjPartialDeriv0(*lovop,x0,z,dy,dx0);
01413       }
01414       catch (RVLException & e) {
01415     e<<"\ncalled from LinCompLOVOp::applyAdjPartialDeriv0\n";
01416     throw e;
01417       }
01418     }
01419 
01420     void applyPartialDeriv20(const Vector<Scalar> & x0,
01421                  const Vector<Scalar> & x1,
01422                  const Vector<Scalar> & dx00,
01423                  const Vector<Scalar> & dx01,
01424                  Vector<Scalar> & dy) const {
01425       try {
01426     Vector<Scalar> z(lop->getRange());
01427     lop->applyOp(x1,z);
01428     RVL::LinOpValOp<Scalar>::export_applyPartialDeriv20(*lovop,x0,z,dx00,dx01,dy);
01429       }
01430       catch (RVLException & e) {
01431     e<<"\ncalled from LinCompLOVOp::applyPartialDeriv20\n";
01432     throw e;
01433       }
01434     }
01435     
01436     void applyAdjPartialDeriv20(const Vector<Scalar> & x0,
01437                 const Vector<Scalar> & x1,
01438                 const Vector<Scalar> & dy,
01439                 const Vector<Scalar> & dx01,
01440                 Vector<Scalar> & dx00) const {
01441       try {
01442     Vector<Scalar> z(lop->getRange());
01443     lop->applyOp(x1,z);
01444     RVL::LinOpValOp<Scalar>::export_applyAdjPartialDeriv20(*lovop,x0,z,dy,dx01,dx00);
01445       }
01446       catch (RVLException & e) {
01447     e<<"\ncalled from LinCompLOVOp::applyAdjPartialDeriv20\n";
01448     throw e;
01449       }
01450     }
01451     
01452     OperatorProductDomain<Scalar> * clonePD() const {
01453       return new LinCompLOVOp<Scalar>(*this);
01454     }
01455     
01456   public:
01457 
01458     LinCompLOVOp(LinearOp<Scalar> const & _lop,
01459          LinOpValOp<Scalar> const & _lovop)
01460       : dom(_lovop.getProductDomain()[0],_lop.getDomain()) {
01461       
01462       std::shared_ptr<RVL::Operator<Scalar> > tmp_lop 
01463     = RVL::Operator<Scalar>::clonePtr(_lop);
01464       lop = dynamic_pointer_cast<RVL::LinearOp<Scalar> >(tmp_lop);
01465       
01466       std::shared_ptr<RVL::Operator<Scalar> > tmp_lovop 
01467     = RVL::Operator<Scalar>::clonePtr(_lovop);
01468       lovop = dynamic_pointer_cast<RVL::LinOpValOp<Scalar> >(tmp_lovop);
01469       
01470       if ( !(lovop.get())||!(lop.get()) ) {
01471     RVLException e;
01472     e<<"ERROR: LinCompLOVOp constructor\n";
01473     e<<"  bad, bad, bad...\n";
01474     throw e;
01475       }
01476     }
01477     
01478     LinCompLOVOp(LinCompLOVOp<Scalar> const & t)
01479       : lop(t.lop), lovop(t.lovop), dom(t.dom) {}
01480 
01481     ProductSpace<Scalar> const & getProductDomain() const { return dom; }
01482     Space<Scalar> const & getRange() const { return lovop->getRange(); }
01483 
01484     ostream & write(ostream & str) const {
01485       str<<"Composition of Operator followed by LinOpValOp\n";
01486       str<<"Operator acts only on second component of LOVO domain\n";
01487       str<<"LinearOp:\n";
01488       lop->write(str);
01489       str<<"LinOpValOp:\n";
01490       lovop->write(str);
01491       return str;
01492     }
01493   };
01494     
01495     
01496   template<class Scalar>
01497   class InvertibleDerivEvaluation;
01498 
01503   template<class Scalar>
01504   class OperatorWithInvertibleDeriv : public Operator<Scalar> {
01505   
01506     friend class InvertibleDerivEvaluation<Scalar>;
01507     typedef typename ScalarFieldTraits<Scalar>::AbsType NormRetType;
01508 
01509   protected:
01510     
01511     virtual void applyInverseDeriv(const Vector<Scalar> & x,
01512               const Vector<Scalar> & dy,
01513               Vector<Scalar> & dx) const = 0;
01514     virtual void applyAdjInverseDeriv(const Vector<Scalar> & x,
01515                       const Vector<Scalar> & dx,
01516                       Vector<Scalar> & dy) const = 0;
01517 
01518     DerivEvaluation<Scalar> 
01519     * createDerivEvaluation(OperatorEvaluation<Scalar> & opeval) const;
01520 
01521   public:
01522 
01523     OperatorWithInvertibleDeriv() {}
01524     ~OperatorWithInvertibleDeriv() {}
01525 
01526     /* Performs a simple inverse check by applying the inverse, then applying
01527     the derivative and examining the norm of the difference.
01528     Returns true if test is successful, false otherwise.
01529   
01530     bool checkInverseDeriv(const Vector<Scalar> & x, 
01531                const Vector<Scalar> & y,
01532                NormRetType tol = 1e-4,
01533                ostream & str = cout);
01534     */
01535   };
01536 
01607   template<class Scalar>
01608   class OperatorEvaluation: public Writeable {
01609 
01610     friend class OpComp<Scalar>;
01611     friend class FcnlOpComp<Scalar>;
01612     friend class DerivEvaluation<Scalar>;
01613     friend class Deriv2Evaluation<Scalar>;
01614     friend class PartialDerivEvaluation<Scalar>;
01615 
01616   private:
01617 
01618     const Operator<Scalar> & fref;
01619     WatchedVecRef<Scalar> wx;
01620     mutable Operator<Scalar> * f;
01621 
01622     mutable Vector<Scalar> val;
01623     mutable bool applied;
01624     DerivEvaluation<Scalar> * deriv;
01625     Deriv2Evaluation<Scalar> * deriv2;
01626 
01627     // disabled
01628     OperatorEvaluation();
01629   
01630     void reset() const {
01631       try {
01632     if (f) delete f;
01633     f = fref.clone();
01634     applied=false;
01635       }
01636       catch (RVLException & e) {
01637     e<<"\ncalled from OperatorEvaluation::reset\n";
01638     throw e;
01639       }
01640     }
01641 
01642   protected:
01643 
01647     void applyDeriv(const Vector<Scalar> & yin,
01648             Vector<Scalar> & yout) const {
01649       try {
01650     if (wx.update()) reset();
01651     f->applyDeriv(wx.get(),yin,yout);
01652       }
01653       catch (RVLException & e) {
01654     e<<"\ncalled from OperatorEvaluation::applyDeriv()\n";
01655     throw e;
01656       }
01657     }
01658 
01662     void applyAdjDeriv(const Vector<Scalar> & yin,
01663                Vector<Scalar> & yout) const {
01664       try {
01665     if (wx.update()) reset();
01666     f->applyAdjDeriv(wx.get(),yin,yout);
01667       }
01668       catch (RVLException & e) {
01669     e<<"\ncalled from OperatorEvaluation::applyAdjDeriv()\n";
01670     throw e;
01671       }
01672     }
01673 
01677     void applyDeriv2(const Vector<Scalar> & x0,
01678              const Vector<Scalar> & x1,
01679              Vector<Scalar> & y) const {
01680       try {
01681     if (wx.update()) reset();
01682     f->applyDeriv2(wx.get(),x0,x1,y);
01683       }
01684       catch (RVLException & e) {
01685     e<<"\ncalled from OperatorEvaluation::applyDeriv2()\n";
01686     throw e;
01687       }
01688     }
01689 
01693     void applyAdjDeriv2(const Vector<Scalar> & x0,
01694             const Vector<Scalar> & y,
01695             Vector<Scalar> & x1) const {
01696       try {
01697     if (wx.update()) reset();
01698     f->applyAdjDeriv2(wx.get(),x0,y,x1);
01699       }
01700       catch (RVLException & e) {
01701     e<<"\ncalled from OperatorEvaluation::applyAdjDeriv2()\n";
01702     throw e;
01703       }
01704     }
01705 
01713     const ProductSpace<Scalar> & getProductDomain() const {
01714 
01715       try {
01716     OperatorProductDomain<Scalar> * pf = NULL;
01717     if ((pf = dynamic_cast<OperatorProductDomain<Scalar> *>(f))) {
01718       return pf->getProductDomain();
01719     }
01720     else {
01721       RVLException e;
01722       e<<"Error: OperatorEvaluation::getProductDomain\n";
01723       e<<"referenced Operator does not have ProductSpace domain\n";
01724       throw e;
01725     }
01726       }
01727       catch (RVLException & e) {
01728     e<<"\ncalled from OperatorEvaluation::getProductDomain\n";
01729     throw e;
01730       }
01731     }
01732 
01733     // access through PartialDerivEvaluation
01734     void applyPartialDeriv(int i,
01735                const Vector<Scalar> & yin,
01736                Vector<Scalar> & yout) const {
01737       try {
01738     if (wx.update()) reset();
01739     OperatorProductDomain<Scalar> * pf = NULL;
01740     if ((pf = dynamic_cast<OperatorProductDomain<Scalar> *>(f))) {
01741       pf->applyPartialDeriv(i,wx.get(),yin,yout);
01742     }
01743     else {
01744       RVLException e;
01745       e<<"Error: OperatorEvaluation::applyPartialDeriv\n";
01746       e<<"referenced Operator does not have ProductSpace domain\n";
01747       e<<"so partial derivatives are not defined\n";
01748       throw e;
01749     }
01750       }
01751       catch (RVLException & e) {
01752     e<<"\ncalled from OperatorEvaluation";
01753     e<<"::applyPartialDeriv()\n";
01754     throw e;
01755       }
01756     }
01757 
01758     // access through PartialDerivEvaluation
01759     void applyAdjPartialDeriv(int i,
01760                   const Vector<Scalar> & yin,
01761                   Vector<Scalar> & yout) const {
01762       try {
01763     if (wx.update()) reset();
01764     OperatorProductDomain<Scalar> * pf = NULL;
01765     if ((pf = dynamic_cast<OperatorProductDomain<Scalar> *>(f))) {
01766       pf->applyAdjPartialDeriv(i,wx.get(),yin,yout);
01767     }
01768     else {
01769       RVLException e;
01770       e<<"Error: OperatorEvaluation::applyAdjPartialDeriv\n";
01771       e<<"referenced Operator does not have ProductSpace domain\n";
01772       e<<"so partial derivatives are not defined\n";
01773       throw e;
01774     }
01775       }
01776       catch (RVLException & e) {
01777     e<<"\ncalled from OperatorEvaluation";
01778     e<<"::applyAdjPartialDeriv()\n";
01779     throw e;
01780       }
01781     }
01782 
01783     /* void applyInverseDeriv( const Vector<Scalar> & dyin,
01784                 Vector<Scalar> & dxout) const {
01785       try {
01786     if (wx.update()) reset();
01787     OperatorWithInvertibleDeriv<Scalar> * pf = NULL;
01788     if (pf = dynamic_cast<OperatorWithInvertibleDeriv<Scalar> *>(f)) {
01789       pf->applyInverseDeriv(wx.get(),dyin,dxout);
01790     }
01791     else {
01792       RVLException e;
01793       e<<"Error: OperatorEvaluation::applyInverseDeriv\n";
01794       e<<"referenced Operator does not have an invertible derivative\n";
01795       throw e;
01796     }
01797       }
01798       catch (RVLException & e) {
01799     e<<"\ncalled from OperatorEvaluation";
01800     e<<"::applyInverseDeriv()\n";
01801     throw e;
01802       }
01803     }
01804     
01805     void applyAdjInverseDeriv( const Vector<Scalar> & dxin,
01806                 Vector<Scalar> & dyout) const {
01807       try {
01808     if (wx.update()) reset();
01809     OperatorWithInvertibleDeriv<Scalar> * pf = NULL;
01810     if (pf = dynamic_cast<OperatorWithInvertibleDeriv<Scalar> *>(f)) {
01811       pf->applyAdjInverseDeriv(wx.get(),dxin,dyout);
01812     }
01813     else {
01814       RVLException e;
01815       e<<"Error: OperatorEvaluation::applyAdjInverseDeriv\n";
01816       e<<"referenced Operator does not have an invertible derivative\n";
01817       throw e;
01818     }
01819       }
01820       catch (RVLException & e) {
01821     e<<"\ncalled from OperatorEvaluation";
01822     e<<"::applyAdjInverseDeriv()\n";
01823     throw e;
01824       }
01825     }
01826     */
01827 
01834 #ifndef RVL_OPERATOR_NEW_ENABLED
01835     void * operator new(size_t size) { 
01836       void * ptr;
01837       ptr = (void *) ::new unsigned char[size]; 
01838       return ptr;
01839     }
01840 #endif
01841 
01842   public:
01843 
01844     OperatorEvaluation(const Operator<Scalar> & _f, 
01845                const Vector<Scalar> & x)
01846       : fref(_f), wx(x), 
01847     val(fref.getRange()), applied(false), 
01848     deriv(_f.createDerivEvaluation(*this)),
01849     deriv2(_f.createDeriv2Evaluation(*this)) { 
01850       f = fref.clone(); 
01851 
01852       if (x.getSpace() != fref.getDomain()) {
01853     RVLException e;
01854     e<<"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n";
01855     e<<"Error: OperatorEvaluation constructor\n";
01856     e<<"-- evaluation point not in domain of operator\n";
01857     e<<"**********************\n";
01858     e<<"***    operator:   ***\n";
01859     e<<"**********************\n";
01860     fref.write(e);
01861     e<<"**********************\n";
01862     e<<"*** domain space:  ***\n";
01863     e<<"**********************\n";
01864     fref.getDomain().write(e);
01865     e<<"**********************\n";
01866     e<<"*** input space:   ***\n";
01867     e<<"**********************\n";
01868     x.getSpace().write(e);
01869     e<<"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n";
01870     throw e;
01871       }
01872       
01873     }
01874 
01875     OperatorEvaluation(const OperatorEvaluation<Scalar> & ev)
01876       : wx(ev.wx), f(ev.fref.clone()), fref(ev.fref),
01877     val(fref.getRange()), applied(false), 
01878     deriv(f->createDerivEvaluation(*this)),
01879     deriv2(f->createDeriv2Evaluation(*this)) { }
01880 
01881     virtual ~OperatorEvaluation() {
01882       if( deriv) {
01883     delete deriv;
01884     deriv = NULL;
01885       }
01886       if( deriv2) {
01887     delete deriv2;
01888     deriv2 = NULL;
01889       }
01890       if (f) delete f; 
01891     }
01892 
01896     Space<Scalar> const & getDomain() const { return fref.getDomain(); }
01897 
01901     Space<Scalar> const & getRange() const { return fref.getRange(); }
01902 
01904     Vector<Scalar> & getPoint() { return wx.get(); }
01905     Vector<Scalar> const & getPoint() const { return wx.get(); }
01906 
01915     Operator<Scalar> const & getOp() const { return *f; }
01916 
01919     Vector<Scalar> const & getValue() const {
01920       try {
01921     if (wx.update()) reset();   
01922     if (!applied) {
01923       f->apply(wx.get(),val);
01924       applied=true;
01925     }
01926     return val;
01927       }
01928       catch (RVLException & e) {
01929     e<<"\ncalled in OperatorEvaluation::getValue\n";
01930     throw e;
01931       }
01932     }
01933 
01935     LinearOp<Scalar> const & getDeriv() const { return *deriv; }
01937     SymmetricBilinearOp<Scalar> const & getDeriv2() const { return *deriv2; }
01938 
01939     ostream & write(ostream & str) const{
01940       str<<"Operator Evaluation:"<<"\n";
01941       str<<"  Operator:\n";
01942       fref.write(str);
01943       str<<"  evaluated at Vector:\n";
01944       wx.get().write(str);
01945       return str;
01946     }
01947   };
01948 
01957   template<class Scalar>
01958   class DerivEvaluation: public LinearOp<Scalar> {
01959 
01960     friend class OperatorEvaluation<Scalar>;
01961     friend class Operator<Scalar>;
01962 
01963   private:
01964 
01965     // disabled
01966     DerivEvaluation();
01967 
01968   protected:
01969 
01970     OperatorEvaluation<Scalar> & fx;
01971 
01972     DerivEvaluation(const DerivEvaluation<Scalar> & d)
01973       : fx(d.fx) {}
01974 
01976     DerivEvaluation(OperatorEvaluation<Scalar> & _fx): fx(_fx) {}
01977 
01978     LinearOp<Scalar> * clone() const {
01979       return new DerivEvaluation<Scalar>(*this);
01980     }
01981 
01984     Operator<Scalar> & getOp() const { return fx.getOp(); }
01985 
01988     void apply(const Vector<Scalar> & y, 
01989            Vector<Scalar> & z) const {
01990       try {
01991     fx.applyDeriv(y,z);
01992       }
01993       catch (RVLException & e) {
01994     e<<"\ncalled in DerivEvaluation::applyOp\n";
01995     throw e;
01996       }
01997     }
01998 
02001     void applyAdj(const Vector<Scalar> & y,
02002           Vector<Scalar> & z) const {
02003       try {
02004     fx.applyAdjDeriv(y,z);
02005       }
02006       catch (RVLException & e) {
02007     e<<"\ncalled in DerivEvaluation::applyAdjOp\n";
02008     throw e;
02009       }
02010     }
02011 
02012   public:
02013 
02014     ~DerivEvaluation() {}
02015 
02017     const Space<Scalar> & getDomain() const { return fx.getDomain(); }
02019     const Space<Scalar> & getRange() const { return fx.getRange(); }
02020 
02021     ostream & write(ostream & str) const{
02022       str<<"Derivative operator"<<"\n";
02023       str<<"part of operator evaluation"<<"\n";
02024       fx.write(str);
02025       return str;
02026     }
02027   };
02028 
02037   template<class Scalar>
02038   class Deriv2Evaluation: public SymmetricBilinearOp<Scalar> {
02039 
02040     friend class OperatorEvaluation<Scalar>;
02041     friend class Operator<Scalar>;
02042 
02043   private:
02044 
02045     // disabled
02046     Deriv2Evaluation();
02047 
02048   protected:
02049 
02050     OperatorEvaluation<Scalar> & fx;
02051 
02052     Deriv2Evaluation(const Deriv2Evaluation<Scalar> & d)
02053       : fx(d.fx) {}
02054 
02056     Deriv2Evaluation(OperatorEvaluation<Scalar> & _fx): fx(_fx) {}
02057 
02058     SymmetricBilinearOp<Scalar> * clone() const {
02059       return new Deriv2Evaluation<Scalar>(*this);
02060     }
02061 
02064     Operator<Scalar> & getOp() const { return fx.getOp(); }
02065 
02068     void apply(const Vector<Scalar> & y0, 
02069            const Vector<Scalar> & y1, 
02070            Vector<Scalar> & z) const {
02071       try {
02072     fx.applyDeriv2(y0,y1,z);
02073       }
02074       catch (RVLException & e) {
02075     e<<"\ncalled in Deriv2Evaluation::applyOp\n";
02076     throw e;
02077       }
02078     }
02079 
02082     void applyAdj(const Vector<Scalar> & y0,
02083           const Vector<Scalar> & z,
02084           Vector<Scalar> & y1) const {
02085       try {
02086     fx.applyAdjDeriv2(y0,z,y1);
02087       }
02088       catch (RVLException & e) {
02089     e<<"\ncalled in Deriv2Evaluation::applyAdjOp\n";
02090     throw e;
02091       }
02092     }
02093 
02094   public:
02095 
02096     ~Deriv2Evaluation() {}
02097 
02099     const Space<Scalar> & getDomain() const { return fx.getDomain(); }
02101     const Space<Scalar> & getRange() const { return fx.getRange(); }
02102 
02103     ostream & write(ostream & str) const{
02104       str<<"Second Derivative operator"<<"\n";
02105       str<<"part of operator evaluation"<<"\n";
02106       fx.write(str);
02107       return str;
02108     }
02109   };
02110 
02113   template<class Scalar>
02114   class InvertibleDerivEvaluation 
02115     : public DerivEvaluation<Scalar>, public Invertible<Scalar> {
02116  
02117     friend class OperatorWithInvertibleDeriv<Scalar>;
02118 
02119   protected:
02120 
02121     LinearOp<Scalar> * clone() const {
02122       return new InvertibleDerivEvaluation<Scalar>(*this);
02123     }
02124 
02125     InvertibleDerivEvaluation(const InvertibleDerivEvaluation<Scalar> & s)
02126       :DerivEvaluation<Scalar>(s) {}
02127 
02131     void applyInv(const Vector<Scalar> & x, 
02132           Vector<Scalar> & y) const {
02133       try {
02134     OperatorWithInvertibleDeriv<Scalar> & opwid = 
02135       dynamic_cast<OperatorWithInvertibleDeriv<Scalar> &>(this->getOp());
02136     opwid.applyInverseDeriv(this->fx.getPoint(), x, y);
02137       }
02138       catch (bad_cast) {
02139     RVLException e;
02140     e<<"Error: InvertibleDerivEvaluation::applyInv\n";
02141     e<<"operator does not have invertible deriv\n";
02142     throw e;
02143       }
02144     }
02145 
02149     void applyInvAdj(const Vector<Scalar> & x, 
02150              Vector<Scalar> & y) const {
02151       try {
02152     OperatorWithInvertibleDeriv<Scalar> & opwid = 
02153       dynamic_cast<OperatorWithInvertibleDeriv<Scalar> &>(this->getOp());
02154     opwid.applyAdjInverseDeriv(this->fx.getPoint(), x, y);
02155       }
02156       catch (bad_cast) {
02157     RVLException e;
02158     e<<"Error: InvertibleDerivEvaluation::applyInvAdj\n";
02159     e<<"operator does not have invertible deriv\n";
02160     throw e;
02161       }
02162     }
02163 
02164   public:
02165 
02166     InvertibleDerivEvaluation(OperatorEvaluation<Scalar> & _fx) 
02167       : DerivEvaluation<Scalar>(_fx) {}
02168 
02170     const Space<Scalar> & getDomain() const { return this->fx.getDomain(); }
02172     const Space<Scalar> & getRange() const { return this->fx.getRange(); }
02173 
02174     ostream & write(ostream & str) const{
02175       str<<"Invertible Derivative operator"<<"\n";
02176       str<<"part of operator evaluation"<<"\n";
02177       this->fx.write(str);
02178       return str;
02179     }
02180 
02181   };
02182 
02184   template<class Scalar>
02185   class OperatorProductDomainEvaluation: public OperatorEvaluation<Scalar> {
02186 
02187     friend class PartialDerivEvaluation<Scalar>;  // added by Yin at 07.15.2013
02188 
02189     PartialDerivEvaluation<Scalar> deriv;
02190 
02191     // disabled
02192     OperatorProductDomainEvaluation();
02193     OperatorProductDomainEvaluation
02194     (const OperatorProductDomainEvaluation<Scalar> &);
02195   
02196   public:
02197   
02200     OperatorProductDomainEvaluation(OperatorProductDomain<Scalar> & _f, 
02201                     const Vector<Scalar> & _x)
02202       : OperatorEvaluation<Scalar>(_f,_x), deriv(*this) {}
02203 
02204     virtual ~OperatorProductDomainEvaluation() {}
02205 
02208     const LinearOp<Scalar> & getPartialDeriv(int ic) { 
02209       try {
02210     deriv.setBlock(ic);
02211     return deriv;
02212       }
02213       catch (RVLException & e) {
02214     e<<"\ncalled from OperatorProductDomainEvaluation::getPartialDeriv\n";
02215     throw e;
02216       }
02217     }
02218 
02219     ostream & write(ostream & str) const{
02220       str<<"Operator Evaluation with Product Domain; as"<<"\n";
02221       return OperatorEvaluation<Scalar>::write(str);
02222     }
02223   };
02224 
02227   template<class Scalar>
02228   class PartialDerivEvaluation: public LinearOp<Scalar> {
02229 
02230     friend class OperatorProductDomainEvaluation<Scalar>; 
02231 
02232   private:
02233 
02234     OperatorProductDomainEvaluation<Scalar> & fx;
02235     int ic;
02236 
02237     // disabled
02238     PartialDerivEvaluation();
02239     PartialDerivEvaluation(const PartialDerivEvaluation<Scalar> & d)
02240       : fx(d.fx), ic(d.ic) {}
02241 
02242   protected:
02243 
02244     PartialDerivEvaluation(OperatorProductDomainEvaluation<Scalar> & _fx)
02245       : fx(_fx), ic(0) {}
02246 
02247    LinearOp<Scalar> * clone() const { 
02248       return new PartialDerivEvaluation<Scalar>(*this);
02249     }
02250 
02251     // image, application, MatVec product, whatever
02252     void apply(const Vector<Scalar> & y, 
02253            Vector<Scalar> & z) const {
02254       try { fx.applyPartialDeriv(ic,y,z); }
02255       catch (RVLException & e) {
02256     e<<"\ncalled in PartialDerivEvaluation::apply\n";
02257     throw e;
02258       }
02259     }
02260 
02261     // image of adjoint (transpose) operator
02262     void applyAdj(const Vector<Scalar> & y,
02263           Vector<Scalar> & z) const {
02264       try { fx.applyAdjPartialDeriv(ic,y,z); }
02265       catch (RVLException & e) {
02266     e<<"\ncalled in PartialDerivEvaluation::applyAdj\n";
02267     throw e;
02268       }
02269     }
02270 
02271   public:
02272 
02273     ~PartialDerivEvaluation() {}
02274 
02275     const Space<Scalar> & getDomain() const { 
02276       try { return (fx.getProductDomain())[ic]; }
02277       catch (RVLException & e) {
02278     e<<"\ncalled from PartialDerivEvaluation::getProductDomain()\n";
02279     throw e;
02280       }
02281     }
02282 
02283     const Space<Scalar> & getRange() const { return fx.getRange(); }
02284 
02285     void setBlock(int i) { ic=i; }  // added by Yin at 07.15.2013
02286 
02287     ostream & write(ostream & str) const{
02288       str<<"Partial Derivative operator"<<"\n";
02289       str<<"component "<<ic<<"\n";
02290       str<<"part of functional evaluation"<<"\n";
02291       fx.write(str);
02292       return str;
02293     }
02294   };
02295 
02305   template<class Scalar>
02306   class LNLOperator: public Operator<Scalar> {
02307   private:
02308 
02309     LinearOp<Scalar> const & L;
02310     // disabled
02311     LNLOperator();
02312 
02313   protected:
02314 
02315     void apply(const Vector<Scalar> & x, 
02316            Vector<Scalar> & y) const {
02317       try {
02318     L.applyOp(x,y);
02319       }
02320       catch (RVLException & e) {
02321     e<<"\ncalled from LNLOperator::apply\n";
02322     throw e;
02323       }
02324     }
02325   
02326     void applyDeriv(const Vector<Scalar> & x, 
02327             const Vector<Scalar> & dx,
02328             Vector<Scalar> & dy) const {
02329       try {
02330     L.applyOp(dx,dy);
02331       }
02332       catch (RVLException & e) {
02333     e<<"\ncalled from LNLOperator::applyDeriv\n";
02334     throw e;
02335       }
02336     }
02337 
02338     void applyAdjDeriv(const Vector<Scalar> & x, 
02339                const Vector<Scalar> & dy,
02340                Vector<Scalar> & dx) const {
02341       try {
02342     L.applyAdjOp(dy,dx);
02343       }
02344       catch (RVLException & e) {
02345     e<<"\ncalled from LNLOperator::applyAdjDeriv\n";
02346     throw e;
02347       }
02348     }
02349   
02350   public:
02351 
02353     LNLOperator(LinearOp<Scalar> const & LL) : L(LL) {}
02354     LNLOperator(const LNLOperator<Scalar> & op) : L(op.L) {}
02355     ~LNLOperator() {}
02356     
02357     // virtual copy constructor - permits override
02358     virtual Operator<Scalar> * clone() const {
02359       return new LNLOperator<Scalar>(*this);
02360     }
02361 
02363     const Space<Scalar> & getDomain() const { return L.getDomain(); }
02364     const Space<Scalar> & getRange() const { return L.getRange(); }
02365 
02366     ostream & write(ostream & str) const {
02367       str<<"Linear operator as operator"<<"\n";
02368       L.write(str);
02369       return str;
02370     }
02371   };
02372 
02383   template<class Scalar>
02384   class ANLOperator: public Operator<Scalar> {
02385   private:
02386 
02387     LinearOp<Scalar> const & L;
02388     Vector<Scalar> const & d;
02389     // disabled
02390     ANLOperator();
02391 
02392   protected:
02393 
02394     void apply(const Vector<Scalar> & x, 
02395            Vector<Scalar> & y) const {
02396       try {
02397     L.applyOp(x,y);
02398     y.linComb(-1.0,d);
02399       }
02400       catch (RVLException & e) {
02401     e<<"\ncalled from ANLOperator::apply\n";
02402     throw e;
02403       }
02404     }
02405   
02406     void applyDeriv(const Vector<Scalar> & x, 
02407             const Vector<Scalar> & dx,
02408             Vector<Scalar> & dy) const {
02409       try {
02410     L.applyOp(dx,dy);
02411       }
02412       catch (RVLException & e) {
02413     e<<"\ncalled from ANLOperator::applyDeriv\n";
02414     throw e;
02415       }
02416     }
02417 
02418     void applyAdjDeriv(const Vector<Scalar> & x, 
02419                const Vector<Scalar> & dy,
02420                Vector<Scalar> & dx) const {
02421       try {
02422     L.applyAdjOp(dy,dx);
02423       }
02424       catch (RVLException & e) {
02425     e<<"\ncalled from ANLOperator::applyAdjDeriv\n";
02426     throw e;
02427       }
02428     }
02429   
02430   public:
02431 
02433     ANLOperator(LinearOp<Scalar> const & LL, Vector<Scalar> const & dd) 
02434       : L(LL), d(dd) {}
02435     ANLOperator(const ANLOperator<Scalar> & op) : L(op.L), d(op.d) {}
02436     ~ANLOperator() {}
02437 
02438     // virtual to permit override
02439     virtual Operator<Scalar> * clone() const {
02440       return new ANLOperator<Scalar>(*this);
02441     }
02442 
02444     Space<Scalar> & getDomain() const { return L.getDomain(); }
02445     Space<Scalar> & getRange() const { return L.getRange(); }
02446 
02447     ostream & write(ostream & str) const {
02448       str<<"Affine operator as operator: linear op"<<"\n";
02449       L.write(str);
02450       str<<"*** shift vector\n";
02451       d.write(str);
02452       return str;
02453     }
02454   };
02455 
02472   template<class Scalar>
02473   class OpFO: public Operator<Scalar> {
02474   private:
02475     
02476     FunctionObject & f;
02477     FunctionObject & dff;
02478     FunctionObject & dfa;
02479     
02480     Space<Scalar> const & dom;
02481     Space<Scalar> const & rng;
02482     
02483     mutable std::vector< RVL::Vector<Scalar> const *> inp;
02484     mutable std::vector< RVL::Vector<Scalar> const *> inpd;
02485 
02486     OpFO();
02487     
02488   protected:
02489     
02490     void apply(const Vector<Scalar> & x, 
02491            Vector<Scalar> & y) const {
02492       try {
02493     inp[0]=&x;
02494     y.eval(f,inp);
02495       }
02496       catch (RVLException & e) {
02497     e<<"\ncalled in OpFO::apply\n";
02498     throw e;
02499       }
02500     }
02501 
02502     void applyDeriv(const Vector<Scalar> & x, 
02503             const Vector<Scalar> & dx,
02504             Vector<Scalar> & z) const {
02505       try {
02506     inpd[0]=&x;
02507     inpd[1]=&dx;
02508     z.eval(dff,inpd);
02509       }
02510       catch (RVLException & e) {
02511     e<<"\ncalled in OpFO::applyDeriv\n";
02512     throw e;
02513       }
02514     }
02515 
02516     void applyAdjDeriv(const Vector<Scalar> & x, 
02517                const Vector<Scalar> & y,
02518                Vector<Scalar> & z) const {
02519       try {
02520     inpd[0]=&x;
02521     inpd[1]=&y;
02522     z.eval(dfa,inpd);
02523       }
02524       catch (RVLException & e) {
02525     e<<"\ncalled in OpFO::applyAdjDeriv\n";
02526     throw e;
02527       }
02528     }
02529 
02530 
02531   public:
02532 
02533     OpFO(const OpFO<Scalar> & A): 
02534       dom(A.dom), rng(A.rng),
02535       f(A.f), dff(A.dff), dfa(A.dfa),
02536       inp(A.inp), inpd(A.inpd) {}
02537 
02538     OpFO(Space<Scalar> const & _dom,
02539      Space<Scalar> const & _rng,
02540      FunctionObject & _f,
02541      FunctionObject & _dff,
02542      FunctionObject & _dfa):
02543       dom(_dom), rng(_rng), f(_f), dff(_dff), dfa(_dfa),
02544       inp(1), inpd(2) {}
02545 
02546     OpFO(Space<Scalar> const & _dom,
02547      Space<Scalar> const & _rng,
02548      FunctionObject & _f,
02549      FunctionObject & _dff,
02550      FunctionObject & _dfa,
02551      std::vector<RVL::Vector<Scalar> const *> par):
02552       dom(_dom), rng(_rng), f(_f), dff(_dff), dfa(_dfa), 
02553       inp(1+par.size()), inpd(2+par.size()) {
02554       for (int i=0;i<par.size();i++) { inp[i+1]=par[i]; inpd[i+2]=par[i]; }
02555     }
02556 
02557     ~OpFO() {}
02558 
02559     // this class is considered terminal, with no overrides foreseen,
02560     // so clone method is not virtual
02561     Operator<Scalar> * clone() const { return new OpFO<Scalar>(*this); }
02562 
02563     // access to domain, range
02564     const Space<Scalar> & getDomain() const { return dom; }
02565     const Space<Scalar> & getRange() const { return rng; }
02566 
02567     ostream & write(ostream & str) const {
02568       str<<"Operator built of function object components"<<endl;
02569       str<<"image function:"<<endl;
02570       f.write(str);
02571       str<<"derivative image function:"<<endl;
02572       dff.write(str);
02573       str<<"derivative adjoint image function:"<<endl;
02574       dfa.write(str);
02575       return str;
02576     }
02577 
02578   };
02579 
02604   template<class Scalar>
02605   class LinCombOperator: public Operator<Scalar> {
02606   private:
02607   
02608     mutable std::vector<Operator<Scalar> *> opvec;
02609     mutable std::vector<Scalar> wtvec;
02610     mutable bool applied;
02611 
02613     void setNext(Scalar a, Operator<Scalar> const & op) {
02614       try {
02615     if (applied) {
02616       RVLException e;
02617       e<<"Error: LinCombOperator::setNext\n";
02618       e<<"object already initialized - non-initialization method called\n";
02619       e<<"further alteration to object data not allowed\n";
02620       throw e;
02621     }
02622     if (opvec.size() > 0) {
02623       if ( (op.getDomain() != opvec[0]->getDomain()) ||
02624            (op.getRange()  != opvec[0]->getRange()) ) {
02625         RVLException e;
02626         e<<"Error: LinCombOp::setNext\n";
02627         e<<"domain or ranges of input operator incompatible with reference (summand 0)\n";
02628         e<<"*** input operator:\n";
02629         op.write(e);
02630         e<<"*** reference operator:\n";
02631         opvec[0]->write(e);
02632         throw e;
02633       }
02634     }
02635     wtvec.push_back(a);
02636     opvec.push_back(RVL::Operator<Scalar>::export_clone(op));
02637       }
02638       catch (RVLException & e) {
02639     e<<"\ncalled from LinCombOperator::setNext\n";
02640       }
02641     }
02642 
02643   protected:
02644 
02645     void apply(const Vector<Scalar> & x, 
02646            Vector<Scalar> & val) const {
02647       try {
02648    
02649     if (opvec.size()<1) {
02650       RVLException e;
02651       e<<"Error: LinCombOp::apply\n";
02652       e<<"not initialized\n";
02653       throw e;
02654     }
02655     applied = true;
02656     this->export_apply(*(opvec[0]),x,val);
02657     val.scale(wtvec[0]);
02658     if (opvec.size() > 1) {
02659       Vector<Scalar> tmp(opvec[0]->getRange());
02660       for (int i=i; i<(int)opvec.size(); i++) {
02661         this->export_apply(*(opvec[i]),x,tmp);
02662         val.linComb(wtvec[i],tmp);
02663       }
02664     }
02665       }
02666       catch (RVLException & e) {
02667     e<<"\ncalled from LinCombOperator::apply\n";
02668     throw e;
02669       }
02670     }
02671 
02672     void applyDeriv(const Vector<Scalar> & x,
02673             const Vector<Scalar> & dx,
02674             Vector<Scalar> & dy) const {
02675       try {
02676     if (opvec.size()<1) {
02677       RVLException e;
02678       e<<"Error: LinCombOp::applyDeriv\n";
02679       e<<"not initialized\n";
02680       throw e;
02681     }
02682     applied = true;
02683     this->export_applyDeriv(*(opvec[0]),x,dx,dy);
02684     dy.scale(wtvec[0]);
02685     if (opvec.size() > 1) {
02686       Vector<Scalar> tmp(opvec[0]->getRange());
02687       for (int i=i; i<(int)opvec.size(); i++) {
02688         this->export_applyDeriv(*(opvec[i]),x,dx,tmp);
02689         dy.linComb(wtvec[i],tmp);
02690       }
02691     }
02692       }
02693       catch (RVLException & e) {
02694     e<<"\ncalled from LinCombOperator::applyDeriv\n";
02695     throw e;
02696       }
02697     }
02698 
02699     void applyAdjDeriv(const Vector<Scalar> & x,
02700                const Vector<Scalar> & dy,
02701                Vector<Scalar> & dx) const {
02702       try {
02703     if (opvec.size()<1) {
02704       RVLException e;
02705       e<<"Error: LinCombOp::applyAdjDeriv\n";
02706       e<<"not initialized\n";
02707       throw e;
02708     }
02709     applied = true;
02710     this->export_applyAdjDeriv(*(opvec[0]),x,dy,dx);
02711     dx.scale(wtvec[0]);
02712     if (opvec.size() > 1) {
02713       Vector<Scalar> tmp(opvec[0]->getDomain());
02714       for (int i=i; i<(int)opvec.size(); i++) {
02715         this->export_applyAdjDeriv(*(opvec[i]),x,dy,tmp);
02716         dx.linComb(wtvec[i],tmp);
02717       }
02718     }
02719       }
02720       catch (RVLException & e) {
02721     e<<"\ncalled from LinCombOperator::applyAdjDeriv\n";
02722     throw e;
02723       }
02724     }
02725 
02726     Operator<Scalar> * clone() const { 
02727       applied = true;
02728       return new LinCombOperator<Scalar>(*this); 
02729     }
02730 
02731   public:
02732   
02733     LinCombOperator(LinCombOperator<Scalar> const & op) {
02734       try {
02735     for (int i=0;i<op.opvec.size(); i++) {
02736       opvec.push_back(op.opvec[i]->clone());
02737       wtvec.push_back(op.wtvec[i]);
02738     }   
02739       }
02740       catch (RVLException & e) {
02741     e<<"\ncalled from LinCombOperator copy constructor\n";
02742       }
02743     }
02744 
02745     LinCombOperator(Scalar a1, Operator<Scalar> const & op1,
02746             Scalar a2, Operator<Scalar> const & op2)
02747       : opvec(2), wtvec(2) {
02748       try {
02749     this->setNext(a1, op1);
02750     this->setNext(a2, op2);
02751       }
02752       catch (RVLException & e) {
02753     e<<"\ncalled from LinCombOperator pair constructor\n";
02754     throw e;
02755       }
02756     }
02757 
02758     LinCombOperator(Scalar a1, Operator<Scalar> const & op1,
02759             Scalar a2, Operator<Scalar> const & op2,
02760             Scalar a3, Operator<Scalar> const & op3)
02761       : opvec(3), wtvec(3) {
02762       try {
02763     this->setNext(a1, op1);
02764     this->setNext(a2, op2);
02765     this->setNext(a3, op3);
02766       }
02767       catch (RVLException & e) {
02768     e<<"\ncalled from LinCombOperator triple constructor\n";
02769     throw e;
02770       }
02771     }
02772 
02773     LinCombOperator(Scalar a1, Operator<Scalar> const & op1,
02774             Scalar a2, Operator<Scalar> const & op2,
02775             Scalar a3, Operator<Scalar> const & op3,
02776             Scalar a4, Operator<Scalar> const & op4)
02777       : opvec(4), wtvec(4) {
02778       try {
02779     this->setNext(a1, op1);
02780     this->setNext(a2, op2);
02781     this->setNext(a3, op3);
02782     this->setNext(a4, op4);
02783       }
02784       catch (RVLException & e) {
02785     e<<"\ncalled from LinCombOperator quad constructor\n";
02786     throw e;
02787       }
02788     }
02789 
02790     LinCombOperator(Scalar a1, Operator<Scalar> const & op1,
02791             Scalar a2, Operator<Scalar> const & op2,
02792             Scalar a3, Operator<Scalar> const & op3,
02793             Scalar a4, Operator<Scalar> const & op4,
02794             Scalar a5, Operator<Scalar> const & op5)
02795       : opvec(2), wtvec(2) {
02796       try {
02797     this->setNext(a1, op1);
02798     this->setNext(a2, op2);
02799     this->setNext(a3, op3);
02800     this->setNext(a4, op4);
02801     this->setNext(a5, op5);
02802       }
02803       catch (RVLException & e) {
02804     e<<"\ncalled from LinCombOperator quint constructor\n";
02805     throw e;
02806       }
02807     }
02808 
02809     ~LinCombOperator() {
02810     for (int i=0;i<(int)opvec.size(); i++) if (opvec[i]) delete opvec[i];
02811     }
02812 
02814     const Space<Scalar> & getDomain() const {
02815       try {
02816     if (opvec.size()<1) {
02817       RVLException e;
02818       e<<"Error: LinCombOperator::getDomain\n";
02819       e<<"object not initialized\n";
02820       throw e;
02821     }
02822     applied = true;
02823     return opvec[0]->getDomain();
02824       }
02825       catch (RVLException & e) {
02826     e<<"\ncalled from LinCombOperator::getDomain\n";
02827       }
02828     }
02829 
02830     const Space<Scalar> & getRange() const {
02831       try {
02832     if (opvec.size()<1) {
02833       RVLException e;
02834       e<<"Error: LinCombOperator::getDomain\n";
02835       e<<"object not initialized\n";
02836       throw e;
02837     } 
02838     applied = true;
02839     return opvec[0]->getRange(); 
02840       }
02841       catch (RVLException & e) {
02842     e<<"\ncalled from LinCombOperator::getRange\n";
02843       }
02844     }
02845 
02846     ostream & write(ostream & str) const {
02847       str<<"LinCombOperator: linear combination of vector-valued functions\n";
02848       if (opvec.size()<1) {
02849     str<<"not initialized\n";
02850       }
02851       else {
02852       for (int i=0;i<(int)opvec.size();i++) {
02853       str<<" --- Operator "<<i<<" with weight "<<wtvec[i]<<"\n";
02854       opvec[i]->write(str);
02855     }
02856       }
02857       return str;
02858     }
02859   };
02860 
02866   template<typename Scalar>
02867   class LinearOpEvaluation {
02868     
02869   private:
02870 
02871     Vector<Scalar> const & ref;
02872     LinearOp<Scalar> const & op;
02873     mutable Vector<Scalar> val;
02874     mutable bool applied;
02875 
02876     LinearOpEvaluation();
02877     LinearOpEvaluation(LinearOpEvaluation<Scalar> const &);
02878 
02879   public:
02880 
02881     LinearOpEvaluation(LinearOp<Scalar> const & _op,
02882                Vector<Scalar> const & _ref)
02883      : ref(_ref), op(_op), val(op.getRange()), applied(false) {
02884       if (ref.getSpace() != op.getDomain()) {
02885     RVLException e;
02886     e<<"Error: LinearOpEvaluation constructor\n";
02887     e<<"input vector not in domain of operator\n";
02888     e<<"\nvector:\n";
02889     ref.write(e);
02890     e<<"\noperator:\n";
02891     op.write(e);
02892     throw e;
02893       }
02894     }
02895 
02896     Vector<Scalar> const & getValue() const {
02897       if (!applied) {
02898     op.applyOp(ref,val);
02899     applied=true;
02900       }
02901       return val;
02902     }
02903   
02904   };
02905   
02911   template<typename Scalar>
02912   class LinearOpAdjEvaluation {
02913     
02914   private:
02915 
02916     Vector<Scalar> const & ref;
02917     LinearOp<Scalar> const & op;
02918     mutable Vector<Scalar> val;
02919     mutable bool applied;
02920 
02921     LinearOpAdjEvaluation();
02922     LinearOpAdjEvaluation(LinearOpEvaluation<Scalar> const &);
02923 
02924   public:
02925 
02926     LinearOpAdjEvaluation(LinearOp<Scalar> const & _op,
02927               Vector<Scalar> const & _ref)
02928       : ref(_ref), op(_op), val(op.getDomain()), applied(false) {
02929       if (ref.getSpace() != op.getRange()) {
02930     RVLException e;
02931     e<<"Error: LinearOpAdjEvaluation constructor\n";
02932     e<<"input vector not in range of operator\n";
02933     e<<"\nvector:\n";
02934     ref.write(e);
02935     e<<"\noperator:\n";
02936     op.write(e);
02937     throw e;
02938       }
02939     }
02940 
02941     Vector<Scalar> const & getValue() const {
02942       if (!applied) {
02943     op.applyAdjOp(ref,val);
02944     applied=true;
02945       }
02946       return val;
02947     }
02948   
02949   };
02950   
03001   template<class Scalar>
03002   class OpComp: public Operator<Scalar> {
03003 
03004   private:
03005 
03006     mutable std::vector<Operator<Scalar> *> opvec;
03007     mutable bool applied;
03008 
03009 
03010   protected:
03011 
03013     void apply(const Vector<Scalar> & x, 
03014            Vector<Scalar> & val) const {
03015       try {
03016     if (opvec.size()<1) {
03017       RVLException e;
03018       e<<"Error: OpComp::apply\n";
03019       e<<"object not initialized\n";
03020       throw e;
03021     }
03022     // set flag to indicate finish of initialization
03023     applied = true;
03024 
03025     // allocate intermediate vectors via evaluation
03026     // special case: one op only, no tmp vector allocation needed
03027     if (opvec.size()==1) 
03028       this->export_apply(*(opvec[0]),x,val);
03029     else {
03030       std::vector<OperatorEvaluation<Scalar> *> opeval(opvec.size()-1);
03031       opeval[0] = new OperatorEvaluation<Scalar>(*(opvec[0]),x);
03032       for (int i=1;i<(int)opvec.size()-1;i++) 
03033         opeval[i] = new OperatorEvaluation<Scalar>(*(opvec[i]),opeval[i-1]->getValue());
03034       this->export_apply(*(opvec[opvec.size()-1]),opeval[opvec.size()-2]->getValue(),val);
03035       for (int i=opvec.size()-2;i>-1;i--) delete opeval[i];
03036     }
03037       }
03038       catch (RVLException & e) {
03039     e<<"\ncalled from OpComp::apply\n";
03040     throw e;
03041       }
03042     }
03043 
03045     void applyDeriv(const Vector<Scalar> & x, 
03046             const Vector<Scalar> & dx,
03047             Vector<Scalar> & dy) const {
03048       try {
03049   
03050     if (opvec.size()<1) {
03051       RVLException e;
03052       e<<"Error: OpComp::applyDeriv\n";
03053       e<<"object not initialized\n";
03054       throw e;
03055     }
03056     // set flag to indicate finish of initialization
03057     applied = true;
03058 
03059     // allocate intermediate vectors via evaluation
03060     // special case: one op only, no tmp vector allocation needed
03061     if (opvec.size()==1) 
03062       this->export_applyDeriv(*(opvec[0]),x,dx,dy);
03063 
03064     // all other cases handled uniformly
03065     else {
03066 
03067       std::vector<LinearOp<Scalar> *> linop(opvec.size(),NULL); // NB: pointer copy, no allocation
03068       std::vector<OperatorEvaluation<Scalar> *> opeval(opvec.size(), NULL);
03069       std::vector<LinearOpEvaluation<Scalar> *> lineval(opvec.size(),NULL);
03070 
03071       // find last non-linear op 
03072       int lastlin=opvec.size();
03073 
03074       while ((lastlin>0) && (linop[lastlin-1]=dynamic_cast<LinearOp<Scalar> *>(opvec[lastlin-1])) ) {
03075         lastlin--;
03076       }
03077       for (int i=0;i<lastlin;i++) {
03078         if (i==0) {
03079           opeval[i] = new OperatorEvaluation<Scalar>(*(opvec[i]),x);
03080           lineval[i] = new LinearOpEvaluation<Scalar>(opeval[i]->getDeriv(),dx);
03081         }
03082         else if (i==(int)opvec.size()-1) {
03083           opeval[i] = new OperatorEvaluation<Scalar>(*(opvec[i]),opeval[i-1]->getValue());
03084           opeval[i]->getDeriv().applyOp(lineval[i-1]->getValue(),dy);   
03085         }
03086         else {
03087           opeval[i] = new OperatorEvaluation<Scalar>(*(opvec[i]),opeval[i-1]->getValue());
03088           lineval[i] = new LinearOpEvaluation<Scalar>(opeval[i]->getDeriv(),lineval[i-1]->getValue());
03089         }
03090       }
03091       for (int i=lastlin;i<(int)opvec.size();i++) {
03092         // last
03093           if (i==(int)opvec.size()-1) 
03094           this->export_apply(*(opvec[i]),lineval[i-1]->getValue(),dy);    
03095         // middle
03096         else if (i > 0) 
03097           lineval[i]=new LinearOpEvaluation<Scalar>(*linop[i],lineval[i-1]->getValue());
03098         // first
03099         else
03100           lineval[0] = new LinearOpEvaluation<Scalar>(*linop[0],dx);
03101       }
03102       
03103       // clean up
03104       for (int i=opvec.size()-1;i>-1;i--) { 
03105         if (lineval[i]) delete lineval[i];
03106         if (opeval[i]) delete opeval[i];
03107       }
03108     }
03109       }
03110       catch (RVLException & e) {
03111     e<<"\ncalled from OpComp::applyDeriv\n";
03112     throw e;
03113       }
03114     }
03115 
03119     void applyAdjDeriv(const Vector<Scalar> & x, 
03120                const Vector<Scalar> & dy,
03121                Vector<Scalar> & dx) const {
03122       try {
03123     // cerr<<"OpComp::applyAdjDeriv 0\n";
03124     if (opvec.size()<1) {
03125       RVLException e;
03126       e<<"Error: OpComp::applyAdjDeriv\n";
03127       e<<"object not initialized\n";
03128       throw e;
03129     }
03130     // set flag to indicate finish of initialization
03131     applied = true;
03132 
03133     // allocate intermediate vectors via evaluation
03134     // special case: one op only, no tmp vector allocation needed
03135     if (opvec.size()==1) 
03136       this->export_applyAdjDeriv(*(opvec[0]),x,dy,dx);
03137 
03138     // all other cases handled uniformly
03139     else {
03140       std::vector<LinearOp<Scalar> *> linop(opvec.size(),NULL); // NB: pointer copy, no allocation
03141       std::vector<OperatorEvaluation<Scalar> *> opeval(opvec.size(),NULL);
03142       std::vector<LinearOpAdjEvaluation<Scalar> *> lineval(opvec.size(),NULL);
03143 
03144       // find last non-linear op 
03145       int lastlin=opvec.size();
03146 
03147       while ((lastlin > 0) && (linop[lastlin-1]=dynamic_cast<LinearOp<Scalar> *>(opvec[lastlin-1]))) {
03148         lastlin--;
03149       }
03150 
03151       for (int i=0;i<lastlin;i++) {
03152         if (i==0) {
03153           opeval[i] = new OperatorEvaluation<Scalar>(*(opvec[i]),x);
03154         }
03155         else {
03156           opeval[i] = new OperatorEvaluation<Scalar>(*(opvec[i]),opeval[i-1]->getValue());
03157         }
03158       }
03159 
03160       for (int i=opvec.size()-1;i>lastlin-1;i--) {
03161         // note that opvec.size() > 1 here, so these branches are indep.
03162         // last
03163           if (i==(int)opvec.size()-1)  
03164           lineval[i]=new LinearOpAdjEvaluation<Scalar>(*(linop[i]),dy);
03165         // middle
03166         else if (i>0)
03167           lineval[i]=new LinearOpAdjEvaluation<Scalar>(*(linop[i]),lineval[i+1]->getValue());
03168         // first
03169         else 
03170           linop[0]->applyAdjOp(lineval[1]->getValue(),dx);
03171       }
03172       for (int i=lastlin-1;i>-1;i--) {
03173         // last step
03174         if (i==0) {
03175           opeval[i]->getDeriv().applyAdjOp(lineval[i+1]->getValue(),dx);    
03176         }
03177         // in case it's ALL nonlinear
03178         else if (i==(int)opvec.size()-1) {
03179           lineval[i] = new LinearOpAdjEvaluation<Scalar>(opeval[i]->getDeriv(),dy);
03180         }
03181         // generic nonlinear step
03182         else {
03183           lineval[i] = new LinearOpAdjEvaluation<Scalar>(opeval[i]->getDeriv(),lineval[i+1]->getValue());
03184         }
03185       }
03186       
03187       for (int i=opvec.size()-1;i>-1;i--) if (opeval[i]) delete opeval[i];
03188       for (int i=0;i<(int)opvec.size();i++)  if (lineval[i]) delete lineval[i];
03189      
03190     }
03191       }
03192       catch (RVLException & e) {      
03193     e<<"\ncalled from OpComp::applyAdjDeriv\n";
03194     throw e;
03195       }
03196     }
03197 
03199     void applyDeriv2(const Vector<Scalar> & x,
03200              const Vector<Scalar> & dx0,
03201              const Vector<Scalar> & dx1,
03202              Vector<Scalar> & dy) const {
03203       try {
03204     
03205     if (opvec.size()<1) {
03206       RVLException e;
03207       e<<"Error: OpComp::applyDeriv2\n";
03208       e<<"object not initialized\n";
03209       throw e;
03210     }
03211     // set flag to indicate finish of initialization
03212     applied = true;
03213         
03214     // allocate intermediate vectors via evaluation
03215     // special case: one op only, no tmp vector allocation needed
03216     if (opvec.size()==1)
03217       this->export_applyDeriv2(*(opvec[0]),x,dx0,dx1,dy);
03218     else if(opvec.size()==2){
03219       std::vector<OperatorEvaluation<Scalar> *> opeval(opvec.size(), NULL);
03220       opeval[0] = new OperatorEvaluation<Scalar>(*(opvec[0]),x);
03221       opeval[1] = new OperatorEvaluation<Scalar>(*(opvec[1]),opeval[0]->getValue());
03222       Vector<Scalar> tmp(opvec[1]->getRange());
03223       Vector<Scalar> dgx0(opvec[1]->getDomain());
03224       Vector<Scalar> dgx1(opvec[1]->getDomain());
03225       Vector<Scalar> d2gx(opvec[1]->getDomain());
03226           
03227       opeval[0]->getDeriv().applyOp(dx0,dgx0);
03228       opeval[0]->getDeriv().applyOp(dx1,dgx1);
03229       opeval[0]->getDeriv2().applyOp(dx0,dx1,d2gx);
03230       opeval[1]->getDeriv2().applyOp(dgx0,dgx1,tmp);
03231       opeval[1]->getDeriv().applyOp(d2gx,dy);
03232       dy.linComb(1.0, tmp);
03233       for (int i=opvec.size()-1;i>-1;i--) if (opeval[i]) delete opeval[i];
03234           
03235     }
03236     // all other cases handled uniformly
03237     else {
03238       RVLException e;
03239       e<<"Error: OpComp::applyDeriv2\n";
03240       e<<"deriv2 for more than two operators has not been implemented\n";
03241       throw e;
03242           
03243     }
03244       }
03245       catch (RVLException & e) {
03246     e<<"\ncalled from OpComp::applyDeriv2\n";
03247     throw e;
03248       }
03249     }
03250     
03251     void applyAdjDeriv2(const Vector<Scalar> & x,
03252             const Vector<Scalar> & dx0,
03253             const Vector<Scalar> & dy,
03254             Vector<Scalar> & dx1) const {
03255       try {
03256     if (opvec.size()<1) {
03257       RVLException e;
03258       e<<"Error: OpComp::applyAdjDeriv2\n";
03259       e<<"object not initialized\n";
03260       throw e;
03261     }
03262     // set flag to indicate finish of initialization
03263     applied = true;
03264     if (opvec.size()==1)
03265       this->export_applyAdjDeriv2(*(opvec[0]),x,dx0,dy,dx1);
03266     else if(opvec.size()==2){
03267       std::vector<OperatorEvaluation<Scalar> *> opeval(opvec.size(), NULL);
03268       opeval[0] = new OperatorEvaluation<Scalar>(*(opvec[0]),x);
03269       opeval[1] = new OperatorEvaluation<Scalar>(*(opvec[1]),opeval[0]->getValue());
03270       Vector<Scalar> tmp(opvec[0]->getDomain());
03271       Vector<Scalar> tmp0(opvec[1]->getDomain());
03272       Vector<Scalar> dftdy(opvec[1]->getDomain());
03273       Vector<Scalar> dgx0(opvec[1]->getDomain());
03274           
03275       opeval[0]->getDeriv().applyOp(dx0,dgx0);
03276       opeval[1]->getDeriv2().applyAdjOp(dgx0,dy,tmp0);
03277       opeval[0]->getDeriv().applyAdjOp(tmp0,tmp);
03278       
03279       opeval[1]->getDeriv().applyAdjOp(dy,dftdy);
03280       opeval[0]->getDeriv2().applyAdjOp(dx0,dftdy,dx1);
03281       dx1.linComb(1.0, tmp);
03282       for (int i=opvec.size()-1;i>-1;i--) if (opeval[i]) delete opeval[i];
03283           
03284     }
03285     // all other cases handled uniformly
03286     else {
03287       RVLException e;
03288       e<<"Error: OpComp::applyAdjDeriv2\n";
03289       e<<"deriv2 for more than two operators has not been implemented\n";
03290       throw e;
03291     }
03292       }
03293       catch (RVLException & e) {
03294     e<<"\ncalled from OpComp::applyAdjDeriv2\n";
03295     throw e;
03296       }
03297     }
03298     
03304     Operator<Scalar> * clone() const { return new OpComp<Scalar>(*this); }
03305     
03306   public:
03307 
03308     OpComp(): opvec(0), applied(false) {}
03309 
03310     OpComp(OpComp<Scalar> const & oc)
03311       : opvec(oc.opvec.size()), applied(false) {
03312     for (int i=0;i<(int)opvec.size(); i++) {
03313       opvec[i]=RVL::Operator<Scalar>::export_clone(*(oc.opvec[i]));
03314       }
03315     }
03316 
03319     void setNext(Operator<Scalar> const & opref) {
03320       try {
03321     if (applied) {
03322       RVLException e;
03323       e<<"Error: OpComp::setNext (Operator)\n";
03324       e<<"operator composition already initialized, may not alter\n";
03325       throw e;
03326     }
03327     if (opvec.size() > 0) {
03328       // last one was an Operator, and there is at least one of those
03329       if (opvec[opvec.size()-1]->getRange() != opref.getDomain())  {
03330         RVLException e;
03331         e<<"Error: OpComp::setNext \n";
03332         e<<"domain of next operator differs from range of previous\n";
03333         e<<"\nnext:\n";
03334         opref.write(e);
03335         e<<"\nprevious:\n";
03336         opvec[opvec.size()-1]->write(e);
03337         throw e;
03338       }
03339     }
03340     opvec.push_back(RVL::Operator<Scalar>::export_clone(opref));
03341       }
03342       catch (RVLException & e) {
03343     e<<"\ncalled from OpComp::setNext(Operator)\n";
03344     throw e;
03345       }
03346     }
03347 
03348     // old-style initializations - deprecated 
03350     OpComp(Operator<Scalar> const & op1ref,
03351        Operator<Scalar> const & op2ref)
03352       : opvec(0), applied(false) {
03353       try {
03354     this->setNext(op1ref);
03355     this->setNext(op2ref);
03356       }
03357       catch (RVLException & e) {
03358     e<<"Error: OpComp pair constructor from setNext\n";
03359     throw e;
03360       }
03361     }
03362 
03364     OpComp(Operator<Scalar> const & op1ref,
03365        Operator<Scalar> const & op2ref,
03366        Operator<Scalar> const & op3ref)
03367       : opvec(0), applied(false) {
03368       try {
03369     this->setNext(op1ref);
03370     this->setNext(op2ref);
03371     this->setNext(op3ref);
03372       }
03373       catch (RVLException & e) {
03374     e<<"Error: OpComp triple constructor from setNext\n";
03375     throw e;
03376       }
03377     }
03378 
03380     OpComp(Operator<Scalar> const & op1ref,
03381        Operator<Scalar> const & op2ref,
03382        Operator<Scalar> const & op3ref,
03383        Operator<Scalar> const & op4ref)
03384       : opvec(0), applied(false) {
03385       try {
03386     this->setNext(op1ref);
03387     this->setNext(op2ref);
03388     this->setNext(op3ref);
03389     this->setNext(op4ref);
03390       }
03391       catch (RVLException & e) {
03392     e<<"Error: OpComp quadruple constructor from setNext\n";
03393     throw e;
03394       }
03395     }
03396 
03398     OpComp(Operator<Scalar> const & op1ref,
03399        Operator<Scalar> const & op2ref,
03400        Operator<Scalar> const & op3ref,
03401        Operator<Scalar> const & op4ref,
03402        Operator<Scalar> const & op5ref)
03403       : opvec(0), applied(false) {
03404       try {
03405     this->setNext(op1ref);
03406     this->setNext(op2ref);
03407     this->setNext(op3ref);
03408     this->setNext(op4ref);
03409     this->setNext(op5ref);
03410       }
03411       catch (RVLException & e) {
03412     e<<"Error: OpComp quintuple constructor from setNext\n";
03413     throw e;
03414       }
03415     }
03416 
03417     ~OpComp() {
03418     for (int i=0;i<(int)opvec.size();i++) { delete opvec[i]; }
03419     }
03420 
03422     const Space<Scalar> & getDomain() const {
03423       try {
03424     if (opvec.size() > 0) {
03425       applied = true;
03426       return opvec[0]->getDomain();
03427     }
03428     RVLException e;
03429     e<<"Error: OpComp::getDomain\n";
03430     e<<"not initialized - no factors specified\n";
03431     throw e;
03432       }
03433     
03434       catch (RVLException & e) {
03435     e<<"\ncalled from OpComp::getDomain\n";
03436     throw e;
03437       }
03438     }
03439 
03440     const Space<Scalar> & getRange() const {
03441       try {
03442     if (opvec.size() > 0) {
03443       applied = true;
03444       return opvec[opvec.size()-1]->getRange();
03445     }
03446     RVLException e;
03447     e<<"Error: OpComp::getRange\n";
03448     e<<"not initialized - no factors specified\n";
03449     throw e;
03450       }
03451       catch (RVLException & e) {
03452     e<<"\ncalled from OpComp::getRange\n";
03453     throw e;
03454       }
03455     }
03456 
03457     ostream & write(ostream & str) const {
03458       try {
03459     if (opvec.size() > 0) {
03460       applied = true;
03461       str<<"OpComp: Operator composition\n";
03462       str<<"-- number of factors = "<<opvec.size()<<"\n";
03463       for (int i=0;i<(int)opvec.size(); i++) {
03464         str<<"\nfactor "<<i<<":\n";
03465         opvec[i]->write(str);
03466       }
03467       return str;
03468     }
03469     else {
03470       RVLException e;
03471       e<<"Error: OpComp::write\n";
03472       e<<"not initialized - no factors specified\n";
03473       throw e;
03474     }
03475       }
03476       catch (RVLException & e) {
03477     e<<"\ncalled from OpComp::write\n";
03478     throw e;
03479       }
03480     }
03481     
03482   };
03483 
03484   template<class Scalar>
03485   DerivEvaluation<Scalar> * 
03486   OperatorWithInvertibleDeriv<Scalar>::createDerivEvaluation
03487   (OperatorEvaluation<Scalar> & opeval) const {
03488     return new InvertibleDerivEvaluation<Scalar>(opeval);
03489   }
03490   
03491   /*
03492   template<class Scalar>
03493   bool OperatorWithInvertibleDeriv<Scalar>::checkInverseDeriv
03494   (const Vector<Scalar> & x,
03495    const Vector<Scalar> & dy,
03496    NormRetType tol,
03497    ostream & str) {
03498     Vector<Scalar> invdy(this->getDomain());
03499     Vector<Scalar> yd(this->getRange());
03500     applyInverseDeriv(x, dy, invdy);
03501     applyDeriv(x, invdy, yd);
03502     yd.linComb(-1.0, dy);
03503     NormRetType n;
03504     n = yd.norm();
03505     if( n < tol ) {
03506       str << "Success.  |DF(x)*inv(DF(x))*dy - dy| = " 
03507       << n << " < tol = " << tol << endl;
03508       return true;
03509     } else {
03510       str << "Failure.  |DF(x)*inv(DF(x))*dy - dy| = " 
03511       << n << " >= tol = " << tol << endl;
03512       return false;
03513     }
03514   }
03515   */
03516 
03517 
03521   template<class Scalar>
03522   class IdentityOp: public Operator<Scalar> {
03523 
03524   private:
03525 
03526     Space<Scalar> const & dom;
03527     Space<Scalar> const & rng;
03528 
03529     IdentityOp();
03530   
03531   protected:
03532 
03533     void apply(const Vector<Scalar> & x, 
03534            Vector<Scalar> & val) const {
03535       try {
03536     SpaceTest(this->getDomain(),x,"RVL::IdentityOp::apply (dom test)");
03537     SpaceTest(this->getRange(),val,"RVL::IdentityOp::apply (rng test)");
03538     //SpaceTest(x.getSpace(),val,"RVL::IdentityOp::apply (space test)");
03539     val.copy(x);
03540       }
03541       catch (RVLException & e) {
03542     e<<"\ncalled from IdentityOp::apply\n";
03543     throw e;
03544       }
03545     }
03546 
03547     void applyDeriv(const Vector<Scalar> & x, 
03548             const Vector<Scalar> & dx,
03549             Vector<Scalar> & dy) const {
03550       try {
03551     SpaceTest(this->getDomain(),x,"RVL::IdentityOp::applyDeriv (dom test x)");
03552     SpaceTest(this->getDomain(),dx,"RVL::IdentityOp::applyDeriv (dom test dx)");
03553     SpaceTest(this->getRange(),dy,"RVL::IdentityOp::applyDeriv (rng test)");
03554     dy.copy(dx);
03555       }
03556       catch (RVLException & e) {
03557     e<<"\ncalled from IdentityOp::applyDeriv\n";
03558     throw e;
03559       }
03560     }
03561 
03562     void applyAdjDeriv(const Vector<Scalar> & x, 
03563                const Vector<Scalar> & dy,
03564                Vector<Scalar> & dx) const {
03565       try {
03566     SpaceTest(this->getDomain(),x,"RVL::IdentityOp::applyAdjDeriv (dom test x)");
03567     SpaceTest(this->getDomain(),dx,"RVL::IdentityOp::applyAdjDeriv (dom test dx)");
03568     SpaceTest(this->getRange(),dy,"RVL::IdentityOp::applyAdjDeriv (rng test)");
03569     dx.copy(dy);
03570       }
03571       catch (RVLException & e) {
03572     e<<"\ncalled from IdentityOp::applyAdjDeriv\n";
03573     throw e;
03574       }
03575     }
03576 
03577     Operator<Scalar> * clone() const { return new IdentityOp<Scalar>(*this); }
03578     
03579   public:
03580 
03581     IdentityOp(const Space<Scalar> & sp)
03582       :dom(sp), rng(sp) {}
03583 
03584     IdentityOp(const IdentityOp<Scalar> & c) 
03585       : dom(c.getDomain()), rng(c.getRange()){}
03586 
03587     ~IdentityOp() {}
03588 
03590     const Space<Scalar> & getDomain() const {
03591       return dom;
03592     }
03593 
03594     const Space<Scalar> & getRange() const {
03595       return rng;
03596     }
03597 
03598     ostream & write(ostream & str) const {
03599       str<<"IdentityOp: Identity Operator\n";
03600       return str;
03601     }
03602     
03603   };
03604 
03605 
03606 
03607 
03608   
03609 }
03610 #endif
03611 

Generated on 5 Jan 2017 for RVL by  doxygen 1.4.7