1 #ifndef CPPAD_CG_EVALUATOR_INCLUDED 2 #define CPPAD_CG_EVALUATOR_INCLUDED 22 template<
class ScalarIn,
class ScalarOut,
class ActiveOut,
class FinalEvaluatorType>
25 template<
class ScalarIn,
class ScalarOut,
class ActiveOut,
class Operations>
43 template<
class ScalarIn,
class ScalarOut,
class ActiveOut,
class FinalEvaluatorType>
45 friend FinalEvaluatorType;
50 const ActiveOut* indep_;
52 std::map<size_t, std::vector<ActiveOut>* > evalsArrays_;
53 std::map<size_t, std::vector<ActiveOut>* > evalsSparseArrays_;
94 std::vector<ActiveOut> depNew(depOld.size());
96 evaluate(indepNew.
data(), indepNew.
size(), depNew.data(), depOld.data(), depNew.size());
116 if (depNew.
size() != depOld.size()) {
117 throw CGException(
"Dependent array sizes are different.");
148 throw CGException(
"The same evaluator cannot be used for simultaneous evaluations. " 149 "Either use a new one or wait for this one to finish its current evaluation.");
160 if(path_.capacity() == 0) {
164 FinalEvaluatorType& thisOps =
static_cast<FinalEvaluatorType&
>(*this);
167 thisOps.prepareNewEvaluation();
170 thisOps.analyzeOutIndeps(indep_, indepSize);
172 for (
size_t i = 0; i < depSize; i++) {
173 CPPADCG_ASSERT_UNKNOWN(depth_ == 0);
174 depNew[i] = evalCG(depOld[i]);
189 inline void prepareNewEvaluation() {
199 for (
const auto& p : evalsArrays_) {
202 evalsArrays_.clear();
204 for (
const auto& p : evalsSparseArrays_) {
207 evalsSparseArrays_.clear();
210 inline void analyzeOutIndeps(
const ActiveOut* indep,
220 return evalOperations(*dep.getOperationNode());
226 return evalArg(args[pos], pos);
231 if (arg.getOperation() !=
nullptr) {
232 path_.back().argIndex = pos;
233 ActiveOut a = evalOperations(*arg.getOperation());
237 return ActiveOut(*arg.getParameter());
245 if (evals_[node] !=
nullptr) {
246 return *evals_[node];
250 FinalEvaluatorType& thisOps =
static_cast<FinalEvaluatorType&
>(*this);
255 ActiveOut result = thisOps.evalOperation(node);
258 ActiveOut* resultPtr = saveEvaluation(node, ActiveOut(result));
267 ActiveOut&& result) {
268 std::unique_ptr<ActiveOut>& resultPtr = evals_[node];
269 CPPADCG_ASSERT_UNKNOWN(resultPtr ==
nullptr);
270 resultPtr.reset(
new ActiveOut(std::move(result)));
272 ActiveOut* resultPtr2 = resultPtr.get();
274 FinalEvaluatorType& thisOps =
static_cast<FinalEvaluatorType&
>(*this);
275 thisOps.processActiveOut(node, *resultPtr2);
282 CPPADCG_ASSERT_KNOWN(node.
getOperationType() == CGOpCode::ArrayCreation,
"Invalid array creation operation");
287 if (it != evalsArrays_.end()) {
291 const std::vector<Argument<ScalarIn> >& args = node.
getArguments();
292 std::vector<ActiveOut>* resultArray =
new std::vector<ActiveOut>(args.size());
298 for (
size_t a = 0; a < args.size(); a++) {
299 (*resultArray)[a] = evalArg(args, a);
307 CPPADCG_ASSERT_KNOWN(node.
getOperationType() == CGOpCode::SparseArrayCreation,
"Invalid array creation operation");
312 if (it != evalsSparseArrays_.end()) {
316 const std::vector<Argument<ScalarIn> >& args = node.
getArguments();
317 std::vector<ActiveOut>* resultArray =
new std::vector<ActiveOut>(args.size());
323 for (
size_t a = 0; a < args.size(); a++) {
324 (*resultArray)[a] = evalArg(args, a);
343 template<
class ScalarIn,
class ScalarOut,
class ActiveOut,
class FinalEvaluatorType>
349 friend class EvaluatorBase<ScalarIn, ScalarOut, ActiveOut, FinalEvaluatorType>;
374 FinalEvaluatorType& thisOps =
static_cast<FinalEvaluatorType&
>(*this);
378 case CGOpCode::Assign:
379 return thisOps.evalAssign(node);
382 return thisOps.evalAbs(node);
385 return thisOps.evalAcos(node);
388 return thisOps.evalAdd(node);
390 case CGOpCode::Alias:
391 return thisOps.evalAlias(node);
394 case CGOpCode::ArrayElement:
395 return thisOps.evalArrayElement(node);
398 return thisOps.evalAsin(node);
401 return thisOps.evalAtan(node);
405 case CGOpCode::ComLt:
406 return thisOps.evalCompareLt(node);
408 case CGOpCode::ComLe:
409 return thisOps.evalCompareLe(node);
411 case CGOpCode::ComEq:
412 return thisOps.evalCompareEq(node);
414 case CGOpCode::ComGe:
415 return thisOps.evalCompareGe(node);
417 case CGOpCode::ComGt:
418 return thisOps.evalCompareGt(node);
420 case CGOpCode::ComNe:
421 return thisOps.evalCompareNe(node);
424 return thisOps.evalCosh(node);
427 return thisOps.evalCos(node);
430 return thisOps.evalDiv(node);
433 return thisOps.evalExp(node);
436 return thisOps.evalIndependent(node);
439 return thisOps.evalLog(node);
442 return thisOps.evalMul(node);
445 return thisOps.evalPow(node);
448 return thisOps.evalPrint(node);
452 return thisOps.evalSign(node);
455 return thisOps.evalSinh(node);
458 return thisOps.evalSin(node);
461 return thisOps.evalSqrt(node);
464 return thisOps.evalSub(node);
467 return thisOps.evalTanh(node);
470 return thisOps.evalTan(node);
472 case CGOpCode::UnMinus:
473 return thisOps.evalMinus(node);
476 return thisOps.evalUnsupportedOperation(node);
480 inline ActiveOut evalAssign(
const NodeIn& node) {
482 CPPADCG_ASSERT_KNOWN(args.size() == 1,
"Invalid number of arguments for assign()");
483 return evalArg(args, 0);
486 inline ActiveOut evalAbs(
const NodeIn& node) {
488 CPPADCG_ASSERT_KNOWN(args.size() == 1,
"Invalid number of arguments for abs()");
489 return abs(evalArg(args, 0));
492 inline ActiveOut evalAcos(
const NodeIn& node) {
494 CPPADCG_ASSERT_KNOWN(args.size() == 1,
"Invalid number of arguments for acos()");
495 return acos(evalArg(args, 0));
498 inline ActiveOut evalAdd(
const NodeIn& node) {
500 CPPADCG_ASSERT_KNOWN(args.size() == 2,
"Invalid number of arguments for addition");
501 return evalArg(args, 0) + evalArg(args, 1);
504 inline ActiveOut evalAlias(
const NodeIn& node) {
506 CPPADCG_ASSERT_KNOWN(args.size() == 1,
"Invalid number of arguments for alias");
507 return evalArg(args, 0);
510 inline ActiveOut evalArrayElement(
const NodeIn& node) {
512 const std::vector<size_t>& info = node.
getInfo();
513 CPPADCG_ASSERT_KNOWN(args.size() == 2,
"Invalid number of arguments for array element");
514 CPPADCG_ASSERT_KNOWN(args[0].getOperation() !=
nullptr,
"Invalid argument for array element");
515 CPPADCG_ASSERT_KNOWN(args[1].getOperation() !=
nullptr,
"Invalid argument for array element");
516 CPPADCG_ASSERT_KNOWN(info.size() == 1,
"Invalid number of information data for array element");
517 size_t index = info[0];
518 std::vector<ActiveOut>& array = this->evalArrayCreationOperation(*args[0].getOperation());
520 FinalEvaluatorType& thisOps =
static_cast<FinalEvaluatorType&
>(*this);
521 thisOps.evalAtomicOperation(*args[1].getOperation());
526 inline ActiveOut evalAsin(
const NodeIn& node) {
528 CPPADCG_ASSERT_KNOWN(args.size() == 1,
"Invalid number of arguments for asin()");
529 return asin(evalArg(args, 0));
532 inline ActiveOut evalAtan(
const NodeIn& node) {
534 CPPADCG_ASSERT_KNOWN(args.size() == 1,
"Invalid number of arguments for atan()");
535 return atan(evalArg(args, 0));
538 inline ActiveOut evalCompareLt(
const NodeIn& node) {
540 CPPADCG_ASSERT_KNOWN(args.size() == 4,
"Invalid number of arguments for CondExpOp(CompareLt, )");
541 return CondExpOp(CompareLt, evalArg(args, 0), evalArg(args, 1), evalArg(args, 2), evalArg(args, 3));
544 inline ActiveOut evalCompareLe(
const NodeIn& node) {
546 CPPADCG_ASSERT_KNOWN(args.size() == 4,
"Invalid number of arguments for CondExpOp(CompareLe, )");
547 return CondExpOp(CompareLe, evalArg(args, 0), evalArg(args, 1), evalArg(args, 2), evalArg(args, 3));
550 inline ActiveOut evalCompareEq(
const NodeIn& node) {
552 CPPADCG_ASSERT_KNOWN(args.size() == 4,
"Invalid number of arguments for CondExpOp(CompareEq, )");
553 return CondExpOp(CompareEq, evalArg(args, 0), evalArg(args, 1), evalArg(args, 2), evalArg(args, 3));
556 inline ActiveOut evalCompareGe(
const NodeIn& node) {
558 CPPADCG_ASSERT_KNOWN(args.size() == 4,
"Invalid number of arguments for CondExpOp(CompareGe, )");
559 return CondExpOp(CompareGe, evalArg(args, 0), evalArg(args, 1), evalArg(args, 2), evalArg(args, 3));
562 inline ActiveOut evalCompareGt(
const NodeIn& node) {
564 CPPADCG_ASSERT_KNOWN(args.size() == 4,
"Invalid number of arguments for CondExpOp(CompareGt, )");
565 return CondExpOp(CompareGt, evalArg(args, 0), evalArg(args, 1), evalArg(args, 2), evalArg(args, 3));
568 inline ActiveOut evalCompareNe(
const NodeIn& node) {
570 CPPADCG_ASSERT_KNOWN(args.size() == 4,
"Invalid number of arguments for CondExpOp(CompareNe, )");
571 return CondExpOp(CompareNe, evalArg(args, 0), evalArg(args, 1), evalArg(args, 2), evalArg(args, 3));
574 inline ActiveOut evalCosh(
const NodeIn& node) {
576 CPPADCG_ASSERT_KNOWN(args.size() == 1,
"Invalid number of arguments for cosh()");
577 return cosh(evalArg(args, 0));
580 inline ActiveOut evalCos(
const NodeIn& node) {
582 CPPADCG_ASSERT_KNOWN(args.size() == 1,
"Invalid number of arguments for cos()");
583 return cos(evalArg(args, 0));
586 inline ActiveOut evalDiv(
const NodeIn& node) {
588 CPPADCG_ASSERT_KNOWN(args.size() == 2,
"Invalid number of arguments for division");
589 return evalArg(args, 0) / evalArg(args, 1);
592 inline ActiveOut evalExp(
const NodeIn& node) {
594 CPPADCG_ASSERT_KNOWN(args.size() == 1,
"Invalid number of arguments for exp()");
595 return exp(evalArg(args, 0));
598 inline ActiveOut evalIndependent(
const NodeIn& node) {
599 size_t index = this->handler_.getIndependentVariableIndex(node);
600 return this->indep_[index];
603 inline ActiveOut evalLog(
const NodeIn& node) {
605 CPPADCG_ASSERT_KNOWN(args.size() == 1,
"Invalid number of arguments for log()");
606 return log(evalArg(args, 0));
609 inline ActiveOut evalMul(
const NodeIn& node) {
611 CPPADCG_ASSERT_KNOWN(args.size() == 2,
"Invalid number of arguments for multiplication");
612 return evalArg(args, 0) * evalArg(args, 1);
615 inline ActiveOut evalPow(
const NodeIn& node) {
617 CPPADCG_ASSERT_KNOWN(args.size() == 2,
"Invalid number of arguments for pow()");
618 return pow(evalArg(args, 0), evalArg(args, 1));
621 inline ActiveOut evalPrint(
const NodeIn& node) {
622 FinalEvaluatorType& thisOps =
static_cast<FinalEvaluatorType&
>(*this);
623 return thisOps.evalUnsupportedOperation(node);
627 inline ActiveOut evalSign(
const NodeIn& node) {
629 CPPADCG_ASSERT_KNOWN(args.size() == 1,
"Invalid number of arguments for sign()");
630 return sign(evalArg(args, 0));
633 inline ActiveOut evalSinh(
const NodeIn& node) {
635 CPPADCG_ASSERT_KNOWN(args.size() == 1,
"Invalid number of arguments for sinh()");
636 return sinh(evalArg(args, 0));
639 inline ActiveOut evalSin(
const NodeIn& node) {
641 CPPADCG_ASSERT_KNOWN(args.size() == 1,
"Invalid number of arguments for sin()");
642 return sin(evalArg(args, 0));
645 inline ActiveOut evalSqrt(
const NodeIn& node) {
647 CPPADCG_ASSERT_KNOWN(args.size() == 1,
"Invalid number of arguments for sqrt()");
648 return sqrt(evalArg(args, 0));
651 inline ActiveOut evalSub(
const NodeIn& node) {
653 CPPADCG_ASSERT_KNOWN(args.size() == 2,
"Invalid number of arguments for subtraction");
654 return evalArg(args, 0) - evalArg(args, 1);
657 inline ActiveOut evalTanh(
const NodeIn& node) {
659 CPPADCG_ASSERT_KNOWN(args.size() == 1,
"Invalid number of arguments for tanh()");
660 return tanh(evalArg(args, 0));
663 inline ActiveOut evalTan(
const NodeIn& node) {
665 CPPADCG_ASSERT_KNOWN(args.size() == 1,
"Invalid number of arguments for tan()");
666 return tan(evalArg(args, 0));
669 inline ActiveOut evalMinus(
const NodeIn& node) {
671 CPPADCG_ASSERT_KNOWN(args.size() == 1,
"Invalid number of arguments for unary minus");
672 return -evalArg(args, 0);
675 inline ActiveOut evalUnsupportedOperation(
const NodeIn& node) {
679 inline void evalAtomicOperation(
const NodeIn& node) {
680 throw CGException(
"Evaluator is unable to handle atomic functions for these variable types");
683 inline void processActiveOut(
const NodeIn& node,
692 template<
class ScalarIn,
class ScalarOut,
class ActiveOut = CppAD::AD<ScalarOut> >
std::vector< ActiveOut > evaluate(ArrayView< const ActiveOut > indepNew, ArrayView< const CG< ScalarIn > > depOld)
const Base & getValue() const
const std::vector< Argument< Base > > & getArguments() const
ActiveOut evalOperation(OperationNode< ScalarIn > &node)
size_t getHandlerPosition() const
void evaluate(ArrayView< const ActiveOut > indepNew, ArrayView< ActiveOut > depNew, ArrayView< const CG< ScalarIn > > depOld)
cg::CG< Base > pow(const cg::CG< Base > &x, const cg::CG< Base > &y)
size_t getIndependentVariableSize() const
CGOpCode getOperationType() const
size_t getManagedNodesCount() const
EvaluatorBase(CodeHandler< ScalarIn > &handler)
void evaluate(const ActiveOut *indepNew, size_t indepSize, ActiveOut *depNew, const CG< ScalarIn > *depOld, size_t depSize)
size_t size() const noexcept
cg::CG< Base > sign(const cg::CG< Base > &x)
const std::vector< size_t > & getInfo() const