CppAD: A C++ Algorithmic Differentiation Package  20130102
pow_op.hpp
Go to the documentation of this file.
00001 /* $Id$ */
00002 # ifndef CPPAD_POW_OP_INCLUDED
00003 # define CPPAD_POW_OP_INCLUDED
00004 
00005 /* --------------------------------------------------------------------------
00006 CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-12 Bradley M. Bell
00007 
00008 CppAD is distributed under multiple licenses. This distribution is under
00009 the terms of the 
00010                     Eclipse Public License Version 1.0.
00011 
00012 A copy of this license is included in the COPYING file of this distribution.
00013 Please visit http://www.coin-or.org/CppAD/ for information on other licenses.
00014 -------------------------------------------------------------------------- */
00015 
00016 CPPAD_BEGIN_NAMESPACE
00017 /*!
00018 \defgroup pow_op_hpp pow_op.hpp
00019 \{
00020 \file pow_op.hpp
00021 Forward and reverse mode calculations for z = pow(x, y).
00022 */
00023 
00024 // --------------------------- Powvv -----------------------------------------
00025 /*!
00026 Compute forward mode Taylor coefficients for result of op = PowvvOp.
00027 
00028 In the documentation below,
00029 this operations is for the case where both x and y are variables
00030 and the argument \a parameter is not used.
00031 
00032 \copydetails forward_pow_op
00033 */
00034 
00035 template <class Base>
00036 inline void forward_powvv_op(
00037      size_t        d           , 
00038      size_t        i_z         ,
00039      const addr_t* arg         ,
00040      const Base*   parameter   ,
00041      size_t        nc_taylor   ,
00042      Base*         taylor      )
00043 {
00044      // convert from final result to first result
00045      i_z -= 2; // NumRes(PowvvOp) - 1;
00046 
00047      // check assumptions
00048      CPPAD_ASSERT_UNKNOWN( NumArg(PowvvOp) == 2 );
00049      CPPAD_ASSERT_UNKNOWN( NumRes(PowvvOp) == 3 );
00050      CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < i_z );
00051      CPPAD_ASSERT_UNKNOWN( size_t(arg[1]) < i_z );
00052      CPPAD_ASSERT_UNKNOWN( d < nc_taylor );
00053 
00054      // z_0 = log(x)
00055      forward_log_op(d, i_z, arg[0], nc_taylor, taylor);
00056 
00057      // z_1 = z_0 * y
00058      addr_t adr[2];
00059      adr[0] = i_z;
00060      adr[1] = arg[1];
00061      forward_mulvv_op(d, i_z+1, adr, parameter, nc_taylor, taylor);
00062 
00063      // z_2 = exp(z_1)
00064 # if CPPAD_USE_FORWARD0SWEEP
00065      CPPAD_ASSERT_UNKNOWN( d > 0 );
00066      forward_exp_op(d, i_z+2, i_z+1, nc_taylor, taylor);
00067 # else
00068      // final result for zero order case is exactly the same as for Base
00069      if( d == 0 )
00070      {    // Taylor coefficients corresponding to arguments and result
00071           Base* x   = taylor + arg[0]  * nc_taylor;
00072           Base* y   = taylor + arg[1]  * nc_taylor;
00073           Base* z_2 = taylor + (i_z+2) * nc_taylor;
00074 
00075           z_2[0] = pow(x[0], y[0]);
00076      }
00077      else forward_exp_op(d, i_z+2, i_z+1, nc_taylor, taylor);
00078 # endif
00079 }
00080 
00081 /*!
00082 Compute zero order forward mode Taylor coefficients for result of op = PowvvOp.
00083 
00084 The C++ source code corresponding to this operation is
00085 \verbatim
00086      z = pow(x, y)
00087 \endverbatim
00088 In the documentation below,
00089 this operations is for the case where both x and y are variables
00090 and the argument \a parameter is not used.
00091 
00092 \copydetails forward_pow_op_0
00093 */
00094 
00095 template <class Base>
00096 inline void forward_powvv_op_0(
00097      size_t        i_z         ,
00098      const addr_t* arg         ,
00099      const Base*   parameter   ,
00100      size_t        nc_taylor   ,
00101      Base*         taylor      )
00102 {
00103      // convert from final result to first result
00104      i_z -= 2; // NumRes(PowvvOp) - 1;
00105 
00106      // check assumptions
00107      CPPAD_ASSERT_UNKNOWN( NumArg(PowvvOp) == 2 );
00108      CPPAD_ASSERT_UNKNOWN( NumRes(PowvvOp) == 3 );
00109      CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < i_z );
00110      CPPAD_ASSERT_UNKNOWN( size_t(arg[1]) < i_z );
00111 
00112      // Taylor coefficients corresponding to arguments and result
00113      Base* x   = taylor + arg[0] * nc_taylor;
00114      Base* y   = taylor + arg[1] * nc_taylor;
00115      Base* z_0 = taylor + i_z    * nc_taylor;
00116      Base* z_1 = z_0    +          nc_taylor;
00117      Base* z_2 = z_1    +          nc_taylor;
00118 
00119      z_0[0] = log( x[0] );
00120      z_1[0] = z_0[0] * y[0];
00121      z_2[0] = pow(x[0], y[0]);
00122 
00123 }
00124 
00125 /*!
00126 Compute reverse mode partial derivatives for result of op = PowvvOp.
00127 
00128 The C++ source code corresponding to this operation is
00129 \verbatim
00130      z = pow(x, y)
00131 \endverbatim
00132 In the documentation below,
00133 this operations is for the case where both x and y are variables
00134 and the argument \a parameter is not used.
00135 
00136 \copydetails reverse_pow_op
00137 */
00138 
00139 template <class Base>
00140 inline void reverse_powvv_op(
00141      size_t        d           , 
00142      size_t        i_z         ,
00143      const addr_t* arg         ,
00144      const Base*   parameter   ,
00145      size_t        nc_taylor   ,
00146      const Base*   taylor      ,
00147      size_t        nc_partial  ,
00148      Base*         partial     )
00149 {
00150      // convert from final result to first result
00151      i_z -= 2; // NumRes(PowvvOp) - 1;
00152 
00153      // check assumptions
00154      CPPAD_ASSERT_UNKNOWN( NumArg(PowvvOp) == 2 );
00155      CPPAD_ASSERT_UNKNOWN( NumRes(PowvvOp) == 3 );
00156      CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < i_z );
00157      CPPAD_ASSERT_UNKNOWN( size_t(arg[1]) < i_z );
00158      CPPAD_ASSERT_UNKNOWN( d < nc_taylor );
00159      CPPAD_ASSERT_UNKNOWN( d < nc_partial );
00160 
00161      // z_2 = exp(z_1)
00162      reverse_exp_op(
00163           d, i_z+2, i_z+1, nc_taylor, taylor, nc_partial, partial
00164      );
00165 
00166      // z_1 = z_0 * y
00167      addr_t adr[2];
00168      adr[0] = i_z;
00169      adr[1] = arg[1];
00170      reverse_mulvv_op(
00171      d, i_z+1, adr, parameter, nc_taylor, taylor, nc_partial, partial
00172      );
00173 
00174      // z_0 = log(x)
00175      reverse_log_op(
00176           d, i_z, arg[0], nc_taylor, taylor, nc_partial, partial
00177      );
00178 }
00179 
00180 // --------------------------- Powpv -----------------------------------------
00181 /*!
00182 Compute forward mode Taylor coefficients for result of op = PowpvOp.
00183 
00184 The C++ source code corresponding to this operation is
00185 \verbatim
00186      z = pow(x, y)
00187 \endverbatim
00188 In the documentation below,
00189 this operations is for the case where x is a parameter and y is a variable.
00190 
00191 \copydetails forward_pow_op
00192 */
00193 
00194 template <class Base>
00195 inline void forward_powpv_op(
00196      size_t        d           , 
00197      size_t        i_z         ,
00198      const addr_t* arg         ,
00199      const Base*   parameter   ,
00200      size_t        nc_taylor   ,
00201      Base*         taylor      )
00202 {
00203      // convert from final result to first result
00204      i_z -= 2; // NumRes(PowpvOp) - 1;
00205 
00206      // check assumptions
00207      CPPAD_ASSERT_UNKNOWN( NumArg(PowpvOp) == 2 );
00208      CPPAD_ASSERT_UNKNOWN( NumRes(PowpvOp) == 3 );
00209      CPPAD_ASSERT_UNKNOWN( size_t(arg[1]) < i_z );
00210      CPPAD_ASSERT_UNKNOWN( d < nc_taylor );
00211 
00212      // Taylor coefficients corresponding to arguments and result
00213      Base* z_0 = taylor + i_z    * nc_taylor;
00214 
00215      // z_0 = log(x)
00216 # if CPPAD_USE_FORWARD0SWEEP
00217      CPPAD_ASSERT_UNKNOWN( d > 0 );
00218      z_0[d] = Base(0);
00219 # else
00220      Base x    = parameter[ arg[0] ];
00221      if( d == 0 )
00222           z_0[0] = log(x);
00223      else z_0[d] = Base(0);
00224 # endif
00225      // z_1 = z_0 * y
00226      addr_t adr[2];
00227      adr[0] = i_z * nc_taylor; // offset of z_0[0] in taylor
00228      adr[1] = arg[1];          // variable index of y in taylor
00229      // use taylor both for parameter and variable values
00230      forward_mulpv_op(d, i_z+1, adr, taylor, nc_taylor, taylor);
00231 
00232      // z_2 = exp(z_1)
00233 # if CPPAD_USE_FORWARD0SWEEP
00234      forward_exp_op(d, i_z+2, i_z+1, nc_taylor, taylor);
00235 # else
00236      // zero order case exactly same as Base type operation
00237      if( d == 0 )
00238      {    Base* y   = taylor + arg[1]  * nc_taylor;
00239           Base* z_2 = taylor + (i_z+2) * nc_taylor;
00240           z_2[0] = pow(x, y[0]);
00241      }
00242      else forward_exp_op(d, i_z+2, i_z+1, nc_taylor, taylor);
00243 # endif
00244 }
00245 /*!
00246 Compute zero order forward mode Taylor coefficient for result of op = PowpvOp.
00247 
00248 The C++ source code corresponding to this operation is
00249 \verbatim
00250      z = pow(x, y)
00251 \endverbatim
00252 In the documentation below,
00253 this operations is for the case where x is a parameter and y is a variable.
00254 
00255 \copydetails forward_pow_op_0
00256 */
00257 
00258 template <class Base>
00259 inline void forward_powpv_op_0(
00260      size_t        i_z         ,
00261      const addr_t* arg         ,
00262      const Base*   parameter   ,
00263      size_t        nc_taylor   ,
00264      Base*         taylor      )
00265 {
00266      // convert from final result to first result
00267      i_z -= 2; // NumRes(PowpvOp) - 1;
00268 
00269      // check assumptions
00270      CPPAD_ASSERT_UNKNOWN( NumArg(PowpvOp) == 2 );
00271      CPPAD_ASSERT_UNKNOWN( NumRes(PowpvOp) == 3 );
00272      CPPAD_ASSERT_UNKNOWN( size_t(arg[1]) < i_z );
00273 
00274      // Paraemter value
00275      Base x = parameter[ arg[0] ];
00276 
00277      // Taylor coefficients corresponding to arguments and result
00278      Base* y   = taylor + arg[1] * nc_taylor;
00279      Base* z_0 = taylor + i_z    * nc_taylor;
00280      Base* z_1 = z_0    +          nc_taylor;
00281      Base* z_2 = z_1    +          nc_taylor;
00282 
00283      // z_0 = log(x)
00284      z_0[0] = log(x);
00285 
00286      // z_1 = z_0 * y
00287      z_1[0] = z_0[0] * y[0];
00288 
00289      // z_2 = exp(z_1)
00290      // zero order case exactly same as Base type operation
00291      z_2[0] = pow(x, y[0]);
00292 }
00293 
00294 /*!
00295 Compute reverse mode partial derivative for result of op = PowpvOp.
00296 
00297 The C++ source code corresponding to this operation is
00298 \verbatim
00299      z = pow(x, y)
00300 \endverbatim
00301 In the documentation below,
00302 this operations is for the case where x is a parameter and y is a variable.
00303 
00304 \copydetails reverse_pow_op
00305 */
00306 
00307 template <class Base>
00308 inline void reverse_powpv_op(
00309      size_t        d           , 
00310      size_t        i_z         ,
00311      const addr_t* arg         ,
00312      const Base*   parameter   ,
00313      size_t        nc_taylor   ,
00314      const Base*   taylor      ,
00315      size_t        nc_partial  ,
00316      Base*         partial     )
00317 {
00318      // convert from final result to first result
00319      i_z -= 2; // NumRes(PowpvOp) - 1;
00320 
00321      // check assumptions
00322      CPPAD_ASSERT_UNKNOWN( NumArg(PowvvOp) == 2 );
00323      CPPAD_ASSERT_UNKNOWN( NumRes(PowvvOp) == 3 );
00324      CPPAD_ASSERT_UNKNOWN( size_t(arg[1]) < i_z );
00325      CPPAD_ASSERT_UNKNOWN( d < nc_taylor );
00326      CPPAD_ASSERT_UNKNOWN( d < nc_partial );
00327 
00328      // z_2 = exp(z_1)
00329      reverse_exp_op(
00330           d, i_z+2, i_z+1, nc_taylor, taylor, nc_partial, partial
00331      );
00332 
00333      // z_1 = z_0 * y
00334      addr_t adr[2];
00335      adr[0] = i_z * nc_taylor; // offset of z_0[0] in taylor 
00336      adr[1] = arg[1];          // index of y in taylor and partial
00337      // use taylor both for parameter and variable values
00338      reverse_mulpv_op(
00339           d, i_z+1, adr, taylor, nc_taylor, taylor, nc_partial, partial
00340      );
00341 
00342      // z_0 = log(x)
00343      // x is a parameter
00344 }
00345 
00346 // --------------------------- Powvp -----------------------------------------
00347 /*!
00348 Compute forward mode Taylor coefficients for result of op = PowvvOp.
00349 
00350 The C++ source code corresponding to this operation is
00351 \verbatim
00352      z = pow(x, y)
00353 \endverbatim
00354 In the documentation below,
00355 this operations is for the case where x is a variable and y is a parameter.
00356 
00357 \copydetails forward_pow_op
00358 */
00359 
00360 template <class Base>
00361 inline void forward_powvp_op(
00362      size_t        d           , 
00363      size_t        i_z         ,
00364      const addr_t* arg         ,
00365      const Base*   parameter   ,
00366      size_t        nc_taylor   ,
00367      Base*         taylor      )
00368 {
00369      // convert from final result to first result
00370      i_z -= 2; // NumRes(PowvpOp) - 1;
00371 
00372      // check assumptions
00373      CPPAD_ASSERT_UNKNOWN( NumArg(PowvpOp) == 2 );
00374      CPPAD_ASSERT_UNKNOWN( NumRes(PowvpOp) == 3 );
00375      CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < i_z );
00376      CPPAD_ASSERT_UNKNOWN( d < nc_taylor );
00377 
00378      // z_0 = log(x)
00379      forward_log_op(d, i_z, arg[0], nc_taylor, taylor);
00380 
00381      // z_1 = y * z_0
00382      addr_t adr[2];
00383      adr[0] = arg[1];
00384      adr[1] = i_z;
00385      forward_mulpv_op(d, i_z+1, adr, parameter, nc_taylor, taylor);
00386 
00387      // z_2 = exp(z_1)
00388      // zero order case exactly same as Base type operation
00389 # if CPPAD_USE_FORWARD0SWEEP
00390      CPPAD_ASSERT_UNKNOWN( d > 0 );
00391      forward_exp_op(d, i_z+2, i_z+1, nc_taylor, taylor);
00392 # else
00393      if( d == 0 )
00394      {    Base* z_2 = taylor + (i_z+2) * nc_taylor;
00395           Base* x   = taylor + arg[0] * nc_taylor;
00396           Base  y   = parameter[ arg[1] ];
00397           z_2[0]  = pow(x[0], y);
00398      }
00399      else forward_exp_op(d, i_z+2, i_z+1, nc_taylor, taylor);
00400 # endif
00401 
00402 }
00403 
00404 /*!
00405 Compute zero order forward mode Taylor coefficients for result of op = PowvvOp.
00406 
00407 The C++ source code corresponding to this operation is
00408 \verbatim
00409      z = pow(x, y)
00410 \endverbatim
00411 In the documentation below,
00412 this operations is for the case where x is a variable and y is a parameter.
00413 
00414 \copydetails forward_pow_op_0
00415 */
00416 
00417 template <class Base>
00418 inline void forward_powvp_op_0(
00419      size_t        i_z         ,
00420      const addr_t* arg         ,
00421      const Base*   parameter   ,
00422      size_t        nc_taylor   ,
00423      Base*         taylor      )
00424 {
00425      // convert from final result to first result
00426      i_z -= 2; // NumRes(PowvpOp) - 1;
00427 
00428      // check assumptions
00429      CPPAD_ASSERT_UNKNOWN( NumArg(PowvpOp) == 2 );
00430      CPPAD_ASSERT_UNKNOWN( NumRes(PowvpOp) == 3 );
00431      CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < i_z );
00432 
00433      // Paraemter value
00434      Base y = parameter[ arg[1] ];
00435 
00436      // Taylor coefficients corresponding to arguments and result
00437      Base* x   = taylor + arg[0] * nc_taylor;
00438      Base* z_0 = taylor + i_z    * nc_taylor;
00439      Base* z_1 = z_0    +          nc_taylor;
00440      Base* z_2 = z_1    +          nc_taylor;
00441 
00442      // z_0 = log(x)
00443      z_0[0] = log(x[0]);
00444 
00445      // z_1 = z_0 * y
00446      z_1[0] = z_0[0] * y;
00447 
00448      // z_2 = exp(z_1)
00449      // zero order case exactly same as Base type operation
00450      z_2[0] = pow(x[0], y);
00451 }
00452 
00453 /*!
00454 Compute reverse mode partial derivative for result of op = PowvpOp.
00455 
00456 The C++ source code corresponding to this operation is
00457 \verbatim
00458      z = pow(x, y)
00459 \endverbatim
00460 In the documentation below,
00461 this operations is for the case where x is a variable and y is a parameter.
00462 
00463 \copydetails reverse_pow_op
00464 */
00465 
00466 template <class Base>
00467 inline void reverse_powvp_op(
00468      size_t        d           , 
00469      size_t        i_z         ,
00470      const addr_t* arg         ,
00471      const Base*   parameter   ,
00472      size_t        nc_taylor   ,
00473      const Base*   taylor      ,
00474      size_t        nc_partial  ,
00475      Base*         partial     )
00476 {
00477      // convert from final result to first result
00478      i_z -= 2; // NumRes(PowvpOp) - 1;
00479 
00480      // check assumptions
00481      CPPAD_ASSERT_UNKNOWN( NumArg(PowvpOp) == 2 );
00482      CPPAD_ASSERT_UNKNOWN( NumRes(PowvpOp) == 3 );
00483      CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < i_z );
00484      CPPAD_ASSERT_UNKNOWN( d < nc_taylor );
00485      CPPAD_ASSERT_UNKNOWN( d < nc_partial );
00486 
00487      // z_2 = exp(z_1)
00488      reverse_exp_op(
00489           d, i_z+2, i_z+1, nc_taylor, taylor, nc_partial, partial
00490      );
00491 
00492      // z_1 = y * z_0
00493      addr_t adr[2];
00494      adr[0] = arg[1];
00495      adr[1] = i_z;
00496      reverse_mulpv_op(
00497      d, i_z+1, adr, parameter, nc_taylor, taylor, nc_partial, partial
00498      );
00499 
00500      // z_0 = log(x)
00501      reverse_log_op(
00502           d, i_z, arg[0], nc_taylor, taylor, nc_partial, partial
00503      );
00504 }
00505 
00506 /*! \} */
00507 CPPAD_END_NAMESPACE
00508 # endif
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines