source: branches/cache/cppad/local/create_cache.hpp @ 3375

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

create_cache.hpp: fix check if file already included.

  • Property svn:keywords set to Id
File size: 6.0 KB
Line 
1/* $Id: create_cache.hpp 3375 2014-09-28 22:19:54Z bradbell $ */
2/* --------------------------------------------------------------------------
3CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-14 Bradley M. Bell
4
5CppAD is distributed under multiple licenses. This distribution is under
6the terms of the
7                    Eclipse Public License Version 1.0.
8
9A copy of this license is included in the COPYING file of this distribution.
10Please visit http://www.coin-or.org/CppAD/ for information on other licenses.
11-------------------------------------------------------------------------- */
12# ifndef CPPAD_CREATE_CACHE_INCLUDED
13# define CPPAD_CREATE_CACHE_INCLUDED
14
15/*
16$begin create_cache$$
17
18$section Under Construction$$
19
20$end
21*/
22# include <list>
23# include <cppad/local/cache_info.hpp>
24
25namespace CppAD { // BEGIN_CPPAD_NAMESPACE
26
27/*!
28Set cache information to correspond to the specified player object.
29
30\param play
31The argument indices in the player object are changed to cache, instead
32of variable, indices. To be specific, after
33<code>
34                play.forward_next(op, arg, i_op, i_var);
35                is_var = arg_is_variable(op, arg, i_arg)
36</code>
37if is_var is true, arg[i_arg] has been changed from the variable index
38for argument i_arg to the cache index for that that variable.
39*/
40template <class Base>
41void cache_info::create(player<Base>& play)
42{       size_t i, j, k;
43
44        // number of variables in operation sequence
45        size_t num_var = play.num_var_rec();
46
47        // initialize last use for each variable as the beginning of the
48        // operation sequence
49        CppAD::vector<size_t> last_use(num_var);
50        for(i = 0; i < num_var; i++)
51                last_use[i] = i;
52
53        // index of last result for current user atomic operation
54        size_t user_i_var;
55        bool   in_user_atomic = false;
56
57        // variables used to represent one operation
58        OpCode        op;     // operator
59        const addr_t* arg;    // arguments
60        size_t        i_var;  // index of last result for operation
61        size_t        i_op;   // index of operation
62
63        // Initilalize forward mode sweep through the operation sequence
64        play.forward_start(op, arg, i_op, i_var);
65        CPPAD_ASSERT_UNKNOWN( op == BeginOp );
66
67# ifndef NDEBUG
68        CPPAD_ASSERT_UNKNOWN( play.num_cache_rec() == 0 );
69        // empty cache2variable vector
70        CppAD::vector<addr_t> cache2variable;
71# endif
72
73        while( op != EndOp )
74        {       // next op
75                play.forward_next(op, arg, i_op, i_var);
76                CPPAD_ASSERT_ARG_BEFORE_RESULT(op, arg, num_var, cache2variable, i_var);
77
78                user_i_var     = i_var;
79                if( op == UserOp )
80                {       in_user_atomic = ! in_user_atomic;
81                        if( in_user_atomic )
82                                user_i_var     = i_var + size_t( arg[3] );
83                }
84                //
85                size_t n_arg = NumArg(op);
86                for(size_t i_arg = 0; i_arg < n_arg; i_arg++)
87                {       if( arg_is_variable(op, arg, i_arg) )
88                                last_use[ arg[i_arg] ] = user_i_var;
89                }
90        }
91
92        // sort the order of the last_use elements
93        CppAD::vector<size_t> order(num_var);
94        index_sort(last_use, order);
95
96        // initialize cache mapping and available list as empty
97        pod_vector<addr_t> variable2cache;
98        std::list<addr_t> available;
99        std::list<addr_t>::iterator itr;
100
101        // compute the cache index corresponding to each variable index
102        // resize(num_var) because constructed with zero size
103        variable2cache.extend(num_var);
104        size_t i_cache = num_var;
105        size_t i_last  = 0;
106        for(i_var = 0; i_var < num_var; i_var++)
107        {       if( available.empty() )
108                        available.push_front(i_cache++);
109                variable2cache[i_var] = available.front();
110                available.pop_front();
111
112                while( i_last < num_var && last_use[ order[i_last] ] <= i_var )
113                {       available.push_back( variable2cache[ order[i_last++] ] );
114                }
115        }
116        size_t number_cache = i_cache - num_var;
117
118        // temporary printing of result
119        std::cout << "number_cache = " << number_cache << std::endl;
120        std::cout << "i_var, last_use, cache" << std::endl;
121        for(i_var = 0; i_var < num_var; i_var++)
122        {       std::cout << i_var << ", ";
123                std::cout << last_use[i_var] << ", ";
124                std::cout << variable2cache[i_var] << std::endl;
125        }
126
127
128        // 2DO: make rec an argument
129        recorder<Base> rec;
130        rec.free();
131
132        // Copy parameters to new recording
133        size_t num_par = play.num_par_rec();
134        for(i = 0; i < num_par; i++)
135                rec.PutPar( play.GetPar(i) );
136
137        // Copy VecAD indices in to new recording
138        size_t num_vecad_vec = play.num_vecad_vec_rec();
139        j                    = 0;
140        for(i = 0; i < num_vecad_vec; i++)
141        {       // lenght of the VecAD object
142                size_t length = play.GetVecInd(j);
143                for(k = 1; k <= length; k++)
144                        rec.PutVecInd( play.GetVecInd(j+k)  );
145                // start of the next VecAD entry
146                j += length + 1;
147        }
148        CPPAD_ASSERT_UNKNOWN( j == play.num_vec_ind_rec() );
149
150        // Initilalize forward sweep through the operation sequence
151        play.forward_start(op, arg, i_op, i_var);
152        CPPAD_ASSERT_UNKNOWN( op == BeginOp );
153
154        // playing forward skips BeginOp at the beginning, but not EndOp at
155        // the end.  Put BeginOp at beginning of recording
156        CPPAD_ASSERT_UNKNOWN( op == BeginOp );
157        CPPAD_ASSERT_NARG_NRES(BeginOp, 1, 1);
158        rec.PutOp(BeginOp);
159        rec.PutArg(0);
160
161        CPPAD_ASSERT_UNKNOWN( NumArg(EndOp) == 0 );
162        while( op != EndOp )
163        {       // next op
164                play.forward_next(op, arg, i_op, i_var);
165                CPPAD_ASSERT_ARG_BEFORE_RESULT(op, arg, num_var, cache2variable, i_var);
166
167                rec.PutOp(op);
168                //
169                size_t n_arg = NumArg(op);
170                for(size_t i_arg = 0; i_arg < n_arg; i_arg++)
171                {       if( arg_is_variable(op, arg, i_arg) )
172                                rec.PutArg( variable2cache[ arg[i_arg] ] );
173                        else
174                                rec.PutArg( arg[i_arg] );
175                }
176        }
177
178
179        // create a player out of this cached recording
180        play.get(rec);
181
182        // set the cache information for this recording
183        num_var_   = num_var;
184        num_cache_ = number_cache;
185        //
186        last_use_.free();
187        last_use_.extend( num_var_ );
188        //
189        order_.free();
190        order_.extend(num_var_);
191        //
192        var2cache_.free();
193        var2cache_.extend(num_var_);
194        //
195        cache2var_.clear();
196        cache2var_.resize(num_cache_);
197        //
198        for(i_var = 0; i_var < num_var_; i_var++)
199        {       last_use_[i_var]  = addr_t( last_use[i_var] );
200                order_[i_var]     = addr_t( order[i_var] );
201                var2cache_[i_var] = variable2cache[i_var];
202        }
203
204        return;
205}
206
207
208template <class Base>
209void ADFun<Base>::create_cache(void)
210{
211        // use cache addresses in the player
212        play_.create_cache();
213
214        // erase the taylor array
215        size_t c = 0;
216        size_t r = 0;
217        capacity_order(c, r);
218
219        return;
220}
221
222} // END_CPPAD_NAMESPACE
223
224# endif
Note: See TracBrowser for help on using the repository browser.