SundanceStdMathFunctors.cpp
Go to the documentation of this file.
00001 /* @HEADER@ */
00002 // ************************************************************************
00003 // 
00004 //                             Sundance
00005 //                 Copyright 2011 Sandia Corporation
00006 // 
00007 // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
00008 // the U.S. Government retains certain rights in this software.
00009 //
00010 // Redistribution and use in source and binary forms, with or without
00011 // modification, are permitted provided that the following conditions are
00012 // met:
00013 //
00014 // 1. Redistributions of source code must retain the above copyright
00015 // notice, this list of conditions and the following disclaimer.
00016 //
00017 // 2. Redistributions in binary form must reproduce the above copyright
00018 // notice, this list of conditions and the following disclaimer in the
00019 // documentation and/or other materials provided with the distribution.
00020 //
00021 // 3. Neither the name of the Corporation nor the names of the
00022 // contributors may be used to endorse or promote products derived from
00023 // this software without specific prior written permission.
00024 //
00025 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
00026 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00027 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
00028 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
00029 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00030 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00031 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00032 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00033 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00034 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00035 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00036 //
00037 // Questions? Contact Kevin Long (kevin.long@ttu.edu)
00038 // 
00039 
00040 /* @HEADER@ */
00041 
00042 #include <math.h>
00043 #include "SundanceStdMathFunctors.hpp"
00044 #include "SundanceOut.hpp"
00045 #include "Teuchos_Utils.hpp"
00046 
00047 using namespace Sundance;
00048 using namespace Teuchos;
00049 using std::endl;
00050 
00051 PowerFunctor::PowerFunctor(const double& p) 
00052   : UnaryFunctor("pow("+Teuchos::toString(p)+")",
00053      powerDomain(p)), 
00054     p_(p),
00055     powerIsInteger_(p==floor(p))
00056 {}
00057 
00058 RCP<FunctorDomain> PowerFunctor::powerDomain(const double& p)
00059 {
00060   /* There are four cases: 
00061    * (1) p is a positive integer, in which case the domain is all of R.
00062    * (2) p is a negative integer, in which case the domain is R\0.
00063    * (3) p is a positive real \notin Z, in which case the domain is [0,\infty).
00064    * (3) p is a negative real \notin Z, in which case the domain is (0,\infty).
00065    */
00066   bool isInZ = floor(p)==p;
00067   bool isNegative = p < 0.0;
00068 
00069   if (isInZ)
00070     {
00071       if (isNegative) return rcp(new NonzeroDomain());
00072     }
00073   else
00074     {
00075       if (isNegative) return rcp(new StrictlyPositiveDomain());
00076       return rcp(new PositiveDomain());
00077     }
00078   return rcp(new UnboundedDomain());
00079 }
00080 
00081 void PowerFunctor::eval1(const double* const x, 
00082                         int nx, 
00083                         double* f, 
00084                         double* df) const
00085 {
00086   if (p_==2)
00087     {
00088       for (int i=0; i<nx; i++) 
00089         {
00090           df[i] = 2.0*x[i];
00091           f[i] = x[i]*x[i];
00092         }
00093     }
00094   else if (p_==1)
00095     {
00096       for (int i=0; i<nx; i++) 
00097         {
00098           df[i] = 1.0;
00099           f[i] = x[i];
00100         }
00101     }
00102   else if (p_==0)
00103     {
00104       for (int i=0; i<nx; i++) 
00105         {
00106           df[i] = 0.0;
00107           f[i] = 1.0;
00108         }
00109     }
00110   else
00111     {
00112       if (checkResults())
00113         {
00114           for (int i=0; i<nx; i++) 
00115             {
00116         TEUCHOS_TEST_FOR_EXCEPTION(!acceptX(1,x[i]), std::runtime_error,
00117          "first deriv of pow(" << x[i] 
00118          << ", " << p_ << ") "
00119          "is undefined");
00120         
00121               double px = ::pow(x[i], p_-1);
00122               df[i] = p_*px;
00123               f[i] = x[i]*px;
00124               //bvbw tried to include math.h, without success
00125 #ifdef REDDISH_PORT_PROBLEM
00126               TEUCHOS_TEST_FOR_EXCEPTION(fpclassify(f[i]) != FP_NORMAL 
00127                                  || fpclassify(df[i]) != FP_NORMAL,
00128                                  std::runtime_error,
00129                                  "Non-normal floating point result detected in "
00130                                  "evaluation of unary functor " << name());
00131 #endif
00132             }
00133         }
00134       else 
00135         {
00136     for (int i=0; i<nx; i++) 
00137       {
00138         TEUCHOS_TEST_FOR_EXCEPTION(!acceptX(1,x[i]), std::runtime_error,
00139          "first deriv of pow(" << x[i] 
00140          << ", " << p_ << ") "
00141          "is undefined");
00142         double px = ::pow(x[i], p_-1);
00143         df[i] = p_*px;
00144         f[i] = x[i]*px;
00145       }
00146         }
00147     }
00148 }
00149 
00150 
00151 
00152 
00153 void PowerFunctor::eval3(const double* const x, 
00154                          int nx, 
00155                          double* f, 
00156                          double* df,
00157                          double* d2f_dxx,
00158                          double* d3f_dxxx) const
00159 {
00160   if (p_==3)
00161     {
00162       for (int i=0; i<nx; i++) 
00163         {
00164           d3f_dxxx[i] = 6.0;
00165           d2f_dxx[i] = 6.0*x[i];
00166           df[i] = 3.0*x[i]*x[i];
00167           f[i] = x[i]*x[i]*x[i];
00168         }
00169     }
00170   else if (p_==2)
00171     {
00172       for (int i=0; i<nx; i++) 
00173         {
00174           d3f_dxxx[i] = 0.0;
00175           d2f_dxx[i] = 2.0;
00176           df[i] = 2.0*x[i];
00177           f[i] = x[i]*x[i];
00178         }
00179     }
00180   else if (p_==1)
00181     {
00182        for (int i=0; i<nx; i++) 
00183         {
00184           d3f_dxxx[i] = 0.0;
00185           d2f_dxx[i] = 0.0;
00186           df[i] = 1.0;
00187           f[i] = x[i];
00188         }
00189     }
00190   else if (p_==0)
00191     {
00192       for (int i=0; i<nx; i++) 
00193         {
00194           d3f_dxxx[i] = 0.0;
00195           d2f_dxx[i] = 0.0;
00196           df[i] = 0.0;
00197           f[i] = 1.0;
00198         }
00199     }
00200   else
00201     {
00202       if (checkResults())
00203         {
00204           for (int i=0; i<nx; i++) 
00205             {
00206               double px = ::pow(x[i], p_-3);
00207               d3f_dxxx[i] = p_ * (p_-1) * (p_-2) * px;
00208               d2f_dxx[i] = p_ * (p_-1) * x[i] * px;
00209               df[i] = p_*x[i]*x[i]*px;
00210               f[i] = x[i]*x[i]*x[i]*px;
00211         TEUCHOS_TEST_FOR_EXCEPTION(!acceptX(3,x[i]), std::runtime_error,
00212          "third deriv of pow(" << x[i] 
00213          << ", " << p_ << ") "
00214          "is undefined");
00215 
00216 
00217 #ifdef REDDISH_PORT_PROBLEM
00218               TEUCHOS_TEST_FOR_EXCEPTION(fpclassify(f[i]) != FP_NORMAL 
00219                                  || fpclassify(df[i]) != FP_NORMAL,
00220                                  std::runtime_error,
00221                                  "Non-normal floating point result detected in "
00222                                  "evaluation of unary functor " << name());
00223 #endif
00224             }
00225         }
00226       else
00227         {
00228           for (int i=0; i<nx; i++) 
00229             {
00230         TEUCHOS_TEST_FOR_EXCEPTION(!acceptX(3,x[i]), std::runtime_error,
00231          "third deriv of pow(" << x[i] 
00232          << ", " << p_ << ") "
00233          "is undefined");
00234 
00235               double px = ::pow(x[i], p_-3);
00236               d3f_dxxx[i] = p_ * (p_-1) * (p_-2) * px;
00237               d2f_dxx[i] = p_ * (p_-1) * x[i] * px;
00238               df[i] = p_*x[i]*x[i]*px;
00239               f[i] = x[i]*x[i]*x[i]*px;
00240             }
00241         }
00242     }
00243 }
00244 
00245 
00246 void PowerFunctor::eval2(const double* const x, 
00247                         int nx, 
00248                         double* f, 
00249                         double* df,
00250                         double* d2f_dxx) const
00251 {
00252   if (p_==2)
00253     {
00254       for (int i=0; i<nx; i++) 
00255         {
00256           d2f_dxx[i] = 2.0;
00257           df[i] = 2.0*x[i];
00258           f[i] = x[i]*x[i];
00259         }
00260     }
00261   else if (p_==1)
00262     {
00263        for (int i=0; i<nx; i++) 
00264         {
00265           d2f_dxx[i] = 0.0;
00266           df[i] = 1.0;
00267           f[i] = x[i];
00268         }
00269     }
00270   else if (p_==0)
00271     {
00272       for (int i=0; i<nx; i++) 
00273         {
00274           d2f_dxx[i] = 0.0;
00275           df[i] = 0.0;
00276           f[i] = 1.0;
00277         }
00278     }
00279   else
00280     {
00281       if (checkResults())
00282         {
00283           for (int i=0; i<nx; i++) 
00284             {
00285         TEUCHOS_TEST_FOR_EXCEPTION(!acceptX(2,x[i]), std::runtime_error,
00286          "second deriv of pow(" << x[i] 
00287          << ", " << p_ << ") "
00288          "is undefined");
00289 
00290 
00291               double px = ::pow(x[i], p_-2);
00292               d2f_dxx[i] = p_ * (p_-1) * px;
00293               df[i] = p_*x[i]*px;
00294               f[i] = x[i]*x[i]*px;
00295 #ifdef REDDISH_PORT_PROBLEM
00296               TEUCHOS_TEST_FOR_EXCEPTION(fpclassify(f[i]) != FP_NORMAL 
00297                                  || fpclassify(df[i]) != FP_NORMAL,
00298                                  std::runtime_error,
00299                                  "Non-normal floating point result detected in "
00300                                  "evaluation of unary functor " << name());
00301 #endif
00302             }
00303         }
00304       else
00305         {
00306     for (int i=0; i<nx; i++) 
00307       {
00308         TEUCHOS_TEST_FOR_EXCEPTION(!acceptX(2,x[i]), std::runtime_error,
00309          "second deriv of pow(" << x[i] 
00310          << ", " << p_ << ") "
00311          "is undefined");
00312         
00313         double px = ::pow(x[i], p_-2);
00314         
00315         d2f_dxx[i] = p_ * (p_-1) * px;
00316         df[i] = p_*x[i]*px;
00317         f[i] = x[i]*x[i]*px;
00318       }
00319   }
00320     }
00321 }
00322 
00323 
00324 
00325 void PowerFunctor::eval0(const double* const x, 
00326                         int nx, 
00327                         double* f) const
00328 {
00329   if (checkResults())
00330     {
00331       for (int i=0; i<nx; i++) 
00332         {
00333     TEUCHOS_TEST_FOR_EXCEPTION(!acceptX(0,x[i]), std::runtime_error,
00334            "pow(" << x[i] 
00335            << ", " << p_ << ") "
00336            "is undefined");
00337 
00338 
00339           f[i] = ::pow(x[i], p_);
00340 #ifdef REDDISH_PORT_PROBLEM
00341           TEUCHOS_TEST_FOR_EXCEPTION(fpclassify(f[i]) != FP_NORMAL, 
00342                              std::runtime_error,
00343                              "Non-normal floating point result detected in "
00344                              "evaluation of unary functor " << name());
00345 #endif
00346   }
00347     }
00348   else
00349     {
00350       for (int i=0; i<nx; i++) 
00351   {
00352     TEUCHOS_TEST_FOR_EXCEPTION(!acceptX(0,x[i]), std::runtime_error,
00353            "pow(" << x[i] 
00354            << ", " << p_ << ") "
00355            "is undefined");
00356 
00357     f[i] = ::pow(x[i], p_);
00358   }
00359     }
00360 }

Site Contact