CppAD: A C++ Algorithmic Differentiation Package
20130918
|
00001 /* $Id$ */ 00002 # ifndef CPPAD_TANH_OP_INCLUDED 00003 # define CPPAD_TANH_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 tanh_op.hpp 00020 Forward and reverse mode calculations for z = tanh(x). 00021 */ 00022 00023 00024 /*! 00025 Compute forward mode Taylor coefficient for result of op = TanOp. 00026 00027 The C++ source code corresponding to this operation is 00028 \verbatim 00029 z = tanh(x) 00030 \endverbatim 00031 The auxillary result is 00032 \verbatim 00033 y = tanh(x)^2 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_tanh_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(TanOp) == 1 ); 00051 CPPAD_ASSERT_UNKNOWN( NumRes(TanOp) == 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* y = z - nc_taylor; 00060 00061 size_t k; 00062 if( p == 0 ) 00063 { z[0] = tanh( x[0] ); 00064 y[0] = z[0] * z[0]; 00065 p++; 00066 } 00067 for(size_t j = p; j <= q; j++) 00068 { Base base_j = static_cast<Base>(j); 00069 00070 z[j] = x[j]; 00071 for(k = 1; k <= j; k++) 00072 z[j] -= Base(k) * x[k] * y[j-k] / base_j; 00073 00074 y[j] = z[0] * z[j]; 00075 for(k = 1; k <= j; k++) 00076 y[j] += z[k] * z[j-k]; 00077 } 00078 } 00079 00080 00081 /*! 00082 Compute zero order forward mode Taylor coefficient for result of op = TanOp. 00083 00084 The C++ source code corresponding to this operation is 00085 \verbatim 00086 z = tanh(x) 00087 \endverbatim 00088 The auxillary result is 00089 \verbatim 00090 y = cos(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_tanh_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(TanOp) == 1 ); 00105 CPPAD_ASSERT_UNKNOWN( NumRes(TanOp) == 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; // called z in documentation 00112 Base* y = z - nc_taylor; // called y in documentation 00113 00114 z[0] = tanh( x[0] ); 00115 y[0] = z[0] * z[0]; 00116 } 00117 00118 /*! 00119 Compute reverse mode partial derivatives for result of op = TanOp. 00120 00121 The C++ source code corresponding to this operation is 00122 \verbatim 00123 z = tanh(x) 00124 \endverbatim 00125 The auxillary result is 00126 \verbatim 00127 y = cos(x) 00128 \endverbatim 00129 The value of y is computed along with the value of z. 00130 00131 \copydetails reverse_unary2_op 00132 */ 00133 00134 template <class Base> 00135 inline void reverse_tanh_op( 00136 size_t d , 00137 size_t i_z , 00138 size_t i_x , 00139 size_t nc_taylor , 00140 const Base* taylor , 00141 size_t nc_partial , 00142 Base* partial ) 00143 { 00144 // check assumptions 00145 CPPAD_ASSERT_UNKNOWN( NumArg(TanOp) == 1 ); 00146 CPPAD_ASSERT_UNKNOWN( NumRes(TanOp) == 2 ); 00147 CPPAD_ASSERT_UNKNOWN( i_x + 1 < i_z ); 00148 CPPAD_ASSERT_UNKNOWN( d < nc_taylor ); 00149 CPPAD_ASSERT_UNKNOWN( d < nc_partial ); 00150 00151 // Taylor coefficients and partials corresponding to argument 00152 const Base* x = taylor + i_x * nc_taylor; 00153 Base* px = partial + i_x * nc_partial; 00154 00155 // Taylor coefficients and partials corresponding to first result 00156 const Base* z = taylor + i_z * nc_taylor; // called z in doc 00157 Base* pz = partial + i_z * nc_partial; 00158 00159 // Taylor coefficients and partials corresponding to auxillary result 00160 const Base* y = z - nc_taylor; // called y in documentation 00161 Base* py = pz - nc_partial; 00162 00163 size_t j = d; 00164 size_t k; 00165 Base base_two(2); 00166 while(j) 00167 { 00168 px[j] += pz[j]; 00169 pz[j] /= Base(j); 00170 for(k = 1; k <= j; k++) 00171 { px[k] -= pz[j] * y[j-k] * Base(k); 00172 py[j-k] -= pz[j] * x[k] * Base(k); 00173 } 00174 for(k = 0; k < j; k++) 00175 pz[k] += py[j-1] * z[j-k-1] * base_two; 00176 00177 --j; 00178 } 00179 px[0] += pz[0] * (Base(1) - y[0]); 00180 } 00181 00182 } // END_CPPAD_NAMESPACE 00183 # endif