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