CppAD: A C++ Algorithmic Differentiation Package 20110419
div.hpp
Go to the documentation of this file.
00001 /* $Id$ */
00002 # ifndef CPPAD_DIV_INCLUDED
00003 # define CPPAD_DIV_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> operator / (const AD<Base> &left , 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  = left.id_  == tape_id;
00028         bool var_right = right.id_ == tape_id;
00029         CPPAD_ASSERT_KNOWN(
00030                 Parameter(left) || 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         AD<Base> result;
00039         result.value_  = left.value_ / right.value_;
00040         CPPAD_ASSERT_UNKNOWN( Parameter(result) );
00041 
00042         if( var_left )
00043         {       if( var_right )
00044                 {       // result = variable / variable
00045                         CPPAD_ASSERT_KNOWN(
00046                                 left.id_ == right.id_,
00047                                 "Dividing AD objects that are"
00048                                 " variables on different tapes."
00049                         );
00050                         CPPAD_ASSERT_UNKNOWN( NumRes(DivvvOp) == 1 );
00051                         CPPAD_ASSERT_UNKNOWN( NumArg(DivvvOp) == 2 );
00052 
00053                         // put operand addresses in tape
00054                         tape->Rec_.PutArg(left.taddr_, right.taddr_);
00055                         // put operator in the tape
00056                         result.taddr_ = tape->Rec_.PutOp(DivvvOp);
00057                         // make result a variable
00058                         result.id_ = tape_id;
00059                 }
00060                 else if( IdenticalOne(right.value_) )
00061                 {       // result = variable / 1
00062                         result.make_variable(left.id_, left.taddr_);
00063                 }
00064                 else
00065                 {       // result = variable / parameter
00066                         CPPAD_ASSERT_UNKNOWN( NumRes(DivvpOp) == 1 );
00067                         CPPAD_ASSERT_UNKNOWN( NumArg(DivvpOp) == 2 );
00068 
00069                         // put operand addresses in tape
00070                         size_t p = tape->Rec_.PutPar(right.value_);
00071                         tape->Rec_.PutArg(left.taddr_, p);
00072                         // put operator in the tape
00073                         result.taddr_ = tape->Rec_.PutOp(DivvpOp);
00074                         // make result a variable
00075                         result.id_ = tape_id;
00076                 }
00077         }
00078         else if( Variable(right) )
00079         {       if( IdenticalZero(left.value_) )
00080                 {       // result = 0 / variable
00081                 }
00082                 else
00083                 {       // result = parameter / variable
00084                         CPPAD_ASSERT_UNKNOWN( NumRes(DivpvOp) == 1 );
00085                         CPPAD_ASSERT_UNKNOWN( NumArg(DivpvOp) == 2 );
00086 
00087                         // put operand addresses in tape
00088                         size_t p = tape->Rec_.PutPar(left.value_);
00089                         tape->Rec_.PutArg(p, right.taddr_);
00090                         // put operator in the tape
00091                         result.taddr_ = tape->Rec_.PutOp(DivpvOp);
00092                         // make result a variable
00093                         result.id_ = tape_id;
00094                 }
00095         }
00096         return result;
00097 }
00098 
00099 // convert other cases into the case above
00100 CPPAD_FOLD_AD_VALUED_BINARY_OPERATOR(/)
00101 
00102 
00103 } // END CppAD namespace
00104 
00105 # endif