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