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