CppADCodeGen  HEAD
A C++ Algorithmic Differentiation Package with Source Code Generation
base_abstract_atomic_fun.hpp
1 #ifndef CPPAD_CG_BASE_ABSTRACT_ATOMIC_FUN_INCLUDED
2 #define CPPAD_CG_BASE_ABSTRACT_ATOMIC_FUN_INCLUDED
3 /* --------------------------------------------------------------------------
4  * CppADCodeGen: C++ Algorithmic Differentiation with Source Code Generation:
5  * Copyright (C) 2019 Joao Leal
6  * Copyright (C) 2013 Ciengis
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 BaseAbstractAtomicFun : public atomic_base<CppAD::cg::CG<Base> > {
29 public:
30  using CGB = CppAD::cg::CG<Base>;
31  using Arg = Argument<Base>;
32 protected:
33 
40  explicit BaseAbstractAtomicFun(const std::string& name) :
41  atomic_base<CGB>(name) {
42  CPPADCG_ASSERT_KNOWN(!name.empty(), "The atomic function name cannot be empty")
43  }
44 
45 public:
46 
47  template <class ADVector>
48  void operator()(const ADVector& ax,
49  ADVector& ay,
50  size_t id = 0) {
51  this->atomic_base<CGB>::operator()(ax, ay, id);
52  }
53 
54  virtual ~BaseAbstractAtomicFun() = default;
55 
56 protected:
57 
58  static inline void appendAsArguments(typename std::vector<Arg>::iterator begin,
59  const CppAD::vector<CGB>& tx) {
60  std::vector<Arg> arguments(tx.size());
61  typename std::vector<Arg>::iterator it = begin;
62  for (size_t i = 0; i < arguments.size(); i++, ++it) {
63  if (tx[i].isParameter()) {
64  *it = Arg(tx[i].getValue());
65  } else {
66  *it = Arg(*tx[i].getOperationNode());
67  }
68  }
69  }
70 
71  static inline OperationNode<Base>* makeArray(CodeHandler<Base>& handler,
72  const CppAD::vector<CGB>& tx) {
73  std::vector<Arg> arrayArgs = asArguments(tx);
74  std::vector<size_t> info; // empty
75 
76  return handler.makeNode(CGOpCode::ArrayCreation, info, arrayArgs);
77  }
78 
79  static inline OperationNode<Base>* makeArray(CodeHandler<Base>& handler,
80  const CppAD::vector<CGB>& tx,
81  size_t p,
82  size_t k) {
83  CPPADCG_ASSERT_UNKNOWN(k <= p)
84  size_t n = tx.size() / (p + 1);
85  std::vector<Arg> arrayArgs(n);
86  for (size_t i = 0; i < n; i++) {
87  arrayArgs[i] = asArgument(tx[i * (p + 1) + k]);
88  }
89 
90  return handler.makeNode(CGOpCode::ArrayCreation,{}, arrayArgs);
91  }
92 
93  static inline OperationNode<Base>* makeZeroArray(CodeHandler<Base>& handler,
94  size_t size) {
95  CppAD::vector<CGB> tx2(size);
96  std::vector<Arg> arrayArgs = asArguments(tx2);
97 
98  return handler.makeNode(CGOpCode::ArrayCreation,{}, arrayArgs);
99  }
100 
101  static inline OperationNode<Base>* makeEmptySparseArray(CodeHandler<Base>& handler,
102  size_t size) {
103  return handler.makeNode(CGOpCode::SparseArrayCreation,{size}, {}); //empty args
104  }
105 
106  static inline OperationNode<Base>* makeSparseArray(CodeHandler<Base>& handler,
107  const CppAD::vector<CGB>& py,
108  size_t p,
109  size_t k) {
110  size_t p1 = p + 1;
111  CPPADCG_ASSERT_UNKNOWN(k < p1)
112  size_t n = py.size() / p1;
113 
114  std::vector<Arg> arrayArgs;
115  std::vector<size_t> arrayIdx(1);
116  arrayIdx[0] = n; // array size
117 
118  arrayArgs.reserve(py.size() / 3);
119  arrayIdx.reserve(1 + py.size() / 3);
120 
121  for (size_t i = 0; i < n; i++) {
122  if (!py[i * p1 + k].isIdenticalZero()) {
123  arrayArgs.push_back(asArgument(py[i * p1 + k]));
124  arrayIdx.push_back(i);
125  }
126  }
127 
128  return handler.makeNode(CGOpCode::SparseArrayCreation, arrayIdx, arrayArgs);
129  }
130 
131  static inline bool isParameters(const CppAD::vector<CGB>& tx) {
132  for (size_t i = 0; i < tx.size(); i++) {
133  if (!tx[i].isParameter()) {
134  return false;
135  }
136  }
137  return true;
138  }
139 
140  static inline bool isValuesDefined(const CppAD::vector<CGB>& tx) {
141  for (size_t i = 0; i < tx.size(); i++) {
142  if (!tx[i].isValueDefined()) {
143  return false;
144  }
145  }
146  return true;
147  }
148 
149 };
150 
151 } // END cg namespace
152 } // END CppAD namespace
153 
154 #endif
BaseAbstractAtomicFun(const std::string &name)