39 static const std::string U_INDEX_TYPE;
40 static const std::string ATOMICFUN_STRUCT_DEFINITION;
42 static const std::string _C_COMP_OP_LT;
43 static const std::string _C_COMP_OP_LE;
44 static const std::string _C_COMP_OP_EQ;
45 static const std::string _C_COMP_OP_GE;
46 static const std::string _C_COMP_OP_GT;
47 static const std::string _C_COMP_OP_NE;
48 static const std::string _C_STATIC_INDEX_ARRAY;
49 static const std::string _C_SPARSE_INDEX_ARRAY;
50 static const std::string _ATOMIC_TX;
51 static const std::string _ATOMIC_TY;
52 static const std::string _ATOMIC_PX;
53 static const std::string _ATOMIC_PY;
55 class AtomicFuncArray;
58 const std::string _baseTypeName;
60 const std::string _spaces;
62 std::unique_ptr<LanguageGenerationData<Base>> _info;
64 std::string _indentation;
66 std::string _inArgName;
68 std::string _outArgName;
70 std::string _atomicArgName;
72 std::ostringstream _code;
76 std::ostringstream _ss;
80 size_t _independentSize;
82 size_t _minTemporaryVarID;
85 std::map<size_t, size_t> _dependentIDs;
89 std::map<size_t, Node*> _temporary;
91 std::string _depAssignOperation;
93 bool _ignoreZeroDepAssign;
95 std::string _functionName;
97 size_t _maxAssignmentsPerFunction;
99 size_t _maxOperationsPerAssignment;
101 std::map<std::string, std::string>* _sources;
103 std::vector<const Arg*> _tmpArrayValues;
105 std::vector<const Arg*> _tmpSparseArrayValues;
107 std::map<std::string, AtomicFuncArray> _atomicFuncArrays;
109 std::vector<const Node*> _funcArgIndexes;
110 std::vector<const LoopStartOperationNode<Base>*> _currentLoops;
112 size_t _parameterPrecision;
114 std::vector<std::string> funcArgDcl_;
115 std::vector<std::string> localFuncArgDcl_;
116 std::string localFuncArgs_;
117 std::string auxArrayName_;
134 _atomicArgName(
"atomicFun"),
138 _minTemporaryVarID(0),
140 _depAssignOperation(
"="),
141 _ignoreZeroDepAssign(
false),
142 _maxAssignmentsPerFunction(0),
150 inline const std::string& getArgumentIn()
const {
154 inline void setArgumentIn(
const std::string&
inArgName) {
158 inline const std::string& getArgumentOut()
const {
162 inline void setArgumentOut(
const std::string&
outArgName) {
166 inline const std::string& getArgumentAtomic()
const {
167 return _atomicArgName;
170 inline void setArgumentAtomic(
const std::string&
atomicArgName) {
174 inline const std::string& getDependentAssignOperation()
const {
175 return _depAssignOperation;
190 return _ignoreZeroDepAssign;
201 _ignoreZeroDepAssign =
ignore;
204 virtual void setGenerateFunction(
const std::string&
functionName) {
208 virtual void setFunctionIndexArgument(
const Node&
funcArgIndex) {
209 _funcArgIndexes.resize(1);
213 virtual void setFunctionIndexArguments(
const std::vector<const Node*>&
funcArgIndexes) {
217 virtual const std::vector<const Node*>& getFunctionIndexArguments()
const {
218 return _funcArgIndexes;
228 return _parameterPrecision;
238 _parameterPrecision =
p;
253 std::map<std::string, std::string>*
sources) {
264 return _maxOperationsPerAssignment;
312 CPPADCG_ASSERT_UNKNOWN(_nameGen !=
nullptr);
317 CPPADCG_ASSERT_KNOWN(
tmpArg.size() == 3,
318 "There must be two temporary variables")
320 _ss << _spaces <<
"// auxiliary variables\n";
327 _ss << _spaces << _baseTypeName <<
" " <<
tmpArg[0].name <<
"[" << size <<
"];\n";
329 }
else if (_temporary.size() > 0) {
330 for (
const std::pair<size_t, Node*>&
p : _temporary) {
332 if (
var->getName() ==
nullptr) {
337 Node*
var1 = _temporary.begin()->second;
339 _ss << _spaces << _baseTypeName <<
" " <<
varName1;
341 typename std::map<size_t, Node*>::const_iterator
it = _temporary.begin();
342 for (
it++;
it != _temporary.end(); ++
it) {
343 _ss <<
", " << *
it->second->getName();
353 _ss << _spaces << _baseTypeName <<
" " <<
tmpArg[1].name <<
"[" <<
arraySize <<
"];\n";
361 _ss << _spaces << _baseTypeName <<
" " <<
tmpArg[2].name <<
"[" <<
sArraySize <<
"];\n";
362 _ss << _spaces << U_INDEX_TYPE <<
" " << _C_SPARSE_INDEX_ARRAY <<
"[" <<
sArraySize <<
"];\n";
371 _ss << _spaces << _baseTypeName <<
"* " << auxArrayName_ <<
";\n";
376 _ss << _spaces << U_INDEX_TYPE <<
" i;\n";
380 createIndexDeclaration();
383 std::string
code = _ss.str();
389 inline void generateArrayContainersDeclaration(std::ostringstream&
ss,
403 virtual void generateArrayContainersDeclaration(std::ostringstream&
ss,
409 ss << _spaces <<
"Array " << _ATOMIC_TY <<
";\n";
411 ss << _spaces <<
"Array " << _ATOMIC_PX <<
";\n";
412 ss << _spaces <<
"Array " << _ATOMIC_PY <<
"[" << (
maxReverseOrder + 1) <<
"];\n";
417 virtual std::string generateDependentVariableDeclaration() {
419 CPPADCG_ASSERT_KNOWN(!
depArg.empty(),
420 "There must be at least one dependent argument")
424 _ss << _spaces << argumentDeclaration(
depArg[
i]) <<
" = " << _outArgName <<
"[" <<
i <<
"];\n";
427 std::string
code = _ss.str();
432 virtual std::string generateIndependentVariableDeclaration() {
434 CPPADCG_ASSERT_KNOWN(!
indArg.empty(),
435 "There must be at least one independent argument")
439 _ss << _spaces <<
"const " << argumentDeclaration(
indArg[
i]) <<
" = " << _inArgName <<
"[" <<
i <<
"];\n";
442 std::string
code = _ss.str();
447 inline std::string generateArgumentAtomicDcl()
const {
448 return "struct LangCAtomicFun " + _atomicArgName;
451 virtual std::string generateFunctionArgumentsDcl()
const {
452 std::string
args = generateFunctionIndexArgumentsDcl();
455 args += generateDefaultFunctionArgumentsDcl();
460 virtual std::vector<std::string> generateFunctionArgumentsDcl2()
const {
461 std::vector<std::string>
args = generateFunctionIndexArgumentsDcl2();
462 std::vector<std::string>
dArgs = generateDefaultFunctionArgumentsDcl2();
467 virtual std::string generateDefaultFunctionArgumentsDcl()
const {
468 return implode(generateDefaultFunctionArgumentsDcl2(),
", ");
471 virtual std::vector<std::string> generateDefaultFunctionArgumentsDcl2()
const {
472 return std::vector<std::string> {_baseTypeName +
" const *const * " + _inArgName,
473 _baseTypeName +
"*const * " + _outArgName,
474 generateArgumentAtomicDcl()};
477 virtual std::string generateFunctionIndexArgumentsDcl()
const {
478 return implode(generateFunctionIndexArgumentsDcl2(),
", ");
481 virtual std::vector<std::string> generateFunctionIndexArgumentsDcl2()
const {
482 std::vector<std::string>
argtxt(_funcArgIndexes.size());
483 for (
size_t a = 0;
a < _funcArgIndexes.size();
a++) {
484 argtxt[
a] = U_INDEX_TYPE +
" " + *_funcArgIndexes[
a]->getName();
489 virtual std::string generateDefaultFunctionArguments()
const {
490 return _inArgName +
", " + _outArgName +
", " + _atomicArgName;
493 virtual std::string generateFunctionIndexArguments()
const {
495 for (
size_t a = 0;
a < _funcArgIndexes.size();
a++) {
497 argtxt += *_funcArgIndexes[
a]->getName();
502 inline void createIndexDeclaration();
504 CPPAD_CG_C_LANG_FUNCNAME(abs)
505 CPPAD_CG_C_LANG_FUNCNAME(acos)
506 CPPAD_CG_C_LANG_FUNCNAME(asin)
507 CPPAD_CG_C_LANG_FUNCNAME(atan)
508 CPPAD_CG_C_LANG_FUNCNAME(cosh)
509 CPPAD_CG_C_LANG_FUNCNAME(cos)
510 CPPAD_CG_C_LANG_FUNCNAME(exp)
511 CPPAD_CG_C_LANG_FUNCNAME(log)
512 CPPAD_CG_C_LANG_FUNCNAME(sinh)
513 CPPAD_CG_C_LANG_FUNCNAME(sin)
514 CPPAD_CG_C_LANG_FUNCNAME(sqrt)
515 CPPAD_CG_C_LANG_FUNCNAME(tanh)
516 CPPAD_CG_C_LANG_FUNCNAME(tan)
517 CPPAD_CG_C_LANG_FUNCNAME(
pow)
519#if CPPAD_USE_CPLUSPLUS_2011
520 CPPAD_CG_C_LANG_FUNCNAME(
erf)
521 CPPAD_CG_C_LANG_FUNCNAME(
erfc)
522 CPPAD_CG_C_LANG_FUNCNAME(
asinh)
523 CPPAD_CG_C_LANG_FUNCNAME(
acosh)
524 CPPAD_CG_C_LANG_FUNCNAME(
atanh)
525 CPPAD_CG_C_LANG_FUNCNAME(
expm1)
526 CPPAD_CG_C_LANG_FUNCNAME(
log1p)
541 const std::vector<std::string>& arguments,
542 const std::vector<std::string>&
arguments2 = {}) {
546 for (
const std::string&
a : arguments) {
548 out <<
",\n" << std::setw(
offset) <<
" ";
555 out <<
",\n" << std::setw(
offset) <<
" ";
563 static inline void printIndexCondExpr(std::ostringstream&
out,
564 const std::vector<size_t>&
info,
565 const std::string& index) {
566 CPPADCG_ASSERT_KNOWN(
info.size() > 1 &&
info.size() % 2 == 0,
"Invalid number of information elements for an index condition expression operation")
573 size_t min =
info[
e];
574 size_t max =
info[
e + 1];
576 out << index <<
" == " << min;
577 }
else if (min == 0) {
578 out << index <<
" <= " << max;
579 }
else if (max == (std::numeric_limits<size_t>::max)()) {
580 out << min <<
" <= " << index;
586 out << min <<
" == " << index <<
" || " << index <<
" == " << max;
588 out << min <<
" <= " << index <<
" && " << index <<
" <= " << max;
600 static inline void printStaticIndexArray(std::ostringstream& os,
601 const std::string& name,
602 const std::vector<size_t>& values);
604 static inline void printStaticIndexMatrix(std::ostringstream& os,
605 const std::string& name,
606 const std::map<
size_t, std::map<size_t, size_t> >& values);
611 static inline void generateNames4RandomIndexPatterns(
const std::set<RandomIndexPattern*>&
randomPatterns);
617 static inline std::string indexPattern2String(
const IndexPattern&
ip,
620 static inline std::string indexPattern2String(
const IndexPattern&
ip,
621 const std::string& index);
623 static inline std::string indexPattern2String(
const IndexPattern&
ip,
624 const std::vector<const Node*>& indexes);
626 static inline std::string indexPattern2String(
const IndexPattern&
ip,
627 const std::vector<const std::string*>& indexes);
629 static inline std::string linearIndexPattern2String(
const LinearIndexPattern&
lip,
632 static inline std::string linearIndexPattern2String(
const LinearIndexPattern&
lip,
633 const std::string& index);
635 static inline bool isOffsetBy(
const IndexPattern*
ip,
636 const IndexPattern*
refIp,
639 static inline bool isOffsetBy(
const LinearIndexPattern*
lIp,
640 const LinearIndexPattern*
refLIp,
643 static inline bool isOffsetBy(
const LinearIndexPattern&
lIp,
644 const LinearIndexPattern&
refLIp,
648 static inline bool isOffsetBy(
const SectionedIndexPattern*
sIp,
649 const SectionedIndexPattern*
refSecp,
652 static inline bool isOffsetBy(
const SectionedIndexPattern&
lIp,
653 const SectionedIndexPattern&
refSecp,
656 static inline Plane2DIndexPattern* encapsulateIndexPattern(
const LinearIndexPattern&
refLIp,
659 static inline Plane2DIndexPattern* encapsulateIndexPattern(
const SectionedIndexPattern&
refSecp,
673 _indentation = _spaces;
675 localFuncArgDcl_.clear();
678 _currentLoops.clear();
679 _atomicFuncArrays.clear();
680 _streamStack.clear();
681 _dependentIDs.clear();
684 _info = std::move(
info);
685 _independentSize = _info->independent.size();
686 _dependent = &_info->dependent;
687 _nameGen = &_info->nameGen;
688 _minTemporaryVarID = _info->minTemporaryVarID;
690 const std::vector<Node*>& variableOrder = _info->variableOrder;
693 std::fill(_tmpArrayValues.begin(), _tmpArrayValues.end(),
nullptr);
695 std::fill(_tmpSparseArrayValues.begin(), _tmpSparseArrayValues.end(),
nullptr);
700 generateNames4RandomIndexPatterns(_info->indexRandomPatterns);
706 for (
size_t j = 0;
j < _independentSize;
j++) {
707 Node&
op = *_info->independent[
j];
708 if (
op.getName() ==
nullptr) {
714 for (
size_t i = 0;
i < dependent.
size();
i++) {
715 Node* node = dependent[
i].getOperationNode();
734 CPPADCG_ASSERT_KNOWN(!
indArg.empty() && !
depArg.empty(),
735 "There must be at least one dependent and one independent argument")
736 CPPADCG_ASSERT_KNOWN(
tmpArg.size() == 3,
737 "There must be three temporary variables")
740 funcArgDcl_ = generateFunctionArgumentsDcl2();
742 localFuncArgDcl_.reserve(funcArgDcl_.size() + 4);
743 localFuncArgDcl_ = funcArgDcl_;
744 localFuncArgDcl_.push_back(argumentDeclaration(
tmpArg[0]));
745 localFuncArgDcl_.push_back(argumentDeclaration(
tmpArg[1]));
746 localFuncArgDcl_.push_back(argumentDeclaration(
tmpArg[2]));
747 localFuncArgDcl_.push_back(U_INDEX_TYPE +
"* " + _C_SPARSE_INDEX_ARRAY);
749 localFuncArgs_ = generateDefaultFunctionArguments() +
", "
753 + _C_SPARSE_INDEX_ARRAY;
756 auxArrayName_ =
tmpArg[1].name +
"p";
764 for (
size_t i = 0;
i < dependent.
size();
i++) {
765 Node* node = dependent[
i].getOperationNode();
766 if (node !=
nullptr) {
768 if (
type != CGOpCode::Inv &&
type != CGOpCode::LoopEnd) {
769 size_t varID = getVariableID(*node);
771 auto it2 = _dependentIDs.find(
varID);
772 if (
it2 == _dependentIDs.end()) {
773 _dependentIDs[getVariableID(*node)] =
i;
786 localFuncNames.reserve(variableOrder.size() / _maxAssignmentsPerFunction);
792 if (variableOrder.size() > 0) {
794 for (
Node* node : variableOrder) {
795 CGOpCode
op = node->getOperationType();
796 if (!isDependent(*node) &&
op != CGOpCode::IndexDeclaration) {
798 if (requiresVariableName(*node) &&
op != CGOpCode::ArrayCreation &&
op != CGOpCode::SparseArrayCreation) {
800 }
else if (
op == CGOpCode::ArrayCreation) {
802 }
else if (
op == CGOpCode::SparseArrayCreation) {
811 if (_info->zeroDependents) {
813 for (
size_t i = 0;
i <
depArg.size();
i++) {
816 _code << _indentation <<
"for(i = 0; i < " << _dependent->
size() <<
"; i++) " <<
a.name <<
"[i]";
821 printParameter(Base(0.0));
827 for (
size_t i = 0;
i < variableOrder.size(); ++
i) {
845 i = printLoopIndexDeps(variableOrder,
i);
851 CPPAD_ASSERT_KNOWN(_streamStack.empty(),
"Error writing all operations to output stream")
864 CPPADCG_ASSERT_KNOWN(
tmpArg[0].array,
865 "The temporary variables must be saved in an array in order to generate multiple functions")
867 _code << ATOMICFUN_STRUCT_DEFINITION <<
"\n\n";
876 _nameGen->customFunctionVariableDeclarations(_code);
877 _code << generateIndependentVariableDeclaration() <<
"\n";
878 _code << generateDependentVariableDeclaration() <<
"\n";
879 _code << generateTemporaryVariableDeclaration(
true,
false,
880 _info->atomicFunctionsMaxForward,
881 _info->atomicFunctionsMaxReverse) <<
"\n";
882 _nameGen->prepareCustomFunctionVariables(_code);
884 _code << _spaces <<
localFuncName <<
"(" << localFuncArgs_ <<
");\n";
894 const std::string&
origVarName = *
dep.getOperationNode()->getName();
896 _code << _spaces <<
varName <<
" " << _depAssignOperation <<
" " <<
origVarName <<
";\n";
902 for (
size_t i = 0;
i < dependent.
size();
i++) {
903 if (dependent[
i].isParameter()) {
904 if (!_ignoreZeroDepAssign || !dependent[
i].isIdenticalZero()) {
906 _code << _spaces <<
"// dependent variables without operations\n";
910 _code << _spaces <<
varName <<
" " << _depAssignOperation <<
" ";
911 printParameter(dependent[
i].getValue());
914 }
else if (dependent[
i].getOperationNode()->getOperationType() == CGOpCode::Inv) {
916 _code << _spaces <<
"// dependent variables without operations\n";
920 const std::string&
indepName = *dependent[
i].getOperationNode()->getName();
921 _code << _spaces <<
varName <<
" " << _depAssignOperation <<
" " <<
indepName <<
";\n";
930 _ss <<
"#include <math.h>\n"
931 "#include <stdio.h>\n\n"
932 << ATOMICFUN_STRUCT_DEFINITION <<
"\n\n";
935 _nameGen->customFunctionVariableDeclarations(_ss);
936 _ss << generateIndependentVariableDeclaration() <<
"\n";
937 _ss << generateDependentVariableDeclaration() <<
"\n";
938 _ss << generateTemporaryVariableDeclaration(
false, _info->zeroDependents,
939 _info->atomicFunctionsMaxForward,
940 _info->atomicFunctionsMaxReverse) <<
"\n";
941 _nameGen->prepareCustomFunctionVariables(_ss);
943 _nameGen->finalizeCustomFunctionVariables(_ss);
948 if (_sources !=
nullptr) {
949 (*_sources)[_functionName +
".c"] = _ss.str();
952 _nameGen->finalizeCustomFunctionVariables(_code);
955 (*_sources)[_functionName +
".c"] = _code.str();
962 inline size_t getVariableID(
const Node& node)
const {
963 return _info->varId[node];
966 inline unsigned printAssignment(Node& node) {
967 return pushAssignment(node, node);
970 inline unsigned pushAssignment(Node&
nodeName,
972 if (
nodeRhs.getOperation() !=
nullptr) {
976 pushParameter(*
nodeRhs.getParameter());
979 _streamStack.flush();
985 inline unsigned pushAssignment(Node&
nodeName,
996 _streamStack.flush();
998 if (
nodeRhs.getOperationType() == CGOpCode::ArrayElement) {
999 Node* array =
nodeRhs.getArguments()[0].getOperation();
1000 size_t arrayId = getVariableID(*array);
1002 if (array->getOperationType() == CGOpCode::ArrayCreation)
1003 _tmpArrayValues[
arrayId - 1 +
pos] =
nullptr;
1005 _tmpSparseArrayValues[
arrayId - 1 +
pos] =
nullptr;
1011 inline virtual void pushAssignmentStart(Node&
op) {
1012 pushAssignmentStart(
op, createVariableName(
op), isDependent(
op));
1015 inline virtual void pushAssignmentStart(Node& node,
1019 _temporary[getVariableID(node)] = &node;
1022 _streamStack << _indentation <<
varName <<
" ";
1024 CGOpCode
op = node.getOperationType();
1025 if (
op == CGOpCode::DependentMultiAssign || (
op == CGOpCode::LoopIndexedDep && node.getInfo()[1] == 1)) {
1026 _streamStack <<
"+=";
1028 _streamStack << _depAssignOperation;
1031 _streamStack <<
"=";
1033 _streamStack <<
" ";
1036 inline virtual void pushAssignmentEnd(Node&
op) {
1037 _streamStack <<
";\n";
1040 virtual std::string argumentDeclaration(
const FuncArgument&
funcArg)
const {
1041 std::string
dcl = _baseTypeName;
1048 virtual void saveLocalFunction(std::vector<std::string>&
localFuncNames,
1054 _ss <<
"#include <math.h>\n"
1055 "#include <stdio.h>\n\n"
1056 << ATOMICFUN_STRUCT_DEFINITION <<
"\n\n";
1059 _nameGen->customFunctionVariableDeclarations(_ss);
1060 _ss << generateIndependentVariableDeclaration() <<
"\n";
1061 _ss << generateDependentVariableDeclaration() <<
"\n";
1065 _ss << _spaces << _baseTypeName <<
"* " << auxArrayName_ <<
";\n";
1068 generateArrayContainersDeclaration(_ss,
1069 _info->atomicFunctionsMaxForward,
1070 _info->atomicFunctionsMaxReverse);
1073 _ss << _spaces << U_INDEX_TYPE <<
" i;\n";
1077 createIndexDeclaration();
1079 _nameGen->prepareCustomFunctionVariables(_ss);
1081 _nameGen->finalizeCustomFunctionVariables(_ss);
1084 (*_sources)[
funcName +
".c"] = _ss.str();
1092 size_t totalUseCount,
1093 size_t opCount)
const override {
1094 CGOpCode
op =
var.getOperationType();
1095 if (totalUseCount > 1) {
1096 return op != CGOpCode::ArrayElement &&
op != CGOpCode::Index &&
op != CGOpCode::IndexDeclaration &&
op != CGOpCode::Tmp;
1098 return (
op == CGOpCode::ArrayCreation ||
1099 op == CGOpCode::SparseArrayCreation ||
1100 op == CGOpCode::AtomicForward ||
1101 op == CGOpCode::AtomicReverse ||
1102 op == CGOpCode::ComLt ||
1103 op == CGOpCode::ComLe ||
1104 op == CGOpCode::ComEq ||
1105 op == CGOpCode::ComGe ||
1106 op == CGOpCode::ComGt ||
1107 op == CGOpCode::ComNe ||
1108 op == CGOpCode::LoopIndexedDep ||
1109 op == CGOpCode::LoopIndexedTmp ||
1110 op == CGOpCode::IndexAssign ||
1111 op == CGOpCode::Assign ||
1112 opCount >= _maxOperationsPerAssignment) &&
1113 op != CGOpCode::CondResult;
1117 virtual bool requiresVariableName(
const Node&
var)
const {
1118 CGOpCode
op =
var.getOperationType();
1119 if (_info->totalUseCount.get(
var) > 1) {
1120 return (
op != CGOpCode::Pri &&
1121 op != CGOpCode::AtomicForward &&
1122 op != CGOpCode::AtomicReverse &&
1123 op != CGOpCode::LoopStart &&
1124 op != CGOpCode::LoopEnd &&
1125 op != CGOpCode::Index &&
1126 op != CGOpCode::IndexAssign &&
1127 op != CGOpCode::StartIf &&
1128 op != CGOpCode::ElseIf &&
1129 op != CGOpCode::Else &&
1130 op != CGOpCode::EndIf &&
1131 op != CGOpCode::CondResult &&
1132 op != CGOpCode::LoopIndexedTmp &&
1133 op != CGOpCode::Tmp);
1135 return isCondAssign(
op);
1147 CGOpCode
op =
var.getOperationType();
1148 return isCondAssign(
op) ||
1149 op == CGOpCode::Pri ||
1150 op == CGOpCode::ArrayCreation ||
1151 op == CGOpCode::SparseArrayCreation ||
1152 op == CGOpCode::AtomicForward ||
1153 op == CGOpCode::AtomicReverse ||
1154 op == CGOpCode::DependentMultiAssign ||
1155 op == CGOpCode::LoopStart ||
1156 op == CGOpCode::LoopEnd ||
1157 op == CGOpCode::IndexAssign ||
1158 op == CGOpCode::StartIf ||
1159 op == CGOpCode::ElseIf ||
1160 op == CGOpCode::Else ||
1161 op == CGOpCode::EndIf ||
1162 op == CGOpCode::CondResult ||
1163 op == CGOpCode::IndexDeclaration;
1166 bool requiresVariableArgument(
enum CGOpCode
op,
size_t argIndex)
const override {
1167 return op == CGOpCode::Sign ||
op == CGOpCode::CondResult ||
op == CGOpCode::Pri;
1170 inline const std::string& createVariableName(Node&
var) {
1171 CGOpCode
op =
var.getOperationType();
1172 CPPADCG_ASSERT_UNKNOWN(getVariableID(
var) > 0)
1173 CPPADCG_ASSERT_UNKNOWN(
op != CGOpCode::AtomicForward)
1174 CPPADCG_ASSERT_UNKNOWN(
op != CGOpCode::AtomicReverse)
1175 CPPADCG_ASSERT_UNKNOWN(
op != CGOpCode::LoopStart)
1176 CPPADCG_ASSERT_UNKNOWN(
op != CGOpCode::LoopEnd)
1177 CPPADCG_ASSERT_UNKNOWN(
op != CGOpCode::Index)
1178 CPPADCG_ASSERT_UNKNOWN(
op != CGOpCode::IndexAssign)
1179 CPPADCG_ASSERT_UNKNOWN(
op != CGOpCode::IndexDeclaration)
1181 if (
var.getName() ==
nullptr) {
1182 if (
op == CGOpCode::ArrayCreation) {
1185 }
else if (
op == CGOpCode::SparseArrayCreation) {
1188 }
else if (
op == CGOpCode::LoopIndexedDep) {
1189 size_t pos =
var.getInfo()[0];
1190 const IndexPattern*
ip = _info->loopDependentIndexPatterns[
pos];
1193 }
else if (
op == CGOpCode::LoopIndexedIndep) {
1194 size_t pos =
var.getInfo()[1];
1195 const IndexPattern*
ip = _info->loopIndependentIndexPatterns[
pos];
1198 }
else if (getVariableID(
var) <= _independentSize) {
1202 }
else if (getVariableID(
var) < _minTemporaryVarID) {
1204 auto it = _dependentIDs.find(getVariableID(
var));
1205 CPPADCG_ASSERT_UNKNOWN(
it != _dependentIDs.end())
1208 var.setName(_nameGen->generateDependent(index));
1210 CPPADCG_ASSERT_KNOWN(
var.getArguments().size() == 1,
"Invalid number of arguments for print operation")
1211 Node*
tmpVar =
var.getArguments()[0].getOperation();
1215 }
else if (
op == CGOpCode::LoopIndexedTmp ||
op == CGOpCode::Tmp) {
1216 CPPADCG_ASSERT_KNOWN(
var.getArguments().size() >= 1,
"Invalid number of arguments for loop indexed temporary operation")
1217 Node*
tmpVar =
var.getArguments()[0].getOperation();
1228 return *
var.getName();
1235 virtual void pushIndependentVariableName(Node&
op) {
1236 CPPADCG_ASSERT_KNOWN(
op.getArguments().size() == 0,
"Invalid number of arguments for independent variable")
1238 _streamStack << _nameGen->generateIndependent(
op, getVariableID(
op));
1242 if (
arg.getOperation() !=
nullptr) {
1244 return pushExpression(*
arg.getOperation());
1247 pushParameter(*
arg.getParameter());
1252 virtual unsigned pushExpression(Node&
op) {
1253 if (getVariableID(
op) > 0) {
1255 _streamStack << createVariableName(
op);
1264 virtual unsigned pushExpressionNoVarCheck2(Node& node) {
1267 unsigned lines = pushExpressionNoVarCheck(node);
1271 _streamStack.flush();
1272 if (!_streamStack.empty()) {
1273 n = &_streamStack.startNewOperationNode();
1281 unsigned lines2 = pushExpressionNoVarCheck(*
n);
1289 virtual unsigned pushExpressionNoVarCheck(Node& node) {
1290 CGOpCode
op = node.getOperationType();
1292 case CGOpCode::ArrayCreation:
1293 pushArrayCreationOp(node);
1295 case CGOpCode::SparseArrayCreation:
1296 pushSparseArrayCreationOp(node);
1298 case CGOpCode::ArrayElement:
1299 pushArrayElementOp(node);
1301 case CGOpCode::Assign:
1302 return pushAssignOp(node);
1305 case CGOpCode::Acos:
1306 case CGOpCode::Asin:
1307 case CGOpCode::Atan:
1308 case CGOpCode::Cosh:
1312 case CGOpCode::Sinh:
1314 case CGOpCode::Sqrt:
1315 case CGOpCode::Tanh:
1317#if CPPAD_USE_CPLUSPLUS_2011
1319 case CGOpCode::Erfc:
1320 case CGOpCode::Asinh:
1321 case CGOpCode::Acosh:
1322 case CGOpCode::Atanh:
1323 case CGOpCode::Expm1:
1324 case CGOpCode::Log1p:
1326 pushUnaryFunction(node);
1328 case CGOpCode::AtomicForward:
1331 case CGOpCode::AtomicReverse:
1335 pushOperationAdd(node);
1337 case CGOpCode::Alias:
1338 return pushOperationAlias(node);
1340 case CGOpCode::ComLt:
1341 case CGOpCode::ComLe:
1342 case CGOpCode::ComEq:
1343 case CGOpCode::ComGe:
1344 case CGOpCode::ComGt:
1345 case CGOpCode::ComNe:
1346 pushConditionalAssignment(node);
1349 pushOperationDiv(node);
1352 pushIndependentVariableName(node);
1355 pushOperationMul(node);
1358 pushPowFunction(node);
1361 pushPrintOperation(node);
1363 case CGOpCode::Sign:
1364 pushSignFunction(node);
1367 pushOperationMinus(node);
1370 case CGOpCode::UnMinus:
1371 pushOperationUnaryMinus(node);
1374 case CGOpCode::DependentMultiAssign:
1375 return pushDependentMultiAssign(node);
1377 case CGOpCode::Index:
1379 case CGOpCode::IndexAssign:
1380 pushIndexAssign(node);
1382 case CGOpCode::IndexDeclaration:
1385 case CGOpCode::LoopStart:
1386 pushLoopStart(node);
1388 case CGOpCode::LoopIndexedIndep:
1389 pushLoopIndexedIndep(node);
1391 case CGOpCode::LoopIndexedDep:
1392 pushLoopIndexedDep(node);
1394 case CGOpCode::LoopIndexedTmp:
1395 pushLoopIndexedTmp(node);
1397 case CGOpCode::TmpDcl:
1403 case CGOpCode::LoopEnd:
1406 case CGOpCode::IndexCondExpr:
1407 pushIndexCondExprOp(node);
1409 case CGOpCode::StartIf:
1412 case CGOpCode::ElseIf:
1415 case CGOpCode::Else:
1418 case CGOpCode::EndIf:
1421 case CGOpCode::CondResult:
1422 pushCondResult(node);
1424 case CGOpCode::UserCustom:
1425 pushUserCustom(node);
1428 throw CGException(
"Unknown operation code '",
op,
"'.");
1433 virtual unsigned pushAssignOp(Node& node) {
1434 CPPADCG_ASSERT_KNOWN(node.getArguments().size() == 1,
"Invalid number of arguments for assign operation")
1436 return push(node.getArguments()[0]);
1439 virtual void pushUnaryFunction(Node&
op) {
1440 CPPADCG_ASSERT_KNOWN(
op.getArguments().size() == 1,
"Invalid number of arguments for unary function")
1446 case CGOpCode::Acos:
1449 case CGOpCode::Asin:
1452 case CGOpCode::Atan:
1455 case CGOpCode::Cosh:
1467 case CGOpCode::Sinh:
1473 case CGOpCode::Sqrt:
1476 case CGOpCode::Tanh:
1482#if CPPAD_USE_CPLUSPLUS_2011
1486 case CGOpCode::Erfc:
1489 case CGOpCode::Asinh:
1492 case CGOpCode::Acosh:
1495 case CGOpCode::Atanh:
1498 case CGOpCode::Expm1:
1501 case CGOpCode::Log1p:
1506 throw CGException(
"Unknown function name for operation code '",
op.getOperationType(),
"'.");
1509 _streamStack <<
"(";
1510 push(
op.getArguments()[0]);
1511 _streamStack <<
")";
1514 virtual void pushPowFunction(Node&
op) {
1515 CPPADCG_ASSERT_KNOWN(
op.getArguments().size() == 2,
"Invalid number of arguments for pow() function")
1518 push(
op.getArguments()[0]);
1519 _streamStack << ", ";
1520 push(
op.getArguments()[1]);
1521 _streamStack << ")";
1524 virtual void pushSignFunction(Node&
op) {
1525 CPPADCG_ASSERT_KNOWN(
op.getArguments().size() == 1,
"Invalid number of arguments for sign() function")
1526 CPPADCG_ASSERT_UNKNOWN(
op.getArguments()[0].getOperation() !=
nullptr)
1527 CPPADCG_ASSERT_UNKNOWN(getVariableID(*
op.getArguments()[0].getOperation()) > 0)
1529 Node&
arg = *
op.getArguments()[0].getOperation();
1533 _streamStack << "(" <<
argName << " " << _C_COMP_OP_GT << " ";
1534 pushParameter(Base(0.0));
1535 _streamStack << "?";
1536 pushParameter(Base(1.0));
1537 _streamStack << ":(" <<
argName << " " << _C_COMP_OP_LT << " ";
1538 pushParameter(Base(0.0));
1539 _streamStack << "?";
1540 pushParameter(Base(-1.0));
1541 _streamStack << ":";
1542 pushParameter(Base(0.0));
1543 _streamStack << "))";
1546 virtual unsigned pushOperationAlias(Node&
op) {
1547 CPPADCG_ASSERT_KNOWN(
op.getArguments().size() == 1,
"Invalid number of arguments for alias")
1551 virtual void pushOperationAdd(Node&
op) {
1552 CPPADCG_ASSERT_KNOWN(
op.getArguments().size() == 2,
"Invalid number of arguments for addition")
1557 if(
right.getParameter() ==
nullptr || (*
right.getParameter() >= 0)) {
1559 _streamStack <<
" + ";
1564 _streamStack <<
" - ";
1565 pushParameter(-*
right.getParameter());
1569 virtual void pushOperationMinus(Node&
op) {
1570 CPPADCG_ASSERT_KNOWN(
op.getArguments().size() == 2,
"Invalid number of arguments for subtraction")
1575 if(
right.getParameter() ==
nullptr || (*
right.getParameter() >= 0)) {
1579 _streamStack <<
" - ";
1581 _streamStack <<
"(";
1585 _streamStack <<
")";
1590 _streamStack <<
" + ";
1591 pushParameter(-*
right.getParameter());
1595 inline bool encloseInParenthesesDiv(
const Node* node)
const {
1596 while (node !=
nullptr) {
1597 if (getVariableID(*node) != 0)
1599 if (node->getOperationType() == CGOpCode::Alias)
1600 node = node->getArguments()[0].getOperation();
1604 return node !=
nullptr &&
1605 getVariableID(*node) == 0 &&
1606 !isFunction(node->getOperationType());
1609 virtual void pushOperationDiv(Node&
op) {
1610 CPPADCG_ASSERT_KNOWN(
op.getArguments().size() == 2,
"Invalid number of arguments for division")
1619 _streamStack <<
"(";
1623 _streamStack <<
")";
1625 _streamStack <<
" / ";
1627 _streamStack <<
"(";
1631 _streamStack <<
")";
1635 inline bool encloseInParenthesesMul(
const Node* node)
const {
1636 while (node !=
nullptr) {
1637 if (getVariableID(*node) != 0)
1639 else if (node->getOperationType() == CGOpCode::Alias)
1640 node = node->getArguments()[0].getOperation();
1644 return node !=
nullptr &&
1645 getVariableID(*node) == 0 &&
1646 node->getOperationType() != CGOpCode::Div &&
1647 node->getOperationType() != CGOpCode::Mul &&
1648 !isFunction(node->getOperationType());
1651 virtual void pushOperationMul(Node&
op) {
1652 CPPADCG_ASSERT_KNOWN(
op.getArguments().size() == 2,
"Invalid number of arguments for multiplication")
1661 _streamStack <<
"(";
1665 _streamStack <<
")";
1667 _streamStack <<
" * ";
1669 _streamStack <<
"(";
1673 _streamStack <<
")";
1677 virtual void pushOperationUnaryMinus(Node&
op) {
1678 CPPADCG_ASSERT_KNOWN(
op.getArguments().size() == 1,
"Invalid number of arguments for unary minus")
1682 bool enclose = encloseInParenthesesMul(
arg.getOperation());
1684 _streamStack << "-";
1686 _streamStack <<
"(";
1688 _streamStack <<
" ";
1692 _streamStack <<
")";
1696 virtual void pushPrintOperation(
const Node& node) {
1697 CPPADCG_ASSERT_KNOWN(node.getOperationType() == CGOpCode::Pri,
"Invalid node type")
1702 replaceString(
before, "\
n", "\\
n");
1703 replaceString(
before, "\"", "\\\"");
1705 replaceString(
after, "\
n", "\\
n");
1706 replaceString(
after, "\"", "\\\"");
1711 _streamStack <<
", ";
1714 _streamStack <<
");\n";
1717 virtual void pushConditionalAssignment(Node& node) {
1718 CPPADCG_ASSERT_UNKNOWN(getVariableID(node) > 0)
1720 const std::vector<Arg>&
args = node.getArguments();
1726 bool isDep = isDependent(node);
1734 pushAssignmentEnd(node);
1736 _streamStack <<_indentation <<
"if( ";
1738 _streamStack <<
" " << getComparison(node.getOperationType()) <<
" ";
1740 _streamStack <<
" ) {\n";
1741 _streamStack <<_spaces;
1744 pushAssignmentEnd(node);
1745 _streamStack <<_indentation <<
"} else {\n";
1746 _streamStack <<_spaces;
1749 pushAssignmentEnd(node);
1750 _streamStack <<_indentation <<
"}\n";
1754 inline bool isSameArgument(
const Arg&
newArg,
1757 if (
oldArg->getParameter() !=
nullptr) {
1758 if (
newArg.getParameter() !=
nullptr) {
1759 return (*
newArg.getParameter() == *
oldArg->getParameter());
1762 return (
newArg.getOperation() ==
oldArg->getOperation());
1768 virtual void pushArrayCreationOp(Node&
op);
1770 virtual void pushSparseArrayCreationOp(Node&
op);
1772 inline void printArrayStructInit(
const std::string&
dataArrayName,
1774 const std::vector<Node*>&
arrays,
1777 inline void printArrayStructInit(
const std::string&
dataArrayName,
1780 inline void markArrayChanged(Node&
ty);
1787 inline std::string getTempArrayName(
const Node&
op);
1789 virtual void pushArrayElementOp(Node&
op);
1792 CPPADCG_ASSERT_KNOWN(
atomicFor.getInfo().size() == 3,
"Invalid number of information elements for atomic forward operation")
1797 CPPADCG_ASSERT_KNOWN(
opArgs.size() ==
p1 * 2,
"Invalid number of arguments for atomic forward operation")
1800 size_t atomicIndex = _info->atomicFunctionId2Index.at(
id);
1803 for (
size_t k = 0;
k <
p1;
k++) {
1808 CPPADCG_ASSERT_KNOWN(
tx[0]->getOperationType() == CGOpCode::ArrayCreation,
"Invalid array type")
1809 CPPADCG_ASSERT_KNOWN(
p == 0 ||
tx[1]->getOperationType() == CGOpCode::SparseArrayCreation,
"Invalid array type")
1811 CPPADCG_ASSERT_KNOWN(
ty[
p]->getOperationType() == CGOpCode::ArrayCreation,
"Invalid array type")
1814 for (
size_t k = 0;
k <
p1;
k++) {
1815 printArrayStructInit(_ATOMIC_TX,
k,
tx,
k);
1818 printArrayStructInit(_ATOMIC_TY, *
ty[
p]);
1821 _streamStack << _indentation <<
"atomicFun.forward(atomicFun.libModel, "
1823 << _ATOMIC_TX <<
", &" << _ATOMIC_TY <<
"); // "
1824 << _info->atomicFunctionId2Name.at(
id)
1830 markArrayChanged(*
ty[
p]);
1834 CPPADCG_ASSERT_KNOWN(
atomicRev.getInfo().size() == 2,
"Invalid number of information elements for atomic reverse operation")
1838 CPPADCG_ASSERT_KNOWN(
opArgs.size() ==
p1 * 4,
"Invalid number of arguments for atomic reverse operation")
1841 size_t atomicIndex = _info->atomicFunctionId2Index.at(
id);
1843 for (
size_t k = 0;
k <
p1;
k++) {
1849 CPPADCG_ASSERT_KNOWN(
tx[0]->getOperationType() == CGOpCode::ArrayCreation,
"Invalid array type")
1850 CPPADCG_ASSERT_KNOWN(
p == 0 ||
tx[1]->getOperationType() == CGOpCode::SparseArrayCreation,
"Invalid array type")
1852 CPPADCG_ASSERT_KNOWN(
px[0]->getOperationType() == CGOpCode::ArrayCreation,
"Invalid array type")
1854 CPPADCG_ASSERT_KNOWN(
py[0]->getOperationType() == CGOpCode::SparseArrayCreation,
"Invalid array type")
1855 CPPADCG_ASSERT_KNOWN(
p == 0 ||
py[1]->getOperationType() == CGOpCode::ArrayCreation,
"Invalid array type")
1858 for (
size_t k = 0;
k <
p1;
k++) {
1859 printArrayStructInit(_ATOMIC_TX,
k,
tx,
k);
1862 for (
size_t k = 0;
k <
p1;
k++) {
1863 printArrayStructInit(_ATOMIC_PY,
k,
py,
k);
1866 printArrayStructInit(_ATOMIC_PX, *
px[0]);
1869 _streamStack << _indentation <<
"atomicFun.reverse(atomicFun.libModel, "
1871 << _ATOMIC_TX <<
", &" << _ATOMIC_PX <<
", " << _ATOMIC_PY <<
"); // "
1872 << _info->atomicFunctionId2Name.at(
id)
1878 markArrayChanged(*
px[0]);
1881 virtual unsigned pushDependentMultiAssign(Node& node) {
1882 CPPADCG_ASSERT_KNOWN(node.getOperationType() == CGOpCode::DependentMultiAssign,
"Invalid node type")
1883 CPPADCG_ASSERT_KNOWN(node.getArguments().size() > 0, "
Invalid number of arguments")
1889 if (
arg.getParameter() !=
nullptr) {
1892 CGOpCode
op =
arg.getOperation()->getOperationType();
1893 useArg =
op != CGOpCode::DependentRefRhs &&
op != CGOpCode::LoopEnd &&
op != CGOpCode::EndIf;
1897 pushAssignment(node,
arg);
1904 virtual void pushLoopStart(Node& node) {
1905 CPPADCG_ASSERT_KNOWN(node.getOperationType() == CGOpCode::LoopStart,
"Invalid node type")
1908 _currentLoops.push_back(&
lnode);
1912 if (
lnode.getIterationCountNode() !=
nullptr) {
1915 std::ostringstream
oss;
1920 _streamStack << _spaces <<
"for("
1924 _indentation += _spaces;
1927 virtual void pushLoopEnd(Node& node) {
1928 CPPADCG_ASSERT_KNOWN(node.getOperationType() == CGOpCode::LoopEnd,
"Invalid node type")
1930 _indentation.
resize(_indentation.size() - _spaces.size());
1932 _streamStack <<_indentation << "}\
n";
1934 _currentLoops.pop_back();
1938 virtual size_t printLoopIndexDeps(
const std::vector<Node*>& variableOrder,
1944 virtual void pushLoopIndexedDep(Node& node);
1946 virtual void pushLoopIndexedIndep(Node& node) {
1947 CPPADCG_ASSERT_KNOWN(node.getOperationType() == CGOpCode::LoopIndexedIndep,
"Invalid node type")
1951 size_t pos = node.getInfo()[1];
1952 const IndexPattern*
ip = _info->loopIndependentIndexPatterns[
pos];
1953 _streamStack <<_nameGen->generateIndexedIndependent(node, getVariableID(node), *
ip);
1956 virtual void pushLoopIndexedTmp(Node& node) {
1957 CPPADCG_ASSERT_KNOWN(node.getOperationType() == CGOpCode::LoopIndexedTmp,
"Invalid node type")
1959 Node*
tmpVar = node.getArguments()[0].getOperation();
1962 push(node.getArguments()[1]);
1965 virtual void pushTmpVar(Node& node) {
1966 CPPADCG_ASSERT_KNOWN(node.getOperationType() == CGOpCode::Tmp,
"Invalid node type")
1968 Node*
tmpVar = node.getArguments()[0].getOperation();
1971 _streamStack <<*
tmpVar->getName();
1974 virtual void pushIndexAssign(Node& node) {
1975 CPPADCG_ASSERT_KNOWN(node.getOperationType() == CGOpCode::IndexAssign,
"Invalid node type")
1981 _streamStack <<_indentation << (*
inode.getIndex().getName())
1982 << " = " << indexPattern2String(
ip,
inode.getIndexPatternIndexes()) << ";\
n";
1985 virtual void pushIndexCondExprOp(Node& node) {
1986 CPPADCG_ASSERT_KNOWN(node.getOperationType() == CGOpCode::IndexCondExpr,
"Invalid node type")
1991 const std::vector<
size_t>&
info = node.getInfo();
1993 auto& iterationIndexOp =
static_cast<IndexOperationNode<Base>&> (*node.getArguments()[0].getOperation());
1994 const std::
string& index = *iterationIndexOp.getIndex().getName();
1996 printIndexCondExpr(_code,
info, index);
2004 CPPADCG_ASSERT_KNOWN(node.getOperationType() == CGOpCode::StartIf,
"Invalid node type")
2005 CPPADCG_ASSERT_KNOWN(node.getArguments().size() >= 1,
"Invalid number of arguments for an 'if start' operation")
2006 CPPADCG_ASSERT_KNOWN(node.getArguments()[0].getOperation() !=
nullptr,
"Invalid argument for an 'if start' operation")
2008 _streamStack <<_indentation <<
"if(";
2009 pushIndexCondExprOp(*node.getArguments()[0].getOperation());
2010 _streamStack <<
") {\n";
2012 _indentation += _spaces;
2021 CPPADCG_ASSERT_KNOWN(node.
getOperationType() == CGOpCode::ElseIf,
"Invalid node type")
2022 CPPADCG_ASSERT_KNOWN(node.
getArguments().size() >= 2,
"Invalid number of arguments for an 'else if' operation")
2023 CPPADCG_ASSERT_KNOWN(node.
getArguments()[0].getOperation() !=
nullptr,
"Invalid argument for an 'else if' operation")
2024 CPPADCG_ASSERT_KNOWN(node.
getArguments()[1].getOperation() !=
nullptr,
"Invalid argument for an 'else if' operation")
2026 _indentation.resize(_indentation.size() - _spaces.size());
2028 _streamStack <<_indentation <<
"} else if(";
2029 pushIndexCondExprOp(*node.
getArguments()[1].getOperation());
2030 _streamStack <<
") {\n";
2032 _indentation += _spaces;
2040 CPPADCG_ASSERT_KNOWN(node.
getOperationType() == CGOpCode::Else,
"Invalid node type")
2041 CPPADCG_ASSERT_KNOWN(node.
getArguments().size() >= 1,
"Invalid number of arguments for an 'else' operation")
2043 _indentation.resize(_indentation.size() - _spaces.size());
2045 _streamStack <<_indentation <<
"} else {\n";
2047 _indentation += _spaces;
2050 virtual void pushEndIf(Node& node) {
2051 CPPADCG_ASSERT_KNOWN(node.getOperationType() == CGOpCode::EndIf,
"Invalid node type for an 'end if' operation")
2053 _indentation.
resize(_indentation.size() - _spaces.size());
2055 _streamStack <<_indentation << "}\
n";
2058 virtual void pushCondResult(Node& node) {
2059 CPPADCG_ASSERT_KNOWN(node.getOperationType() == CGOpCode::CondResult,
"Invalid node type")
2065 Node&
nodeArg = *node.getArguments()[1].getOperation();
2069 virtual void pushUserCustom(Node& node) {
2070 CPPADCG_ASSERT_KNOWN(node.getOperationType() == CGOpCode::UserCustom,
"Invalid node type")
2076 if (
arg.getOperationType() == CGOpCode::LoopIndexedDep) {
2079 size_t id = getVariableID(
arg);
2080 return id > _independentSize &&
id < _minTemporaryVarID;
2083 virtual void printParameter(
const Base& value) {
2084 writeParameter(value, _code);
2087 virtual void pushParameter(
const Base& value) {
2088 writeParameter(value, _streamStack);
2091 template<
class Output>
2092 void writeParameter(
const Base& value,
Output&
output) {
2094 std::ostringstream os;
2095 os << std::setprecision(_parameterPrecision) << value;
2097 std::string
number = os.str();
2100 if (std::abs(value) > Base(0) && value != Base(1) && value != Base(-1)) {
2101 if (
number.find(
'.') == std::string::npos &&
number.find(
'e') == std::string::npos) {
2109 virtual const std::string& getComparison(
enum CGOpCode
op)
const {
2111 case CGOpCode::ComLt:
2112 return _C_COMP_OP_LT;
2114 case CGOpCode::ComLe:
2115 return _C_COMP_OP_LE;
2117 case CGOpCode::ComEq:
2118 return _C_COMP_OP_EQ;
2120 case CGOpCode::ComGe:
2121 return _C_COMP_OP_GE;
2123 case CGOpCode::ComGt:
2124 return _C_COMP_OP_GT;
2126 case CGOpCode::ComNe:
2127 return _C_COMP_OP_NE;
2137 static const std::string
format;
2141 static bool isFunction(
enum CGOpCode
op) {
2142 return isUnaryFunction(
op) ||
op == CGOpCode::Pow;
2145 static bool isUnaryFunction(
enum CGOpCode
op) {
2148 case CGOpCode::Acos:
2149 case CGOpCode::Asin:
2150 case CGOpCode::Atan:
2151 case CGOpCode::Cosh:
2155 case CGOpCode::Sinh:
2157 case CGOpCode::Sqrt:
2158 case CGOpCode::Tanh:
2160#if CPPAD_USE_CPLUSPLUS_2011
2162 case CGOpCode::Erfc:
2163 case CGOpCode::Asinh:
2164 case CGOpCode::Acosh:
2165 case CGOpCode::Atanh:
2166 case CGOpCode::Expm1:
2167 case CGOpCode::Log1p:
2175 inline static bool isCondAssign(
enum CGOpCode
op) {
2177 case CGOpCode::ComLt:
2178 case CGOpCode::ComLe:
2179 case CGOpCode::ComEq:
2180 case CGOpCode::ComGe:
2181 case CGOpCode::ComGt:
2182 case CGOpCode::ComNe:
2190 class AtomicFuncArray {
2197 unsigned short scope;