linop_base.hh

Go to the documentation of this file.
00001 /*************************************************************************
00002 
00003 Copyright Rice University, 2004, 2005, 2006
00004 All rights reserved.
00005 
00006 Permission is hereby granted, free of charge, to any person obtaining a
00007 copy of this software and associated documentation files (the "Software"),
00008 to deal in the Software without restriction, including without limitation
00009 the rights to use, copy, modify, merge, publish, distribute, and/or sell
00010 copies of the Software, and to permit persons to whom the Software is
00011 furnished to do so, provided that the above copyright notice(s) and this
00012 permission notice appear in all copies of the Software and that both the
00013 above copyright notice(s) and this permission notice appear in supporting
00014 documentation.
00015 
00016 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00017 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00018 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY
00019 RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS
00020 NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL
00021 DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
00022 PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
00023 ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
00024 THIS SOFTWARE.
00025 
00026 Except as contained in this notice, the name of a copyright holder shall
00027 not be used in advertising or otherwise to promote the sale, use or other
00028 dealings in this Software without prior written authorization of the
00029 copyright holder.
00030 
00031 **************************************************************************/
00032 
00033 #ifndef __RVL_LINOP_BASE
00034 #define __RVL_LINOP_BASE
00035 
00036 #include "space.hh"
00037 #include "write.hh"
00038 
00039 namespace RVL {
00040 
00041   // because of this forward declaration, this header file MUST be
00042   // referenced only through inclusion in op.hh
00043   template<typename Scalar>
00044   class Operator;
00045 
00122   template <class Scalar>
00123   class LinearOp: public Operator<Scalar> {
00124     
00125   protected:
00126 
00136 #ifndef RVL_OPERATOR_NEW_ENABLED
00137     void * operator new(size_t size) { 
00138       void * ptr;
00139       ptr = (void *) ::new unsigned char[size]; 
00140       return ptr;
00141     }
00142 #endif
00143 
00144     // note: clone and apply are inherited from Operator
00145 
00150     virtual void applyAdj(const Vector<Scalar> & x,
00151               Vector<Scalar> & y) const = 0;
00152 
00156     void applyDeriv(const Vector<Scalar> &, 
00157             const Vector<Scalar> & dx,
00158             Vector<Scalar> & dy) const { this->apply(dx,dy); }
00159 
00161     void applyAdjDeriv(const Vector<Scalar> &, 
00162                const Vector<Scalar> & dy,
00163                Vector<Scalar> & dx) const { this->applyAdj(dy,dx); }
00164      
00169     void applyDeriv2(const Vector<Scalar> &,
00170                     const Vector<Scalar> &,
00171                     const Vector<Scalar> &,
00172                     Vector<Scalar> & dy) const { dy.zero(); }
00173       
00175     void applyAdjDeriv2(const Vector<Scalar> &,
00176                        const Vector<Scalar> &,
00177                        const Vector<Scalar> &,
00178                        Vector<Scalar> & dx1) const { dx1.zero(); }
00179 
00180   public:
00181 
00182     LinearOp() {}
00183     LinearOp(const LinearOp<Scalar> & Op) {}
00184     virtual ~LinearOp() {}
00185 
00186     // getDomain and getRange inherited from Operator
00187 
00193     void applyOp(Vector<Scalar> const & x,
00194          Vector<Scalar> & y) const {
00195       try {
00196 
00197     if (x.getSpace() != this->getDomain()) {
00198       RVLException e;
00199       e<<"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n";
00200       e<<"Error: LinearOp::applyOp - input not in domain\n";
00201       e<<"**********************\n";
00202       e<<"*** this operator: ***\n";
00203       e<<"**********************\n";
00204       this->write(e);
00205       e<<"**********************\n";
00206       e<<"*** domain space:  ***\n";
00207       e<<"**********************\n";
00208       this->getDomain().write(e);
00209       e<<"**********************\n";
00210       e<<"*** input space:   ***\n";
00211       e<<"**********************\n";
00212       x.getSpace().write(e);
00213       e<<"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n";
00214       throw e;
00215     }
00216 
00217     if (y.getSpace() != this->getRange()) {
00218       RVLException e;
00219       e<<"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n";
00220       e<<"Error: LinearOp::applyOp - output not in range\n";
00221       e<<"**********************\n";
00222       e<<"*** this operator: ***\n";
00223       e<<"**********************\n";
00224       this->write(e);
00225       e<<"**********************\n";
00226       e<<"*** range space:   ***\n";
00227       e<<"**********************\n";
00228       this->getRange().write(e);
00229       e<<"**********************\n";
00230       e<<"*** output space:  ***\n";
00231       e<<"**********************\n";
00232       y.getSpace().write(e);
00233       e<<"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n";
00234       throw e;
00235     }
00236 
00237     this->apply(x,y);
00238 
00239       }
00240 
00241       catch (RVLException & e) {
00242     e<<"\ncalled from LinearOp::applyOp\n";
00243     throw e;
00244       }
00245     }
00246 
00252     void applyAdjOp(Vector<Scalar> const & x,
00253             Vector<Scalar> & y) const {
00254 
00255       try {
00256 
00257     if (x.getSpace() != this->getRange()) {
00258       RVLException e;
00259       e<<"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n";
00260       e<<"Error: LinearOp::applyAdjOp - input not in range\n";
00261       e<<"**********************\n";
00262       e<<"*** this operator: ***\n";
00263       e<<"**********************\n";
00264       this->write(e);
00265       e<<"**********************\n";
00266       e<<"*** range space:   ***\n";
00267       e<<"**********************\n";
00268       this->getRange().write(e);
00269       e<<"**********************\n";
00270       e<<"*** input space:   ***\n";
00271       e<<"**********************\n";
00272       x.getSpace().write(e);
00273       e<<"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n";
00274       throw e;
00275     }
00276 
00277     if (y.getSpace() != this->getDomain()) {
00278       RVLException e;
00279       e<<"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n";
00280       e<<"Error: LinearOp::applyAdjOp - output not in domain\n";
00281       e<<"**********************\n";
00282       e<<"*** this operator: ***\n";
00283       e<<"**********************\n";
00284       this->write(e);
00285       e<<"**********************\n";
00286       e<<"*** domain space:  ***\n";
00287       e<<"**********************\n";
00288       this->getDomain().write(e);
00289       e<<"**********************\n";
00290       e<<"*** output space:  ***\n";
00291       e<<"**********************\n";
00292       y.getSpace().write(e);
00293       e<<"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n";
00294       throw e;
00295     }
00296 
00297     this->applyAdj(x,y);
00298       }
00299       catch (RVLException & e) {
00300     e<<"\ncalled from LinearOp::applyAdjOp\n";
00301     throw e;
00302       }
00303     }
00304 
00310     virtual void applyPlusOp(Vector<Scalar> const & x,
00311                  Vector<Scalar> & y) const {
00312       try {
00313     Vector<Scalar> z(this->getRange());
00314     this->applyOp(x,z);
00315     y.linComb(ScalarFieldTraits<Scalar>::One(),z);
00316       }
00317       catch (RVLException & e) {
00318     e<<"\ncalled from LinearOp::applyPlusOp (with lincomb) \n";
00319     throw e;
00320       }
00321     }
00322 
00328     virtual void applyPlusAdjOp(Vector<Scalar> const & x,
00329                 Vector<Scalar> & y) const {
00330       try {
00331     Vector<Scalar> z(this->getDomain());
00332     this->applyAdjOp(x,z);
00333     y.linComb(ScalarFieldTraits<Scalar>::One(),z);
00334       }
00335       catch (RVLException & e) {
00336     e<<"\ncalled from LinearOp::applyOp (with lincomb) \n";
00337     throw e;
00338       }
00339     }
00340 
00346     virtual void applyOp(Scalar alpha, Vector<Scalar> const & x,
00347              Scalar beta, Vector<Scalar> & y) const {
00348       try {
00349     Vector<Scalar> z(this->getRange());
00350     // refer to public rather than deprecated protected method
00351     this->applyOp(x,z);
00352     y.linComb(alpha,z,beta);
00353       }
00354       catch (RVLException & e) {
00355     e<<"\ncalled from LinearOp::applyOp (with lincomb) \n";
00356     throw e;
00357       }
00358     }
00359     
00365     virtual void applyAdjOp(Scalar alpha, Vector<Scalar> const & x,
00366                 Scalar beta, Vector<Scalar> & y) const {
00367       try {
00368     Vector<Scalar> z(this->getDomain());
00369     // refer to public rather than deprecated protected method
00370     this->applyAdjOp(x,z);
00371     y.linComb(alpha,z,beta);
00372       }
00373       catch (RVLException & e) {
00374     e<<"\ncalled from LinearOp::applyAdjOp (with lincomb) \n";
00375     throw e;
00376       }
00377     }
00378 
00379   };
00380 
00384   template<class Scalar>
00385   class LinearOpFO: public LinearOp<Scalar> {
00386 
00387   private: 
00388 
00389     FunctionObject & fwdfo;
00390     FunctionObject & adjfo;
00391 
00392     const Space<Scalar> & dom;
00393     const Space<Scalar> & rng;
00394 
00395     LinearOpFO();
00396 
00397   protected:
00398 
00399     LinearOp<Scalar> * clone() const {
00400       return new LinearOpFO<Scalar>(*this); 
00401     }
00402 
00403     void apply(const Vector<Scalar> & Input, 
00404            Vector<Scalar> & Output) const {
00405       try {
00406     Output.eval(fwdfo,Input);
00407       }
00408       catch (RVLException & e) {
00409     e<<"\ncalled from LinearOpFO::applyOp\n";
00410     throw e;
00411       }
00412     }
00413 
00414     void applyAdj(const Vector<Scalar> & Input,
00415           Vector<Scalar> & Output) const {
00416       try {
00417     Output.eval(adjfo,Input);
00418       }
00419       catch (RVLException & e) {
00420     e<<"\ncalled from LinearOpFO::applyAdjOp\n";
00421     throw e;
00422       }
00423     }
00424 
00425   public:
00426 
00427     LinearOpFO(const Space<Scalar> & _dom,
00428            const Space<Scalar> & _rng,
00429            FunctionObject & _fwdfo,
00430            FunctionObject & _adjfo)
00431       : LinearOp<Scalar>(), 
00432     fwdfo(_fwdfo), adjfo(_adjfo), dom(_dom), rng(_rng)  {}
00433     LinearOpFO( const LinearOpFO<Scalar> & l)
00434       : LinearOp<Scalar>(l), 
00435     fwdfo(l.fwdfo), adjfo(l.adjfo), dom(l.dom), rng(l.rng) {}
00436     virtual ~LinearOpFO() {}
00437 
00438     virtual const Space<Scalar> & getDomain() const { return dom; }
00439     virtual const Space<Scalar> & getRange() const { return rng; }
00440 
00441     virtual ostream & write(ostream & str) const {
00442       str<<"Linear Operator calling function objects for image methods\n";
00443       str<<"domain:\n";
00444       dom.write(str);
00445       str<<"range:\n";
00446       rng.write(str);
00447       str<<"Function object implementing forward map:\n";
00448       fwdfo.write(str);
00449       str<<"Function object implementing adjoint map:\n";
00450       adjfo.write(str);
00451       return str;
00452     }
00453   };
00454   
00458   template<class Scalar>
00459   class Invertible {
00460 
00461   protected:
00462 
00468     virtual void applyInv(const Vector<Scalar> & x, 
00469               Vector<Scalar> & y) const = 0;
00470 
00475     virtual void applyInvAdj(const Vector<Scalar> & x,
00476                  Vector<Scalar> & y) const = 0;
00477 
00478   public:
00479     Invertible() {}
00480     Invertible(const Invertible<Scalar> & Op) {}
00481     virtual ~Invertible() {}
00482   };
00483 
00486   template<class Scalar>
00487   class LinearOpWithInverse : public LinearOp<Scalar>, public Invertible<Scalar> {
00488   public:
00489     LinearOpWithInverse() {}
00490     ~LinearOpWithInverse() {}
00491 
00498     void applyInvOp(Vector<Scalar> const & x,
00499             Vector<Scalar> & y) const {
00500       try {
00501 
00502     if (x.getSpace() != this->getDomain()) {
00503       RVLException e;
00504       e<<"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n";
00505       e<<"Error: Invertible::applyInvOp - input not in range\n";
00506       e<<"**********************\n";
00507       e<<"*** this operator: ***\n";
00508       e<<"**********************\n";
00509       this->write(e);
00510       e<<"**********************\n";
00511       e<<"*** range space:   ***\n";
00512       e<<"**********************\n";
00513       this->getRange().write(e);
00514       e<<"**********************\n";
00515       e<<"*** input space:   ***\n";
00516       e<<"**********************\n";
00517       x.getSpace().write(e);
00518       e<<"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n";
00519       throw e;
00520     }
00521 
00522     if (y.getSpace() != this->getRange()) {
00523       RVLException e;
00524       e<<"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n";
00525       e<<"Error: Invertible::applyInvOp - output not in domain\n";
00526       e<<"**********************\n";
00527       e<<"*** this operator: ***\n";
00528       e<<"**********************\n";
00529       this->write(e);
00530       e<<"**********************\n";
00531       e<<"*** domain space:  ***\n";
00532       e<<"**********************\n";
00533       this->getDomain().write(e);
00534       e<<"**********************\n";
00535       e<<"*** output space:  ***\n";
00536       e<<"**********************\n";
00537       y.getSpace().write(e);
00538       e<<"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n";
00539       throw e;
00540     }
00541 
00542     this->applyInv(x,y);
00543 
00544       }
00545 
00546       catch (RVLException & e) {
00547     e<<"\ncalled from LinearOp::applyOp\n";
00548     throw e;
00549       }
00550     }
00551 
00558     void applyInvAdjOp(Vector<Scalar> const & x,
00559                Vector<Scalar> & y) const {
00560 
00561       try {
00562 
00563     if (x.getSpace() != this->getDomain()) {
00564       RVLException e;
00565       e<<"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n";
00566       e<<"Error: Invertible::applyInvAdjOp - input not in domain\n";
00567       e<<"**********************\n";
00568       e<<"*** this operator: ***\n";
00569       e<<"**********************\n";
00570       this->write(e);
00571       e<<"**********************\n";
00572       e<<"*** domain space:  ***\n";
00573       e<<"**********************\n";
00574       this->getDomain().write(e);
00575       e<<"**********************\n";
00576       e<<"*** input space:   ***\n";
00577       e<<"**********************\n";
00578       x.getSpace().write(e);
00579       e<<"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n";
00580       throw e;
00581     }
00582 
00583     if (y.getSpace() != this->getRange()) {
00584       RVLException e;
00585       e<<"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n";
00586       e<<"Error: Invertible::applyInvAdjOp - output not in range\n";
00587       e<<"**********************\n";
00588       e<<"*** this operator: ***\n";
00589       e<<"**********************\n";
00590       this->write(e);
00591       e<<"**********************\n";
00592       e<<"*** range space:   ***\n";
00593       e<<"**********************\n";
00594       this->getRange().write(e);
00595       e<<"**********************\n";
00596       e<<"*** output space:  ***\n";
00597       e<<"**********************\n";
00598       y.getSpace().write(e);
00599       e<<"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n";
00600       throw e;
00601     }
00602 
00603     this->applyInvAdj(x,y);
00604       }
00605       catch (RVLException & e) {
00606     e<<"\ncalled from LinearOp::applyAdjOp\n";
00607     throw e;
00608       }
00609     }
00610 
00611   };
00612 
00619   template <class Scalar>
00620   class AdjLinearOp: public LinearOp<Scalar> {
00621   
00622   private:
00623   
00624     const LinearOp<Scalar> & op;
00625   
00626     // default constructor--disabled
00627     AdjLinearOp();
00628     // copy constructor--private
00629     AdjLinearOp(const AdjLinearOp<Scalar> & a) 
00630       : op(a.op) {}
00631   
00632   protected:
00633 
00634     virtual LinearOp<Scalar> * clone() const {
00635       return new AdjLinearOp<Scalar>(*this);
00636     }
00637 
00638     void apply(const Vector<Scalar> & x, 
00639          Vector<Scalar> & y) const {
00640       try {
00641     op.applyAdjOp(x,y);
00642       }
00643       catch (RVLException & e) {
00644     e<<"\ncalled from AdjLinearOp::apply\n";
00645     throw e;
00646       }
00647     }
00648 
00649     void applyAdj(const Vector<Scalar> & x,
00650           Vector<Scalar> & y) const {
00651       try {
00652     op.applyOp(x,y);
00653       }
00654       catch (RVLException & e) {
00655     e<<"\ncalled from AdjLinearOp::applyAdj\n";
00656     throw e;
00657       }
00658     }
00659   
00660   public:
00661   
00662     AdjLinearOp(const LinearOp<Scalar> & _op)
00663       : op(_op) {}
00664 
00665     ~AdjLinearOp() {}
00666   
00667     const Space<Scalar> & getDomain() const { return op.getRange(); } 
00668     const Space<Scalar> & getRange() const { return op.getDomain(); }
00669 
00670     ostream & write(ostream & str) const {
00671       str<<"Adjoint Operator - build on\n";
00672       op.write(str);
00673       return str;
00674     }
00675   };
00676 
00684   template<class Scalar>
00685   class NormalLinearOp: public LinearOp<Scalar> {
00686   
00687   private:
00688   
00689     const LinearOp<Scalar> & op;
00690   
00691     NormalLinearOp();
00692     NormalLinearOp(const NormalLinearOp<Scalar> & n)
00693       : op(n.op) {}
00694   
00695   protected:
00696 
00697     LinearOp<Scalar> * clone() const {
00698       return new NormalLinearOp<Scalar>(*this);
00699     }
00700 
00701     void apply(const Vector<Scalar> & x, 
00702            Vector<Scalar> & y) const {
00703       try {
00704     Vector<Scalar> z(op.getRange());
00705     op.applyOp(x,z);
00706     op.applyAdjOp(z,y);
00707       }
00708       catch (RVLException & e) {
00709     e<<"\ncalled from NormalLinearOp::apply\n";
00710     throw e;
00711       }
00712     } 
00713 
00714     void applyAdj(const Vector<Scalar> & x,
00715           Vector<Scalar> & y) const {
00716       try {
00717     this->applyOp(x,y);
00718       }
00719       catch (RVLException & e) {
00720     e<<"\ncalled from NormalLinearOp::applyAdj\n";
00721     throw e;
00722       }
00723     } 
00724     
00725   public:
00726   
00727     // constructs the object from a LinearOp
00728     NormalLinearOp(const LinearOp<Scalar> & _op)
00729       : op(_op) {}
00730   
00731     // destructor.
00732     ~NormalLinearOp() {}
00733   
00735     const Space<Scalar> & getDomain() const { return op.getDomain(); }
00736     const Space<Scalar> & getRange() const { return op.getDomain(); }
00737 
00738     // report
00739     ostream & write(ostream & str) const {
00740       str<<"Normal Operator - build on\n";
00741       op.write(str);
00742       return str;
00743     }
00744   };
00745 
00753   template<class Scalar>
00754   class ScaleOpFwd: public LinearOp<Scalar> {
00755   
00756   private:
00757   
00758     const Space<Scalar> & sp;
00759     Scalar mu;
00760   
00761     ScaleOpFwd();
00762 
00763   protected:
00764 
00765     virtual LinearOp<Scalar> * clone() const {
00766       return new ScaleOpFwd<Scalar>(*this);
00767     }
00768 
00769 
00770     void apply(const Vector<Scalar> & x, 
00771            Vector<Scalar> & y) const {
00772       try {
00773     if (abs(mu-ScalarFieldTraits<Scalar>::One())<=numeric_limits<Scalar>::epsilon())
00774       y.copy(x);
00775     else if (abs(mu)<=numeric_limits<Scalar>::epsilon())
00776       y.zero();
00777     else
00778       y.scale(mu,x);
00779       }
00780       catch (RVLException & e) {
00781     e<<"\ncalled from ScaleOpFwd::apply\n";
00782     throw e;
00783       }
00784     }
00785 
00786     void applyAdj(const Vector<Scalar> & x,
00787           Vector<Scalar> & y) const {
00788 
00789       try {
00790     this->applyOp(x,y);
00791       }
00792       catch (RVLException & e) {
00793     e<<"\ncalled from ScaleOpFwd::applyAdj\n";
00794     throw e;
00795       }
00796     }  
00797 
00798   public:
00799   
00800     ScaleOpFwd(const Space<Scalar> & _sp, Scalar _mu)
00801       : sp(_sp), mu(_mu) {}
00802 
00803     ScaleOpFwd(const ScaleOpFwd<Scalar> & s)
00804       : sp(s.sp), mu(s.mu) {}
00805 
00806     ~ScaleOpFwd() {}
00807     const Space<Scalar> & getDomain() const { return sp; } 
00808     const Space<Scalar> & getRange() const { return sp; }
00809     Scalar getScale() const { return mu; }
00810     void setScale(Scalar _mu) { mu=_mu; }
00811 
00812     ostream & write(ostream & str) const {
00813       str<<"ScaleOpFwd - build on\n";
00814       sp.write(str);
00815       str<<"and scale factor\n";
00816       str<<mu<<endl;
00817       return str;
00818     }
00819   };
00820 
00826   template<class Scalar>
00827   class ScaleOpInv: public LinearOp<Scalar> {
00828   
00829   private:
00830   
00831     const Space<Scalar> & sp;
00832     Scalar mu;
00833   
00834     ScaleOpInv();
00835     ScaleOpInv(const ScaleOpInv<Scalar> & s)
00836       : sp(s.sp), mu(s.mu) {}
00837   
00838   protected:
00839 
00840     virtual LinearOp<Scalar> * clone() const {
00841       return new ScaleOpInv<Scalar>(*this);
00842     }
00843 
00844     void apply(const Vector<Scalar> & x, 
00845            Vector<Scalar> & y) const {
00846       try {
00847     if (fabs(mu-ScalarFieldTraits<Scalar>::One())<=numeric_limits<Scalar>::epsilon())
00848       y.copy(x);
00849     else if (fabs(mu)<=numeric_limits<Scalar>::epsilon())
00850       y.zero();
00851     else
00852       y.scale(mu,x);
00853       }
00854       catch (RVLException & e) {
00855     e<<"\ncalled from ScaleOpInv::apply\n";
00856     throw e;
00857       }
00858     }
00859 
00860     void applyAdj(const Vector<Scalar> & x,
00861           Vector<Scalar> & y) const {
00862       try {
00863     apply(x,y);
00864       }
00865       catch (RVLException & e) {
00866     e<<"\ncalled from ScaleOpInv::applyAdj\n";
00867     throw e;
00868       }
00869     }
00870 
00871   public:
00872   
00873     ScaleOpInv(const LinearOp<Scalar> & op,Scalar _mu)
00874       : sp(op.getDomain()) {
00875       Scalar one = ScalarFieldTraits<Scalar>::One();
00876       if (ProtectedDivision(one,_mu,mu)) {
00877     RVLException e;
00878     e<<"Error: ScaleOpInv constructor\n";
00879     e<<"reciprocal of mu = "<<_mu<<" caused zerodivide\n";
00880     throw e;
00881       }
00882     }
00883   
00884     ScaleOpInv(const ScaleOpFwd<Scalar> & op)
00885       : sp(op.getDomain()) {
00886       Scalar one = ScalarFieldTraits<Scalar>::One();
00887       if (ProtectedDivision(one,op.getScale(),mu)) {
00888     RVLException e;
00889     e<<"Error: ScaleOpInv constructor\n";
00890     e<<"based on ScaleOpFwd:\n";
00891     op.write(e);
00892     e<<"reciprocal of mu = "<<op.getScale()<<" caused zerodivide\n";
00893     throw e;
00894       }
00895     }
00896   
00897     ~ScaleOpInv() {}
00898   
00899     const Space<Scalar> & getDomain() const { return sp; } 
00900     const Space<Scalar> & getRange() const { return sp; }
00901   
00902     Scalar getScale() const { return mu; }
00903     void setScale(Scalar _mu) { mu=_mu; }
00904 
00905     ostream & write(ostream & str) const {
00906       str<<"Scale Operator - build on\n";
00907       sp.write(str);
00908       str<<"and scale factor\n";
00909       str<<mu<<endl;
00910       return str;
00911     }
00912   };
00913 
00926   template<class Scalar>
00927   class LinCombLinearOp: public LinearOp<Scalar> {
00928   
00929   private:
00930 
00931     Scalar w1, w2;
00932     LinearOp<Scalar> const & op1;
00933     LinearOp<Scalar> const & op2;
00934   
00935     LinCombLinearOp();
00936 
00937   protected:
00938 
00939     virtual LinearOp<Scalar> * clone() const {
00940       return new LinCombLinearOp<Scalar>(*this);
00941     }
00942       
00943     void apply(const Vector<Scalar> & x, 
00944          Vector<Scalar> & y) const {
00945       try {
00946     Vector<Scalar> z(op1.getRange());
00947     op1.applyOp(x,z);
00948     op2.applyOp(x,y);
00949     y.linComb(w1,z,w2);
00950       }
00951       catch (RVLException & e) {
00952     e<<"\ncalled from LinCombLinearOp::apply\n";
00953     throw e;
00954       }
00955     }
00956 
00957     void applyAdj(const Vector<Scalar> & x, 
00958             Vector<Scalar> & y) const {
00959       try {
00960     Vector<Scalar> z(op1.getDomain());
00961     op1.applyAdjOp(x,z);
00962     op2.applyAdjOp(x,y);
00963     y.linComb(w1,z,w2);
00964       }
00965       catch (RVLException & e) {
00966     e<<"\ncalled from LinCombLinearOp::applyAdj\n";
00967     throw e;
00968       }
00969     }
00970   
00971   public:
00972   
00973     LinCombLinearOp(Scalar _w1, LinearOp<Scalar> const & _op1,
00974             Scalar _w2, LinearOp<Scalar> const & _op2)
00975       : w1(_w1), w2(_w2), op1(_op1), op2(_op2) {
00976       try {
00977     if ((op2.getDomain() != op1.getDomain()) ||
00978         (op2.getRange() != op1.getRange())) {
00979       RVLException e;
00980       e<<"Error: LinCombLinearOp constructor\n";
00981       e<<"incompatible domains or ranges\n";
00982       e<<"\n";
00983       e<<"**** operator 1:\n";
00984       op1.write(e);
00985       e<<"\n";
00986       e<<"**** operator 2:\n";
00987       op2.write(e);
00988       e<<"\n";
00989       throw e;
00990     }
00991       }
00992       catch (RVLException & e) {
00993     e<<"\ncalled from LinCombLinearOp::LinCombLinearOp\n";
00994     throw e;
00995       }
00996     }
00997 
00998     LinCombLinearOp(LinCombLinearOp const & op) 
00999       : w1(op.w1), w2(op.w2), op1(op.op1), op2(op.op2) {}
01000 
01001     ~LinCombLinearOp() {}
01002 
01003     const Space<Scalar> & getDomain() const {
01004       return op1.getDomain();
01005     }
01006 
01007     const Space<Scalar> & getRange() const {
01008       return op1.getRange();
01009     }
01010 
01011     ostream & write(ostream & str) const {
01012       str<<"LinCombLinearOp - linear combinations\n";
01013       str<<"\n";
01014       str<<"**** operator 1:\n";
01015       op1.write(str);
01016       str<<"     weight 1 = "<<w1<<"\n";
01017       str<<"\nfollowed by\n";
01018       str<<"**** operator 2:\n";
01019       op2.write(str);
01020       str<<"     weight 2 = "<<w2<<"\n";
01021       str<<"\n";
01022       return str;
01023     }
01024   };
01025 
01026 
01033   template<typename Scalar>
01034   class SymmetricBilinearOp: public Writeable {
01035 
01036   protected:
01037 
01038     virtual void apply(const Vector<Scalar> & x0, 
01039                const Vector<Scalar> & x1,
01040                Vector<Scalar> & y) const = 0;
01041 
01042     virtual void applyAdj(const Vector<Scalar> & x0, 
01043               const Vector<Scalar> & y,
01044               Vector<Scalar> & x1) const = 0;
01045     
01046     virtual SymmetricBilinearOp<Scalar> * clone() const = 0;
01047 
01048   public:
01049 
01050 #ifndef RVL_OPERATOR_NEW_ENABLED
01051     void * operator new(size_t size) { 
01052       void * ptr;
01053       ptr = (void *) ::new unsigned char[size]; 
01054       return ptr;
01055     }
01056 #endif
01057 
01058     virtual ~SymmetricBilinearOp() {}
01059 
01060     virtual Space<Scalar> const & getDomain() const = 0; 
01061     virtual Space<Scalar> const & getRange() const = 0; 
01062 
01069     void applyOp(Vector<Scalar> const & x0,
01070          Vector<Scalar> const & x1,
01071          Vector<Scalar> & y) const {
01072       try {
01073 
01074     if (x0.getSpace() != this->getDomain()) {
01075       RVLException e;
01076       e<<"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n";
01077       e<<"Error: SymmetricBilinearOp::applyOp - input 0 not in domain\n";
01078       e<<"**********************\n";
01079       e<<"*** this operator: ***\n";
01080       e<<"**********************\n";
01081       this->write(e);
01082       e<<"**********************\n";
01083       e<<"*** domain space:  ***\n";
01084       e<<"**********************\n";
01085       this->getDomain().write(e);
01086       e<<"**********************\n";
01087       e<<"*** input space:   ***\n";
01088       e<<"**********************\n";
01089       x0.getSpace().write(e);
01090       e<<"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n";
01091       throw e;
01092     }
01093 
01094     if (x1.getSpace() != this->getDomain()) {
01095       RVLException e;
01096       e<<"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n";
01097       e<<"Error: SymmetricBilinearOp::applyOp - input 1 not in domain\n";
01098       e<<"**********************\n";
01099       e<<"*** this operator: ***\n";
01100       e<<"**********************\n";
01101       this->write(e);
01102       e<<"**********************\n";
01103       e<<"*** domain space:  ***\n";
01104       e<<"**********************\n";
01105       this->getDomain().write(e);
01106       e<<"**********************\n";
01107       e<<"*** input space:   ***\n";
01108       e<<"**********************\n";
01109       x1.getSpace().write(e);
01110       e<<"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n";
01111       throw e;
01112     }
01113 
01114     if (y.getSpace() != this->getRange()) {
01115       RVLException e;
01116       e<<"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n";
01117       e<<"Error: SymmetricBilinearOp::applyOp - output not in range\n";
01118       e<<"**********************\n";
01119       e<<"*** this operator: ***\n";
01120       e<<"**********************\n";
01121       this->write(e);
01122       e<<"**********************\n";
01123       e<<"*** range space:   ***\n";
01124       e<<"**********************\n";
01125       this->getRange().write(e);
01126       e<<"**********************\n";
01127       e<<"*** output space:  ***\n";
01128       e<<"**********************\n";
01129       y.getSpace().write(e);
01130       e<<"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n";
01131       throw e;
01132     }
01133 
01134     this->apply(x0,x1,y);
01135 
01136       }
01137 
01138       catch (RVLException & e) {
01139     e<<"\ncalled from SymmetricBilinearOp::applyOp\n";
01140     throw e;
01141       }
01142     }
01143     
01156     void applyAdjOp(Vector<Scalar> const & x0,
01157             Vector<Scalar> const & y,
01158             Vector<Scalar> & x1) const {
01159       try {
01160 
01161     if (x0.getSpace() != this->getDomain()) {
01162       RVLException e;
01163       e<<"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n";
01164       e<<"Error: SymmetricBilinearOp::applyOp - input 0 not in domain\n";
01165       e<<"**********************\n";
01166       e<<"*** this operator: ***\n";
01167       e<<"**********************\n";
01168       this->write(e);
01169       e<<"**********************\n";
01170       e<<"*** domain space:  ***\n";
01171       e<<"**********************\n";
01172       this->getDomain().write(e);
01173       e<<"**********************\n";
01174       e<<"*** input space:   ***\n";
01175       e<<"**********************\n";
01176       x0.getSpace().write(e);
01177       e<<"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n";
01178       throw e;
01179     }
01180 
01181     if (x1.getSpace() != this->getDomain()) {
01182       RVLException e;
01183       e<<"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n";
01184       e<<"Error: SymmetricBilinearOp::applyOp - output not in domain \n";
01185       e<<"**********************\n";
01186       e<<"*** this operator: ***\n";
01187       e<<"**********************\n";
01188       this->write(e);
01189       e<<"**********************\n";
01190       e<<"*** domain space:  ***\n";
01191       e<<"**********************\n";
01192       this->getDomain().write(e);
01193       e<<"**********************\n";
01194       e<<"*** output space:  ***\n";
01195       e<<"**********************\n";
01196       x1.getSpace().write(e);
01197       e<<"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n";
01198       throw e;
01199     }
01200 
01201     if (y.getSpace() != this->getRange()) {
01202       RVLException e;
01203       e<<"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n";
01204       e<<"Error: LinearOp::applyOp - intput 1 not in range\n";
01205       e<<"**********************\n";
01206       e<<"*** this operator: ***\n";
01207       e<<"**********************\n";
01208       this->write(e);
01209       e<<"**********************\n";
01210       e<<"*** range space:   ***\n";
01211       e<<"**********************\n";
01212       this->getRange().write(e);
01213       e<<"**********************\n";
01214       e<<"*** input 1 space: ***\n";
01215       e<<"**********************\n";
01216       y.getSpace().write(e);
01217       e<<"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n";
01218       throw e;
01219     }
01220 
01221     this->applyAdj(x0,y,x1);
01222 
01223       }
01224 
01225       catch (RVLException & e) {
01226     e<<"\ncalled from SymmetricBilinearOp::applyAdjOp\n";
01227     throw e;
01228       }
01229     }
01230   };
01231 
01233   template<class Scalar>
01234   class LinearBilinearOp: public LinearOp<Scalar> {
01235 
01236   private:
01237     SymmetricBilinearOp<Scalar> const & blop;
01238     Vector<Scalar> const & x0;
01239 
01240 #ifndef RVL_OPERATOR_NEW_ENABLED
01241     void * operator new(size_t size) { 
01242       void * ptr;
01243       ptr = (void *) ::new unsigned char[size]; 
01244       return ptr;
01245     }
01246 #endif
01247 
01248   protected:
01249 
01250     void apply(Vector<Scalar> const & x1,
01251            Vector<Scalar> & y) const {
01252       try {
01253     blop.applyOp(x0,x1,y);
01254       }
01255       catch (RVLException & e) {
01256     e<<"\ncalled from LinearBilinearOp::apply\n";
01257     throw e;
01258       }
01259     }
01260 
01261     void applyAdj(Vector<Scalar> const & y,
01262           Vector<Scalar> & x1) const {
01263       try {
01264     blop.applyAdjOp(x0,y,x1);
01265       }
01266       catch (RVLException & e) {
01267     e<<"\ncalled from LinearBilinearOp::applyAdj\n";
01268     throw e;
01269       }
01270     }
01271 
01272     Operator<Scalar> * clone() const {
01273       return new LinearBilinearOp<Scalar>(*this);
01274     }
01275 
01276   public:
01277 
01278     LinearBilinearOp(SymmetricBilinearOp<Scalar> const & _blop,
01279              Vector<Scalar> const & _x0) 
01280       : blop(_blop), x0(_x0) {}
01281     
01282     LinearBilinearOp(LinearBilinearOp<Scalar> const & lbl) 
01283       : blop(lbl.blop), x0(lbl.x0) {}
01284 
01285     Space<Scalar> const & getDomain() const { return blop.getDomain(); }
01286     Space<Scalar> const & getRange() const { return blop.getRange(); }
01287 
01288     ostream & write(ostream & str) const {
01289       str<<"Linear Operator wrapper around Bilinear Operator\n";
01290       str<<"  by fixing first argument\n";
01291       str<<"Bilinear Operator:\n";
01292       blop.write(str);
01293       str<<"First argument (vector):\n";
01294       x0.write(str);
01295       return str;
01296     }
01297   };
01298 }
01299 
01300 #endif
01301 
01302 
01303 
01304 
01305 
01306 
01307 

Generated on 5 Jan 2017 for RVL by  doxygen 1.4.7