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