CppADCodeGen  HEAD
A C++ Algorithmic Differentiation Package with Source Code Generation
language_dot_arrays.hpp
1 #ifndef CPPAD_CG_LANGUAGE_DOT_ARRAYS_INCLUDED
2 #define CPPAD_CG_LANGUAGE_DOT_ARRAYS_INCLUDED
3 /* --------------------------------------------------------------------------
4  * CppADCodeGen: C++ Algorithmic Differentiation with Source Code Generation:
5  * Copyright (C) 2016 Ciengis
6  * Copyright (C) 2020 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 
22 template<class Base>
23 std::string LanguageDot<Base>::printArrayCreationOp(OperationNode<Base>& array) {
24  CPPADCG_ASSERT_KNOWN(array.getArguments().size() > 0, "Invalid number of arguments for array creation operation")
25  const std::vector<Argument<Base> >& args = array.getArguments();
26  const size_t argSize = args.size();
27 
28  _ss.str("");
29  _ss << "array[" << args.size() << "]";
30  std::string name = printNodeDeclaration(array, _ss);
31 
32  for (size_t i = 0; i < argSize; i++) {
33  // try to use a loop for element assignment
34  size_t newI = printArrayCreationUsingLoop(name, array, i, nullptr);
35 
36  // print elements not assign in a loop
37  if (newI == i) {
38  // individual element assignment
39  std::string aName = print(args[i]);
40 
41  printEdge(aName, name, std::to_string(i)); // std::to_string(i)
42  _code << _endline;
43 
44  } else {
45  i = newI - 1;
46  }
47  }
48 
49  return name;
50 }
51 
52 template<class Base>
53 std::string LanguageDot<Base>::printSparseArrayCreationOp(OperationNode<Base>& array) {
54 
55  const std::vector<size_t>& info = array.getInfo();
56  CPPADCG_ASSERT_KNOWN(!info.empty(), "Invalid number of information elements for sparse array creation operation")
57 
58  const std::vector<Argument<Base> >& args = array.getArguments();
59  const size_t argSize = args.size();
60 
61  CPPADCG_ASSERT_KNOWN(info.size() == argSize + 1, "Invalid number of arguments for sparse array creation operation")
62 
63  _ss.str("");
64  _ss << "sparse[" << info[0] << "]"; // nnz: args.size()
65  std::string name = printNodeDeclaration(array, _ss);
66 
67  if (argSize == 0)
68  return name; // empty array
69 
70  for (size_t i = 0; i < argSize; i++) {
71  // try to use a loop for element assignment
72  size_t newI = printArrayCreationUsingLoop(name, array, i, &info[i]);
73 
74  // print element values not assign in a loop
75  if (newI == i) {
76  // individual element assignment
77  std::string aName = print(args[i]);
78 
79  printEdge(aName, name, std::to_string(info[i + 1])); // std::to_string(i)
80  _code << _endline;
81 
82  } else {
83  i = newI - 1;
84  }
85  }
86 
87  return name;
88 }
89 
90 template<class Base>
91 inline size_t LanguageDot<Base>::printArrayCreationUsingLoop(const std::string& arrayName,
92  const OperationNode<Base>& array,
93  size_t starti,
94  const size_t* indexes) {
95 
96  const std::vector<Argument<Base> >& args = array.getArguments();
97  const size_t argSize = args.size();
98  size_t i = starti + 1;
99 
103  if(args[starti].getParameter() == nullptr)
104  return starti;
105 
106  const Base& value = *args[starti].getParameter();
107  for (; i < argSize; i++) {
108  if (args[i].getParameter() == nullptr ||
109  *args[i].getParameter() != value) {
110  break; // not the same constant value
111  }
112 
113  if (indexes != nullptr && i - starti != indexes[i] - indexes[starti])
114  break; // not the same constant value
115  }
116 
117  if (i - starti < 3)
118  return starti;
119 
120  std::string aName = print(args[starti]);
121 
125  if (indexes != nullptr)
126  printEdge(aName, arrayName, std::to_string(indexes[starti]) + "..." + std::to_string(indexes[i]));
127  else
128  printEdge(aName, arrayName, std::to_string(starti) + "..." + std::to_string(i));
129  _code << _endline;
130 
131  return i;
132 }
133 
134 template<class Base>
136  CPPADCG_ASSERT_KNOWN(op.getArguments().size() == 2, "Invalid number of arguments for array element operation")
137  CPPADCG_ASSERT_KNOWN(op.getArguments()[0].getOperation() != nullptr, "Invalid argument for array element operation")
138  CPPADCG_ASSERT_KNOWN(op.getInfo().size() == 1, "Invalid number of information indexes for array element operation")
139 
140  std::string name = makeNodeName(op);
141 
142  _ss.str("");
143  _ss << "[" << op.getInfo()[0] << "]";
144  printEdges(name, op, std::vector<std::string>{}, std::vector<std::string>{_ss.str()});
145 
146  return name;
147 }
148 
149 } // END cg namespace
150 } // END CppAD namespace
151 
152 #endif
size_t printArrayCreationUsingLoop(const std::string &arrayName, const OperationNode< Base > &array, size_t startj, const size_t *indexes)
const std::vector< Argument< Base > > & getArguments() const
const std::vector< size_t > & getInfo() const