1 #ifndef CPPAD_CG_EVALUATOR_INCLUDED 2 #define CPPAD_CG_EVALUATOR_INCLUDED 23 template<
class ScalarIn,
class ScalarOut,
class ActiveOut,
class FinalEvaluatorType>
26 template<
class ScalarIn,
class ScalarOut,
class ActiveOut,
class Operations>
44 template<
class ScalarIn,
class ScalarOut,
class ActiveOut,
class FinalEvaluatorType>
46 friend FinalEvaluatorType;
51 const ActiveOut* indep_;
53 std::map<size_t, std::vector<ActiveOut>* > evalsArrays_;
54 std::map<size_t, std::vector<ActiveOut>* > evalsSparseArrays_;
95 std::vector<ActiveOut> depNew(depOld.size());
97 evaluate(indepNew.
data(), indepNew.
size(), depNew.data(), depOld.data(), depNew.size());
117 if (depNew.
size() != depOld.size()) {
118 throw CGException(
"Dependent array sizes are different.");
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.");
161 if(path_.capacity() == 0) {
165 FinalEvaluatorType& thisOps =
static_cast<FinalEvaluatorType&
>(*this);
168 thisOps.prepareNewEvaluation();
171 thisOps.analyzeOutIndeps(indep_, indepSize);
173 for (
size_t i = 0; i < depSize; i++) {
174 CPPADCG_ASSERT_UNKNOWN(depth_ == 0);
175 depNew[i] = evalCG(depOld[i]);
190 inline void prepareNewEvaluation() {
200 for (
const auto& p : evalsArrays_) {
203 evalsArrays_.clear();
205 for (
const auto& p : evalsSparseArrays_) {
208 evalsSparseArrays_.clear();
211 inline void analyzeOutIndeps(
const ActiveOut* indep,
221 return evalOperations(*dep.getOperationNode());
227 return evalArg(args[pos], pos);
232 if (arg.getOperation() !=
nullptr) {
233 path_.back().argIndex = pos;
234 ActiveOut a = evalOperations(*arg.getOperation());
238 return ActiveOut(*arg.getParameter());
246 if (evals_[node] !=
nullptr) {
247 return *evals_[node];
251 FinalEvaluatorType& thisOps =
static_cast<FinalEvaluatorType&
>(*this);
256 ActiveOut result = thisOps.evalOperation(node);
259 ActiveOut* resultPtr = saveEvaluation(node, ActiveOut(result));
268 ActiveOut&& result) {
269 std::unique_ptr<ActiveOut>& resultPtr = evals_[node];
270 CPPADCG_ASSERT_UNKNOWN(resultPtr ==
nullptr);
271 resultPtr.reset(
new ActiveOut(std::move(result)));
273 ActiveOut* resultPtr2 = resultPtr.get();
275 FinalEvaluatorType& thisOps =
static_cast<FinalEvaluatorType&
>(*this);
276 thisOps.processActiveOut(node, *resultPtr2);
283 CPPADCG_ASSERT_KNOWN(node.
getOperationType() == CGOpCode::ArrayCreation,
"Invalid array creation operation");
288 if (it != evalsArrays_.end()) {
292 const std::vector<Argument<ScalarIn> >& args = node.
getArguments();
293 auto* resultArray =
new std::vector<ActiveOut>(args.size());
299 for (
size_t a = 0; a < args.size(); a++) {
300 (*resultArray)[a] = evalArg(args, a);
308 CPPADCG_ASSERT_KNOWN(node.
getOperationType() == CGOpCode::SparseArrayCreation,
"Invalid array creation operation");
313 if (it != evalsSparseArrays_.end()) {
317 const std::vector<Argument<ScalarIn> >& args = node.
getArguments();
318 auto* resultArray =
new std::vector<ActiveOut>(args.size());
324 for (
size_t a = 0; a < args.size(); a++) {
325 (*resultArray)[a] = evalArg(args, a);
344 template<
class ScalarIn,
class ScalarOut,
class ActiveOut,
class FinalEvaluatorType>
350 friend class EvaluatorBase<ScalarIn, ScalarOut, ActiveOut, FinalEvaluatorType>;
375 FinalEvaluatorType& thisOps =
static_cast<FinalEvaluatorType&
>(*this);
379 case CGOpCode::Assign:
380 return thisOps.evalAssign(node);
383 return thisOps.evalAbs(node);
386 return thisOps.evalAcos(node);
389 return thisOps.evalAdd(node);
391 case CGOpCode::Alias:
392 return thisOps.evalAlias(node);
395 case CGOpCode::ArrayElement:
396 return thisOps.evalArrayElement(node);
399 return thisOps.evalAsin(node);
402 return thisOps.evalAtan(node);
406 case CGOpCode::ComLt:
407 return thisOps.evalCompareLt(node);
409 case CGOpCode::ComLe:
410 return thisOps.evalCompareLe(node);
412 case CGOpCode::ComEq:
413 return thisOps.evalCompareEq(node);
415 case CGOpCode::ComGe:
416 return thisOps.evalCompareGe(node);
418 case CGOpCode::ComGt:
419 return thisOps.evalCompareGt(node);
421 case CGOpCode::ComNe:
422 return thisOps.evalCompareNe(node);
425 return thisOps.evalCosh(node);
428 return thisOps.evalCos(node);
431 return thisOps.evalDiv(node);
434 return thisOps.evalExp(node);
437 return thisOps.evalIndependent(node);
440 return thisOps.evalLog(node);
443 return thisOps.evalMul(node);
446 return thisOps.evalPow(node);
449 return thisOps.evalPrint(node);
453 return thisOps.evalSign(node);
456 return thisOps.evalSinh(node);
459 return thisOps.evalSin(node);
462 return thisOps.evalSqrt(node);
465 return thisOps.evalSub(node);
468 return thisOps.evalTanh(node);
471 return thisOps.evalTan(node);
473 case CGOpCode::UnMinus:
474 return thisOps.evalMinus(node);
477 return thisOps.evalUnsupportedOperation(node);
481 inline ActiveOut evalAssign(
const NodeIn& node) {
483 CPPADCG_ASSERT_KNOWN(args.size() == 1,
"Invalid number of arguments for assign()")
484 return evalArg(args, 0);
487 inline ActiveOut evalAbs(
const NodeIn& node) {
489 CPPADCG_ASSERT_KNOWN(args.size() == 1,
"Invalid number of arguments for abs()")
490 return abs(evalArg(args, 0));
493 inline ActiveOut evalAcos(
const NodeIn& node) {
495 CPPADCG_ASSERT_KNOWN(args.size() == 1,
"Invalid number of arguments for acos()")
496 return acos(evalArg(args, 0));
499 inline ActiveOut evalAdd(
const NodeIn& node) {
501 CPPADCG_ASSERT_KNOWN(args.size() == 2,
"Invalid number of arguments for addition")
502 return evalArg(args, 0) + evalArg(args, 1);
505 inline ActiveOut evalAlias(
const NodeIn& node) {
507 CPPADCG_ASSERT_KNOWN(args.size() == 1,
"Invalid number of arguments for alias")
508 return evalArg(args, 0);
511 inline ActiveOut evalArrayElement(
const NodeIn& node) {
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());
521 FinalEvaluatorType& thisOps =
static_cast<FinalEvaluatorType&
>(*this);
522 thisOps.evalAtomicOperation(*args[1].getOperation());
527 inline ActiveOut evalAsin(
const NodeIn& node) {
529 CPPADCG_ASSERT_KNOWN(args.size() == 1,
"Invalid number of arguments for asin()")
530 return asin(evalArg(args, 0));
533 inline ActiveOut evalAtan(
const NodeIn& node) {
535 CPPADCG_ASSERT_KNOWN(args.size() == 1,
"Invalid number of arguments for atan()")
536 return atan(evalArg(args, 0));
539 inline ActiveOut evalCompareLt(
const NodeIn& node) {
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));
545 inline ActiveOut evalCompareLe(
const NodeIn& node) {
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));
551 inline ActiveOut evalCompareEq(
const NodeIn& node) {
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));
557 inline ActiveOut evalCompareGe(
const NodeIn& node) {
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));
563 inline ActiveOut evalCompareGt(
const NodeIn& node) {
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));
569 inline ActiveOut evalCompareNe(
const NodeIn& node) {
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));
575 inline ActiveOut evalCosh(
const NodeIn& node) {
577 CPPADCG_ASSERT_KNOWN(args.size() == 1,
"Invalid number of arguments for cosh()")
578 return cosh(evalArg(args, 0));
581 inline ActiveOut evalCos(
const NodeIn& node) {
583 CPPADCG_ASSERT_KNOWN(args.size() == 1,
"Invalid number of arguments for cos()")
584 return cos(evalArg(args, 0));
587 inline ActiveOut evalDiv(
const NodeIn& node) {
589 CPPADCG_ASSERT_KNOWN(args.size() == 2,
"Invalid number of arguments for division")
590 return evalArg(args, 0) / evalArg(args, 1);
593 inline ActiveOut evalExp(
const NodeIn& node) {
595 CPPADCG_ASSERT_KNOWN(args.size() == 1,
"Invalid number of arguments for exp()")
596 return exp(evalArg(args, 0));
599 inline ActiveOut evalIndependent(
const NodeIn& node) {
600 size_t index = this->handler_.getIndependentVariableIndex(node);
601 return this->indep_[index];
604 inline ActiveOut evalLog(
const NodeIn& node) {
606 CPPADCG_ASSERT_KNOWN(args.size() == 1,
"Invalid number of arguments for log()")
607 return log(evalArg(args, 0));
610 inline ActiveOut evalMul(
const NodeIn& node) {
612 CPPADCG_ASSERT_KNOWN(args.size() == 2,
"Invalid number of arguments for multiplication")
613 return evalArg(args, 0) * evalArg(args, 1);
616 inline ActiveOut evalPow(
const NodeIn& node) {
618 CPPADCG_ASSERT_KNOWN(args.size() == 2,
"Invalid number of arguments for pow()")
619 return pow(evalArg(args, 0), evalArg(args, 1));
622 inline ActiveOut evalPrint(
const NodeIn& node) {
623 FinalEvaluatorType& thisOps =
static_cast<FinalEvaluatorType&
>(*this);
624 return thisOps.evalUnsupportedOperation(node);
628 inline ActiveOut evalSign(
const NodeIn& node) {
630 CPPADCG_ASSERT_KNOWN(args.size() == 1,
"Invalid number of arguments for sign()")
631 return sign(evalArg(args, 0));
634 inline ActiveOut evalSinh(
const NodeIn& node) {
636 CPPADCG_ASSERT_KNOWN(args.size() == 1,
"Invalid number of arguments for sinh()")
637 return sinh(evalArg(args, 0));
640 inline ActiveOut evalSin(
const NodeIn& node) {
642 CPPADCG_ASSERT_KNOWN(args.size() == 1,
"Invalid number of arguments for sin()")
643 return sin(evalArg(args, 0));
646 inline ActiveOut evalSqrt(
const NodeIn& node) {
648 CPPADCG_ASSERT_KNOWN(args.size() == 1,
"Invalid number of arguments for sqrt()")
649 return sqrt(evalArg(args, 0));
652 inline ActiveOut evalSub(
const NodeIn& node) {
654 CPPADCG_ASSERT_KNOWN(args.size() == 2,
"Invalid number of arguments for subtraction")
655 return evalArg(args, 0) - evalArg(args, 1);
658 inline ActiveOut evalTanh(
const NodeIn& node) {
660 CPPADCG_ASSERT_KNOWN(args.size() == 1,
"Invalid number of arguments for tanh()")
661 return tanh(evalArg(args, 0));
664 inline ActiveOut evalTan(
const NodeIn& node) {
666 CPPADCG_ASSERT_KNOWN(args.size() == 1,
"Invalid number of arguments for tan()")
667 return tan(evalArg(args, 0));
670 inline ActiveOut evalMinus(
const NodeIn& node) {
672 CPPADCG_ASSERT_KNOWN(args.size() == 1,
"Invalid number of arguments for unary minus")
673 return -evalArg(args, 0);
676 inline ActiveOut evalUnsupportedOperation(
const NodeIn& node) {
680 inline void evalAtomicOperation(
const NodeIn& node) {
681 throw CGException(
"Evaluator is unable to handle atomic functions for these variable types");
684 inline void processActiveOut(
const NodeIn& node,
693 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