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_RNOP
00034 #define __RVL_RNOP
00035
00036 #include "op.hh"
00037 #include "rnmat.hh"
00038
00051 namespace RVL {
00052
00054 template<typename T, int f(int, int, T const *, T *)>
00055 class CFunction: public BinaryLocalFunctionObject<T> {
00056 public:
00057 void operator()(LocalDataContainer<T> & y,
00058 LocalDataContainer<T> const & x) {
00059 int err=0;
00060 if (err=f(y.getSize(), x.getSize(), x.getData(), y.getData())) {
00061 RVLException e;
00062 e<<"Error: CFunction::operator() - err="<<err<<"\n";
00063 throw e;
00064 }
00065 }
00066 string getName() const { string tmp = "CFunction"; return tmp; }
00067 };
00068
00081 template<typename T, int df(int, int, T const *, T *)>
00082 class CJacobian: public UnaryLocalFunctionObjectConstEval<T> {
00083 private:
00084 GenMat<T> & a;
00085 CJacobian();
00086 CJacobian(CJacobian<T, df> const &);
00087 public:
00088 CJacobian(GenMat<T> & _a): a(_a) {}
00089 void operator()(LocalDataContainer<T> const & x) {
00090 int err=0;
00091 if (err=df(a.getNRows(), a.getNCols(), x.getData(), a.getData())) {
00092 RVLException e;
00093 e<<"Error: CJacobian::operator() - err="<<err<<"\n";
00094 throw e;
00095 }
00096 }
00097 string getName() const { string tmp = "CJacobian"; return tmp; }
00098 };
00099
00101 template<typename T>
00102 class OpWithGenMatDeriv: public Operator<T> {
00103 public:
00104 virtual GenMat<T> const & getGenMat() const = 0;
00105 };
00106
00111 template<typename T, int f(int, int, T const *, T *), int df(int, int, T const *, T *)>
00112 class GenOp: public OpWithGenMatDeriv<T> {
00113
00114 private:
00115
00116
00117 RnSpace<T> const & dom;
00118 RnSpace<T> const & rng;
00119
00120
00121
00122 mutable GenMat<T> deriv;
00123 mutable bool init;
00124
00125
00126
00127
00128 void buildJacobian(Vector<T> const & x) const {
00129 try {
00130 if (!init) {
00131 CJacobian<T, df> j(deriv);
00132 x.eval(j);
00133 init=true;
00134 }
00135 }
00136 catch (RVLException & e) {
00137 e<<"\ncalled from GenOp::buildJacobian\n";
00138 throw e;
00139 }
00140 }
00141
00142 GenOp();
00143
00144 protected:
00145
00147 virtual void apply(const Vector<T> & x,
00148 Vector<T> & y) const {
00149 try {
00150 CFunction<T, f> ff;
00151 y.eval(ff,x);
00152
00153 buildJacobian(x);
00154 }
00155 catch (RVLException & e) {
00156 e<<"\ncalled from GenOp::apply\n";
00157 throw e;
00158 }
00159 }
00160
00162 virtual void applyDeriv(const Vector<T> & x,
00163 const Vector<T> & dx,
00164 Vector<T> & dy) const {
00165 try {
00166 buildJacobian(x);
00167 deriv.applyOp(dx,dy);
00168 }
00169 catch (RVLException & e) {
00170 e<<"\ncalled from GenOp::applyDeriv\n";
00171 throw e;
00172 }
00173 }
00174
00176 virtual void applyAdjDeriv(const Vector<T> & x,
00177 const Vector<T> & dy,
00178 Vector<T> & dx) const {
00179 try {
00180 buildJacobian(x);
00181 deriv.applyAdjOp(dy,dx);
00182 }
00183 catch (RVLException & e) {
00184 e<<"\ncalled from GenOp::applyAdjDeriv\n";
00185 throw e;
00186 }
00187 }
00188
00189 virtual Operator<T> * clone() const {
00190 return new GenOp<T, f, df>(dom,rng);
00191 }
00192
00193 public:
00194
00196 GenOp(RnSpace<T> const & _dom, RnSpace<T> const & _rng)
00197 : dom(_dom), rng(_rng), deriv(dom,rng), init(false) {}
00202 GenOp(GenOp<T, f, df> const & a)
00203 : dom(a.dom), rng(a.rng), deriv(dom,rng), init(false) {}
00204
00205 Space<T> const & getDomain() const { return dom; }
00206 Space<T> const & getRange() const { return rng; }
00207
00210 GenMat<T> const & getGenMat() const {
00211 if (init) return deriv;
00212 RVLException e;
00213 e<<"Error: GenOp::getGenMat\n";
00214 e<<"Jacobian matrix not initialized - must evaluate somewhere first!\n";
00215 throw e;
00216 }
00217
00218 ostream & write(ostream & str) const {
00219 str<<"GenOp instance\n";
00220 str<<"domain:\n";
00221 dom.write(str);
00222 str<<"range:\n";
00223 rng.write(str);
00224 return str;
00225 }
00226 };
00227
00228 }
00229
00230 #endif