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