source: branches/cache/cppad/local/cache.hpp @ 3333

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

Move arg_is_variable to op_code.hpp so can be used by printOp.

  • Property svn:keywords set to Id
File size: 3.8 KB
Line 
1/*
2$begin cache$$
3
4$section Under Construction$$
5
6$end
7*/
8# include <list>
9
10namespace CppAD { // BEGIN_CPPAD_NAMESPACE
11
12template <class Base>
13void create_cache(
14        player<Base>&       play )
15{       size_t i, j, k;
16
17        // number of variables in operation sequence
18        size_t num_var = play.num_var_rec();
19
20        // initialize last use for each variable as the beginning of the
21        // operation sequence
22        CppAD::vector<size_t> last_use(num_var);
23        for(i = 0; i < num_var; i++)
24                last_use[i] = i;
25
26        // index of last result for current user atomic operation
27        size_t user_i_var;
28        bool   in_user_atomic = false;
29
30        // variables used to represent one operation
31        OpCode        op;     // operator
32        const addr_t* arg;    // arguments
33        size_t        i_var;  // index of last result for operation
34        size_t        i_op;   // index of operation
35
36        // Initilalize forward mode sweep through the operation sequence
37        play.forward_start(op, arg, i_op, i_var);
38        CPPAD_ASSERT_UNKNOWN( op == BeginOp );
39
40        while( op != EndOp )
41        {       // next op
42                play.forward_next(op, arg, i_op, i_var);
43                CPPAD_ASSERT_ARG_BEFORE_RESULT(op, arg, i_var);
44
45                if( op == UserOp )
46                {       in_user_atomic = ! in_user_atomic;
47                        if( in_user_atomic )
48                                user_i_var     = i_var + size_t( arg[3] );
49                        else
50                                user_i_var     = i_var;
51                }
52                //
53                size_t n_arg = NumArg(op);
54                for(size_t i_arg = 0; i_arg < n_arg; i_arg++)
55                {       if( arg_is_variable(op, arg, i_arg) )
56                                last_use[ arg[i_arg] ] = i_var;
57                }
58        }
59
60        // sort the order of the last_use elements
61        CppAD::vector<size_t> order(num_var);
62        index_sort(last_use, order);
63
64        // initialize the cache vector and available flags as empty
65        CppAD::vector<addr_t> cache(num_var);
66        std::list<addr_t> available;
67        std::list<addr_t>::iterator itr;
68
69        // compute the cache index corresponding to each variable index
70        size_t i_cache = num_var;
71        size_t i_last  = 0;
72        for(i_var = 0; i_var < num_var; i_var++)
73        {       if( available.empty() )
74                        available.push_front(i_cache++);
75                cache[i_var] = available.front();
76                available.pop_front();
77
78                while( i_last < num_var && last_use[ order[i_last] ] <= i_var )
79                {       available.push_back( cache[ order[i_last++] ] );
80                }
81        }
82
83        // temporary printing of result
84        std::cout << "i_var, last_use, cache" << std::endl;
85        for(i_var = 0; i_var < num_var; i_var++)
86        {       std::cout << i_var << ", ";
87                std::cout << last_use[i_var] << ", ";
88                std::cout << cache[i_var] << std::endl;
89        }
90        std::cout << "num_cache = " << i_cache - num_var << std::endl;
91
92
93        // 2DO: make rec an argument
94        recorder<Base> rec;
95        rec.free();
96
97        // Copy parameters to new recording
98        size_t num_par = play.num_par_rec();
99        for(i = 0; i < num_par; i++)
100                rec.PutPar( play.GetPar(i) );
101
102        // Copy VecAD indices in to new recording
103        size_t num_vecad_vec = play.num_vecad_vec_rec();
104        j                    = 0;
105        for(i = 0; i < num_vecad_vec; i++)
106        {       // lenght of the VecAD object
107                size_t length = play.GetVecInd(j);
108                for(k = 1; k <= length; k++)
109                        rec.PutVecInd( play.GetVecInd(j+k)  );
110                // start of the next VecAD entry
111                j += length + 1;
112        }
113        CPPAD_ASSERT_UNKNOWN( j == play.num_vec_ind_rec() );
114
115        // Initilalize forward sweep through the operation sequence
116        play.forward_start(op, arg, i_op, i_var);
117        CPPAD_ASSERT_UNKNOWN( op == BeginOp );
118
119        // playing forward skips BeginOp at the beginning, but not EndOp at
120        // the end.  Put BeginOp at beginning of recording
121        CPPAD_ASSERT_UNKNOWN( op == BeginOp );
122        CPPAD_ASSERT_NARG_NRES(BeginOp, 1, 1);
123        rec.PutOp(BeginOp);
124        rec.PutArg(0);
125
126        while( op != EndOp )
127        {       // next op
128                play.forward_next(op, arg, i_op, i_var);
129                CPPAD_ASSERT_ARG_BEFORE_RESULT(op, arg, i_var);
130
131                rec.PutOp(op);
132                //
133                size_t n_arg = NumArg(op);
134                for(size_t i_arg = 0; i_arg < n_arg; i_arg++)
135                {       if( arg_is_variable(op, arg, i_arg) )
136                                rec.PutArg( cache[ arg[i_arg] ] );
137                        else
138                                rec.PutArg( arg[i_arg] );
139                }
140        }
141        return;
142}
143
144
145template <class Base>
146void ADFun<Base>::cache(void)
147{       create_cache(play_);
148}
149
150} // END_CPPAD_NAMESPACE
Note: See TracBrowser for help on using the repository browser.