CppAD: A C++ Algorithmic Differentiation Package  20130102
div_op.hpp
Go to the documentation of this file.
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
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines