1 #ifndef CPPAD_CG_LANGUAGE_LATEX_INCLUDED 2 #define CPPAD_CG_LANGUAGE_LATEX_INCLUDED 35 static const std::string _C_STATIC_INDEX_ARRAY;
36 static const std::string _C_SPARSE_INDEX_ARRAY;
37 static const std::string _COMP_OP_LT;
38 static const std::string _COMP_OP_LE;
39 static const std::string _COMP_OP_EQ;
40 static const std::string _COMP_OP_GE;
41 static const std::string _COMP_OP_GT;
42 static const std::string _COMP_OP_NE;
43 static const std::string _ATOMIC_TX;
44 static const std::string _ATOMIC_TY;
45 static const std::string _ATOMIC_PX;
46 static const std::string _ATOMIC_PY;
51 size_t _indentationLevel;
53 std::string _startVar;
57 std::string _startDepVar;
59 std::string _endDepVar;
61 std::string _startIndepVar;
63 std::string _endIndepVar;
69 std::string _startAlgLine;
71 std::string _endAlgLine;
73 std::string _startEqBlock;
75 std::string _endEqBlock;
76 std::string _algFileStart;
77 std::string _algFileEnd;
78 std::string _forStart;
80 std::string _conditionStart;
81 std::string _conditionEnd;
84 std::string _elseIfStart;
85 std::string _elseIfEnd;
86 std::string _elseStart;
88 std::string _assignStr;
90 std::string _multOpStr;
92 std::string _multValOpStr;
96 std::ostringstream _code;
100 std::ostringstream _ss;
102 size_t _independentSize;
104 size_t _minTemporaryVarID;
107 std::map<size_t, size_t> _dependentIDs;
111 std::map<size_t, Node*> _temporary;
113 bool _ignoreZeroDepAssign;
115 std::string _filename;
117 size_t _maxAssignmentsPerFile;
119 std::map<std::string, std::string>* _sources;
121 std::vector<const Arg*> _tmpArrayValues;
123 std::vector<const Arg*> _tmpSparseArrayValues;
125 std::vector<const LoopStartOperationNode<Base>*> _currentLoops;
127 size_t _parameterPrecision;
131 bool _powBaseEnclose;
133 std::string auxArrayName_;
142 _indentationLevel(0),
143 _startVar(
"\\begin{CGVar}"),
144 _endVar(
"\\end{CGVar}"),
145 _startDepVar(
"\\begin{CGDepVar}"),
146 _endDepVar(
"\\end{CGDepVar}"),
147 _startIndepVar(
"\\begin{CGIndVar}"),
148 _endIndepVar(
"\\end{CGIndVar}"),
149 _startEq(
"\\begin{CGEq}"),
150 _endEq(
"\\end{CGEq}"),
151 _startAlgLine(
"\\begin{CGLine}"),
152 _endAlgLine(
"\\end{CGLine}"),
153 _startEqBlock(
"\\begin{CGEqBlock}"),
154 _endEqBlock(
"\\end{CGEqBlock}"),
155 _algFileStart(
"\\begin{CGAlgFile}"),
156 _algFileEnd(
"\\end{CGAlgFile}"),
157 _forStart(
"\\begin{CGFor}"),
158 _forEnd(
"\\end{CGFor}"),
159 _conditionStart(
"\\begin{CGCond}"),
160 _conditionEnd(
"\\end{CGCond}"),
161 _ifStart(
"\\begin{CGIf}"),
162 _ifEnd(
"\\end{CGIf}"),
163 _elseIfStart(
"\\begin{CGElseIf}"),
164 _elseIfEnd(
"\\end{CGElseIf}"),
165 _elseStart(
"\\begin{CGElse}"),
166 _elseEnd(
"\\end{CGElse}"),
169 _multValOpStr(
"\\times"),
173 _minTemporaryVarID(0),
175 _ignoreZeroDepAssign(false),
176 _filename(
"algorithm"),
177 _maxAssignmentsPerFile(0),
179 _parameterPrecision(
std::numeric_limits<Base>::digits10),
180 _inEquationEnv(false),
181 _powBaseEnclose(false) {
184 inline const std::string& getAssignString()
const {
188 inline void setAssignString(
const std::string& assign) {
192 inline bool isIgnoreZeroDepAssign()
const {
193 return _ignoreZeroDepAssign;
196 inline void setIgnoreZeroDepAssign(
bool ignore) {
197 _ignoreZeroDepAssign = ignore;
200 virtual void setFilename(
const std::string& name) {
211 const std::string& end) {
237 const std::string& end) {
238 _startDepVar = begin;
263 const std::string& end) {
264 _startIndepVar = begin;
272 return _startIndepVar;
289 const std::string& end) {
315 const std::string& end) {
316 _startAlgLine = begin;
324 return _startAlgLine;
342 const std::string& end) {
343 _startEqBlock = begin;
352 return _startEqBlock;
370 const std::string& end) {
371 _algFileStart = begin;
379 return _algFileStart;
396 const std::string& end) {
422 const std::string& end) {
423 _conditionStart = begin;
431 return _conditionStart;
438 return _conditionEnd;
448 const std::string& end) {
474 const std::string& end) {
475 _elseIfStart = begin;
500 const std::string& end) {
526 return _parameterPrecision;
536 _parameterPrecision = p;
548 _powBaseEnclose = enclose;
558 return _powBaseEnclose;
582 _multOpStr = multOpStr;
590 return _multValOpStr;
601 _multValOpStr = multValOpStr;
604 virtual void setMaxAssignmentsPerFunction(
size_t maxAssignmentsPerFunction,
605 std::map<std::string, std::string>* sources) {
606 _maxAssignmentsPerFile = maxAssignmentsPerFunction;
615 static inline void printIndexCondExpr(std::ostringstream& out,
616 const std::vector<size_t>& info,
617 const std::string& index) {
618 CPPADCG_ASSERT_KNOWN(info.size() > 1 && info.size() % 2 == 0,
"Invalid number of information elements for an index condition expression operation")
620 size_t infoSize = info.size();
621 for (
size_t e = 0; e < infoSize; e += 2) {
625 size_t min = info[e];
626 size_t max = info[e + 1];
628 out << index <<
" == " << min;
629 }
else if (min == 0) {
630 out << index <<
" \\le " << max;
631 }
else if (max == (std::numeric_limits<size_t>::max)()) {
632 out << min <<
" \\le " << index;
638 out << min <<
" == " << index <<
" \\vee " << index <<
" == " << max;
640 out << min <<
" \\le " << index <<
" \\wedge" << index <<
" \\le " << max;
652 inline void printStaticIndexArray(std::ostringstream& os,
653 const std::string& name,
654 const std::vector<size_t>& values);
656 inline void printStaticIndexMatrix(std::ostringstream& os,
657 const std::string& name,
658 const std::map<
size_t, std::map<size_t, size_t> >& values);
663 static inline void generateNames4RandomIndexPatterns(
const std::set<RandomIndexPattern*>& randomPatterns);
666 const std::string& identation,
667 const std::set<RandomIndexPattern*>& randomPatterns);
669 static inline std::string indexPattern2String(
const IndexPattern& ip,
672 static inline std::string indexPattern2String(
const IndexPattern& ip,
673 const std::vector<const Node*>& indexes);
686 const bool multiFile = _maxAssignmentsPerFile > 0 && _sources !=
nullptr;
691 _indentationLevel = 0;
693 _inEquationEnv =
false;
695 _currentLoops.clear();
696 _dependentIDs.clear();
701 _independentSize = info->independent.size();
702 _dependent = &info->dependent;
703 _nameGen = &info->nameGen;
704 _minTemporaryVarID = info->minTemporaryVarID;
706 const std::vector<Node*>& variableOrder = info->variableOrder;
709 std::fill(_tmpArrayValues.begin(), _tmpArrayValues.end(),
nullptr);
711 std::fill(_tmpSparseArrayValues.begin(), _tmpSparseArrayValues.end(),
nullptr);
716 generateNames4RandomIndexPatterns(info->indexRandomPatterns);
722 for (
size_t j = 0; j < _independentSize; j++) {
723 Node& op = *info->independent[j];
730 for (
size_t i = 0; i < dependent.
size(); i++) {
731 Node* node = dependent[i].getOperationNode();
734 size_t pos = node->
getInfo()[0];
735 const IndexPattern* ip = info->loopDependentIndexPatterns[pos];
747 const std::vector<FuncArgument>& indArg = _nameGen->
getIndependent();
748 const std::vector<FuncArgument>& depArg = _nameGen->
getDependent();
749 const std::vector<FuncArgument>& tmpArg = _nameGen->
getTemporary();
750 CPPADCG_ASSERT_KNOWN(!indArg.empty() && !depArg.empty(),
751 "There must be at least one dependent and one independent argument")
752 CPPADCG_ASSERT_KNOWN(tmpArg.size() == 3,
753 "There must be three temporary variables")
755 auxArrayName_ = tmpArg[1].name +
"p";
761 std::set<size_t> dependentDuplicates;
763 for (
size_t i = 0; i < dependent.
size(); i++) {
764 Node* node = dependent[i].getOperationNode();
765 if (node !=
nullptr) {
767 if (type != CGOpCode::Inv && type != CGOpCode::LoopEnd) {
768 size_t varID = getVariableID(*node);
770 auto it2 = _dependentIDs.find(varID);
771 if (it2 == _dependentIDs.end()) {
772 _dependentIDs[getVariableID(*node)] = i;
775 dependentDuplicates.insert(i);
783 std::vector<std::string> inputLatexFiles;
785 inputLatexFiles.reserve(variableOrder.size() / _maxAssignmentsPerFile);
791 if (variableOrder.size() > 0) {
793 for (
Node* node : variableOrder) {
794 CGOpCode op = node->getOperationType();
795 if (!isDependent(*node) && op != CGOpCode::IndexDeclaration) {
797 if (requiresVariableName(*node) && op != CGOpCode::ArrayCreation && op != CGOpCode::SparseArrayCreation) {
799 }
else if (op == CGOpCode::ArrayCreation) {
801 }
else if (op == CGOpCode::SparseArrayCreation) {
810 if (info->zeroDependents) {
813 checkEquationEnvStart();
814 for (
size_t i = 0; i < depArg.size(); i++) {
815 _code << _startAlgLine << _startEq;
823 printParameter(Base(0.0));
824 _code << _endEq << _endAlgLine << _endline;
828 size_t assignCount = 0;
829 for (
Node* it : variableOrder) {
831 if (assignCount >= _maxAssignmentsPerFile && multiFile && _currentLoops.empty()) {
833 saveLocalFunction(inputLatexFiles, inputLatexFiles.empty() && info->zeroDependents);
839 if (node.getOperationType() == CGOpCode::DependentRefRhs) {
841 }
else if (node.getOperationType() == CGOpCode::TmpDcl) {
845 assignCount += printAssignment(node);
848 if (!inputLatexFiles.empty() && assignCount > 0) {
850 saveLocalFunction(inputLatexFiles,
false);
854 if (!inputLatexFiles.empty()) {
858 CPPADCG_ASSERT_KNOWN(tmpArg[0].array,
859 "The temporary variables must be saved in an array in order to generate multiple functions")
860 printAlgorithmFileStart(_code);
861 for (
auto & inputLatexFile : inputLatexFiles) {
862 _code <<
"\\input{" << inputLatexFile <<
"}" << _endline;
864 printAlgorithmFileEnd(_code);
868 if (!dependentDuplicates.empty()) {
869 _code <<
"% variable duplicates: " << dependentDuplicates.size() << _endline;
871 checkEquationEnvStart();
872 for (
size_t index : dependentDuplicates) {
873 const CG<Base>& dep = (*_dependent)[index];
875 const std::string& origVarName = *dep.getOperationNode()->getName();
877 _code << _startAlgLine << _startEq
878 << _startDepVar << varName << _endDepVar
880 << _startDepVar << origVarName << _endDepVar;
881 printAssignmentEnd();
886 bool commentWritten =
false;
887 for (
size_t i = 0; i < dependent.
size(); i++) {
888 if (dependent[i].isParameter()) {
889 if (!_ignoreZeroDepAssign || !dependent[i].isIdenticalZero()) {
890 if (!commentWritten) {
891 _code <<
"% dependent variables without operations" << _endline;
892 commentWritten =
true;
894 checkEquationEnvStart();
897 _code << _startAlgLine << _startEq
898 << _startDepVar << varName << _endDepVar << _assignStr;
899 printParameter(dependent[i].getValue());
900 printAssignmentEnd();
902 }
else if (dependent[i].getOperationNode()->getOperationType() == CGOpCode::Inv) {
903 if (!commentWritten) {
904 _code <<
"% dependent variables without operations" << _endline;
905 commentWritten =
true;
907 checkEquationEnvStart();
910 const std::string& indepName = *dependent[i].getOperationNode()->getName();
911 _code << _startAlgLine << _startEq
912 << _startDepVar << varName << _endDepVar
914 << _startIndepVar << indepName << _endIndepVar;
915 printAssignmentEnd(*dependent[i].getOperationNode());
919 checkEquationEnvEnd();
924 if (inputLatexFiles.empty()) {
926 printAlgorithmFileStart(_ss);
928 printAlgorithmFileEnd(_ss);
932 if (_sources !=
nullptr) {
933 (*_sources)[_filename +
".tex"] = _ss.str();
937 (*_sources)[_filename +
".tex"] = _code.str();
942 inline size_t getVariableID(
const Node& node)
const {
943 return _info->
varId[node];
946 inline virtual void printAlgorithmFileStart(std::ostream& out) {
947 out <<
"% Latex source file for '" << _filename <<
"' (automatically generated by CppADCodeGen)" << _endline;
948 out << _algFileStart << _endline;
951 inline virtual void printAlgorithmFileEnd(std::ostream& out) {
955 inline virtual void checkEquationEnvStart() {
956 if (!_inEquationEnv) {
957 _code << _startEqBlock << _endline;
958 _inEquationEnv =
true;
962 inline virtual void checkEquationEnvEnd() {
963 if (_inEquationEnv) {
964 _code << _endEqBlock << _endline;
965 _inEquationEnv =
false;
969 inline unsigned printAssignment(
Node& node) {
970 return printAssignment(node, node);
973 inline unsigned printAssignment(
Node& nodeName,
974 const Arg& nodeRhs) {
975 if (nodeRhs.getOperation() !=
nullptr) {
976 return printAssignment(nodeName, *nodeRhs.getOperation());
978 printAssignmentStart(nodeName);
979 printParameter(*nodeRhs.getParameter());
980 printAssignmentEnd(nodeName);
985 inline unsigned printAssignment(
Node& nodeName,
989 printAssignmentStart(nodeName);
991 unsigned lines = printExpressionNoVarCheck(nodeRhs);
993 printAssignmentEnd(nodeRhs);
998 size_t arrayId = getVariableID(*array);
999 size_t pos = nodeRhs.
getInfo()[0];
1001 _tmpArrayValues[arrayId - 1 + pos] =
nullptr;
1003 _tmpSparseArrayValues[arrayId - 1 + pos] =
nullptr;
1009 inline virtual void printAssignmentStart(
Node& op) {
1010 printAssignmentStart(op, createVariableName(op), isDependent(op));
1013 inline virtual void printAssignmentStart(
Node& node,
const std::string& varName,
bool isDep) {
1015 _temporary[getVariableID(node)] = &node;
1018 checkEquationEnvStart();
1020 _code << _startAlgLine << _startEq;
1022 _code << _startDepVar << varName << _endDepVar;
1024 _code << _startVar << varName << _endVar;
1027 if (op == CGOpCode::DependentMultiAssign || (op == CGOpCode::LoopIndexedDep && node.
getInfo()[1] == 1)) {
1030 _code << _assignStr;
1034 inline virtual void printAssignmentEnd() {
1035 _code << _endEq << _endAlgLine << _endline;
1038 inline virtual void printAssignmentEnd(
Node& op) {
1039 printAssignmentEnd();
1042 virtual void saveLocalFunction(std::vector<std::string>& localFuncNames,
1043 bool zeroDependentArray) {
1044 _ss << _filename <<
"__part_" << (localFuncNames.size() + 1);
1045 std::string funcName = _ss.str();
1049 _nameGen->prepareCustomFunctionVariables(_ss);
1051 _nameGen->finalizeCustomFunctionVariables(_ss);
1053 (*_sources)[funcName +
".tex"] = _ss.str();
1054 localFuncNames.push_back(funcName);
1061 size_t totalUseCount,
1062 size_t opCount)
const override {
1064 if (totalUseCount > 1) {
1065 return op != CGOpCode::ArrayElement && op != CGOpCode::Index && op != CGOpCode::IndexDeclaration && op != CGOpCode::Tmp;
1067 return ( op == CGOpCode::ArrayCreation ||
1068 op == CGOpCode::SparseArrayCreation ||
1069 op == CGOpCode::AtomicForward ||
1070 op == CGOpCode::AtomicReverse ||
1071 op == CGOpCode::ComLt ||
1072 op == CGOpCode::ComLe ||
1073 op == CGOpCode::ComEq ||
1074 op == CGOpCode::ComGe ||
1075 op == CGOpCode::ComGt ||
1076 op == CGOpCode::ComNe ||
1077 op == CGOpCode::LoopIndexedDep ||
1078 op == CGOpCode::LoopIndexedTmp ||
1079 op == CGOpCode::IndexAssign ||
1080 op == CGOpCode::Assign) &&
1081 op != CGOpCode::CondResult;
1085 virtual bool requiresVariableName(
const Node& var)
const {
1088 op != CGOpCode::AtomicForward &&
1089 op != CGOpCode::AtomicReverse &&
1090 op != CGOpCode::LoopStart &&
1091 op != CGOpCode::LoopEnd &&
1092 op != CGOpCode::Index &&
1093 op != CGOpCode::IndexAssign &&
1094 op != CGOpCode::StartIf &&
1095 op != CGOpCode::ElseIf &&
1096 op != CGOpCode::Else &&
1097 op != CGOpCode::EndIf &&
1098 op != CGOpCode::CondResult &&
1099 op != CGOpCode::LoopIndexedTmp &&
1100 op != CGOpCode::Tmp);
1112 return isCondAssign(op) ||
1113 op == CGOpCode::ArrayCreation ||
1114 op == CGOpCode::SparseArrayCreation ||
1115 op == CGOpCode::AtomicForward ||
1116 op == CGOpCode::AtomicReverse ||
1117 op == CGOpCode::DependentMultiAssign ||
1118 op == CGOpCode::LoopStart ||
1119 op == CGOpCode::LoopEnd ||
1120 op == CGOpCode::IndexAssign ||
1121 op == CGOpCode::StartIf ||
1122 op == CGOpCode::ElseIf ||
1123 op == CGOpCode::Else ||
1124 op == CGOpCode::EndIf ||
1125 op == CGOpCode::CondResult ||
1126 op == CGOpCode::IndexDeclaration;
1129 bool requiresVariableArgument(
enum CGOpCode op,
size_t argIndex)
const override {
1130 return op == CGOpCode::CondResult;
1133 inline const std::string& createVariableName(
Node& var) {
1135 CPPADCG_ASSERT_UNKNOWN(getVariableID(var) > 0)
1136 CPPADCG_ASSERT_UNKNOWN(op != CGOpCode::AtomicForward)
1137 CPPADCG_ASSERT_UNKNOWN(op != CGOpCode::AtomicReverse)
1138 CPPADCG_ASSERT_UNKNOWN(op != CGOpCode::LoopStart)
1139 CPPADCG_ASSERT_UNKNOWN(op != CGOpCode::LoopEnd)
1140 CPPADCG_ASSERT_UNKNOWN(op != CGOpCode::Index)
1141 CPPADCG_ASSERT_UNKNOWN(op != CGOpCode::IndexAssign)
1142 CPPADCG_ASSERT_UNKNOWN(op != CGOpCode::IndexDeclaration)
1144 if (var.
getName() ==
nullptr) {
1145 if (op == CGOpCode::ArrayCreation) {
1148 }
else if (op == CGOpCode::SparseArrayCreation) {
1151 }
else if (op == CGOpCode::LoopIndexedDep) {
1152 size_t pos = var.
getInfo()[0];
1153 const IndexPattern* ip = _info->loopDependentIndexPatterns[pos];
1156 }
else if (op == CGOpCode::LoopIndexedIndep) {
1157 size_t pos = var.
getInfo()[1];
1158 const IndexPattern* ip = _info->loopIndependentIndexPatterns[pos];
1161 }
else if (getVariableID(var) <= _independentSize) {
1165 }
else if (getVariableID(var) < _minTemporaryVarID) {
1167 auto it = _dependentIDs.find(getVariableID(var));
1168 CPPADCG_ASSERT_UNKNOWN(it != _dependentIDs.end())
1170 size_t index = it->second;
1173 }
else if (op == CGOpCode::LoopIndexedTmp || op == CGOpCode::Tmp) {
1174 CPPADCG_ASSERT_KNOWN(var.
getArguments().size() >= 1,
"Invalid number of arguments for loop indexed temporary operation")
1176 CPPADCG_ASSERT_KNOWN(tmpVar !=
nullptr && tmpVar->getOperationType() == CGOpCode::TmpDcl,
"Invalid arguments for loop indexed temporary operation")
1177 return createVariableName(*tmpVar);
1193 virtual void printIndependentVariableName(
Node& op) {
1194 CPPADCG_ASSERT_KNOWN(op.
getArguments().size() == 0,
"Invalid number of arguments for independent variable")
1196 _code << _startIndepVar << _nameGen->
generateIndependent(op, getVariableID(op)) << _endIndepVar;
1199 virtual unsigned print(
const Arg& arg) {
1200 if (arg.getOperation() !=
nullptr) {
1202 return printExpression(*arg.getOperation());
1205 printParameter(*arg.getParameter());
1210 virtual unsigned printExpression(
Node& node) {
1211 if (getVariableID(node) > 0) {
1212 const std::string& name = createVariableName(node);
1215 if (getVariableID(node) >= _minTemporaryVarID || op == CGOpCode::ArrayCreation || op == CGOpCode::SparseArrayCreation || op == CGOpCode::LoopIndexedDep || op == CGOpCode::LoopIndexedIndep) {
1217 _code << _startVar << name << _endVar;
1219 }
else if (getVariableID(node) <= _independentSize) {
1221 _code << _startIndepVar << name << _endIndepVar;
1225 _code << _startDepVar << name << _endDepVar;
1232 return printExpressionNoVarCheck(node);
1236 virtual unsigned printExpressionNoVarCheck(
Node& node) {
1239 case CGOpCode::ArrayCreation:
1240 printArrayCreationOp(node);
1242 case CGOpCode::SparseArrayCreation:
1243 printSparseArrayCreationOp(node);
1245 case CGOpCode::ArrayElement:
1246 printArrayElementOp(node);
1248 case CGOpCode::Assign:
1249 return printAssignOp(node);
1252 case CGOpCode::Acos:
1253 case CGOpCode::Asin:
1254 case CGOpCode::Atan:
1255 case CGOpCode::Cosh:
1259 case CGOpCode::Sign:
1260 case CGOpCode::Sinh:
1262 case CGOpCode::Sqrt:
1263 case CGOpCode::Tanh:
1265 #if CPPAD_USE_CPLUSPLUS_2011 1267 case CGOpCode::Erfc:
1268 case CGOpCode::Asinh:
1269 case CGOpCode::Acosh:
1270 case CGOpCode::Atanh:
1271 case CGOpCode::Expm1:
1272 case CGOpCode::Log1p:
1274 printUnaryFunction(node);
1276 case CGOpCode::AtomicForward:
1279 case CGOpCode::AtomicReverse:
1283 printOperationAdd(node);
1285 case CGOpCode::Alias:
1286 return printOperationAlias(node);
1288 case CGOpCode::ComLt:
1289 case CGOpCode::ComLe:
1290 case CGOpCode::ComEq:
1291 case CGOpCode::ComGe:
1292 case CGOpCode::ComGt:
1293 case CGOpCode::ComNe:
1294 printConditionalAssignment(node);
1297 printOperationDiv(node);
1300 printIndependentVariableName(node);
1303 printOperationMul(node);
1306 printPowFunction(node);
1312 printOperationMinus(node);
1315 case CGOpCode::UnMinus:
1316 printOperationUnaryMinus(node);
1319 case CGOpCode::DependentMultiAssign:
1320 return printDependentMultiAssign(node);
1322 case CGOpCode::Index:
1324 case CGOpCode::IndexAssign:
1325 printIndexAssign(node);
1327 case CGOpCode::IndexDeclaration:
1330 case CGOpCode::LoopStart:
1331 printLoopStart(node);
1333 case CGOpCode::LoopIndexedIndep:
1334 printLoopIndexedIndep(node);
1336 case CGOpCode::LoopIndexedDep:
1337 printLoopIndexedDep(node);
1339 case CGOpCode::LoopIndexedTmp:
1340 printLoopIndexedTmp(node);
1342 case CGOpCode::TmpDcl:
1348 case CGOpCode::LoopEnd:
1351 case CGOpCode::IndexCondExpr:
1352 printIndexCondExprOp(node);
1354 case CGOpCode::StartIf:
1357 case CGOpCode::ElseIf:
1360 case CGOpCode::Else:
1363 case CGOpCode::EndIf:
1366 case CGOpCode::CondResult:
1367 printCondResult(node);
1369 case CGOpCode::UserCustom:
1370 printUserCustom(node);
1373 throw CGException(
"Unknown operation code '", op,
"'.");
1378 virtual unsigned printAssignOp(
Node& node) {
1379 CPPADCG_ASSERT_KNOWN(node.
getArguments().size() == 1,
"Invalid number of arguments for assign operation")
1384 virtual void printUnaryFunction(
Node& op) {
1385 CPPADCG_ASSERT_KNOWN(op.
getArguments().size() == 1,
"Invalid number of arguments for unary function")
1393 case CGOpCode::Acos:
1394 _code <<
"\\arccos";
1396 case CGOpCode::Asin:
1397 _code <<
"\\arcsin";
1399 case CGOpCode::Atan:
1400 _code <<
"\\arctan";
1402 case CGOpCode::Cosh:
1414 case CGOpCode::Sinh:
1417 case CGOpCode::Sign:
1418 _code <<
"\\operatorname{sgn}";
1423 case CGOpCode::Sqrt:
1428 case CGOpCode::Tanh:
1434 #if CPPAD_USE_CPLUSPLUS_2011 1436 _code <<
"\\operatorname{erf}";
1438 case CGOpCode::Erfc:
1439 _code <<
"\\operatorname{erfc}";
1441 case CGOpCode::Asinh:
1442 _code <<
"\\operatorname{arcsinh}";
1444 case CGOpCode::Acosh:
1445 _code <<
"\\operatorname{arccosh}";
1447 case CGOpCode::Atanh:
1448 _code <<
"\\operatorname{arctanh}";
1450 case CGOpCode::Expm1:
1451 _code <<
"\\operatorname{expm1}";
1453 case CGOpCode::Log1p:
1454 _code <<
"\\operatorname{log1p}";
1461 _code <<
"\\mathopen{}\\left(";
1463 _code <<
"\\right)\\mathclose{}";
1466 virtual void printPowFunction(
Node& op) {
1467 CPPADCG_ASSERT_KNOWN(op.
getArguments().size() == 2,
"Invalid number of arguments for pow() function")
1469 auto encloseInParentheses = [
this](
const Node* node) {
1470 while (node !=
nullptr) {
1471 if (getVariableID(*node) != 0)
1478 return node !=
nullptr &&
1479 getVariableID(*node) == 0 &&
1483 bool encloseBase = _powBaseEnclose || encloseInParentheses(op.
getArguments()[0].getOperation());
1484 bool encloseExpo = encloseInParentheses(op.
getArguments()[1].getOperation());
1491 _code <<
"\\right)";
1497 _code <<
"\\right)";
1501 virtual unsigned printOperationAlias(
Node& op) {
1502 CPPADCG_ASSERT_KNOWN(op.
getArguments().size() == 1,
"Invalid number of arguments for alias")
1506 virtual void printOperationAdd(
Node& op) {
1507 CPPADCG_ASSERT_KNOWN(op.
getArguments().size() == 2,
"Invalid number of arguments for addition")
1512 if(right.getParameter() ==
nullptr || (*right.getParameter() >= 0)) {
1520 printParameter(-*right.getParameter());
1524 virtual void printOperationMinus(
Node& op) {
1525 CPPADCG_ASSERT_KNOWN(op.
getArguments().size() == 2,
"Invalid number of arguments for subtraction")
1530 if(right.getParameter() ==
nullptr || (*right.getParameter() >= 0)) {
1531 bool encloseRight = encloseInParenthesesMul(right);
1540 _code <<
"\\right)";
1546 printParameter(-*right.getParameter());
1550 virtual void printOperationDiv(
Node& op) {
1551 CPPADCG_ASSERT_KNOWN(op.
getArguments().size() == 2,
"Invalid number of arguments for division")
1565 inline bool encloseInParenthesesMul(
const Arg& arg)
const {
1566 if (arg.getParameter() !=
nullptr) {
1567 return ((*arg.getParameter()) < 0);
1569 return encloseInParenthesesMul(arg.getOperation());
1573 inline bool encloseInParenthesesMul(
const Node* node)
const {
1574 while (node !=
nullptr) {
1575 if (getVariableID(*node) != 0) {
1583 return node !=
nullptr &&
1584 getVariableID(*node) == 0 &&
1590 virtual void printOperationMul(
Node& op) {
1591 CPPADCG_ASSERT_KNOWN(op.
getArguments().size() == 2,
"Invalid number of arguments for multiplication")
1596 bool encloseLeft = encloseInParenthesesMul(left);
1597 bool encloseRight = encloseInParenthesesMul(right);
1599 auto isNumber = [
this](
const Node* node,
int pos) ->
bool {
1600 while (node !=
nullptr) {
1601 if(getVariableID(*node) != 0) {
1605 if (op == CGOpCode::Alias) {
1608 }
else if (op == CGOpCode::Mul) {
1610 }
else if (pos == 0 && op == CGOpCode::Pow) {
1624 _code <<
"\\right)";
1627 if (isNumber(left.getOperation(), 1) && isNumber(right.getOperation(), 0))
1628 _code << _multValOpStr;
1630 _code << _multOpStr;
1637 _code <<
"\\right)";
1641 virtual void printOperationUnaryMinus(
Node& op) {
1642 CPPADCG_ASSERT_KNOWN(op.
getArguments().size() == 1,
"Invalid number of arguments for unary minus")
1646 bool enclose = encloseInParenthesesMul(arg);
1654 _code <<
"\\right)";
1658 virtual void printConditionalAssignment(
Node& node) {
1659 CPPADCG_ASSERT_UNKNOWN(getVariableID(node) > 0)
1662 const Arg &left = args[0];
1663 const Arg &right = args[1];
1664 const Arg &trueCase = args[2];
1665 const Arg &falseCase = args[3];
1667 bool isDep = isDependent(node);
1668 const std::string& varName = createVariableName(node);
1670 if ((trueCase.getParameter() !=
nullptr && falseCase.getParameter() !=
nullptr && *trueCase.getParameter() == *falseCase.getParameter()) ||
1671 (trueCase.getOperation() !=
nullptr && falseCase.getOperation() !=
nullptr && trueCase.getOperation() == falseCase.getOperation())) {
1673 printAssignmentStart(node, varName, isDep);
1675 printAssignmentEnd(node);
1677 checkEquationEnvEnd();
1680 _code << _conditionStart;
1684 _code << _conditionEnd;
1687 printAssignmentStart(node, varName, isDep);
1689 printAssignmentEnd(node);
1690 checkEquationEnvEnd();
1691 _code << _ifEnd << _endline;
1692 _code << _elseStart << _endline;
1694 printAssignmentStart(node, varName, isDep);
1696 printAssignmentEnd(node);
1697 checkEquationEnvEnd();
1698 _code << _elseEnd << _endline;
1702 inline bool isSameArgument(
const Arg& newArg,
1703 const Arg* oldArg) {
1704 if (oldArg !=
nullptr) {
1705 if (oldArg->getParameter() !=
nullptr) {
1706 if (newArg.getParameter() !=
nullptr) {
1707 return (*newArg.getParameter() == *oldArg->getParameter());
1710 return (newArg.getOperation() == oldArg->getOperation());
1716 virtual void printArrayCreationOp(
Node& op);
1718 virtual void printSparseArrayCreationOp(
Node& op);
1720 inline void printArrayStructInit(
const std::string& dataArrayName,
1722 const std::vector<Node*>& arrays,
1725 inline void printArrayStructInit(
const std::string& dataArrayName,
1728 inline void markArrayChanged(
Node& ty);
1733 std::vector<const Arg*>& tmpArrayValues);
1735 inline std::string getTempArrayName(
const Node& op);
1737 virtual void printArrayElementOp(
Node& op);
1740 CPPADCG_ASSERT_KNOWN(atomicFor.
getInfo().size() == 3,
"Invalid number of information elements for atomic forward operation")
1741 int q = atomicFor.
getInfo()[1];
1742 int p = atomicFor.
getInfo()[2];
1744 const std::vector<Arg>& opArgs = atomicFor.
getArguments();
1745 CPPADCG_ASSERT_KNOWN(opArgs.size() == p1 * 2,
"Invalid number of arguments for atomic forward operation")
1747 size_t id = atomicFor.
getInfo()[0];
1748 std::vector<Node*> tx(p1), ty(p1);
1749 for (
size_t k = 0; k < p1; k++) {
1750 tx[k] = opArgs[0 * p1 + k].getOperation();
1751 ty[k] = opArgs[1 * p1 + k].getOperation();
1754 CPPADCG_ASSERT_KNOWN(tx[0]->getOperationType() == CGOpCode::ArrayCreation,
"Invalid array type")
1755 CPPADCG_ASSERT_KNOWN(p == 0 || tx[1]->getOperationType() == CGOpCode::SparseArrayCreation,
"Invalid array type")
1756 CPPADCG_ASSERT_KNOWN(ty[p]->getOperationType() == CGOpCode::ArrayCreation,
"Invalid array type")
1759 for (
size_t k = 0; k < p1; k++) {
1760 printArrayStructInit(_ATOMIC_TX, k, tx, k);
1763 printArrayStructInit(_ATOMIC_TY, *ty[p]);
1766 _code << _startAlgLine << _startEq
1768 << q <<
", " << p <<
", " 1769 << _ATOMIC_TX <<
", &" << _ATOMIC_TY <<
")" 1770 << _endEq << _endAlgLine << _endline;
1775 markArrayChanged(*ty[p]);
1779 CPPADCG_ASSERT_KNOWN(atomicRev.
getInfo().size() == 2,
"Invalid number of information elements for atomic reverse operation")
1780 int p = atomicRev.
getInfo()[1];
1782 const std::vector<Arg>& opArgs = atomicRev.
getArguments();
1783 CPPADCG_ASSERT_KNOWN(opArgs.size() == p1 * 4,
"Invalid number of arguments for atomic reverse operation")
1785 size_t id = atomicRev.
getInfo()[0];
1786 std::vector<Node*> tx(p1), px(p1), py(p1);
1787 for (
size_t k = 0; k < p1; k++) {
1788 tx[k] = opArgs[0 * p1 + k].getOperation();
1789 px[k] = opArgs[2 * p1 + k].getOperation();
1790 py[k] = opArgs[3 * p1 + k].getOperation();
1793 CPPADCG_ASSERT_KNOWN(tx[0]->getOperationType() == CGOpCode::ArrayCreation,
"Invalid array type")
1794 CPPADCG_ASSERT_KNOWN(p == 0 || tx[1]->getOperationType() == CGOpCode::SparseArrayCreation,
"Invalid array type")
1796 CPPADCG_ASSERT_KNOWN(px[0]->getOperationType() == CGOpCode::ArrayCreation,
"Invalid array type")
1798 CPPADCG_ASSERT_KNOWN(py[0]->getOperationType() == CGOpCode::SparseArrayCreation,
"Invalid array type")
1799 CPPADCG_ASSERT_KNOWN(p == 0 || py[1]->getOperationType() == CGOpCode::ArrayCreation,
"Invalid array type")
1802 for (
size_t k = 0; k < p1; k++) {
1803 printArrayStructInit(_ATOMIC_TX, k, tx, k);
1806 for (
size_t k = 0; k < p1; k++) {
1807 printArrayStructInit(_ATOMIC_PY, k, py, k);
1810 printArrayStructInit(_ATOMIC_PX, *px[0]);
1813 _code << _startAlgLine << _startEq
1816 << _ATOMIC_TX <<
", &" << _ATOMIC_PX <<
", " << _ATOMIC_PY <<
")" 1817 << _endEq << _endAlgLine << _endline;
1822 markArrayChanged(*px[0]);
1825 virtual unsigned printDependentMultiAssign(
Node& node) {
1826 CPPADCG_ASSERT_KNOWN(node.
getOperationType() == CGOpCode::DependentMultiAssign,
"Invalid node type")
1827 CPPADCG_ASSERT_KNOWN(node.
getArguments().size() > 0,
"Invalid number of arguments")
1830 for (
size_t a = 0; a < args.size(); a++) {
1831 bool useArg =
false;
1832 const Arg& arg = args[a];
1833 if (arg.getParameter() !=
nullptr) {
1836 CGOpCode op = arg.getOperation()->getOperationType();
1837 useArg = op != CGOpCode::DependentRefRhs && op != CGOpCode::LoopEnd && op != CGOpCode::EndIf;
1841 printAssignment(node, arg);
1848 virtual void printLoopStart(
Node& node) {
1849 CPPADCG_ASSERT_KNOWN(node.
getOperationType() == CGOpCode::LoopStart,
"Invalid node type")
1852 _currentLoops.push_back(&lnode);
1854 const std::string& jj = *lnode.getIndex().getName();
1856 if (lnode.getIterationCountNode() !=
nullptr) {
1857 lastIt = *lnode.getIterationCountNode()->getIndex().getName() +
" - 1";
1859 lastIt = std::to_string(lnode.getIterationCount() - 1);
1862 checkEquationEnvEnd();
1864 _code << _forStart <<
"{$" << jj <<
"\\in \\left[0, " << lastIt <<
"\\right]$}" << _endline;
1865 _indentationLevel++;
1868 virtual void printLoopEnd(
Node& node) {
1869 CPPADCG_ASSERT_KNOWN(node.
getOperationType() == CGOpCode::LoopEnd,
"Invalid node type")
1871 checkEquationEnvEnd();
1873 _indentationLevel--;
1875 _code << _forEnd << _endline;
1877 _currentLoops.pop_back();
1880 virtual void printLoopIndexedDep(
Node& node) {
1881 CPPADCG_ASSERT_KNOWN(node.
getArguments().size() >= 1,
"Invalid number of arguments for loop indexed dependent operation")
1887 virtual void printLoopIndexedIndep(
Node& node) {
1888 CPPADCG_ASSERT_KNOWN(node.
getOperationType() == CGOpCode::LoopIndexedIndep,
"Invalid node type")
1889 CPPADCG_ASSERT_KNOWN(node.
getInfo().size() == 1,
"Invalid number of information elements for loop indexed independent operation")
1892 size_t pos = node.
getInfo()[1];
1893 const IndexPattern* ip = _info->loopIndependentIndexPatterns[pos];
1897 virtual void printLoopIndexedTmp(
Node& node) {
1898 CPPADCG_ASSERT_KNOWN(node.
getOperationType() == CGOpCode::LoopIndexedTmp,
"Invalid node type")
1899 CPPADCG_ASSERT_KNOWN(node.
getArguments().size() == 2,
"Invalid number of arguments for loop indexed temporary operation")
1901 CPPADCG_ASSERT_KNOWN(tmpVar !=
nullptr && tmpVar->getOperationType() == CGOpCode::TmpDcl,
"Invalid arguments for loop indexed temporary operation")
1906 virtual void printTmpVar(
Node& node) {
1907 CPPADCG_ASSERT_KNOWN(node.
getOperationType() == CGOpCode::Tmp,
"Invalid node type")
1908 CPPADCG_ASSERT_KNOWN(node.
getArguments().size() > 0,
"Invalid number of arguments for temporary variable usage operation")
1910 CPPADCG_ASSERT_KNOWN(tmpVar !=
nullptr && tmpVar->getOperationType() == CGOpCode::TmpDcl,
"Invalid arguments for loop indexed temporary operation")
1912 _code << _startVar << *tmpVar->getName() << _endVar;
1915 virtual void printIndexAssign(
Node& node) {
1916 CPPADCG_ASSERT_KNOWN(node.
getOperationType() == CGOpCode::IndexAssign,
"Invalid node type")
1917 CPPADCG_ASSERT_KNOWN(node.
getArguments().size() > 0,
"Invalid number of arguments for an index assignment operation")
1921 checkEquationEnvStart();
1924 _code << _startAlgLine << _startEq
1925 << (*inode.getIndex().getName())
1926 << _assignStr << indexPattern2String(ip, inode.getIndexPatternIndexes())
1927 << _endEq << _endAlgLine << _endline;
1930 virtual void printIndexCondExprOp(
Node& node) {
1931 CPPADCG_ASSERT_KNOWN(node.
getOperationType() == CGOpCode::IndexCondExpr,
"Invalid node type")
1932 CPPADCG_ASSERT_KNOWN(node.
getArguments().size() == 1,
"Invalid number of arguments for an index condition expression operation")
1933 CPPADCG_ASSERT_KNOWN(node.
getArguments()[0].getOperation() !=
nullptr,
"Invalid argument for an index condition expression operation")
1934 CPPADCG_ASSERT_KNOWN(node.
getArguments()[0].getOperation()->getOperationType() == CGOpCode::Index,
"Invalid argument for an index condition expression operation")
1936 const std::vector<size_t>& info = node.
getInfo();
1939 const std::string& index = *iterationIndexOp.getIndex().
getName();
1941 checkEquationEnvStart();
1943 printIndexCondExpr(_code, info, index);
1951 CPPADCG_ASSERT_KNOWN(node.
getOperationType() == CGOpCode::StartIf,
"Invalid node type")
1952 CPPADCG_ASSERT_KNOWN(node.
getArguments().size() >= 1,
"Invalid number of arguments for an 'if start' operation")
1953 CPPADCG_ASSERT_KNOWN(node.
getArguments()[0].getOperation() !=
nullptr,
"Invalid argument for an 'if start' operation")
1955 checkEquationEnvEnd();
1959 _code << _conditionStart;
1960 printIndexCondExprOp(*node.
getArguments()[0].getOperation());
1961 checkEquationEnvEnd();
1962 _code << _conditionEnd;
1965 _indentationLevel++;
1974 CPPADCG_ASSERT_KNOWN(node.
getOperationType() == CGOpCode::ElseIf,
"Invalid node type")
1975 CPPADCG_ASSERT_KNOWN(node.
getArguments().size() >= 2,
"Invalid number of arguments for an 'else if' operation")
1976 CPPADCG_ASSERT_KNOWN(node.
getArguments()[0].getOperation() !=
nullptr,
"Invalid argument for an 'else if' operation")
1977 CPPADCG_ASSERT_KNOWN(node.
getArguments()[1].getOperation() !=
nullptr,
"Invalid argument for an 'else if' operation")
1979 checkEquationEnvEnd();
1980 _indentationLevel--;
1983 CGOpCode nType = node.
getArguments()[0].getOperation()->getOperationType();
1984 if (nType == CGOpCode::StartIf) {
1985 _code << _ifEnd << _endline;
1986 }
else if (nType == CGOpCode::ElseIf) {
1987 _code << _elseIfEnd << _endline;
1991 _code << _elseIfStart;
1992 _code << _conditionStart;
1994 printIndexCondExprOp(*node.
getArguments()[1].getOperation());
1995 checkEquationEnvEnd();
1996 _code << _conditionEnd;
1999 _indentationLevel++;
2007 CPPADCG_ASSERT_KNOWN(node.
getOperationType() == CGOpCode::Else,
"Invalid node type")
2008 CPPADCG_ASSERT_KNOWN(node.
getArguments().size() >= 1,
"Invalid number of arguments for an 'else' operation")
2010 checkEquationEnvEnd();
2011 _indentationLevel--;
2014 CGOpCode nType = node.
getArguments()[0].getOperation()->getOperationType();
2015 if (nType == CGOpCode::StartIf) {
2016 _code << _ifEnd << _endline;
2017 }
else if (nType == CGOpCode::ElseIf) {
2018 _code << _elseIfEnd << _endline;
2022 _code << _elseStart << _endline;
2024 _indentationLevel++;
2027 virtual void printEndIf(
Node& node) {
2028 CPPADCG_ASSERT_KNOWN(node.
getOperationType() == CGOpCode::EndIf,
"Invalid node type for an 'end if' operation")
2030 _indentationLevel--;
2033 CGOpCode nType = node.
getArguments()[0].getOperation()->getOperationType();
2034 if (nType == CGOpCode::StartIf) {
2035 _code << _ifEnd << _endline;
2036 }
else if (nType == CGOpCode::ElseIf) {
2037 _code << _elseIfEnd << _endline;
2039 assert(nType == CGOpCode::Else);
2040 _code << _elseEnd << _endline;
2044 virtual void printCondResult(
Node& node) {
2045 CPPADCG_ASSERT_KNOWN(node.
getOperationType() == CGOpCode::CondResult,
"Invalid node type")
2046 CPPADCG_ASSERT_KNOWN(node.
getArguments().size() == 2,
"Invalid number of arguments for an assignment inside an if/else operation")
2047 CPPADCG_ASSERT_KNOWN(node.
getArguments()[0].getOperation() !=
nullptr,
"Invalid argument for an an assignment inside an if/else operation")
2048 CPPADCG_ASSERT_KNOWN(node.
getArguments()[1].getOperation() !=
nullptr,
"Invalid argument for an an assignment inside an if/else operation")
2052 printAssignment(nodeArg);
2055 virtual void printUserCustom(
Node& node) {
2056 CPPADCG_ASSERT_KNOWN(node.
getOperationType() == CGOpCode::UserCustom,
"Invalid node type")
2058 throw CGException(
"Unable to generate Latex for user custom operation nodes.");
2061 inline bool isDependent(
const Node& arg)
const {
2065 size_t id = getVariableID(arg);
2066 return id > _independentSize &&
id < _minTemporaryVarID;
2069 virtual void printParameter(
const Base& value) {
2071 std::ostringstream os;
2072 os << std::setprecision(_parameterPrecision) << value;
2074 std::string number = os.str();
2075 size_t pos = number.find(
'e');
2076 if (pos != std::string::npos) {
2077 std::string n =
" \\times 10^{";
2078 number.replace(pos, 1, n);
2080 if (number[pos] ==
'-' || number[pos] ==
'+')
2082 while (number[pos] ==
'0')
2083 number.replace(pos, 1,
"");
2091 virtual const std::string& getComparison(
enum CGOpCode op)
const {
2093 case CGOpCode::ComLt:
2096 case CGOpCode::ComLe:
2099 case CGOpCode::ComEq:
2102 case CGOpCode::ComGe:
2105 case CGOpCode::ComGt:
2108 case CGOpCode::ComNe:
2112 CPPAD_ASSERT_UNKNOWN(0)
2115 throw CGException(
"Invalid comparison operator code");
2118 inline const std::string& getPrintfBaseFormat() {
2119 static const std::string format;
2123 static bool isFunction(
enum CGOpCode op) {
2124 return isUnaryFunction(op) || op == CGOpCode::Pow;
2127 static bool isUnaryFunction(
enum CGOpCode op) {
2130 case CGOpCode::Acos:
2131 case CGOpCode::Asin:
2132 case CGOpCode::Atan:
2133 case CGOpCode::Cosh:
2137 case CGOpCode::Sign:
2138 case CGOpCode::Sinh:
2140 #if CPPAD_USE_CPLUSPLUS_2011 2142 case CGOpCode::Erfc:
2143 case CGOpCode::Asinh:
2144 case CGOpCode::Acosh:
2145 case CGOpCode::Atanh:
2146 case CGOpCode::Expm1:
2147 case CGOpCode::Log1p:
2149 case CGOpCode::Sqrt:
2150 case CGOpCode::Tanh:
2158 static bool isCondAssign(
enum CGOpCode op) {
2160 case CGOpCode::ComLt:
2161 case CGOpCode::ComLe:
2162 case CGOpCode::ComEq:
2163 case CGOpCode::ComGe:
2164 case CGOpCode::ComGt:
2165 case CGOpCode::ComNe:
2173 template<
class Base>
2175 template<
class Base>
2177 template<
class Base>
2179 template<
class Base>
2181 template<
class Base>
2183 template<
class Base>
2186 template<
class Base>
2189 template<
class Base>
2192 template<
class Base>
2195 template<
class Base>
2198 template<
class Base>
2201 template<
class Base>
virtual size_t getParameterPrecision() const
virtual void printStartIf(Node &node)
const std::map< size_t, std::string > & atomicFunctionId2Name
virtual std::string generateTemporary(const OperationNode< Base > &variable, size_t id)=0
virtual const std::string & getDependentVarEnvironmentEnd() const
virtual std::string generateIndexedDependent(const OperationNode< Base > &var, size_t id, const IndexPattern &ip)=0
virtual const std::string & getForEnvironmentEnd() const
virtual size_t getMaxTemporaryArrayVariableID() const =0
virtual void setIfEnvironment(const std::string &begin, const std::string &end)
virtual std::string generateIndexedIndependent(const OperationNode< Base > &var, size_t id, const IndexPattern &ip)=0
virtual void setEquationEnvironment(const std::string &begin, const std::string &end)
virtual const std::string & getElseEnvironmentStart() const
const std::string * getName() const
virtual const std::string & getAlgorithmLineEnvironmentStart() const
virtual const std::string & getIfEnvironmentEnd() const
const std::vector< Argument< Base > > & getArguments() const
virtual const std::vector< FuncArgument > & getTemporary() const
virtual const std::string & getElseIfEnvironmentStart() const
virtual const std::string & getIndependentVarEnvironmentEnd() const
virtual void printElse(Node &node)
virtual const std::string & getConditionEnvironmentStart() const
virtual bool isAlwaysEnclosePowBase() const
virtual const std::string & getElseIfEnvironmentEnd() const
virtual const std::string & getEquationEnvironmentStart() const
const CodeHandlerVector< Base, size_t > & varId
virtual void setIndependentVarEnvironment(const std::string &begin, const std::string &end)
bool createsNewVariable(const Node &var, size_t totalUseCount, size_t opCount) const override
virtual void printAtomicForwardOp(Node &atomicFor)
const std::string & getMultiplicationConstParOperator() const
virtual void setElseEnvironment(const std::string &begin, const std::string &end)
virtual std::string generateDependent(size_t index)=0
virtual const std::string & getVariableEnvironmentStart() const
virtual const std::string & getElseEnvironmentEnd() const
const CodeHandlerVector< Base, size_t > & totalUseCount
CGOpCode getOperationType() const
virtual const std::string & getForEnvironmentStart() const
virtual const std::string & getIndependentVarEnvironmentStart() const
virtual const std::string & getAgorithmFileEnvironmentStart() const
virtual void setAlwaysEnclosePowBase(bool enclose)
virtual const std::string & getIfEnvironmentStart() const
bool requiresVariableDependencies() const override
virtual const std::string & getDependentVarEnvironmentStart() const
virtual void setConditionEnvironment(const std::string &begin, const std::string &end)
virtual std::string generateTemporaryArray(const OperationNode< Base > &variable, size_t id)=0
virtual void setElseIfEnvironment(const std::string &begin, const std::string &end)
virtual const std::string & getEquationEnvironmentEnd() const
virtual size_t getMaxTemporarySparseArrayVariableID() const =0
void setMultiplicationOperator(const std::string &multOpStr)
void generateSourceCode(std::ostream &out, std::unique_ptr< LanguageGenerationData< Base > > info) override
virtual const std::vector< FuncArgument > & getDependent() const
virtual std::string generateTemporarySparseArray(const OperationNode< Base > &variable, size_t id)=0
size_t printArrayCreationUsingLoop(size_t startPos, Node &array, size_t startj, std::vector< const Arg *> &tmpArrayValues)
const std::string & getMultiplicationOperator() const
virtual const std::string & getEquationBlockEnvironmentEnd() const
virtual const std::vector< FuncArgument > & getIndependent() const
virtual void setParameterPrecision(size_t p)
virtual const std::string & getConditionEnvironmentEnd() const
virtual void setDependentVarEnvironment(const std::string &begin, const std::string &end)
virtual void printElseIf(Node &node)
virtual std::string generateIndependent(const OperationNode< Base > &variable, size_t id)=0
void setName(const std::string &name)
void setMultiplicationConstParOperator(const std::string &multValOpStr)
virtual const std::string & getVariableEnvironmentEnd() const
virtual const std::string & getAlgorithmLineEnvironmentEnd() const
virtual bool directlyAssignsVariable(const Node &var) const
virtual void setForEnvironment(const std::string &begin, const std::string &end)
size_t size() const noexcept
virtual void setVariableEnvironment(const std::string &begin, const std::string &end)
virtual const std::string & getAgorithmFileEnvironmentEnd() const
void printRandomIndexPatternDeclaration(std::ostringstream &os, const std::string &identation, const std::set< RandomIndexPattern *> &randomPatterns)
virtual void printAtomicReverseOp(Node &atomicRev)
virtual void setEquationBlockEnvironment(const std::string &begin, const std::string &end)
virtual const std::string & getEquationBlockEnvironmentStart() const
virtual void setAlgorithmLineEnvironment(const std::string &begin, const std::string &end)
const std::vector< size_t > & getInfo() const
virtual void setAgorithmFileEnvironment(const std::string &begin, const std::string &end)