CppAD: A C++ Algorithmic Differentiation Package 20110419
mul_eq.hpp
Go to the documentation of this file.
00001 /* $Id$ */
00002 # ifndef CPPAD_MUL_EQ_INCLUDED
00003 # define CPPAD_MUL_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 
00038         Base left;
00039         left    = value_;
00040         value_ *= right.value_;
00041 
00042         if( var_left )
00043         {       if( var_right )
00044                 {       // this = variable * variable
00045                         CPPAD_ASSERT_UNKNOWN( NumRes(MulvvOp) == 1 );
00046                         CPPAD_ASSERT_UNKNOWN( NumArg(MulvvOp) == 2 );
00047 
00048                         // put operand addresses in tape
00049                         tape->Rec_.PutArg(taddr_, right.taddr_);
00050                         // put operator in the tape
00051                         taddr_ = tape->Rec_.PutOp(MulvvOp);
00052                         // make this a variable
00053                         CPPAD_ASSERT_UNKNOWN( id_ == tape_id );
00054                 }
00055                 else if( IdenticalOne( right.value_ ) )
00056                 {       // this = variable * 1
00057                 }
00058                 else if( IdenticalZero( right.value_ ) )
00059                 {       // this = variable * 0
00060                         make_parameter();
00061                 }
00062                 else
00063                 {       // this = variable  * parameter
00064                         //      = parameter * variable
00065                         CPPAD_ASSERT_UNKNOWN( NumRes(MulpvOp) == 1 );
00066                         CPPAD_ASSERT_UNKNOWN( NumArg(MulpvOp) == 2 );
00067 
00068                         // put operand addresses in tape
00069                         size_t p = tape->Rec_.PutPar(right.value_);
00070                         tape->Rec_.PutArg(p, taddr_);
00071                         // put operator in the tape
00072                         taddr_ = tape->Rec_.PutOp(MulpvOp);
00073                         // make this a variable
00074                         CPPAD_ASSERT_UNKNOWN( id_ == tape_id );
00075                 }
00076         }
00077         else if( var_right  )
00078         {       if( IdenticalZero(left) )
00079                 {       // this = 0 * right
00080                 }
00081                 else if( IdenticalOne(left) )
00082                 {       // this = 1 * right
00083                         make_variable(right.id_, right.taddr_);
00084                 }
00085                 else
00086                 {       // this = parameter * variable
00087                         CPPAD_ASSERT_UNKNOWN( NumRes(MulpvOp) == 1 );
00088                         CPPAD_ASSERT_UNKNOWN( NumArg(MulpvOp) == 2 );
00089 
00090                         // put operand addresses in tape
00091                         size_t p = tape->Rec_.PutPar(left);
00092                         tape->Rec_.PutArg(p, right.taddr_);
00093                         // put operator in the tape
00094                         taddr_ = tape->Rec_.PutOp(MulpvOp);
00095                         // make this a variable
00096                         id_ = tape_id;
00097                 }
00098         }
00099         return *this;
00100 }
00101 
00102 CPPAD_FOLD_ASSIGNMENT_OPERATOR(*=)
00103 
00104 } // END CppAD namespace
00105 
00106 # endif