source: trunk/cppad/local/pow_op.hpp @ 3301

Last change on this file since 3301 was 3301, checked in by bradbell, 6 years ago

merge in multiple forward direcitons from branches/forward_dir

  • Property svn:keywords set to Id
File size: 16.9 KB
Line 
1/* $Id: pow_op.hpp 3301 2014-05-24 05:20:21Z bradbell $ */
2# ifndef CPPAD_POW_OP_INCLUDED
3# define CPPAD_POW_OP_INCLUDED
4
5/* --------------------------------------------------------------------------
6CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-14 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
16namespace CppAD { // BEGIN_CPPAD_NAMESPACE
17/*!
18\file pow_op.hpp
19Forward and reverse mode calculations for z = pow(x, y).
20*/
21
22// --------------------------- Powvv -----------------------------------------
23/*!
24Compute forward mode Taylor coefficients for result of op = PowvvOp.
25
26In the documentation below,
27this operations is for the case where both x and y are variables
28and the argument \a parameter is not used.
29
30\copydetails forward_pow_op
31*/
32
33template <class Base>
34inline void forward_powvv_op(
35        size_t        p           , 
36        size_t        q           , 
37        size_t        i_z         ,
38        const addr_t* arg         ,
39        const Base*   parameter   ,
40        size_t        cap_order   ,
41        Base*         taylor      )
42{
43        // convert from final result to first result
44        i_z -= 2; // 2 = NumRes(PowvvOp) - 1;
45
46        // check assumptions
47        CPPAD_ASSERT_UNKNOWN( NumArg(PowvvOp) == 2 );
48        CPPAD_ASSERT_UNKNOWN( NumRes(PowvvOp) == 3 );
49        CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < i_z );
50        CPPAD_ASSERT_UNKNOWN( size_t(arg[1]) < i_z );
51        CPPAD_ASSERT_UNKNOWN( q < cap_order );
52        CPPAD_ASSERT_UNKNOWN( p <= q );
53
54        // z_0 = log(x)
55        forward_log_op(p, q, i_z, arg[0], cap_order, taylor);
56
57        // z_1 = z_0 * y
58        addr_t adr[2];
59        adr[0] = i_z;
60        adr[1] = arg[1];
61        forward_mulvv_op(p, q, i_z+1, adr, parameter, cap_order, taylor);
62
63        // z_2 = exp(z_1)
64        // final result for zero order case is exactly the same as for Base
65        if( p == 0 )
66        {       // Taylor coefficients corresponding to arguments and result
67                Base* x   = taylor + arg[0]  * cap_order;
68                Base* y   = taylor + arg[1]  * cap_order;
69                Base* z_2 = taylor + (i_z+2) * cap_order;
70
71                z_2[0] = pow(x[0], y[0]);
72                p++;
73        }
74        if( p <= q )
75                forward_exp_op(p, q, i_z+2, i_z+1, cap_order, taylor);
76}
77/*!
78Multiple directions forward mode Taylor coefficients for op = PowvvOp.
79
80The C++ source code corresponding to this operation is
81\verbatim
82        z = pow(x, y)
83\endverbatim
84In the documentation below,
85this operations is for the case where x is a variable and y is a parameter.
86
87\copydetails forward_pow_op_dir
88*/
89
90template <class Base>
91inline void forward_powvv_op_dir(
92        size_t        q           , 
93        size_t        r           , 
94        size_t        i_z         ,
95        const addr_t* arg         ,
96        const Base*   parameter   ,
97        size_t        cap_order   ,
98        Base*         taylor      )
99{
100        // convert from final result to first result
101        i_z -= 2; // 2 = NumRes(PowvvOp) - 1
102
103        // check assumptions
104        CPPAD_ASSERT_UNKNOWN( NumArg(PowvvOp) == 2 );
105        CPPAD_ASSERT_UNKNOWN( NumRes(PowvvOp) == 3 );
106        CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < i_z );
107        CPPAD_ASSERT_UNKNOWN( 0 < q );
108        CPPAD_ASSERT_UNKNOWN( q < cap_order );
109
110        // z_0 = log(x)
111        forward_log_op_dir(q, r, i_z, arg[0], cap_order, taylor);
112
113        // z_1 = y * z_0
114        addr_t adr[2];
115        adr[0] = i_z;
116        adr[1] = arg[1];
117        forward_mulvv_op_dir(q, r, i_z+1, adr, parameter, cap_order, taylor);
118
119        // z_2 = exp(z_1)
120        forward_exp_op_dir(q, r, i_z+2, i_z+1, cap_order, taylor);
121}
122/*!
123Compute zero order forward mode Taylor coefficients for result of op = PowvvOp.
124
125The C++ source code corresponding to this operation is
126\verbatim
127        z = pow(x, y)
128\endverbatim
129In the documentation below,
130this operations is for the case where both x and y are variables
131and the argument \a parameter is not used.
132
133\copydetails forward_pow_op_0
134*/
135
136template <class Base>
137inline void forward_powvv_op_0(
138        size_t        i_z         ,
139        const addr_t* arg         ,
140        const Base*   parameter   ,
141        size_t        cap_order   ,
142        Base*         taylor      )
143{
144        // convert from final result to first result
145        i_z -= 2; // NumRes(PowvvOp) - 1;
146
147        // check assumptions
148        CPPAD_ASSERT_UNKNOWN( NumArg(PowvvOp) == 2 );
149        CPPAD_ASSERT_UNKNOWN( NumRes(PowvvOp) == 3 );
150        CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < i_z );
151        CPPAD_ASSERT_UNKNOWN( size_t(arg[1]) < i_z );
152
153        // Taylor coefficients corresponding to arguments and result
154        Base* x   = taylor + arg[0] * cap_order;
155        Base* y   = taylor + arg[1] * cap_order;
156        Base* z_0 = taylor + i_z    * cap_order;
157        Base* z_1 = z_0    +          cap_order;
158        Base* z_2 = z_1    +          cap_order;
159
160        z_0[0] = log( x[0] );
161        z_1[0] = z_0[0] * y[0];
162        z_2[0] = pow(x[0], y[0]);
163
164}
165
166/*!
167Compute reverse mode partial derivatives for result of op = PowvvOp.
168
169The C++ source code corresponding to this operation is
170\verbatim
171        z = pow(x, y)
172\endverbatim
173In the documentation below,
174this operations is for the case where both x and y are variables
175and the argument \a parameter is not used.
176
177\copydetails reverse_pow_op
178*/
179
180template <class Base>
181inline void reverse_powvv_op(
182        size_t        d           , 
183        size_t        i_z         ,
184        const addr_t* arg         ,
185        const Base*   parameter   ,
186        size_t        cap_order   ,
187        const Base*   taylor      ,
188        size_t        nc_partial  ,
189        Base*         partial     )
190{
191        // convert from final result to first result
192        i_z -= 2; // NumRes(PowvvOp) - 1;
193
194        // check assumptions
195        CPPAD_ASSERT_UNKNOWN( NumArg(PowvvOp) == 2 );
196        CPPAD_ASSERT_UNKNOWN( NumRes(PowvvOp) == 3 );
197        CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < i_z );
198        CPPAD_ASSERT_UNKNOWN( size_t(arg[1]) < i_z );
199        CPPAD_ASSERT_UNKNOWN( d < cap_order );
200        CPPAD_ASSERT_UNKNOWN( d < nc_partial );
201
202        // z_2 = exp(z_1)
203        reverse_exp_op(
204                d, i_z+2, i_z+1, cap_order, taylor, nc_partial, partial
205        );
206
207        // z_1 = z_0 * y
208        addr_t adr[2];
209        adr[0] = i_z;
210        adr[1] = arg[1];
211        reverse_mulvv_op(
212        d, i_z+1, adr, parameter, cap_order, taylor, nc_partial, partial
213        );
214
215        // z_0 = log(x)
216        reverse_log_op(
217                d, i_z, arg[0], cap_order, taylor, nc_partial, partial
218        );
219}
220
221// --------------------------- Powpv -----------------------------------------
222/*!
223Compute forward mode Taylor coefficients for result of op = PowpvOp.
224
225The C++ source code corresponding to this operation is
226\verbatim
227        z = pow(x, y)
228\endverbatim
229In the documentation below,
230this operations is for the case where x is a parameter and y is a variable.
231
232\copydetails forward_pow_op
233*/
234
235template <class Base>
236inline void forward_powpv_op(
237        size_t        p           , 
238        size_t        q           , 
239        size_t        i_z         ,
240        const addr_t* arg         ,
241        const Base*   parameter   ,
242        size_t        cap_order   ,
243        Base*         taylor      )
244{
245        // convert from final result to first result
246        i_z -= 2; // 2 = NumRes(PowpvOp) - 1;
247
248        // check assumptions
249        CPPAD_ASSERT_UNKNOWN( NumArg(PowpvOp) == 2 );
250        CPPAD_ASSERT_UNKNOWN( NumRes(PowpvOp) == 3 );
251        CPPAD_ASSERT_UNKNOWN( size_t(arg[1]) < i_z );
252        CPPAD_ASSERT_UNKNOWN( q < cap_order );
253        CPPAD_ASSERT_UNKNOWN( p <= q );
254
255        // Taylor coefficients corresponding to arguments and result
256        Base* z_0 = taylor + i_z    * cap_order;
257
258        // z_0 = log(x)
259        Base x    = parameter[ arg[0] ];
260        size_t d;
261        for(d = p; d <= q; d++)
262        {       if( d == 0 )
263                        z_0[d] = log(x);
264                else    z_0[d] = Base(0);
265        }
266
267        // z_1 = z_0 * y
268        addr_t adr[2];
269        // offset of z_i in taylor (as if it were a parameter); i.e., log(x)
270        adr[0] = i_z * cap_order; 
271        // offset of y in taylor (as a variable)
272        adr[1] = arg[1];
273
274        // Trick: use taylor both for the parameter vector and variable values
275        forward_mulpv_op(p, q, i_z+1, adr, taylor, cap_order, taylor);
276
277        // z_2 = exp(z_1)
278        // zero order case exactly same as Base type operation
279        if( p == 0 )
280        {       Base* y   = taylor + arg[1]  * cap_order;
281                Base* z_2 = taylor + (i_z+2) * cap_order;
282                z_2[0] = pow(x, y[0]);
283                p++;
284        }
285        if( p <= q )
286                forward_exp_op(p, q, i_z+2, i_z+1, cap_order, taylor);
287}
288/*!
289Multiple directions forward mode Taylor coefficients for op = PowpvOp.
290
291The C++ source code corresponding to this operation is
292\verbatim
293        z = pow(x, y)
294\endverbatim
295In the documentation below,
296this operations is for the case where x is a parameter and y is a variable.
297
298\copydetails forward_pow_op_dir
299*/
300
301template <class Base>
302inline void forward_powpv_op_dir(
303        size_t        q           , 
304        size_t        r           , 
305        size_t        i_z         ,
306        const addr_t* arg         ,
307        const Base*   parameter   ,
308        size_t        cap_order   ,
309        Base*         taylor      )
310{       
311        // convert from final result to first result
312        i_z -= 2; // 2 = NumRes(PowpvOp) - 1;
313
314        // check assumptions
315        CPPAD_ASSERT_UNKNOWN( NumArg(PowpvOp) == 2 );
316        CPPAD_ASSERT_UNKNOWN( NumRes(PowpvOp) == 3 );
317        CPPAD_ASSERT_UNKNOWN( size_t(arg[1]) < i_z );
318        CPPAD_ASSERT_UNKNOWN( 0 < q );
319        CPPAD_ASSERT_UNKNOWN( q < cap_order );
320
321        // Taylor coefficients corresponding to arguments and result
322        size_t num_taylor_per_var = (cap_order-1) * r + 1;
323        Base* z_0 = taylor + i_z * num_taylor_per_var;
324
325        // z_0 = log(x)
326        size_t m  = (q-1) * r + 1;
327        for(size_t ell = 0; ell < r; ell++)
328                z_0[m+ell] = Base(0);
329
330        // z_1 = z_0 * y
331        addr_t adr[2];
332        // offset of z_0 in taylor (as if it were a parameter); i.e., log(x)
333        adr[0] = i_z * num_taylor_per_var;
334        // ofset of y in taylor (as a variable)
335        adr[1] = arg[1];
336
337        // Trick: use taylor both for the parameter vector and variable values
338        forward_mulpv_op_dir(q, r, i_z+1, adr, taylor, cap_order, taylor);
339
340        // z_2 = exp(z_1)
341        forward_exp_op_dir(q, r, i_z+2, i_z+1, cap_order, taylor);
342}
343/*!
344Compute zero order forward mode Taylor coefficient for result of op = PowpvOp.
345
346The C++ source code corresponding to this operation is
347\verbatim
348        z = pow(x, y)
349\endverbatim
350In the documentation below,
351this operations is for the case where x is a parameter and y is a variable.
352
353\copydetails forward_pow_op_0
354*/
355
356template <class Base>
357inline void forward_powpv_op_0(
358        size_t        i_z         ,
359        const addr_t* arg         ,
360        const Base*   parameter   ,
361        size_t        cap_order   ,
362        Base*         taylor      )
363{
364        // convert from final result to first result
365        i_z -= 2; // NumRes(PowpvOp) - 1;
366
367        // check assumptions
368        CPPAD_ASSERT_UNKNOWN( NumArg(PowpvOp) == 2 );
369        CPPAD_ASSERT_UNKNOWN( NumRes(PowpvOp) == 3 );
370        CPPAD_ASSERT_UNKNOWN( size_t(arg[1]) < i_z );
371
372        // Paraemter value
373        Base x = parameter[ arg[0] ];
374
375        // Taylor coefficients corresponding to arguments and result
376        Base* y   = taylor + arg[1] * cap_order;
377        Base* z_0 = taylor + i_z    * cap_order;
378        Base* z_1 = z_0    +          cap_order;
379        Base* z_2 = z_1    +          cap_order;
380
381        // z_0 = log(x)
382        z_0[0] = log(x);
383
384        // z_1 = z_0 * y
385        z_1[0] = z_0[0] * y[0];
386
387        // z_2 = exp(z_1)
388        // zero order case exactly same as Base type operation
389        z_2[0] = pow(x, y[0]);
390}
391
392/*!
393Compute reverse mode partial derivative for result of op = PowpvOp.
394
395The C++ source code corresponding to this operation is
396\verbatim
397        z = pow(x, y)
398\endverbatim
399In the documentation below,
400this operations is for the case where x is a parameter and y is a variable.
401
402\copydetails reverse_pow_op
403*/
404
405template <class Base>
406inline void reverse_powpv_op(
407        size_t        d           , 
408        size_t        i_z         ,
409        const addr_t* arg         ,
410        const Base*   parameter   ,
411        size_t        cap_order   ,
412        const Base*   taylor      ,
413        size_t        nc_partial  ,
414        Base*         partial     )
415{
416        // convert from final result to first result
417        i_z -= 2; // NumRes(PowpvOp) - 1;
418
419        // check assumptions
420        CPPAD_ASSERT_UNKNOWN( NumArg(PowvvOp) == 2 );
421        CPPAD_ASSERT_UNKNOWN( NumRes(PowvvOp) == 3 );
422        CPPAD_ASSERT_UNKNOWN( size_t(arg[1]) < i_z );
423        CPPAD_ASSERT_UNKNOWN( d < cap_order );
424        CPPAD_ASSERT_UNKNOWN( d < nc_partial );
425
426        // z_2 = exp(z_1)
427        reverse_exp_op(
428                d, i_z+2, i_z+1, cap_order, taylor, nc_partial, partial
429        );
430
431        // z_1 = z_0 * y
432        addr_t adr[2];
433        adr[0] = i_z * cap_order; // offset of z_0[0] in taylor
434        adr[1] = arg[1];          // index of y in taylor and partial
435        // use taylor both for parameter and variable values
436        reverse_mulpv_op(
437                d, i_z+1, adr, taylor, cap_order, taylor, nc_partial, partial
438        );
439
440        // z_0 = log(x)
441        // x is a parameter
442}
443
444// --------------------------- Powvp -----------------------------------------
445/*!
446Compute forward mode Taylor coefficients for result of op = PowvpOp.
447
448The C++ source code corresponding to this operation is
449\verbatim
450        z = pow(x, y)
451\endverbatim
452In the documentation below,
453this operations is for the case where x is a variable and y is a parameter.
454
455\copydetails forward_pow_op
456*/
457
458template <class Base>
459inline void forward_powvp_op(
460        size_t        p           , 
461        size_t        q           , 
462        size_t        i_z         ,
463        const addr_t* arg         ,
464        const Base*   parameter   ,
465        size_t        cap_order   ,
466        Base*         taylor      )
467{
468        // convert from final result to first result
469        i_z -= 2; // 2 = NumRes(PowvpOp) - 1
470
471        // check assumptions
472        CPPAD_ASSERT_UNKNOWN( NumArg(PowvpOp) == 2 );
473        CPPAD_ASSERT_UNKNOWN( NumRes(PowvpOp) == 3 );
474        CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < i_z );
475        CPPAD_ASSERT_UNKNOWN( q < cap_order );
476        CPPAD_ASSERT_UNKNOWN( p <= q );
477
478        // z_0 = log(x)
479        forward_log_op(p, q, i_z, arg[0], cap_order, taylor);
480
481        // z_1 = y * z_0
482        addr_t adr[2];
483        adr[0] = arg[1];
484        adr[1] = i_z;
485        forward_mulpv_op(p, q, i_z+1, adr, parameter, cap_order, taylor);
486
487        // z_2 = exp(z_1)
488        // zero order case exactly same as Base type operation
489        if( p == 0 )
490        {       Base* z_2 = taylor + (i_z+2) * cap_order;
491                Base* x   = taylor + arg[0] * cap_order;
492                Base  y   = parameter[ arg[1] ];
493                z_2[0]  = pow(x[0], y);
494                p++;
495        }
496        if( p <= q )
497                forward_exp_op(p, q, i_z+2, i_z+1, cap_order, taylor);
498}
499/*!
500Multiple directions forward mode Taylor coefficients for op = PowvpOp.
501
502The C++ source code corresponding to this operation is
503\verbatim
504        z = pow(x, y)
505\endverbatim
506In the documentation below,
507this operations is for the case where x is a variable and y is a parameter.
508
509\copydetails forward_pow_op_dir
510*/
511
512template <class Base>
513inline void forward_powvp_op_dir(
514        size_t        q           , 
515        size_t        r           , 
516        size_t        i_z         ,
517        const addr_t* arg         ,
518        const Base*   parameter   ,
519        size_t        cap_order   ,
520        Base*         taylor      )
521{
522        // convert from final result to first result
523        i_z -= 2; // 2 = NumRes(PowvpOp) - 1
524
525        // check assumptions
526        CPPAD_ASSERT_UNKNOWN( NumArg(PowvpOp) == 2 );
527        CPPAD_ASSERT_UNKNOWN( NumRes(PowvpOp) == 3 );
528        CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < i_z );
529        CPPAD_ASSERT_UNKNOWN( 0 < q );
530        CPPAD_ASSERT_UNKNOWN( q < cap_order );
531
532        // z_0 = log(x)
533        forward_log_op_dir(q, r, i_z, arg[0], cap_order, taylor);
534
535        // z_1 = y * z_0
536        addr_t adr[2];
537        adr[0] = arg[1];
538        adr[1] = i_z;
539        forward_mulpv_op_dir(q, r, i_z+1, adr, parameter, cap_order, taylor);
540
541        // z_2 = exp(z_1)
542        forward_exp_op_dir(q, r, i_z+2, i_z+1, cap_order, taylor);
543}
544
545/*!
546Compute zero order forward mode Taylor coefficients for result of op = PowvpOp.
547
548The C++ source code corresponding to this operation is
549\verbatim
550        z = pow(x, y)
551\endverbatim
552In the documentation below,
553this operations is for the case where x is a variable and y is a parameter.
554
555\copydetails forward_pow_op_0
556*/
557
558template <class Base>
559inline void forward_powvp_op_0(
560        size_t        i_z         ,
561        const addr_t* arg         ,
562        const Base*   parameter   ,
563        size_t        cap_order   ,
564        Base*         taylor      )
565{
566        // convert from final result to first result
567        i_z -= 2; // NumRes(PowvpOp) - 1;
568
569        // check assumptions
570        CPPAD_ASSERT_UNKNOWN( NumArg(PowvpOp) == 2 );
571        CPPAD_ASSERT_UNKNOWN( NumRes(PowvpOp) == 3 );
572        CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < i_z );
573
574        // Paraemter value
575        Base y = parameter[ arg[1] ];
576
577        // Taylor coefficients corresponding to arguments and result
578        Base* x   = taylor + arg[0] * cap_order;
579        Base* z_0 = taylor + i_z    * cap_order;
580        Base* z_1 = z_0    +          cap_order;
581        Base* z_2 = z_1    +          cap_order;
582
583        // z_0 = log(x)
584        z_0[0] = log(x[0]);
585
586        // z_1 = z_0 * y
587        z_1[0] = z_0[0] * y;
588
589        // z_2 = exp(z_1)
590        // zero order case exactly same as Base type operation
591        z_2[0] = pow(x[0], y);
592}
593
594/*!
595Compute reverse mode partial derivative for result of op = PowvpOp.
596
597The C++ source code corresponding to this operation is
598\verbatim
599        z = pow(x, y)
600\endverbatim
601In the documentation below,
602this operations is for the case where x is a variable and y is a parameter.
603
604\copydetails reverse_pow_op
605*/
606
607template <class Base>
608inline void reverse_powvp_op(
609        size_t        d           , 
610        size_t        i_z         ,
611        const addr_t* arg         ,
612        const Base*   parameter   ,
613        size_t        cap_order   ,
614        const Base*   taylor      ,
615        size_t        nc_partial  ,
616        Base*         partial     )
617{
618        // convert from final result to first result
619        i_z -= 2; // NumRes(PowvpOp) - 1;
620
621        // check assumptions
622        CPPAD_ASSERT_UNKNOWN( NumArg(PowvpOp) == 2 );
623        CPPAD_ASSERT_UNKNOWN( NumRes(PowvpOp) == 3 );
624        CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < i_z );
625        CPPAD_ASSERT_UNKNOWN( d < cap_order );
626        CPPAD_ASSERT_UNKNOWN( d < nc_partial );
627
628        // z_2 = exp(z_1)
629        reverse_exp_op(
630                d, i_z+2, i_z+1, cap_order, taylor, nc_partial, partial
631        );
632
633        // z_1 = y * z_0
634        addr_t adr[2];
635        adr[0] = arg[1];
636        adr[1] = i_z;
637        reverse_mulpv_op(
638        d, i_z+1, adr, parameter, cap_order, taylor, nc_partial, partial
639        );
640
641        // z_0 = log(x)
642        reverse_log_op(
643                d, i_z, arg[0], cap_order, taylor, nc_partial, partial
644        );
645}
646
647} // END_CPPAD_NAMESPACE
648# endif
Note: See TracBrowser for help on using the repository browser.