CppAD: A C++ Algorithmic Differentiation Package
20130918
|
00001 /* $Id$ */ 00002 # ifndef CPPAD_ATAN_OP_INCLUDED 00003 # define CPPAD_ATAN_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 00017 namespace CppAD { // BEGIN_CPPAD_NAMESPACE 00018 /*! 00019 \file atan_op.hpp 00020 Forward and reverse mode calculations for z = atan(x). 00021 */ 00022 00023 00024 /*! 00025 Forward mode Taylor coefficient for result of op = AtanOp. 00026 00027 The C++ source code corresponding to this operation is 00028 \verbatim 00029 z = atan(x) 00030 \endverbatim 00031 The auxillary result is 00032 \verbatim 00033 y = 1 + x * x 00034 \endverbatim 00035 The value of y, and its derivatives, are computed along with the value 00036 and derivatives of z. 00037 00038 \copydetails forward_unary2_op 00039 */ 00040 template <class Base> 00041 inline void forward_atan_op( 00042 size_t p , 00043 size_t q , 00044 size_t i_z , 00045 size_t i_x , 00046 size_t nc_taylor , 00047 Base* taylor ) 00048 { 00049 // check assumptions 00050 CPPAD_ASSERT_UNKNOWN( NumArg(AtanOp) == 1 ); 00051 CPPAD_ASSERT_UNKNOWN( NumRes(AtanOp) == 2 ); 00052 CPPAD_ASSERT_UNKNOWN( i_x + 1 < i_z ); 00053 CPPAD_ASSERT_UNKNOWN( q < nc_taylor ); 00054 CPPAD_ASSERT_UNKNOWN( p <= q ); 00055 00056 // Taylor coefficients corresponding to argument and result 00057 Base* x = taylor + i_x * nc_taylor; 00058 Base* z = taylor + i_z * nc_taylor; 00059 Base* b = z - nc_taylor; // called y in documentation 00060 00061 size_t k; 00062 if( p == 0 ) 00063 { z[0] = atan( x[0] ); 00064 b[0] = Base(1) + x[0] * x[0]; 00065 p++; 00066 } 00067 for(size_t j = p; j <= q; j++) 00068 { 00069 b[j] = Base(2) * x[0] * x[j]; 00070 z[j] = Base(0); 00071 for(k = 1; k < j; k++) 00072 { b[j] += x[k] * x[j-k]; 00073 z[j] -= Base(k) * z[k] * b[j-k]; 00074 } 00075 z[j] /= Base(j); 00076 z[j] += x[j]; 00077 z[j] /= b[0]; 00078 } 00079 } 00080 00081 /*! 00082 Zero order forward mode Taylor coefficient for result of op = AtanOp. 00083 00084 The C++ source code corresponding to this operation is 00085 \verbatim 00086 z = atan(x) 00087 \endverbatim 00088 The auxillary result is 00089 \verbatim 00090 y = 1 + x * x 00091 \endverbatim 00092 The value of y is computed along with the value of z. 00093 00094 \copydetails forward_unary2_op_0 00095 */ 00096 template <class Base> 00097 inline void forward_atan_op_0( 00098 size_t i_z , 00099 size_t i_x , 00100 size_t nc_taylor , 00101 Base* taylor ) 00102 { 00103 // check assumptions 00104 CPPAD_ASSERT_UNKNOWN( NumArg(AtanOp) == 1 ); 00105 CPPAD_ASSERT_UNKNOWN( NumRes(AtanOp) == 2 ); 00106 CPPAD_ASSERT_UNKNOWN( i_x + 1 < i_z ); 00107 CPPAD_ASSERT_UNKNOWN( 0 < nc_taylor ); 00108 00109 // Taylor coefficients corresponding to argument and result 00110 Base* x = taylor + i_x * nc_taylor; 00111 Base* z = taylor + i_z * nc_taylor; 00112 Base* b = z - nc_taylor; // called y in documentation 00113 00114 z[0] = atan( x[0] ); 00115 b[0] = Base(1) + x[0] * x[0]; 00116 } 00117 /*! 00118 Reverse mode partial derivatives for result of op = AtanOp. 00119 00120 The C++ source code corresponding to this operation is 00121 \verbatim 00122 z = atan(x) 00123 \endverbatim 00124 The auxillary result is 00125 \verbatim 00126 y = 1 + x * x 00127 \endverbatim 00128 The value of y is computed along with the value of z. 00129 00130 \copydetails reverse_unary2_op 00131 */ 00132 00133 template <class Base> 00134 inline void reverse_atan_op( 00135 size_t d , 00136 size_t i_z , 00137 size_t i_x , 00138 size_t nc_taylor , 00139 const Base* taylor , 00140 size_t nc_partial , 00141 Base* partial ) 00142 { 00143 // check assumptions 00144 CPPAD_ASSERT_UNKNOWN( NumArg(AtanOp) == 1 ); 00145 CPPAD_ASSERT_UNKNOWN( NumRes(AtanOp) == 2 ); 00146 CPPAD_ASSERT_UNKNOWN( i_x + 1 < i_z ); 00147 CPPAD_ASSERT_UNKNOWN( d < nc_taylor ); 00148 CPPAD_ASSERT_UNKNOWN( d < nc_partial ); 00149 00150 // Taylor coefficients and partials corresponding to argument 00151 const Base* x = taylor + i_x * nc_taylor; 00152 Base* px = partial + i_x * nc_partial; 00153 00154 // Taylor coefficients and partials corresponding to first result 00155 const Base* z = taylor + i_z * nc_taylor; 00156 Base* pz = partial + i_z * nc_partial; 00157 00158 // Taylor coefficients and partials corresponding to auxillary result 00159 const Base* b = z - nc_taylor; // called y in documentation 00160 Base* pb = pz - nc_partial; 00161 00162 // number of indices to access 00163 size_t j = d; 00164 size_t k; 00165 while(j) 00166 { // scale partials w.r.t z[j] and b[j] 00167 pz[j] /= b[0]; 00168 pb[j] *= Base(2); 00169 00170 pb[0] -= pz[j] * z[j]; 00171 px[j] += pz[j] + pb[j] * x[0]; 00172 px[0] += pb[j] * x[j]; 00173 00174 // more scaling of partials w.r.t z[j] 00175 pz[j] /= Base(j); 00176 00177 for(k = 1; k < j; k++) 00178 { pb[j-k] -= pz[j] * Base(k) * z[k]; 00179 pz[k] -= pz[j] * Base(k) * b[j-k]; 00180 px[k] += pb[j] * x[j-k]; 00181 } 00182 --j; 00183 } 00184 px[0] += pz[0] / b[0] + pb[0] * Base(2) * x[0]; 00185 } 00186 00187 } // END_CPPAD_NAMESPACE 00188 # endif