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