CppAD: A C++ Algorithmic Differentiation Package
20130102
|
00001 /* $Id$ */ 00002 # ifndef CPPAD_DIV_INCLUDED 00003 # define CPPAD_DIV_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 // BEGIN CppAD namespace 00017 namespace CppAD { 00018 00019 template <class Base> 00020 AD<Base> operator / (const AD<Base> &left , const AD<Base> &right) 00021 { 00022 // compute the Base part 00023 AD<Base> result; 00024 result.value_ = left.value_ / right.value_; 00025 CPPAD_ASSERT_UNKNOWN( Parameter(result) ); 00026 00027 // check if there is a recording in progress 00028 ADTape<Base>* tape = AD<Base>::tape_ptr(); 00029 if( tape == CPPAD_NULL ) 00030 return result; 00031 tape_id_t tape_id = tape->id_; 00032 00033 // tape_id cannot match the default value for tape_id_; i.e., 0 00034 CPPAD_ASSERT_UNKNOWN( tape_id > 0 ); 00035 bool var_left = left.tape_id_ == tape_id; 00036 bool var_right = right.tape_id_ == tape_id; 00037 00038 if( var_left ) 00039 { if( var_right ) 00040 { // result = variable / variable 00041 CPPAD_ASSERT_KNOWN( 00042 left.tape_id_ == right.tape_id_, 00043 "Dividing AD objects that are" 00044 " variables on different tapes." 00045 ); 00046 CPPAD_ASSERT_UNKNOWN( NumRes(DivvvOp) == 1 ); 00047 CPPAD_ASSERT_UNKNOWN( NumArg(DivvvOp) == 2 ); 00048 00049 // put operand addresses in tape 00050 tape->Rec_.PutArg(left.taddr_, right.taddr_); 00051 // put operator in the tape 00052 result.taddr_ = tape->Rec_.PutOp(DivvvOp); 00053 // make result a variable 00054 result.tape_id_ = tape_id; 00055 } 00056 else if( IdenticalOne(right.value_) ) 00057 { // result = variable / 1 00058 result.make_variable(left.tape_id_, left.taddr_); 00059 } 00060 else 00061 { // result = variable / parameter 00062 CPPAD_ASSERT_UNKNOWN( NumRes(DivvpOp) == 1 ); 00063 CPPAD_ASSERT_UNKNOWN( NumArg(DivvpOp) == 2 ); 00064 00065 // put operand addresses in tape 00066 addr_t p = tape->Rec_.PutPar(right.value_); 00067 tape->Rec_.PutArg(left.taddr_, p); 00068 // put operator in the tape 00069 result.taddr_ = tape->Rec_.PutOp(DivvpOp); 00070 // make result a variable 00071 result.tape_id_ = tape_id; 00072 } 00073 } 00074 else if( Variable(right) ) 00075 { if( IdenticalZero(left.value_) ) 00076 { // result = 0 / variable 00077 } 00078 else 00079 { // result = parameter / variable 00080 CPPAD_ASSERT_UNKNOWN( NumRes(DivpvOp) == 1 ); 00081 CPPAD_ASSERT_UNKNOWN( NumArg(DivpvOp) == 2 ); 00082 00083 // put operand addresses in tape 00084 addr_t p = tape->Rec_.PutPar(left.value_); 00085 tape->Rec_.PutArg(p, right.taddr_); 00086 // put operator in the tape 00087 result.taddr_ = tape->Rec_.PutOp(DivpvOp); 00088 // make result a variable 00089 result.tape_id_ = tape_id; 00090 } 00091 } 00092 return result; 00093 } 00094 00095 // convert other cases into the case above 00096 CPPAD_FOLD_AD_VALUED_BINARY_OPERATOR(/) 00097 00098 00099 } // END CppAD namespace 00100 00101 # endif