source: branches/cache/cppad/local/pow_op.hpp @ 3324

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

merge trunk changes into cache

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