CppAD: A C++ Algorithmic Differentiation Package 20110419
|
00001 /* $Id$ */ 00002 # ifndef CPPAD_ADD_EQ_INCLUDED 00003 # define CPPAD_ADD_EQ_INCLUDED 00004 00005 /* -------------------------------------------------------------------------- 00006 CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-11 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 // BEGIN CppAD namespace 00017 namespace CppAD { 00018 00019 template <class Base> 00020 AD<Base>& AD<Base>::operator += (const AD<Base> &right) 00021 { ADTape<Base> *tape = AD<Base>::tape_ptr(); 00022 size_t tape_id = 0; 00023 if( tape != CPPAD_NULL ) 00024 tape_id = tape->id_; 00025 00026 // id_ setting for parameters cannot match 0 00027 bool var_left = id_ == tape_id; 00028 bool var_right = right.id_ == tape_id; 00029 CPPAD_ASSERT_KNOWN( 00030 Parameter(*this) || var_left , 00031 "+=: left operand is a variable for a different thread" 00032 ); 00033 CPPAD_ASSERT_KNOWN( 00034 Parameter(right) || var_right , 00035 "+=: right operand is a variable for a different thread" 00036 ); 00037 Base left; 00038 left = value_; 00039 value_ += right.value_; 00040 00041 if( var_left ) 00042 { if( var_right ) 00043 { // this = variable + variable 00044 CPPAD_ASSERT_UNKNOWN( NumRes(AddvvOp) == 1 ); 00045 CPPAD_ASSERT_UNKNOWN( NumArg(AddvvOp) == 2 ); 00046 00047 // put operand addresses in tape 00048 tape->Rec_.PutArg(taddr_, right.taddr_); 00049 // put operator in the tape 00050 taddr_ = tape->Rec_.PutOp(AddvvOp); 00051 // make this a variable 00052 CPPAD_ASSERT_UNKNOWN( id_ == tape_id ); 00053 } 00054 else if( ! IdenticalZero( right.value_ ) ) 00055 { // this = variable + parameter 00056 // = parameter + variable 00057 CPPAD_ASSERT_UNKNOWN( NumRes(AddpvOp) == 1 ); 00058 CPPAD_ASSERT_UNKNOWN( NumArg(AddpvOp) == 2 ); 00059 00060 // put operand addresses in tape 00061 size_t p = tape->Rec_.PutPar(right.value_); 00062 tape->Rec_.PutArg(p, taddr_); 00063 // put operator in the tape 00064 taddr_ = tape->Rec_.PutOp(AddpvOp); 00065 // make this a variable 00066 CPPAD_ASSERT_UNKNOWN( id_ == tape_id ); 00067 } 00068 } 00069 else if( var_right ) 00070 { if( IdenticalZero(left) ) 00071 { // this = 0 + right 00072 make_variable(right.id_, right.taddr_); 00073 } 00074 else 00075 { // this = parameter + variable 00076 CPPAD_ASSERT_UNKNOWN( NumRes(AddpvOp) == 1 ); 00077 CPPAD_ASSERT_UNKNOWN( NumArg(AddpvOp) == 2 ); 00078 00079 // put operand addresses in tape 00080 size_t p = tape->Rec_.PutPar(left); 00081 tape->Rec_.PutArg(p, right.taddr_); 00082 // put operator in the tape 00083 taddr_ = tape->Rec_.PutOp(AddpvOp); 00084 // make this a variable 00085 id_ = tape_id; 00086 } 00087 } 00088 return *this; 00089 } 00090 00091 CPPAD_FOLD_ASSIGNMENT_OPERATOR(+=) 00092 00093 } // END CppAD namespace 00094 00095 # endif