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