CppADCodeGen  HEAD
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  * 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 
19 namespace CppAD {
20 namespace cg {
21 
27 template<class Base>
28 class OperationNode {
29  friend class CodeHandler<Base>;
30 public:
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;
35 public:
36  static const std::set<CGOpCode> CUSTOM_NODE_CLASS;
37 private:
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_;
65 public:
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 
237 protected:
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 
299 public:
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 
312 protected:
313  static inline std::set<CGOpCode> makeCustomNodeClassesSet() noexcept;
314 
315 };
316 
317 template<class Base>
318 inline 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 
328 template<class Base>
329 const std::set<CGOpCode> OperationNode<Base>::CUSTOM_NODE_CLASS = makeCustomNodeClassesSet();
330 
331 template<class Base>
332 inline 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
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