CppAD: A C++ Algorithmic Differentiation Package 20110419
|
00001 /* $Id$ */ 00002 # ifndef CPPAD_ABS_OP_INCLUDED 00003 # define CPPAD_ABS_OP_INCLUDED 00004 00005 /* -------------------------------------------------------------------------- 00006 CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-10 Bradley M. Bell 00007 00008 CppAD is distributed under multiple licenses. This distribution is under 00009 the terms of the 00010 Common 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 \file abs_op.hpp 00020 Forward and reverse mode calculations for z = abs(x). 00021 */ 00022 00023 00024 /*! 00025 Compute forward mode Taylor coefficient for result of op = AbsOp. 00026 00027 The C++ source code corresponding to this operation is 00028 \verbatim 00029 z = abs(x) 00030 \endverbatim 00031 00032 \copydetails forward_unary1_op 00033 */ 00034 template <class Base> 00035 inline void forward_abs_op( 00036 size_t j , 00037 size_t i_z , 00038 size_t i_x , 00039 size_t nc_taylor , 00040 Base* taylor ) 00041 { 00042 size_t k; 00043 static Base zero(0); 00044 00045 // check assumptions 00046 CPPAD_ASSERT_UNKNOWN( NumArg(AbsOp) == 1 ); 00047 CPPAD_ASSERT_UNKNOWN( NumRes(AbsOp) == 1 ); 00048 CPPAD_ASSERT_UNKNOWN( i_x < i_z ); 00049 CPPAD_ASSERT_UNKNOWN( j < nc_taylor ); 00050 00051 // Taylor coefficients corresponding to argument and result 00052 Base* x = taylor + i_x * nc_taylor; 00053 Base* z = taylor + i_z * nc_taylor; 00054 00055 // order that decides positive, negative or zero 00056 k = 0; 00057 while( (k < j) & (x[k] == zero) ) 00058 k++; 00059 00060 if( GreaterThanZero(x[k]) ) 00061 z[j] = x[j]; 00062 else if( LessThanZero(x[k]) ) 00063 z[j] = -x[j]; 00064 else z[j] = zero; 00065 } 00066 00067 /*! 00068 Compute zero order forward mode Taylor coefficient for result of op = AbsOp. 00069 00070 The C++ source code corresponding to this operation is 00071 \verbatim 00072 z = abs(x) 00073 \endverbatim 00074 00075 \copydetails forward_unary1_op_0 00076 */ 00077 template <class Base> 00078 inline void forward_abs_op_0( 00079 size_t i_z , 00080 size_t i_x , 00081 size_t nc_taylor , 00082 Base* taylor ) 00083 { 00084 00085 // check assumptions 00086 CPPAD_ASSERT_UNKNOWN( NumArg(AbsOp) == 1 ); 00087 CPPAD_ASSERT_UNKNOWN( NumRes(AbsOp) == 1 ); 00088 CPPAD_ASSERT_UNKNOWN( i_x < i_z ); 00089 CPPAD_ASSERT_UNKNOWN( 0 < nc_taylor ); 00090 00091 // Taylor coefficients corresponding to argument and result 00092 Base y0 = *(taylor + i_x * nc_taylor); 00093 Base* z = taylor + i_z * nc_taylor; 00094 00095 if( LessThanZero(y0) ) 00096 z[0] = - y0; 00097 else z[0] = y0; 00098 } 00099 /*! 00100 Compute reverse mode partial derivatives for result of op = AbsOp. 00101 00102 The C++ source code corresponding to this operation is 00103 \verbatim 00104 z = abs(x) 00105 \endverbatim 00106 00107 \copydetails reverse_unary1_op 00108 */ 00109 00110 template <class Base> 00111 inline void reverse_abs_op( 00112 size_t d , 00113 size_t i_z , 00114 size_t i_x , 00115 size_t nc_taylor , 00116 const Base* taylor , 00117 size_t nc_partial , 00118 Base* partial ) 00119 { size_t j, k; 00120 static Base zero(0); 00121 00122 00123 // check assumptions 00124 CPPAD_ASSERT_UNKNOWN( NumArg(AbsOp) == 1 ); 00125 CPPAD_ASSERT_UNKNOWN( NumRes(AbsOp) == 1 ); 00126 CPPAD_ASSERT_UNKNOWN( i_x < i_z ); 00127 CPPAD_ASSERT_UNKNOWN( d < nc_taylor ); 00128 CPPAD_ASSERT_UNKNOWN( d < nc_partial ); 00129 00130 // Taylor coefficients and partials corresponding to argument 00131 const Base* x = taylor + i_x * nc_taylor; 00132 Base* px = partial + i_x * nc_partial; 00133 00134 // Taylor coefficients and partials corresponding to result 00135 Base* pz = partial + i_z * nc_partial; 00136 00137 // order that decides positive, negative or zero 00138 k = 0; 00139 while( (k < d) & (x[k] == zero) ) 00140 k++; 00141 00142 if( GreaterThanZero(x[k]) ) 00143 { // partial of z w.r.t y is +1 00144 for(j = k; j <= d; j++) 00145 px[j] += pz[j]; 00146 } 00147 else if( LessThanZero(x[k]) ) 00148 { // partial of z w.r.t y is -1 00149 for(j = k; j <= d; j++) 00150 px[j] -= pz[j]; 00151 } 00152 } 00153 00154 CPPAD_END_NAMESPACE 00155 # endif