CppAD: A C++ Algorithmic Differentiation Package
20130918
|
00001 /* $Id$ */ 00002 # ifndef CPPAD_COMPARE_INCLUDED 00003 # define CPPAD_COMPARE_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 ------------------------------------------------------------------------------- 00018 $begin Compare$$ 00019 $spell 00020 cos 00021 Op 00022 bool 00023 const 00024 $$ 00025 00026 $index binary, AD compare operator$$ 00027 $index AD, binary compare operator$$ 00028 $index compare, AD binary operator$$ 00029 $index operator, AD binary compare$$ 00030 00031 $index <, AD operator$$ 00032 $index <=, AD operator$$ 00033 $index >, AD operator$$ 00034 $index >=, AD operator$$ 00035 $index ==, AD operator$$ 00036 $index !=, AD operator$$ 00037 00038 $section AD Binary Comparison Operators$$ 00039 00040 00041 $head Syntax$$ 00042 00043 $icode%b% = %x% %Op% %y%$$ 00044 00045 00046 $head Purpose$$ 00047 Compares two operands where one of the operands is an 00048 $codei%AD<%Base%>%$$ object. 00049 The comparison has the same interpretation as for 00050 the $icode Base$$ type. 00051 00052 00053 $head Op$$ 00054 The operator $icode Op$$ is one of the following: 00055 $table 00056 $bold Op$$ $pre $$ $cnext $bold Meaning$$ $rnext 00057 $code <$$ $cnext is $icode x$$ less than $icode y$$ $rnext 00058 $code <=$$ $cnext is $icode x$$ less than or equal $icode y$$ $rnext 00059 $code >$$ $cnext is $icode x$$ greater than $icode y$$ $rnext 00060 $code >=$$ $cnext is $icode x$$ greater than or equal $icode y$$ $rnext 00061 $code ==$$ $cnext is $icode x$$ equal to $icode y$$ $rnext 00062 $code !=$$ $cnext is $icode x$$ not equal to $icode y$$ 00063 $tend 00064 00065 $head x$$ 00066 The operand $icode x$$ has prototype 00067 $codei% 00068 const %Type% &%x% 00069 %$$ 00070 where $icode Type$$ is $codei%AD<%Base%>%$$, $icode Base$$, or $code int$$. 00071 00072 $head y$$ 00073 The operand $icode y$$ has prototype 00074 $codei% 00075 const %Type% &%y% 00076 %$$ 00077 where $icode Type$$ is $codei%AD<%Base%>%$$, $icode Base$$, or $code int$$. 00078 00079 $head b$$ 00080 The result $icode b$$ has type 00081 $codei% 00082 bool %b% 00083 %$$ 00084 00085 $head Operation Sequence$$ 00086 The result of this operation is a $code bool$$ value 00087 (not an $cref/AD of Base/glossary/AD of Base/$$ object). 00088 Thus it will not be recorded as part of an 00089 AD of $icode Base$$ 00090 $cref/operation sequence/glossary/Operation/Sequence/$$. 00091 $pre 00092 00093 $$ 00094 For example, suppose 00095 $icode x$$ and $icode y$$ are $codei%AD<%Base%>%$$ objects, 00096 the tape corresponding to $codei%AD<%Base%>%$$ is recording, 00097 $icode b$$ is true, 00098 and the subsequent code is 00099 $codei% 00100 if( %b% ) 00101 %y% = cos(%x%); 00102 else %y% = sin(%x%); 00103 %$$ 00104 only the assignment $icode%y% = cos(%x%)%$$ is recorded on the tape 00105 (if $icode x$$ is a $cref/parameter/glossary/Parameter/$$, 00106 nothing is recorded). 00107 The $cref CompareChange$$ function can yield 00108 some information about changes in comparison operation results. 00109 You can use $cref CondExp$$ to obtain comparison operations 00110 that depends on the 00111 $cref/independent variable/glossary/Tape/Independent Variable/$$ 00112 values with out re-taping the AD sequence of operations. 00113 00114 $head Assumptions$$ 00115 If one of the $icode Op$$ operators listed above 00116 is used with an $codei%AD<%Base%>%$$ object, 00117 it is assumed that the same operator is supported by the base type 00118 $icode Base$$. 00119 00120 $head Example$$ 00121 $children% 00122 example/compare.cpp 00123 %$$ 00124 The file 00125 $cref compare.cpp$$ 00126 contains an example and test of these operations. 00127 It returns true if it succeeds and false otherwise. 00128 00129 $end 00130 ------------------------------------------------------------------------------- 00131 */ 00132 // BEGIN CppAD namespace 00133 namespace CppAD { 00134 00135 template <class Base> 00136 00137 // -------------- RecordCompare(cop, result, left, right) -------------------- 00138 /// All these operations are done in \c Rec_, so we should move this 00139 /// routine to <tt>recorder<Base></tt>. 00140 void ADTape<Base>::RecordCompare( 00141 enum CompareOp cop , 00142 bool result , 00143 const AD<Base> &left , 00144 const AD<Base> &right ) 00145 { addr_t ind0, ind1, ind2, ind3; 00146 00147 // ind[1] = base 2 representation of [result, Var(left), Var(right]) 00148 ind1 = 0; 00149 00150 // ind[2] = left address 00151 if( Parameter(left) ) 00152 ind2 = Rec_.PutPar(left.value_); 00153 else 00154 { ind1 += 2; 00155 ind2 = left.taddr_; 00156 } 00157 00158 // ind[3] = right address 00159 if( Parameter(right) ) 00160 ind3 = Rec_.PutPar(right.value_); 00161 else 00162 { ind1 += 4; 00163 ind3 = right.taddr_; 00164 } 00165 00166 // If both left and right are parameters, do not need to record 00167 if( ind1 == 0 ) 00168 return; 00169 00170 // ind[1] & 1 = result 00171 if( result ) 00172 ind1+= 1; 00173 00174 // ind[0] = cop 00175 ind0 = size_t (cop); 00176 00177 CPPAD_ASSERT_UNKNOWN( ind1 > 1 ); 00178 CPPAD_ASSERT_UNKNOWN( NumArg(ComOp) == 4 ); 00179 CPPAD_ASSERT_UNKNOWN( NumRes(ComOp) == 0 ); 00180 00181 // put the operator in the tape 00182 Rec_.PutOp(ComOp); 00183 Rec_.PutArg(ind0, ind1, ind2, ind3); 00184 } 00185 00186 // -------------------------------- < ------------------------- 00187 # ifdef NDEBUG 00188 00189 template <class Base> 00190 CPPAD_INLINE_FRIEND_TEMPLATE_FUNCTION 00191 bool operator < (const AD<Base> &left , const AD<Base> &right) 00192 { bool result = (left.value_ < right.value_); 00193 return result; 00194 } 00195 00196 # else 00197 template <class Base> 00198 CPPAD_INLINE_FRIEND_TEMPLATE_FUNCTION 00199 bool operator < (const AD<Base> &left , const AD<Base> &right) 00200 { bool result = (left.value_ < right.value_); 00201 00202 ADTape<Base> *tape = CPPAD_NULL; 00203 if( Variable(left) ) 00204 tape = left.tape_this(); 00205 else if ( Variable(right) ) 00206 tape = right.tape_this(); 00207 00208 if( tape != CPPAD_NULL ) 00209 tape->RecordCompare(CompareLt, result, left, right); 00210 00211 return result; 00212 } 00213 # endif 00214 00215 // convert other cases into the case above 00216 CPPAD_FOLD_BOOL_VALUED_BINARY_OPERATOR(<) 00217 00218 // -------------------------------- <= ------------------------- 00219 # ifdef NDEBUG 00220 00221 template <class Base> 00222 CPPAD_INLINE_FRIEND_TEMPLATE_FUNCTION 00223 bool operator <= (const AD<Base> &left , const AD<Base> &right) 00224 { bool result = (left.value_ <= right.value_); 00225 return result; 00226 } 00227 00228 # else 00229 template <class Base> 00230 CPPAD_INLINE_FRIEND_TEMPLATE_FUNCTION 00231 bool operator <= (const AD<Base> &left , const AD<Base> &right) 00232 { bool result = (left.value_ <= right.value_); 00233 00234 ADTape<Base> *tape = CPPAD_NULL; 00235 if( Variable(left) ) 00236 tape = left.tape_this(); 00237 else if ( Variable(right) ) 00238 tape = right.tape_this(); 00239 00240 if( tape != CPPAD_NULL ) 00241 tape->RecordCompare(CompareLe, result, left, right); 00242 00243 return result; 00244 } 00245 # endif 00246 00247 // convert other cases into the case above 00248 CPPAD_FOLD_BOOL_VALUED_BINARY_OPERATOR(<=) 00249 00250 00251 // -------------------------------- > ------------------------- 00252 # ifdef NDEBUG 00253 00254 template <class Base> 00255 CPPAD_INLINE_FRIEND_TEMPLATE_FUNCTION 00256 bool operator > (const AD<Base> &left , const AD<Base> &right) 00257 { bool result = (left.value_ > right.value_); 00258 return result; 00259 } 00260 00261 # else 00262 template <class Base> 00263 CPPAD_INLINE_FRIEND_TEMPLATE_FUNCTION 00264 bool operator > (const AD<Base> &left , const AD<Base> &right) 00265 { bool result = (left.value_ > right.value_); 00266 00267 ADTape<Base> *tape = CPPAD_NULL; 00268 if( Variable(left) ) 00269 tape = left.tape_this(); 00270 else if ( Variable(right) ) 00271 tape = right.tape_this(); 00272 00273 if( tape != CPPAD_NULL ) 00274 tape->RecordCompare(CompareGt, result, left, right); 00275 00276 00277 return result; 00278 } 00279 # endif 00280 00281 // convert other cases into the case above 00282 CPPAD_FOLD_BOOL_VALUED_BINARY_OPERATOR(>) 00283 00284 // -------------------------------- >= ------------------------- 00285 # ifdef NDEBUG 00286 00287 template <class Base> 00288 CPPAD_INLINE_FRIEND_TEMPLATE_FUNCTION 00289 bool operator >= (const AD<Base> &left , const AD<Base> &right) 00290 { bool result = (left.value_ >= right.value_); 00291 return result; 00292 } 00293 00294 # else 00295 template <class Base> 00296 CPPAD_INLINE_FRIEND_TEMPLATE_FUNCTION 00297 bool operator >= (const AD<Base> &left , const AD<Base> &right) 00298 { bool result = (left.value_ >= right.value_); 00299 00300 ADTape<Base> *tape = CPPAD_NULL; 00301 if( Variable(left) ) 00302 tape = left.tape_this(); 00303 else if ( Variable(right) ) 00304 tape = right.tape_this(); 00305 00306 if( tape != CPPAD_NULL ) 00307 tape->RecordCompare(CompareGe, result, left, right); 00308 00309 return result; 00310 } 00311 # endif 00312 00313 // convert other cases into the case above 00314 CPPAD_FOLD_BOOL_VALUED_BINARY_OPERATOR(>=) 00315 00316 00317 // -------------------------------- == ------------------------- 00318 # ifdef NDEBUG 00319 00320 template <class Base> 00321 CPPAD_INLINE_FRIEND_TEMPLATE_FUNCTION 00322 bool operator == (const AD<Base> &left , const AD<Base> &right) 00323 { bool result = (left.value_ == right.value_); 00324 return result; 00325 } 00326 00327 # else 00328 template <class Base> 00329 CPPAD_INLINE_FRIEND_TEMPLATE_FUNCTION 00330 bool operator == (const AD<Base> &left , const AD<Base> &right) 00331 { bool result = (left.value_ == right.value_); 00332 00333 ADTape<Base> *tape = CPPAD_NULL; 00334 if( Variable(left) ) 00335 tape = left.tape_this(); 00336 else if ( Variable(right) ) 00337 tape = right.tape_this(); 00338 00339 if( tape != CPPAD_NULL ) 00340 tape->RecordCompare(CompareEq, result, left, right); 00341 00342 return result; 00343 } 00344 # endif 00345 00346 // convert other cases into the case above 00347 CPPAD_FOLD_BOOL_VALUED_BINARY_OPERATOR(==) 00348 00349 // -------------------------------- != ------------------------- 00350 # ifdef NDEBUG 00351 00352 template <class Base> 00353 CPPAD_INLINE_FRIEND_TEMPLATE_FUNCTION 00354 bool operator != (const AD<Base> &left , const AD<Base> &right) 00355 { bool result = (left.value_ != right.value_); 00356 return result; 00357 } 00358 00359 # else 00360 template <class Base> 00361 CPPAD_INLINE_FRIEND_TEMPLATE_FUNCTION 00362 bool operator != (const AD<Base> &left , const AD<Base> &right) 00363 { bool result = (left.value_ != right.value_); 00364 00365 ADTape<Base> *tape = CPPAD_NULL; 00366 if( Variable(left) ) 00367 tape = left.tape_this(); 00368 else if ( Variable(right) ) 00369 tape = right.tape_this(); 00370 00371 if( tape != CPPAD_NULL ) 00372 tape->RecordCompare(CompareNe, result, left, right); 00373 00374 return result; 00375 } 00376 # endif 00377 00378 // convert other cases into the case above 00379 CPPAD_FOLD_BOOL_VALUED_BINARY_OPERATOR(!=) 00380 00381 } // END CppAD namespace 00382 00383 # endif