00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033 #ifndef __RVL_LINOP_BASE
00034 #define __RVL_LINOP_BASE
00035
00036 #include "space.hh"
00037 #include "write.hh"
00038
00039 namespace RVL {
00040
00041
00042
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
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
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
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
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
00627 AdjLinearOp();
00628
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
00728 NormalLinearOp(const LinearOp<Scalar> & _op)
00729 : op(_op) {}
00730
00731
00732 ~NormalLinearOp() {}
00733
00735 const Space<Scalar> & getDomain() const { return op.getDomain(); }
00736 const Space<Scalar> & getRange() const { return op.getDomain(); }
00737
00738
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