CppAD: A C++ Algorithmic Differentiation Package 20110419
|
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