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;
616 static inline void printIndexCondExpr(std::ostringstream& out,
617 const std::vector<size_t>& info,
618 const std::string& index) {
619 CPPADCG_ASSERT_KNOWN(info.size() > 1 && info.size() % 2 == 0,
"Invalid number of information elements for an index condition expression operation");
621 size_t infoSize = info.size();
622 for (
size_t e = 0; e < infoSize; e += 2) {
626 size_t min = info[e];
627 size_t max = info[e + 1];
629 out << index <<
" == " << min;
630 }
else if (min == 0) {
631 out << index <<
" \\le " << max;
632 }
else if (max == std::numeric_limits<size_t>::max()) {
633 out << min <<
" \\le " << index;
639 out << min <<
" == " << index <<
" \\vee " << index <<
" == " << max;
641 out << min <<
" \\le " << index <<
" \\wedge" << index <<
" \\le " << max;
653 inline void printStaticIndexArray(std::ostringstream& os,
654 const std::string& name,
655 const std::vector<size_t>& values);
657 inline void printStaticIndexMatrix(std::ostringstream& os,
658 const std::string& name,
659 const std::map<
size_t, std::map<size_t, size_t> >& values);
664 static inline void generateNames4RandomIndexPatterns(
const std::set<RandomIndexPattern*>& randomPatterns);
667 const std::string& identation,
668 const std::set<RandomIndexPattern*>& randomPatterns);
670 static inline std::string indexPattern2String(
const IndexPattern& ip,
673 static inline std::string indexPattern2String(
const IndexPattern& ip,
674 const std::vector<const Node*>& indexes);
687 const bool multiFile = _maxAssignmentsPerFile > 0 && _sources !=
nullptr;
692 _indentationLevel = 0;
694 _inEquationEnv =
false;
696 _currentLoops.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.size() > 0 && depArg.size() > 0,
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 std::map<size_t, size_t>::const_iterator 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) {
812 const std::vector<FuncArgument>& depArg = _nameGen->
getDependent();
814 checkEquationEnvStart();
815 for (
size_t i = 0; i < depArg.size(); i++) {
816 _code << _startAlgLine << _startEq;
824 printParameter(Base(0.0));
825 _code << _endEq << _endAlgLine << _endline;
829 size_t assignCount = 0;
830 for (
Node* it : variableOrder) {
832 if (assignCount >= _maxAssignmentsPerFile && multiFile && _currentLoops.empty()) {
834 saveLocalFunction(inputLatexFiles, inputLatexFiles.empty() && info->zeroDependents);
840 if (node.getOperationType() == CGOpCode::DependentRefRhs) {
842 }
else if (node.getOperationType() == CGOpCode::TmpDcl) {
846 assignCount += printAssignment(node);
849 if (inputLatexFiles.size() > 0 && assignCount > 0) {
851 saveLocalFunction(inputLatexFiles,
false);
855 if (!inputLatexFiles.empty()) {
859 CPPADCG_ASSERT_KNOWN(tmpArg[0].array,
860 "The temporary variables must be saved in an array in order to generate multiple functions");
861 printAlgorithmFileStart(_code);
862 for (
size_t i = 0; i < inputLatexFiles.size(); i++) {
863 _code <<
"\\input{" << inputLatexFiles[i] <<
"}" << _endline;
865 printAlgorithmFileEnd(_code);
869 if (dependentDuplicates.size() > 0) {
870 _code <<
"% variable duplicates: " << dependentDuplicates.size() << _endline;
872 checkEquationEnvStart();
873 for (
size_t index : dependentDuplicates) {
874 const CG<Base>& dep = (*_dependent)[index];
876 const std::string& origVarName = *dep.getOperationNode()->getName();
878 _code << _startAlgLine << _startEq
879 << _startDepVar << varName << _endDepVar
881 << _startDepVar << origVarName << _endDepVar;
882 printAssignmentEnd();
887 bool commentWritten =
false;
888 for (
size_t i = 0; i < dependent.
size(); i++) {
889 if (dependent[i].isParameter()) {
890 if (!_ignoreZeroDepAssign || !dependent[i].isIdenticalZero()) {
891 if (!commentWritten) {
892 _code <<
"% dependent variables without operations" << _endline;
893 commentWritten =
true;
895 checkEquationEnvStart();
898 _code << _startAlgLine << _startEq
899 << _startDepVar << varName << _endDepVar << _assignStr;
900 printParameter(dependent[i].getValue());
901 printAssignmentEnd();
903 }
else if (dependent[i].getOperationNode()->getOperationType() == CGOpCode::Inv) {
904 if (!commentWritten) {
905 _code <<
"% dependent variables without operations" << _endline;
906 commentWritten =
true;
908 checkEquationEnvStart();
911 const std::string& indepName = *dependent[i].getOperationNode()->getName();
912 _code << _startAlgLine << _startEq
913 << _startDepVar << varName << _endDepVar
915 << _startIndepVar << indepName << _endIndepVar;
916 printAssignmentEnd(*dependent[i].getOperationNode());
920 checkEquationEnvEnd();
925 if (inputLatexFiles.empty()) {
927 printAlgorithmFileStart(_ss);
929 printAlgorithmFileEnd(_ss);
933 if (_sources !=
nullptr) {
934 (*_sources)[_filename +
".tex"] = _ss.str();
938 (*_sources)[_filename +
".tex"] = _code.str();
943 inline size_t getVariableID(
const Node& node)
const {
944 return _info->
varId[node];
947 inline virtual void printAlgorithmFileStart(std::ostream& out) {
948 out <<
"% Latex source file for '" << _filename <<
"' (automatically generated by CppADCodeGen)" << _endline;
949 out << _algFileStart << _endline;
952 inline virtual void printAlgorithmFileEnd(std::ostream& out) {
956 inline virtual void checkEquationEnvStart() {
957 if (!_inEquationEnv) {
958 _code << _startEqBlock << _endline;
959 _inEquationEnv =
true;
963 inline virtual void checkEquationEnvEnd() {
964 if (_inEquationEnv) {
965 _code << _endEqBlock << _endline;
966 _inEquationEnv =
false;
970 inline unsigned printAssignment(
Node& node) {
971 return printAssignment(node, node);
974 inline unsigned printAssignment(
Node& nodeName,
975 const Arg& nodeRhs) {
976 if (nodeRhs.getOperation() !=
nullptr) {
977 return printAssignment(nodeName, *nodeRhs.getOperation());
979 printAssignmentStart(nodeName);
980 printParameter(*nodeRhs.getParameter());
981 printAssignmentEnd(nodeName);
986 inline unsigned printAssignment(
Node& nodeName,
990 printAssignmentStart(nodeName);
992 unsigned lines = printExpressionNoVarCheck(nodeRhs);
994 printAssignmentEnd(nodeRhs);
999 size_t arrayId = getVariableID(*array);
1000 size_t pos = nodeRhs.
getInfo()[0];
1002 _tmpArrayValues[arrayId - 1 + pos] =
nullptr;
1004 _tmpSparseArrayValues[arrayId - 1 + pos] =
nullptr;
1010 inline virtual void printAssignmentStart(
Node& op) {
1011 printAssignmentStart(op, createVariableName(op), isDependent(op));
1014 inline virtual void printAssignmentStart(
Node& node,
const std::string& varName,
bool isDep) {
1016 _temporary[getVariableID(node)] = &node;
1019 checkEquationEnvStart();
1021 _code << _startAlgLine << _startEq;
1023 _code << _startDepVar << varName << _endDepVar;
1025 _code << _startVar << varName << _endVar;
1028 if (op == CGOpCode::DependentMultiAssign || (op == CGOpCode::LoopIndexedDep && node.
getInfo()[1] == 1)) {
1031 _code << _assignStr;
1035 inline virtual void printAssignmentEnd() {
1036 _code << _endEq << _endAlgLine << _endline;
1039 inline virtual void printAssignmentEnd(
Node& op) {
1040 printAssignmentEnd();
1043 virtual void saveLocalFunction(std::vector<std::string>& localFuncNames,
1044 bool zeroDependentArray) {
1045 _ss << _filename <<
"__part_" << (localFuncNames.size() + 1);
1046 std::string funcName = _ss.str();
1050 _nameGen->prepareCustomFunctionVariables(_ss);
1052 _nameGen->finalizeCustomFunctionVariables(_ss);
1054 (*_sources)[funcName +
".tex"] = _ss.str();
1055 localFuncNames.push_back(funcName);
1062 size_t totalUseCount)
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 std::map<size_t, size_t>::const_iterator 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 printUnaryFunction(node);
1267 case CGOpCode::AtomicForward:
1270 case CGOpCode::AtomicReverse:
1274 printOperationAdd(node);
1276 case CGOpCode::Alias:
1277 return printOperationAlias(node);
1279 case CGOpCode::ComLt:
1280 case CGOpCode::ComLe:
1281 case CGOpCode::ComEq:
1282 case CGOpCode::ComGe:
1283 case CGOpCode::ComGt:
1284 case CGOpCode::ComNe:
1285 printConditionalAssignment(node);
1288 printOperationDiv(node);
1291 printIndependentVariableName(node);
1294 printOperationMul(node);
1297 printPowFunction(node);
1303 printOperationMinus(node);
1306 case CGOpCode::UnMinus:
1307 printOperationUnaryMinus(node);
1310 case CGOpCode::DependentMultiAssign:
1311 return printDependentMultiAssign(node);
1313 case CGOpCode::Index:
1315 case CGOpCode::IndexAssign:
1316 printIndexAssign(node);
1318 case CGOpCode::IndexDeclaration:
1321 case CGOpCode::LoopStart:
1322 printLoopStart(node);
1324 case CGOpCode::LoopIndexedIndep:
1325 printLoopIndexedIndep(node);
1327 case CGOpCode::LoopIndexedDep:
1328 printLoopIndexedDep(node);
1330 case CGOpCode::LoopIndexedTmp:
1331 printLoopIndexedTmp(node);
1333 case CGOpCode::TmpDcl:
1339 case CGOpCode::LoopEnd:
1342 case CGOpCode::IndexCondExpr:
1343 printIndexCondExprOp(node);
1345 case CGOpCode::StartIf:
1348 case CGOpCode::ElseIf:
1351 case CGOpCode::Else:
1354 case CGOpCode::EndIf:
1357 case CGOpCode::CondResult:
1358 printCondResult(node);
1360 case CGOpCode::UserCustom:
1361 printUserCustom(node);
1364 throw CGException(
"Unknown operation code '", op,
"'.");
1369 virtual unsigned printAssignOp(
Node& node) {
1370 CPPADCG_ASSERT_KNOWN(node.
getArguments().size() == 1,
"Invalid number of arguments for assign operation");
1375 virtual void printUnaryFunction(
Node& op) {
1376 CPPADCG_ASSERT_KNOWN(op.
getArguments().size() == 1,
"Invalid number of arguments for unary function");
1384 case CGOpCode::Acos:
1385 _code <<
"\\arccos";
1387 case CGOpCode::Asin:
1388 _code <<
"\\arcsin";
1390 case CGOpCode::Atan:
1391 _code <<
"\\arctan";
1393 case CGOpCode::Cosh:
1405 case CGOpCode::Sinh:
1408 case CGOpCode::Sign:
1409 _code <<
"\\operatorname{sgn}";
1414 case CGOpCode::Sqrt:
1419 case CGOpCode::Tanh:
1429 _code <<
"\\mathopen{}\\left(";
1431 _code <<
"\\right)\\mathclose{}";
1434 virtual void printPowFunction(
Node& op) {
1435 CPPADCG_ASSERT_KNOWN(op.
getArguments().size() == 2,
"Invalid number of arguments for pow() function");
1437 auto encloseInParentheses = [
this](
const Node* node) {
1438 while (node !=
nullptr) {
1439 if (getVariableID(*node) != 0)
1446 return node !=
nullptr &&
1447 getVariableID(*node) == 0 &&
1451 bool encloseBase = _powBaseEnclose || encloseInParentheses(op.
getArguments()[0].getOperation());
1452 bool encloseExpo = encloseInParentheses(op.
getArguments()[1].getOperation());
1459 _code <<
"\\right)";
1465 _code <<
"\\right)";
1469 virtual unsigned printOperationAlias(
Node& op) {
1470 CPPADCG_ASSERT_KNOWN(op.
getArguments().size() == 1,
"Invalid number of arguments for alias");
1474 virtual void printOperationAdd(
Node& op) {
1475 CPPADCG_ASSERT_KNOWN(op.
getArguments().size() == 2,
"Invalid number of arguments for addition");
1480 if(right.getParameter() ==
nullptr || (*right.getParameter() >= 0)) {
1488 printParameter(-*right.getParameter());
1492 virtual void printOperationMinus(
Node& op) {
1493 CPPADCG_ASSERT_KNOWN(op.
getArguments().size() == 2,
"Invalid number of arguments for subtraction");
1498 if(right.getParameter() ==
nullptr || (*right.getParameter() >= 0)) {
1499 bool encloseRight = encloseInParenthesesMul(right);
1508 _code <<
"\\right)";
1514 printParameter(-*right.getParameter());
1518 virtual void printOperationDiv(
Node& op) {
1519 CPPADCG_ASSERT_KNOWN(op.
getArguments().size() == 2,
"Invalid number of arguments for division");
1533 inline bool encloseInParenthesesMul(
const Arg& arg)
const {
1534 if (arg.getParameter() !=
nullptr) {
1535 return ((*arg.getParameter()) < 0);
1537 return encloseInParenthesesMul(arg.getOperation());
1541 inline bool encloseInParenthesesMul(
const Node* node)
const {
1542 while (node !=
nullptr) {
1543 if (getVariableID(*node) != 0) {
1551 return node !=
nullptr &&
1552 getVariableID(*node) == 0 &&
1558 virtual void printOperationMul(
Node& op) {
1559 CPPADCG_ASSERT_KNOWN(op.
getArguments().size() == 2,
"Invalid number of arguments for multiplication");
1564 bool encloseLeft = encloseInParenthesesMul(left);
1565 bool encloseRight = encloseInParenthesesMul(right);
1567 auto isNumber = [
this](
const Node* node,
int pos) ->
bool {
1568 while (node !=
nullptr) {
1569 if(getVariableID(*node) != 0) {
1573 if (op == CGOpCode::Alias) {
1576 }
else if (op == CGOpCode::Mul) {
1578 }
else if (pos == 0 && op == CGOpCode::Pow) {
1592 _code <<
"\\right)";
1595 if (isNumber(left.getOperation(), 1) && isNumber(right.getOperation(), 0))
1596 _code << _multValOpStr;
1598 _code << _multOpStr;
1605 _code <<
"\\right)";
1609 virtual void printOperationUnaryMinus(
Node& op) {
1610 CPPADCG_ASSERT_KNOWN(op.
getArguments().size() == 1,
"Invalid number of arguments for unary minus");
1614 bool enclose = encloseInParenthesesMul(arg);
1622 _code <<
"\\right)";
1626 virtual void printConditionalAssignment(
Node& node) {
1627 CPPADCG_ASSERT_UNKNOWN(getVariableID(node) > 0);
1630 const Arg &left = args[0];
1631 const Arg &right = args[1];
1632 const Arg &trueCase = args[2];
1633 const Arg &falseCase = args[3];
1635 bool isDep = isDependent(node);
1636 const std::string& varName = createVariableName(node);
1638 if ((trueCase.getParameter() !=
nullptr && falseCase.getParameter() !=
nullptr && *trueCase.getParameter() == *falseCase.getParameter()) ||
1639 (trueCase.getOperation() !=
nullptr && falseCase.getOperation() !=
nullptr && trueCase.getOperation() == falseCase.getOperation())) {
1641 printAssignmentStart(node, varName, isDep);
1643 printAssignmentEnd(node);
1645 checkEquationEnvEnd();
1648 _code << _conditionStart;
1652 _code << _conditionEnd;
1655 printAssignmentStart(node, varName, isDep);
1657 printAssignmentEnd(node);
1658 checkEquationEnvEnd();
1659 _code << _ifEnd << _endline;
1660 _code << _elseStart << _endline;
1662 printAssignmentStart(node, varName, isDep);
1664 printAssignmentEnd(node);
1665 checkEquationEnvEnd();
1666 _code << _elseEnd << _endline;
1670 inline bool isSameArgument(
const Arg& newArg,
1671 const Arg* oldArg) {
1672 if (oldArg !=
nullptr) {
1673 if (oldArg->getParameter() !=
nullptr) {
1674 if (newArg.getParameter() !=
nullptr) {
1675 return (*newArg.getParameter() == *oldArg->getParameter());
1678 return (newArg.getOperation() == oldArg->getOperation());
1684 virtual void printArrayCreationOp(
Node& op);
1686 virtual void printSparseArrayCreationOp(
Node& op);
1688 inline void printArrayStructInit(
const std::string& dataArrayName,
1690 const std::vector<Node*>& arrays,
1693 inline void printArrayStructInit(
const std::string& dataArrayName,
1696 inline void markArrayChanged(
Node& ty);
1701 std::vector<const Arg*>& tmpArrayValues);
1703 inline std::string getTempArrayName(
const Node& op);
1705 virtual void printArrayElementOp(
Node& op);
1708 CPPADCG_ASSERT_KNOWN(atomicFor.
getInfo().size() == 3,
"Invalid number of information elements for atomic forward operation");
1709 int q = atomicFor.
getInfo()[1];
1710 int p = atomicFor.
getInfo()[2];
1712 const std::vector<Arg>& opArgs = atomicFor.
getArguments();
1713 CPPADCG_ASSERT_KNOWN(opArgs.size() == p1 * 2,
"Invalid number of arguments for atomic forward operation");
1715 size_t id = atomicFor.
getInfo()[0];
1716 std::vector<Node*> tx(p1), ty(p1);
1717 for (
size_t k = 0; k < p1; k++) {
1718 tx[k] = opArgs[0 * p1 + k].getOperation();
1719 ty[k] = opArgs[1 * p1 + k].getOperation();
1722 CPPADCG_ASSERT_KNOWN(tx[0]->getOperationType() == CGOpCode::ArrayCreation,
"Invalid array type");
1723 CPPADCG_ASSERT_KNOWN(p == 0 || tx[1]->getOperationType() == CGOpCode::SparseArrayCreation,
"Invalid array type");
1724 CPPADCG_ASSERT_KNOWN(ty[p]->getOperationType() == CGOpCode::ArrayCreation,
"Invalid array type");
1727 for (
size_t k = 0; k < p1; k++) {
1728 printArrayStructInit(_ATOMIC_TX, k, tx, k);
1731 printArrayStructInit(_ATOMIC_TY, *ty[p]);
1734 _code << _startAlgLine << _startEq
1736 << q <<
", " << p <<
", " 1737 << _ATOMIC_TX <<
", &" << _ATOMIC_TY <<
")" 1738 << _endEq << _endAlgLine << _endline;
1743 markArrayChanged(*ty[p]);
1747 CPPADCG_ASSERT_KNOWN(atomicRev.
getInfo().size() == 2,
"Invalid number of information elements for atomic reverse operation");
1748 int p = atomicRev.
getInfo()[1];
1750 const std::vector<Arg>& opArgs = atomicRev.
getArguments();
1751 CPPADCG_ASSERT_KNOWN(opArgs.size() == p1 * 4,
"Invalid number of arguments for atomic reverse operation");
1753 size_t id = atomicRev.
getInfo()[0];
1754 std::vector<Node*> tx(p1), px(p1), py(p1);
1755 for (
size_t k = 0; k < p1; k++) {
1756 tx[k] = opArgs[0 * p1 + k].getOperation();
1757 px[k] = opArgs[2 * p1 + k].getOperation();
1758 py[k] = opArgs[3 * p1 + k].getOperation();
1761 CPPADCG_ASSERT_KNOWN(tx[0]->getOperationType() == CGOpCode::ArrayCreation,
"Invalid array type");
1762 CPPADCG_ASSERT_KNOWN(p == 0 || tx[1]->getOperationType() == CGOpCode::SparseArrayCreation,
"Invalid array type");
1764 CPPADCG_ASSERT_KNOWN(px[0]->getOperationType() == CGOpCode::ArrayCreation,
"Invalid array type");
1766 CPPADCG_ASSERT_KNOWN(py[0]->getOperationType() == CGOpCode::SparseArrayCreation,
"Invalid array type");
1767 CPPADCG_ASSERT_KNOWN(p == 0 || py[1]->getOperationType() == CGOpCode::ArrayCreation,
"Invalid array type");
1770 for (
size_t k = 0; k < p1; k++) {
1771 printArrayStructInit(_ATOMIC_TX, k, tx, k);
1774 for (
size_t k = 0; k < p1; k++) {
1775 printArrayStructInit(_ATOMIC_PY, k, py, k);
1778 printArrayStructInit(_ATOMIC_PX, *px[0]);
1781 _code << _startAlgLine << _startEq
1784 << _ATOMIC_TX <<
", &" << _ATOMIC_PX <<
", " << _ATOMIC_PY <<
")" 1785 << _endEq << _endAlgLine << _endline;
1790 markArrayChanged(*px[0]);
1793 virtual unsigned printDependentMultiAssign(
Node& node) {
1794 CPPADCG_ASSERT_KNOWN(node.
getOperationType() == CGOpCode::DependentMultiAssign,
"Invalid node type");
1795 CPPADCG_ASSERT_KNOWN(node.
getArguments().size() > 0,
"Invalid number of arguments");
1798 for (
size_t a = 0; a < args.size(); a++) {
1799 bool useArg =
false;
1800 const Arg& arg = args[a];
1801 if (arg.getParameter() !=
nullptr) {
1804 CGOpCode op = arg.getOperation()->getOperationType();
1805 useArg = op != CGOpCode::DependentRefRhs && op != CGOpCode::LoopEnd && op != CGOpCode::EndIf;
1809 printAssignment(node, arg);
1816 virtual void printLoopStart(
Node& node) {
1817 CPPADCG_ASSERT_KNOWN(node.
getOperationType() == CGOpCode::LoopStart,
"Invalid node type");
1820 _currentLoops.push_back(&lnode);
1822 const std::string& jj = *lnode.getIndex().getName();
1824 if (lnode.getIterationCountNode() !=
nullptr) {
1825 lastIt = *lnode.getIterationCountNode()->getIndex().getName() +
" - 1";
1827 lastIt = std::to_string(lnode.getIterationCount() - 1);
1830 checkEquationEnvEnd();
1832 _code << _forStart <<
"{$" << jj <<
"\\in \\left[0, " << lastIt <<
"\\right]$}" << _endline;
1833 _indentationLevel++;
1836 virtual void printLoopEnd(
Node& node) {
1837 CPPADCG_ASSERT_KNOWN(node.
getOperationType() == CGOpCode::LoopEnd,
"Invalid node type");
1839 checkEquationEnvEnd();
1841 _indentationLevel--;
1843 _code << _forEnd << _endline;
1845 _currentLoops.pop_back();
1848 virtual void printLoopIndexedDep(
Node& node) {
1849 CPPADCG_ASSERT_KNOWN(node.
getArguments().size() >= 1,
"Invalid number of arguments for loop indexed dependent operation");
1855 virtual void printLoopIndexedIndep(
Node& node) {
1856 CPPADCG_ASSERT_KNOWN(node.
getOperationType() == CGOpCode::LoopIndexedIndep,
"Invalid node type");
1857 CPPADCG_ASSERT_KNOWN(node.
getInfo().size() == 1,
"Invalid number of information elements for loop indexed independent operation");
1860 size_t pos = node.
getInfo()[1];
1861 const IndexPattern* ip = _info->loopIndependentIndexPatterns[pos];
1865 virtual void printLoopIndexedTmp(
Node& node) {
1866 CPPADCG_ASSERT_KNOWN(node.
getOperationType() == CGOpCode::LoopIndexedTmp,
"Invalid node type");
1867 CPPADCG_ASSERT_KNOWN(node.
getArguments().size() == 2,
"Invalid number of arguments for loop indexed temporary operation");
1869 CPPADCG_ASSERT_KNOWN(tmpVar !=
nullptr && tmpVar->getOperationType() == CGOpCode::TmpDcl,
"Invalid arguments for loop indexed temporary operation");
1874 virtual void printTmpVar(
Node& node) {
1875 CPPADCG_ASSERT_KNOWN(node.
getOperationType() == CGOpCode::Tmp,
"Invalid node type");
1876 CPPADCG_ASSERT_KNOWN(node.
getArguments().size() > 0,
"Invalid number of arguments for temporary variable usage operation");
1878 CPPADCG_ASSERT_KNOWN(tmpVar !=
nullptr && tmpVar->getOperationType() == CGOpCode::TmpDcl,
"Invalid arguments for loop indexed temporary operation");
1880 _code << _startVar << *tmpVar->getName() << _endVar;
1883 virtual void printIndexAssign(
Node& node) {
1884 CPPADCG_ASSERT_KNOWN(node.
getOperationType() == CGOpCode::IndexAssign,
"Invalid node type");
1885 CPPADCG_ASSERT_KNOWN(node.
getArguments().size() > 0,
"Invalid number of arguments for an index assignment operation");
1889 checkEquationEnvStart();
1892 _code << _startAlgLine << _startEq
1893 << (*inode.getIndex().getName())
1894 << _assignStr << indexPattern2String(ip, inode.getIndexPatternIndexes())
1895 << _endEq << _endAlgLine << _endline;
1898 virtual void printIndexCondExprOp(
Node& node) {
1899 CPPADCG_ASSERT_KNOWN(node.
getOperationType() == CGOpCode::IndexCondExpr,
"Invalid node type");
1900 CPPADCG_ASSERT_KNOWN(node.
getArguments().size() == 1,
"Invalid number of arguments for an index condition expression operation");
1901 CPPADCG_ASSERT_KNOWN(node.
getArguments()[0].getOperation() !=
nullptr,
"Invalid argument for an index condition expression operation");
1902 CPPADCG_ASSERT_KNOWN(node.
getArguments()[0].getOperation()->getOperationType() == CGOpCode::Index,
"Invalid argument for an index condition expression operation");
1904 const std::vector<size_t>& info = node.
getInfo();
1907 const std::string& index = *iterationIndexOp.getIndex().getName();
1909 checkEquationEnvStart();
1911 printIndexCondExpr(_code, info, index);
1919 CPPADCG_ASSERT_KNOWN(node.
getOperationType() == CGOpCode::StartIf,
"Invalid node type");
1920 CPPADCG_ASSERT_KNOWN(node.
getArguments().size() >= 1,
"Invalid number of arguments for an 'if start' operation");
1921 CPPADCG_ASSERT_KNOWN(node.
getArguments()[0].getOperation() !=
nullptr,
"Invalid argument for an 'if start' operation");
1923 checkEquationEnvEnd();
1927 _code << _conditionStart;
1928 printIndexCondExprOp(*node.
getArguments()[0].getOperation());
1929 checkEquationEnvEnd();
1930 _code << _conditionEnd;
1933 _indentationLevel++;
1942 CPPADCG_ASSERT_KNOWN(node.
getOperationType() == CGOpCode::ElseIf,
"Invalid node type");
1943 CPPADCG_ASSERT_KNOWN(node.
getArguments().size() >= 2,
"Invalid number of arguments for an 'else if' operation");
1944 CPPADCG_ASSERT_KNOWN(node.
getArguments()[0].getOperation() !=
nullptr,
"Invalid argument for an 'else if' operation");
1945 CPPADCG_ASSERT_KNOWN(node.
getArguments()[1].getOperation() !=
nullptr,
"Invalid argument for an 'else if' operation");
1947 checkEquationEnvEnd();
1948 _indentationLevel--;
1951 CGOpCode nType = node.
getArguments()[0].getOperation()->getOperationType();
1952 if (nType == CGOpCode::StartIf) {
1953 _code << _ifEnd << _endline;
1954 }
else if (nType == CGOpCode::ElseIf) {
1955 _code << _elseIfEnd << _endline;
1959 _code << _elseIfStart;
1960 _code << _conditionStart;
1962 printIndexCondExprOp(*node.
getArguments()[1].getOperation());
1963 checkEquationEnvEnd();
1964 _code << _conditionEnd;
1967 _indentationLevel++;
1975 CPPADCG_ASSERT_KNOWN(node.
getOperationType() == CGOpCode::Else,
"Invalid node type");
1976 CPPADCG_ASSERT_KNOWN(node.
getArguments().size() >= 1,
"Invalid number of arguments for an 'else' operation");
1978 checkEquationEnvEnd();
1979 _indentationLevel--;
1982 CGOpCode nType = node.
getArguments()[0].getOperation()->getOperationType();
1983 if (nType == CGOpCode::StartIf) {
1984 _code << _ifEnd << _endline;
1985 }
else if (nType == CGOpCode::ElseIf) {
1986 _code << _elseIfEnd << _endline;
1990 _code << _elseStart << _endline;
1992 _indentationLevel++;
1995 virtual void printEndIf(
Node& node) {
1996 CPPADCG_ASSERT_KNOWN(node.
getOperationType() == CGOpCode::EndIf,
"Invalid node type for an 'end if' operation");
1998 _indentationLevel--;
2001 CGOpCode nType = node.
getArguments()[0].getOperation()->getOperationType();
2002 if (nType == CGOpCode::StartIf) {
2003 _code << _ifEnd << _endline;
2004 }
else if (nType == CGOpCode::ElseIf) {
2005 _code << _elseIfEnd << _endline;
2007 assert(nType == CGOpCode::Else);
2008 _code << _elseEnd << _endline;
2012 virtual void printCondResult(
Node& node) {
2013 CPPADCG_ASSERT_KNOWN(node.
getOperationType() == CGOpCode::CondResult,
"Invalid node type");
2014 CPPADCG_ASSERT_KNOWN(node.
getArguments().size() == 2,
"Invalid number of arguments for an assignment inside an if/else operation");
2015 CPPADCG_ASSERT_KNOWN(node.
getArguments()[0].getOperation() !=
nullptr,
"Invalid argument for an an assignment inside an if/else operation");
2016 CPPADCG_ASSERT_KNOWN(node.
getArguments()[1].getOperation() !=
nullptr,
"Invalid argument for an an assignment inside an if/else operation");
2020 printAssignment(nodeArg);
2023 virtual void printUserCustom(
Node& node) {
2024 CPPADCG_ASSERT_KNOWN(node.
getOperationType() == CGOpCode::UserCustom,
"Invalid node type");
2026 throw CGException(
"Unable to generate Latex for user custom operation nodes.");
2029 inline bool isDependent(
const Node& arg)
const {
2033 size_t id = getVariableID(arg);
2034 return id > _independentSize &&
id < _minTemporaryVarID;
2037 virtual void printParameter(
const Base& value) {
2039 std::ostringstream os;
2040 os << std::setprecision(_parameterPrecision) << value;
2042 std::string number = os.str();
2043 size_t pos = number.find(
'e');
2044 if (pos != std::string::npos) {
2045 std::string n =
" \\times 10^{";
2046 number.replace(pos, 1, n);
2048 if (number[pos] ==
'-' || number[pos] ==
'+')
2050 while (number[pos] ==
'0')
2051 number.replace(pos, 1,
"");
2059 virtual const std::string& getComparison(
enum CGOpCode op)
const {
2061 case CGOpCode::ComLt:
2064 case CGOpCode::ComLe:
2067 case CGOpCode::ComEq:
2070 case CGOpCode::ComGe:
2073 case CGOpCode::ComGt:
2076 case CGOpCode::ComNe:
2080 CPPAD_ASSERT_UNKNOWN(0);
2082 throw CGException(
"Invalid comparison operator code");
2085 inline const std::string& getPrintfBaseFormat() {
2086 static const std::string format;
2090 static bool isFunction(
enum CGOpCode op) {
2091 return isUnaryFunction(op) || op == CGOpCode::Pow;
2094 static bool isUnaryFunction(
enum CGOpCode op) {
2097 case CGOpCode::Acos:
2098 case CGOpCode::Asin:
2099 case CGOpCode::Atan:
2100 case CGOpCode::Cosh:
2104 case CGOpCode::Sign:
2105 case CGOpCode::Sinh:
2107 case CGOpCode::Sqrt:
2108 case CGOpCode::Tanh:
2116 static bool isCondAssign(
enum CGOpCode op) {
2118 case CGOpCode::ComLt:
2119 case CGOpCode::ComLe:
2120 case CGOpCode::ComEq:
2121 case CGOpCode::ComGe:
2122 case CGOpCode::ComGt:
2123 case CGOpCode::ComNe:
2131 template<
class Base>
2133 template<
class Base>
2135 template<
class Base>
2137 template<
class Base>
2139 template<
class Base>
2141 template<
class Base>
2144 template<
class Base>
2147 template<
class Base>
2150 template<
class Base>
2153 template<
class Base>
2156 template<
class Base>
2159 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) 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)
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)
void generateSourceCode(std::ostream &out, const std::unique_ptr< LanguageGenerationData< Base > > &info) override
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)