1 | /* $Id: forward.hpp 2970 2013-10-19 02:16:02Z bradbell $ */ |
---|
2 | # ifndef CPPAD_FORWARD_INCLUDED |
---|
3 | # define CPPAD_FORWARD_INCLUDED |
---|
4 | |
---|
5 | /* -------------------------------------------------------------------------- |
---|
6 | CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-13 Bradley M. Bell |
---|
7 | |
---|
8 | CppAD is distributed under multiple licenses. This distribution is under |
---|
9 | the terms of the |
---|
10 | Eclipse Public License Version 1.0. |
---|
11 | |
---|
12 | A copy of this license is included in the COPYING file of this distribution. |
---|
13 | Please visit http://www.coin-or.org/CppAD/ for information on other licenses. |
---|
14 | -------------------------------------------------------------------------- */ |
---|
15 | |
---|
16 | /* |
---|
17 | $begin Forward$$ |
---|
18 | |
---|
19 | $section Forward Mode$$ |
---|
20 | |
---|
21 | $childtable% |
---|
22 | omh/forward.omh% |
---|
23 | cppad/local/cap_taylor.hpp% |
---|
24 | example/forward.cpp% |
---|
25 | example/forward_mul.cpp |
---|
26 | %$$ |
---|
27 | |
---|
28 | $end |
---|
29 | ----------------------------------------------------------------------------- |
---|
30 | */ |
---|
31 | |
---|
32 | // documened after Forward but included here so easy to see |
---|
33 | # include <cppad/local/cap_taylor.hpp> |
---|
34 | |
---|
35 | namespace CppAD { // BEGIN_CPPAD_NAMESPACE |
---|
36 | /*! |
---|
37 | \defgroup forward_hpp forward.hpp |
---|
38 | \{ |
---|
39 | \file forward.hpp |
---|
40 | User interface to forward mode computations |
---|
41 | */ |
---|
42 | |
---|
43 | /*! |
---|
44 | Compute arbitrary order forward mode Taylor coefficieints. |
---|
45 | |
---|
46 | \tparam Base |
---|
47 | The type used during the forward mode computations; i.e., the corresponding |
---|
48 | recording of operations used the type \c AD<Base>. |
---|
49 | |
---|
50 | \tparam Vector |
---|
51 | is a Simple Vector class with eleements of type \c Base. |
---|
52 | |
---|
53 | \param p |
---|
54 | is the hightest order for this forward mode computation; i.e., |
---|
55 | after this calculation there will be <code>p+1</code> |
---|
56 | Taylor coefficients per variables. |
---|
57 | |
---|
58 | \param x_p |
---|
59 | contains Taylor coefficients for the independent variables. |
---|
60 | The size of \a x_p must either be \c n or <code>n*(p+1)</code>, |
---|
61 | We define <code>q = p + 1 - x_p.size() / n</code>. |
---|
62 | The Taylor coefficients of order k, for |
---|
63 | k = q, ... , p are calculated. |
---|
64 | |
---|
65 | \param s |
---|
66 | Is the stream where output corresponding to \c PriOp operations will written. |
---|
67 | */ |
---|
68 | |
---|
69 | template <typename Base> |
---|
70 | template <typename Vector> |
---|
71 | Vector ADFun<Base>::Forward( |
---|
72 | size_t p , |
---|
73 | const Vector& x_p , |
---|
74 | std::ostream& s ) |
---|
75 | { // temporary indices |
---|
76 | size_t i, j, k; |
---|
77 | |
---|
78 | // number of independent variables |
---|
79 | size_t n = ind_taddr_.size(); |
---|
80 | |
---|
81 | // number of dependent variables |
---|
82 | size_t m = dep_taddr_.size(); |
---|
83 | |
---|
84 | // check Vector is Simple Vector class with Base type elements |
---|
85 | CheckSimpleVector<Base, Vector>(); |
---|
86 | |
---|
87 | CPPAD_ASSERT_KNOWN( |
---|
88 | size_t(x_p.size()) == n || size_t(x_p.size()) == n*(p+1), |
---|
89 | "Forward: x_p.size() is not equal n or n*(p+1)" |
---|
90 | ); |
---|
91 | size_t n_order = size_t(x_p.size()) / n; |
---|
92 | CPPAD_ASSERT_KNOWN( |
---|
93 | p <= taylor_per_var_ || n_order == p + 1, |
---|
94 | "The number of Taylor coefficient currently stored in this ADFun\n" |
---|
95 | "is less than p and x_p.size() != n*(p+1)." |
---|
96 | ); |
---|
97 | |
---|
98 | // check if the taylor_ matrix needs more columns |
---|
99 | if( taylor_col_dim_ <= p ) |
---|
100 | capacity_taylor(p + 1); |
---|
101 | CPPAD_ASSERT_UNKNOWN( taylor_col_dim_ > p ); |
---|
102 | |
---|
103 | // set the p-th order taylor_ coefficients for independent variables |
---|
104 | for(j = 0; j < n; j++) |
---|
105 | { CPPAD_ASSERT_UNKNOWN( ind_taddr_[j] < total_num_var_ ); |
---|
106 | |
---|
107 | // ind_taddr_[j] is operator taddr for j-th independent variable |
---|
108 | CPPAD_ASSERT_UNKNOWN( play_.GetOp( ind_taddr_[j] ) == InvOp ); |
---|
109 | |
---|
110 | // It is also variable taddr for j-th independent variable |
---|
111 | if( n_order == 1 ) |
---|
112 | taylor_[ind_taddr_[j] * taylor_col_dim_ + p] = x_p[j]; |
---|
113 | else for(k = 0; k < n_order; k++) |
---|
114 | taylor_[ind_taddr_[j] * taylor_col_dim_ + k] = |
---|
115 | x_p[j * n_order + k]; |
---|
116 | } |
---|
117 | |
---|
118 | // evaluate the derivatives |
---|
119 | size_t q = (p + 1) - n_order; |
---|
120 | if( p == 0 ) |
---|
121 | { |
---|
122 | # if CPPAD_USE_FORWARD0SWEEP |
---|
123 | compare_change_ = forward0sweep(s, true, |
---|
124 | n, total_num_var_, &play_, taylor_col_dim_, taylor_.data(), |
---|
125 | cskip_var_ |
---|
126 | ); |
---|
127 | # else |
---|
128 | compare_change_ = forward_sweep(s, true, q, |
---|
129 | p, n, total_num_var_, &play_, taylor_col_dim_, taylor_.data(), |
---|
130 | cskip_var_ |
---|
131 | ); |
---|
132 | # endif |
---|
133 | } |
---|
134 | else if( q == 0 ) |
---|
135 | { compare_change_ = forward_sweep(s, true, q, |
---|
136 | p, n, total_num_var_, &play_, taylor_col_dim_, taylor_.data(), |
---|
137 | cskip_var_ |
---|
138 | ); |
---|
139 | } |
---|
140 | else |
---|
141 | { forward_sweep(s, true, q, |
---|
142 | p, n, total_num_var_, &play_, taylor_col_dim_, taylor_.data(), |
---|
143 | cskip_var_ |
---|
144 | ); |
---|
145 | } |
---|
146 | |
---|
147 | // return Taylor coefficients for dependent variables |
---|
148 | Vector y_p; |
---|
149 | if( n_order == 1 ) |
---|
150 | { y_p.resize(m); |
---|
151 | for(i = 0; i < m; i++) |
---|
152 | { CPPAD_ASSERT_UNKNOWN( dep_taddr_[i] < total_num_var_ ); |
---|
153 | y_p[i] = taylor_[dep_taddr_[i] * taylor_col_dim_ + p]; |
---|
154 | } |
---|
155 | } |
---|
156 | else |
---|
157 | { y_p.resize(m * n_order ); |
---|
158 | for(i = 0; i < m; i++) |
---|
159 | { for(k = 0; k < n_order; k++) |
---|
160 | y_p[ i * n_order + k] = |
---|
161 | taylor_[ dep_taddr_[i] * taylor_col_dim_ + k ]; |
---|
162 | } |
---|
163 | } |
---|
164 | # ifndef NDEBUG |
---|
165 | if( check_for_nan_ ) |
---|
166 | { bool ok = true; |
---|
167 | if( p == 0 && n_order == 1 ) |
---|
168 | ok = ! hasnan(y_p); |
---|
169 | else if( n_order != 1 ) |
---|
170 | { for(i = 0; i < m; i++) |
---|
171 | ok &= ! isnan( y_p[ i * n_order + 0 ] ); |
---|
172 | } |
---|
173 | CPPAD_ASSERT_KNOWN(ok, |
---|
174 | "y_p = f.Forward(p, x): has a zero order Taylor coefficient " |
---|
175 | "with the value nan." |
---|
176 | ); |
---|
177 | if( p != 0 && n_order == 1 ) |
---|
178 | ok = ! hasnan(y_p); |
---|
179 | else if( n_order != 1 ) |
---|
180 | { for(i = 0; i < m; i++) |
---|
181 | { for(k = 1; k < n_order; k++) |
---|
182 | ok &= ! isnan( y_p[ i * n_order + k ] ); |
---|
183 | } |
---|
184 | } |
---|
185 | CPPAD_ASSERT_KNOWN(ok, |
---|
186 | "y_p = f.Forward(p, x): has a non-zero order Taylor coefficient\n" |
---|
187 | "with the value nan (but zero order coefficients are not nan)." |
---|
188 | ); |
---|
189 | } |
---|
190 | # endif |
---|
191 | |
---|
192 | |
---|
193 | // now we have p + 1 taylor_ coefficients per variable |
---|
194 | taylor_per_var_ = p + 1; |
---|
195 | |
---|
196 | return y_p; |
---|
197 | } |
---|
198 | |
---|
199 | /*! \} */ |
---|
200 | } // END_CPPAD_NAMESPACE |
---|
201 | # endif |
---|