source: branches/opt_cond_exp/cppad/local/forward0sweep.hpp @ 2968

Last change on this file since 2968 was 2968, checked in by bradbell, 7 years ago

First version that actually calls forward_cskip_0, not yet actually skipping
operations.

  • Property svn:keywords set to Id
File size: 18.7 KB
Line 
1/* $Id: forward0sweep.hpp 2968 2013-10-18 19:41:48Z bradbell $ */
2# ifndef CPPAD_FORWARD0SWEEP_INCLUDED
3# define CPPAD_FORWARD0SWEEP_INCLUDED
4
5/* --------------------------------------------------------------------------
6CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-13 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\defgroup forward0sweep_hpp forward0sweep.hpp
19\{
20\file forward0sweep.hpp
21Compute zero order forward mode Taylor coefficients.
22*/
23
24/*
25\def CPPAD_ATOMIC_CALL
26This avoids warnings when NDEBUG is defined and user_ok is not used.
27If \c NDEBUG is defined, this resolves to
28\code
29        user_atom->forward
30\endcode
31otherwise, it respolves to
32\code
33        user_ok = user_atom->forward
34\endcode
35This maco is undefined at the end of this file to facillitate is
36use with a different definition in other files.
37*/
38# ifdef NDEBUG
39# define CPPAD_ATOMIC_CALL user_atom->forward
40# else
41# define CPPAD_ATOMIC_CALL user_ok = user_atom->forward
42# endif
43
44/*!
45\def CPPAD_FORWARD0SWEEP_TRACE
46This value is either zero or one.
47Zero is the normal operational value.
48If it is one, a trace of every forward0sweep computation is printed.
49(Note that forward0sweep is not used if CPPAD_USE_FORWARD0SWEEP is zero).
50*/
51# define CPPAD_FORWARD0SWEEP_TRACE 0
52
53/*!
54Compute zero order forward mode Taylor coefficients.
55
56\tparam Base
57The type used during the forward mode computations; i.e., the corresponding
58recording of operations used the type \c AD<Base>.
59
60\param s_out
61Is the stream where output corresponding to \c PriOp operations will
62be written.
63
64\param print
65If \a print is false,
66suppress the output that is otherwise generated by the c PriOp instructions.
67
68\param n
69is the number of independent variables on the tape.
70
71\param numvar
72is the total number of variables on the tape.
73This is also equal to the number of rows in the matrix \a Taylor; i.e.,
74\a Rec->num_rec_var().
75
76\param Rec
77The information stored in \a Rec
78is a recording of the operations corresponding to the function
79\f[
80        F : {\bf R}^n \rightarrow {\bf R}^m
81\f]
82where \f$ n \f$ is the number of independent variables and
83\f$ m \f$ is the number of dependent variables.
84\n
85\n
86The object \a Rec is effectly constant.
87There are two exceptions to this.
88The first exception is that while palying back the tape
89the object \a Rec holds information about the current location
90with in the tape and this changes during palyback.
91The second exception is the fact that the
92zero order ( \a d = 0 ) versions of the VecAD operators LdpOp and LdvOp
93modify the corresponding \a op_arg values returned by
94\ref player::next_forward and \ref player::next_reverse; see the
95\link load_op.hpp LdpOp and LdvOp \endlink operations.
96
97\param J
98Is the number of columns in the coefficient matrix \a Taylor.
99This must be greater than or equal one.
100
101\param Taylor
102\b Input: For j = 1 , ... , \a n,
103\a Taylor [ j * J + 0 ]
104variable with index i on the tape
105(independent variable with index (j-1) in the independent variable vector).
106\n
107\n
108\b Output: For i = \a n + 1, ... , \a numvar - 1,
109\a Taylor [ i * J + 0 ]
110is the zero order Taylor coefficient for the variable with
111index i on the tape.
112
113\a return
114The return value is equal to the number of ComOp operations
115that have a different result from when the information in
116\a Rec was recorded.
117(Note that if NDEBUG is true, there are no ComOp operations
118in Rec and hence this return value is always zero.)
119
120\param cskip_var
121Is a vector with size \c numvar,
122the input value of the elements does not matter.
123Upon return, if cskip_var[i] is true, the value of variable with index i
124does not affect any of the dependent variable (given the value
125of the independent variables).
126*/
127
128template <class Base>
129size_t forward0sweep(
130        std::ostream&         s_out,
131        bool                  print,
132        size_t                n,
133        size_t                numvar,
134        player<Base>         *Rec,
135        size_t                J,
136        Base                 *Taylor,
137        CppAD::vector<bool>&  cskip_var
138)
139{       CPPAD_ASSERT_UNKNOWN( J >= 1 );
140
141        // op code for current instruction
142        OpCode           op;
143
144        // index for current instruction
145        size_t         i_op;
146
147        // next variables
148        size_t        i_var;
149
150        // constant and non-constant version of the operation argument indices
151        addr_t*         non_const_arg;
152        const addr_t*   arg = CPPAD_NULL;
153
154        // initialize the comparision operator (ComOp) counter
155        size_t compareCount = 0;
156
157        // This is an order zero calculation, initialize vector indices
158        pod_vector<size_t> VectorInd;  // address for each element
159        pod_vector<bool>   VectorVar;  // is element a variable
160        size_t  i = Rec->num_rec_vecad_ind();
161        if( i > 0 )
162        {       VectorInd.extend(i);
163                VectorVar.extend(i);
164                while(i--)
165                {       VectorInd[i] = Rec->GetVecInd(i);
166                        VectorVar[i] = false;
167                }
168        }
169
170        // work space used by UserOp.
171        const size_t user_q = 0;     // lowest order
172        const size_t user_p = 0;     // highest order
173        vector<bool> user_vx;        // empty vecotor
174        vector<bool> user_vy;        // empty vecotor
175        vector<Base> user_tx;        // argument vector Taylor coefficients
176        vector<Base> user_ty;        // result vector Taylor coefficients
177        size_t user_index = 0;       // indentifier for this atomic operation
178        size_t user_id    = 0;       // user identifier for this call to operator
179        size_t user_i     = 0;       // index in result vector
180        size_t user_j     = 0;       // index in argument vector
181        size_t user_m     = 0;       // size of result vector
182        size_t user_n     = 0;       // size of arugment vector
183        //
184        atomic_base<Base>* user_atom = CPPAD_NULL; // user's atomic op calculator
185# ifndef NDEBUG
186        bool               user_ok   = false;      // atomic op return value
187# endif
188        //
189        // next expected operator in a UserOp sequence
190        enum { user_start, user_arg, user_ret, user_end } user_state = user_start;
191
192        // check numvar argument
193        CPPAD_ASSERT_UNKNOWN( Rec->num_rec_var() == numvar );
194
195        // length of the parameter vector (used by CppAD assert macros)
196        const size_t num_par = Rec->num_rec_par();
197
198        // length of the text vector (used by CppAD assert macros)
199        const size_t num_text = Rec->num_rec_text();
200
201        // pointer to the beginning of the parameter vector
202        const Base* parameter = CPPAD_NULL;
203        if( num_par > 0 )
204                parameter = Rec->GetPar();
205
206        // pointer to the beginning of the text vector
207        const char* text = CPPAD_NULL;
208        if( num_text > 0 )
209                text = Rec->GetTxt(0);
210
211        // skip the BeginOp at the beginning of the recording
212        Rec->start_forward(op, arg, i_op, i_var);
213        CPPAD_ASSERT_UNKNOWN( op == BeginOp );
214# if CPPAD_FORWARD0SWEEP_TRACE
215        std::cout << std::endl;
216# endif
217        while(op != EndOp)
218        {
219                // this op
220                Rec->next_forward(op, arg, i_op, i_var);
221# ifndef NDEBUG
222                if( i_op <= n )
223                {       CPPAD_ASSERT_UNKNOWN((op == InvOp) | (op == BeginOp));
224                }
225                else    CPPAD_ASSERT_UNKNOWN((op != InvOp) & (op != BeginOp));
226# endif
227
228                // action to take depends on the case
229                switch( op )
230                {
231                        case AbsOp:
232                        forward_abs_op_0(i_var, arg[0], J, Taylor);
233                        break;
234                        // -------------------------------------------------
235
236                        case AddvvOp:
237                        forward_addvv_op_0(i_var, arg, parameter, J, Taylor);
238                        break;
239                        // -------------------------------------------------
240
241                        case AddpvOp:
242                        CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par );
243                        forward_addpv_op_0(i_var, arg, parameter, J, Taylor);
244                        break;
245                        // -------------------------------------------------
246
247                        case AcosOp:
248                        // sqrt(1 - x * x), acos(x)
249                        CPPAD_ASSERT_UNKNOWN( i_var < numvar  );
250                        forward_acos_op_0(i_var, arg[0], J, Taylor);
251                        break;
252                        // -------------------------------------------------
253
254                        case AsinOp:
255                        // sqrt(1 - x * x), asin(x)
256                        CPPAD_ASSERT_UNKNOWN( i_var < numvar  );
257                        forward_asin_op_0(i_var, arg[0], J, Taylor);
258                        break;
259                        // -------------------------------------------------
260
261                        case AtanOp:
262                        // 1 + x * x, atan(x)
263                        CPPAD_ASSERT_UNKNOWN( i_var < numvar  );
264                        forward_atan_op_0(i_var, arg[0], J, Taylor);
265                        break;
266                        // -------------------------------------------------
267
268                        case CSkipOp:
269                        // CSumOp has a variable number of arguments and
270                        // next_forward thinks it one has one argument.
271                        // we must inform next_forward of this special case.
272                        Rec->forward_cskip(op, arg, i_op, i_var);
273                        forward_cskip_op_0(
274                                i_var, arg, num_par, parameter, J, Taylor, cskip_var
275                        );
276                        break;
277                        // -------------------------------------------------
278
279                        case CSumOp:
280                        // CSumOp has a variable number of arguments and
281                        // next_forward thinks it one has one argument.
282                        // we must inform next_forward of this special case.
283                        Rec->forward_csum(op, arg, i_op, i_var);
284                        forward_csum_op(
285                                0, 0, i_var, arg, num_par, parameter, J, Taylor
286                        );
287                        break;
288
289                        // -------------------------------------------------
290                        case CExpOp:
291                        // Use the general case with d == 0
292                        // (could create an optimzied verison for this case)
293                        forward_cond_op_0(
294                                i_var, arg, num_par, parameter, J, Taylor
295                        );
296                        break;
297                        // ---------------------------------------------------
298                        case ComOp:
299                        forward_comp_op_0(
300                        compareCount, arg, num_par, parameter, J, Taylor
301                        );
302                        break;
303                        // ---------------------------------------------------
304
305                        case CosOp:
306                        // sin(x), cos(x)
307                        CPPAD_ASSERT_UNKNOWN( i_var < numvar  );
308                        forward_cos_op_0(i_var, arg[0], J, Taylor);
309                        break;
310                        // ---------------------------------------------------
311
312                        case CoshOp:
313                        // sinh(x), cosh(x)
314                        CPPAD_ASSERT_UNKNOWN( i_var < numvar  );
315                        forward_cosh_op_0(i_var, arg[0], J, Taylor);
316                        break;
317                        // -------------------------------------------------
318
319                        case DisOp:
320                        forward_dis_op_0(i_var, arg, J, Taylor);
321                        break;
322                        // -------------------------------------------------
323
324                        case DivvvOp:
325                        forward_divvv_op_0(i_var, arg, parameter, J, Taylor);
326                        break;
327                        // -------------------------------------------------
328
329                        case DivpvOp:
330                        CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par );
331                        forward_divpv_op_0(i_var, arg, parameter, J, Taylor);
332                        break;
333                        // -------------------------------------------------
334
335                        case DivvpOp:
336                        CPPAD_ASSERT_UNKNOWN( size_t(arg[1]) < num_par );
337                        forward_divvp_op_0(i_var, arg, parameter, J, Taylor);
338                        break;
339                        // -------------------------------------------------
340
341                        case EndOp:
342                        CPPAD_ASSERT_NARG_NRES(op, 0, 0);
343                        break;
344                        // -------------------------------------------------
345
346                        case ExpOp:
347                        forward_exp_op_0(i_var, arg[0], J, Taylor);
348                        break;
349                        // -------------------------------------------------
350
351                        case InvOp:
352                        break;
353                        // -------------------------------------------------
354
355                        case LdpOp:
356                        CPPAD_ASSERT_UNKNOWN( VectorInd.size() != 0 );
357                        CPPAD_ASSERT_UNKNOWN( VectorVar.size() != 0 );
358                        non_const_arg = Rec->forward_non_const_arg();
359                        forward_load_p_op_0(
360                                i_var, 
361                                non_const_arg, 
362                                num_par, 
363                                parameter, 
364                                J, 
365                                Taylor,
366                                Rec->num_rec_vecad_ind(),
367                                VectorVar.data(),
368                                VectorInd.data()
369                        );
370                        break;
371                        // -------------------------------------------------
372
373                        case LdvOp:
374                        CPPAD_ASSERT_UNKNOWN( VectorInd.size() != 0 );
375                        CPPAD_ASSERT_UNKNOWN( VectorVar.size() != 0 );
376                        non_const_arg = Rec->forward_non_const_arg();
377                        forward_load_v_op_0(
378                                i_var, 
379                                non_const_arg, 
380                                num_par, 
381                                parameter, 
382                                J, 
383                                Taylor,
384                                Rec->num_rec_vecad_ind(),
385                                VectorVar.data(),
386                                VectorInd.data()
387                        );
388                        break;
389                        // -------------------------------------------------
390
391                        case LogOp:
392                        forward_log_op_0(i_var, arg[0], J, Taylor);
393                        break;
394                        // -------------------------------------------------
395
396                        case MulvvOp:
397                        forward_mulvv_op_0(i_var, arg, parameter, J, Taylor);
398                        break;
399                        // -------------------------------------------------
400
401                        case MulpvOp:
402                        CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par );
403                        forward_mulpv_op_0(i_var, arg, parameter, J, Taylor);
404                        break;
405                        // -------------------------------------------------
406
407                        case ParOp:
408                        forward_par_op_0(
409                                i_var, arg, num_par, parameter, J, Taylor
410                        );
411                        break;
412                        // -------------------------------------------------
413
414                        case PowvpOp:
415                        CPPAD_ASSERT_UNKNOWN( size_t(arg[1]) < num_par );
416                        forward_powvp_op_0(i_var, arg, parameter, J, Taylor);
417                        break;
418                        // -------------------------------------------------
419
420                        case PowpvOp:
421                        CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par );
422                        forward_powpv_op_0(i_var, arg, parameter, J, Taylor);
423                        break;
424                        // -------------------------------------------------
425
426                        case PowvvOp:
427                        forward_powvv_op_0(i_var, arg, parameter, J, Taylor);
428                        break;
429                        // -------------------------------------------------
430
431                        case PriOp:
432                        if( print ) forward_pri_0(s_out,
433                                i_var, arg, num_text, text, num_par, parameter, J, Taylor
434                        );
435                        break;
436                        // -------------------------------------------------
437
438                        case SignOp:
439                        // cos(x), sin(x)
440                        CPPAD_ASSERT_UNKNOWN( i_var < numvar  );
441                        forward_sign_op_0(i_var, arg[0], J, Taylor);
442                        break;
443                        // -------------------------------------------------
444
445                        case SinOp:
446                        // cos(x), sin(x)
447                        CPPAD_ASSERT_UNKNOWN( i_var < numvar  );
448                        forward_sin_op_0(i_var, arg[0], J, Taylor);
449                        break;
450                        // -------------------------------------------------
451
452                        case SinhOp:
453                        // cosh(x), sinh(x)
454                        CPPAD_ASSERT_UNKNOWN( i_var < numvar  );
455                        forward_sinh_op_0(i_var, arg[0], J, Taylor);
456                        break;
457                        // -------------------------------------------------
458
459                        case SqrtOp:
460                        forward_sqrt_op_0(i_var, arg[0], J, Taylor);
461                        break;
462                        // -------------------------------------------------
463
464                        case StppOp:
465                        forward_store_pp_op_0(
466                                i_var, 
467                                arg, 
468                                num_par, 
469                                J, 
470                                Taylor,
471                                Rec->num_rec_vecad_ind(),
472                                VectorVar.data(),
473                                VectorInd.data()
474                        );
475                        break;
476                        // -------------------------------------------------
477
478                        case StpvOp:
479                        forward_store_pv_op_0(
480                                i_var, 
481                                arg, 
482                                num_par, 
483                                J, 
484                                Taylor,
485                                Rec->num_rec_vecad_ind(),
486                                VectorVar.data(),
487                                VectorInd.data()
488                        );
489                        break;
490                        // -------------------------------------------------
491
492                        case StvpOp:
493                        forward_store_vp_op_0(
494                                i_var, 
495                                arg, 
496                                num_par, 
497                                J, 
498                                Taylor,
499                                Rec->num_rec_vecad_ind(),
500                                VectorVar.data(),
501                                VectorInd.data()
502                        );
503                        break;
504                        // -------------------------------------------------
505
506                        case StvvOp:
507                        forward_store_vv_op_0(
508                                i_var, 
509                                arg, 
510                                num_par, 
511                                J, 
512                                Taylor,
513                                Rec->num_rec_vecad_ind(),
514                                VectorVar.data(),
515                                VectorInd.data()
516                        );
517                        break;
518                        // -------------------------------------------------
519
520                        case SubvvOp:
521                        forward_subvv_op_0(i_var, arg, parameter, J, Taylor);
522                        break;
523                        // -------------------------------------------------
524
525                        case SubpvOp:
526                        CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par );
527                        forward_subpv_op_0(i_var, arg, parameter, J, Taylor);
528                        break;
529                        // -------------------------------------------------
530
531                        case SubvpOp:
532                        CPPAD_ASSERT_UNKNOWN( size_t(arg[1]) < num_par );
533                        forward_subvp_op_0(i_var, arg, parameter, J, Taylor);
534                        break;
535                        // -------------------------------------------------
536
537                        case TanOp:
538                        // tan(x)^2, tan(x)
539                        CPPAD_ASSERT_UNKNOWN( i_var < numvar  );
540                        forward_tan_op_0(i_var, arg[0], J, Taylor);
541                        break;
542                        // -------------------------------------------------
543
544                        case TanhOp:
545                        // tanh(x)^2, tanh(x)
546                        CPPAD_ASSERT_UNKNOWN( i_var < numvar  );
547                        forward_tanh_op_0(i_var, arg[0], J, Taylor);
548                        break;
549                        // -------------------------------------------------
550
551                        case UserOp:
552                        // start or end an atomic operation sequence
553                        CPPAD_ASSERT_UNKNOWN( NumRes( UserOp ) == 0 );
554                        CPPAD_ASSERT_UNKNOWN( NumArg( UserOp ) == 4 );
555                        if( user_state == user_start )
556                        {       user_index = arg[0];
557                                user_id    = arg[1];
558                                user_n     = arg[2];
559                                user_m     = arg[3];
560                                user_atom  = atomic_base<Base>::class_object(user_index);
561# ifndef NDEBUG
562                                if( user_atom == CPPAD_NULL )
563                                {       std::string msg = 
564                                                atomic_base<Base>::class_name(user_index)
565                                                + ": atomic_base function has been deleted";
566                                        CPPAD_ASSERT_KNOWN(false, msg.c_str() );
567                                }
568# endif
569                                if(user_tx.size() != user_n)
570                                        user_tx.resize(user_n);
571                                if(user_ty.size() != user_m)
572                                        user_ty.resize(user_m);
573                                user_j     = 0;
574                                user_i     = 0;
575                                user_state = user_arg;
576                        }
577                        else
578                        {       CPPAD_ASSERT_UNKNOWN( user_state == user_end );
579                                CPPAD_ASSERT_UNKNOWN( user_index == size_t(arg[0]) );
580                                CPPAD_ASSERT_UNKNOWN( user_id    == size_t(arg[1]) );
581                                CPPAD_ASSERT_UNKNOWN( user_n     == size_t(arg[2]) );
582                                CPPAD_ASSERT_UNKNOWN( user_m     == size_t(arg[3]) );
583# ifndef NDEBUG
584                                if( ! user_ok )
585                                {       std::string msg = 
586                                                atomic_base<Base>::class_name(user_index)
587                                                + ": atomic_base.forward: returned false";
588                                        CPPAD_ASSERT_KNOWN(false, msg.c_str() );
589                                }
590# endif
591                                user_state = user_start;
592                        }
593                        break;
594
595                        case UsrapOp:
596                        // parameter argument in an atomic operation sequence
597                        CPPAD_ASSERT_UNKNOWN( user_state == user_arg );
598                        CPPAD_ASSERT_UNKNOWN( user_j < user_n );
599                        CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par );
600                        user_tx[user_j++] = parameter[ arg[0] ];
601                        if( user_j == user_n )
602                        {       // call users function for this operation
603                                user_atom->set_id(user_id);
604                                CPPAD_ATOMIC_CALL(user_q, user_p, 
605                                        user_vx, user_vy, user_tx, user_ty
606                                );
607                                user_state = user_ret;
608                        }
609                        break;
610
611                        case UsravOp:
612                        // variable argument in an atomic operation sequence
613                        CPPAD_ASSERT_UNKNOWN( user_state == user_arg );
614                        CPPAD_ASSERT_UNKNOWN( user_j < user_n );
615                        CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) <= i_var );
616                        user_tx[user_j++] = Taylor[ arg[0] * J + 0 ];
617                        if( user_j == user_n )
618                        {       // call users function for this operation
619                                user_atom->set_id(user_id);
620                                CPPAD_ATOMIC_CALL(user_q, user_p, 
621                                        user_vx, user_vy, user_tx, user_ty
622                                );
623                                user_state = user_ret;
624                        }
625                        break;
626
627                        case UsrrpOp:
628                        // parameter result in an atomic operation sequence
629                        CPPAD_ASSERT_UNKNOWN( user_state == user_ret );
630                        CPPAD_ASSERT_UNKNOWN( user_i < user_m );
631                        user_i++;
632                        if( user_i == user_m )
633                                user_state = user_end;
634                        break;
635
636                        case UsrrvOp:
637                        // variable result in an atomic operation sequence
638                        CPPAD_ASSERT_UNKNOWN( user_state == user_ret );
639                        CPPAD_ASSERT_UNKNOWN( user_i < user_m );
640                        Taylor[ i_var * J + 0 ] = user_ty[user_i++];
641                        if( user_i == user_m )
642                                user_state = user_end;
643                        break;
644                        // -------------------------------------------------
645
646                        default:
647                        CPPAD_ASSERT_UNKNOWN(false);
648                }
649# if CPPAD_FORWARD0SWEEP_TRACE
650                size_t       d      = 0;
651                size_t       i_tmp  = i_var;
652                Base*        Z_tmp  = Taylor + i_var * J;
653
654                printOp(
655                        std::cout, 
656                        Rec,
657                        i_tmp,
658                        op, 
659                        arg,
660                        d + 1, 
661                        Z_tmp, 
662                        0, 
663                        (Base *) CPPAD_NULL
664                );
665        }
666        std::cout << std::endl;
667# else
668        }
669# endif
670        CPPAD_ASSERT_UNKNOWN( user_state == user_start );
671        CPPAD_ASSERT_UNKNOWN( i_var + 1 == Rec->num_rec_var() );
672
673        return compareCount;
674}
675
676/*! \} */
677} // END_CPPAD_NAMESPACE
678
679// preprocessor symbols that are local to this file
680# undef CPPAD_FORWARD0SWEEP_TRACE
681# undef CPPAD_ATOMIC_CALL
682
683# endif
Note: See TracBrowser for help on using the repository browser.