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

Last change on this file since 3341 was 3341, checked in by bradbell, 6 years ago
  1. Add num_var and cache2var to cppad_assert_arg_before_result.
  2. In sweeps, change numvar to num_var.

forward2sweep.hpp: remove extra asserts (arg_before_result cases).

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