source: trunk/cppad/local/pow.hpp @ 2506

Last change on this file since 2506 was 2506, checked in by bradbell, 8 years ago

Change Licenses: CPL-1.0 -> EPL-1.0, GPL-2.0->GPL-3.0

  • Property svn:keywords set to Id
File size: 7.1 KB
Line 
1/* $Id: pow.hpp 2506 2012-10-24 19:36:49Z bradbell $ */
2# ifndef CPPAD_POW_INCLUDED
3# define CPPAD_POW_INCLUDED
4
5/* --------------------------------------------------------------------------
6CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-12 Bradley M. Bell
7
8CppAD is distributed under multiple licenses. This distribution is under
9the terms of the
10                    Eclipse Public License Version 1.0.
11
12A copy of this license is included in the COPYING file of this distribution.
13Please visit http://www.coin-or.org/CppAD/ for information on other licenses.
14-------------------------------------------------------------------------- */
15
16/*
17$begin pow$$
18$spell
19        Vec
20        std
21        namespace
22        CppAD
23        const
24$$
25
26$index pow, AD$$
27$index exponent, AD function$$
28
29$section The AD Power Function$$
30
31$head Syntax$$
32$icode%z% = pow(%x%, %y%)%$$
33
34$head See Also$$
35$cref pow_int$$
36
37
38$head Purpose$$
39Determines the value of the power function which is defined by
40$latex \[
41        {\rm pow} (x, y) = x^y
42\] $$
43This version of the $code pow$$ function may use
44logarithms and exponentiation to compute derivatives.
45This will not work if $icode x$$ is less than or equal zero.
46If the value of $icode y$$ is an integer,
47the $cref pow_int$$ function is used to compute this value
48using only multiplication (and division if $icode y$$ is negative).
49(This will work even if $icode x$$ is less than or equal zero.)
50
51$head x$$
52The argument $icode x$$ has one of the following prototypes
53$codei%
54        const %Base%&                    %x%
55        const AD<%Base%>&                %x%
56        const VecAD<%Base%>::reference&  %x%
57%$$
58
59$head y$$
60The argument $icode y$$ has one of the following prototypes
61$codei%
62        const %Base%&                    %y%
63        const AD<%Base%>&                %y%
64        const VecAD<%Base%>::reference&  %y%
65%$$
66
67$head z$$
68If both $icode x$$ and $icode y$$ are $icode Base$$ objects,
69the result $icode z$$ is also a $icode Base$$ object.
70Otherwise, it has prototype
71$codei%
72        AD<%Base%> %z%
73%$$
74
75$head Operation Sequence$$
76This is an AD of $icode Base$$
77$cref/atomic operation/glossary/Operation/Atomic/$$
78and hence is part of the current
79AD of $icode Base$$
80$cref/operation sequence/glossary/Operation/Sequence/$$.
81
82$head Example$$
83$children%
84        example/pow.cpp
85%$$
86The file
87$cref pow.cpp$$
88is an examples and tests of this function.   
89It returns true if it succeeds and false otherwise.
90
91$end
92-------------------------------------------------------------------------------
93*/
94
95//  BEGIN CppAD namespace
96namespace CppAD {
97 
98// case where x and y are AD<Base> -----------------------------------------
99template <class Base> AD<Base> 
100pow(const AD<Base>& x, const AD<Base>& y)
101{
102        // compute the Base part
103        AD<Base> result;
104        result.value_  = pow(x.value_, y.value_);
105        CPPAD_ASSERT_UNKNOWN( Parameter(result) );
106
107        // check if there is a recording in progress
108        ADTape<Base>* tape = AD<Base>::tape_ptr();
109        if( tape == CPPAD_NULL )
110                return result;
111        tape_id_t tape_id = tape->id_;
112
113        // tape_id cannot match the default value for tape_id_; i.e., 0
114        CPPAD_ASSERT_UNKNOWN( tape_id > 0 );
115        bool var_x = x.tape_id_ == tape_id;
116        bool var_y = y.tape_id_ == tape_id;
117
118        if( var_x )
119        {       if( var_y )
120                {       // result = variable^variable
121                        CPPAD_ASSERT_UNKNOWN( NumRes(PowvvOp) == 3 );
122                        CPPAD_ASSERT_UNKNOWN( NumArg(PowvvOp) == 2 );
123
124                        // put operand addresses in tape
125                        tape->Rec_.PutArg(x.taddr_, y.taddr_);
126
127                        // put operator in the tape
128                        result.taddr_ = tape->Rec_.PutOp(PowvvOp);
129
130                        // make result a variable
131                        result.tape_id_ = tape_id;
132                }
133                else if( IdenticalZero( y.value_ ) )
134                {       // result = variable^0
135                }
136                else
137                {       // result = variable^parameter
138                        CPPAD_ASSERT_UNKNOWN( NumRes(PowvpOp) == 3 );
139                        CPPAD_ASSERT_UNKNOWN( NumArg(PowvpOp) == 2 );
140
141                        // put operand addresses in tape
142                        addr_t p = tape->Rec_.PutPar(y.value_);
143                        tape->Rec_.PutArg(x.taddr_, p);
144
145                        // put operator in the tape
146                        result.taddr_ = tape->Rec_.PutOp(PowvpOp);
147
148                        // make result a variable
149                        result.tape_id_ = tape_id;
150                }
151        }
152        else if( var_y )
153        {       if( IdenticalZero(x.value_) )
154                {       // result = 0^variable
155                }
156                else
157                {       // result = variable^parameter
158                        CPPAD_ASSERT_UNKNOWN( NumRes(PowpvOp) == 3 );
159                        CPPAD_ASSERT_UNKNOWN( NumArg(PowpvOp) == 2 );
160
161                        // put operand addresses in tape
162                        addr_t p = tape->Rec_.PutPar(x.value_);
163                        tape->Rec_.PutArg(p, y.taddr_);
164
165                        // put operator in the tape
166                        result.taddr_ = tape->Rec_.PutOp(PowpvOp);
167
168                        // make result a variable
169                        result.tape_id_ = tape_id;
170                }
171        }
172        return result;
173}
174// =========================================================================
175// Fold operations in same way as CPPAD_FOLD_AD_VALUED_BINARY_OPERATION(Op)
176// -------------------------------------------------------------------------
177// Operations with VecAD_reference<Base> and AD<Base> only
178
179template <class Base> AD<Base>
180pow(const AD<Base>& x, const VecAD_reference<Base>& y)
181{       return pow(x, y.ADBase()); }
182
183template <class Base> AD<Base> 
184pow(const VecAD_reference<Base>& x, const VecAD_reference<Base>& y) 
185{       return pow(x.ADBase(), y.ADBase()); }
186
187template <class Base> AD<Base>
188pow(const VecAD_reference<Base>& x, const AD<Base>& y)
189{       return pow(x.ADBase(), y); }
190// -------------------------------------------------------------------------
191// Operations with Base
192
193template <class Base> AD<Base>
194pow(const Base& x, const AD<Base>& y)
195{       return pow(AD<Base>(x), y); }
196
197template <class Base> AD<Base>
198pow(const Base& x, const VecAD_reference<Base>& y)
199{       return pow(AD<Base>(x), y.ADBase()); }
200
201template <class Base> AD<Base>
202pow(const AD<Base>& x, const Base& y)
203{       return pow(x, AD<Base>(y)); }
204
205template <class Base> AD<Base>
206pow(const VecAD_reference<Base>& x, const Base& y)
207{       return pow(x.ADBase(), AD<Base>(y)); }
208// -------------------------------------------------------------------------
209// Operations with double
210
211template <class Base> AD<Base>
212pow(const double& x, const AD<Base>& y)
213{       return pow(AD<Base>(x), y); }
214
215template <class Base> AD<Base>
216pow(const double& x, const VecAD_reference<Base>& y)
217{       return pow(AD<Base>(x), y.ADBase()); }
218
219template <class Base> AD<Base>
220pow(const AD<Base>& x, const double& y)
221{       return pow(x, AD<Base>(y)); }
222
223template <class Base> AD<Base>
224pow(const VecAD_reference<Base>& x, const double& y)
225{       return pow(x.ADBase(), AD<Base>(y)); }
226// -------------------------------------------------------------------------
227// Special case to avoid ambuigity when Base is double
228
229inline AD<double>
230pow(const double& x, const AD<double>& y)
231{       return pow(AD<double>(x), y); }
232
233inline AD<double>
234pow(const double& x, const VecAD_reference<double>& y)
235{       return pow(AD<double>(x), y.ADBase()); }
236
237inline AD<double>
238pow(const AD<double>& x, const double& y)
239{       return pow(x, AD<double>(y)); }
240
241inline AD<double>
242pow(const VecAD_reference<double>& x, const double& y)
243{       return pow(x.ADBase(), AD<double>(y)); }
244
245// =========================================================================
246// Fold operations for the cases where x is an int,
247// but let cppad/pow_int.hpp handle the cases where y is an int.
248// -------------------------------------------------------------------------
249template <class Base> AD<Base> pow
250(const int& x, const VecAD_reference<Base>& y)
251{       return pow(AD<Base>(x), y.ADBase()); }
252
253template <class Base> AD<Base> pow
254(const int& x, const AD<Base>& y)
255{       return pow(AD<Base>(x), y); }
256
257} // END CppAD namespace
258
259# endif
Note: See TracBrowser for help on using the repository browser.