CppAD: A C++ Algorithmic Differentiation Package
20130102
|
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