Sandia Home
Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

SundanceUnaryFunctor.hpp

Go to the documentation of this file.
00001 /* @HEADER@ */
00002 // ************************************************************************
00003 // 
00004 //                              Sundance
00005 //                 Copyright (2005) Sandia Corporation
00006 // 
00007 // Copyright (year first published) Sandia Corporation.  Under the terms 
00008 // of Contract DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government 
00009 // retains certain rights in this software.
00010 // 
00011 // This library is free software; you can redistribute it and/or modify
00012 // it under the terms of the GNU Lesser General Public License as
00013 // published by the Free Software Foundation; either version 2.1 of the
00014 // License, or (at your option) any later version.
00015 //  
00016 // This library is distributed in the hope that it will be useful, but
00017 // WITHOUT ANY WARRANTY; without even the implied warranty of
00018 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00019 // Lesser General Public License for more details.
00020 //                                                                                 
00021 // You should have received a copy of the GNU Lesser General Public
00022 // License along with this library; if not, write to the Free Software
00023 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
00024 // USA                                                                                
00025 // Questions? Contact Kevin Long (krlong@sandia.gov), 
00026 // Sandia National Laboratories, Livermore, California, USA
00027 // 
00028 // ************************************************************************
00029 /* @HEADER@ */
00030 
00031 #ifndef SUNDANCE_UNARYFUNCTOR_H
00032 #define SUNDANCE_UNARYFUNCTOR_H
00033 
00034 #include "SundanceDefs.hpp"
00035 #include "SundanceExceptions.hpp"
00036 #include "SundanceFunctorDomain.hpp"
00037 #include "Teuchos_ScalarTraits.hpp"
00038 #include "Teuchos_RefCountPtr.hpp"
00039 
00040 #ifndef DOXYGEN_DEVELOPER_ONLY
00041 
00042 namespace SundanceUtils
00043 {
00044   using namespace Teuchos;
00045 
00046   using std::string;
00047   using std::ostream;
00048 
00049   /**
00050    * 
00051    */
00052   class UnaryFunctor
00053   {
00054   public:
00055     /** ctor */
00056     UnaryFunctor(const string& name, 
00057                  const RefCountPtr<FunctorDomain>& domain 
00058                  = rcp(new UnboundedDomain())) 
00059       : name_(name), h_(fdStep()), domain_(domain) {;}
00060 
00061     /** */
00062     virtual ~UnaryFunctor(){;}
00063 
00064     /** */
00065     const 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     /** Specify whether we should test for NAN or INFINITE results. */
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 RefCountPtr<FunctorDomain>& domain() const 
00129     {return domain_;}
00130   private:
00131     string name_;
00132 
00133     double h_;
00134 
00135     RefCountPtr<FunctorDomain> domain_;
00136   };
00137 }
00138 
00139 /** */
00140 #define SUNDANCE_UNARY_FUNCTOR(opName, functorName, description, domain, \
00141                                funcDefinition, firstDerivDefinition,    \
00142                                secondDerivDefinition)                   \
00143   class functorName : public SundanceUtils::UnaryFunctor                \
00144   {                                                                     \
00145   public:                                                               \
00146     /** ctor for description functor */                                 \
00147     functorName() : SundanceUtils::UnaryFunctor(#opName, rcp(new domain)) {;} \
00148       /** virtual dtor */                                               \
00149       virtual ~functorName(){;}                                         \
00150       /** Evaluate function at an array of values */                    \
00151       void eval0(const double* const x, int nx, double* f) const ;      \
00152       /** Evaluate function and first derivative at an array of values */ \
00153       void eval1(const double* const x,                                 \
00154                  int nx,                                                \
00155                  double* f,                                             \
00156                  double* df) const ;                                    \
00157       /** Evaluate function and first two derivatives at an array of values */ \
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             TEST_FOR_EXCEPTION(Teuchos::ScalarTraits<double>::isnaninf(f[i]), RuntimeError, "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              TEST_FOR_EXCEPTION(Teuchos::ScalarTraits<double>::isnaninf(f[i])||Teuchos::ScalarTraits<double>::isnaninf(df[i]), \
00191                                 RuntimeError,                           \
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               TEST_FOR_EXCEPTION(Teuchos::ScalarTraits<double>::isnaninf(f[i])||Teuchos::ScalarTraits<double>::isnaninf(df[i])||Teuchos::ScalarTraits<double>::isnaninf(d2f[i]), \
00220                                  RuntimeError,                          \
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 SundanceUtils::UnaryFunctor                \
00244   {                                                                     \
00245   public:                                                               \
00246     /** ctor for description functor */                                 \
00247     functorName() : SundanceUtils::UnaryFunctor(#opName, rcp(new domain)) {;} \
00248       /** virtual dtor */                                               \
00249       virtual ~functorName(){;}                                         \
00250       /** Evaluate function at an array of values */                    \
00251       void eval0(const double* const x, int nx, double* f) const ;      \
00252       /** Evaluate function and first derivative at an array of values */ \
00253       void eval1(const double* const x,                                 \
00254                  int nx,                                                \
00255                  double* f,                                             \
00256                  double* df) const ;                                    \
00257       /** Evaluate function and first two derivatives at an array of values */ \
00258       void eval2(const double* const x,                                 \
00259                  int nx,                                                \
00260                  double* f,                                             \
00261                  double* df,                                            \
00262                  double* d2f_dxx) const ;                               \
00263       /** Evaluate function and first thress derivatives at an array of values */ \
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             TEST_FOR_EXCEPTION(Teuchos::ScalarTraits<double>::isnaninf(f[i]), RuntimeError, "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              TEST_FOR_EXCEPTION(Teuchos::ScalarTraits<double>::isnaninf(f[i])||Teuchos::ScalarTraits<double>::isnaninf(df[i]), \
00298                                 RuntimeError,                           \
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               TEST_FOR_EXCEPTION(Teuchos::ScalarTraits<double>::isnaninf(f[i])||Teuchos::ScalarTraits<double>::isnaninf(df[i])||Teuchos::ScalarTraits<double>::isnaninf(d2f[i]), \
00327                                  RuntimeError,                          \
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               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                                  RuntimeError,                          \
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  /* DOXYGEN_DEVELOPER_ONLY */  
00379 
00380 #endif

© Sandia Corporation | Site Contact | Privacy and Security