CppADCodeGen  HEAD
A C++ Algorithmic Differentiation Package with Source Code Generation
evaluator.hpp
1 #ifndef CPPAD_CG_EVALUATOR_INCLUDED
2 #define CPPAD_CG_EVALUATOR_INCLUDED
3 /* --------------------------------------------------------------------------
4  * CppADCodeGen: C++ Algorithmic Differentiation with Source Code Generation:
5  * Copyright (C) 2012 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 // forward declarations
23 template<class ScalarIn, class ScalarOut, class ActiveOut, class FinalEvaluatorType>
25 
26 template<class ScalarIn, class ScalarOut, class ActiveOut, class Operations>
28 
44 template<class ScalarIn, class ScalarOut, class ActiveOut, class FinalEvaluatorType>
45 class EvaluatorBase {
46  friend FinalEvaluatorType;
47 protected:
48  using SourceCodePath = typename CodeHandler<ScalarIn>::SourceCodePath;
49 protected:
50  CodeHandler<ScalarIn>& handler_;
51  const ActiveOut* indep_;
53  std::map<size_t, std::vector<ActiveOut>* > evalsArrays_;
54  std::map<size_t, std::vector<ActiveOut>* > evalsSparseArrays_;
55  bool underEval_;
56  size_t depth_;
57  SourceCodePath path_;
58 public:
59 
64  handler_(handler),
65  indep_(nullptr),
66  evals_(handler),
67  underEval_(false),
68  depth_(0) { // not really required (but it avoids warnings)
69  }
70 
71  inline virtual ~EvaluatorBase() {
72  clear();
73  }
74 
78  inline bool isUnderEvaluation() {
79  return underEval_;
80  }
81 
93  inline std::vector<ActiveOut> evaluate(ArrayView<const ActiveOut> indepNew,
94  ArrayView<const CG<ScalarIn> > depOld) {
95  std::vector<ActiveOut> depNew(depOld.size());
96 
97  evaluate(indepNew.data(), indepNew.size(), depNew.data(), depOld.data(), depNew.size());
98 
99  return depNew;
100  }
101 
114  inline void evaluate(ArrayView<const ActiveOut> indepNew,
115  ArrayView<ActiveOut> depNew,
116  ArrayView<const CG<ScalarIn> > depOld) {
117  if (depNew.size() != depOld.size()) {
118  throw CGException("Dependent array sizes are different.");
119  }
120 
121  evaluate(indepNew.data(), indepNew.size(), depNew.data(), depOld.data(), depNew.size());
122  }
123 
137  inline void evaluate(const ActiveOut* indepNew,
138  size_t indepSize,
139  ActiveOut* depNew,
140  const CG<ScalarIn>* depOld,
141  size_t depSize) {
142  if (handler_.getIndependentVariableSize() != indepSize) {
143  throw CGException("Invalid independent variable size. Expected ", handler_.getIndependentVariableSize(), " but got ", indepSize, ".");
144  }
145 
146  CPPADCG_ASSERT_KNOWN(handler_.getIndependentVariableSize() == indepSize, "Invalid size the array of independent variables")
147 
148  if (underEval_) {
149  throw CGException("The same evaluator cannot be used for simultaneous evaluations. "
150  "Either use a new one or wait for this one to finish its current evaluation.");
151  }
152 
153  underEval_ = true;
154 
155  clear(); // clean-up from any previous call that might have failed
156  evals_.adjustSize();
157 
158  depth_ = 0;
159  path_.clear();
160 
161  if(path_.capacity() == 0) {
162  path_.reserve(30);
163  }
164 
165  FinalEvaluatorType& thisOps = static_cast<FinalEvaluatorType&>(*this);
166 
167  try {
168  thisOps.prepareNewEvaluation();
169 
170  indep_ = indepNew;
171  thisOps.analyzeOutIndeps(indep_, indepSize);
172 
173  for (size_t i = 0; i < depSize; i++) {
174  CPPADCG_ASSERT_UNKNOWN(depth_ == 0);
175  depNew[i] = evalCG(depOld[i]);
176  }
177 
178  thisOps.clear(); // clean-up
179 
180  } catch (...) {
181  underEval_ = false;
182  throw;
183  }
184 
185  underEval_ = false;
186  }
187 
188 protected:
189 
190  inline void prepareNewEvaluation() {
191  // empty
192  }
193 
197  inline void clear() {
198  evals_.clear();
199 
200  for (const auto& p : evalsArrays_) {
201  delete p.second;
202  }
203  evalsArrays_.clear();
204 
205  for (const auto& p : evalsSparseArrays_) {
206  delete p.second;
207  }
208  evalsSparseArrays_.clear();
209  }
210 
211  inline void analyzeOutIndeps(const ActiveOut* indep,
212  size_t n) {
213  // empty
214  }
215 
216  inline ActiveOut evalCG(const CG<ScalarIn>& dep) {
217  if (dep.isParameter()) {
218  // parameter
219  return ActiveOut(dep.getValue());
220  } else {
221  return evalOperations(*dep.getOperationNode());
222  }
223  }
224 
225  inline ActiveOut evalArg(const std::vector<Argument<ScalarIn> >& args,
226  size_t pos) {
227  return evalArg(args[pos], pos);
228  }
229 
230  inline ActiveOut evalArg(const Argument<ScalarIn>& arg,
231  size_t pos) {
232  if (arg.getOperation() != nullptr) {
233  path_.back().argIndex = pos;
234  ActiveOut a = evalOperations(*arg.getOperation());
235  return a;
236  } else {
237  // parameter
238  return ActiveOut(*arg.getParameter());
239  }
240  }
241 
242  inline const ActiveOut& evalOperations(OperationNode<ScalarIn>& node) {
243  CPPADCG_ASSERT_KNOWN(node.getHandlerPosition() < handler_.getManagedNodesCount(), "this node is not managed by the code handler")
244 
245  // check if this node was previously determined
246  if (evals_[node] != nullptr) {
247  return *evals_[node];
248  }
249 
250  // first evaluation of this node
251  FinalEvaluatorType& thisOps = static_cast<FinalEvaluatorType&>(*this);
252 
253  path_.push_back(OperationPathNode<ScalarIn>(&node, -1));
254  depth_++;
255 
256  ActiveOut result = thisOps.evalOperation(node);
257 
258  // save it for reuse
259  ActiveOut* resultPtr = saveEvaluation(node, ActiveOut(result));
260 
261  depth_--;
262  path_.pop_back();
263 
264  return *resultPtr;
265  }
266 
267  inline ActiveOut* saveEvaluation(const OperationNode<ScalarIn>& node,
268  ActiveOut&& result) {
269  std::unique_ptr<ActiveOut>& resultPtr = evals_[node];
270  CPPADCG_ASSERT_UNKNOWN(resultPtr == nullptr); // not supposed to override existing result
271  resultPtr.reset(new ActiveOut(std::move(result)));
272 
273  ActiveOut* resultPtr2 = resultPtr.get(); // do not use a reference (just in case evals_ is resized)
274 
275  FinalEvaluatorType& thisOps = static_cast<FinalEvaluatorType&>(*this);
276  thisOps.processActiveOut(node, *resultPtr2);
277 
278  return resultPtr2;
279  }
280 
281  inline std::vector<ActiveOut>& evalArrayCreationOperation(const OperationNode<ScalarIn>& node) {
282 
283  CPPADCG_ASSERT_KNOWN(node.getOperationType() == CGOpCode::ArrayCreation, "Invalid array creation operation");
284  CPPADCG_ASSERT_KNOWN(node.getHandlerPosition() < handler_.getManagedNodesCount(), "this node is not managed by the code handler")
285 
286  // check if this node was previously determined
287  auto it = evalsArrays_.find(node.getHandlerPosition());
288  if (it != evalsArrays_.end()) {
289  return *it->second;
290  }
291 
292  const std::vector<Argument<ScalarIn> >& args = node.getArguments();
293  auto* resultArray = new std::vector<ActiveOut>(args.size());
294 
295  // save it for reuse
296  evalsArrays_[node.getHandlerPosition()] = resultArray;
297 
298  // define its elements
299  for (size_t a = 0; a < args.size(); a++) {
300  (*resultArray)[a] = evalArg(args, a);
301  }
302 
303  return *resultArray;
304  }
305 
306  inline std::vector<ActiveOut>& evalSparseArrayCreationOperation(const OperationNode<ScalarIn>& node) {
307 
308  CPPADCG_ASSERT_KNOWN(node.getOperationType() == CGOpCode::SparseArrayCreation, "Invalid array creation operation");
309  CPPADCG_ASSERT_KNOWN(node.getHandlerPosition() < handler_.getManagedNodesCount(), "this node is not managed by the code handler")
310 
311  // check if this node was previously determined
312  auto it = evalsSparseArrays_.find(node.getHandlerPosition());
313  if (it != evalsSparseArrays_.end()) {
314  return *it->second;
315  }
316 
317  const std::vector<Argument<ScalarIn> >& args = node.getArguments();
318  auto* resultArray = new std::vector<ActiveOut>(args.size());
319 
320  // save it for reuse
321  evalsSparseArrays_[node.getHandlerPosition()] = resultArray;
322 
323  // define its elements
324  for (size_t a = 0; a < args.size(); a++) {
325  (*resultArray)[a] = evalArg(args, a);
326  }
327 
328  return *resultArray;
329  }
330 
331 };
332 
333 
344 template<class ScalarIn, class ScalarOut, class ActiveOut, class FinalEvaluatorType>
345 class EvaluatorOperations : public EvaluatorBase<ScalarIn, ScalarOut, ActiveOut, FinalEvaluatorType> {
350  friend class EvaluatorBase<ScalarIn, ScalarOut, ActiveOut, FinalEvaluatorType>;
351 public:
354  using ArgIn = Argument<ScalarIn>;
355 public:
357  Base(handler) {
358  }
359 
360  virtual ~EvaluatorOperations() { }
361 
362 protected:
363 
364  using Base::evalArg;
365 
374  inline ActiveOut evalOperation(OperationNode<ScalarIn>& node) {
375  FinalEvaluatorType& thisOps = static_cast<FinalEvaluatorType&>(*this);
376 
377  const CGOpCode code = node.getOperationType();
378  switch (code) {
379  case CGOpCode::Assign:
380  return thisOps.evalAssign(node);
381 
382  case CGOpCode::Abs: // abs(variable)
383  return thisOps.evalAbs(node);
384 
385  case CGOpCode::Acos: // acos(variable)
386  return thisOps.evalAcos(node);
387 
388  case CGOpCode::Add: // a + b
389  return thisOps.evalAdd(node);
390 
391  case CGOpCode::Alias:
392  return thisOps.evalAlias(node);
393 
394  //case CGArrayCreationOp: // {a, b, c ...}
395  case CGOpCode::ArrayElement: // x[i]
396  return thisOps.evalArrayElement(node);
397 
398  case CGOpCode::Asin: // asin(variable)
399  return thisOps.evalAsin(node);
400 
401  case CGOpCode::Atan: // atan(variable)
402  return thisOps.evalAtan(node);
403 
404  //CGAtomicForwardOp
405  //CGAtomicReverseOp
406  case CGOpCode::ComLt: // return left < right? trueCase: falseCase
407  return thisOps.evalCompareLt(node);
408 
409  case CGOpCode::ComLe: // return left <= right? trueCase: falseCase
410  return thisOps.evalCompareLe(node);
411 
412  case CGOpCode::ComEq: // return left == right? trueCase: falseCase
413  return thisOps.evalCompareEq(node);
414 
415  case CGOpCode::ComGe: // return left >= right? trueCase: falseCase
416  return thisOps.evalCompareGe(node);
417 
418  case CGOpCode::ComGt: // return left > right? trueCase: falseCase
419  return thisOps.evalCompareGt(node);
420 
421  case CGOpCode::ComNe: // return left != right? trueCase: falseCase
422  return thisOps.evalCompareNe(node);
423 
424  case CGOpCode::Cosh: // cosh(variable)
425  return thisOps.evalCosh(node);
426 
427  case CGOpCode::Cos: // cos(variable)
428  return thisOps.evalCos(node);
429 
430  case CGOpCode::Div: // a / b
431  return thisOps.evalDiv(node);
432 
433  case CGOpCode::Exp: // exp(variable)
434  return thisOps.evalExp(node);
435 
436  case CGOpCode::Inv: // independent variable
437  return thisOps.evalIndependent(node);
438 
439  case CGOpCode::Log: // log(variable)
440  return thisOps.evalLog(node);
441 
442  case CGOpCode::Mul: // a * b
443  return thisOps.evalMul(node);
444 
445  case CGOpCode::Pow: // pow(a, b)
446  return thisOps.evalPow(node);
447 
448  case CGOpCode::Pri: // pow(a, b)
449  return thisOps.evalPrint(node);
450  //case PriOp: // PrintFor(text, parameter or variable, parameter or variable)
451 
452  case CGOpCode::Sign: // return (x > 0)? 1.0:((x == 0)? 0.0:-1)
453  return thisOps.evalSign(node);
454 
455  case CGOpCode::Sinh: // sinh(variable)
456  return thisOps.evalSinh(node);
457 
458  case CGOpCode::Sin: // sin(variable)
459  return thisOps.evalSin(node);
460 
461  case CGOpCode::Sqrt: // sqrt(variable)
462  return thisOps.evalSqrt(node);
463 
464  case CGOpCode::Sub: // a - b
465  return thisOps.evalSub(node);
466 
467  case CGOpCode::Tanh: // tanh(variable)
468  return thisOps.evalTanh(node);
469 
470  case CGOpCode::Tan: // tan(variable)
471  return thisOps.evalTan(node);
472 
473  case CGOpCode::UnMinus: // -(a)
474  return thisOps.evalMinus(node);
475 
476  default:
477  return thisOps.evalUnsupportedOperation(node);
478  }
479  }
480 
481  inline ActiveOut evalAssign(const NodeIn& node) {
482  const std::vector<ArgIn>& args = node.getArguments();
483  CPPADCG_ASSERT_KNOWN(args.size() == 1, "Invalid number of arguments for assign()")
484  return evalArg(args, 0);
485  }
486 
487  inline ActiveOut evalAbs(const NodeIn& node) {
488  const std::vector<ArgIn>& args = node.getArguments();
489  CPPADCG_ASSERT_KNOWN(args.size() == 1, "Invalid number of arguments for abs()")
490  return abs(evalArg(args, 0));
491  }
492 
493  inline ActiveOut evalAcos(const NodeIn& node) {
494  const std::vector<ArgIn>& args = node.getArguments();
495  CPPADCG_ASSERT_KNOWN(args.size() == 1, "Invalid number of arguments for acos()")
496  return acos(evalArg(args, 0));
497  }
498 
499  inline ActiveOut evalAdd(const NodeIn& node) {
500  const std::vector<ArgIn>& args = node.getArguments();
501  CPPADCG_ASSERT_KNOWN(args.size() == 2, "Invalid number of arguments for addition")
502  return evalArg(args, 0) + evalArg(args, 1);
503  }
504 
505  inline ActiveOut evalAlias(const NodeIn& node) {
506  const std::vector<ArgIn>& args = node.getArguments();
507  CPPADCG_ASSERT_KNOWN(args.size() == 1, "Invalid number of arguments for alias")
508  return evalArg(args, 0);
509  }
510 
511  inline ActiveOut evalArrayElement(const NodeIn& node) {
512  const std::vector<ArgIn>& args = node.getArguments();
513  const std::vector<size_t>& info = node.getInfo();
514  CPPADCG_ASSERT_KNOWN(args.size() == 2, "Invalid number of arguments for array element")
515  CPPADCG_ASSERT_KNOWN(args[0].getOperation() != nullptr, "Invalid argument for array element");
516  CPPADCG_ASSERT_KNOWN(args[1].getOperation() != nullptr, "Invalid argument for array element");
517  CPPADCG_ASSERT_KNOWN(info.size() == 1, "Invalid number of information data for array element")
518  size_t index = info[0];
519  std::vector<ActiveOut>& array = this->evalArrayCreationOperation(*args[0].getOperation()); // array creation
520 
521  FinalEvaluatorType& thisOps = static_cast<FinalEvaluatorType&>(*this);
522  thisOps.evalAtomicOperation(*args[1].getOperation()); // atomic operation
523 
524  return array[index];
525  }
526 
527  inline ActiveOut evalAsin(const NodeIn& node) {
528  const std::vector<ArgIn>& args = node.getArguments();
529  CPPADCG_ASSERT_KNOWN(args.size() == 1, "Invalid number of arguments for asin()")
530  return asin(evalArg(args, 0));
531  }
532 
533  inline ActiveOut evalAtan(const NodeIn& node) {
534  const std::vector<ArgIn>& args = node.getArguments();
535  CPPADCG_ASSERT_KNOWN(args.size() == 1, "Invalid number of arguments for atan()")
536  return atan(evalArg(args, 0));
537  }
538 
539  inline ActiveOut evalCompareLt(const NodeIn& node) {
540  const std::vector<ArgIn>& args = node.getArguments();
541  CPPADCG_ASSERT_KNOWN(args.size() == 4, "Invalid number of arguments for CondExpOp(CompareLt, )")
542  return CondExpOp(CompareLt, evalArg(args, 0), evalArg(args, 1), evalArg(args, 2), evalArg(args, 3));
543  }
544 
545  inline ActiveOut evalCompareLe(const NodeIn& node) {
546  const std::vector<ArgIn>& args = node.getArguments();
547  CPPADCG_ASSERT_KNOWN(args.size() == 4, "Invalid number of arguments for CondExpOp(CompareLe, )")
548  return CondExpOp(CompareLe, evalArg(args, 0), evalArg(args, 1), evalArg(args, 2), evalArg(args, 3));
549  }
550 
551  inline ActiveOut evalCompareEq(const NodeIn& node) {
552  const std::vector<ArgIn>& args = node.getArguments();
553  CPPADCG_ASSERT_KNOWN(args.size() == 4, "Invalid number of arguments for CondExpOp(CompareEq, )")
554  return CondExpOp(CompareEq, evalArg(args, 0), evalArg(args, 1), evalArg(args, 2), evalArg(args, 3));
555  }
556 
557  inline ActiveOut evalCompareGe(const NodeIn& node) {
558  const std::vector<ArgIn>& args = node.getArguments();
559  CPPADCG_ASSERT_KNOWN(args.size() == 4, "Invalid number of arguments for CondExpOp(CompareGe, )")
560  return CondExpOp(CompareGe, evalArg(args, 0), evalArg(args, 1), evalArg(args, 2), evalArg(args, 3));
561  }
562 
563  inline ActiveOut evalCompareGt(const NodeIn& node) {
564  const std::vector<ArgIn>& args = node.getArguments();
565  CPPADCG_ASSERT_KNOWN(args.size() == 4, "Invalid number of arguments for CondExpOp(CompareGt, )")
566  return CondExpOp(CompareGt, evalArg(args, 0), evalArg(args, 1), evalArg(args, 2), evalArg(args, 3));
567  }
568 
569  inline ActiveOut evalCompareNe(const NodeIn& node) {
570  const std::vector<ArgIn>& args = node.getArguments();
571  CPPADCG_ASSERT_KNOWN(args.size() == 4, "Invalid number of arguments for CondExpOp(CompareNe, )")
572  return CondExpOp(CompareNe, evalArg(args, 0), evalArg(args, 1), evalArg(args, 2), evalArg(args, 3));
573  }
574 
575  inline ActiveOut evalCosh(const NodeIn& node) {
576  const std::vector<ArgIn>& args = node.getArguments();
577  CPPADCG_ASSERT_KNOWN(args.size() == 1, "Invalid number of arguments for cosh()")
578  return cosh(evalArg(args, 0));
579  }
580 
581  inline ActiveOut evalCos(const NodeIn& node) {
582  const std::vector<ArgIn>& args = node.getArguments();
583  CPPADCG_ASSERT_KNOWN(args.size() == 1, "Invalid number of arguments for cos()")
584  return cos(evalArg(args, 0));
585  }
586 
587  inline ActiveOut evalDiv(const NodeIn& node) {
588  const std::vector<ArgIn>& args = node.getArguments();
589  CPPADCG_ASSERT_KNOWN(args.size() == 2, "Invalid number of arguments for division")
590  return evalArg(args, 0) / evalArg(args, 1);
591  }
592 
593  inline ActiveOut evalExp(const NodeIn& node) {
594  const std::vector<ArgIn>& args = node.getArguments();
595  CPPADCG_ASSERT_KNOWN(args.size() == 1, "Invalid number of arguments for exp()")
596  return exp(evalArg(args, 0));
597  }
598 
599  inline ActiveOut evalIndependent(const NodeIn& node) {
600  size_t index = this->handler_.getIndependentVariableIndex(node);
601  return this->indep_[index];
602  }
603 
604  inline ActiveOut evalLog(const NodeIn& node) {
605  const std::vector<ArgIn>& args = node.getArguments();
606  CPPADCG_ASSERT_KNOWN(args.size() == 1, "Invalid number of arguments for log()")
607  return log(evalArg(args, 0));
608  }
609 
610  inline ActiveOut evalMul(const NodeIn& node) {
611  const std::vector<ArgIn>& args = node.getArguments();
612  CPPADCG_ASSERT_KNOWN(args.size() == 2, "Invalid number of arguments for multiplication")
613  return evalArg(args, 0) * evalArg(args, 1);
614  }
615 
616  inline ActiveOut evalPow(const NodeIn& node) {
617  const std::vector<ArgIn>& args = node.getArguments();
618  CPPADCG_ASSERT_KNOWN(args.size() == 2, "Invalid number of arguments for pow()")
619  return pow(evalArg(args, 0), evalArg(args, 1));
620  }
621 
622  inline ActiveOut evalPrint(const NodeIn& node) {
623  FinalEvaluatorType& thisOps = static_cast<FinalEvaluatorType&>(*this);
624  return thisOps.evalUnsupportedOperation(node);
625  }
626 
627  //case PriOp: // PrintFor(text, parameter or variable, parameter or variable)
628  inline ActiveOut evalSign(const NodeIn& node) {
629  const std::vector<ArgIn>& args = node.getArguments();
630  CPPADCG_ASSERT_KNOWN(args.size() == 1, "Invalid number of arguments for sign()")
631  return sign(evalArg(args, 0));
632  }
633 
634  inline ActiveOut evalSinh(const NodeIn& node) {
635  const std::vector<ArgIn>& args = node.getArguments();
636  CPPADCG_ASSERT_KNOWN(args.size() == 1, "Invalid number of arguments for sinh()")
637  return sinh(evalArg(args, 0));
638  }
639 
640  inline ActiveOut evalSin(const NodeIn& node) {
641  const std::vector<ArgIn>& args = node.getArguments();
642  CPPADCG_ASSERT_KNOWN(args.size() == 1, "Invalid number of arguments for sin()")
643  return sin(evalArg(args, 0));
644  }
645 
646  inline ActiveOut evalSqrt(const NodeIn& node) {
647  const std::vector<ArgIn>& args = node.getArguments();
648  CPPADCG_ASSERT_KNOWN(args.size() == 1, "Invalid number of arguments for sqrt()")
649  return sqrt(evalArg(args, 0));
650  }
651 
652  inline ActiveOut evalSub(const NodeIn& node) {
653  const std::vector<ArgIn>& args = node.getArguments();
654  CPPADCG_ASSERT_KNOWN(args.size() == 2, "Invalid number of arguments for subtraction")
655  return evalArg(args, 0) - evalArg(args, 1);
656  }
657 
658  inline ActiveOut evalTanh(const NodeIn& node) {
659  const std::vector<ArgIn>& args = node.getArguments();
660  CPPADCG_ASSERT_KNOWN(args.size() == 1, "Invalid number of arguments for tanh()")
661  return tanh(evalArg(args, 0));
662  }
663 
664  inline ActiveOut evalTan(const NodeIn& node) {
665  const std::vector<ArgIn>& args = node.getArguments();
666  CPPADCG_ASSERT_KNOWN(args.size() == 1, "Invalid number of arguments for tan()")
667  return tan(evalArg(args, 0));
668  }
669 
670  inline ActiveOut evalMinus(const NodeIn& node) {
671  const std::vector<ArgIn>& args = node.getArguments();
672  CPPADCG_ASSERT_KNOWN(args.size() == 1, "Invalid number of arguments for unary minus")
673  return -evalArg(args, 0);
674  }
675 
676  inline ActiveOut evalUnsupportedOperation(const NodeIn& node) {
677  throw CGException("Unknown operation code '", node.getOperationType(), "'");
678  }
679 
680  inline void evalAtomicOperation(const NodeIn& node) {
681  throw CGException("Evaluator is unable to handle atomic functions for these variable types");
682  }
683 
684  inline void processActiveOut(const NodeIn& node,
685  ActiveOut& a) {
686  }
687 };
688 
693 template<class ScalarIn, class ScalarOut, class ActiveOut = CppAD::AD<ScalarOut> >
694 class Evaluator : public EvaluatorOperations<ScalarIn, ScalarOut, ActiveOut, Evaluator<ScalarIn, ScalarOut, ActiveOut> > {
695 public:
697 public:
698 
699  inline Evaluator(CodeHandler<ScalarIn>& handler) :
700  Base(handler) {
701  }
702 
703  inline virtual ~Evaluator() = default;
704 };
705 
706 } // END cg namespace
707 } // END CppAD namespace
708 
709 #endif
std::vector< ActiveOut > evaluate(ArrayView< const ActiveOut > indepNew, ArrayView< const CG< ScalarIn > > depOld)
Definition: evaluator.hpp:93
pointer data() noexcept
Definition: array_view.hpp:220
const Base & getValue() const
Definition: variable.hpp:45
const std::vector< Argument< Base > > & getArguments() const
ActiveOut evalOperation(OperationNode< ScalarIn > &node)
Definition: evaluator.hpp:374
size_t getHandlerPosition() const
void evaluate(ArrayView< const ActiveOut > indepNew, ArrayView< ActiveOut > depNew, ArrayView< const CG< ScalarIn > > depOld)
Definition: evaluator.hpp:114
cg::CG< Base > pow(const cg::CG< Base > &x, const cg::CG< Base > &y)
Definition: math_other.hpp:21
size_t getIndependentVariableSize() const
CGOpCode getOperationType() const
size_t getManagedNodesCount() const
EvaluatorBase(CodeHandler< ScalarIn > &handler)
Definition: evaluator.hpp:63
void evaluate(const ActiveOut *indepNew, size_t indepSize, ActiveOut *depNew, const CG< ScalarIn > *depOld, size_t depSize)
Definition: evaluator.hpp:137
size_t size() const noexcept
Definition: array_view.hpp:202
bool isParameter() const
Definition: variable.hpp:35
cg::CG< Base > sign(const cg::CG< Base > &x)
Definition: math_other.hpp:74
const std::vector< size_t > & getInfo() const