CppAD: A C++ Algorithmic Differentiation Package
20130102
|
00001 /* $Id$ */ 00002 # ifndef CPPAD_DIV_OP_INCLUDED 00003 # define CPPAD_DIV_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 div_op_hpp div_op.hpp 00019 \{ 00020 \file div_op.hpp 00021 Forward and reverse mode calculations for z = x / y. 00022 */ 00023 00024 // --------------------------- Divvv ----------------------------------------- 00025 /*! 00026 Compute forward mode Taylor coefficients for result of op = DivvvOp. 00027 00028 The C++ source code corresponding to this operation is 00029 \verbatim 00030 z = x / y 00031 \endverbatim 00032 In the documentation below, 00033 this operations is for the case where both x and y are variables 00034 and the argument \a parameter is not used. 00035 00036 \copydetails forward_binary_op 00037 */ 00038 00039 template <class Base> 00040 inline void forward_divvv_op( 00041 size_t d , 00042 size_t i_z , 00043 const addr_t* arg , 00044 const Base* parameter , 00045 size_t nc_taylor , 00046 Base* taylor ) 00047 { 00048 // check assumptions 00049 CPPAD_ASSERT_UNKNOWN( NumArg(DivvvOp) == 2 ); 00050 CPPAD_ASSERT_UNKNOWN( NumRes(DivvvOp) == 1 ); 00051 CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < i_z ); 00052 CPPAD_ASSERT_UNKNOWN( size_t(arg[1]) < i_z ); 00053 CPPAD_ASSERT_UNKNOWN( d < nc_taylor ); 00054 00055 // Taylor coefficients corresponding to arguments and result 00056 Base* x = taylor + arg[0] * nc_taylor; 00057 Base* y = taylor + arg[1] * nc_taylor; 00058 Base* z = taylor + i_z * nc_taylor; 00059 00060 00061 // Using CondExp, it can make sense to divide by zero, 00062 // so do not make it an error. 00063 size_t k; 00064 z[d] = x[d]; 00065 for(k = 1; k <= d; k++) 00066 z[d] -= z[d-k] * y[k]; 00067 z[d] /= y[0]; 00068 } 00069 00070 00071 /*! 00072 Compute zero order forward mode Taylor coefficients for result of op = DivvvOp. 00073 00074 The C++ source code corresponding to this operation is 00075 \verbatim 00076 z = x / y 00077 \endverbatim 00078 In the documentation below, 00079 this operations is for the case where both x and y are variables 00080 and the argument \a parameter is not used. 00081 00082 \copydetails forward_binary_op_0 00083 */ 00084 00085 template <class Base> 00086 inline void forward_divvv_op_0( 00087 size_t i_z , 00088 const addr_t* arg , 00089 const Base* parameter , 00090 size_t nc_taylor , 00091 Base* taylor ) 00092 { 00093 // check assumptions 00094 CPPAD_ASSERT_UNKNOWN( NumArg(DivvvOp) == 2 ); 00095 CPPAD_ASSERT_UNKNOWN( NumRes(DivvvOp) == 1 ); 00096 CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < i_z ); 00097 CPPAD_ASSERT_UNKNOWN( size_t(arg[1]) < i_z ); 00098 00099 // Taylor coefficients corresponding to arguments and result 00100 Base* x = taylor + arg[0] * nc_taylor; 00101 Base* y = taylor + arg[1] * nc_taylor; 00102 Base* z = taylor + i_z * nc_taylor; 00103 00104 z[0] = x[0] / y[0]; 00105 } 00106 00107 /*! 00108 Compute reverse mode partial derivatives for result of op = DivvvOp. 00109 00110 The C++ source code corresponding to this operation is 00111 \verbatim 00112 z = x / y 00113 \endverbatim 00114 In the documentation below, 00115 this operations is for the case where both x and y are variables 00116 and the argument \a parameter is not used. 00117 00118 \copydetails reverse_binary_op 00119 */ 00120 00121 template <class Base> 00122 inline void reverse_divvv_op( 00123 size_t d , 00124 size_t i_z , 00125 const addr_t* arg , 00126 const Base* parameter , 00127 size_t nc_taylor , 00128 const Base* taylor , 00129 size_t nc_partial , 00130 Base* partial ) 00131 { 00132 // check assumptions 00133 CPPAD_ASSERT_UNKNOWN( NumArg(DivvvOp) == 2 ); 00134 CPPAD_ASSERT_UNKNOWN( NumRes(DivvvOp) == 1 ); 00135 CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < i_z ); 00136 CPPAD_ASSERT_UNKNOWN( size_t(arg[1]) < i_z ); 00137 CPPAD_ASSERT_UNKNOWN( d < nc_taylor ); 00138 CPPAD_ASSERT_UNKNOWN( d < nc_partial ); 00139 00140 // Arguments 00141 const Base* y = taylor + arg[1] * nc_taylor; 00142 const Base* z = taylor + i_z * nc_taylor; 00143 00144 // Partial derivatives corresponding to arguments and result 00145 Base* px = partial + arg[0] * nc_partial; 00146 Base* py = partial + arg[1] * nc_partial; 00147 Base* pz = partial + i_z * nc_partial; 00148 00149 // Using CondExp, it can make sense to divide by zero 00150 // so do not make it an error. 00151 00152 size_t k; 00153 // number of indices to access 00154 size_t j = d + 1; 00155 while(j) 00156 { --j; 00157 // scale partial w.r.t. z[j] 00158 pz[j] /= y[0]; 00159 00160 px[j] += pz[j]; 00161 for(k = 1; k <= j; k++) 00162 { pz[j-k] -= pz[j] * y[k]; 00163 py[k] -= pz[j] * z[j-k]; 00164 } 00165 py[0] -= pz[j] * z[j]; 00166 } 00167 } 00168 00169 // --------------------------- Divpv ----------------------------------------- 00170 /*! 00171 Compute forward mode Taylor coefficients for result of op = DivpvOp. 00172 00173 The C++ source code corresponding to this operation is 00174 \verbatim 00175 z = x / y 00176 \endverbatim 00177 In the documentation below, 00178 this operations is for the case where x is a parameter and y is a variable. 00179 00180 \copydetails forward_binary_op 00181 */ 00182 00183 template <class Base> 00184 inline void forward_divpv_op( 00185 size_t d , 00186 size_t i_z , 00187 const addr_t* arg , 00188 const Base* parameter , 00189 size_t nc_taylor , 00190 Base* taylor ) 00191 { 00192 // check assumptions 00193 CPPAD_ASSERT_UNKNOWN( NumArg(DivpvOp) == 2 ); 00194 CPPAD_ASSERT_UNKNOWN( NumRes(DivpvOp) == 1 ); 00195 CPPAD_ASSERT_UNKNOWN( size_t(arg[1]) < i_z ); 00196 CPPAD_ASSERT_UNKNOWN( d < nc_taylor ); 00197 00198 // Taylor coefficients corresponding to arguments and result 00199 Base* y = taylor + arg[1] * nc_taylor; 00200 Base* z = taylor + i_z * nc_taylor; 00201 00202 // Paraemter value 00203 Base x = parameter[ arg[0] ]; 00204 00205 // Using CondExp, it can make sense to divide by zero, 00206 // so do not make it an error. 00207 size_t k; 00208 # if USE_CPPAD_FORWARD0SWEEP 00209 z[d] = Base(0); 00210 # else 00211 if( d == 0 ) 00212 z[d] = x; 00213 else z[d] = Base(0); 00214 # endif 00215 for(k = 1; k <= d; k++) 00216 z[d] -= z[d-k] * y[k]; 00217 z[d] /= y[0]; 00218 00219 } 00220 00221 /*! 00222 Compute zero order forward mode Taylor coefficient for result of op = DivpvOp. 00223 00224 The C++ source code corresponding to this operation is 00225 \verbatim 00226 z = x / y 00227 \endverbatim 00228 In the documentation below, 00229 this operations is for the case where x is a parameter and y is a variable. 00230 00231 \copydetails forward_binary_op_0 00232 */ 00233 00234 template <class Base> 00235 inline void forward_divpv_op_0( 00236 size_t i_z , 00237 const addr_t* arg , 00238 const Base* parameter , 00239 size_t nc_taylor , 00240 Base* taylor ) 00241 { 00242 // check assumptions 00243 CPPAD_ASSERT_UNKNOWN( NumArg(DivpvOp) == 2 ); 00244 CPPAD_ASSERT_UNKNOWN( NumRes(DivpvOp) == 1 ); 00245 CPPAD_ASSERT_UNKNOWN( size_t(arg[1]) < i_z ); 00246 00247 // Paraemter value 00248 Base x = parameter[ arg[0] ]; 00249 00250 // Taylor coefficients corresponding to arguments and result 00251 Base* y = taylor + arg[1] * nc_taylor; 00252 Base* z = taylor + i_z * nc_taylor; 00253 00254 z[0] = x / y[0]; 00255 } 00256 00257 /*! 00258 Compute reverse mode partial derivative for result of op = DivpvOp. 00259 00260 The C++ source code corresponding to this operation is 00261 \verbatim 00262 z = x / y 00263 \endverbatim 00264 In the documentation below, 00265 this operations is for the case where x is a parameter and y is a variable. 00266 00267 \copydetails reverse_binary_op 00268 */ 00269 00270 template <class Base> 00271 inline void reverse_divpv_op( 00272 size_t d , 00273 size_t i_z , 00274 const addr_t* arg , 00275 const Base* parameter , 00276 size_t nc_taylor , 00277 const Base* taylor , 00278 size_t nc_partial , 00279 Base* partial ) 00280 { 00281 // check assumptions 00282 CPPAD_ASSERT_UNKNOWN( NumArg(DivvvOp) == 2 ); 00283 CPPAD_ASSERT_UNKNOWN( NumRes(DivvvOp) == 1 ); 00284 CPPAD_ASSERT_UNKNOWN( size_t(arg[1]) < i_z ); 00285 CPPAD_ASSERT_UNKNOWN( d < nc_taylor ); 00286 CPPAD_ASSERT_UNKNOWN( d < nc_partial ); 00287 00288 // Arguments 00289 const Base* y = taylor + arg[1] * nc_taylor; 00290 const Base* z = taylor + i_z * nc_taylor; 00291 00292 // Partial derivatives corresponding to arguments and result 00293 Base* py = partial + arg[1] * nc_partial; 00294 Base* pz = partial + i_z * nc_partial; 00295 00296 // Using CondExp, it can make sense to divide by zero so do not 00297 // make it an error. 00298 00299 size_t k; 00300 // number of indices to access 00301 size_t j = d + 1; 00302 while(j) 00303 { --j; 00304 // scale partial w.r.t z[j] 00305 pz[j] /= y[0]; 00306 00307 for(k = 1; k <= j; k++) 00308 { pz[j-k] -= pz[j] * y[k]; 00309 py[k] -= pz[j] * z[j-k]; 00310 } 00311 py[0] -= pz[j] * z[j]; 00312 } 00313 } 00314 00315 00316 // --------------------------- Divvp ----------------------------------------- 00317 /*! 00318 Compute forward mode Taylor coefficients for result of op = DivvvOp. 00319 00320 The C++ source code corresponding to this operation is 00321 \verbatim 00322 z = x / y 00323 \endverbatim 00324 In the documentation below, 00325 this operations is for the case where x is a variable and y is a parameter. 00326 00327 \copydetails forward_binary_op 00328 */ 00329 00330 template <class Base> 00331 inline void forward_divvp_op( 00332 size_t d , 00333 size_t i_z , 00334 const addr_t* arg , 00335 const Base* parameter , 00336 size_t nc_taylor , 00337 Base* taylor ) 00338 { 00339 // check assumptions 00340 CPPAD_ASSERT_UNKNOWN( NumArg(DivvpOp) == 2 ); 00341 CPPAD_ASSERT_UNKNOWN( NumRes(DivvpOp) == 1 ); 00342 CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < i_z ); 00343 CPPAD_ASSERT_UNKNOWN( d < nc_taylor ); 00344 00345 // Taylor coefficients corresponding to arguments and result 00346 Base* x = taylor + arg[0] * nc_taylor; 00347 Base* z = taylor + i_z * nc_taylor; 00348 00349 // Parameter value 00350 Base y = parameter[ arg[1] ]; 00351 00352 // Using CondExp and multiple levels of AD, it can make sense 00353 // to divide by zero so do not make it an error. 00354 z[d] = x[d] / y; 00355 } 00356 00357 00358 /*! 00359 Compute zero order forward mode Taylor coefficients for result of op = DivvvOp. 00360 00361 The C++ source code corresponding to this operation is 00362 \verbatim 00363 z = x / y 00364 \endverbatim 00365 In the documentation below, 00366 this operations is for the case where x is a variable and y is a parameter. 00367 00368 \copydetails forward_binary_op_0 00369 */ 00370 00371 template <class Base> 00372 inline void forward_divvp_op_0( 00373 size_t i_z , 00374 const addr_t* arg , 00375 const Base* parameter , 00376 size_t nc_taylor , 00377 Base* taylor ) 00378 { 00379 // check assumptions 00380 CPPAD_ASSERT_UNKNOWN( NumArg(DivvpOp) == 2 ); 00381 CPPAD_ASSERT_UNKNOWN( NumRes(DivvpOp) == 1 ); 00382 CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < i_z ); 00383 00384 // Parameter value 00385 Base y = parameter[ arg[1] ]; 00386 00387 // Taylor coefficients corresponding to arguments and result 00388 Base* x = taylor + arg[0] * nc_taylor; 00389 Base* z = taylor + i_z * nc_taylor; 00390 00391 z[0] = x[0] / y; 00392 } 00393 00394 /*! 00395 Compute reverse mode partial derivative for result of op = DivvpOp. 00396 00397 The C++ source code corresponding to this operation is 00398 \verbatim 00399 z = x / y 00400 \endverbatim 00401 In the documentation below, 00402 this operations is for the case where x is a variable and y is a parameter. 00403 00404 \copydetails reverse_binary_op 00405 */ 00406 00407 template <class Base> 00408 inline void reverse_divvp_op( 00409 size_t d , 00410 size_t i_z , 00411 const addr_t* arg , 00412 const Base* parameter , 00413 size_t nc_taylor , 00414 const Base* taylor , 00415 size_t nc_partial , 00416 Base* partial ) 00417 { 00418 // check assumptions 00419 CPPAD_ASSERT_UNKNOWN( NumArg(DivvpOp) == 2 ); 00420 CPPAD_ASSERT_UNKNOWN( NumRes(DivvpOp) == 1 ); 00421 CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < i_z ); 00422 CPPAD_ASSERT_UNKNOWN( d < nc_taylor ); 00423 CPPAD_ASSERT_UNKNOWN( d < nc_partial ); 00424 00425 // Argument values 00426 Base y = parameter[ arg[1] ]; 00427 00428 // Partial derivatives corresponding to arguments and result 00429 Base* px = partial + arg[0] * nc_partial; 00430 Base* pz = partial + i_z * nc_partial; 00431 00432 // Using CondExp, it can make sense to divide by zero 00433 // so do not make it an error. 00434 00435 // number of indices to access 00436 size_t j = d + 1; 00437 while(j) 00438 { --j; 00439 px[j] += pz[j] / y; 00440 } 00441 } 00442 00443 /*! \} */ 00444 CPPAD_END_NAMESPACE 00445 # endif