CppADCodeGen 2.4.3
A C++ Algorithmic Differentiation Package with Source Code Generation
Loading...
Searching...
No Matches
operation_node.hpp
1#ifndef CPPAD_CG_EXPRESSION_NODE_INCLUDED
2#define CPPAD_CG_EXPRESSION_NODE_INCLUDED
3/* --------------------------------------------------------------------------
4 * CppADCodeGen: C++ Algorithmic Differentiation with Source Code Generation:
5 * Copyright (C) 2012 Ciengis
6 * Copyright (C) 2019 Joao Leal
7 *
8 * CppADCodeGen is distributed under multiple licenses:
9 *
10 * - Eclipse Public License Version 1.0 (EPL1), and
11 * - GNU General Public License Version 3 (GPL3).
12 *
13 * EPL1 terms and conditions can be found in the file "epl-v10.txt", while
14 * terms and conditions for the GPL3 can be found in the file "gpl3.txt".
15 * ----------------------------------------------------------------------------
16 * Author: Joao Leal
17 */
18
19namespace CppAD {
20namespace cg {
21
27template<class Base>
29 friend class CodeHandler<Base>;
30public:
31 using iterator = typename std::vector<Argument<Base> >::iterator;
32 using const_iterator = typename std::vector<Argument<Base> >::const_iterator;
33 using const_reverse_iterator = typename std::vector<Argument<Base> >::const_reverse_iterator;
34 using reverse_iterator = typename std::vector<Argument<Base> >::reverse_iterator;
35public:
36 static const std::set<CGOpCode> CUSTOM_NODE_CLASS;
37private:
42 CodeHandler<Base>* handler_;
46 CGOpCode operation_;
50 std::vector<size_t> info_;
56 std::vector<Argument<Base> > arguments_;
60 size_t pos_;
64 std::unique_ptr<std::string> name_;
65public:
70 inline void makeAlias(const Argument<Base>& other) {
71 CPPADCG_ASSERT_UNKNOWN(CUSTOM_NODE_CLASS.find(operation_) == CUSTOM_NODE_CLASS.end()); // TODO: consider relaxing this check
72
73 operation_ = CGOpCode::Alias;
74 arguments_.resize(1);
75 arguments_[0] = other;
76 name_.reset();
77 }
78
86 return handler_;
87 }
88
93 inline CGOpCode getOperationType() const {
94 return operation_;
95 }
96
104 inline void setOperation(CGOpCode op,
105 const std::vector<Argument<Base> >& arguments = std::vector<Argument<Base> >()) {
106 CPPADCG_ASSERT_UNKNOWN(op == operation_ || CUSTOM_NODE_CLASS.find(op) == CUSTOM_NODE_CLASS.end()); // cannot transform into a node with a custom class
107
108 operation_ = op;
109 arguments_ = arguments;
110 }
111
117 inline const std::vector<Argument<Base> >& getArguments() const {
118 return arguments_;
119 }
120
126 inline std::vector<Argument<Base> >& getArguments() {
127 return arguments_;
128 }
129
134 inline const std::vector<size_t>& getInfo() const {
135 return info_;
136 }
137
142 inline std::vector<size_t>& getInfo() {
143 return info_;
144 }
145
151 inline const std::string* getName() const {
152 return name_.get();
153 }
154
159 inline void setName(const std::string& name) {
160 if (name_ != nullptr)
161 *name_ = name;
162 else
163 name_.reset(new std::string(name));
164 }
165
169 inline void clearName() {
170 name_.reset();
171 }
172
181 inline size_t getHandlerPosition() const {
182 return pos_;
183 }
184
185 // argument iterators
186
187 inline iterator begin() {
188 return arguments_.begin();
189 }
190
191 inline const_iterator begin() const {
192 return arguments_.begin();
193 }
194
195 inline iterator end() {
196 return arguments_.end();
197 }
198
199 inline const_iterator end() const {
200 return arguments_.end();
201 }
202
203 inline reverse_iterator rbegin() {
204 return arguments_.rbegin();
205 }
206
207 inline const_reverse_iterator rbegin() const {
208 return arguments_.rbegin();
209 }
210
211 inline reverse_iterator rend() {
212 return arguments_.rend();
213 }
214
215 inline const_reverse_iterator rend() const {
216 return arguments_.rend();
217 }
218
219 inline const_iterator cbegin() const noexcept {
220 return arguments_.cbegin();
221 }
222
223 inline const_iterator cend() const noexcept {
224 return arguments_.cend();
225 }
226
227 inline const_reverse_iterator crbegin() const noexcept {
228 return arguments_.crbegin();
229 }
230
231 inline const_reverse_iterator crend() const noexcept {
232 return arguments_.crend();
233 }
234
235 inline virtual ~OperationNode() = default;
236
237protected:
238
239 inline OperationNode(const OperationNode& orig) :
240 handler_(orig.handler_),
241 operation_(orig.operation_),
242 info_(orig.info_),
243 arguments_(orig.arguments_),
244 pos_((std::numeric_limits<size_t>::max)()),
245 name_(orig.name_ != nullptr ? new std::string(*orig.name_) : nullptr) {
246 }
247
248 inline OperationNode(CodeHandler<Base>* handler,
249 CGOpCode op) :
250 handler_(handler),
251 operation_(op),
252 pos_((std::numeric_limits<size_t>::max)()) {
253 }
254
255 inline OperationNode(CodeHandler<Base>* handler,
256 CGOpCode op,
257 const Argument<Base>& arg) :
258 handler_(handler),
259 operation_(op),
260 arguments_ {arg},
261 pos_((std::numeric_limits<size_t>::max)()) {
262 }
263
264 inline OperationNode(CodeHandler<Base>* handler,
265 CGOpCode op,
266 std::vector<Argument<Base> >&& args) :
267 handler_(handler),
268 operation_(op),
269 arguments_(std::move(args)),
270 pos_((std::numeric_limits<size_t>::max)()) {
271 }
272
273 inline OperationNode(CodeHandler<Base>* handler,
274 CGOpCode op,
275 std::vector<size_t>&& info,
276 std::vector<Argument<Base> >&& args) :
277 handler_(handler),
278 operation_(op),
279 info_(std::move(info)),
280 arguments_(std::move(args)),
281 pos_((std::numeric_limits<size_t>::max)()) {
282 }
283
284 inline OperationNode(CodeHandler<Base>* handler,
285 CGOpCode op,
286 const std::vector<size_t>& info,
287 const std::vector<Argument<Base> >& args) :
288 handler_(handler),
289 operation_(op),
290 info_(info),
291 arguments_(args),
292 pos_((std::numeric_limits<size_t>::max)()) {
293 }
294
295 inline void setHandlerPosition(size_t pos) {
296 pos_ = pos;
297 }
298
299public:
300
306 static std::unique_ptr<OperationNode<Base>> makeTemporaryNode(CGOpCode op,
307 const std::vector<size_t>& info,
308 const std::vector<Argument<Base> >& args) {
309 return std::unique_ptr<OperationNode<Base>> (new OperationNode<Base>(nullptr, op, info, args));
310 }
311
312protected:
313 static inline std::set<CGOpCode> makeCustomNodeClassesSet() noexcept;
314
315};
316
317template<class Base>
318inline std::set<CGOpCode> OperationNode<Base>::makeCustomNodeClassesSet() noexcept {
319 std::set<CGOpCode> s;
320 s.insert(CGOpCode::IndexAssign);
321 s.insert(CGOpCode::Index);
322 s.insert(CGOpCode::LoopStart);
323 s.insert(CGOpCode::LoopEnd);
324 s.insert(CGOpCode::Pri);
325 return s;
326}
327
328template<class Base>
329const std::set<CGOpCode> OperationNode<Base>::CUSTOM_NODE_CLASS = makeCustomNodeClassesSet();
330
331template<class Base>
332inline std::ostream& operator<<(
333 std::ostream& os, //< stream to write to
334 const OperationNode<Base>& c) {
335 CGOpCode op = c.getOperationType();
336 switch (op) {
337 case CGOpCode::ArrayCreation:
338 os << "new $1[" << c.getArguments().size() << "]";
339 break;
340 case CGOpCode::SparseArrayCreation:
341 os << "new $1[" << c.getInfo()[0] << "]";
342 break;
343 case CGOpCode::ArrayElement:
344 os << "$1[" << c.getInfo()[0] << "]";
345 break;
346 case CGOpCode::AtomicForward:
347 os << "atomicFunction.forward(" << c.getInfo()[0] << ", " << c.getInfo()[1] << ", vx, vy, $1, $2)";
348 break;
349 case CGOpCode::AtomicReverse:
350 os << "atomicFunction.reverse(" << c.getInfo()[0] << ", $1, $2, $3, $4)";
351 break;
352 case CGOpCode::Sign:
353 os << "if($1 > 0) { 1 } else if($1 == 0) { 0 } else { -1 }";
354 break;
355
356 default:
357 os << op;
358 }
359
360 return os;
361}
362
363} // END cg namespace
364} // END CppAD namespace
365
366#endif
void setOperation(CGOpCode op, const std::vector< Argument< Base > > &arguments=std::vector< Argument< Base > >())
void setName(const std::string &name)
static std::unique_ptr< OperationNode< Base > > makeTemporaryNode(CGOpCode op, const std::vector< size_t > &info, const std::vector< Argument< Base > > &args)
const std::vector< size_t > & getInfo() const
size_t getHandlerPosition() const
std::vector< size_t > & getInfo()
const std::vector< Argument< Base > > & getArguments() const
CGOpCode getOperationType() const
std::vector< Argument< Base > > & getArguments()
void makeAlias(const Argument< Base > &other)
const std::string * getName() const
CodeHandler< Base > * getCodeHandler() const