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 #ifndef SUNDANCE_UNARYFUNCTOR_H
00032 #define SUNDANCE_UNARYFUNCTOR_H
00033
00034 #include "SundanceDefs.hpp"
00035 #include "PlayaExceptions.hpp"
00036 #include "SundanceFunctorDomain.hpp"
00037 #include "Teuchos_ScalarTraits.hpp"
00038 #include "Teuchos_RefCountPtr.hpp"
00039
00040 #ifndef DOXYGEN_DEVELOPER_ONLY
00041
00042 namespace Sundance
00043 {
00044 using namespace Teuchos;
00045
00046
00047
00048
00049
00050
00051
00052 class UnaryFunctor
00053 {
00054 public:
00055
00056 UnaryFunctor(const std::string& name,
00057 const RCP<FunctorDomain>& domain
00058 = rcp(new UnboundedDomain()))
00059 : name_(name), h_(fdStep()), domain_(domain) {;}
00060
00061
00062 virtual ~UnaryFunctor(){;}
00063
00064
00065 const std::string& name() const {return name_;}
00066
00067
00068 virtual void eval0(const double* const x,
00069 int nx,
00070 double* f) const = 0 ;
00071
00072
00073 virtual void eval1(const double* const x,
00074 int nx,
00075 double* f,
00076 double* df_dx) const ;
00077
00078
00079 virtual void eval2(const double* const x,
00080 int nx,
00081 double* f,
00082 double* df_dx,
00083 double* d2f_dxx) const ;
00084
00085
00086 virtual void eval3(const double* const x,
00087 int nx,
00088 double* f,
00089 double* df_dx,
00090 double* d2f_dxx,
00091 double* d3f_dxxx) const ;
00092
00093
00094
00095
00096 void evalFDDerivs1(const double* const x,
00097 int nx,
00098 double* f,
00099 double* df_dx) const ;
00100
00101 void evalFDDerivs2(const double* const x,
00102 int nx,
00103 double* f,
00104 double* df_dx,
00105 double* d2f_dxx) const ;
00106
00107 void evalFDDerivs3(const double* const x,
00108 int nx,
00109 double* f,
00110 double* df_dx,
00111 double* d2f_dxx,
00112 double* d3f_dxxx) const ;
00113
00114
00115 bool testDerivs(const double& x, const double& tol) const ;
00116
00117
00118 bool testInvalidValue(const double& xBad) const ;
00119
00120
00121 bool test(int nx, const double& tol) const ;
00122
00123
00124 static bool& checkResults() {static bool rtn = false; return rtn;}
00125
00126 static double& fdStep() {static double rtn = 1.0e-3; return rtn;}
00127
00128 const RCP<FunctorDomain>& domain() const
00129 {return domain_;}
00130 private:
00131 std::string name_;
00132
00133 double h_;
00134
00135 RCP<FunctorDomain> domain_;
00136 };
00137 }
00138
00139
00140 #define SUNDANCE_UNARY_FUNCTOR(opName, functorName, description, domain, \
00141 funcDefinition, firstDerivDefinition, \
00142 secondDerivDefinition) \
00143 class functorName : public Sundance::UnaryFunctor \
00144 { \
00145 public: \
00146 \
00147 functorName() : Sundance::UnaryFunctor(#opName, rcp(new domain)) {;} \
00148 \
00149 virtual ~functorName(){;} \
00150 \
00151 void eval0(const double* const x, int nx, double* f) const ; \
00152 \
00153 void eval1(const double* const x, \
00154 int nx, \
00155 double* f, \
00156 double* df) const ; \
00157 \
00158 void eval2(const double* const x, \
00159 int nx, \
00160 double* f, \
00161 double* df, \
00162 double* d2f_dxx) const ; \
00163 }; \
00164 inline void functorName::eval0(const double* const x, int nx, double* f) const \
00165 { \
00166 if (checkResults()) \
00167 { \
00168 for (int i=0; i<nx; i++) \
00169 { \
00170 f[i] = funcDefinition; \
00171 TEUCHOS_TEST_FOR_EXCEPTION(Teuchos::ScalarTraits<double>::isnaninf(f[i]), std::runtime_error, "Non-normal floating point result detected in evaluation of unary functor " << name() << " at argument " << x[i]); \
00172 } \
00173 } \
00174 else \
00175 { \
00176 for (int i=0; i<nx; i++) f[i] = funcDefinition; \
00177 } \
00178 } \
00179 inline void functorName::eval1(const double* const x, \
00180 int nx, \
00181 double* f, \
00182 double* df) const \
00183 { \
00184 if (checkResults()) \
00185 { \
00186 for (int i=0; i<nx; i++) \
00187 { \
00188 f[i] = funcDefinition; \
00189 df[i] = firstDerivDefinition; \
00190 TEUCHOS_TEST_FOR_EXCEPTION(Teuchos::ScalarTraits<double>::isnaninf(f[i])||Teuchos::ScalarTraits<double>::isnaninf(df[i]), \
00191 std::runtime_error, \
00192 "Non-normal floating point result detected in " \
00193 "evaluation of unary functor " \
00194 << name() << " at argument " << x[i]); \
00195 } \
00196 } \
00197 else \
00198 { \
00199 for (int i=0; i<nx; i++) \
00200 { \
00201 f[i] = funcDefinition; \
00202 df[i] = firstDerivDefinition; \
00203 } \
00204 } \
00205 } \
00206 inline void functorName::eval2(const double* const x, \
00207 int nx, \
00208 double* f, \
00209 double* df, \
00210 double* d2f) const \
00211 { \
00212 if (checkResults()) \
00213 { \
00214 for (int i=0; i<nx; i++) \
00215 { \
00216 f[i] = funcDefinition; \
00217 df[i] = firstDerivDefinition; \
00218 d2f[i] = secondDerivDefinition; \
00219 TEUCHOS_TEST_FOR_EXCEPTION(Teuchos::ScalarTraits<double>::isnaninf(f[i])||Teuchos::ScalarTraits<double>::isnaninf(df[i])||Teuchos::ScalarTraits<double>::isnaninf(d2f[i]), \
00220 std::runtime_error, \
00221 "Non-normal floating point result detected in " \
00222 "evaluation of unary functor " \
00223 << name() << " at argument " << x[i] ); \
00224 } \
00225 } \
00226 else \
00227 { \
00228 for (int i=0; i<nx; i++) \
00229 { \
00230 f[i] = funcDefinition; \
00231 df[i] = firstDerivDefinition; \
00232 d2f[i] = secondDerivDefinition; \
00233 } \
00234 } \
00235 }
00236
00237
00238
00239
00240 #define SUNDANCE_UNARY_FUNCTOR3(opName, functorName, description, domain, \
00241 funcDefinition, firstDerivDefinition, \
00242 secondDerivDefinition, thirdDerivDefinition) \
00243 class functorName : public Sundance::UnaryFunctor \
00244 { \
00245 public: \
00246 \
00247 functorName() : Sundance::UnaryFunctor(#opName, rcp(new domain)) {;} \
00248 \
00249 virtual ~functorName(){;} \
00250 \
00251 void eval0(const double* const x, int nx, double* f) const ; \
00252 \
00253 void eval1(const double* const x, \
00254 int nx, \
00255 double* f, \
00256 double* df) const ; \
00257 \
00258 void eval2(const double* const x, \
00259 int nx, \
00260 double* f, \
00261 double* df, \
00262 double* d2f_dxx) const ; \
00263 \
00264 void eval3(const double* const x, \
00265 int nx, \
00266 double* f, \
00267 double* df, \
00268 double* d2f_dxx, \
00269 double* d3f_dxxx) const ; \
00270 }; \
00271 inline void functorName::eval0(const double* const x, int nx, double* f) const \
00272 { \
00273 if (checkResults()) \
00274 { \
00275 for (int i=0; i<nx; i++) \
00276 { \
00277 f[i] = funcDefinition; \
00278 TEUCHOS_TEST_FOR_EXCEPTION(Teuchos::ScalarTraits<double>::isnaninf(f[i]), std::runtime_error, "Non-normal floating point result detected in evaluation of unary functor " << name() << " at argument " << x[i]); \
00279 } \
00280 } \
00281 else \
00282 { \
00283 for (int i=0; i<nx; i++) f[i] = funcDefinition; \
00284 } \
00285 } \
00286 inline void functorName::eval1(const double* const x, \
00287 int nx, \
00288 double* f, \
00289 double* df) const \
00290 { \
00291 if (checkResults()) \
00292 { \
00293 for (int i=0; i<nx; i++) \
00294 { \
00295 f[i] = funcDefinition; \
00296 df[i] = firstDerivDefinition; \
00297 TEUCHOS_TEST_FOR_EXCEPTION(Teuchos::ScalarTraits<double>::isnaninf(f[i])||Teuchos::ScalarTraits<double>::isnaninf(df[i]), \
00298 std::runtime_error, \
00299 "Non-normal floating point result detected in " \
00300 "evaluation of unary functor " \
00301 << name() << " at argument " << x[i]); \
00302 } \
00303 } \
00304 else \
00305 { \
00306 for (int i=0; i<nx; i++) \
00307 { \
00308 f[i] = funcDefinition; \
00309 df[i] = firstDerivDefinition; \
00310 } \
00311 } \
00312 } \
00313 inline void functorName::eval2(const double* const x, \
00314 int nx, \
00315 double* f, \
00316 double* df, \
00317 double* d2f) const \
00318 { \
00319 if (checkResults()) \
00320 { \
00321 for (int i=0; i<nx; i++) \
00322 { \
00323 f[i] = funcDefinition; \
00324 df[i] = firstDerivDefinition; \
00325 d2f[i] = secondDerivDefinition; \
00326 TEUCHOS_TEST_FOR_EXCEPTION(Teuchos::ScalarTraits<double>::isnaninf(f[i])||Teuchos::ScalarTraits<double>::isnaninf(df[i])||Teuchos::ScalarTraits<double>::isnaninf(d2f[i]), \
00327 std::runtime_error, \
00328 "Non-normal floating point result detected in " \
00329 "evaluation of unary functor " \
00330 << name() << " at argument " << x[i] ); \
00331 } \
00332 } \
00333 else \
00334 { \
00335 for (int i=0; i<nx; i++) \
00336 { \
00337 f[i] = funcDefinition; \
00338 df[i] = firstDerivDefinition; \
00339 d2f[i] = secondDerivDefinition; \
00340 } \
00341 } \
00342 } \
00343 inline void functorName::eval3(const double* const x, \
00344 int nx, \
00345 double* f, \
00346 double* df, \
00347 double* d2f, \
00348 double* d3f) const \
00349 { \
00350 if (checkResults()) \
00351 { \
00352 for (int i=0; i<nx; i++) \
00353 { \
00354 f[i] = funcDefinition; \
00355 df[i] = firstDerivDefinition; \
00356 d2f[i] = secondDerivDefinition; \
00357 d3f[i] = thirdDerivDefinition; \
00358 TEUCHOS_TEST_FOR_EXCEPTION(Teuchos::ScalarTraits<double>::isnaninf(f[i])||Teuchos::ScalarTraits<double>::isnaninf(df[i])||Teuchos::ScalarTraits<double>::isnaninf(d2f[i])||Teuchos::ScalarTraits<double>::isnaninf(d3f[i]), \
00359 std::runtime_error, \
00360 "Non-normal floating point result detected in " \
00361 "evaluation of unary functor " \
00362 << name() << " at argument " << x[i] ); \
00363 } \
00364 } \
00365 else \
00366 { \
00367 for (int i=0; i<nx; i++) \
00368 { \
00369 f[i] = funcDefinition; \
00370 df[i] = firstDerivDefinition; \
00371 d2f[i] = secondDerivDefinition; \
00372 d3f[i] = thirdDerivDefinition; \
00373 } \
00374 } \
00375 }
00376
00377
00378 #endif
00379
00380 #endif