From ee1e56180ec2b5961195e40f76d1609eb3a42f94 Mon Sep 17 00:00:00 2001 From: Alan Garny Date: Tue, 22 Oct 2024 13:42:27 +1300 Subject: [PATCH 01/10] Some minor cleaning up. --- src/analyser.cpp | 8 +++++--- src/analyserexternalvariable.cpp | 1 - src/analyservariable.cpp | 1 - src/analyservariable_p.h | 1 - src/annotator.cpp | 1 - src/api/libcellml/generator.h | 5 ++--- src/component.cpp | 1 - src/debug.cpp | 1 - src/generator.cpp | 8 +++----- src/importer.cpp | 1 - src/model.cpp | 1 - src/printer.cpp | 1 - src/units.cpp | 1 - src/utilities.cpp | 1 - src/utilities.h | 1 + src/validator.cpp | 1 - 16 files changed, 11 insertions(+), 23 deletions(-) diff --git a/src/analyser.cpp b/src/analyser.cpp index 7fd91c6667..c3a68d105c 100644 --- a/src/analyser.cpp +++ b/src/analyser.cpp @@ -376,6 +376,8 @@ Analyser::AnalyserImpl::AnalyserImpl() mGeneratorProfile->setAbsoluteValueString("abs"); mGeneratorProfile->setNaturalLogarithmString("ln"); mGeneratorProfile->setCommonLogarithmString("log"); + mGeneratorProfile->setMinString("min"); + mGeneratorProfile->setMaxString("max"); mGeneratorProfile->setRemString("rem"); mGeneratorProfile->setAsinString("arcsin"); mGeneratorProfile->setAcosString("arccos"); @@ -2440,9 +2442,9 @@ void Analyser::AnalyserImpl::analyseModel(const ModelPtr &model) + "' is"; description += hasPrimaryVariable ? " the" : - (equivalentVariableCount == 1) ? - " its corresponding" : - " their corresponding"; + ((equivalentVariableCount == 1) ? + " its corresponding" : + " their corresponding"); description += " primary variable and will therefore be the one used as an external variable."; referenceRule = Issue::ReferenceRule::ANALYSER_EXTERNAL_VARIABLE_USE_PRIMARY_VARIABLE; diff --git a/src/analyserexternalvariable.cpp b/src/analyserexternalvariable.cpp index 41a9606ff9..b1910f8843 100644 --- a/src/analyserexternalvariable.cpp +++ b/src/analyserexternalvariable.cpp @@ -17,7 +17,6 @@ limitations under the License. #include "libcellml/analyserexternalvariable.h" #include "analyserexternalvariable_p.h" -#include "commonutils.h" #include "utilities.h" namespace libcellml { diff --git a/src/analyservariable.cpp b/src/analyservariable.cpp index 3c03d84734..bcda865b32 100644 --- a/src/analyservariable.cpp +++ b/src/analyservariable.cpp @@ -40,7 +40,6 @@ void AnalyserVariable::AnalyserVariableImpl::populate(AnalyserVariable::Type typ mIndex = index; mInitialisingVariable = initialisingVariable; mVariable = variable; - mComponent = owningComponent(mVariable); std::copy(equations.begin(), equations.end(), back_inserter(mEquations)); } diff --git a/src/analyservariable_p.h b/src/analyservariable_p.h index 98f0462a94..71a146da4c 100644 --- a/src/analyservariable_p.h +++ b/src/analyservariable_p.h @@ -33,7 +33,6 @@ struct AnalyserVariable::AnalyserVariableImpl size_t mIndex = 0; VariablePtr mInitialisingVariable; VariablePtr mVariable; - ComponentPtr mComponent; std::vector mEquations; static AnalyserVariablePtr create(); diff --git a/src/annotator.cpp b/src/annotator.cpp index 715997d9af..85d401b09c 100644 --- a/src/annotator.cpp +++ b/src/annotator.cpp @@ -29,7 +29,6 @@ limitations under the License. #include "libcellml/variable.h" #include "anycellmlelement_p.h" -#include "commonutils.h" #include "internaltypes.h" #include "issue_p.h" #include "logger_p.h" diff --git a/src/api/libcellml/generator.h b/src/api/libcellml/generator.h index 85d5b71eb1..4bebebfd6d 100644 --- a/src/api/libcellml/generator.h +++ b/src/api/libcellml/generator.h @@ -111,13 +111,12 @@ class LIBCELLML_EXPORT Generator * Return the equation code for the given @ref AnalyserEquationAst using @ref GeneratorProfile. * * @param ast The @ref AnalyserEquationAst for which we want to generate some code. - * @param generatorProfile The @ref GeneratorProfile, if any, to use to generate the equation code. If no + * @param profile The @ref GeneratorProfile, if any, to use to generate the equation code. If no * @ref GeneratorProfile is provided then the default @ref GeneratorProfile is used. * * @return The equation code as a @c std::string. */ - static std::string equationCode(const AnalyserEquationAstPtr &ast, - const GeneratorProfilePtr &generatorProfile); + static std::string equationCode(const AnalyserEquationAstPtr &ast, const GeneratorProfilePtr &profile); /** * @brief Get the equation code for the given @ref AnalyserEquationAst using a default @ref GeneratorProfile. diff --git a/src/component.cpp b/src/component.cpp index 207d731e6a..43be7989b9 100644 --- a/src/component.cpp +++ b/src/component.cpp @@ -27,7 +27,6 @@ limitations under the License. #include "libcellml/reset.h" #include "libcellml/variable.h" -#include "commonutils.h" #include "component_p.h" #include "reset_p.h" #include "utilities.h" diff --git a/src/debug.cpp b/src/debug.cpp index a41ed57b4e..e999003345 100644 --- a/src/debug.cpp +++ b/src/debug.cpp @@ -26,7 +26,6 @@ limitations under the License. #include "libcellml/model.h" #include "libcellml/variable.h" -#include "commonutils.h" #include "utilities.h" namespace libcellml { diff --git a/src/generator.cpp b/src/generator.cpp index c8ce8d87c3..8b99a40204 100644 --- a/src/generator.cpp +++ b/src/generator.cpp @@ -27,7 +27,6 @@ limitations under the License. #include "libcellml/units.h" #include "libcellml/version.h" -#include "commonutils.h" #include "generator_p.h" #include "generatorprofilesha1values.h" #include "generatorprofiletools.h" @@ -2152,13 +2151,12 @@ std::string Generator::implementationCode() const return mPimpl->mCode; } -std::string Generator::equationCode(const AnalyserEquationAstPtr &ast, - const GeneratorProfilePtr &generatorProfile) +std::string Generator::equationCode(const AnalyserEquationAstPtr &ast, const GeneratorProfilePtr &profile) { GeneratorPtr generator = libcellml::Generator::create(); - if (generatorProfile != nullptr) { - generator->setProfile(generatorProfile); + if (profile != nullptr) { + generator->setProfile(profile); } return generator->mPimpl->generateCode(ast); diff --git a/src/importer.cpp b/src/importer.cpp index 7e74657fa5..01092d3adc 100644 --- a/src/importer.cpp +++ b/src/importer.cpp @@ -32,7 +32,6 @@ limitations under the License. #include "libcellml/variable.h" #include "anycellmlelement_p.h" -#include "commonutils.h" #include "issue_p.h" #include "logger_p.h" #include "utilities.h" diff --git a/src/model.cpp b/src/model.cpp index 7f89305ded..a429333d03 100644 --- a/src/model.cpp +++ b/src/model.cpp @@ -30,7 +30,6 @@ limitations under the License. #include "libcellml/units.h" #include "libcellml/variable.h" -#include "commonutils.h" #include "component_p.h" #include "componententity_p.h" #include "internaltypes.h" diff --git a/src/printer.cpp b/src/printer.cpp index db5ca8727c..b4b1dfa4db 100644 --- a/src/printer.cpp +++ b/src/printer.cpp @@ -33,7 +33,6 @@ limitations under the License. #include "libcellml/variable.h" #include "anycellmlelement_p.h" -#include "commonutils.h" #include "internaltypes.h" #include "issue_p.h" #include "logger_p.h" diff --git a/src/units.cpp b/src/units.cpp index 87800cdd88..398c74486c 100644 --- a/src/units.cpp +++ b/src/units.cpp @@ -30,7 +30,6 @@ limitations under the License. #include #include -#include "commonutils.h" #include "units_p.h" #include "utilities.h" diff --git a/src/utilities.cpp b/src/utilities.cpp index 996fc653f3..4fdc46fe4d 100644 --- a/src/utilities.cpp +++ b/src/utilities.cpp @@ -36,7 +36,6 @@ limitations under the License. #include "libcellml/units.h" #include "libcellml/variable.h" -#include "commonutils.h" #include "xmldoc.h" #include "xmlutils.h" diff --git a/src/utilities.h b/src/utilities.h index 87beda8aff..df5083fb6c 100644 --- a/src/utilities.h +++ b/src/utilities.h @@ -26,6 +26,7 @@ limitations under the License. #include "libcellml/types.h" #include "libcellml/variable.h" +#include "commonutils.h" #include "internaltypes.h" #include "xmldoc.h" diff --git a/src/validator.cpp b/src/validator.cpp index 10cf488738..19a0d80712 100644 --- a/src/validator.cpp +++ b/src/validator.cpp @@ -33,7 +33,6 @@ limitations under the License. #include "libcellml/variable.h" #include "anycellmlelement_p.h" -#include "commonutils.h" #include "issue_p.h" #include "logger_p.h" #include "namespaces.h" From 7c13a040d9a8018e0b5f5ed7fa309c894efd05e7 Mon Sep 17 00:00:00 2001 From: Alan Garny Date: Tue, 22 Oct 2024 14:45:45 +1300 Subject: [PATCH 02/10] Moved areNearlyEqual() from utilties to commonutils. --- src/commonutils.cpp | 51 +++++++++++++++++++++++++++++++++++++++++++++ src/commonutils.h | 17 +++++++++++++++ src/utilities.cpp | 48 ------------------------------------------ src/utilities.h | 17 --------------- 4 files changed, 68 insertions(+), 65 deletions(-) diff --git a/src/commonutils.cpp b/src/commonutils.cpp index 412691ff77..e5581e9915 100644 --- a/src/commonutils.cpp +++ b/src/commonutils.cpp @@ -16,6 +16,9 @@ limitations under the License. #include "commonutils.h" +#include +#include + #include "libcellml/component.h" #include "libcellml/model.h" @@ -40,6 +43,54 @@ libcellml::ComponentPtr owningComponent(const libcellml::ParentedEntityConstPtr return std::dynamic_pointer_cast(entity->parent()); } +uint64_t ulpsDistance(double a, double b) +{ + static const auto max = std::numeric_limits::max(); + + // Max distance for NaN. + if (std::isnan(a) || std::isnan(b)) { + return max; + } + + // If one's infinite and they're not equal, max distance. + if (std::isinf(a) != std::isinf(b)) { + return max; + } + + static const int SIZE_OF_DOUBLE = sizeof(double); + + uint64_t ia; + uint64_t ib; + memcpy(&ia, &a, SIZE_OF_DOUBLE); + memcpy(&ib, &b, SIZE_OF_DOUBLE); + + // Return the absolute value of the distance in ULPs. + uint64_t distance = max; + if (ia < ib) { + distance = ib + ~ia + 1; + } else { + distance = ia + ~ib + 1; + } + return distance; +} + +bool areNearlyEqual(double a, double b) +{ + static const double fixedEpsilon = std::numeric_limits::epsilon(); + static const ptrdiff_t ulpsEpsilon = 1; + + if (fabs(a - b) <= fixedEpsilon) { + return true; + } + + // If they are not the same sign then return false. + if ((a < 0.0) != (b < 0.0)) { + return false; + } + + return ulpsDistance(a, b) <= ulpsEpsilon; +} + #ifndef TEST_UTILS } // namespace libcellml #endif diff --git a/src/commonutils.h b/src/commonutils.h index dc5ad20c00..66fff07a08 100644 --- a/src/commonutils.h +++ b/src/commonutils.h @@ -45,6 +45,23 @@ libcellml::ModelPtr TEST_EXPORT owningModel(const libcellml::ParentedEntityConst */ libcellml::ComponentPtr TEST_EXPORT owningComponent(const libcellml::ParentedEntityConstPtr &entity); +/** + * @brief Decide if two doubles are nearly equal. + * + * Test two doubles to determine if they are close enough + * to be considered equal. + * + * Uses a modified form of comparing floats: + * + * https://bitbashing.io/comparing-floats.html + * + * @param a A @c double to test. + * @param b A @c double to test. + * + * @return @c true if the given doubles are considered close, @c false otherwise. + */ +bool TEST_EXPORT areNearlyEqual(double a, double b); + #ifndef TEST_UTILS } // namespace libcellml diff --git a/src/utilities.cpp b/src/utilities.cpp index 4fdc46fe4d..7e5fc772e5 100644 --- a/src/utilities.cpp +++ b/src/utilities.cpp @@ -268,54 +268,6 @@ bool areEqual(double a, double b) return convertToString(a + 0.0) == convertToString(b + 0.0); } -uint64_t ulpsDistance(double a, double b) -{ - static const auto max = std::numeric_limits::max(); - - // Max distance for NaN. - if (std::isnan(a) || std::isnan(b)) { - return max; - } - - // If one's infinite and they're not equal, max distance. - if (std::isinf(a) != std::isinf(b)) { - return max; - } - - static const int SIZE_OF_DOUBLE = sizeof(double); - - uint64_t ia; - uint64_t ib; - memcpy(&ia, &a, SIZE_OF_DOUBLE); - memcpy(&ib, &b, SIZE_OF_DOUBLE); - - // Return the absolute value of the distance in ULPs. - uint64_t distance = max; - if (ia < ib) { - distance = ib + ~ia + 1; - } else { - distance = ia + ~ib + 1; - } - return distance; -} - -bool areNearlyEqual(double a, double b) -{ - static const double fixedEpsilon = std::numeric_limits::epsilon(); - static const ptrdiff_t ulpsEpsilon = 1; - - if (fabs(a - b) <= fixedEpsilon) { - return true; - } - - // If they are not the same sign then return false. - if ((a < 0.0) != (b < 0.0)) { - return false; - } - - return ulpsDistance(a, b) <= ulpsEpsilon; -} - std::vector getImportedComponents(const ComponentEntityConstPtr &componentEntity) { std::vector importedComponents; diff --git a/src/utilities.h b/src/utilities.h index df5083fb6c..00d06ccd62 100644 --- a/src/utilities.h +++ b/src/utilities.h @@ -333,23 +333,6 @@ bool isCellMLReal(const std::string &candidate); */ bool areEqual(double a, double b); -/** - * @brief Decide if two doubles are nearly equal. - * - * Test two doubles to determine if they are close enough - * to be considered equal. - * - * Uses a modified form of comparing floats: - * - * https://bitbashing.io/comparing-floats.html - * - * @param a A @c double to test. - * @param b A @c double to test. - * - * @return @c true if the given doubles are considered close, @c false otherwise. - */ -bool areNearlyEqual(double a, double b); - /** * @brief Compare strings to determine if they are equal. * From c029d7e5539d8e63e84e2d6e8a90c1aeae848543 Mon Sep 17 00:00:00 2001 From: Alan Garny Date: Tue, 22 Oct 2024 14:41:34 +1300 Subject: [PATCH 03/10] Analyser: account for the case where a piecewise statement doesn't have any children. --- src/analyser.cpp | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/src/analyser.cpp b/src/analyser.cpp index c3a68d105c..1ebf42d134 100644 --- a/src/analyser.cpp +++ b/src/analyser.cpp @@ -688,30 +688,32 @@ void Analyser::AnalyserImpl::analyseNode(const XmlNodePtr &node, ast->mPimpl->populate(AnalyserEquationAst::Type::PIECEWISE, astParent); - analyseNode(mathmlChildNode(node, 0), ast->mPimpl->mOwnedLeftChild, ast, component, equation); + if (childCount >= 1) { + analyseNode(mathmlChildNode(node, 0), ast->mPimpl->mOwnedLeftChild, ast, component, equation); - if (childCount >= 2) { - AnalyserEquationAstPtr astRight; - AnalyserEquationAstPtr tempAst; + if (childCount >= 2) { + AnalyserEquationAstPtr astRight; + AnalyserEquationAstPtr tempAst; - analyseNode(mathmlChildNode(node, childCount - 1), astRight, nullptr, component, equation); + analyseNode(mathmlChildNode(node, childCount - 1), astRight, nullptr, component, equation); - for (auto i = childCount - 2; i > 0; --i) { - tempAst = AnalyserEquationAst::create(); + for (auto i = childCount - 2; i > 0; --i) { + tempAst = AnalyserEquationAst::create(); - tempAst->mPimpl->populate(AnalyserEquationAst::Type::PIECEWISE, astParent); + tempAst->mPimpl->populate(AnalyserEquationAst::Type::PIECEWISE, astParent); - analyseNode(mathmlChildNode(node, i), tempAst->mPimpl->mOwnedLeftChild, tempAst, component, equation); + analyseNode(mathmlChildNode(node, i), tempAst->mPimpl->mOwnedLeftChild, tempAst, component, equation); - astRight->mPimpl->mParent = tempAst; + astRight->mPimpl->mParent = tempAst; - tempAst->mPimpl->mOwnedRightChild = astRight; - astRight = tempAst; - } + tempAst->mPimpl->mOwnedRightChild = astRight; + astRight = tempAst; + } - astRight->mPimpl->mParent = ast; + astRight->mPimpl->mParent = ast; - ast->mPimpl->mOwnedRightChild = astRight; + ast->mPimpl->mOwnedRightChild = astRight; + } } } else if (node->isMathmlElement("piece")) { ast->mPimpl->populate(AnalyserEquationAst::Type::PIECE, astParent); From 6b4889f3c61d9077876eb8ee56154e2eb007fb3d Mon Sep 17 00:00:00 2001 From: Alan Garny Date: Tue, 22 Oct 2024 15:44:27 +1300 Subject: [PATCH 04/10] Debug: improved printAstAsTree(). --- src/debug.cpp | 60 +++++++++++++++++++++++++++++++++-------------- src/debug.h | 2 +- src/generator.cpp | 24 +++++++++---------- src/generator_p.h | 4 ++-- 4 files changed, 58 insertions(+), 32 deletions(-) diff --git a/src/debug.cpp b/src/debug.cpp index e999003345..2c9dbcd8ac 100644 --- a/src/debug.cpp +++ b/src/debug.cpp @@ -26,6 +26,7 @@ limitations under the License. #include "libcellml/model.h" #include "libcellml/variable.h" +#include "generator_p.h" #include "utilities.h" namespace libcellml { @@ -76,7 +77,8 @@ void printAnalyserModelEquations(const AnalyserModelPtr &model) Debug() << "\n---------------------------------------[API equation #" << ++eqnNb << "]"; if (eqn->ast() != nullptr) { - Debug() << "\n" << astAsCode(eqn->ast()); + Debug() << "\n" + << astAsCode(eqn->ast()); } else { Debug() << "\nNo equation"; } @@ -336,7 +338,29 @@ std::string doPrintAstAsTree(AnalyserEquationAstTrunk *trunk) return res + trunk->mStr; } -std::string doPrintAstAsTree(const AnalyserEquationAstPtr &ast) +std::string ciValue(const AnalyserVariablePtr &analyserVariable, bool rate) +{ + std::string res = (analyserVariable->type() == AnalyserVariable::Type::STATE) ? + (rate ? + "rates" : + "states") : + ((analyserVariable->type() == AnalyserVariable::Type::CONSTANT) ? + "constants" : + ((analyserVariable->type() == AnalyserVariable::Type::COMPUTED_CONSTANT) ? + "computedConstants" : + ((analyserVariable->type() == AnalyserVariable::Type::ALGEBRAIC) ? + "algebraic" : + "externals"))); + auto variable = analyserVariable->variable(); + + res += "[" + std::to_string(analyserVariable->index()) + "] | " + + owningComponent(variable)->name() + " | " + + variable->name() + std::string(rate ? "'" : ""); + + return res; +} + +std::string doPrintAstAsTree(const AnalyserModelPtr &model, const AnalyserEquationAstPtr &ast) { std::string res; @@ -577,15 +601,11 @@ std::string doPrintAstAsTree(const AnalyserEquationAstPtr &ast) // Token elements. - case AnalyserEquationAst::Type::CI: { - auto astVariable = ast->variable(); - - if (astVariable != nullptr) { - res = astVariable->name(); - } + case AnalyserEquationAst::Type::CI: + res = ciValue(libcellml::analyserVariable(model, ast->variable()), + ast->parent()->type() == AnalyserEquationAst::Type::DIFF); break; - } case AnalyserEquationAst::Type::CN: res = ast->value(); @@ -637,7 +657,7 @@ std::string doPrintAstAsTree(const AnalyserEquationAstPtr &ast) return res; } -std::string doPrintAstAsTree(const AnalyserEquationAstPtr &ast, +std::string doPrintAstAsTree(const AnalyserModelPtr &model, const AnalyserEquationAstPtr &ast, AnalyserEquationAstTrunk *prevTrunk, bool isLeft) { if (ast == nullptr) { @@ -650,7 +670,7 @@ std::string doPrintAstAsTree(const AnalyserEquationAstPtr &ast, auto astLeftChild = ast->leftChild(); if (astLeftChild != nullptr) { - res += doPrintAstAsTree(astLeftChild, &trunk, true); + res += doPrintAstAsTree(model, astLeftChild, &trunk, true); } if (prevTrunk == nullptr) { @@ -663,7 +683,15 @@ std::string doPrintAstAsTree(const AnalyserEquationAstPtr &ast, prevTrunk->mStr = prevStr; } - res += doPrintAstAsTree(&trunk) + doPrintAstAsTree(ast) + "\n"; + auto astRightChild = ast->rightChild(); + + res += doPrintAstAsTree(&trunk); + + if (astLeftChild != nullptr) { + res += (astRightChild != nullptr) ? "┤" : "┘"; + } + + res += " " + doPrintAstAsTree(model, ast) + "\n"; if (prevTrunk != nullptr) { prevTrunk->mStr = prevStr; @@ -671,18 +699,16 @@ std::string doPrintAstAsTree(const AnalyserEquationAstPtr &ast, trunk.mStr = TRUNK; - auto astRightChild = ast->rightChild(); - if (astRightChild != nullptr) { - res += doPrintAstAsTree(astRightChild, &trunk, false); + res += doPrintAstAsTree(model, astRightChild, &trunk, false); } return res; } -void printAstAsTree(const AnalyserEquationAstPtr &ast) +void printAstAsTree(const AnalyserModelPtr &model, const AnalyserEquationAstPtr &ast) { - Debug() << doPrintAstAsTree(ast, nullptr, false); + Debug() << doPrintAstAsTree(model, ast, nullptr, false); } void printAstAsCode(const AnalyserEquationAstPtr &ast) diff --git a/src/debug.h b/src/debug.h index 0c6f861ad4..37a02618e3 100644 --- a/src/debug.h +++ b/src/debug.h @@ -95,7 +95,7 @@ struct Debug void printAnalyserModelEquations(const AnalyserModelPtr &model); void printAnalyserModelVariables(const AnalyserModelPtr &model); -void printAstAsTree(const AnalyserEquationAstPtr &ast); +void printAstAsTree(const AnalyserModelPtr &model, const AnalyserEquationAstPtr &ast); void printAstAsCode(const AnalyserEquationAstPtr &ast); void printComponentMap(const ComponentMap &map); void printConnectionMap(const ConnectionMap &map); diff --git a/src/generator.cpp b/src/generator.cpp index 8b99a40204..1a8b0a2c71 100644 --- a/src/generator.cpp +++ b/src/generator.cpp @@ -63,22 +63,22 @@ bool Generator::GeneratorImpl::modelHasNlas() const } } -AnalyserVariablePtr Generator::GeneratorImpl::analyserVariable(const VariablePtr &variable) const +AnalyserVariablePtr analyserVariable(const AnalyserModelPtr &model, const VariablePtr &variable) { // Find and return the analyser variable associated with the given variable. AnalyserVariablePtr res; - auto modelVoi = mModel->voi(); - VariablePtr modelVoiVariable = (modelVoi != nullptr) ? modelVoi->variable() : nullptr; + auto modelVoi = model->voi(); + auto modelVoiVariable = (modelVoi != nullptr) ? modelVoi->variable() : nullptr; if ((modelVoiVariable != nullptr) - && mModel->areEquivalentVariables(variable, modelVoiVariable)) { + && model->areEquivalentVariables(variable, modelVoiVariable)) { res = modelVoi; } else { // Normally, we would have something like: // - // for (const auto &modelVariable : variables(mModel)) { - // if (mModel->areEquivalentVariables(variable, modelVariable->variable())) { + // for (const auto &modelVariable : variables(model)) { + // if (model->areEquivalentVariables(variable, modelVariable->variable())) { // res = modelVariable; // // break; @@ -88,11 +88,11 @@ AnalyserVariablePtr Generator::GeneratorImpl::analyserVariable(const VariablePtr // but we always have variables, so llvm-cov will complain that the false branch of our for loop is never // reached. The below code is a bit more verbose but at least it makes llvm-cov happy. - auto modelVariables = variables(mModel); + auto modelVariables = variables(model); auto modelVariable = modelVariables.begin(); do { - if (mModel->areEquivalentVariables(variable, (*modelVariable)->variable())) { + if (model->areEquivalentVariables(variable, (*modelVariable)->variable())) { res = *modelVariable; } else { ++modelVariable; @@ -108,12 +108,12 @@ double Generator::GeneratorImpl::scalingFactor(const VariablePtr &variable) cons // Return the scaling factor for the given variable, accounting for the fact that a constant may be initialised by // another variable which initial value may be defined in a different component. - auto analyserVariable = Generator::GeneratorImpl::analyserVariable(variable); + auto analyserVariable = libcellml::analyserVariable(mModel, variable); if ((analyserVariable->type() == AnalyserVariable::Type::CONSTANT) && !isCellMLReal(variable->initialValue())) { auto initialValueVariable = owningComponent(variable)->variable(variable->initialValue()); - auto initialValueAnalyserVariable = Generator::GeneratorImpl::analyserVariable(initialValueVariable); + auto initialValueAnalyserVariable = libcellml::analyserVariable(mModel, initialValueVariable); if (owningComponent(variable) != owningComponent(initialValueAnalyserVariable->variable())) { return Units::scalingFactor(initialValueVariable->units(), variable->units()); @@ -889,7 +889,7 @@ std::string Generator::GeneratorImpl::generateDoubleOrConstantVariableNameCode(c } auto initialValueVariable = owningComponent(variable)->variable(variable->initialValue()); - auto analyserInitialValueVariable = analyserVariable(initialValueVariable); + auto analyserInitialValueVariable = analyserVariable(mModel, initialValueVariable); return mProfile->constantsArrayString() + mProfile->openArrayString() + convertToString(analyserInitialValueVariable->index()) + mProfile->closeArrayString(); } @@ -906,7 +906,7 @@ std::string Generator::GeneratorImpl::generateVariableNameCode(const VariablePtr return variable->name(); } - auto analyserVariable = Generator::GeneratorImpl::analyserVariable(variable); + auto analyserVariable = libcellml::analyserVariable(mModel, variable); if (analyserVariable->type() == AnalyserVariable::Type::VARIABLE_OF_INTEGRATION) { return mProfile->voiString(); diff --git a/src/generator_p.h b/src/generator_p.h index d85e8e2f44..fce8d2e7d7 100644 --- a/src/generator_p.h +++ b/src/generator_p.h @@ -26,6 +26,8 @@ namespace libcellml { std::string generateDoubleCode(const std::string &value); +AnalyserVariablePtr analyserVariable(const AnalyserModelPtr &model, const VariablePtr &variable); + /** * @brief The Generator::GeneratorImpl struct. * @@ -44,8 +46,6 @@ struct Generator::GeneratorImpl bool modelHasOdes() const; bool modelHasNlas() const; - AnalyserVariablePtr analyserVariable(const VariablePtr &variable) const; - double scalingFactor(const VariablePtr &variable) const; bool isNegativeNumber(const AnalyserEquationAstPtr &ast) const; From b61141d1eaf291dc42f8a20da4fb4acdcf70469d Mon Sep 17 00:00:00 2001 From: Alan Garny Date: Tue, 22 Oct 2024 16:19:58 +1300 Subject: [PATCH 05/10] Have our debug.* files formatted. --- CMakeLists.txt | 4 +++- src/CMakeLists.txt | 3 +++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 1dd1554065..1d5a5ed396 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -249,8 +249,10 @@ if(CLANG_FORMAT_AVAILABLE) ${SOURCE_FILES} ${HEADER_FILES} ${CONFIG_FILES} - ${TESTS_HEADER_FILES} + ${DEBUG_SOURCE_FILES} + ${DEBUG_HEADER_FILES} ${TESTS_SOURCE_FILES} + ${TESTS_HEADER_FILES} ) set(CHECK_CODE_FORMATTING_SCRIPT ${CMAKE_CURRENT_BINARY_DIR}/cmake_command_check_code_formatting.cmake) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 82d4676d18..17601cb516 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -379,3 +379,6 @@ set(CONFIG_FILES ${LIBCELLML_VERSIONCONFIG_H_IN} PARENT_SCOPE ) + +set(DEBUG_SOURCE_FILES ${DEBUG_SOURCE_FILES} PARENT_SCOPE) +set(DEBUG_HEADER_FILES ${DEBUG_HEADER_FILES} PARENT_SCOPE) From 8308d8e1ca8d7b349436849372abf607eded9e14 Mon Sep 17 00:00:00 2001 From: Alan Garny Date: Tue, 22 Oct 2024 16:14:54 +1300 Subject: [PATCH 06/10] Moved parts of our Generator class to our new GeneratorInterpreter class. --- src/CMakeLists.txt | 3 + src/analyser.cpp | 1 + src/debug.cpp | 2 +- src/generator.cpp | 1533 ++-------------------------------- src/generator_p.h | 70 +- src/generatorinterpreter.cpp | 1512 +++++++++++++++++++++++++++++++++ src/generatorinterpreter.h | 92 ++ src/generatorinterpreter_p.h | 108 +++ 8 files changed, 1789 insertions(+), 1532 deletions(-) create mode 100644 src/generatorinterpreter.cpp create mode 100644 src/generatorinterpreter.h create mode 100644 src/generatorinterpreter_p.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 17601cb516..ab771dfb08 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -49,6 +49,7 @@ set(SOURCE_FILES ${CMAKE_CURRENT_SOURCE_DIR}/entity.cpp ${CMAKE_CURRENT_SOURCE_DIR}/enums.cpp ${CMAKE_CURRENT_SOURCE_DIR}/generator.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/generatorinterpreter.cpp ${CMAKE_CURRENT_SOURCE_DIR}/generatorprofile.cpp ${CMAKE_CURRENT_SOURCE_DIR}/generatorprofiletools.cpp ${CMAKE_CURRENT_SOURCE_DIR}/importedentity.cpp @@ -133,6 +134,8 @@ set(GIT_HEADER_FILES ${CMAKE_CURRENT_SOURCE_DIR}/debug.h ${CMAKE_CURRENT_SOURCE_DIR}/entity_p.h ${CMAKE_CURRENT_SOURCE_DIR}/generator_p.h + ${CMAKE_CURRENT_SOURCE_DIR}/generatorinterpreter_p.h + ${CMAKE_CURRENT_SOURCE_DIR}/generatorinterpreter.h ${CMAKE_CURRENT_SOURCE_DIR}/generatorprofile_p.h ${CMAKE_CURRENT_SOURCE_DIR}/generatorprofilesha1values.h ${CMAKE_CURRENT_SOURCE_DIR}/generatorprofiletools.h diff --git a/src/analyser.cpp b/src/analyser.cpp index 1ebf42d134..0bb84b717e 100644 --- a/src/analyser.cpp +++ b/src/analyser.cpp @@ -34,6 +34,7 @@ limitations under the License. #include "analyservariable_p.h" #include "commonutils.h" #include "generator_p.h" +#include "generatorinterpreter_p.h" #include "xmlutils.h" namespace libcellml { diff --git a/src/debug.cpp b/src/debug.cpp index 2c9dbcd8ac..ff462fec15 100644 --- a/src/debug.cpp +++ b/src/debug.cpp @@ -26,7 +26,7 @@ limitations under the License. #include "libcellml/model.h" #include "libcellml/variable.h" -#include "generator_p.h" +#include "generatorinterpreter_p.h" #include "utilities.h" namespace libcellml { diff --git a/src/generator.cpp b/src/generator.cpp index 1a8b0a2c71..8ebe9c958f 100644 --- a/src/generator.cpp +++ b/src/generator.cpp @@ -28,6 +28,7 @@ limitations under the License. #include "libcellml/version.h" #include "generator_p.h" +#include "generatorinterpreter_p.h" #include "generatorprofilesha1values.h" #include "generatorprofiletools.h" #include "utilities.h" @@ -41,186 +42,6 @@ void Generator::GeneratorImpl::reset() mCode = {}; } -bool Generator::GeneratorImpl::modelHasOdes() const -{ - switch (mModel->type()) { - case AnalyserModel::Type::ODE: - case AnalyserModel::Type::DAE: - return true; - default: - return false; - } -} - -bool Generator::GeneratorImpl::modelHasNlas() const -{ - switch (mModel->type()) { - case AnalyserModel::Type::NLA: - case AnalyserModel::Type::DAE: - return true; - default: - return false; - } -} - -AnalyserVariablePtr analyserVariable(const AnalyserModelPtr &model, const VariablePtr &variable) -{ - // Find and return the analyser variable associated with the given variable. - - AnalyserVariablePtr res; - auto modelVoi = model->voi(); - auto modelVoiVariable = (modelVoi != nullptr) ? modelVoi->variable() : nullptr; - - if ((modelVoiVariable != nullptr) - && model->areEquivalentVariables(variable, modelVoiVariable)) { - res = modelVoi; - } else { - // Normally, we would have something like: - // - // for (const auto &modelVariable : variables(model)) { - // if (model->areEquivalentVariables(variable, modelVariable->variable())) { - // res = modelVariable; - // - // break; - // } - // } - // - // but we always have variables, so llvm-cov will complain that the false branch of our for loop is never - // reached. The below code is a bit more verbose but at least it makes llvm-cov happy. - - auto modelVariables = variables(model); - auto modelVariable = modelVariables.begin(); - - do { - if (model->areEquivalentVariables(variable, (*modelVariable)->variable())) { - res = *modelVariable; - } else { - ++modelVariable; - } - } while (res == nullptr); - } - - return res; -} - -double Generator::GeneratorImpl::scalingFactor(const VariablePtr &variable) const -{ - // Return the scaling factor for the given variable, accounting for the fact that a constant may be initialised by - // another variable which initial value may be defined in a different component. - - auto analyserVariable = libcellml::analyserVariable(mModel, variable); - - if ((analyserVariable->type() == AnalyserVariable::Type::CONSTANT) - && !isCellMLReal(variable->initialValue())) { - auto initialValueVariable = owningComponent(variable)->variable(variable->initialValue()); - auto initialValueAnalyserVariable = libcellml::analyserVariable(mModel, initialValueVariable); - - if (owningComponent(variable) != owningComponent(initialValueAnalyserVariable->variable())) { - return Units::scalingFactor(initialValueVariable->units(), variable->units()); - } - } - - return Units::scalingFactor(analyserVariable->variable()->units(), variable->units()); -} - -bool Generator::GeneratorImpl::isNegativeNumber(const AnalyserEquationAstPtr &ast) const -{ - if (ast->type() == AnalyserEquationAst::Type::CN) { - double doubleValue; - - convertToDouble(ast->value(), doubleValue); - - return doubleValue < 0.0; - } - - return false; -} - -bool Generator::GeneratorImpl::isRelationalOperator(const AnalyserEquationAstPtr &ast) const -{ - switch (ast->type()) { - case AnalyserEquationAst::Type::EQ: - return mProfile->hasEqOperator(); - case AnalyserEquationAst::Type::NEQ: - return mProfile->hasNeqOperator(); - case AnalyserEquationAst::Type::LT: - return mProfile->hasLtOperator(); - case AnalyserEquationAst::Type::LEQ: - return mProfile->hasLeqOperator(); - case AnalyserEquationAst::Type::GT: - return mProfile->hasGtOperator(); - case AnalyserEquationAst::Type::GEQ: - return mProfile->hasGeqOperator(); - default: - return false; - } -} - -bool Generator::GeneratorImpl::isAndOperator(const AnalyserEquationAstPtr &ast) const -{ - return (ast->type() == AnalyserEquationAst::Type::AND) - && mProfile->hasAndOperator(); -} - -bool Generator::GeneratorImpl::isOrOperator(const AnalyserEquationAstPtr &ast) const -{ - return (ast->type() == AnalyserEquationAst::Type::OR) - && mProfile->hasOrOperator(); -} - -bool Generator::GeneratorImpl::isXorOperator(const AnalyserEquationAstPtr &ast) const -{ - return (ast->type() == AnalyserEquationAst::Type::XOR) - && mProfile->hasXorOperator(); -} - -bool Generator::GeneratorImpl::isLogicalOperator(const AnalyserEquationAstPtr &ast) const -{ - // Note: AnalyserEquationAst::Type::NOT is a unary logical operator, hence - // we don't include it here since this method is only used to - // determine whether parentheses should be added around some code. - - return isAndOperator(ast) || isOrOperator(ast) || isXorOperator(ast); -} - -bool Generator::GeneratorImpl::isPlusOperator(const AnalyserEquationAstPtr &ast) const -{ - return ast->type() == AnalyserEquationAst::Type::PLUS; -} - -bool Generator::GeneratorImpl::isMinusOperator(const AnalyserEquationAstPtr &ast) const -{ - return ast->type() == AnalyserEquationAst::Type::MINUS; -} - -bool Generator::GeneratorImpl::isTimesOperator(const AnalyserEquationAstPtr &ast) const -{ - return ast->type() == AnalyserEquationAst::Type::TIMES; -} - -bool Generator::GeneratorImpl::isDivideOperator(const AnalyserEquationAstPtr &ast) const -{ - return ast->type() == AnalyserEquationAst::Type::DIVIDE; -} - -bool Generator::GeneratorImpl::isPowerOperator(const AnalyserEquationAstPtr &ast) const -{ - return (ast->type() == AnalyserEquationAst::Type::POWER) - && mProfile->hasPowerOperator(); -} - -bool Generator::GeneratorImpl::isRootOperator(const AnalyserEquationAstPtr &ast) const -{ - return (ast->type() == AnalyserEquationAst::Type::ROOT) - && mProfile->hasPowerOperator(); -} - -bool Generator::GeneratorImpl::isPiecewiseStatement(const AnalyserEquationAstPtr &ast) const -{ - return (ast->type() == AnalyserEquationAst::Type::PIECEWISE) - && mProfile->hasConditionalOperator(); -} - void Generator::GeneratorImpl::updateVariableInfoSizes(size_t &componentSize, size_t &nameSize, size_t &unitsSize, @@ -246,11 +67,6 @@ bool Generator::GeneratorImpl::modifiedProfile() const sha1(profileContents) != PYTHON_GENERATOR_PROFILE_SHA1; } -std::string Generator::GeneratorImpl::newLineIfNeeded() -{ - return mCode.empty() ? "" : "\n"; -} - void Generator::GeneratorImpl::addOriginCommentCode() { if (!mProfile->commentString().empty() @@ -264,7 +80,7 @@ void Generator::GeneratorImpl::addOriginCommentCode() "Python"; profileInformation += " profile of"; - mCode += newLineIfNeeded() + mCode += newLineIfNeeded(mCode) + replace(mProfile->commentString(), "[CODE]", replace(replace(mProfile->originCommentString(), "[PROFILE_INFORMATION]", profileInformation), "[LIBCELLML_VERSION]", versionString())); } @@ -273,7 +89,7 @@ void Generator::GeneratorImpl::addOriginCommentCode() void Generator::GeneratorImpl::addInterfaceHeaderCode() { if (!mProfile->interfaceHeaderString().empty()) { - mCode += newLineIfNeeded() + mCode += newLineIfNeeded(mCode) + mProfile->interfaceHeaderString(); } } @@ -287,7 +103,7 @@ void Generator::GeneratorImpl::addImplementationHeaderCode() if (!mProfile->implementationHeaderString().empty() && ((hasInterfaceFileName && !mProfile->interfaceFileNameString().empty()) || !hasInterfaceFileName)) { - mCode += newLineIfNeeded() + mCode += newLineIfNeeded(mCode) + replace(mProfile->implementationHeaderString(), "[INTERFACE_FILE_NAME]", mProfile->interfaceFileNameString()); } @@ -321,7 +137,7 @@ void Generator::GeneratorImpl::addVersionAndLibcellmlVersionCode(bool interface) } if (!code.empty()) { - mCode += newLineIfNeeded() + mCode += newLineIfNeeded(mCode) + code; } } @@ -330,7 +146,7 @@ void Generator::GeneratorImpl::addStateAndVariableCountCode(bool interface) { std::string code; - if (modelHasOdes() + if (mModelHasOdes && ((interface && !mProfile->interfaceStateCountString().empty()) || (!interface && !mProfile->implementationStateCountString().empty()))) { code += interface ? @@ -373,7 +189,7 @@ void Generator::GeneratorImpl::addStateAndVariableCountCode(bool interface) } if (!code.empty()) { - mCode += newLineIfNeeded() + mCode += newLineIfNeeded(mCode) + code; } } @@ -397,7 +213,7 @@ std::string Generator::GeneratorImpl::generateVariableInfoObjectCode(const std:: void Generator::GeneratorImpl::addVariableInfoObjectCode() { if (!mProfile->variableInfoObjectString().empty()) { - mCode += newLineIfNeeded() + mCode += newLineIfNeeded(mCode) + generateVariableInfoObjectCode(mProfile->variableInfoObjectString()); } } @@ -416,12 +232,12 @@ void Generator::GeneratorImpl::addInterfaceVariableInfoCode() { std::string code; - if (modelHasOdes() + if (mModelHasOdes && !mProfile->interfaceVoiInfoString().empty()) { code += mProfile->interfaceVoiInfoString(); } - if (modelHasOdes() + if (mModelHasOdes && !mProfile->interfaceStateInfoString().empty()) { code += mProfile->interfaceStateInfoString(); } @@ -444,7 +260,7 @@ void Generator::GeneratorImpl::addInterfaceVariableInfoCode() } if (!code.empty()) { - mCode += newLineIfNeeded() + mCode += newLineIfNeeded(mCode) + code; } } @@ -475,18 +291,18 @@ void Generator::GeneratorImpl::doAddImplementationVariableInfoCode(const std::st infoElementsCode += "\n"; } - mCode += newLineIfNeeded() + mCode += newLineIfNeeded(mCode) + replace(variableInfoString, "[CODE]", infoElementsCode); } } void Generator::GeneratorImpl::addImplementationVariableInfoCode() { - if (modelHasOdes()) { + if (mModelHasOdes) { doAddImplementationVariableInfoCode(mProfile->implementationVoiInfoString(), {mModel->voi()}, true); } - if (modelHasOdes()) { + if (mModelHasOdes) { doAddImplementationVariableInfoCode(mProfile->implementationStateInfoString(), mModel->states(), false); } @@ -503,73 +319,73 @@ void Generator::GeneratorImpl::addArithmeticFunctionsCode() { if (mModel->needEqFunction() && !mProfile->hasEqOperator() && !mProfile->eqFunctionString().empty()) { - mCode += newLineIfNeeded() + mCode += newLineIfNeeded(mCode) + mProfile->eqFunctionString(); } if (mModel->needNeqFunction() && !mProfile->hasNeqOperator() && !mProfile->neqFunctionString().empty()) { - mCode += newLineIfNeeded() + mCode += newLineIfNeeded(mCode) + mProfile->neqFunctionString(); } if (mModel->needLtFunction() && !mProfile->hasLtOperator() && !mProfile->ltFunctionString().empty()) { - mCode += newLineIfNeeded() + mCode += newLineIfNeeded(mCode) + mProfile->ltFunctionString(); } if (mModel->needLeqFunction() && !mProfile->hasLeqOperator() && !mProfile->leqFunctionString().empty()) { - mCode += newLineIfNeeded() + mCode += newLineIfNeeded(mCode) + mProfile->leqFunctionString(); } if (mModel->needGtFunction() && !mProfile->hasGtOperator() && !mProfile->gtFunctionString().empty()) { - mCode += newLineIfNeeded() + mCode += newLineIfNeeded(mCode) + mProfile->gtFunctionString(); } if (mModel->needGeqFunction() && !mProfile->hasGeqOperator() && !mProfile->geqFunctionString().empty()) { - mCode += newLineIfNeeded() + mCode += newLineIfNeeded(mCode) + mProfile->geqFunctionString(); } if (mModel->needAndFunction() && !mProfile->hasAndOperator() && !mProfile->andFunctionString().empty()) { - mCode += newLineIfNeeded() + mCode += newLineIfNeeded(mCode) + mProfile->andFunctionString(); } if (mModel->needOrFunction() && !mProfile->hasOrOperator() && !mProfile->orFunctionString().empty()) { - mCode += newLineIfNeeded() + mCode += newLineIfNeeded(mCode) + mProfile->orFunctionString(); } if (mModel->needXorFunction() && !mProfile->hasXorOperator() && !mProfile->xorFunctionString().empty()) { - mCode += newLineIfNeeded() + mCode += newLineIfNeeded(mCode) + mProfile->xorFunctionString(); } if (mModel->needNotFunction() && !mProfile->hasNotOperator() && !mProfile->notFunctionString().empty()) { - mCode += newLineIfNeeded() + mCode += newLineIfNeeded(mCode) + mProfile->notFunctionString(); } if (mModel->needMinFunction() && !mProfile->minFunctionString().empty()) { - mCode += newLineIfNeeded() + mCode += newLineIfNeeded(mCode) + mProfile->minFunctionString(); } if (mModel->needMaxFunction() && !mProfile->maxFunctionString().empty()) { - mCode += newLineIfNeeded() + mCode += newLineIfNeeded(mCode) + mProfile->maxFunctionString(); } } @@ -578,73 +394,73 @@ void Generator::GeneratorImpl::addTrigonometricFunctionsCode() { if (mModel->needSecFunction() && !mProfile->secFunctionString().empty()) { - mCode += newLineIfNeeded() + mCode += newLineIfNeeded(mCode) + mProfile->secFunctionString(); } if (mModel->needCscFunction() && !mProfile->cscFunctionString().empty()) { - mCode += newLineIfNeeded() + mCode += newLineIfNeeded(mCode) + mProfile->cscFunctionString(); } if (mModel->needCotFunction() && !mProfile->cotFunctionString().empty()) { - mCode += newLineIfNeeded() + mCode += newLineIfNeeded(mCode) + mProfile->cotFunctionString(); } if (mModel->needSechFunction() && !mProfile->sechFunctionString().empty()) { - mCode += newLineIfNeeded() + mCode += newLineIfNeeded(mCode) + mProfile->sechFunctionString(); } if (mModel->needCschFunction() && !mProfile->cschFunctionString().empty()) { - mCode += newLineIfNeeded() + mCode += newLineIfNeeded(mCode) + mProfile->cschFunctionString(); } if (mModel->needCothFunction() && !mProfile->cothFunctionString().empty()) { - mCode += newLineIfNeeded() + mCode += newLineIfNeeded(mCode) + mProfile->cothFunctionString(); } if (mModel->needAsecFunction() && !mProfile->asecFunctionString().empty()) { - mCode += newLineIfNeeded() + mCode += newLineIfNeeded(mCode) + mProfile->asecFunctionString(); } if (mModel->needAcscFunction() && !mProfile->acscFunctionString().empty()) { - mCode += newLineIfNeeded() + mCode += newLineIfNeeded(mCode) + mProfile->acscFunctionString(); } if (mModel->needAcotFunction() && !mProfile->acotFunctionString().empty()) { - mCode += newLineIfNeeded() + mCode += newLineIfNeeded(mCode) + mProfile->acotFunctionString(); } if (mModel->needAsechFunction() && !mProfile->asechFunctionString().empty()) { - mCode += newLineIfNeeded() + mCode += newLineIfNeeded(mCode) + mProfile->asechFunctionString(); } if (mModel->needAcschFunction() && !mProfile->acschFunctionString().empty()) { - mCode += newLineIfNeeded() + mCode += newLineIfNeeded(mCode) + mProfile->acschFunctionString(); } if (mModel->needAcothFunction() && !mProfile->acothFunctionString().empty()) { - mCode += newLineIfNeeded() + mCode += newLineIfNeeded(mCode) + mProfile->acothFunctionString(); } } @@ -653,7 +469,7 @@ void Generator::GeneratorImpl::addInterfaceCreateDeleteArrayMethodsCode() { std::string code; - if (modelHasOdes() + if (mModelHasOdes && !mProfile->interfaceCreateStatesArrayMethodString().empty()) { code += mProfile->interfaceCreateStatesArrayMethodString(); } @@ -681,42 +497,42 @@ void Generator::GeneratorImpl::addInterfaceCreateDeleteArrayMethodsCode() } if (!code.empty()) { - mCode += newLineIfNeeded() + mCode += newLineIfNeeded(mCode) + code; } } void Generator::GeneratorImpl::addImplementationCreateDeleteArrayMethodsCode() { - if (modelHasOdes() + if (mModelHasOdes && !mProfile->implementationCreateStatesArrayMethodString().empty()) { - mCode += newLineIfNeeded() + mCode += newLineIfNeeded(mCode) + mProfile->implementationCreateStatesArrayMethodString(); } if (!mProfile->implementationCreateConstantsArrayMethodString().empty()) { - mCode += newLineIfNeeded() + mCode += newLineIfNeeded(mCode) + mProfile->implementationCreateConstantsArrayMethodString(); } if (!mProfile->implementationCreateComputedConstantsArrayMethodString().empty()) { - mCode += newLineIfNeeded() + mCode += newLineIfNeeded(mCode) + mProfile->implementationCreateComputedConstantsArrayMethodString(); } if (!mProfile->implementationCreateAlgebraicArrayMethodString().empty()) { - mCode += newLineIfNeeded() + mCode += newLineIfNeeded(mCode) + mProfile->implementationCreateAlgebraicArrayMethodString(); } if (mModel->hasExternalVariables() && !mProfile->implementationCreateExternalsArrayMethodString().empty()) { - mCode += newLineIfNeeded() + mCode += newLineIfNeeded(mCode) + mProfile->implementationCreateExternalsArrayMethodString(); } if (!mProfile->implementationDeleteArrayMethodString().empty()) { - mCode += newLineIfNeeded() + mCode += newLineIfNeeded(mCode) + mProfile->implementationDeleteArrayMethodString(); } } @@ -724,10 +540,10 @@ void Generator::GeneratorImpl::addImplementationCreateDeleteArrayMethodsCode() void Generator::GeneratorImpl::addExternalVariableMethodTypeDefinitionCode() { if (mModel->hasExternalVariables()) { - auto externalVariableMethodTypeDefinitionString = mProfile->externalVariableMethodTypeDefinitionString(modelHasOdes()); + auto externalVariableMethodTypeDefinitionString = mProfile->externalVariableMethodTypeDefinitionString(mModelHasOdes); if (!externalVariableMethodTypeDefinitionString.empty()) { - mCode += newLineIfNeeded() + mCode += newLineIfNeeded(mCode) + externalVariableMethodTypeDefinitionString; } } @@ -735,1050 +551,25 @@ void Generator::GeneratorImpl::addExternalVariableMethodTypeDefinitionCode() void Generator::GeneratorImpl::addRootFindingInfoObjectCode() { - if (modelHasNlas() - && !mProfile->rootFindingInfoObjectString(modelHasOdes(), mModel->hasExternalVariables()).empty()) { - mCode += newLineIfNeeded() - + mProfile->rootFindingInfoObjectString(modelHasOdes(), mModel->hasExternalVariables()); + if (mModelHasNlas + && !mProfile->rootFindingInfoObjectString(mModelHasOdes, mModel->hasExternalVariables()).empty()) { + mCode += newLineIfNeeded(mCode) + + mProfile->rootFindingInfoObjectString(mModelHasOdes, mModel->hasExternalVariables()); } } void Generator::GeneratorImpl::addExternNlaSolveMethodCode() { - if (modelHasNlas() + if (mModelHasNlas && !mProfile->externNlaSolveMethodString().empty()) { - mCode += newLineIfNeeded() + mCode += newLineIfNeeded(mCode) + mProfile->externNlaSolveMethodString(); } } -void Generator::GeneratorImpl::addNlaSystemsCode() -{ - if (modelHasNlas() - && !mProfile->objectiveFunctionMethodString(modelHasOdes(), mModel->hasExternalVariables()).empty() - && !mProfile->findRootMethodString(modelHasOdes(), mModel->hasExternalVariables()).empty() - && !mProfile->nlaSolveCallString(modelHasOdes(), mModel->hasExternalVariables()).empty()) { - // Note: only states and algebraic variables can be computed through an NLA system. Constants, computed - // constants, and external variables cannot, by definition, be computed through an NLA system. - - std::vector handledNlaEquations; - - for (const auto &equation : mModel->equations()) { - if ((equation->type() == AnalyserEquation::Type::NLA) - && (std::find(handledNlaEquations.begin(), handledNlaEquations.end(), equation) == handledNlaEquations.end())) { - std::string methodBody; - auto i = MAX_SIZE_T; - auto variables = libcellml::variables(equation); - - for (const auto &variable : variables) { - auto arrayString = (variable->type() == AnalyserVariable::Type::STATE) ? - mProfile->ratesArrayString() : - mProfile->algebraicArrayString(); - - methodBody += mProfile->indentString() - + arrayString + mProfile->openArrayString() + convertToString(variable->index()) + mProfile->closeArrayString() - + mProfile->equalityString() - + mProfile->uArrayString() + mProfile->openArrayString() + convertToString(++i) + mProfile->closeArrayString() - + mProfile->commandSeparatorString() + "\n"; - } - - methodBody += newLineIfNeeded(); - - i = MAX_SIZE_T; - - methodBody += mProfile->indentString() - + mProfile->fArrayString() + mProfile->openArrayString() + convertToString(++i) + mProfile->closeArrayString() - + mProfile->equalityString() - + generateCode(equation->ast()) - + mProfile->commandSeparatorString() + "\n"; - - handledNlaEquations.push_back(equation); - - for (const auto &nlaSibling : equation->nlaSiblings()) { - methodBody += mProfile->indentString() - + mProfile->fArrayString() + mProfile->openArrayString() + convertToString(++i) + mProfile->closeArrayString() - + mProfile->equalityString() - + generateCode(nlaSibling->ast()) - + mProfile->commandSeparatorString() + "\n"; - - handledNlaEquations.push_back(nlaSibling); - } - - mCode += newLineIfNeeded() - + replace(replace(mProfile->objectiveFunctionMethodString(modelHasOdes(), mModel->hasExternalVariables()), - "[INDEX]", convertToString(equation->nlaSystemIndex())), - "[CODE]", generateMethodBodyCode(methodBody)); - - methodBody = {}; - - i = MAX_SIZE_T; - - for (const auto &variable : variables) { - auto arrayString = (variable->type() == AnalyserVariable::Type::STATE) ? - mProfile->ratesArrayString() : - mProfile->algebraicArrayString(); - - methodBody += mProfile->indentString() - + mProfile->uArrayString() + mProfile->openArrayString() + convertToString(++i) + mProfile->closeArrayString() - + mProfile->equalityString() - + arrayString + mProfile->openArrayString() + convertToString(variable->index()) + mProfile->closeArrayString() - + mProfile->commandSeparatorString() + "\n"; - } - - auto variablesCount = variables.size(); - - methodBody += newLineIfNeeded() - + mProfile->indentString() - + replace(replace(mProfile->nlaSolveCallString(modelHasOdes(), mModel->hasExternalVariables()), - "[INDEX]", convertToString(equation->nlaSystemIndex())), - "[SIZE]", convertToString(variablesCount)); - - methodBody += newLineIfNeeded(); - - i = MAX_SIZE_T; - - for (const auto &variable : variables) { - auto arrayString = (variable->type() == AnalyserVariable::Type::STATE) ? - mProfile->ratesArrayString() : - mProfile->algebraicArrayString(); - - methodBody += mProfile->indentString() - + arrayString + mProfile->openArrayString() + convertToString(variable->index()) + mProfile->closeArrayString() - + mProfile->equalityString() - + mProfile->uArrayString() + mProfile->openArrayString() + convertToString(++i) + mProfile->closeArrayString() - + mProfile->commandSeparatorString() + "\n"; - } - - mCode += newLineIfNeeded() - + replace(replace(replace(mProfile->findRootMethodString(modelHasOdes(), mModel->hasExternalVariables()), - "[INDEX]", convertToString(equation->nlaSystemIndex())), - "[SIZE]", convertToString(variablesCount)), - "[CODE]", generateMethodBodyCode(methodBody)); - } - } - } -} - -std::string Generator::GeneratorImpl::generateMethodBodyCode(const std::string &methodBody) const -{ - return methodBody.empty() ? - mProfile->emptyMethodString().empty() ? - "" : - mProfile->indentString() + mProfile->emptyMethodString() : - methodBody; -} - -std::string generateDoubleCode(const std::string &value) -{ - if (value.find('.') != std::string::npos) { - return value; - } - - auto ePos = value.find('e'); - - if (ePos == std::string::npos) { - return value + ".0"; - } - - return value.substr(0, ePos) + ".0" + value.substr(ePos); -} - -std::string Generator::GeneratorImpl::generateDoubleOrConstantVariableNameCode(const VariablePtr &variable) const -{ - if (isCellMLReal(variable->initialValue())) { - return generateDoubleCode(variable->initialValue()); - } - - auto initialValueVariable = owningComponent(variable)->variable(variable->initialValue()); - auto analyserInitialValueVariable = analyserVariable(mModel, initialValueVariable); - - return mProfile->constantsArrayString() + mProfile->openArrayString() + convertToString(analyserInitialValueVariable->index()) + mProfile->closeArrayString(); -} - -std::string Generator::GeneratorImpl::generateVariableNameCode(const VariablePtr &variable, - bool state) const -{ - // Generate some code for a variable name, but only if we have a model. If - // we don't have a model, it means that we are using the generator from the - // analyser, in which case we just want to return the original name of the - // variable. - - if (mModel == nullptr) { - return variable->name(); - } - - auto analyserVariable = libcellml::analyserVariable(mModel, variable); - - if (analyserVariable->type() == AnalyserVariable::Type::VARIABLE_OF_INTEGRATION) { - return mProfile->voiString(); - } - - std::string arrayName; - - if (analyserVariable->type() == AnalyserVariable::Type::STATE) { - arrayName = state ? - mProfile->statesArrayString() : - mProfile->ratesArrayString(); - } else if (analyserVariable->type() == AnalyserVariable::Type::CONSTANT) { - arrayName = mProfile->constantsArrayString(); - } else if (analyserVariable->type() == AnalyserVariable::Type::COMPUTED_CONSTANT) { - arrayName = mProfile->computedConstantsArrayString(); - } else if (analyserVariable->type() == AnalyserVariable::Type::ALGEBRAIC) { - arrayName = mProfile->algebraicArrayString(); - } else { - arrayName = mProfile->externalArrayString(); - } - - return arrayName + mProfile->openArrayString() + convertToString(analyserVariable->index()) + mProfile->closeArrayString(); -} - -std::string Generator::GeneratorImpl::generateOperatorCode(const std::string &op, - const AnalyserEquationAstPtr &ast) const -{ - // Generate the code for the left and right branches of the given AST. - - std::string res; - auto astLeftChild = ast->leftChild(); - auto astRightChild = ast->rightChild(); - auto astLeftChildCode = generateCode(astLeftChild); - auto astRightChildCode = generateCode(astRightChild); - - // Determine whether parentheses should be added around the left and/or - // right piece of code, and this based on the precedence of the operators - // used in CellML, which are listed below from higher to lower precedence: - // 1. Parentheses [Left to right] - // 2. POWER (as an operator, not as a function, i.e. [Left to right] - // as in Matlab and not in C, for example) - // 3. Unary PLUS, Unary MINUS, NOT [Right to left] - // 4. TIMES, DIVIDE [Left to right] - // 5. PLUS, MINUS [Left to right] - // 6. LT, LEQ, GT, GEQ [Left to right] - // 7. EQ, NEQ [Left to right] - // 8. XOR (bitwise) [Left to right] - // 9. AND (logical) [Left to right] - // 10. OR (logical) [Left to right] - // 11. PIECEWISE (as an operator) [Right to left] - - if (isPlusOperator(ast)) { - if (isRelationalOperator(astLeftChild) - || isLogicalOperator(astLeftChild) - || isPiecewiseStatement(astLeftChild)) { - astLeftChildCode = "(" + astLeftChildCode + ")"; - } - - if (isRelationalOperator(astRightChild) - || isLogicalOperator(astRightChild) - || isPiecewiseStatement(astRightChild)) { - astRightChildCode = "(" + astRightChildCode + ")"; - } - } else if (isMinusOperator(ast)) { - if (isRelationalOperator(astLeftChild) - || isLogicalOperator(astLeftChild) - || isPiecewiseStatement(astLeftChild)) { - astLeftChildCode = "(" + astLeftChildCode + ")"; - } - - if (isNegativeNumber(astRightChild) - || isRelationalOperator(astRightChild) - || isLogicalOperator(astRightChild) - || isMinusOperator(astRightChild) - || isPiecewiseStatement(astRightChild) - || (astRightChildCode.rfind(mProfile->minusString(), 0) == 0)) { - astRightChildCode = "(" + astRightChildCode + ")"; - } else if (isPlusOperator(astRightChild)) { - if (astRightChild->rightChild() != nullptr) { - astRightChildCode = "(" + astRightChildCode + ")"; - } - } - } else if (isTimesOperator(ast)) { - if (isRelationalOperator(astLeftChild) - || isLogicalOperator(astLeftChild) - || isPiecewiseStatement(astLeftChild)) { - astLeftChildCode = "(" + astLeftChildCode + ")"; - } else if (isPlusOperator(astLeftChild) - || isMinusOperator(astLeftChild)) { - if (astLeftChild->rightChild() != nullptr) { - astLeftChildCode = "(" + astLeftChildCode + ")"; - } - } - - if (isRelationalOperator(astRightChild) - || isLogicalOperator(astRightChild) - || isPiecewiseStatement(astRightChild)) { - astRightChildCode = "(" + astRightChildCode + ")"; - } else if (isPlusOperator(astRightChild) - || isMinusOperator(astRightChild)) { - if (astRightChild->rightChild() != nullptr) { - astRightChildCode = "(" + astRightChildCode + ")"; - } - } - } else if (isDivideOperator(ast)) { - if (isRelationalOperator(astLeftChild) - || isLogicalOperator(astLeftChild) - || isPiecewiseStatement(astLeftChild)) { - astLeftChildCode = "(" + astLeftChildCode + ")"; - } else if (isPlusOperator(astLeftChild) - || isMinusOperator(astLeftChild)) { - if (astLeftChild->rightChild() != nullptr) { - astLeftChildCode = "(" + astLeftChildCode + ")"; - } - } - - if (isRelationalOperator(astRightChild) - || isLogicalOperator(astRightChild) - || isTimesOperator(astRightChild) - || isDivideOperator(astRightChild) - || isPiecewiseStatement(astRightChild)) { - astRightChildCode = "(" + astRightChildCode + ")"; - } else if (isPlusOperator(astRightChild) - || isMinusOperator(astRightChild)) { - if (astRightChild->rightChild() != nullptr) { - astRightChildCode = "(" + astRightChildCode + ")"; - } - } - } else if (isAndOperator(ast)) { - // Note: according to the precedence rules above, we only need to - // add parentheses around OR and PIECEWISE. However, it looks - // better/clearer to have some around some other operators - // (agreed, this is somewhat subjective). - - if (isRelationalOperator(astLeftChild) - || isOrOperator(astLeftChild) - || isXorOperator(astLeftChild) - || isPiecewiseStatement(astLeftChild)) { - astLeftChildCode = "(" + astLeftChildCode + ")"; - } else if (isPlusOperator(astLeftChild) - || isMinusOperator(astLeftChild)) { - if (astLeftChild->rightChild() != nullptr) { - astLeftChildCode = "(" + astLeftChildCode + ")"; - } - } else if (isPowerOperator(astLeftChild)) { - astLeftChildCode = "(" + astLeftChildCode + ")"; - } else if (isRootOperator(astLeftChild)) { - astLeftChildCode = "(" + astLeftChildCode + ")"; - } - - if (isRelationalOperator(astRightChild) - || isOrOperator(astRightChild) - || isXorOperator(astRightChild) - || isPiecewiseStatement(astRightChild)) { - astRightChildCode = "(" + astRightChildCode + ")"; - } else if (isPlusOperator(astRightChild) - || isMinusOperator(astRightChild)) { - if (astRightChild->rightChild() != nullptr) { - astRightChildCode = "(" + astRightChildCode + ")"; - } - } else if (isPowerOperator(astRightChild)) { - astRightChildCode = "(" + astRightChildCode + ")"; - } else if (isRootOperator(astRightChild)) { - astRightChildCode = "(" + astRightChildCode + ")"; - } - } else if (isOrOperator(ast)) { - // Note: according to the precedence rules above, we only need to - // add parentheses around PIECEWISE. However, it looks - // better/clearer to have some around some other operators - // (agreed, this is somewhat subjective). - - if (isRelationalOperator(astLeftChild) - || isAndOperator(astLeftChild) - || isXorOperator(astLeftChild) - || isPiecewiseStatement(astLeftChild)) { - astLeftChildCode = "(" + astLeftChildCode + ")"; - } else if (isPlusOperator(astLeftChild) - || isMinusOperator(astLeftChild)) { - if (astLeftChild->rightChild() != nullptr) { - astLeftChildCode = "(" + astLeftChildCode + ")"; - } - } else if (isPowerOperator(astLeftChild)) { - astLeftChildCode = "(" + astLeftChildCode + ")"; - } else if (isRootOperator(astLeftChild)) { - astLeftChildCode = "(" + astLeftChildCode + ")"; - } - - if (isRelationalOperator(astRightChild) - || isAndOperator(astRightChild) - || isXorOperator(astRightChild) - || isPiecewiseStatement(astRightChild)) { - astRightChildCode = "(" + astRightChildCode + ")"; - } else if (isPlusOperator(astRightChild) - || isMinusOperator(astRightChild)) { - if (astRightChild->rightChild() != nullptr) { - astRightChildCode = "(" + astRightChildCode + ")"; - } - } else if (isPowerOperator(astRightChild)) { - astRightChildCode = "(" + astRightChildCode + ")"; - } else if (isRootOperator(astRightChild)) { - astRightChildCode = "(" + astRightChildCode + ")"; - } - } else if (isXorOperator(ast)) { - // Note: according to the precedence rules above, we only need to - // add parentheses around AND, OR and PIECEWISE. However, it - // looks better/clearer to have some around some other - // operators (agreed, this is somewhat subjective). - - if (isRelationalOperator(astLeftChild) - || isAndOperator(astLeftChild) - || isOrOperator(astLeftChild) - || isPiecewiseStatement(astLeftChild)) { - astLeftChildCode = "(" + astLeftChildCode + ")"; - } else if (isPlusOperator(astLeftChild) - || isMinusOperator(astLeftChild)) { - if (astLeftChild->rightChild() != nullptr) { - astLeftChildCode = "(" + astLeftChildCode + ")"; - } - } else if (isPowerOperator(astLeftChild)) { - astLeftChildCode = "(" + astLeftChildCode + ")"; - } else if (isRootOperator(astLeftChild)) { - astLeftChildCode = "(" + astLeftChildCode + ")"; - } - - if (isRelationalOperator(astRightChild) - || isAndOperator(astRightChild) - || isOrOperator(astRightChild) - || isPiecewiseStatement(astRightChild)) { - astRightChildCode = "(" + astRightChildCode + ")"; - } else if (isPlusOperator(astRightChild) - || isMinusOperator(astRightChild)) { - if (astRightChild->rightChild() != nullptr) { - astRightChildCode = "(" + astRightChildCode + ")"; - } - } else if (isPowerOperator(astRightChild)) { - astRightChildCode = "(" + astRightChildCode + ")"; - } else if (isRootOperator(astRightChild)) { - astRightChildCode = "(" + astRightChildCode + ")"; - } - } else if (isPowerOperator(ast)) { - if (isRelationalOperator(astLeftChild) - || isLogicalOperator(astLeftChild) - || isMinusOperator(astLeftChild) - || isTimesOperator(astLeftChild) - || isDivideOperator(astLeftChild) - || isPiecewiseStatement(astLeftChild)) { - astLeftChildCode = "(" + astLeftChildCode + ")"; - } else if (isPlusOperator(astLeftChild)) { - if (astLeftChild->rightChild() != nullptr) { - astLeftChildCode = "(" + astLeftChildCode + ")"; - } - } - - if (isRelationalOperator(astRightChild) - || isLogicalOperator(astRightChild) - || isMinusOperator(astLeftChild) - || isTimesOperator(astRightChild) - || isDivideOperator(astRightChild) - || isPowerOperator(astRightChild) - || isRootOperator(astRightChild) - || isPiecewiseStatement(astRightChild)) { - astRightChildCode = "(" + astRightChildCode + ")"; - } else if (isPlusOperator(astRightChild)) { - if (astRightChild->rightChild() != nullptr) { - astRightChildCode = "(" + astRightChildCode + ")"; - } - } - } else if (isRootOperator(ast)) { - if (isRelationalOperator(astRightChild) - || isLogicalOperator(astRightChild) - || isMinusOperator(astRightChild) - || isTimesOperator(astRightChild) - || isDivideOperator(astRightChild) - || isPiecewiseStatement(astRightChild)) { - astRightChildCode = "(" + astRightChildCode + ")"; - } else if (isPlusOperator(astRightChild)) { - if (astRightChild->rightChild() != nullptr) { - astRightChildCode = "(" + astRightChildCode + ")"; - } - } - - auto astLeftChildLeftChild = astLeftChild->leftChild(); - - if (isRelationalOperator(astLeftChildLeftChild) - || isLogicalOperator(astLeftChildLeftChild) - || isMinusOperator(astLeftChildLeftChild) - || isTimesOperator(astLeftChildLeftChild) - || isDivideOperator(astLeftChildLeftChild) - || isPowerOperator(astLeftChildLeftChild) - || isRootOperator(astLeftChildLeftChild) - || isPiecewiseStatement(astLeftChildLeftChild)) { - astLeftChildCode = "(" + astLeftChildCode + ")"; - } else if (isPlusOperator(astLeftChildLeftChild)) { - if (astLeftChildLeftChild->rightChild() != nullptr) { - astLeftChildCode = "(" + astLeftChildCode + ")"; - } - } - - return astRightChildCode + op + "(1.0/" + astLeftChildCode + ")"; - } - - return astLeftChildCode + op + astRightChildCode; -} - -std::string Generator::GeneratorImpl::generateMinusUnaryCode(const AnalyserEquationAstPtr &ast) const -{ - // Generate the code for the left branch of the given AST. - - auto astLeftChild = ast->leftChild(); - auto code = generateCode(astLeftChild); - - // Determine whether parentheses should be added around the left code. - - if (isRelationalOperator(astLeftChild) - || isLogicalOperator(astLeftChild) - || isPlusOperator(astLeftChild) - || isMinusOperator(astLeftChild) - || isPiecewiseStatement(astLeftChild)) { - code = "(" + code + ")"; - } - - return mProfile->minusString() + code; -} - -std::string Generator::GeneratorImpl::generateOneParameterFunctionCode(const std::string &function, - const AnalyserEquationAstPtr &ast) const -{ - return function + "(" + generateCode(ast->leftChild()) + ")"; -} - -std::string Generator::GeneratorImpl::generateTwoParameterFunctionCode(const std::string &function, - const AnalyserEquationAstPtr &ast) const -{ - return function + "(" + generateCode(ast->leftChild()) + ", " + generateCode(ast->rightChild()) + ")"; -} - -std::string Generator::GeneratorImpl::generatePiecewiseIfCode(const std::string &condition, - const std::string &value) const -{ - return replace(replace(mProfile->hasConditionalOperator() ? - mProfile->conditionalOperatorIfString() : - mProfile->piecewiseIfString(), - "[CONDITION]", condition), - "[IF_STATEMENT]", value); -} - -std::string Generator::GeneratorImpl::generatePiecewiseElseCode(const std::string &value) const -{ - return replace(mProfile->hasConditionalOperator() ? - mProfile->conditionalOperatorElseString() : - mProfile->piecewiseElseString(), - "[ELSE_STATEMENT]", value); -} - -std::string Generator::GeneratorImpl::generateCode(const AnalyserEquationAstPtr &ast) const -{ - // Generate the code for the given AST. - // Note: AnalyserEquationAst::Type::BVAR is only relevant when there is no - // model (in which case we want to generate something like dx/dt, as - // is in the case of the analyser when we want to mention an equation) - // since otherwise we don't need to generate any code for it (since we - // will, instead, want to generate something like rates[0]). - - std::string code; - - switch (ast->type()) { - case AnalyserEquationAst::Type::EQUALITY: - code = generateOperatorCode(mProfile->equalityString(), ast); - - break; - case AnalyserEquationAst::Type::EQ: - if (mProfile->hasEqOperator()) { - code = generateOperatorCode(mProfile->eqString(), ast); - } else { - code = generateTwoParameterFunctionCode(mProfile->eqString(), ast); - } - - break; - case AnalyserEquationAst::Type::NEQ: - if (mProfile->hasNeqOperator()) { - code = generateOperatorCode(mProfile->neqString(), ast); - } else { - code = generateTwoParameterFunctionCode(mProfile->neqString(), ast); - } - - break; - case AnalyserEquationAst::Type::LT: - if (mProfile->hasLtOperator()) { - code = generateOperatorCode(mProfile->ltString(), ast); - } else { - code = generateTwoParameterFunctionCode(mProfile->ltString(), ast); - } - - break; - case AnalyserEquationAst::Type::LEQ: - if (mProfile->hasLeqOperator()) { - code = generateOperatorCode(mProfile->leqString(), ast); - } else { - code = generateTwoParameterFunctionCode(mProfile->leqString(), ast); - } - - break; - case AnalyserEquationAst::Type::GT: - if (mProfile->hasGtOperator()) { - code = generateOperatorCode(mProfile->gtString(), ast); - } else { - code = generateTwoParameterFunctionCode(mProfile->gtString(), ast); - } - - break; - case AnalyserEquationAst::Type::GEQ: - if (mProfile->hasGeqOperator()) { - code = generateOperatorCode(mProfile->geqString(), ast); - } else { - code = generateTwoParameterFunctionCode(mProfile->geqString(), ast); - } - - break; - case AnalyserEquationAst::Type::AND: - if (mProfile->hasAndOperator()) { - code = generateOperatorCode(mProfile->andString(), ast); - } else { - code = generateTwoParameterFunctionCode(mProfile->andString(), ast); - } - - break; - case AnalyserEquationAst::Type::OR: - if (mProfile->hasOrOperator()) { - code = generateOperatorCode(mProfile->orString(), ast); - } else { - code = generateTwoParameterFunctionCode(mProfile->orString(), ast); - } - - break; - case AnalyserEquationAst::Type::XOR: - if (mProfile->hasXorOperator()) { - code = generateOperatorCode(mProfile->xorString(), ast); - } else { - code = generateTwoParameterFunctionCode(mProfile->xorString(), ast); - } - - break; - case AnalyserEquationAst::Type::NOT: - if (mProfile->hasNotOperator()) { - code = mProfile->notString() + generateCode(ast->leftChild()); - } else { - code = generateOneParameterFunctionCode(mProfile->notString(), ast); - } - - break; - case AnalyserEquationAst::Type::PLUS: - if (ast->rightChild() != nullptr) { - code = generateOperatorCode(mProfile->plusString(), ast); - } else { - code = generateCode(ast->leftChild()); - } - - break; - case AnalyserEquationAst::Type::MINUS: - if (ast->rightChild() != nullptr) { - code = generateOperatorCode(mProfile->minusString(), ast); - } else { - code = generateMinusUnaryCode(ast); - } - - break; - case AnalyserEquationAst::Type::TIMES: - code = generateOperatorCode(mProfile->timesString(), ast); - - break; - case AnalyserEquationAst::Type::DIVIDE: - code = generateOperatorCode(mProfile->divideString(), ast); - - break; - case AnalyserEquationAst::Type::POWER: { - auto stringValue = generateCode(ast->rightChild()); - double doubleValue; - auto validConversion = convertToDouble(stringValue, doubleValue); - - if (validConversion && areEqual(doubleValue, 0.5)) { - code = generateOneParameterFunctionCode(mProfile->squareRootString(), ast); - } else if (validConversion && areEqual(doubleValue, 2.0) - && !mProfile->squareString().empty()) { - code = generateOneParameterFunctionCode(mProfile->squareString(), ast); - } else { - code = mProfile->hasPowerOperator() ? - generateOperatorCode(mProfile->powerString(), ast) : - mProfile->powerString() + "(" + generateCode(ast->leftChild()) + ", " + stringValue + ")"; - } - } break; - case AnalyserEquationAst::Type::ROOT: { - auto astRightChild = ast->rightChild(); - - if (astRightChild != nullptr) { - auto astLeftChild = ast->leftChild(); - double doubleValue; - - if (convertToDouble(generateCode(astLeftChild), doubleValue) - && areEqual(doubleValue, 2.0)) { - code = mProfile->squareRootString() + "(" + generateCode(astRightChild) + ")"; - } else { - if (mProfile->hasPowerOperator()) { - code = generateOperatorCode(mProfile->powerString(), ast); - } else { - auto rootValueAst = AnalyserEquationAst::create(); - - rootValueAst->setType(AnalyserEquationAst::Type::DIVIDE); - rootValueAst->setParent(ast); - - auto leftChild = AnalyserEquationAst::create(); - - leftChild->setType(AnalyserEquationAst::Type::CN); - leftChild->setValue("1.0"); - leftChild->setParent(rootValueAst); - - rootValueAst->setLeftChild(leftChild); - rootValueAst->setRightChild(astLeftChild->leftChild()); - - code = mProfile->powerString() + "(" + generateCode(astRightChild) + ", " + generateOperatorCode(mProfile->divideString(), rootValueAst) + ")"; - } - } - } else { - code = generateOneParameterFunctionCode(mProfile->squareRootString(), ast); - } - } break; - case AnalyserEquationAst::Type::ABS: - code = generateOneParameterFunctionCode(mProfile->absoluteValueString(), ast); - - break; - case AnalyserEquationAst::Type::EXP: - code = generateOneParameterFunctionCode(mProfile->exponentialString(), ast); - - break; - case AnalyserEquationAst::Type::LN: - code = generateOneParameterFunctionCode(mProfile->naturalLogarithmString(), ast); - - break; - case AnalyserEquationAst::Type::LOG: { - auto astRightChild = ast->rightChild(); - - if (astRightChild != nullptr) { - auto stringValue = generateCode(ast->leftChild()); - double doubleValue; - - if (convertToDouble(stringValue, doubleValue) - && areEqual(doubleValue, 10.0)) { - code = mProfile->commonLogarithmString() + "(" + generateCode(astRightChild) + ")"; - } else { - code = mProfile->naturalLogarithmString() + "(" + generateCode(astRightChild) + ")/" + mProfile->naturalLogarithmString() + "(" + stringValue + ")"; - } - } else { - code = generateOneParameterFunctionCode(mProfile->commonLogarithmString(), ast); - } - } break; - case AnalyserEquationAst::Type::CEILING: - code = generateOneParameterFunctionCode(mProfile->ceilingString(), ast); - - break; - case AnalyserEquationAst::Type::FLOOR: - code = generateOneParameterFunctionCode(mProfile->floorString(), ast); - - break; - case AnalyserEquationAst::Type::MIN: - code = generateTwoParameterFunctionCode(mProfile->minString(), ast); - - break; - case AnalyserEquationAst::Type::MAX: - code = generateTwoParameterFunctionCode(mProfile->maxString(), ast); - - break; - case AnalyserEquationAst::Type::REM: - code = generateTwoParameterFunctionCode(mProfile->remString(), ast); - - break; - case AnalyserEquationAst::Type::DIFF: - if (mModel != nullptr) { - code = generateCode(ast->rightChild()); - } else { - code = "d" + generateCode(ast->rightChild()) + "/d" + generateCode(ast->leftChild()); - } - - break; - case AnalyserEquationAst::Type::SIN: - code = generateOneParameterFunctionCode(mProfile->sinString(), ast); - - break; - case AnalyserEquationAst::Type::COS: - code = generateOneParameterFunctionCode(mProfile->cosString(), ast); - - break; - case AnalyserEquationAst::Type::TAN: - code = generateOneParameterFunctionCode(mProfile->tanString(), ast); - - break; - case AnalyserEquationAst::Type::SEC: - code = generateOneParameterFunctionCode(mProfile->secString(), ast); - - break; - case AnalyserEquationAst::Type::CSC: - code = generateOneParameterFunctionCode(mProfile->cscString(), ast); - - break; - case AnalyserEquationAst::Type::COT: - code = generateOneParameterFunctionCode(mProfile->cotString(), ast); - - break; - case AnalyserEquationAst::Type::SINH: - code = generateOneParameterFunctionCode(mProfile->sinhString(), ast); - - break; - case AnalyserEquationAst::Type::COSH: - code = generateOneParameterFunctionCode(mProfile->coshString(), ast); - - break; - case AnalyserEquationAst::Type::TANH: - code = generateOneParameterFunctionCode(mProfile->tanhString(), ast); - - break; - case AnalyserEquationAst::Type::SECH: - code = generateOneParameterFunctionCode(mProfile->sechString(), ast); - - break; - case AnalyserEquationAst::Type::CSCH: - code = generateOneParameterFunctionCode(mProfile->cschString(), ast); - - break; - case AnalyserEquationAst::Type::COTH: - code = generateOneParameterFunctionCode(mProfile->cothString(), ast); - - break; - case AnalyserEquationAst::Type::ASIN: - code = generateOneParameterFunctionCode(mProfile->asinString(), ast); - - break; - case AnalyserEquationAst::Type::ACOS: - code = generateOneParameterFunctionCode(mProfile->acosString(), ast); - - break; - case AnalyserEquationAst::Type::ATAN: - code = generateOneParameterFunctionCode(mProfile->atanString(), ast); - - break; - case AnalyserEquationAst::Type::ASEC: - code = generateOneParameterFunctionCode(mProfile->asecString(), ast); - - break; - case AnalyserEquationAst::Type::ACSC: - code = generateOneParameterFunctionCode(mProfile->acscString(), ast); - - break; - case AnalyserEquationAst::Type::ACOT: - code = generateOneParameterFunctionCode(mProfile->acotString(), ast); - - break; - case AnalyserEquationAst::Type::ASINH: - code = generateOneParameterFunctionCode(mProfile->asinhString(), ast); - - break; - case AnalyserEquationAst::Type::ACOSH: - code = generateOneParameterFunctionCode(mProfile->acoshString(), ast); - - break; - case AnalyserEquationAst::Type::ATANH: - code = generateOneParameterFunctionCode(mProfile->atanhString(), ast); - - break; - case AnalyserEquationAst::Type::ASECH: - code = generateOneParameterFunctionCode(mProfile->asechString(), ast); - - break; - case AnalyserEquationAst::Type::ACSCH: - code = generateOneParameterFunctionCode(mProfile->acschString(), ast); - - break; - case AnalyserEquationAst::Type::ACOTH: - code = generateOneParameterFunctionCode(mProfile->acothString(), ast); - - break; - case AnalyserEquationAst::Type::PIECEWISE: { - auto astRightChild = ast->rightChild(); - - if (astRightChild != nullptr) { - if (astRightChild->type() == AnalyserEquationAst::Type::PIECE) { - code = generateCode(ast->leftChild()) + generatePiecewiseElseCode(generateCode(astRightChild) + generatePiecewiseElseCode(mProfile->nanString())); - } else { - code = generateCode(ast->leftChild()) + generatePiecewiseElseCode(generateCode(astRightChild)); - } - } else { - code = generateCode(ast->leftChild()) + generatePiecewiseElseCode(mProfile->nanString()); - } - } break; - case AnalyserEquationAst::Type::PIECE: - code = generatePiecewiseIfCode(generateCode(ast->rightChild()), generateCode(ast->leftChild())); - - break; - case AnalyserEquationAst::Type::OTHERWISE: - code = generateCode(ast->leftChild()); - - break; - case AnalyserEquationAst::Type::CI: - code = generateVariableNameCode(ast->variable(), ast->parent()->type() != AnalyserEquationAst::Type::DIFF); - - break; - case AnalyserEquationAst::Type::CN: - code = generateDoubleCode(ast->value()); - - break; - case AnalyserEquationAst::Type::DEGREE: - case AnalyserEquationAst::Type::LOGBASE: - code = generateCode(ast->leftChild()); - - break; - case AnalyserEquationAst::Type::BVAR: - code = generateCode(ast->leftChild()); - - break; - case AnalyserEquationAst::Type::TRUE: - code = mProfile->trueString(); - - break; - case AnalyserEquationAst::Type::FALSE: - code = mProfile->falseString(); - - break; - case AnalyserEquationAst::Type::E: - code = mProfile->eString(); - - break; - case AnalyserEquationAst::Type::PI: - code = mProfile->piString(); - - break; - case AnalyserEquationAst::Type::INF: - code = mProfile->infString(); - - break; - default: // AnalyserEquationAst::Type::NAN. - code = mProfile->nanString(); - - break; - } - - return code; -} - -bool Generator::GeneratorImpl::isToBeComputedAgain(const AnalyserEquationPtr &equation) const -{ - // NLA and algebraic equations that are state/rate-based and external - // equations are to be computed again (in the computeVariables() method). - - switch (equation->type()) { - case AnalyserEquation::Type::NLA: - case AnalyserEquation::Type::ALGEBRAIC: - return equation->isStateRateBased(); - case AnalyserEquation::Type::EXTERNAL: - return true; - default: - return false; - } -} - -bool Generator::GeneratorImpl::isSomeConstant(const AnalyserEquationPtr &equation, - bool includeComputedConstants) const -{ - auto type = equation->type(); - - return (type == AnalyserEquation::Type::TRUE_CONSTANT) - || (!includeComputedConstants && (type == AnalyserEquation::Type::VARIABLE_BASED_CONSTANT)); -} - -std::string Generator::GeneratorImpl::generateZeroInitialisationCode(const AnalyserVariablePtr &variable) const -{ - return mProfile->indentString() - + generateVariableNameCode(variable->variable(), false) - + mProfile->equalityString() - + "0.0" - + mProfile->commandSeparatorString() + "\n"; -} - -std::string Generator::GeneratorImpl::generateInitialisationCode(const AnalyserVariablePtr &variable) const -{ - auto initialisingVariable = variable->initialisingVariable(); - auto scalingFactor = Generator::GeneratorImpl::scalingFactor(initialisingVariable); - std::string scalingFactorCode; - - if (!areNearlyEqual(scalingFactor, 1.0)) { - scalingFactorCode = generateDoubleCode(convertToString(scalingFactor)) + mProfile->timesString(); - } - - return mProfile->indentString() - + generateVariableNameCode(variable->variable()) - + mProfile->equalityString() - + scalingFactorCode + generateDoubleOrConstantVariableNameCode(initialisingVariable) - + mProfile->commandSeparatorString() + "\n"; -} - -std::string Generator::GeneratorImpl::generateEquationCode(const AnalyserEquationPtr &equation, - std::vector &remainingEquations, - std::vector &equationsForDependencies, - bool includeComputedConstants) -{ - std::string res; - - if (std::find(remainingEquations.begin(), remainingEquations.end(), equation) != remainingEquations.end()) { - // Stop tracking the equation and its NLA siblings, if any. - // Note: we need to do this as soon as possible to avoid recursive - // calls, something that would happen if we were to do this at the - // end of this if statement. - - remainingEquations.erase(std::find(remainingEquations.begin(), remainingEquations.end(), equation)); - - for (const auto &nlaSibling : equation->nlaSiblings()) { - remainingEquations.erase(std::find(remainingEquations.begin(), remainingEquations.end(), nlaSibling)); - } - - // Generate any dependency that this equation may have. - - if (!isSomeConstant(equation, includeComputedConstants)) { - for (const auto &dependency : equation->dependencies()) { - if ((dependency->type() != AnalyserEquation::Type::ODE) - && !isSomeConstant(dependency, includeComputedConstants) - && (equationsForDependencies.empty() - || isToBeComputedAgain(dependency) - || (std::find(equationsForDependencies.begin(), equationsForDependencies.end(), dependency) != equationsForDependencies.end()))) { - res += generateEquationCode(dependency, remainingEquations, equationsForDependencies, includeComputedConstants); - } - } - } - - // Generate the equation code itself, based on the equation type. - - switch (equation->type()) { - case AnalyserEquation::Type::EXTERNAL: - for (const auto &variable : variables(equation)) { - res += mProfile->indentString() - + generateVariableNameCode(variable->variable()) - + mProfile->equalityString() - + replace(mProfile->externalVariableMethodCallString(modelHasOdes()), - "[INDEX]", convertToString(variable->index())) - + mProfile->commandSeparatorString() + "\n"; - } - - break; - case AnalyserEquation::Type::NLA: - if (!mProfile->findRootCallString(modelHasOdes(), mModel->hasExternalVariables()).empty()) { - res += mProfile->indentString() - + replace(mProfile->findRootCallString(modelHasOdes(), mModel->hasExternalVariables()), - "[INDEX]", convertToString(equation->nlaSystemIndex())); - } - - break; - default: - res += mProfile->indentString() + generateCode(equation->ast()) + mProfile->commandSeparatorString() + "\n"; - - break; - } - } - - return res; -} - -std::string Generator::GeneratorImpl::generateEquationCode(const AnalyserEquationPtr &equation, - std::vector &remainingEquations) -{ - std::vector dummyEquationsForComputeVariables; - - return generateEquationCode(equation, remainingEquations, dummyEquationsForComputeVariables, true); -} - void Generator::GeneratorImpl::addInterfaceComputeModelMethodsCode() { - auto interfaceInitialiseVariablesMethodString = mProfile->interfaceInitialiseVariablesMethodString(modelHasOdes()); + auto interfaceInitialiseVariablesMethodString = mProfile->interfaceInitialiseVariablesMethodString(mModelHasOdes); std::string code; if (!interfaceInitialiseVariablesMethodString.empty()) { @@ -1791,12 +582,12 @@ void Generator::GeneratorImpl::addInterfaceComputeModelMethodsCode() auto interfaceComputeRatesMethodString = mProfile->interfaceComputeRatesMethodString(mModel->hasExternalVariables()); - if (modelHasOdes() + if (mModelHasOdes && !interfaceComputeRatesMethodString.empty()) { code += interfaceComputeRatesMethodString; } - auto interfaceComputeVariablesMethodString = mProfile->interfaceComputeVariablesMethodString(modelHasOdes(), + auto interfaceComputeVariablesMethodString = mProfile->interfaceComputeVariablesMethodString(mModelHasOdes, mModel->hasExternalVariables()); if (!interfaceComputeVariablesMethodString.empty()) { @@ -1804,179 +595,16 @@ void Generator::GeneratorImpl::addInterfaceComputeModelMethodsCode() } if (!code.empty()) { - mCode += newLineIfNeeded() + mCode += newLineIfNeeded(mCode) + code; } } -std::string Generator::GeneratorImpl::generateConstantInitialisationCode(const std::vector::iterator constant, - std::vector &remainingConstants) -{ - auto initialisingVariable = (*constant)->initialisingVariable(); - auto initialValue = initialisingVariable->initialValue(); - - if (!isCellMLReal(initialValue)) { - auto initialisingComponent = owningComponent(initialisingVariable); - auto crtConstant = std::find_if(remainingConstants.begin(), remainingConstants.end(), - [=](const AnalyserVariablePtr &av) -> bool { - return initialisingComponent->variable(initialValue) == av->variable(); - }); - - if (crtConstant != remainingConstants.end()) { - return generateConstantInitialisationCode(crtConstant, remainingConstants); - } - } - - auto code = generateInitialisationCode(*constant); - - remainingConstants.erase(constant); - - return code; -} - -void Generator::GeneratorImpl::addImplementationInitialiseVariablesMethodCode(std::vector &remainingEquations) -{ - auto implementationInitialiseVariablesMethodString = mProfile->implementationInitialiseVariablesMethodString(modelHasOdes()); - - if (!implementationInitialiseVariablesMethodString.empty()) { - // Initialise our states (after, if needed, initialising the constant on which it depends). - - std::string methodBody; - auto constants = mModel->constants(); - - for (const auto &state : mModel->states()) { - auto initialisingVariable = state->initialisingVariable(); - auto initialValue = initialisingVariable->initialValue(); - - if (!isCellMLReal(initialValue)) { - // The initial value references a constant. - - auto initialisingComponent = owningComponent(initialisingVariable); - auto constant = std::find_if(constants.begin(), constants.end(), - [=](const AnalyserVariablePtr &av) -> bool { - return initialisingComponent->variable(initialValue)->hasEquivalentVariable(av->variable()); - }); - - methodBody += generateConstantInitialisationCode(constant, constants); - } - - methodBody += generateInitialisationCode(state); - } - - // Use an initial guess of zero for rates computed using an NLA system - // (see the note below). - - for (const auto &state : mModel->states()) { - if (state->equation(0)->type() == AnalyserEquation::Type::NLA) { - methodBody += generateZeroInitialisationCode(state); - } - } - - // Initialise our (remaining) constants. - - while (!constants.empty()) { - methodBody += generateConstantInitialisationCode(constants.begin(), constants); - } - - // Initialise our computed constants that are initialised using an equation (e.g., x = 3 rather than x with an - // initial value of 3). - - auto equations = mModel->equations(); - - for (const auto &equation : equations) { - if (equation->type() == AnalyserEquation::Type::TRUE_CONSTANT) { - methodBody += generateEquationCode(equation, remainingEquations); - } - } - - // Initialise our algebraic variables that have an initial value. Also use an initial guess of zero for - // algebraic variables computed using an NLA system. - // Note: a variable which is the only unknown in an equation, but which is not on its own on either the LHS or - // RHS of that equation (e.g., x = y+z with x and y known and z unknown) is (currently) to be computed - // using an NLA system for which we need an initial guess. We use an initial guess of zero, which is fine - // since such an NLA system has only one solution. - - for (const auto &algebraic : mModel->algebraic()) { - if (algebraic->initialisingVariable() != nullptr) { - methodBody += generateInitialisationCode(algebraic); - } else if (algebraic->equation(0)->type() == AnalyserEquation::Type::NLA) { - methodBody += generateZeroInitialisationCode(algebraic); - } - } - - mCode += newLineIfNeeded() - + replace(implementationInitialiseVariablesMethodString, - "[CODE]", generateMethodBodyCode(methodBody)); - } -} - -void Generator::GeneratorImpl::addImplementationComputeComputedConstantsMethodCode(std::vector &remainingEquations) +void Generator::GeneratorImpl::addImplementationComputeModelMethodsCode() { - if (!mProfile->implementationComputeComputedConstantsMethodString().empty()) { - std::string methodBody; - - for (const auto &equation : mModel->equations()) { - if (equation->type() == AnalyserEquation::Type::VARIABLE_BASED_CONSTANT) { - methodBody += generateEquationCode(equation, remainingEquations); - } - } + auto generatorInterpreter = GeneratorInterpreter::create(mModel, mProfile, mCode); - mCode += newLineIfNeeded() - + replace(mProfile->implementationComputeComputedConstantsMethodString(), - "[CODE]", generateMethodBodyCode(methodBody)); - } -} - -void Generator::GeneratorImpl::addImplementationComputeRatesMethodCode(std::vector &remainingEquations) -{ - auto implementationComputeRatesMethodString = mProfile->implementationComputeRatesMethodString(mModel->hasExternalVariables()); - - if (modelHasOdes() - && !implementationComputeRatesMethodString.empty()) { - std::string methodBody; - - for (const auto &equation : mModel->equations()) { - // A rate is computed either through an ODE equation or through an - // NLA equation in case the rate is not on its own on either the LHS - // or RHS of the equation. - - auto variables = libcellml::variables(equation); - - if ((equation->type() == AnalyserEquation::Type::ODE) - || ((equation->type() == AnalyserEquation::Type::NLA) - && (variables.size() == 1) - && (variables[0]->type() == AnalyserVariable::Type::STATE))) { - methodBody += generateEquationCode(equation, remainingEquations); - } - } - - mCode += newLineIfNeeded() - + replace(implementationComputeRatesMethodString, - "[CODE]", generateMethodBodyCode(methodBody)); - } -} - -void Generator::GeneratorImpl::addImplementationComputeVariablesMethodCode(std::vector &remainingEquations) -{ - auto implementationComputeVariablesMethodString = mProfile->implementationComputeVariablesMethodString(modelHasOdes(), - mModel->hasExternalVariables()); - - if (!implementationComputeVariablesMethodString.empty()) { - std::string methodBody; - auto equations = mModel->equations(); - std::vector newRemainingEquations {std::begin(equations), std::end(equations)}; - - for (const auto &equation : equations) { - if ((std::find(remainingEquations.begin(), remainingEquations.end(), equation) != remainingEquations.end()) - || isToBeComputedAgain(equation)) { - methodBody += generateEquationCode(equation, newRemainingEquations, remainingEquations, false); - } - } - - mCode += newLineIfNeeded() - + replace(implementationComputeVariablesMethodString, - "[CODE]", generateMethodBodyCode(methodBody)); - } + mCode = generatorInterpreter->code(); } Generator::Generator() @@ -2012,6 +640,8 @@ AnalyserModelPtr Generator::model() void Generator::setModel(const AnalyserModelPtr &model) { mPimpl->mModel = model; + mPimpl->mModelHasOdes = modelHasOdes(model); + mPimpl->mModelHasNlas = modelHasNlas(model); } std::string Generator::interfaceCode() const @@ -2120,46 +750,19 @@ std::string Generator::implementationCode() const mPimpl->addRootFindingInfoObjectCode(); mPimpl->addExternNlaSolveMethodCode(); - mPimpl->addNlaSystemsCode(); - - // Add code for the implementation to initialise our variables. - - auto equations = mPimpl->mModel->equations(); - std::vector remainingEquations {std::begin(equations), std::end(equations)}; - - mPimpl->addImplementationInitialiseVariablesMethodCode(remainingEquations); - // Add code for the implementation to compute our computed constants. + // Add code for the implementation to compute the model. - mPimpl->addImplementationComputeComputedConstantsMethodCode(remainingEquations); - - // Add code for the implementation to compute our rates (and any variables - // on which they depend). - - mPimpl->addImplementationComputeRatesMethodCode(remainingEquations); - - // Add code for the implementation to compute our variables. - // Note: this method computes the remaining variables, i.e. the ones not - // needed to compute our rates, but also the variables that depend on - // the value of some states/rates and all the external variables. - // This method is typically called after having integrated a model, - // thus ensuring that variables that rely on the value of some - // states/rates are up to date. - - mPimpl->addImplementationComputeVariablesMethodCode(remainingEquations); + mPimpl->addImplementationComputeModelMethodsCode(); return mPimpl->mCode; } std::string Generator::equationCode(const AnalyserEquationAstPtr &ast, const GeneratorProfilePtr &profile) { - GeneratorPtr generator = libcellml::Generator::create(); - - if (profile != nullptr) { - generator->setProfile(profile); - } + auto generatorInterpreter = GeneratorInterpreter::create(ast, profile); - return generator->mPimpl->generateCode(ast); + return generatorInterpreter->code(); } std::string Generator::equationCode(const AnalyserEquationAstPtr &ast) diff --git a/src/generator_p.h b/src/generator_p.h index fce8d2e7d7..86dc616728 100644 --- a/src/generator_p.h +++ b/src/generator_p.h @@ -24,10 +24,6 @@ limitations under the License. namespace libcellml { -std::string generateDoubleCode(const std::string &value); - -AnalyserVariablePtr analyserVariable(const AnalyserModelPtr &model, const VariablePtr &variable); - /** * @brief The Generator::GeneratorImpl struct. * @@ -36,41 +32,20 @@ AnalyserVariablePtr analyserVariable(const AnalyserModelPtr &model, const Variab struct Generator::GeneratorImpl { AnalyserModelPtr mModel; - - std::string mCode; + bool mModelHasOdes = false; + bool mModelHasNlas = false; GeneratorProfilePtr mProfile = GeneratorProfile::create(); + std::string mCode; void reset(); - bool modelHasOdes() const; - bool modelHasNlas() const; - - double scalingFactor(const VariablePtr &variable) const; - - bool isNegativeNumber(const AnalyserEquationAstPtr &ast) const; - - bool isRelationalOperator(const AnalyserEquationAstPtr &ast) const; - bool isAndOperator(const AnalyserEquationAstPtr &ast) const; - bool isOrOperator(const AnalyserEquationAstPtr &ast) const; - bool isXorOperator(const AnalyserEquationAstPtr &ast) const; - bool isLogicalOperator(const AnalyserEquationAstPtr &ast) const; - bool isPlusOperator(const AnalyserEquationAstPtr &ast) const; - bool isMinusOperator(const AnalyserEquationAstPtr &ast) const; - bool isTimesOperator(const AnalyserEquationAstPtr &ast) const; - bool isDivideOperator(const AnalyserEquationAstPtr &ast) const; - bool isPowerOperator(const AnalyserEquationAstPtr &ast) const; - bool isRootOperator(const AnalyserEquationAstPtr &ast) const; - bool isPiecewiseStatement(const AnalyserEquationAstPtr &ast) const; - void updateVariableInfoSizes(size_t &componentSize, size_t &nameSize, size_t &unitsSize, const AnalyserVariablePtr &variable) const; bool modifiedProfile() const; - std::string newLineIfNeeded(); - void addOriginCommentCode(); void addInterfaceHeaderCode(); @@ -104,46 +79,9 @@ struct Generator::GeneratorImpl void addRootFindingInfoObjectCode(); void addExternNlaSolveMethodCode(); - void addNlaSystemsCode(); - - std::string generateMethodBodyCode(const std::string &methodBody) const; - - std::string generateDoubleOrConstantVariableNameCode(const VariablePtr &variable) const; - std::string generateVariableNameCode(const VariablePtr &variable, - bool state = true) const; - - std::string generateOperatorCode(const std::string &op, - const AnalyserEquationAstPtr &ast) const; - std::string generateMinusUnaryCode(const AnalyserEquationAstPtr &ast) const; - std::string generateOneParameterFunctionCode(const std::string &function, - const AnalyserEquationAstPtr &ast) const; - std::string generateTwoParameterFunctionCode(const std::string &function, - const AnalyserEquationAstPtr &ast) const; - std::string generatePiecewiseIfCode(const std::string &condition, - const std::string &value) const; - std::string generatePiecewiseElseCode(const std::string &value) const; - std::string generateCode(const AnalyserEquationAstPtr &ast) const; - - bool isToBeComputedAgain(const AnalyserEquationPtr &equation) const; - bool isSomeConstant(const AnalyserEquationPtr &equation, - bool includeComputedConstants) const; - - std::string generateZeroInitialisationCode(const AnalyserVariablePtr &variable) const; - std::string generateInitialisationCode(const AnalyserVariablePtr &variable) const; - std::string generateEquationCode(const AnalyserEquationPtr &equation, - std::vector &remainingEquations, - std::vector &equationsForDependencies, - bool includeComputedConstants); - std::string generateEquationCode(const AnalyserEquationPtr &equation, - std::vector &remainingEquations); void addInterfaceComputeModelMethodsCode(); - std::string generateConstantInitialisationCode(const std::vector::iterator constant, - std::vector &remainingConstants); - void addImplementationInitialiseVariablesMethodCode(std::vector &remainingEquations); - void addImplementationComputeComputedConstantsMethodCode(std::vector &remainingEquations); - void addImplementationComputeRatesMethodCode(std::vector &remainingEquations); - void addImplementationComputeVariablesMethodCode(std::vector &remainingEquations); + void addImplementationComputeModelMethodsCode(); }; } // namespace libcellml diff --git a/src/generatorinterpreter.cpp b/src/generatorinterpreter.cpp new file mode 100644 index 0000000000..5826d8b556 --- /dev/null +++ b/src/generatorinterpreter.cpp @@ -0,0 +1,1512 @@ +/* +Copyright libCellML Contributors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +#include "generatorinterpreter_p.h" + +#include "libcellml/analyserequationast.h" +#include "libcellml/analysermodel.h" +#include "libcellml/analyservariable.h" + +#include "utilities.h" + +namespace libcellml { + +GeneratorInterpreter::GeneratorInterpreterImpl::GeneratorInterpreterImpl(const AnalyserModelPtr &model, + const GeneratorProfilePtr &profile, + const std::string &code) +{ + initialise(model, profile, code); +} + +GeneratorInterpreter::GeneratorInterpreterImpl::GeneratorInterpreterImpl(const AnalyserEquationAstPtr &ast, + const GeneratorProfilePtr &profile) +{ + if (profile != nullptr) { + mProfile = profile; + } + + mCode = generateCode(ast); +} + +void GeneratorInterpreter::GeneratorInterpreterImpl::initialise(const AnalyserModelPtr &model, + const GeneratorProfilePtr &profile, + const std::string &code) +{ + mModel = model; + mModelHasOdes = modelHasOdes(model); + mModelHasNlas = modelHasNlas(model); + mProfile = profile; + mCode = code; + + // Add code for solving the NLA systems. + + addNlaSystemsCode(); + + // Add code for the implementation to initialise our variables. + + auto equations = mModel->equations(); + std::vector remainingEquations {std::begin(equations), std::end(equations)}; + + initialiseVariables(remainingEquations); + + // Add code for the implementation to compute our computed constants. + + computeComputedConstants(remainingEquations); + + // Add code for the implementation to compute our rates (and any variables on which they depend). + + computeRates(remainingEquations); + + // Add code for the implementation to compute our variables. + // Note: this method computes the remaining variables, i.e. the ones not needed to compute our rates, but also the + // variables that depend on the value of some states/rates and all the external variables. This method is + // typically called after having integrated a model, thus ensuring that variables that rely on the value of + // some states/rates are up to date. + + computeVariables(remainingEquations); +} + +bool modelHasOdes(const AnalyserModelPtr &model) +{ + switch (model->type()) { + case AnalyserModel::Type::ODE: + case AnalyserModel::Type::DAE: + return true; + default: + return false; + } +} + +bool modelHasNlas(const AnalyserModelPtr &model) +{ + switch (model->type()) { + case AnalyserModel::Type::NLA: + case AnalyserModel::Type::DAE: + return true; + default: + return false; + } +} + +AnalyserVariablePtr analyserVariable(const AnalyserModelPtr &model, const VariablePtr &variable) +{ + // Find and return the analyser variable associated with the given variable. + + AnalyserVariablePtr res; + auto modelVoi = model->voi(); + auto modelVoiVariable = (modelVoi != nullptr) ? modelVoi->variable() : nullptr; + + if ((modelVoiVariable != nullptr) + && model->areEquivalentVariables(variable, modelVoiVariable)) { + res = modelVoi; + } else { + // Normally, we would have something like: + // + // for (const auto &modelVariable : variables(model)) { + // if (model->areEquivalentVariables(variable, modelVariable->variable())) { + // res = modelVariable; + // + // break; + // } + // } + // + // but we always have variables, so llvm-cov will complain that the false branch of our for loop is never + // reached. The below code is a bit more verbose but at least it makes llvm-cov happy. + + auto modelVariables = variables(model); + auto modelVariable = modelVariables.begin(); + + do { + if (model->areEquivalentVariables(variable, (*modelVariable)->variable())) { + res = *modelVariable; + } else { + ++modelVariable; + } + } while (res == nullptr); + } + + return res; +} + +double GeneratorInterpreter::GeneratorInterpreterImpl::scalingFactor(const VariablePtr &variable) const +{ + // Return the scaling factor for the given variable, accounting for the fact that a constant may be initialised by + // another variable which initial value may be defined in a different component. + + auto analyserVariable = libcellml::analyserVariable(mModel, variable); + + if ((analyserVariable->type() == AnalyserVariable::Type::CONSTANT) + && !isCellMLReal(variable->initialValue())) { + auto initialValueVariable = owningComponent(variable)->variable(variable->initialValue()); + auto initialValueAnalyserVariable = libcellml::analyserVariable(mModel, initialValueVariable); + + if (owningComponent(variable) != owningComponent(initialValueAnalyserVariable->variable())) { + return Units::scalingFactor(initialValueVariable->units(), variable->units()); + } + } + + return Units::scalingFactor(analyserVariable->variable()->units(), variable->units()); +} + +bool GeneratorInterpreter::GeneratorInterpreterImpl::isNegativeNumber(const AnalyserEquationAstPtr &ast) const +{ + if (ast->type() == AnalyserEquationAst::Type::CN) { + double doubleValue; + + convertToDouble(ast->value(), doubleValue); + + return doubleValue < 0.0; + } + + return false; +} + +bool GeneratorInterpreter::GeneratorInterpreterImpl::isRelationalOperator(const AnalyserEquationAstPtr &ast) const +{ + switch (ast->type()) { + case AnalyserEquationAst::Type::EQ: + return mProfile->hasEqOperator(); + case AnalyserEquationAst::Type::NEQ: + return mProfile->hasNeqOperator(); + case AnalyserEquationAst::Type::LT: + return mProfile->hasLtOperator(); + case AnalyserEquationAst::Type::LEQ: + return mProfile->hasLeqOperator(); + case AnalyserEquationAst::Type::GT: + return mProfile->hasGtOperator(); + case AnalyserEquationAst::Type::GEQ: + return mProfile->hasGeqOperator(); + default: + return false; + } +} + +bool GeneratorInterpreter::GeneratorInterpreterImpl::isAndOperator(const AnalyserEquationAstPtr &ast) const +{ + return (ast->type() == AnalyserEquationAst::Type::AND) + && mProfile->hasAndOperator(); +} + +bool GeneratorInterpreter::GeneratorInterpreterImpl::isOrOperator(const AnalyserEquationAstPtr &ast) const +{ + return (ast->type() == AnalyserEquationAst::Type::OR) + && mProfile->hasOrOperator(); +} + +bool GeneratorInterpreter::GeneratorInterpreterImpl::isXorOperator(const AnalyserEquationAstPtr &ast) const +{ + return (ast->type() == AnalyserEquationAst::Type::XOR) + && mProfile->hasXorOperator(); +} + +bool GeneratorInterpreter::GeneratorInterpreterImpl::isLogicalOperator(const AnalyserEquationAstPtr &ast) const +{ + // Note: AnalyserEquationAst::Type::NOT is a unary logical operator, hence we don't include it here since this + // method is only used to determine whether parentheses should be added around some code. + + return isAndOperator(ast) || isOrOperator(ast) || isXorOperator(ast); +} + +bool GeneratorInterpreter::GeneratorInterpreterImpl::isPlusOperator(const AnalyserEquationAstPtr &ast) const +{ + return ast->type() == AnalyserEquationAst::Type::PLUS; +} + +bool GeneratorInterpreter::GeneratorInterpreterImpl::isMinusOperator(const AnalyserEquationAstPtr &ast) const +{ + return ast->type() == AnalyserEquationAst::Type::MINUS; +} + +bool GeneratorInterpreter::GeneratorInterpreterImpl::isTimesOperator(const AnalyserEquationAstPtr &ast) const +{ + return ast->type() == AnalyserEquationAst::Type::TIMES; +} + +bool GeneratorInterpreter::GeneratorInterpreterImpl::isDivideOperator(const AnalyserEquationAstPtr &ast) const +{ + return ast->type() == AnalyserEquationAst::Type::DIVIDE; +} + +bool GeneratorInterpreter::GeneratorInterpreterImpl::isPowerOperator(const AnalyserEquationAstPtr &ast) const +{ + return (ast->type() == AnalyserEquationAst::Type::POWER) + && mProfile->hasPowerOperator(); +} + +bool GeneratorInterpreter::GeneratorInterpreterImpl::isRootOperator(const AnalyserEquationAstPtr &ast) const +{ + return (ast->type() == AnalyserEquationAst::Type::ROOT) + && mProfile->hasPowerOperator(); +} + +bool GeneratorInterpreter::GeneratorInterpreterImpl::isPiecewiseStatement(const AnalyserEquationAstPtr &ast) const +{ + return (ast->type() == AnalyserEquationAst::Type::PIECEWISE) + && mProfile->hasConditionalOperator(); +} + +std::string newLineIfNeeded(const std::string &code) +{ + return code.empty() ? "" : "\n"; +} + +std::string GeneratorInterpreter::GeneratorInterpreterImpl::generateMethodBodyCode(const std::string &methodBody) const +{ + return methodBody.empty() ? + (mProfile->emptyMethodString().empty() ? + "" : + mProfile->indentString() + mProfile->emptyMethodString()) : + methodBody; +} + +std::string generateDoubleCode(const std::string &value) +{ + if (value.find('.') != std::string::npos) { + return value; + } + + auto ePos = value.find('e'); + + if (ePos == std::string::npos) { + return value + ".0"; + } + + return value.substr(0, ePos) + ".0" + value.substr(ePos); +} + +std::string GeneratorInterpreter::GeneratorInterpreterImpl::generateVariableNameCode(const VariablePtr &variable, + bool rate) const +{ + // Generate some code for a variable name, but only if we have a model. If we don't have a model, it means that we + // are using the generator from the analyser, in which case we just want to return the original name of the + // variable. + + if (mModel == nullptr) { + return variable->name(); + } + + auto analyserVariable = libcellml::analyserVariable(mModel, variable); + + if (analyserVariable->type() == AnalyserVariable::Type::VARIABLE_OF_INTEGRATION) { + return mProfile->voiString(); + } + + std::string arrayName; + + if (analyserVariable->type() == AnalyserVariable::Type::STATE) { + arrayName = rate ? + mProfile->ratesArrayString() : + mProfile->statesArrayString(); + } else if (analyserVariable->type() == AnalyserVariable::Type::CONSTANT) { + arrayName = mProfile->constantsArrayString(); + } else if (analyserVariable->type() == AnalyserVariable::Type::COMPUTED_CONSTANT) { + arrayName = mProfile->computedConstantsArrayString(); + } else if (analyserVariable->type() == AnalyserVariable::Type::ALGEBRAIC) { + arrayName = mProfile->algebraicArrayString(); + } else { + arrayName = mProfile->externalArrayString(); + } + + return arrayName + mProfile->openArrayString() + convertToString(analyserVariable->index()) + mProfile->closeArrayString(); +} + +std::string GeneratorInterpreter::GeneratorInterpreterImpl::generateOperatorCode(const std::string &op, + const AnalyserEquationAstPtr &ast) const +{ + // Generate the code for the left and right branches of the given AST. + + std::string res; + auto astLeftChild = ast->leftChild(); + auto astRightChild = ast->rightChild(); + auto leftCode = generateCode(astLeftChild); + auto rightCode = generateCode(astRightChild); + + // Determine whether parentheses should be added around the left and/or right piece of code, and this based on the + // precedence of the operators used in CellML, which are listed below from higher to lower precedence: + // 1. Parentheses [Left to right] + // 2. POWER (as an operator, not as a function, i.e. [Left to right] + // as in Matlab and not in C, for example) + // 3. Unary PLUS, Unary MINUS, NOT [Right to left] + // 4. TIMES, DIVIDE [Left to right] + // 5. PLUS, MINUS [Left to right] + // 6. LT, LEQ, GT, GEQ [Left to right] + // 7. EQ, NEQ [Left to right] + // 8. XOR (bitwise) [Left to right] + // 9. AND (logical) [Left to right] + // 10. OR (logical) [Left to right] + // 11. PIECEWISE (as an operator) [Right to left] + + if (isPlusOperator(ast)) { + if (isRelationalOperator(astLeftChild) + || isLogicalOperator(astLeftChild) + || isPiecewiseStatement(astLeftChild)) { + leftCode = "(" + leftCode + ")"; + } + + if (isRelationalOperator(astRightChild) + || isLogicalOperator(astRightChild) + || isPiecewiseStatement(astRightChild)) { + rightCode = "(" + rightCode + ")"; + } + } else if (isMinusOperator(ast)) { + if (isRelationalOperator(astLeftChild) + || isLogicalOperator(astLeftChild) + || isPiecewiseStatement(astLeftChild)) { + leftCode = "(" + leftCode + ")"; + } + + if (isNegativeNumber(astRightChild) + || isRelationalOperator(astRightChild) + || isLogicalOperator(astRightChild) + || isMinusOperator(astRightChild) + || isPiecewiseStatement(astRightChild) + || (rightCode.rfind(mProfile->minusString(), 0) == 0)) { + rightCode = "(" + rightCode + ")"; + } else if (isPlusOperator(astRightChild)) { + if (astRightChild->rightChild() != nullptr) { + rightCode = "(" + rightCode + ")"; + } + } + } else if (isTimesOperator(ast)) { + if (isRelationalOperator(astLeftChild) + || isLogicalOperator(astLeftChild) + || isPiecewiseStatement(astLeftChild)) { + leftCode = "(" + leftCode + ")"; + } else if (isPlusOperator(astLeftChild) + || isMinusOperator(astLeftChild)) { + if (astLeftChild->rightChild() != nullptr) { + leftCode = "(" + leftCode + ")"; + } + } + + if (isRelationalOperator(astRightChild) + || isLogicalOperator(astRightChild) + || isPiecewiseStatement(astRightChild)) { + rightCode = "(" + rightCode + ")"; + } else if (isPlusOperator(astRightChild) + || isMinusOperator(astRightChild)) { + if (astRightChild->rightChild() != nullptr) { + rightCode = "(" + rightCode + ")"; + } + } + } else if (isDivideOperator(ast)) { + if (isRelationalOperator(astLeftChild) + || isLogicalOperator(astLeftChild) + || isPiecewiseStatement(astLeftChild)) { + leftCode = "(" + leftCode + ")"; + } else if (isPlusOperator(astLeftChild) + || isMinusOperator(astLeftChild)) { + if (astLeftChild->rightChild() != nullptr) { + leftCode = "(" + leftCode + ")"; + } + } + + if (isRelationalOperator(astRightChild) + || isLogicalOperator(astRightChild) + || isTimesOperator(astRightChild) + || isDivideOperator(astRightChild) + || isPiecewiseStatement(astRightChild)) { + rightCode = "(" + rightCode + ")"; + } else if (isPlusOperator(astRightChild) + || isMinusOperator(astRightChild)) { + if (astRightChild->rightChild() != nullptr) { + rightCode = "(" + rightCode + ")"; + } + } + } else if (isAndOperator(ast)) { + // Note: according to the precedence rules above, we only need to add parentheses around OR and PIECEWISE. + // However, it looks better/clearer to have some around some other operators (agreed, this is somewhat + // subjective). + + if (isRelationalOperator(astLeftChild) + || isOrOperator(astLeftChild) + || isXorOperator(astLeftChild) + || isPiecewiseStatement(astLeftChild)) { + leftCode = "(" + leftCode + ")"; + } else if (isPlusOperator(astLeftChild) + || isMinusOperator(astLeftChild)) { + if (astLeftChild->rightChild() != nullptr) { + leftCode = "(" + leftCode + ")"; + } + } else if (isPowerOperator(astLeftChild)) { + leftCode = "(" + leftCode + ")"; + } else if (isRootOperator(astLeftChild)) { + leftCode = "(" + leftCode + ")"; + } + + if (isRelationalOperator(astRightChild) + || isOrOperator(astRightChild) + || isXorOperator(astRightChild) + || isPiecewiseStatement(astRightChild)) { + rightCode = "(" + rightCode + ")"; + } else if (isPlusOperator(astRightChild) + || isMinusOperator(astRightChild)) { + if (astRightChild->rightChild() != nullptr) { + rightCode = "(" + rightCode + ")"; + } + } else if (isPowerOperator(astRightChild)) { + rightCode = "(" + rightCode + ")"; + } else if (isRootOperator(astRightChild)) { + rightCode = "(" + rightCode + ")"; + } + } else if (isOrOperator(ast)) { + // Note: according to the precedence rules above, we only need to add parentheses around PIECEWISE. However, it + // looks better/clearer to have some around some other operators (agreed, this is somewhat subjective). + + if (isRelationalOperator(astLeftChild) + || isAndOperator(astLeftChild) + || isXorOperator(astLeftChild) + || isPiecewiseStatement(astLeftChild)) { + leftCode = "(" + leftCode + ")"; + } else if (isPlusOperator(astLeftChild) + || isMinusOperator(astLeftChild)) { + if (astLeftChild->rightChild() != nullptr) { + leftCode = "(" + leftCode + ")"; + } + } else if (isPowerOperator(astLeftChild)) { + leftCode = "(" + leftCode + ")"; + } else if (isRootOperator(astLeftChild)) { + leftCode = "(" + leftCode + ")"; + } + + if (isRelationalOperator(astRightChild) + || isAndOperator(astRightChild) + || isXorOperator(astRightChild) + || isPiecewiseStatement(astRightChild)) { + rightCode = "(" + rightCode + ")"; + } else if (isPlusOperator(astRightChild) + || isMinusOperator(astRightChild)) { + if (astRightChild->rightChild() != nullptr) { + rightCode = "(" + rightCode + ")"; + } + } else if (isPowerOperator(astRightChild)) { + rightCode = "(" + rightCode + ")"; + } else if (isRootOperator(astRightChild)) { + rightCode = "(" + rightCode + ")"; + } + } else if (isXorOperator(ast)) { + // Note: according to the precedence rules above, we only need to add parentheses around AND, OR and PIECEWISE. + // However, it looks better/clearer to have some around some other operators (agreed, this is somewhat + // subjective). + + if (isRelationalOperator(astLeftChild) + || isAndOperator(astLeftChild) + || isOrOperator(astLeftChild) + || isPiecewiseStatement(astLeftChild)) { + leftCode = "(" + leftCode + ")"; + } else if (isPlusOperator(astLeftChild) + || isMinusOperator(astLeftChild)) { + if (astLeftChild->rightChild() != nullptr) { + leftCode = "(" + leftCode + ")"; + } + } else if (isPowerOperator(astLeftChild)) { + leftCode = "(" + leftCode + ")"; + } else if (isRootOperator(astLeftChild)) { + leftCode = "(" + leftCode + ")"; + } + + if (isRelationalOperator(astRightChild) + || isAndOperator(astRightChild) + || isOrOperator(astRightChild) + || isPiecewiseStatement(astRightChild)) { + rightCode = "(" + rightCode + ")"; + } else if (isPlusOperator(astRightChild) + || isMinusOperator(astRightChild)) { + if (astRightChild->rightChild() != nullptr) { + rightCode = "(" + rightCode + ")"; + } + } else if (isPowerOperator(astRightChild)) { + rightCode = "(" + rightCode + ")"; + } else if (isRootOperator(astRightChild)) { + rightCode = "(" + rightCode + ")"; + } + } else if (isPowerOperator(ast)) { + if (isRelationalOperator(astLeftChild) + || isLogicalOperator(astLeftChild) + || isMinusOperator(astLeftChild) + || isTimesOperator(astLeftChild) + || isDivideOperator(astLeftChild) + || isPiecewiseStatement(astLeftChild)) { + leftCode = "(" + leftCode + ")"; + } else if (isPlusOperator(astLeftChild)) { + if (astLeftChild->rightChild() != nullptr) { + leftCode = "(" + leftCode + ")"; + } + } + + if (isRelationalOperator(astRightChild) + || isLogicalOperator(astRightChild) + || isMinusOperator(astLeftChild) + || isTimesOperator(astRightChild) + || isDivideOperator(astRightChild) + || isPowerOperator(astRightChild) + || isRootOperator(astRightChild) + || isPiecewiseStatement(astRightChild)) { + rightCode = "(" + rightCode + ")"; + } else if (isPlusOperator(astRightChild)) { + if (astRightChild->rightChild() != nullptr) { + rightCode = "(" + rightCode + ")"; + } + } + } else if (isRootOperator(ast)) { + if (isRelationalOperator(astRightChild) + || isLogicalOperator(astRightChild) + || isMinusOperator(astRightChild) + || isTimesOperator(astRightChild) + || isDivideOperator(astRightChild) + || isPiecewiseStatement(astRightChild)) { + rightCode = "(" + rightCode + ")"; + } else if (isPlusOperator(astRightChild)) { + if (astRightChild->rightChild() != nullptr) { + rightCode = "(" + rightCode + ")"; + } + } + + auto astLeftChildLeftChild = astLeftChild->leftChild(); + + if (isRelationalOperator(astLeftChildLeftChild) + || isLogicalOperator(astLeftChildLeftChild) + || isMinusOperator(astLeftChildLeftChild) + || isTimesOperator(astLeftChildLeftChild) + || isDivideOperator(astLeftChildLeftChild) + || isPowerOperator(astLeftChildLeftChild) + || isRootOperator(astLeftChildLeftChild) + || isPiecewiseStatement(astLeftChildLeftChild)) { + leftCode = "(" + leftCode + ")"; + } else if (isPlusOperator(astLeftChildLeftChild)) { + if (astLeftChildLeftChild->rightChild() != nullptr) { + leftCode = "(" + leftCode + ")"; + } + } + + return rightCode + op + "(1.0/" + leftCode + ")"; + } + + return leftCode + op + rightCode; +} + +std::string GeneratorInterpreter::GeneratorInterpreterImpl::generateMinusUnaryCode(const AnalyserEquationAstPtr &ast) const +{ + // Generate the code for the left branch of the given AST. + + auto astLeftChild = ast->leftChild(); + auto leftCode = generateCode(astLeftChild); + + // Determine whether parentheses should be added around the left code. + + if (isRelationalOperator(astLeftChild) + || isLogicalOperator(astLeftChild) + || isPlusOperator(astLeftChild) + || isMinusOperator(astLeftChild) + || isPiecewiseStatement(astLeftChild)) { + leftCode = "(" + leftCode + ")"; + } + + return mProfile->minusString() + leftCode; +} + +std::string GeneratorInterpreter::GeneratorInterpreterImpl::generateOneParameterFunctionCode(const std::string &function, + const AnalyserEquationAstPtr &ast) const +{ + return function + "(" + generateCode(ast->leftChild()) + ")"; +} + +std::string GeneratorInterpreter::GeneratorInterpreterImpl::generateTwoParameterFunctionCode(const std::string &function, + const AnalyserEquationAstPtr &ast) const +{ + auto leftCode = generateCode(ast->leftChild()); + auto rightCode = generateCode(ast->rightChild()); + + return function + "(" + leftCode + ", " + rightCode + ")"; +} + +std::string GeneratorInterpreter::GeneratorInterpreterImpl::generatePiecewiseIfCode(const std::string &condition, + const std::string &value) const +{ + return replace(replace(mProfile->hasConditionalOperator() ? + mProfile->conditionalOperatorIfString() : + mProfile->piecewiseIfString(), + "[CONDITION]", condition), + "[IF_STATEMENT]", value); +} + +std::string GeneratorInterpreter::GeneratorInterpreterImpl::generatePiecewiseElseCode(const std::string &value) const +{ + return replace(mProfile->hasConditionalOperator() ? + mProfile->conditionalOperatorElseString() : + mProfile->piecewiseElseString(), + "[ELSE_STATEMENT]", value); +} + +std::string GeneratorInterpreter::GeneratorInterpreterImpl::generateCode(const AnalyserEquationAstPtr &ast) const +{ + // Make sure that we have an AST to work on. + + if (ast == nullptr) { + return {}; + } + + // Generate the code for the given AST. + // Note: AnalyserEquationAst::Type::BVAR is only relevant when there is no model (in which case we want to generate + // something like dx/dt, as is in the case of the analyser when we want to mention an equation) since + // otherwise we don't need to generate any code for it (since we will, instead, want to generate something + // like rates[0]). + + std::string code; + + switch (ast->type()) { + case AnalyserEquationAst::Type::EQUALITY: + code = generateOperatorCode(mProfile->equalityString(), ast); + + break; + case AnalyserEquationAst::Type::EQ: + if (mProfile->hasEqOperator()) { + code = generateOperatorCode(mProfile->eqString(), ast); + } else { + code = generateTwoParameterFunctionCode(mProfile->eqString(), ast); + } + + break; + case AnalyserEquationAst::Type::NEQ: + if (mProfile->hasNeqOperator()) { + code = generateOperatorCode(mProfile->neqString(), ast); + } else { + code = generateTwoParameterFunctionCode(mProfile->neqString(), ast); + } + + break; + case AnalyserEquationAst::Type::LT: + if (mProfile->hasLtOperator()) { + code = generateOperatorCode(mProfile->ltString(), ast); + } else { + code = generateTwoParameterFunctionCode(mProfile->ltString(), ast); + } + + break; + case AnalyserEquationAst::Type::LEQ: + if (mProfile->hasLeqOperator()) { + code = generateOperatorCode(mProfile->leqString(), ast); + } else { + code = generateTwoParameterFunctionCode(mProfile->leqString(), ast); + } + + break; + case AnalyserEquationAst::Type::GT: + if (mProfile->hasGtOperator()) { + code = generateOperatorCode(mProfile->gtString(), ast); + } else { + code = generateTwoParameterFunctionCode(mProfile->gtString(), ast); + } + + break; + case AnalyserEquationAst::Type::GEQ: + if (mProfile->hasGeqOperator()) { + code = generateOperatorCode(mProfile->geqString(), ast); + } else { + code = generateTwoParameterFunctionCode(mProfile->geqString(), ast); + } + + break; + case AnalyserEquationAst::Type::AND: + if (mProfile->hasAndOperator()) { + code = generateOperatorCode(mProfile->andString(), ast); + } else { + code = generateTwoParameterFunctionCode(mProfile->andString(), ast); + } + + break; + case AnalyserEquationAst::Type::OR: + if (mProfile->hasOrOperator()) { + code = generateOperatorCode(mProfile->orString(), ast); + } else { + code = generateTwoParameterFunctionCode(mProfile->orString(), ast); + } + + break; + case AnalyserEquationAst::Type::XOR: + if (mProfile->hasXorOperator()) { + code = generateOperatorCode(mProfile->xorString(), ast); + } else { + code = generateTwoParameterFunctionCode(mProfile->xorString(), ast); + } + + break; + case AnalyserEquationAst::Type::NOT: + if (mProfile->hasNotOperator()) { + code = mProfile->notString() + generateCode(ast->leftChild()); + } else { + code = generateOneParameterFunctionCode(mProfile->notString(), ast); + } + + break; + case AnalyserEquationAst::Type::PLUS: + if (ast->rightChild() != nullptr) { + code = generateOperatorCode(mProfile->plusString(), ast); + } else { + code = generateCode(ast->leftChild()); + } + + break; + case AnalyserEquationAst::Type::MINUS: + code = (ast->rightChild() != nullptr) ? + generateOperatorCode(mProfile->minusString(), ast) : + generateMinusUnaryCode(ast); + + break; + case AnalyserEquationAst::Type::TIMES: + code = generateOperatorCode(mProfile->timesString(), ast); + + break; + case AnalyserEquationAst::Type::DIVIDE: + code = generateOperatorCode(mProfile->divideString(), ast); + + break; + case AnalyserEquationAst::Type::POWER: { + auto rightCode = generateCode(ast->rightChild()); + double doubleValue; + auto validConversion = convertToDouble(rightCode, doubleValue); + + if (validConversion && areEqual(doubleValue, 0.5)) { + code = mProfile->squareRootString() + "(" + generateCode(ast->leftChild()) + ")"; + } else if (validConversion && areEqual(doubleValue, 2.0) + && !mProfile->squareString().empty()) { + code = mProfile->squareString() + "(" + generateCode(ast->leftChild()) + ")"; + } else if (mProfile->hasPowerOperator()) { + code = generateOperatorCode(mProfile->powerString(), ast); + } else { + code = mProfile->powerString() + "(" + generateCode(ast->leftChild()) + ", " + rightCode + ")"; + } + } break; + case AnalyserEquationAst::Type::ROOT: { + auto astRightChild = ast->rightChild(); + + if (astRightChild != nullptr) { + auto astLeftChild = ast->leftChild(); + auto leftCode = generateCode(astLeftChild); + double doubleValue; + auto validConversion = convertToDouble(leftCode, doubleValue); + + if (validConversion && areEqual(doubleValue, 2.0)) { + code = mProfile->squareRootString() + "(" + generateCode(astRightChild) + ")"; + } else if (validConversion && areEqual(doubleValue, 0.5) + && !mProfile->squareString().empty()) { + code = mProfile->squareString() + "(" + generateCode(astRightChild) + ")"; + } else if (mProfile->hasPowerOperator()) { + code = generateOperatorCode(mProfile->powerString(), ast); + } else { + auto inverseValueAst = AnalyserEquationAst::create(); + + inverseValueAst->setType(AnalyserEquationAst::Type::DIVIDE); + inverseValueAst->setParent(ast); + + auto inverseValueAstLeftChild = AnalyserEquationAst::create(); + + inverseValueAstLeftChild->setType(AnalyserEquationAst::Type::CN); + inverseValueAstLeftChild->setValue("1.0"); + inverseValueAstLeftChild->setParent(inverseValueAst); + + inverseValueAst->setLeftChild(inverseValueAstLeftChild); + inverseValueAst->setRightChild(astLeftChild->leftChild()); + + code = mProfile->powerString() + "(" + generateCode(astRightChild) + ", " + generateOperatorCode(mProfile->divideString(), inverseValueAst) + ")"; + } + } else { + code = mProfile->squareRootString() + "(" + generateCode(ast->leftChild()) + ")"; + } + } break; + case AnalyserEquationAst::Type::ABS: + code = generateOneParameterFunctionCode(mProfile->absoluteValueString(), ast); + + break; + case AnalyserEquationAst::Type::EXP: + code = generateOneParameterFunctionCode(mProfile->exponentialString(), ast); + + break; + case AnalyserEquationAst::Type::LN: + code = generateOneParameterFunctionCode(mProfile->naturalLogarithmString(), ast); + + break; + case AnalyserEquationAst::Type::LOG: { + auto astRightChild = ast->rightChild(); + + if (astRightChild != nullptr) { + auto leftCode = generateCode(ast->leftChild()); + double doubleValue; + auto rightCode = generateCode(astRightChild); + + if (convertToDouble(leftCode, doubleValue) + && areEqual(doubleValue, 10.0)) { + code = mProfile->commonLogarithmString() + "(" + rightCode + ")"; + } else { + code = mProfile->naturalLogarithmString() + "(" + rightCode + ")/" + mProfile->naturalLogarithmString() + "(" + leftCode + ")"; + } + } else { + code = generateOneParameterFunctionCode(mProfile->commonLogarithmString(), ast); + } + } break; + case AnalyserEquationAst::Type::CEILING: + code = generateOneParameterFunctionCode(mProfile->ceilingString(), ast); + + break; + case AnalyserEquationAst::Type::FLOOR: + code = generateOneParameterFunctionCode(mProfile->floorString(), ast); + + break; + case AnalyserEquationAst::Type::MIN: + code = generateTwoParameterFunctionCode(mProfile->minString(), ast); + + break; + case AnalyserEquationAst::Type::MAX: + code = generateTwoParameterFunctionCode(mProfile->maxString(), ast); + + break; + case AnalyserEquationAst::Type::REM: + code = generateTwoParameterFunctionCode(mProfile->remString(), ast); + + break; + case AnalyserEquationAst::Type::DIFF: + if (mModel != nullptr) { + code = generateCode(ast->rightChild()); + } else { + code = "d" + generateCode(ast->rightChild()) + "/d" + generateCode(ast->leftChild()); + } + + break; + case AnalyserEquationAst::Type::SIN: + code = generateOneParameterFunctionCode(mProfile->sinString(), ast); + + break; + case AnalyserEquationAst::Type::COS: + code = generateOneParameterFunctionCode(mProfile->cosString(), ast); + + break; + case AnalyserEquationAst::Type::TAN: + code = generateOneParameterFunctionCode(mProfile->tanString(), ast); + + break; + case AnalyserEquationAst::Type::SEC: + code = generateOneParameterFunctionCode(mProfile->secString(), ast); + + break; + case AnalyserEquationAst::Type::CSC: + code = generateOneParameterFunctionCode(mProfile->cscString(), ast); + + break; + case AnalyserEquationAst::Type::COT: + code = generateOneParameterFunctionCode(mProfile->cotString(), ast); + + break; + case AnalyserEquationAst::Type::SINH: + code = generateOneParameterFunctionCode(mProfile->sinhString(), ast); + + break; + case AnalyserEquationAst::Type::COSH: + code = generateOneParameterFunctionCode(mProfile->coshString(), ast); + + break; + case AnalyserEquationAst::Type::TANH: + code = generateOneParameterFunctionCode(mProfile->tanhString(), ast); + + break; + case AnalyserEquationAst::Type::SECH: + code = generateOneParameterFunctionCode(mProfile->sechString(), ast); + + break; + case AnalyserEquationAst::Type::CSCH: + code = generateOneParameterFunctionCode(mProfile->cschString(), ast); + + break; + case AnalyserEquationAst::Type::COTH: + code = generateOneParameterFunctionCode(mProfile->cothString(), ast); + + break; + case AnalyserEquationAst::Type::ASIN: + code = generateOneParameterFunctionCode(mProfile->asinString(), ast); + + break; + case AnalyserEquationAst::Type::ACOS: + code = generateOneParameterFunctionCode(mProfile->acosString(), ast); + + break; + case AnalyserEquationAst::Type::ATAN: + code = generateOneParameterFunctionCode(mProfile->atanString(), ast); + + break; + case AnalyserEquationAst::Type::ASEC: + code = generateOneParameterFunctionCode(mProfile->asecString(), ast); + + break; + case AnalyserEquationAst::Type::ACSC: + code = generateOneParameterFunctionCode(mProfile->acscString(), ast); + + break; + case AnalyserEquationAst::Type::ACOT: + code = generateOneParameterFunctionCode(mProfile->acotString(), ast); + + break; + case AnalyserEquationAst::Type::ASINH: + code = generateOneParameterFunctionCode(mProfile->asinhString(), ast); + + break; + case AnalyserEquationAst::Type::ACOSH: + code = generateOneParameterFunctionCode(mProfile->acoshString(), ast); + + break; + case AnalyserEquationAst::Type::ATANH: + code = generateOneParameterFunctionCode(mProfile->atanhString(), ast); + + break; + case AnalyserEquationAst::Type::ASECH: + code = generateOneParameterFunctionCode(mProfile->asechString(), ast); + + break; + case AnalyserEquationAst::Type::ACSCH: + code = generateOneParameterFunctionCode(mProfile->acschString(), ast); + + break; + case AnalyserEquationAst::Type::ACOTH: + code = generateOneParameterFunctionCode(mProfile->acothString(), ast); + + break; + case AnalyserEquationAst::Type::PIECEWISE: { + auto astLeftChild = ast->leftChild(); + auto astRightChild = ast->rightChild(); + auto leftCode = generateCode(astLeftChild); + auto rightCode = generateCode(astRightChild); + + if (astRightChild != nullptr) { + if (astRightChild->type() == AnalyserEquationAst::Type::PIECE) { + code = leftCode + generatePiecewiseElseCode(rightCode + generatePiecewiseElseCode(mProfile->nanString())); + } else { + code = leftCode + generatePiecewiseElseCode(rightCode); + } + } else if (astLeftChild != nullptr) { + if (astLeftChild->type() == AnalyserEquationAst::Type::PIECE) { + code = leftCode + generatePiecewiseElseCode(mProfile->nanString()); + } else { + code = leftCode; + } + } else { + code = mProfile->nanString(); + } + } break; + case AnalyserEquationAst::Type::PIECE: { + auto leftCode = generateCode(ast->leftChild()); + auto rightCode = generateCode(ast->rightChild()); + + code = generatePiecewiseIfCode(rightCode, leftCode); + } break; + case AnalyserEquationAst::Type::OTHERWISE: { + code = generateCode(ast->leftChild()); + } break; + case AnalyserEquationAst::Type::CI: { + auto variable = ast->variable(); + bool rate = ast->parent()->type() == AnalyserEquationAst::Type::DIFF; + + code = generateVariableNameCode(variable, rate); + } break; + case AnalyserEquationAst::Type::CN: { + double doubleValue; + + convertToDouble(ast->value(), doubleValue); + + code = generateDoubleCode(ast->value()); + } break; + case AnalyserEquationAst::Type::DEGREE: + case AnalyserEquationAst::Type::LOGBASE: { + code = generateCode(ast->leftChild()); + } break; + case AnalyserEquationAst::Type::BVAR: { + code = generateCode(ast->leftChild()); + } break; + case AnalyserEquationAst::Type::TRUE: + code = mProfile->trueString(); + + break; + case AnalyserEquationAst::Type::FALSE: + code = mProfile->falseString(); + + break; + case AnalyserEquationAst::Type::E: + code = mProfile->eString(); + + break; + case AnalyserEquationAst::Type::PI: + code = mProfile->piString(); + + break; + case AnalyserEquationAst::Type::INF: + code = mProfile->infString(); + + break; + default: // AnalyserEquationAst::Type::NAN. + code = mProfile->nanString(); + + break; + } + + return code; +} + +bool GeneratorInterpreter::GeneratorInterpreterImpl::isToBeComputedAgain(const AnalyserEquationPtr &equation) const +{ + // NLA and algebraic equations that are state/rate-based and external equations are to be computed again (in the + // computeVariables() method). + + switch (equation->type()) { + case AnalyserEquation::Type::NLA: + case AnalyserEquation::Type::ALGEBRAIC: + return equation->isStateRateBased(); + case AnalyserEquation::Type::EXTERNAL: + return true; + default: + return false; + } +} + +bool GeneratorInterpreter::GeneratorInterpreterImpl::isSomeConstant(const AnalyserEquationPtr &equation, + bool includeComputedConstants) const +{ + auto type = equation->type(); + + return (type == AnalyserEquation::Type::TRUE_CONSTANT) + || (!includeComputedConstants && (type == AnalyserEquation::Type::VARIABLE_BASED_CONSTANT)); +} + +std::string GeneratorInterpreter::GeneratorInterpreterImpl::generateZeroInitialisationCode(const AnalyserVariablePtr &variable) +{ + bool rate = variable->type() == AnalyserVariable::Type::STATE; + + return mProfile->indentString() + + generateVariableNameCode(variable->variable(), rate) + + mProfile->equalityString() + + "0.0" + + mProfile->commandSeparatorString() + "\n"; +} + +std::string GeneratorInterpreter::GeneratorInterpreterImpl::generateInitialisationCode(const AnalyserVariablePtr &variable) +{ + // Determine whether the initialising variable has an initial value per se or if it is initialised by another + // variable. + + auto initialisingVariable = variable->initialisingVariable(); + std::string initialValueCode; + + if (isCellMLReal(initialisingVariable->initialValue())) { + initialValueCode = generateDoubleCode(initialisingVariable->initialValue()); + } else { + auto initialValueVariable = owningComponent(initialisingVariable)->variable(initialisingVariable->initialValue()); + auto analyserInitialValueVariable = analyserVariable(mModel, initialValueVariable); + + initialValueCode = mProfile->constantsArrayString() + mProfile->openArrayString() + convertToString(analyserInitialValueVariable->index()) + mProfile->closeArrayString(); + } + + // Determine the scaling factor, if any. + + auto scalingFactor = GeneratorInterpreter::GeneratorInterpreterImpl::scalingFactor(initialisingVariable); + + if (!areNearlyEqual(scalingFactor, 1.0)) { + initialValueCode = generateDoubleCode(convertToString(scalingFactor)) + mProfile->timesString() + initialValueCode; + } + + return mProfile->indentString() + + generateVariableNameCode(variable->variable()) + + mProfile->equalityString() + + initialValueCode + + mProfile->commandSeparatorString() + "\n"; +} + +std::string GeneratorInterpreter::GeneratorInterpreterImpl::generateEquationCode(const AnalyserEquationPtr &equation, + std::vector &remainingEquations, + std::vector &equationsForDependencies, + bool includeComputedConstants) +{ + std::string res; + + if (std::find(remainingEquations.begin(), remainingEquations.end(), equation) != remainingEquations.end()) { + // Stop tracking the equation and its NLA siblings, if any. + // Note: we need to do this as soon as possible to avoid recursive calls, something that would happen if we were + // to do this at the end of this if statement. + + remainingEquations.erase(std::find(remainingEquations.begin(), remainingEquations.end(), equation)); + + for (const auto &nlaSibling : equation->nlaSiblings()) { + remainingEquations.erase(std::find(remainingEquations.begin(), remainingEquations.end(), nlaSibling)); + } + + // Generate any dependency that this equation may have. + + if (!isSomeConstant(equation, includeComputedConstants)) { + for (const auto &dependency : equation->dependencies()) { + if ((dependency->type() != AnalyserEquation::Type::ODE) + && !isSomeConstant(dependency, includeComputedConstants) + && (equationsForDependencies.empty() + || isToBeComputedAgain(dependency) + || (std::find(equationsForDependencies.begin(), equationsForDependencies.end(), dependency) != equationsForDependencies.end()))) { + res += generateEquationCode(dependency, remainingEquations, equationsForDependencies, includeComputedConstants); + } + } + } + + // Generate the equation code itself, based on the equation type. + + switch (equation->type()) { + case AnalyserEquation::Type::EXTERNAL: + for (const auto &variable : variables(equation)) { + res += mProfile->indentString() + + generateVariableNameCode(variable->variable()) + + mProfile->equalityString() + + replace(mProfile->externalVariableMethodCallString(mModelHasOdes), + "[INDEX]", convertToString(variable->index())) + + mProfile->commandSeparatorString() + "\n"; + } + + break; + case AnalyserEquation::Type::NLA: + if (!mProfile->findRootCallString(mModelHasOdes, mModel->hasExternalVariables()).empty()) { + res += mProfile->indentString() + + replace(mProfile->findRootCallString(mModelHasOdes, mModel->hasExternalVariables()), + "[INDEX]", convertToString(equation->nlaSystemIndex())); + } + + break; + default: + res += mProfile->indentString() + generateCode(equation->ast()) + mProfile->commandSeparatorString() + "\n"; + + break; + } + } + + return res; +} + +std::string GeneratorInterpreter::GeneratorInterpreterImpl::generateEquationCode(const AnalyserEquationPtr &equation, + std::vector &remainingEquations) +{ + std::vector dummyEquationsForComputeVariables; + + return generateEquationCode(equation, remainingEquations, dummyEquationsForComputeVariables, true); +} + +void GeneratorInterpreter::GeneratorInterpreterImpl::addNlaSystemsCode() +{ + if (mModelHasNlas + && !mProfile->objectiveFunctionMethodString(mModelHasOdes, mModel->hasExternalVariables()).empty() + && !mProfile->findRootMethodString(mModelHasOdes, mModel->hasExternalVariables()).empty() + && !mProfile->nlaSolveCallString(mModelHasOdes, mModel->hasExternalVariables()).empty()) { + // Note: only states and algebraic variables can be computed through an NLA system. Constants, computed + // constants, and external variables cannot, by definition, be computed through an NLA system. + + std::vector handledNlaEquations; + + for (const auto &equation : mModel->equations()) { + if ((equation->type() == AnalyserEquation::Type::NLA) + && (std::find(handledNlaEquations.begin(), handledNlaEquations.end(), equation) == handledNlaEquations.end())) { + std::string methodBody; + auto i = MAX_SIZE_T; + auto variables = libcellml::variables(equation); + + for (const auto &variable : variables) { + auto arrayString = (variable->type() == AnalyserVariable::Type::STATE) ? + mProfile->ratesArrayString() : + mProfile->algebraicArrayString(); + + methodBody += mProfile->indentString() + + arrayString + mProfile->openArrayString() + convertToString(variable->index()) + mProfile->closeArrayString() + + mProfile->equalityString() + + mProfile->uArrayString() + mProfile->openArrayString() + convertToString(++i) + mProfile->closeArrayString() + + mProfile->commandSeparatorString() + "\n"; + } + + methodBody += newLineIfNeeded(mCode); + + i = MAX_SIZE_T; + + methodBody += mProfile->indentString() + + mProfile->fArrayString() + mProfile->openArrayString() + convertToString(++i) + mProfile->closeArrayString() + + mProfile->equalityString() + + generateCode(equation->ast()) + + mProfile->commandSeparatorString() + "\n"; + + handledNlaEquations.push_back(equation); + + for (const auto &nlaSibling : equation->nlaSiblings()) { + methodBody += mProfile->indentString() + + mProfile->fArrayString() + mProfile->openArrayString() + convertToString(++i) + mProfile->closeArrayString() + + mProfile->equalityString() + + generateCode(nlaSibling->ast()) + + mProfile->commandSeparatorString() + "\n"; + + handledNlaEquations.push_back(nlaSibling); + } + + mCode += newLineIfNeeded(mCode) + + replace(replace(mProfile->objectiveFunctionMethodString(mModelHasOdes, mModel->hasExternalVariables()), + "[INDEX]", convertToString(equation->nlaSystemIndex())), + "[CODE]", generateMethodBodyCode(methodBody)); + + methodBody = {}; + + i = MAX_SIZE_T; + + for (const auto &variable : variables) { + auto arrayString = (variable->type() == AnalyserVariable::Type::STATE) ? + mProfile->ratesArrayString() : + mProfile->algebraicArrayString(); + + methodBody += mProfile->indentString() + + mProfile->uArrayString() + mProfile->openArrayString() + convertToString(++i) + mProfile->closeArrayString() + + mProfile->equalityString() + + arrayString + mProfile->openArrayString() + convertToString(variable->index()) + mProfile->closeArrayString() + + mProfile->commandSeparatorString() + "\n"; + } + + auto variablesCount = variables.size(); + + methodBody += newLineIfNeeded(mCode) + + mProfile->indentString() + + replace(replace(mProfile->nlaSolveCallString(mModelHasOdes, mModel->hasExternalVariables()), + "[INDEX]", convertToString(equation->nlaSystemIndex())), + "[SIZE]", convertToString(variablesCount)); + + methodBody += newLineIfNeeded(mCode); + + i = MAX_SIZE_T; + + for (const auto &variable : variables) { + auto arrayString = (variable->type() == AnalyserVariable::Type::STATE) ? + mProfile->ratesArrayString() : + mProfile->algebraicArrayString(); + + methodBody += mProfile->indentString() + + arrayString + mProfile->openArrayString() + convertToString(variable->index()) + mProfile->closeArrayString() + + mProfile->equalityString() + + mProfile->uArrayString() + mProfile->openArrayString() + convertToString(++i) + mProfile->closeArrayString() + + mProfile->commandSeparatorString() + "\n"; + } + + mCode += newLineIfNeeded(mCode) + + replace(replace(replace(mProfile->findRootMethodString(mModelHasOdes, mModel->hasExternalVariables()), + "[INDEX]", convertToString(equation->nlaSystemIndex())), + "[SIZE]", convertToString(variablesCount)), + "[CODE]", generateMethodBodyCode(methodBody)); + } + } + } +} + +std::string GeneratorInterpreter::GeneratorInterpreterImpl::generateConstantInitialisationCode(const std::vector::iterator constant, + std::vector &remainingConstants) +{ + auto initialisingVariable = (*constant)->initialisingVariable(); + auto initialValue = initialisingVariable->initialValue(); + + if (!isCellMLReal(initialValue)) { + auto initialisingComponent = owningComponent(initialisingVariable); + auto crtConstant = std::find_if(remainingConstants.begin(), remainingConstants.end(), + [=](const AnalyserVariablePtr &av) -> bool { + return initialisingComponent->variable(initialValue) == av->variable(); + }); + + if (crtConstant != remainingConstants.end()) { + return generateConstantInitialisationCode(crtConstant, remainingConstants); + } + } + + auto code = generateInitialisationCode(*constant); + + remainingConstants.erase(constant); + + return code; +} + +void GeneratorInterpreter::GeneratorInterpreterImpl::initialiseVariables(std::vector &remainingEquations) +{ + auto implementationInitialiseVariablesMethodString = mProfile->implementationInitialiseVariablesMethodString(mModelHasOdes); + + if (!implementationInitialiseVariablesMethodString.empty()) { + // Initialise our states (after, if needed, initialising the constant on which it depends). + + std::string methodBody; + auto constants = mModel->constants(); + + for (const auto &state : mModel->states()) { + auto initialisingVariable = state->initialisingVariable(); + auto initialValue = initialisingVariable->initialValue(); + + if (!isCellMLReal(initialValue)) { + // The initial value references a constant. + + auto initialisingComponent = owningComponent(initialisingVariable); + auto constant = std::find_if(constants.begin(), constants.end(), + [=](const AnalyserVariablePtr &av) -> bool { + return initialisingComponent->variable(initialValue)->hasEquivalentVariable(av->variable()); + }); + + methodBody += generateConstantInitialisationCode(constant, constants); + } + + methodBody += generateInitialisationCode(state); + } + + // Use an initial guess of zero for rates computed using an NLA system (see the note below). + + for (const auto &state : mModel->states()) { + if (state->equation(0)->type() == AnalyserEquation::Type::NLA) { + methodBody += generateZeroInitialisationCode(state); + } + } + + // Initialise our (remaining) constants. + + while (!constants.empty()) { + methodBody += generateConstantInitialisationCode(constants.begin(), constants); + } + + // Initialise our computed constants that are initialised using an equation (e.g., x = 3 rather than x with an + // initial value of 3). + + auto equations = mModel->equations(); + + for (const auto &equation : equations) { + if (equation->type() == AnalyserEquation::Type::TRUE_CONSTANT) { + methodBody += generateEquationCode(equation, remainingEquations); + } + } + + // Initialise our algebraic variables that have an initial value. Also use an initial guess of zero for + // algebraic variables computed using an NLA system. + // Note: a variable which is the only unknown in an equation, but which is not on its own on either the LHS or + // RHS of that equation (e.g., x = y+z with x and y known and z unknown) is (currently) to be computed + // using an NLA system for which we need an initial guess. We use an initial guess of zero, which is fine + // since such an NLA system has only one solution. + + for (const auto &algebraic : mModel->algebraic()) { + if (algebraic->initialisingVariable() != nullptr) { + methodBody += generateInitialisationCode(algebraic); + } else if (algebraic->equation(0)->type() == AnalyserEquation::Type::NLA) { + methodBody += generateZeroInitialisationCode(algebraic); + } + } + + mCode += newLineIfNeeded(mCode) + + replace(implementationInitialiseVariablesMethodString, + "[CODE]", generateMethodBodyCode(methodBody)); + } +} + +void GeneratorInterpreter::GeneratorInterpreterImpl::computeComputedConstants(std::vector &remainingEquations) +{ + if (!mProfile->implementationComputeComputedConstantsMethodString().empty()) { + std::string methodBody; + + for (const auto &equation : mModel->equations()) { + if (equation->type() == AnalyserEquation::Type::VARIABLE_BASED_CONSTANT) { + methodBody += generateEquationCode(equation, remainingEquations); + } + } + + mCode += newLineIfNeeded(mCode) + + replace(mProfile->implementationComputeComputedConstantsMethodString(), + "[CODE]", generateMethodBodyCode(methodBody)); + } +} + +void GeneratorInterpreter::GeneratorInterpreterImpl::computeRates(std::vector &remainingEquations) +{ + auto implementationComputeRatesMethodString = mProfile->implementationComputeRatesMethodString(mModel->hasExternalVariables()); + + if (mModelHasOdes + && !implementationComputeRatesMethodString.empty()) { + std::string methodBody; + + for (const auto &equation : mModel->equations()) { + // A rate is computed either through an ODE equation or through an NLA equation in case the rate is not on + // its own on either the LHS or RHS of the equation. + + auto variables = libcellml::variables(equation); + + if ((equation->type() == AnalyserEquation::Type::ODE) + || ((equation->type() == AnalyserEquation::Type::NLA) + && (variables.size() == 1) + && (variables[0]->type() == AnalyserVariable::Type::STATE))) { + methodBody += generateEquationCode(equation, remainingEquations); + } + } + + mCode += newLineIfNeeded(mCode) + + replace(implementationComputeRatesMethodString, + "[CODE]", generateMethodBodyCode(methodBody)); + } +} + +void GeneratorInterpreter::GeneratorInterpreterImpl::computeVariables(std::vector &remainingEquations) +{ + auto implementationComputeVariablesMethodString = mProfile->implementationComputeVariablesMethodString(mModelHasOdes, + mModel->hasExternalVariables()); + + if (!implementationComputeVariablesMethodString.empty()) { + std::string methodBody; + auto equations = mModel->equations(); + std::vector newRemainingEquations {std::begin(equations), std::end(equations)}; + + for (const auto &equation : equations) { + if ((std::find(remainingEquations.begin(), remainingEquations.end(), equation) != remainingEquations.end()) + || isToBeComputedAgain(equation)) { + methodBody += generateEquationCode(equation, newRemainingEquations, remainingEquations, false); + } + } + + mCode += newLineIfNeeded(mCode) + + replace(implementationComputeVariablesMethodString, + "[CODE]", generateMethodBodyCode(methodBody)); + } +} + +GeneratorInterpreter::GeneratorInterpreter(const AnalyserModelPtr &model, const GeneratorProfilePtr &profile, + const std::string &code) + : mPimpl(new GeneratorInterpreterImpl(model, profile, code)) +{ +} + +GeneratorInterpreter::GeneratorInterpreter(const AnalyserEquationAstPtr &ast, const GeneratorProfilePtr &profile) + : mPimpl(new GeneratorInterpreterImpl(ast, profile)) +{ +} + +GeneratorInterpreter::~GeneratorInterpreter() +{ + delete mPimpl; +} + +GeneratorInterpreterPtr GeneratorInterpreter::create(const AnalyserModelPtr &model, const GeneratorProfilePtr &profile, + const std::string &code) noexcept +{ + return std::shared_ptr {new GeneratorInterpreter {model, profile, code}}; +} + +GeneratorInterpreterPtr GeneratorInterpreter::create(const AnalyserEquationAstPtr &ast, + const GeneratorProfilePtr &profile) noexcept +{ + return std::shared_ptr {new GeneratorInterpreter {ast, profile}}; +} + +std::string GeneratorInterpreter::code() const +{ + return mPimpl->mCode; +} + +} // namespace libcellml diff --git a/src/generatorinterpreter.h b/src/generatorinterpreter.h new file mode 100644 index 0000000000..9c54e13732 --- /dev/null +++ b/src/generatorinterpreter.h @@ -0,0 +1,92 @@ +/* +Copyright libCellML Contributors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +#pragma once + +#include "libcellml/analyserequation.h" + +namespace libcellml { + +class GeneratorInterpreter; /**< Forward declaration of GeneratorInterpreter class. */ +using GeneratorInterpreterPtr = std::shared_ptr; /**< Type definition for shared GeneratorInterpreter pointer. */ + +/** + * @brief The GeneratorInterpreter class. + * + * The GeneratorInterpreter class is used by the Generator and Interpreter classes to generate the code to compute a + * model. + */ +class GeneratorInterpreter +{ +public: + ~GeneratorInterpreter(); /**< Destructor, @private. */ + GeneratorInterpreter(const GeneratorInterpreter &rhs) = delete; /**< Copy constructor, @private. */ + GeneratorInterpreter(GeneratorInterpreter &&rhs) noexcept = delete; /**< Move constructor, @private. */ + GeneratorInterpreter &operator=(GeneratorInterpreter rhs) = delete; /**< Assignment operator, @private. */ + + /** + * @brief Create an @ref GeneratorInterpreter object. + * + * Factory method to create an @ref GeneratorInterpreter. Create a generator-interpreter with:: + * + * @code + * auto interpreterStatement = libcellml::GeneratorInterpreter::create(model, profile, code); + * @endcode + * + * @param model The model for which we want to generate the code to compute. + * @param profile The profile to be used to generate the code to compute. + * @param code The code that has already been generated. + * + * @return A smart pointer to an @ref GeneratorInterpreter object. + */ + static GeneratorInterpreterPtr create(const AnalyserModelPtr &model, const GeneratorProfilePtr &profile, + const std::string &code) noexcept; + + /** + * @brief Create an @ref GeneratorInterpreter object. + * + * Factory method to create an @ref GeneratorInterpreter. Create a generator-interpreter with:: + * + * @code + * auto interpreterStatement = libcellml::GeneratorInterpreter::create(profile); + * @endcode + * + * @param ast The AST for which we want to generate some code. + * @param profile The profile to be used to generate some code. + * + * @return A smart pointer to an @ref GeneratorInterpreter object. + */ + static GeneratorInterpreterPtr create(const AnalyserEquationAstPtr &ast, + const GeneratorProfilePtr &profile) noexcept; + + /** + * @brief Get the code to compute the model. + * + * Get the @c std::string code to compute the model. + * + * @return The @c std::string code to compute the model. + */ + std::string code() const; + +private: + GeneratorInterpreter(const AnalyserModelPtr &model, const GeneratorProfilePtr &profile, const std::string &code); /**< Constructor, @private. */ + GeneratorInterpreter(const AnalyserEquationAstPtr &ast, const GeneratorProfilePtr &profile); /**< Constructor, @private. */ + + struct GeneratorInterpreterImpl; + GeneratorInterpreterImpl *mPimpl; /**< Private member to implementation pointer, @private. */ +}; + +} // namespace libcellml diff --git a/src/generatorinterpreter_p.h b/src/generatorinterpreter_p.h new file mode 100644 index 0000000000..ff00b80187 --- /dev/null +++ b/src/generatorinterpreter_p.h @@ -0,0 +1,108 @@ +/* +Copyright libCellML Contributors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +#pragma once + +#include "generatorinterpreter.h" + +#include "libcellml/generatorprofile.h" + +namespace libcellml { + +bool modelHasOdes(const AnalyserModelPtr &model); +bool modelHasNlas(const AnalyserModelPtr &model); + +AnalyserVariablePtr analyserVariable(const AnalyserModelPtr &model, const VariablePtr &variable); + +std::string newLineIfNeeded(const std::string &code); + +std::string generateDoubleCode(const std::string &value); + +/** + * @brief The GeneratorInterpreter::GeneratorInterpreterImpl struct. + * + * The private implementation for the GeneratorInterpreter class. + */ +struct GeneratorInterpreter::GeneratorInterpreterImpl +{ + AnalyserModelPtr mModel; + bool mModelHasOdes = false; + bool mModelHasNlas = false; + + GeneratorProfilePtr mProfile = GeneratorProfile::create(); + std::string mCode; + + explicit GeneratorInterpreterImpl(const AnalyserModelPtr &model, const GeneratorProfilePtr &profile, + const std::string &code); + explicit GeneratorInterpreterImpl(const AnalyserEquationAstPtr &ast, const GeneratorProfilePtr &profile); + + void initialise(const AnalyserModelPtr &model, const GeneratorProfilePtr &profile, const std::string &code); + + double scalingFactor(const VariablePtr &variable) const; + + bool isNegativeNumber(const AnalyserEquationAstPtr &ast) const; + + bool isRelationalOperator(const AnalyserEquationAstPtr &ast) const; + bool isAndOperator(const AnalyserEquationAstPtr &ast) const; + bool isOrOperator(const AnalyserEquationAstPtr &ast) const; + bool isXorOperator(const AnalyserEquationAstPtr &ast) const; + bool isLogicalOperator(const AnalyserEquationAstPtr &ast) const; + bool isPlusOperator(const AnalyserEquationAstPtr &ast) const; + bool isMinusOperator(const AnalyserEquationAstPtr &ast) const; + bool isTimesOperator(const AnalyserEquationAstPtr &ast) const; + bool isDivideOperator(const AnalyserEquationAstPtr &ast) const; + bool isPowerOperator(const AnalyserEquationAstPtr &ast) const; + bool isRootOperator(const AnalyserEquationAstPtr &ast) const; + bool isPiecewiseStatement(const AnalyserEquationAstPtr &ast) const; + + std::string generateMethodBodyCode(const std::string &methodBody) const; + + std::string generateVariableNameCode(const VariablePtr &variable, + bool rate = false) const; + + std::string generateOperatorCode(const std::string &op, const AnalyserEquationAstPtr &ast) const; + std::string generateMinusUnaryCode(const AnalyserEquationAstPtr &ast) const; + std::string generateOneParameterFunctionCode(const std::string &function, const AnalyserEquationAstPtr &ast) const; + std::string generateTwoParameterFunctionCode(const std::string &function, const AnalyserEquationAstPtr &ast) const; + std::string generatePiecewiseIfCode(const std::string &condition, + const std::string &value) const; + std::string generatePiecewiseElseCode(const std::string &value) const; + std::string generateCode(const AnalyserEquationAstPtr &ast) const; + + bool isToBeComputedAgain(const AnalyserEquationPtr &equation) const; + bool isSomeConstant(const AnalyserEquationPtr &equation, + bool includeComputedConstants) const; + + std::string generateZeroInitialisationCode(const AnalyserVariablePtr &variable); + std::string generateInitialisationCode(const AnalyserVariablePtr &variable); + std::string generateEquationCode(const AnalyserEquationPtr &equation, + std::vector &remainingEquations, + std::vector &equationsForDependencies, + bool includeComputedConstants); + std::string generateEquationCode(const AnalyserEquationPtr &equation, + std::vector &remainingEquations); + + void addNlaSystemsCode(); + + std::string generateConstantInitialisationCode(const std::vector::iterator constant, + std::vector &remainingConstants); + void initialiseVariables(std::vector &remainingEquations); + void computeComputedConstants(std::vector &remainingEquations); + void computeRates(std::vector &remainingEquations); + void computeVariables(std::vector &remainingEquations); +}; + +} // namespace libcellml From becf20e92f16d60ba26a58db43341315e93533a2 Mon Sep 17 00:00:00 2001 From: Alan Garny Date: Tue, 22 Oct 2024 23:36:52 +1300 Subject: [PATCH 07/10] GeneratorProfile: slight math-related improvements. --- src/generatorprofile.cpp | 42 +++++++++----------------------- src/generatorprofilesha1values.h | 4 +-- 2 files changed, 14 insertions(+), 32 deletions(-) diff --git a/src/generatorprofile.cpp b/src/generatorprofile.cpp index 2d1a11d2f4..87843836fc 100644 --- a/src/generatorprofile.cpp +++ b/src/generatorprofile.cpp @@ -79,8 +79,8 @@ void GeneratorProfile::GeneratorProfileImpl::loadProfile(GeneratorProfile::Profi mCommonLogarithmString = "log10"; mCeilingString = "ceil"; mFloorString = "floor"; - mMinString = "min"; - mMaxString = "max"; + mMinString = "fmin"; + mMaxString = "fmax"; mRemString = "fmod"; mHasPowerOperator = false; @@ -123,7 +123,7 @@ void GeneratorProfile::GeneratorProfileImpl::loadProfile(GeneratorProfile::Profi mTrueString = "1.0"; mFalseString = "0.0"; - mEString = convertToString(exp(1.0)); + mEString = convertToString(M_E); mPiString = convertToString(M_PI); mInfString = "INFINITY"; mNanString = "NAN"; @@ -143,14 +143,8 @@ void GeneratorProfile::GeneratorProfileImpl::loadProfile(GeneratorProfile::Profi " return (x != 0.0) ^ (y != 0.0);\n" "}\n"; mNotFunctionString = ""; - mMinFunctionString = "double min(double x, double y)\n" - "{\n" - " return (x < y)?x:y;\n" - "}\n"; - mMaxFunctionString = "double max(double x, double y)\n" - "{\n" - " return (x > y)?x:y;\n" - "}\n"; + mMinFunctionString = ""; + mMaxFunctionString = ""; // Trigonometric functions. @@ -192,21 +186,15 @@ void GeneratorProfile::GeneratorProfileImpl::loadProfile(GeneratorProfile::Profi "}\n"; mAsechFunctionString = "double asech(double x)\n" "{\n" - " double oneOverX = 1.0/x;\n" - "\n" - " return log(oneOverX+sqrt(oneOverX*oneOverX-1.0));\n" + " return acosh(1.0/x);\n" "}\n"; mAcschFunctionString = "double acsch(double x)\n" "{\n" - " double oneOverX = 1.0/x;\n" - "\n" - " return log(oneOverX+sqrt(oneOverX*oneOverX+1.0));\n" + " return asinh(1.0/x);\n" "}\n"; mAcothFunctionString = "double acoth(double x)\n" "{\n" - " double oneOverX = 1.0/x;\n" - "\n" - " return 0.5*log((1.0+oneOverX)/(1.0-oneOverX));\n" + " return atanh(1.0/x);\n" "}\n"; // Miscellaneous. @@ -636,7 +624,7 @@ void GeneratorProfile::GeneratorProfileImpl::loadProfile(GeneratorProfile::Profi mTrueString = "1.0"; mFalseString = "0.0"; - mEString = convertToString(exp(1.0)); + mEString = convertToString(M_E); mPiString = convertToString(M_PI); mInfString = "inf"; mNanString = "nan"; @@ -711,19 +699,13 @@ void GeneratorProfile::GeneratorProfileImpl::loadProfile(GeneratorProfile::Profi " return atan(1.0/x)\n"; mAsechFunctionString = "\n" "def asech(x):\n" - " one_over_x = 1.0/x\n" - "\n" - " return log(one_over_x+sqrt(one_over_x*one_over_x-1.0))\n"; + " return acosh(1.0/x)\n"; mAcschFunctionString = "\n" "def acsch(x):\n" - " one_over_x = 1.0/x\n" - "\n" - " return log(one_over_x+sqrt(one_over_x*one_over_x+1.0))\n"; + " return asinh(1.0/x)\n"; mAcothFunctionString = "\n" "def acoth(x):\n" - " one_over_x = 1.0/x\n" - "\n" - " return 0.5*log((1.0+one_over_x)/(1.0-one_over_x))\n"; + " return atanh(1.0/x)\n"; // Miscellaneous. diff --git a/src/generatorprofilesha1values.h b/src/generatorprofilesha1values.h index 1bb721da23..6e870864e1 100644 --- a/src/generatorprofilesha1values.h +++ b/src/generatorprofilesha1values.h @@ -24,7 +24,7 @@ namespace libcellml { * The content of this file is generated, do not edit this file directly. * See docs/dev_utilities.rst for further information. */ -static const char C_GENERATOR_PROFILE_SHA1[] = "f0d3add475025d2d4b805747828dbaf2f1345b2f"; -static const char PYTHON_GENERATOR_PROFILE_SHA1[] = "35838d23a1b89fe47293f75e2684ba6d230cf4a8"; +static const char C_GENERATOR_PROFILE_SHA1[] = "e0be7345a3da30625ef6f2316ea4280323703566"; +static const char PYTHON_GENERATOR_PROFILE_SHA1[] = "dece9fc3241b5a84a4e1ab67972501af0e550b35"; } // namespace libcellml From a7e4f621b041b7527ba71f0e79639b305809db66 Mon Sep 17 00:00:00 2001 From: Alan Garny Date: Tue, 22 Oct 2024 23:42:39 +1300 Subject: [PATCH 08/10] Tests utils: some minor cleaning up. --- tests/test_utils.cpp | 32 ++++++++++++++++---------------- tests/test_utils.h | 1 + 2 files changed, 17 insertions(+), 16 deletions(-) diff --git a/tests/test_utils.cpp b/tests/test_utils.cpp index 0275c8483e..2025954e12 100644 --- a/tests/test_utils.cpp +++ b/tests/test_utils.cpp @@ -259,6 +259,22 @@ void expectEqualIssuesCellmlElementTypesLevelsReferenceRulesUrls(const std::vect } } +void expectEqualFileContents(const std::string &fileName, const std::string &fileContents) +{ + // Uncomment the below when you want to generate the expected file contents. + // #define NEW_GENERATOR + +#ifdef NEW_GENERATOR + std::ofstream file(resourcePath(fileName)); + + file << fileContents; + + file.close(); +#endif + + EXPECT_EQ(::fileContents(fileName), fileContents); +} + libcellml::ModelPtr createModel(const std::string &name) { libcellml::ModelPtr model = libcellml::Model::create(); @@ -416,19 +432,3 @@ void compareReset(const libcellml::ResetPtr &r1, const libcellml::ResetPtr &r2) EXPECT_EQ(r1->testValueId(), r2->testValueId()); EXPECT_EQ(r1->resetValueId(), r2->resetValueId()); } - -void expectEqualFileContents(const std::string &fileName, const std::string &fileContents) -{ - // Uncomment the below when you want to generate the expected file contents. - // #define NEW_GENERATOR - -#ifdef NEW_GENERATOR - std::ofstream file(resourcePath(fileName)); - - file << fileContents; - - file.close(); -#endif - - EXPECT_EQ(::fileContents(fileName), fileContents); -} diff --git a/tests/test_utils.h b/tests/test_utils.h index c89198426a..2390a07ee1 100644 --- a/tests/test_utils.h +++ b/tests/test_utils.h @@ -104,6 +104,7 @@ void TEST_EXPORT expectEqualIssuesCellmlElementTypesLevelsReferenceRulesUrls(con const std::vector &referenceRules, const std::vector &urls, const libcellml::LoggerPtr &logger); + void TEST_EXPORT expectEqualFileContents(const std::string &fileName, const std::string &fileContents); libcellml::ModelPtr TEST_EXPORT createModel(const std::string &name = ""); From a14384584700c73f0affade5061774d46cea9bb7 Mon Sep 17 00:00:00 2001 From: Alan Garny Date: Wed, 23 Oct 2024 00:27:04 +1300 Subject: [PATCH 09/10] Tests: various minor improvements. --- .../bindings/python/test_generator_profile.py | 14 +- tests/coverage/coverage.cpp | 41 +- tests/generator/generator.cpp | 69 +-- tests/generator/generatorprofile.cpp | 28 +- tests/resources/coverage/generator/model.c | 418 ++++++++--------- .../resources/coverage/generator/model.cellml | 307 ++++++++++++- .../generator/model.implementation.out | 397 ++++++++-------- tests/resources/coverage/generator/model.out | 365 ++++++++------- tests/resources/coverage/generator/model.py | 408 +++++++++-------- .../{model.modified.profile.c => model.xor.c} | 422 +++++++++--------- .../{model.modified.profile.h => model.xor.h} | 2 +- ...model.modified.profile.py => model.xor.py} | 412 +++++++++-------- .../generator/cellml_slc_example/model.c | 92 ++++ .../generator/cellml_slc_example/model.h | 32 ++ ...algebraic.c => model.algebraic.external.c} | 2 +- ...algebraic.h => model.algebraic.external.h} | 0 ...gebraic.py => model.algebraic.external.py} | 0 ...t.c => model.computed.constant.external.c} | 2 +- ...t.h => model.computed.constant.external.h} | 0 ...py => model.computed.constant.external.py} | 0 ...l.constant.c => model.constant.external.c} | 2 +- ...l.constant.h => model.constant.external.h} | 0 ...constant.py => model.constant.external.py} | 0 ...c => model.dependent.algebraic.external.c} | 2 +- ...h => model.dependent.algebraic.external.h} | 0 ... => model.dependent.algebraic.external.py} | 0 ...el.dependent.computed.constant.external.c} | 2 +- ...el.dependent.computed.constant.external.h} | 0 ...l.dependent.computed.constant.external.py} | 0 ....c => model.dependent.constant.external.c} | 2 +- ....h => model.dependent.constant.external.h} | 0 ...y => model.dependent.constant.external.py} | 0 ...ate.c => model.dependent.state.external.c} | 2 +- ...ate.h => model.dependent.state.external.h} | 0 ...e.py => model.dependent.state.external.py} | 0 .../{model.state.c => model.state.external.c} | 2 +- .../{model.state.h => model.state.external.h} | 0 ...model.state.py => model.state.external.py} | 0 ...ellml => model.unknown.vars.on.rhs.cellml} | 0 39 files changed, 1729 insertions(+), 1294 deletions(-) rename tests/resources/coverage/generator/{model.modified.profile.c => model.xor.c} (65%) rename tests/resources/coverage/generator/{model.modified.profile.h => model.xor.h} (98%) rename tests/resources/coverage/generator/{model.modified.profile.py => model.xor.py} (71%) create mode 100644 tests/resources/generator/cellml_slc_example/model.c create mode 100644 tests/resources/generator/cellml_slc_example/model.h rename tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/{model.algebraic.c => model.algebraic.external.c} (99%) rename tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/{model.algebraic.h => model.algebraic.external.h} (100%) rename tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/{model.algebraic.py => model.algebraic.external.py} (100%) rename tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/{model.computed.constant.c => model.computed.constant.external.c} (99%) rename tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/{model.computed.constant.h => model.computed.constant.external.h} (100%) rename tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/{model.computed.constant.py => model.computed.constant.external.py} (100%) rename tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/{model.constant.c => model.constant.external.c} (99%) rename tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/{model.constant.h => model.constant.external.h} (100%) rename tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/{model.constant.py => model.constant.external.py} (100%) rename tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/{model.dependent.algebraic.c => model.dependent.algebraic.external.c} (99%) rename tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/{model.dependent.algebraic.h => model.dependent.algebraic.external.h} (100%) rename tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/{model.dependent.algebraic.py => model.dependent.algebraic.external.py} (100%) rename tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/{model.dependent.computed.constant.c => model.dependent.computed.constant.external.c} (99%) rename tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/{model.dependent.computed.constant.h => model.dependent.computed.constant.external.h} (100%) rename tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/{model.dependent.computed.constant.py => model.dependent.computed.constant.external.py} (100%) rename tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/{model.dependent.constant.c => model.dependent.constant.external.c} (99%) rename tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/{model.dependent.constant.h => model.dependent.constant.external.h} (100%) rename tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/{model.dependent.constant.py => model.dependent.constant.external.py} (100%) rename tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/{model.dependent.state.c => model.dependent.state.external.c} (99%) rename tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/{model.dependent.state.h => model.dependent.state.external.h} (100%) rename tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/{model.dependent.state.py => model.dependent.state.external.py} (100%) rename tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/{model.state.c => model.state.external.c} (99%) rename tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/{model.state.h => model.state.external.h} (100%) rename tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/{model.state.py => model.state.external.py} (100%) rename tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/{model_unknown_vars_on_rhs.cellml => model.unknown.vars.on.rhs.cellml} (100%) diff --git a/tests/bindings/python/test_generator_profile.py b/tests/bindings/python/test_generator_profile.py index 54befa0120..0c6e4ec6c4 100644 --- a/tests/bindings/python/test_generator_profile.py +++ b/tests/bindings/python/test_generator_profile.py @@ -162,7 +162,7 @@ def test_acoth_function_string(self): g = GeneratorProfile() self.assertEqual( - 'double acoth(double x)\n{\n double oneOverX = 1.0/x;\n\n return 0.5*log((1.0+oneOverX)/(1.0-oneOverX));\n}\n', + 'double acoth(double x)\n{\n return atanh(1.0/x);\n}\n', g.acothFunctionString()) g.setAcothFunctionString(GeneratorProfileTestCase.VALUE) self.assertEqual(GeneratorProfileTestCase.VALUE, g.acothFunctionString()) @@ -200,7 +200,7 @@ def test_acsch_function_string(self): g = GeneratorProfile() self.assertEqual( - 'double acsch(double x)\n{\n double oneOverX = 1.0/x;\n\n return log(oneOverX+sqrt(oneOverX*oneOverX+1.0));\n}\n', + 'double acsch(double x)\n{\n return asinh(1.0/x);\n}\n', g.acschFunctionString()) g.setAcschFunctionString(GeneratorProfileTestCase.VALUE) self.assertEqual(GeneratorProfileTestCase.VALUE, g.acschFunctionString()) @@ -265,7 +265,7 @@ def test_asech_function_string(self): g = GeneratorProfile() self.assertEqual( - 'double asech(double x)\n{\n double oneOverX = 1.0/x;\n\n return log(oneOverX+sqrt(oneOverX*oneOverX-1.0));\n}\n', + 'double asech(double x)\n{\n return acosh(1.0/x);\n}\n', g.asechFunctionString()) g.setAsechFunctionString(GeneratorProfileTestCase.VALUE) self.assertEqual(GeneratorProfileTestCase.VALUE, g.asechFunctionString()) @@ -1285,7 +1285,7 @@ def test_max_function_string(self): g = GeneratorProfile() - self.assertEqual('double max(double x, double y)\n{\n return (x > y)?x:y;\n}\n', g.maxFunctionString()) + self.assertEqual('', g.maxFunctionString()) g.setMaxFunctionString(GeneratorProfileTestCase.VALUE) self.assertEqual(GeneratorProfileTestCase.VALUE, g.maxFunctionString()) @@ -1294,7 +1294,7 @@ def test_max_string(self): g = GeneratorProfile() - self.assertEqual('max', g.maxString()) + self.assertEqual('fmax', g.maxString()) g.setMaxString(GeneratorProfileTestCase.VALUE) self.assertEqual(GeneratorProfileTestCase.VALUE, g.maxString()) @@ -1303,7 +1303,7 @@ def test_min_function_string(self): g = GeneratorProfile() - self.assertEqual('double min(double x, double y)\n{\n return (x < y)?x:y;\n}\n', g.minFunctionString()) + self.assertEqual('', g.minFunctionString()) g.setMinFunctionString(GeneratorProfileTestCase.VALUE) self.assertEqual(GeneratorProfileTestCase.VALUE, g.minFunctionString()) @@ -1312,7 +1312,7 @@ def test_min_string(self): g = GeneratorProfile() - self.assertEqual('min', g.minString()) + self.assertEqual('fmin', g.minString()) g.setMinString(GeneratorProfileTestCase.VALUE) self.assertEqual(GeneratorProfileTestCase.VALUE, g.minString()) diff --git a/tests/coverage/coverage.cpp b/tests/coverage/coverage.cpp index 4e71511c89..9cbbd6fe8d 100644 --- a/tests/coverage/coverage.cpp +++ b/tests/coverage/coverage.cpp @@ -597,10 +597,10 @@ TEST(Coverage, generator) EXPECT_EQ(size_t(1), analyserModel->stateCount()); EXPECT_EQ(size_t(7), analyserModel->constantCount()); - EXPECT_EQ(size_t(199), analyserModel->computedConstantCount()); - EXPECT_EQ(size_t(2), analyserModel->algebraicCount()); + EXPECT_EQ(size_t(207), analyserModel->computedConstantCount()); + EXPECT_EQ(size_t(5), analyserModel->algebraicCount()); EXPECT_EQ(size_t(1), analyserModel->externalCount()); - EXPECT_EQ(size_t(203), analyserModel->equationCount()); + EXPECT_EQ(size_t(214), analyserModel->equationCount()); EXPECT_NE(nullptr, analyserModel->voi()); EXPECT_EQ(size_t(0), analyserModel->voi()->equationCount()); @@ -627,6 +627,7 @@ TEST(Coverage, generator) EXPECT_EQ(size_t(1), analyserModel->equation(0)->states().size()); EXPECT_NE(nullptr, analyserModel->equation(0)->state(0)); EXPECT_EQ(nullptr, analyserModel->equation(0)->state(analyserModel->equation(0)->stateCount())); + /*---GRY--- STILL NEEDED? EXPECT_NE(nullptr, analyserModel->equation(199)); EXPECT_NE(size_t(0), analyserModel->equation(199)->dependencyCount()); EXPECT_NE(size_t(0), analyserModel->equation(199)->dependencies().size()); @@ -649,6 +650,7 @@ TEST(Coverage, generator) EXPECT_EQ(nullptr, analyserModel->equation(199)->external(0)); EXPECT_EQ(nullptr, analyserModel->equation(199)->external(analyserModel->equation(199)->externalCount())); EXPECT_EQ(nullptr, analyserModel->equation(analyserModel->equationCount())); + */ for (const auto &equation : analyserModel->equations()) { checkAstTypeAsString(equation->ast()); @@ -666,9 +668,11 @@ TEST(Coverage, generator) EXPECT_NE(nullptr, analyserModel->constant(i)->initialisingVariable()); } + /*---GRY--- STILL NEEDED? for (size_t i = 0; i < analyserModel->algebraicCount(); ++i) { EXPECT_NE(nullptr, analyserModel->algebraic(i)->initialisingVariable()); } + */ EXPECT_EQ(nullptr, generator->model()); EXPECT_EQ(EMPTY_STRING, generator->interfaceCode()); @@ -682,20 +686,14 @@ TEST(Coverage, generator) auto profile = generator->profile(); - profile->setInterfaceCreateStatesArrayMethodString("double * createStatesVector();\n"); - profile->setImplementationCreateStatesArrayMethodString("double * createStatesVector()\n" - "{\n" - " double *res = (double *) malloc(STATE_COUNT*sizeof(double));\n" - "\n" - " for (size_t i = 0; i < STATE_COUNT; ++i) {\n" - " res[i] = NAN;\n" - " }\n" - "\n" - " return res;\n" - "}\n"); - - EXPECT_EQ_FILE_CONTENTS("coverage/generator/model.modified.profile.h", generator->interfaceCode()); - EXPECT_EQ_FILE_CONTENTS("coverage/generator/model.modified.profile.c", generator->implementationCode()); + profile->setXorString("XOR"); + profile->setXorFunctionString("double XOR(double x, double y)\n" + "{\n" + " return (x != 0.0) ^ (y != 0.0);\n" + "}\n"); + + EXPECT_EQ_FILE_CONTENTS("coverage/generator/model.xor.h", generator->interfaceCode()); + EXPECT_EQ_FILE_CONTENTS("coverage/generator/model.xor.c", generator->implementationCode()); profile = libcellml::GeneratorProfile::create(); @@ -847,12 +845,13 @@ TEST(Coverage, generator) EXPECT_EQ(EMPTY_STRING, generator->interfaceCode()); EXPECT_EQ_FILE_CONTENTS("coverage/generator/model.py", generator->implementationCode()); - profile->setImplementationCreateStatesArrayMethodString("\n" - "def create_states_vector():\n" - " return [nan]*STATE_COUNT\n"); + profile->setXorString("XOR_FUNC"); + profile->setXorFunctionString("\n" + "def XOR_FUNC(x, y):\n" + " return 1.0 if bool(x) ^ bool(y) else 0.0\n"); EXPECT_EQ(EMPTY_STRING, generator->interfaceCode()); - EXPECT_EQ_FILE_CONTENTS("coverage/generator/model.modified.profile.py", generator->implementationCode()); + EXPECT_EQ_FILE_CONTENTS("coverage/generator/model.xor.py", generator->implementationCode()); // Coverage for the case where mProfile is equal to nullptr in Generator. diff --git a/tests/generator/generator.cpp b/tests/generator/generator.cpp index d84acefb86..fbf3c7b684 100644 --- a/tests/generator/generator.cpp +++ b/tests/generator/generator.cpp @@ -1203,7 +1203,7 @@ TEST(Generator, hodgkinHuxleySquidAxonModel1952) TEST(Generator, hodgkinHuxleySquidAxonModel1952UnknownVarsOnRhs) { auto parser = libcellml::Parser::create(); - auto model = parser->parseModel(fileContents("generator/hodgkin_huxley_squid_axon_model_1952/model_unknown_vars_on_rhs.cellml")); + auto model = parser->parseModel(fileContents("generator/hodgkin_huxley_squid_axon_model_1952/model.unknown.vars.on.rhs.cellml")); EXPECT_EQ(size_t(0), parser->issueCount()); @@ -1253,16 +1253,16 @@ TEST(Generator, hodgkinHuxleySquidAxonModel1952WithStateVariableAsExternalVariab auto profile = generator->profile(); - profile->setInterfaceFileNameString("model.state.h"); + profile->setInterfaceFileNameString("model.state.external.h"); - EXPECT_EQ_FILE_CONTENTS("generator/hodgkin_huxley_squid_axon_model_1952/model.state.h", generator->interfaceCode()); - EXPECT_EQ_FILE_CONTENTS("generator/hodgkin_huxley_squid_axon_model_1952/model.state.c", generator->implementationCode()); + EXPECT_EQ_FILE_CONTENTS("generator/hodgkin_huxley_squid_axon_model_1952/model.state.external.h", generator->interfaceCode()); + EXPECT_EQ_FILE_CONTENTS("generator/hodgkin_huxley_squid_axon_model_1952/model.state.external.c", generator->implementationCode()); profile = libcellml::GeneratorProfile::create(libcellml::GeneratorProfile::Profile::PYTHON); generator->setProfile(profile); - EXPECT_EQ_FILE_CONTENTS("generator/hodgkin_huxley_squid_axon_model_1952/model.state.py", generator->implementationCode()); + EXPECT_EQ_FILE_CONTENTS("generator/hodgkin_huxley_squid_axon_model_1952/model.state.external.py", generator->implementationCode()); } TEST(Generator, hodgkinHuxleySquidAxonModel1952WithStateVariablesAsExternalVariablesIncludingOneDependingOnTheOther) @@ -1297,16 +1297,16 @@ TEST(Generator, hodgkinHuxleySquidAxonModel1952WithStateVariablesAsExternalVaria auto profile = generator->profile(); - profile->setInterfaceFileNameString("model.dependent.state.h"); + profile->setInterfaceFileNameString("model.dependent.state.external.h"); - EXPECT_EQ_FILE_CONTENTS("generator/hodgkin_huxley_squid_axon_model_1952/model.dependent.state.h", generator->interfaceCode()); - EXPECT_EQ_FILE_CONTENTS("generator/hodgkin_huxley_squid_axon_model_1952/model.dependent.state.c", generator->implementationCode()); + EXPECT_EQ_FILE_CONTENTS("generator/hodgkin_huxley_squid_axon_model_1952/model.dependent.state.external.h", generator->interfaceCode()); + EXPECT_EQ_FILE_CONTENTS("generator/hodgkin_huxley_squid_axon_model_1952/model.dependent.state.external.c", generator->implementationCode()); profile = libcellml::GeneratorProfile::create(libcellml::GeneratorProfile::Profile::PYTHON); generator->setProfile(profile); - EXPECT_EQ_FILE_CONTENTS("generator/hodgkin_huxley_squid_axon_model_1952/model.dependent.state.py", generator->implementationCode()); + EXPECT_EQ_FILE_CONTENTS("generator/hodgkin_huxley_squid_axon_model_1952/model.dependent.state.external.py", generator->implementationCode()); } TEST(Generator, hodgkinHuxleySquidAxonModel1952WithConstantAsExternalVariable) @@ -1334,16 +1334,16 @@ TEST(Generator, hodgkinHuxleySquidAxonModel1952WithConstantAsExternalVariable) auto profile = generator->profile(); - profile->setInterfaceFileNameString("model.constant.h"); + profile->setInterfaceFileNameString("model.constant.external.h"); - EXPECT_EQ_FILE_CONTENTS("generator/hodgkin_huxley_squid_axon_model_1952/model.constant.h", generator->interfaceCode()); - EXPECT_EQ_FILE_CONTENTS("generator/hodgkin_huxley_squid_axon_model_1952/model.constant.c", generator->implementationCode()); + EXPECT_EQ_FILE_CONTENTS("generator/hodgkin_huxley_squid_axon_model_1952/model.constant.external.h", generator->interfaceCode()); + EXPECT_EQ_FILE_CONTENTS("generator/hodgkin_huxley_squid_axon_model_1952/model.constant.external.c", generator->implementationCode()); profile = libcellml::GeneratorProfile::create(libcellml::GeneratorProfile::Profile::PYTHON); generator->setProfile(profile); - EXPECT_EQ_FILE_CONTENTS("generator/hodgkin_huxley_squid_axon_model_1952/model.constant.py", generator->implementationCode()); + EXPECT_EQ_FILE_CONTENTS("generator/hodgkin_huxley_squid_axon_model_1952/model.constant.external.py", generator->implementationCode()); } TEST(Generator, hodgkinHuxleySquidAxonModel1952WithConstantsAsExternalVariablesIncludingOneDependingOnTheOther) @@ -1377,16 +1377,16 @@ TEST(Generator, hodgkinHuxleySquidAxonModel1952WithConstantsAsExternalVariablesI auto profile = generator->profile(); - profile->setInterfaceFileNameString("model.dependent.constant.h"); + profile->setInterfaceFileNameString("model.dependent.constant.external.h"); - EXPECT_EQ_FILE_CONTENTS("generator/hodgkin_huxley_squid_axon_model_1952/model.dependent.constant.h", generator->interfaceCode()); - EXPECT_EQ_FILE_CONTENTS("generator/hodgkin_huxley_squid_axon_model_1952/model.dependent.constant.c", generator->implementationCode()); + EXPECT_EQ_FILE_CONTENTS("generator/hodgkin_huxley_squid_axon_model_1952/model.dependent.constant.external.h", generator->interfaceCode()); + EXPECT_EQ_FILE_CONTENTS("generator/hodgkin_huxley_squid_axon_model_1952/model.dependent.constant.external.c", generator->implementationCode()); profile = libcellml::GeneratorProfile::create(libcellml::GeneratorProfile::Profile::PYTHON); generator->setProfile(profile); - EXPECT_EQ_FILE_CONTENTS("generator/hodgkin_huxley_squid_axon_model_1952/model.dependent.constant.py", generator->implementationCode()); + EXPECT_EQ_FILE_CONTENTS("generator/hodgkin_huxley_squid_axon_model_1952/model.dependent.constant.external.py", generator->implementationCode()); } TEST(Generator, hodgkinHuxleySquidAxonModel1952WithComputedConstantAsExternalVariable) @@ -1414,16 +1414,16 @@ TEST(Generator, hodgkinHuxleySquidAxonModel1952WithComputedConstantAsExternalVar auto profile = generator->profile(); - profile->setInterfaceFileNameString("model.computed.constant.h"); + profile->setInterfaceFileNameString("model.computed.constant.external.h"); - EXPECT_EQ_FILE_CONTENTS("generator/hodgkin_huxley_squid_axon_model_1952/model.computed.constant.h", generator->interfaceCode()); - EXPECT_EQ_FILE_CONTENTS("generator/hodgkin_huxley_squid_axon_model_1952/model.computed.constant.c", generator->implementationCode()); + EXPECT_EQ_FILE_CONTENTS("generator/hodgkin_huxley_squid_axon_model_1952/model.computed.constant.external.h", generator->interfaceCode()); + EXPECT_EQ_FILE_CONTENTS("generator/hodgkin_huxley_squid_axon_model_1952/model.computed.constant.external.c", generator->implementationCode()); profile = libcellml::GeneratorProfile::create(libcellml::GeneratorProfile::Profile::PYTHON); generator->setProfile(profile); - EXPECT_EQ_FILE_CONTENTS("generator/hodgkin_huxley_squid_axon_model_1952/model.computed.constant.py", generator->implementationCode()); + EXPECT_EQ_FILE_CONTENTS("generator/hodgkin_huxley_squid_axon_model_1952/model.computed.constant.external.py", generator->implementationCode()); } TEST(Generator, hodgkinHuxleySquidAxonModel1952WithComputedConstantsAsExternalVariablesIncludingOneDependingOnTheOther) @@ -1457,16 +1457,16 @@ TEST(Generator, hodgkinHuxleySquidAxonModel1952WithComputedConstantsAsExternalVa auto profile = generator->profile(); - profile->setInterfaceFileNameString("model.dependent.computed.constant.h"); + profile->setInterfaceFileNameString("model.dependent.computed.constant.external.h"); - EXPECT_EQ_FILE_CONTENTS("generator/hodgkin_huxley_squid_axon_model_1952/model.dependent.computed.constant.h", generator->interfaceCode()); - EXPECT_EQ_FILE_CONTENTS("generator/hodgkin_huxley_squid_axon_model_1952/model.dependent.computed.constant.c", generator->implementationCode()); + EXPECT_EQ_FILE_CONTENTS("generator/hodgkin_huxley_squid_axon_model_1952/model.dependent.computed.constant.external.h", generator->interfaceCode()); + EXPECT_EQ_FILE_CONTENTS("generator/hodgkin_huxley_squid_axon_model_1952/model.dependent.computed.constant.external.c", generator->implementationCode()); profile = libcellml::GeneratorProfile::create(libcellml::GeneratorProfile::Profile::PYTHON); generator->setProfile(profile); - EXPECT_EQ_FILE_CONTENTS("generator/hodgkin_huxley_squid_axon_model_1952/model.dependent.computed.constant.py", generator->implementationCode()); + EXPECT_EQ_FILE_CONTENTS("generator/hodgkin_huxley_squid_axon_model_1952/model.dependent.computed.constant.external.py", generator->implementationCode()); } TEST(Generator, hodgkinHuxleySquidAxonModel1952WithAlgebraicVariableAsExternalVariable) @@ -1494,16 +1494,16 @@ TEST(Generator, hodgkinHuxleySquidAxonModel1952WithAlgebraicVariableAsExternalVa auto profile = generator->profile(); - profile->setInterfaceFileNameString("model.algebraic.h"); + profile->setInterfaceFileNameString("model.algebraic.external.h"); - EXPECT_EQ_FILE_CONTENTS("generator/hodgkin_huxley_squid_axon_model_1952/model.algebraic.h", generator->interfaceCode()); - EXPECT_EQ_FILE_CONTENTS("generator/hodgkin_huxley_squid_axon_model_1952/model.algebraic.c", generator->implementationCode()); + EXPECT_EQ_FILE_CONTENTS("generator/hodgkin_huxley_squid_axon_model_1952/model.algebraic.external.h", generator->interfaceCode()); + EXPECT_EQ_FILE_CONTENTS("generator/hodgkin_huxley_squid_axon_model_1952/model.algebraic.external.c", generator->implementationCode()); profile = libcellml::GeneratorProfile::create(libcellml::GeneratorProfile::Profile::PYTHON); generator->setProfile(profile); - EXPECT_EQ_FILE_CONTENTS("generator/hodgkin_huxley_squid_axon_model_1952/model.algebraic.py", generator->implementationCode()); + EXPECT_EQ_FILE_CONTENTS("generator/hodgkin_huxley_squid_axon_model_1952/model.algebraic.external.py", generator->implementationCode()); } TEST(Generator, hodgkinHuxleySquidAxonModel1952WithAlgebraicVariablesAsExternalVariablesIncludingOneDependingOnTheOther) @@ -1537,16 +1537,16 @@ TEST(Generator, hodgkinHuxleySquidAxonModel1952WithAlgebraicVariablesAsExternalV auto profile = generator->profile(); - profile->setInterfaceFileNameString("model.dependent.algebraic.h"); + profile->setInterfaceFileNameString("model.dependent.algebraic.external.h"); - EXPECT_EQ_FILE_CONTENTS("generator/hodgkin_huxley_squid_axon_model_1952/model.dependent.algebraic.h", generator->interfaceCode()); - EXPECT_EQ_FILE_CONTENTS("generator/hodgkin_huxley_squid_axon_model_1952/model.dependent.algebraic.c", generator->implementationCode()); + EXPECT_EQ_FILE_CONTENTS("generator/hodgkin_huxley_squid_axon_model_1952/model.dependent.algebraic.external.h", generator->interfaceCode()); + EXPECT_EQ_FILE_CONTENTS("generator/hodgkin_huxley_squid_axon_model_1952/model.dependent.algebraic.external.c", generator->implementationCode()); profile = libcellml::GeneratorProfile::create(libcellml::GeneratorProfile::Profile::PYTHON); generator->setProfile(profile); - EXPECT_EQ_FILE_CONTENTS("generator/hodgkin_huxley_squid_axon_model_1952/model.dependent.algebraic.py", generator->implementationCode()); + EXPECT_EQ_FILE_CONTENTS("generator/hodgkin_huxley_squid_axon_model_1952/model.dependent.algebraic.external.py", generator->implementationCode()); } TEST(Generator, hodgkinHuxleySquidAxonModel1952WithVariousExternalVariables) @@ -1972,6 +1972,9 @@ TEST(Generator, modelWithComplexUnitsOutOfScope) generator->setModel(analyserModel); + EXPECT_EQ_FILE_CONTENTS("generator/cellml_slc_example/model.h", generator->interfaceCode()); + EXPECT_EQ_FILE_CONTENTS("generator/cellml_slc_example/model.c", generator->implementationCode()); + auto profile = libcellml::GeneratorProfile::create(libcellml::GeneratorProfile::Profile::PYTHON); generator->setProfile(profile); diff --git a/tests/generator/generatorprofile.cpp b/tests/generator/generatorprofile.cpp index 1b8071fbf8..4339294f9e 100644 --- a/tests/generator/generatorprofile.cpp +++ b/tests/generator/generatorprofile.cpp @@ -88,8 +88,8 @@ TEST(GeneratorProfile, defaultArithmeticOperatorValues) EXPECT_EQ("log10", generatorProfile->commonLogarithmString()); EXPECT_EQ("ceil", generatorProfile->ceilingString()); EXPECT_EQ("floor", generatorProfile->floorString()); - EXPECT_EQ("min", generatorProfile->minString()); - EXPECT_EQ("max", generatorProfile->maxString()); + EXPECT_EQ("fmin", generatorProfile->minString()); + EXPECT_EQ("fmax", generatorProfile->maxString()); EXPECT_EQ("fmod", generatorProfile->remString()); EXPECT_EQ(false, generatorProfile->hasPowerOperator()); @@ -167,16 +167,8 @@ TEST(GeneratorProfile, defaultArithmeticFunctionValues) "}\n", generatorProfile->xorFunctionString()); EXPECT_EQ("", generatorProfile->notFunctionString()); - EXPECT_EQ("double min(double x, double y)\n" - "{\n" - " return (x < y)?x:y;\n" - "}\n", - generatorProfile->minFunctionString()); - EXPECT_EQ("double max(double x, double y)\n" - "{\n" - " return (x > y)?x:y;\n" - "}\n", - generatorProfile->maxFunctionString()); + EXPECT_EQ("", generatorProfile->minFunctionString()); + EXPECT_EQ("", generatorProfile->maxFunctionString()); } TEST(GeneratorProfile, defaultTrigonometricFunctionValues) @@ -230,23 +222,17 @@ TEST(GeneratorProfile, defaultTrigonometricFunctionValues) generatorProfile->acotFunctionString()); EXPECT_EQ("double asech(double x)\n" "{\n" - " double oneOverX = 1.0/x;\n" - "\n" - " return log(oneOverX+sqrt(oneOverX*oneOverX-1.0));\n" + " return acosh(1.0/x);\n" "}\n", generatorProfile->asechFunctionString()); EXPECT_EQ("double acsch(double x)\n" "{\n" - " double oneOverX = 1.0/x;\n" - "\n" - " return log(oneOverX+sqrt(oneOverX*oneOverX+1.0));\n" + " return asinh(1.0/x);\n" "}\n", generatorProfile->acschFunctionString()); EXPECT_EQ("double acoth(double x)\n" "{\n" - " double oneOverX = 1.0/x;\n" - "\n" - " return 0.5*log((1.0+oneOverX)/(1.0-oneOverX));\n" + " return atanh(1.0/x);\n" "}\n", generatorProfile->acothFunctionString()); } diff --git a/tests/resources/coverage/generator/model.c b/tests/resources/coverage/generator/model.c index b168f71788..dfefa277a5 100644 --- a/tests/resources/coverage/generator/model.c +++ b/tests/resources/coverage/generator/model.c @@ -10,8 +10,8 @@ const char LIBCELLML_VERSION[] = "0.6.0"; const size_t STATE_COUNT = 1; const size_t CONSTANT_COUNT = 7; -const size_t COMPUTED_CONSTANT_COUNT = 199; -const size_t ALGEBRAIC_COUNT = 2; +const size_t COMPUTED_CONSTANT_COUNT = 207; +const size_t ALGEBRAIC_COUNT = 5; const size_t EXTERNAL_COUNT = 1; const VariableInfo VOI_INFO = {"t", "second", "my_component"}; @@ -59,8 +59,6 @@ const VariableInfo COMPUTED_CONSTANT_INFO[] = { {"eqnAndParenthesesRightPower", "dimensionless", "my_component"}, {"eqnAndParenthesesRightRoot", "dimensionless", "my_component"}, {"eqnAndCoverageParentheses", "dimensionless", "my_component"}, - {"eqnOr", "dimensionless", "my_component"}, - {"eqnOrMultiple", "dimensionless", "my_component"}, {"eqnOrParentheses", "dimensionless", "my_component"}, {"eqnOrParenthesesLeftPlusWith", "dimensionless", "my_component"}, {"eqnOrParenthesesLeftPlusWithout", "dimensionless", "my_component"}, @@ -90,7 +88,6 @@ const VariableInfo COMPUTED_CONSTANT_INFO[] = { {"eqnXorParenthesesRightMinusWithout", "dimensionless", "my_component"}, {"eqnXorParenthesesRightPower", "dimensionless", "my_component"}, {"eqnXorParenthesesRightRoot", "dimensionless", "my_component"}, - {"eqnXorCoverageParentheses", "dimensionless", "my_component"}, {"eqnNot", "dimensionless", "my_component"}, {"eqnPlusMultiple", "dimensionless", "my_component"}, {"eqnPlusParentheses", "dimensionless", "my_component"}, @@ -147,6 +144,7 @@ const VariableInfo COMPUTED_CONSTANT_INFO[] = { {"eqnPowerParenthesesRightRoot", "dimensionless", "my_component"}, {"eqnRootSqrt", "dimensionless", "my_component"}, {"eqnRootSqrtOther", "dimensionless", "my_component"}, + {"eqnRootSqr", "dimensionless", "my_component"}, {"eqnRootCube", "dimensionless", "my_component"}, {"eqnRootCi", "dimensionless", "my_component"}, {"eqnRootParentheses", "dimensionless", "my_component"}, @@ -202,11 +200,16 @@ const VariableInfo COMPUTED_CONSTANT_INFO[] = { {"eqnArcsech", "dimensionless", "my_component"}, {"eqnArccsch", "dimensionless", "my_component"}, {"eqnArccoth", "dimensionless", "my_component"}, + {"eqnPiecewise", "dimensionless", "my_component"}, {"eqnPiecewisePiece", "dimensionless", "my_component"}, + {"eqnPiecewisePiece2", "dimensionless", "my_component"}, + {"eqnPiecewiseOtherwise", "dimensionless", "my_component"}, {"eqnPiecewisePieceOtherwise", "dimensionless", "my_component"}, {"eqnPiecewisePiecePiecePiece", "dimensionless", "my_component"}, + {"eqnPiecewisePiecePiecePiece2", "dimensionless", "my_component"}, {"eqnPiecewisePiecePiecePieceOtherwise", "dimensionless", "my_component"}, {"eqnWithPiecewise", "dimensionless", "my_component"}, + {"eqnWithPiecewise2", "dimensionless", "my_component"}, {"eqnCnInteger", "dimensionless", "my_component"}, {"eqnCnDouble", "dimensionless", "my_component"}, {"eqnCnIntegerWithExponent", "dimensionless", "my_component"}, @@ -219,20 +222,28 @@ const VariableInfo COMPUTED_CONSTANT_INFO[] = { {"eqnInfinity", "dimensionless", "my_component"}, {"eqnNotanumber", "dimensionless", "my_component"}, {"eqnCoverageForPlusOperator", "dimensionless", "my_component"}, + {"eqnCoverageForPlusOperator2", "dimensionless", "my_component"}, {"eqnCoverageForMinusOperator", "dimensionless", "my_component"}, + {"eqnCoverageForMinusOperator2", "dimensionless", "my_component"}, {"eqnCoverageForTimesOperator", "dimensionless", "my_component"}, + {"eqnCoverageForTimesOperator2", "dimensionless", "my_component"}, {"eqnCoverageForDivideOperator", "dimensionless", "my_component"}, + {"eqnCoverageForDivideOperator2", "dimensionless", "my_component"}, {"eqnCoverageForAndOperator", "dimensionless", "my_component"}, {"eqnCoverageForOrOperator", "dimensionless", "my_component"}, {"eqnCoverageForXorOperator", "dimensionless", "my_component"}, {"eqnCoverageForPowerOperator", "dimensionless", "my_component"}, {"eqnCoverageForRootOperator", "dimensionless", "my_component"}, {"eqnCoverageForMinusUnary", "dimensionless", "my_component"}, + {"eqnCoverageForMinusUnary2", "dimensionless", "my_component"}, {"eqnComputedConstant1", "dimensionless", "my_component"}, {"eqnComputedConstant2", "dimensionless", "my_component"} }; const VariableInfo ALGEBRAIC_INFO[] = { + {"eqnOr", "dimensionless", "my_component"}, + {"eqnOrMultiple", "dimensionless", "my_component"}, + {"eqnXorCoverageParentheses", "dimensionless", "my_component"}, {"eqnNlaVariable1", "dimensionless", "my_component"}, {"eqnNlaVariable2", "dimensionless", "my_component"} }; @@ -246,16 +257,6 @@ double xor(double x, double y) return (x != 0.0) ^ (y != 0.0); } -double min(double x, double y) -{ - return (x < y)?x:y; -} - -double max(double x, double y) -{ - return (x > y)?x:y; -} - double sec(double x) { return 1.0/cos(x); @@ -303,23 +304,17 @@ double acot(double x) double asech(double x) { - double oneOverX = 1.0/x; - - return log(oneOverX+sqrt(oneOverX*oneOverX-1.0)); + return acosh(1.0/x); } double acsch(double x) { - double oneOverX = 1.0/x; - - return log(oneOverX+sqrt(oneOverX*oneOverX+1.0)); + return asinh(1.0/x); } double acoth(double x) { - double oneOverX = 1.0/x; - - return 0.5*log((1.0+oneOverX)/(1.0-oneOverX)); + return atanh(1.0/x); } double * createStatesArray() @@ -405,11 +400,11 @@ void objectiveFunction0(double *u, double *f, void *data) double *algebraic = ((RootFindingInfo *) data)->algebraic; double *externals = ((RootFindingInfo *) data)->externals; - algebraic[0] = u[0]; - algebraic[1] = u[1]; + algebraic[3] = u[0]; + algebraic[4] = u[1]; - f[0] = algebraic[0]+algebraic[1]+states[0]-0.0; - f[1] = algebraic[0]-algebraic[1]-(computedConstants[197]+computedConstants[198]); + f[0] = algebraic[3]+algebraic[4]+states[0]-0.0; + f[1] = algebraic[3]-algebraic[4]-(computedConstants[205]+computedConstants[206]); } void findRoot0(double voi, double *states, double *rates, double *constants, double *computedConstants, double *algebraic, double *externals) @@ -417,13 +412,13 @@ void findRoot0(double voi, double *states, double *rates, double *constants, dou RootFindingInfo rfi = { voi, states, rates, constants, computedConstants, algebraic, externals }; double u[2]; - u[0] = algebraic[0]; - u[1] = algebraic[1]; + u[0] = algebraic[3]; + u[1] = algebraic[4]; nlaSolve(objectiveFunction0, u, 2, &rfi); - algebraic[0] = u[0]; - algebraic[1] = u[1]; + algebraic[3] = u[0]; + algebraic[4] = u[1]; } void initialiseVariables(double *states, double *rates, double *constants, double *computedConstants, double *algebraic) @@ -436,20 +431,21 @@ void initialiseVariables(double *states, double *rates, double *constants, doubl constants[4] = 5.0; constants[5] = 6.0; constants[6] = 7.0; - computedConstants[176] = 123.0; - computedConstants[177] = 123.456789; - computedConstants[178] = 123.0e99; - computedConstants[179] = 123.456789e99; - computedConstants[181] = 1.0; - computedConstants[182] = 0.0; - computedConstants[183] = 2.71828182845905; - computedConstants[184] = 3.14159265358979; - computedConstants[185] = INFINITY; - computedConstants[186] = NAN; - computedConstants[197] = 1.0; - computedConstants[198] = 3.0; - algebraic[0] = 1.0; - algebraic[1] = 2.0; + computedConstants[169] = NAN; + computedConstants[179] = 123.0; + computedConstants[180] = 123.456789; + computedConstants[181] = 123.0e99; + computedConstants[182] = 123.456789e99; + computedConstants[184] = 1.0; + computedConstants[185] = 0.0; + computedConstants[186] = 2.71828182845905; + computedConstants[187] = 3.14159265358979; + computedConstants[188] = INFINITY; + computedConstants[189] = NAN; + computedConstants[205] = 1.0; + computedConstants[206] = 3.0; + algebraic[3] = 1.0; + algebraic[4] = 2.0; } void computeComputedConstants(double *constants, double *computedConstants) @@ -463,9 +459,9 @@ void computeComputedConstants(double *constants, double *computedConstants) computedConstants[6] = constants[0] <= constants[1]; computedConstants[7] = constants[0]/(constants[1] <= constants[2]); computedConstants[8] = constants[0] > constants[1]; - computedConstants[9] = constants[0]/(constants[1] > constants[2]); + computedConstants[9] = constants[0]/(constants[2] > constants[1]); computedConstants[10] = constants[0] >= constants[1]; - computedConstants[11] = constants[0]/(constants[1] >= constants[2]); + computedConstants[11] = constants[0]/(constants[2] >= constants[1]); computedConstants[12] = constants[0] && constants[1]; computedConstants[13] = constants[0] && constants[1] && constants[2]; computedConstants[14] = (constants[0] < constants[1]) && (constants[2] > constants[3]); @@ -482,165 +478,172 @@ void computeComputedConstants(double *constants, double *computedConstants) computedConstants[25] = (constants[0] < constants[1]) && pow(constants[2], constants[3]); computedConstants[26] = (constants[0] < constants[1]) && pow(constants[2], 1.0/constants[3]); computedConstants[27] = constants[0]/(constants[1] && constants[2]); - computedConstants[28] = constants[0] || constants[1]; - computedConstants[29] = constants[0] || constants[1] || constants[2]; - computedConstants[30] = (constants[0] < constants[1]) || (constants[2] > constants[3]); - computedConstants[31] = (constants[0]+constants[1]) || (constants[2] > constants[3]); - computedConstants[32] = constants[0] || (constants[1] > constants[2]); - computedConstants[33] = (constants[0]-constants[1]) || (constants[2] > constants[3]); - computedConstants[34] = -constants[0] || (constants[1] > constants[2]); - computedConstants[35] = pow(constants[0], constants[1]) || (constants[2] > constants[3]); - computedConstants[36] = pow(constants[0], 1.0/constants[1]) || (constants[2] > constants[3]); - computedConstants[37] = (constants[0] < constants[1]) || (constants[2]+constants[3]); - computedConstants[38] = (constants[0] < constants[1]) || constants[2]; - computedConstants[39] = (constants[0] < constants[1]) || (constants[2]-constants[3]); - computedConstants[40] = (constants[0] < constants[1]) || -constants[2]; - computedConstants[41] = (constants[0] < constants[1]) || pow(constants[2], constants[3]); - computedConstants[42] = (constants[0] < constants[1]) || pow(constants[2], 1.0/constants[3]); - computedConstants[43] = constants[0]/(constants[1] || constants[2]); - computedConstants[44] = xor(constants[0], constants[1]); - computedConstants[45] = xor(constants[0], xor(constants[1], constants[2])); - computedConstants[46] = xor(constants[0] < constants[1], constants[2] > constants[3]); - computedConstants[47] = xor(constants[0]+constants[1], constants[2] > constants[3]); - computedConstants[48] = xor(constants[0], constants[1] > constants[2]); - computedConstants[49] = xor(constants[0]-constants[1], constants[2] > constants[3]); - computedConstants[50] = xor(-constants[0], constants[1] > constants[2]); - computedConstants[51] = xor(pow(constants[0], constants[1]), constants[2] > constants[3]); - computedConstants[52] = xor(pow(constants[0], 1.0/constants[1]), constants[2] > constants[3]); - computedConstants[53] = xor(constants[0] < constants[1], constants[2]+constants[3]); - computedConstants[54] = xor(constants[0] < constants[1], constants[2]); - computedConstants[55] = xor(constants[0] < constants[1], constants[2]-constants[3]); - computedConstants[56] = xor(constants[0] < constants[1], -constants[2]); - computedConstants[57] = xor(constants[0] < constants[1], pow(constants[2], constants[3])); - computedConstants[58] = xor(constants[0] < constants[1], pow(constants[2], 1.0/constants[3])); - computedConstants[59] = constants[0]/xor(constants[1], constants[2]); - computedConstants[60] = !constants[0]; - computedConstants[61] = constants[0]+constants[1]+constants[2]; - computedConstants[62] = (constants[0] < constants[1])+(constants[2] > constants[3]); - computedConstants[63] = constants[0]; - computedConstants[64] = constants[0]-constants[1]; - computedConstants[65] = (constants[0] < constants[1])-(constants[2] > constants[3]); - computedConstants[66] = (constants[0] < constants[1])-(constants[2]+constants[3]); - computedConstants[67] = (constants[0] < constants[1])-constants[2]; - computedConstants[68] = constants[0]-(-constants[1]); - computedConstants[69] = constants[0]-(-constants[1]*constants[2]); - computedConstants[70] = -constants[0]; - computedConstants[71] = -(constants[0] < constants[1]); - computedConstants[72] = constants[0]*constants[1]; - computedConstants[73] = constants[0]*constants[1]*constants[2]; - computedConstants[74] = (constants[0] < constants[1])*(constants[2] > constants[3]); - computedConstants[75] = (constants[0]+constants[1])*(constants[2] > constants[3]); - computedConstants[76] = constants[0]*(constants[1] > constants[2]); - computedConstants[77] = (constants[0]-constants[1])*(constants[2] > constants[3]); - computedConstants[78] = -constants[0]*(constants[1] > constants[2]); - computedConstants[79] = (constants[0] < constants[1])*(constants[2]+constants[3]); - computedConstants[80] = (constants[0] < constants[1])*constants[2]; - computedConstants[81] = (constants[0] < constants[1])*(constants[2]-constants[3]); - computedConstants[82] = (constants[0] < constants[1])*-constants[2]; - computedConstants[83] = constants[0]/constants[1]; - computedConstants[84] = (constants[0] < constants[1])/(constants[3] > constants[2]); - computedConstants[85] = (constants[0]+constants[1])/(constants[3] > constants[2]); - computedConstants[86] = constants[0]/(constants[2] > constants[1]); - computedConstants[87] = (constants[0]-constants[1])/(constants[3] > constants[2]); - computedConstants[88] = -constants[0]/(constants[2] > constants[1]); - computedConstants[89] = (constants[0] < constants[1])/(constants[2]+constants[3]); - computedConstants[90] = (constants[0] < constants[1])/constants[2]; - computedConstants[91] = (constants[0] < constants[1])/(constants[2]-constants[3]); - computedConstants[92] = (constants[0] < constants[1])/-constants[2]; - computedConstants[93] = (constants[0] < constants[1])/(constants[2]*constants[3]); - computedConstants[94] = (constants[0] < constants[1])/(constants[2]/constants[3]); - computedConstants[95] = sqrt(constants[0]); - computedConstants[96] = pow(constants[0], 2.0); - computedConstants[97] = pow(constants[0], 3.0); - computedConstants[98] = pow(constants[0], constants[1]); - computedConstants[99] = pow(constants[0] <= constants[1], constants[2] >= constants[3]); - computedConstants[100] = pow(constants[0]+constants[1], constants[2] >= constants[3]); - computedConstants[101] = pow(constants[0], constants[1] >= constants[2]); - computedConstants[102] = pow(constants[0]-constants[1], constants[2] >= constants[3]); - computedConstants[103] = pow(-constants[0], constants[1] >= constants[2]); - computedConstants[104] = pow(constants[0]*constants[1], constants[2] >= constants[3]); - computedConstants[105] = pow(constants[0]/constants[1], constants[2] >= constants[3]); - computedConstants[106] = pow(constants[0] <= constants[1], constants[2]+constants[3]); - computedConstants[107] = pow(constants[0] <= constants[1], constants[2]); - computedConstants[108] = pow(constants[0] <= constants[1], constants[2]-constants[3]); - computedConstants[109] = pow(constants[0] <= constants[1], -constants[2]); - computedConstants[110] = pow(constants[0] <= constants[1], constants[2]*constants[3]); - computedConstants[111] = pow(constants[0] <= constants[1], constants[2]/constants[3]); - computedConstants[112] = pow(constants[0] <= constants[1], pow(constants[2], constants[3])); - computedConstants[113] = pow(constants[0] <= constants[1], pow(constants[2], 1.0/constants[3])); - computedConstants[114] = sqrt(constants[0]); - computedConstants[115] = sqrt(constants[0]); - computedConstants[116] = pow(constants[0], 1.0/3.0); - computedConstants[117] = pow(constants[0], 1.0/constants[1]); - computedConstants[118] = pow(constants[0] < constants[1], 1.0/(constants[3] > constants[2])); - computedConstants[119] = pow(constants[0]+constants[1], 1.0/(constants[3] > constants[2])); - computedConstants[120] = pow(constants[0], 1.0/(constants[2] > constants[1])); - computedConstants[121] = pow(constants[0]-constants[1], 1.0/(constants[3] > constants[2])); - computedConstants[122] = pow(-constants[0], 1.0/(constants[2] > constants[1])); - computedConstants[123] = pow(constants[0]*constants[1], 1.0/(constants[3] > constants[2])); - computedConstants[124] = pow(constants[0]/constants[1], 1.0/(constants[3] > constants[2])); - computedConstants[125] = pow(constants[0] < constants[1], 1.0/(constants[2]+constants[3])); - computedConstants[126] = pow(constants[0] < constants[1], 1.0/constants[2]); - computedConstants[127] = pow(constants[0] < constants[1], 1.0/(constants[2]-constants[3])); - computedConstants[128] = pow(constants[0] < constants[1], 1.0/-constants[2]); - computedConstants[129] = pow(constants[0] < constants[1], 1.0/(constants[2]*constants[3])); - computedConstants[130] = pow(constants[0] < constants[1], 1.0/(constants[2]/constants[3])); - computedConstants[131] = pow(constants[0] < constants[1], 1.0/pow(constants[2], constants[3])); - computedConstants[132] = pow(constants[0] < constants[1], 1.0/pow(constants[2], 1.0/constants[3])); - computedConstants[133] = fabs(constants[0]); - computedConstants[134] = exp(constants[0]); - computedConstants[135] = log(constants[0]); + computedConstants[28] = (constants[0] < constants[1]) || (constants[2] > constants[3]); + computedConstants[29] = (constants[0]+constants[1]) || (constants[2] > constants[3]); + computedConstants[30] = constants[0] || (constants[1] > constants[2]); + computedConstants[31] = (constants[0]-constants[1]) || (constants[2] > constants[3]); + computedConstants[32] = -constants[0] || (constants[1] > constants[2]); + computedConstants[33] = pow(constants[0], constants[1]) || (constants[2] > constants[3]); + computedConstants[34] = pow(constants[0], 1.0/constants[1]) || (constants[2] > constants[3]); + computedConstants[35] = (constants[0] < constants[1]) || (constants[2]+constants[3]); + computedConstants[36] = (constants[0] < constants[1]) || constants[2]; + computedConstants[37] = (constants[0] < constants[1]) || (constants[2]-constants[3]); + computedConstants[38] = (constants[0] < constants[1]) || -constants[2]; + computedConstants[39] = (constants[0] < constants[1]) || pow(constants[2], constants[3]); + computedConstants[40] = (constants[0] < constants[1]) || pow(constants[2], 1.0/constants[3]); + computedConstants[41] = constants[0]/(constants[1] || constants[2]); + computedConstants[42] = xor(constants[0], constants[1]); + computedConstants[43] = xor(constants[0], xor(constants[1], constants[2])); + computedConstants[44] = xor(constants[0] < constants[1], constants[2] > constants[3]); + computedConstants[45] = xor(constants[0]+constants[1], constants[2] > constants[3]); + computedConstants[46] = xor(constants[0], constants[1] > constants[2]); + computedConstants[47] = xor(constants[0]-constants[1], constants[2] > constants[3]); + computedConstants[48] = xor(-constants[0], constants[1] > constants[2]); + computedConstants[49] = xor(pow(constants[0], constants[1]), constants[2] > constants[3]); + computedConstants[50] = xor(pow(constants[0], 1.0/constants[1]), constants[2] > constants[3]); + computedConstants[51] = xor(constants[0] < constants[1], constants[2]+constants[3]); + computedConstants[52] = xor(constants[0] < constants[1], constants[2]); + computedConstants[53] = xor(constants[0] < constants[1], constants[2]-constants[3]); + computedConstants[54] = xor(constants[0] < constants[1], -constants[2]); + computedConstants[55] = xor(constants[0] < constants[1], pow(constants[2], constants[3])); + computedConstants[56] = xor(constants[0] < constants[1], pow(constants[2], 1.0/constants[3])); + computedConstants[57] = !constants[0]; + computedConstants[58] = constants[0]+constants[1]+constants[2]; + computedConstants[59] = (constants[0] < constants[1])+(constants[2] > constants[3]); + computedConstants[60] = constants[0]; + computedConstants[61] = constants[0]-constants[1]; + computedConstants[62] = (constants[0] < constants[1])-(constants[2] > constants[3]); + computedConstants[63] = (constants[0] < constants[1])-(constants[2]+constants[3]); + computedConstants[64] = (constants[0] < constants[1])-constants[2]; + computedConstants[65] = constants[0]-(-constants[1]); + computedConstants[66] = constants[0]-(-constants[1]*constants[2]); + computedConstants[67] = -constants[0]; + computedConstants[68] = -(constants[0] < constants[1]); + computedConstants[69] = constants[0]*constants[1]; + computedConstants[70] = constants[0]*constants[1]*constants[2]; + computedConstants[71] = (constants[0] < constants[1])*(constants[2] > constants[3]); + computedConstants[72] = (constants[0]+constants[1])*(constants[2] > constants[3]); + computedConstants[73] = constants[0]*(constants[1] > constants[2]); + computedConstants[74] = (constants[0]-constants[1])*(constants[2] > constants[3]); + computedConstants[75] = -constants[0]*(constants[1] > constants[2]); + computedConstants[76] = (constants[0] < constants[1])*(constants[2]+constants[3]); + computedConstants[77] = (constants[0] < constants[1])*constants[2]; + computedConstants[78] = (constants[0] < constants[1])*(constants[2]-constants[3]); + computedConstants[79] = (constants[0] < constants[1])*-constants[2]; + computedConstants[80] = constants[0]/constants[1]; + computedConstants[81] = (constants[0] < constants[1])/(constants[3] > constants[2]); + computedConstants[82] = (constants[0]+constants[1])/(constants[3] > constants[2]); + computedConstants[83] = constants[0]/(constants[2] > constants[1]); + computedConstants[84] = (constants[0]-constants[1])/(constants[3] > constants[2]); + computedConstants[85] = -constants[0]/(constants[2] > constants[1]); + computedConstants[86] = (constants[0] < constants[1])/(constants[2]+constants[3]); + computedConstants[87] = (constants[0] < constants[1])/constants[2]; + computedConstants[88] = (constants[0] < constants[1])/(constants[2]-constants[3]); + computedConstants[89] = (constants[0] < constants[1])/-constants[2]; + computedConstants[90] = (constants[0] < constants[1])/(constants[2]*constants[3]); + computedConstants[91] = (constants[0] < constants[1])/(constants[2]/constants[3]); + computedConstants[92] = sqrt(constants[0]); + computedConstants[93] = pow(constants[0], 2.0); + computedConstants[94] = pow(constants[0], 3.0); + computedConstants[95] = pow(constants[0], constants[1]); + computedConstants[96] = pow(constants[0] <= constants[1], constants[2] >= constants[3]); + computedConstants[97] = pow(constants[0]+constants[1], constants[2] >= constants[3]); + computedConstants[98] = pow(constants[0], constants[1] >= constants[2]); + computedConstants[99] = pow(constants[0]-constants[1], constants[2] >= constants[3]); + computedConstants[100] = pow(-constants[0], constants[1] >= constants[2]); + computedConstants[101] = pow(constants[0]*constants[1], constants[2] >= constants[3]); + computedConstants[102] = pow(constants[0]/constants[1], constants[2] >= constants[3]); + computedConstants[103] = pow(constants[0] <= constants[1], constants[2]+constants[3]); + computedConstants[104] = pow(constants[0] <= constants[1], constants[2]); + computedConstants[105] = pow(constants[0] <= constants[1], constants[2]-constants[3]); + computedConstants[106] = pow(constants[0] <= constants[1], -constants[2]); + computedConstants[107] = pow(constants[0] <= constants[1], constants[2]*constants[3]); + computedConstants[108] = pow(constants[0] <= constants[1], constants[2]/constants[3]); + computedConstants[109] = pow(constants[0] <= constants[1], pow(constants[2], constants[3])); + computedConstants[110] = pow(constants[0] <= constants[1], pow(constants[2], 1.0/constants[3])); + computedConstants[111] = sqrt(constants[0]); + computedConstants[112] = sqrt(constants[0]); + computedConstants[113] = pow(constants[0], 1.0/0.5); + computedConstants[114] = pow(constants[0], 1.0/3.0); + computedConstants[115] = pow(constants[0], 1.0/constants[1]); + computedConstants[116] = pow(constants[0] < constants[1], 1.0/(constants[3] > constants[2])); + computedConstants[117] = pow(constants[0]+constants[1], 1.0/(constants[3] > constants[2])); + computedConstants[118] = pow(constants[0], 1.0/(constants[2] > constants[1])); + computedConstants[119] = pow(constants[0]-constants[1], 1.0/(constants[3] > constants[2])); + computedConstants[120] = pow(-constants[0], 1.0/(constants[2] > constants[1])); + computedConstants[121] = pow(constants[0]*constants[1], 1.0/(constants[3] > constants[2])); + computedConstants[122] = pow(constants[0]/constants[1], 1.0/(constants[3] > constants[2])); + computedConstants[123] = pow(constants[0] < constants[1], 1.0/(constants[2]+constants[3])); + computedConstants[124] = pow(constants[0] < constants[1], 1.0/constants[2]); + computedConstants[125] = pow(constants[0] < constants[1], 1.0/(constants[2]-constants[3])); + computedConstants[126] = pow(constants[0] < constants[1], 1.0/-constants[2]); + computedConstants[127] = pow(constants[0] < constants[1], 1.0/(constants[2]*constants[3])); + computedConstants[128] = pow(constants[0] < constants[1], 1.0/(constants[2]/constants[3])); + computedConstants[129] = pow(constants[0] < constants[1], 1.0/pow(constants[2], constants[3])); + computedConstants[130] = pow(constants[0] < constants[1], 1.0/pow(constants[2], 1.0/constants[3])); + computedConstants[131] = fabs(constants[0]); + computedConstants[132] = exp(constants[0]); + computedConstants[133] = log(constants[0]); + computedConstants[134] = log10(constants[0]); + computedConstants[135] = log(constants[0])/log(2.0); computedConstants[136] = log10(constants[0]); - computedConstants[137] = log(constants[0])/log(2.0); - computedConstants[138] = log10(constants[0]); - computedConstants[139] = log(constants[0])/log(constants[1]); - computedConstants[140] = ceil(constants[0]); - computedConstants[141] = floor(constants[0]); - computedConstants[142] = min(constants[0], constants[1]); - computedConstants[143] = min(constants[0], min(constants[1], constants[2])); - computedConstants[144] = max(constants[0], constants[1]); - computedConstants[145] = max(constants[0], max(constants[1], constants[2])); - computedConstants[146] = fmod(constants[0], constants[1]); - computedConstants[147] = sin(constants[0]); - computedConstants[148] = cos(constants[0]); - computedConstants[149] = tan(constants[0]); - computedConstants[150] = sec(constants[0]); - computedConstants[151] = csc(constants[0]); - computedConstants[152] = cot(constants[0]); - computedConstants[153] = sinh(constants[0]); - computedConstants[154] = cosh(constants[0]); - computedConstants[155] = tanh(constants[0]); - computedConstants[156] = sech(constants[0]); - computedConstants[157] = csch(constants[0]); - computedConstants[158] = coth(constants[0]); - computedConstants[159] = asin(constants[0]); - computedConstants[160] = acos(constants[0]); - computedConstants[161] = atan(constants[0]); - computedConstants[162] = asec(constants[0]); - computedConstants[163] = acsc(constants[0]); - computedConstants[164] = acot(constants[0]); - computedConstants[165] = asinh(constants[0]); - computedConstants[166] = acosh(constants[0]); - computedConstants[167] = atanh(constants[0]/2.0); - computedConstants[168] = asech(constants[0]); - computedConstants[169] = acsch(constants[0]); - computedConstants[170] = acoth(2.0*constants[0]); - computedConstants[171] = (constants[0] > constants[1])?constants[0]:NAN; - computedConstants[172] = (constants[0] > constants[1])?constants[0]:constants[2]; - computedConstants[173] = (constants[0] > constants[1])?constants[0]:(constants[2] > constants[3])?constants[2]:(constants[4] > constants[5])?constants[4]:NAN; - computedConstants[174] = (constants[0] > constants[1])?constants[0]:(constants[2] > constants[3])?constants[2]:(constants[4] > constants[5])?constants[4]:constants[6]; - computedConstants[175] = 123.0+((constants[0] > constants[1])?constants[0]:NAN); - computedConstants[180] = constants[0]; - computedConstants[187] = (constants[0] && constants[1])+((constants[2] > constants[3])?constants[1]:NAN)+constants[4]+(constants[5] && constants[6]); - computedConstants[188] = (constants[0] && constants[1])-(((constants[2] > constants[3])?constants[1]:NAN)-(constants[4]-((constants[2] > constants[3])?constants[1]:NAN)))-(constants[5] && constants[6]); - computedConstants[189] = (constants[0] && constants[1])*((constants[2] > constants[3])?constants[1]:NAN)*constants[4]*((constants[2] > constants[3])?constants[1]:NAN)*(constants[5] && constants[6]); - computedConstants[190] = (constants[0] && constants[1])/(((constants[2] > constants[3])?constants[1]:NAN)/(constants[4]/((constants[2] > constants[3])?constants[1]:NAN))); - computedConstants[191] = (constants[0] || constants[1]) && xor(constants[0], constants[1]) && ((constants[2] > constants[3])?constants[1]:NAN) && constants[4] && ((constants[2] > constants[3])?constants[1]:NAN) && xor(constants[0], constants[1]) && (constants[0] || constants[1]); - computedConstants[192] = (constants[0] && constants[1]) || xor(constants[0], constants[1]) || ((constants[2] > constants[3])?constants[1]:NAN) || constants[4] || ((constants[2] > constants[3])?constants[1]:NAN) || xor(constants[0], constants[1]) || (constants[0] && constants[1]); - computedConstants[193] = xor(constants[0] && constants[1], xor(constants[0] || constants[1], xor((constants[2] > constants[3])?constants[1]:NAN, xor(xor(xor(constants[4], (constants[2] > constants[3])?constants[1]:NAN), constants[0] || constants[1]), constants[0] && constants[1])))); - computedConstants[194] = pow(constants[0] && constants[1], pow((constants[2] > constants[3])?constants[1]:NAN, pow(pow(constants[4], (constants[2] > constants[3])?constants[1]:NAN), constants[0] && constants[1]))); - computedConstants[195] = pow(pow(pow(constants[0] && constants[1], 1.0/pow((constants[2] > constants[3])?constants[1]:NAN, 1.0/constants[4])), 1.0/((constants[2] > constants[3])?constants[1]:NAN)), 1.0/(constants[0] && constants[1])); - computedConstants[196] = -(constants[0] && constants[1])+-((constants[2] > constants[3])?constants[1]:NAN); + computedConstants[137] = log(constants[0])/log(constants[1]); + computedConstants[138] = ceil(constants[0]); + computedConstants[139] = floor(constants[0]); + computedConstants[140] = fmin(constants[0], constants[1]); + computedConstants[141] = fmin(constants[0], fmin(constants[1], constants[2])); + computedConstants[142] = fmax(constants[0], constants[1]); + computedConstants[143] = fmax(constants[0], fmax(constants[1], constants[2])); + computedConstants[144] = fmod(constants[0], constants[1]); + computedConstants[145] = sin(constants[0]); + computedConstants[146] = cos(constants[0]); + computedConstants[147] = tan(constants[0]); + computedConstants[148] = sec(constants[0]); + computedConstants[149] = csc(constants[0]); + computedConstants[150] = cot(constants[0]); + computedConstants[151] = sinh(constants[0]); + computedConstants[152] = cosh(constants[0]); + computedConstants[153] = tanh(constants[0]); + computedConstants[154] = sech(constants[0]); + computedConstants[155] = csch(constants[0]); + computedConstants[156] = coth(constants[0]); + computedConstants[157] = asin(constants[0]); + computedConstants[158] = acos(constants[0]); + computedConstants[159] = atan(constants[0]); + computedConstants[160] = asec(constants[0]); + computedConstants[161] = acsc(constants[0]); + computedConstants[162] = acot(constants[0]); + computedConstants[163] = asinh(constants[0]); + computedConstants[164] = acosh(constants[0]); + computedConstants[165] = atanh(constants[0]/2.0); + computedConstants[166] = asech(constants[0]); + computedConstants[167] = acsch(constants[0]); + computedConstants[168] = acoth(2.0*constants[0]); + computedConstants[170] = (constants[0] > constants[1])?constants[0]:NAN; + computedConstants[171] = (constants[0] < constants[1])?constants[0]:NAN; + computedConstants[172] = constants[0]; + computedConstants[173] = (constants[0] > constants[1])?constants[0]:constants[2]; + computedConstants[174] = (constants[0] > constants[1])?constants[0]:(constants[2] > constants[3])?constants[2]:(constants[4] > constants[5])?constants[4]:NAN; + computedConstants[175] = (constants[0] < constants[1])?constants[0]:(constants[2] > constants[3])?constants[2]:(constants[4] > constants[5])?constants[4]:NAN; + computedConstants[176] = (constants[0] > constants[1])?constants[0]:(constants[2] > constants[3])?constants[2]:(constants[4] > constants[5])?constants[4]:constants[6]; + computedConstants[177] = 123.0+((constants[0] > constants[1])?constants[0]:NAN); + computedConstants[178] = 123.0+((constants[0] < constants[1])?constants[0]:NAN); + computedConstants[183] = constants[0]; + computedConstants[190] = (constants[0] && constants[1])+((constants[2] > constants[3])?constants[1]:NAN)+constants[4]+(constants[5] && constants[6]); + computedConstants[191] = (constants[0] && constants[1])+((constants[2] < constants[3])?constants[1]:NAN)+constants[4]+(constants[5] && constants[6]); + computedConstants[192] = (constants[0] && constants[1])-(((constants[2] > constants[3])?constants[1]:NAN)-(constants[4]-((constants[2] > constants[3])?constants[1]:NAN)))-(constants[5] && constants[6]); + computedConstants[193] = (constants[0] && constants[1])-(((constants[2] < constants[3])?constants[1]:NAN)-(constants[4]-((constants[2] < constants[3])?constants[1]:NAN)))-(constants[5] && constants[6]); + computedConstants[194] = (constants[0] && constants[1])*((constants[2] > constants[3])?constants[1]:NAN)*constants[4]*((constants[2] > constants[3])?constants[1]:NAN)*(constants[5] && constants[6]); + computedConstants[195] = (constants[0] && constants[1])*((constants[2] < constants[3])?constants[1]:NAN)*constants[4]*((constants[2] < constants[3])?constants[1]:NAN)*(constants[5] && constants[6]); + computedConstants[196] = (constants[0] && constants[1])/(((constants[2] > constants[3])?constants[1]:NAN)/(constants[4]/((constants[2] > constants[3])?constants[1]:NAN))); + computedConstants[197] = (constants[0] && constants[1])/(((constants[2] < constants[3])?constants[1]:NAN)/(constants[4]/((constants[2] < constants[3])?constants[1]:NAN))); + computedConstants[198] = (constants[0] || constants[1]) && xor(constants[0], constants[1]) && ((constants[2] > constants[3])?constants[1]:NAN) && constants[4] && ((constants[2] > constants[3])?constants[1]:NAN) && xor(constants[0], constants[1]) && (constants[0] || constants[1]); + computedConstants[199] = (constants[0] && constants[1]) || xor(constants[0], constants[1]) || ((constants[2] > constants[3])?constants[1]:NAN) || constants[4] || ((constants[2] > constants[3])?constants[1]:NAN) || xor(constants[0], constants[1]) || (constants[0] && constants[1]); + computedConstants[200] = xor(constants[0] && constants[1], xor(constants[0] || constants[1], xor((constants[2] > constants[3])?constants[1]:NAN, xor(xor(xor(constants[4], (constants[2] > constants[3])?constants[1]:NAN), constants[0] || constants[1]), constants[0] && constants[1])))); + computedConstants[201] = pow(constants[0] && constants[1], pow((constants[2] > constants[3])?constants[1]:NAN, pow(pow(constants[4], (constants[2] > constants[3])?constants[1]:NAN), constants[0] && constants[1]))); + computedConstants[202] = pow(pow(pow(constants[0] && constants[1], 1.0/pow((constants[2] > constants[3])?constants[1]:NAN, 1.0/constants[4])), 1.0/((constants[2] > constants[3])?constants[1]:NAN)), 1.0/(constants[0] && constants[1])); + computedConstants[203] = -(constants[0] && constants[1])+-((constants[2] > constants[3])?constants[1]:NAN); + computedConstants[204] = -(constants[0] && constants[1])+-((constants[2] < constants[3])?constants[1]:NAN); } void computeRates(double voi, double *states, double *rates, double *constants, double *computedConstants, double *algebraic, double *externals, ExternalVariable externalVariable) @@ -650,6 +653,9 @@ void computeRates(double voi, double *states, double *rates, double *constants, void computeVariables(double voi, double *states, double *rates, double *constants, double *computedConstants, double *algebraic, double *externals, ExternalVariable externalVariable) { + algebraic[0] = states[0] || states[0]; + algebraic[1] = states[0] || states[0] || constants[0]; + algebraic[2] = constants[0]/xor(constants[1], states[0]); externals[0] = externalVariable(voi, states, rates, constants, computedConstants, algebraic, externals, 0); findRoot0(voi, states, rates, constants, computedConstants, algebraic, externals); } diff --git a/tests/resources/coverage/generator/model.cellml b/tests/resources/coverage/generator/model.cellml index 6a2574eed1..9ea2a4e296 100644 --- a/tests/resources/coverage/generator/model.cellml +++ b/tests/resources/coverage/generator/model.cellml @@ -129,6 +129,7 @@ + @@ -184,11 +185,16 @@ + + + + + @@ -201,15 +207,20 @@ + + + + + @@ -349,8 +360,8 @@ m - n o + n @@ -373,8 +384,8 @@ m - n o + n @@ -640,8 +651,8 @@ eqnOr - m - n + x + x @@ -649,9 +660,9 @@ eqnOrMultiple + x + x m - n - o @@ -1139,7 +1150,7 @@ n - o + x @@ -1984,6 +1995,17 @@ m + + + eqnRootSqr + + + + 0.5 + + m + + eqnRootCube @@ -2685,6 +2707,11 @@ + + + eqnPiecewise + + eqnPiecewisePiece @@ -2699,6 +2726,29 @@ + + + eqnPiecewisePiece2 + + + m + + + m + n + + + + + + + eqnPiecewiseOtherwise + + + m + + + eqnPiecewisePieceOtherwise @@ -2746,6 +2796,36 @@ + + + eqnPiecewisePiecePiecePiece2 + + + m + + + m + n + + + + o + + + o + p + + + + q + + + q + r + + + + eqnPiecewisePiecePiecePieceOtherwise @@ -2799,6 +2879,24 @@ + + + eqnWithPiecewise2 + + + 123 + + + m + + + m + n + + + + + @@ -2920,6 +3018,40 @@ + + + eqnCoverageForPlusOperator2 + + + + + + + m + n + + + + + + n + + + o + p + + + + q + + + + + r + s + + + eqnCoverageForMinusOperator @@ -2967,6 +3099,53 @@ + + + eqnCoverageForMinusOperator2 + + + + + + + m + n + + + + + + n + + + o + p + + + + + + q + + + n + + + o + p + + + + + + + + + r + s + + + eqnCoverageForTimesOperator @@ -3014,6 +3193,53 @@ + + + eqnCoverageForTimesOperator2 + + + + + + + m + n + + + + + + n + + + o + p + + + + + + q + + + n + + + o + p + + + + + + + + + r + s + + + eqnCoverageForDivideOperator @@ -3053,6 +3279,45 @@ + + + eqnCoverageForDivideOperator2 + + + + + m + n + + + + + + n + + + o + p + + + + + + q + + + n + + + o + p + + + + + + + eqnCoverageForAndOperator @@ -3372,6 +3637,34 @@ + + + eqnCoverageForMinusUnary2 + + + + + + + m + n + + + + + + + n + + + o + p + + + + + + diff --git a/tests/resources/coverage/generator/model.implementation.out b/tests/resources/coverage/generator/model.implementation.out index 2b2639f4b9..3ba38209d5 100644 --- a/tests/resources/coverage/generator/model.implementation.out +++ b/tests/resources/coverage/generator/model.implementation.out @@ -5,16 +5,6 @@ double xor(double x, double y) return (x != 0.0) ^ (y != 0.0); } -double min(double x, double y) -{ - return (x < y)?x:y; -} - -double max(double x, double y) -{ - return (x > y)?x:y; -} - double sec(double x) { return 1.0/cos(x); @@ -62,23 +52,17 @@ double acot(double x) double asech(double x) { - double oneOverX = 1.0/x; - - return log(oneOverX+sqrt(oneOverX*oneOverX-1.0)); + return acosh(1.0/x); } double acsch(double x) { - double oneOverX = 1.0/x; - - return log(oneOverX+sqrt(oneOverX*oneOverX+1.0)); + return asinh(1.0/x); } double acoth(double x) { - double oneOverX = 1.0/x; - - return 0.5*log((1.0+oneOverX)/(1.0-oneOverX)); + return atanh(1.0/x); } double * createStatesArray() @@ -164,11 +148,11 @@ void objectiveFunction0(double *u, double *f, void *data) double *algebraic = ((RootFindingInfo *) data)->algebraic; double *externals = ((RootFindingInfo *) data)->externals; - algebraic[0] = u[0]; - algebraic[1] = u[1]; + algebraic[3] = u[0]; + algebraic[4] = u[1]; - f[0] = algebraic[0]+algebraic[1]+states[0]-0.0; - f[1] = algebraic[0]-algebraic[1]-(computedConstants[197]+computedConstants[198]); + f[0] = algebraic[3]+algebraic[4]+states[0]-0.0; + f[1] = algebraic[3]-algebraic[4]-(computedConstants[205]+computedConstants[206]); } void findRoot0(double voi, double *states, double *rates, double *constants, double *computedConstants, double *algebraic, double *externals) @@ -176,13 +160,13 @@ void findRoot0(double voi, double *states, double *rates, double *constants, dou RootFindingInfo rfi = { voi, states, rates, constants, computedConstants, algebraic, externals }; double u[2]; - u[0] = algebraic[0]; - u[1] = algebraic[1]; + u[0] = algebraic[3]; + u[1] = algebraic[4]; nlaSolve(objectiveFunction0, u, 2, &rfi); - algebraic[0] = u[0]; - algebraic[1] = u[1]; + algebraic[3] = u[0]; + algebraic[4] = u[1]; } void initialiseVariables(double *states, double *rates, double *constants, double *computedConstants, double *algebraic) @@ -195,20 +179,21 @@ void initialiseVariables(double *states, double *rates, double *constants, doubl constants[4] = 5.0; constants[5] = 6.0; constants[6] = 7.0; - computedConstants[176] = 123.0; - computedConstants[177] = 123.456789; - computedConstants[178] = 123.0e99; - computedConstants[179] = 123.456789e99; - computedConstants[181] = 1.0; - computedConstants[182] = 0.0; - computedConstants[183] = 2.71828182845905; - computedConstants[184] = 3.14159265358979; - computedConstants[185] = INFINITY; - computedConstants[186] = NAN; - computedConstants[197] = 1.0; - computedConstants[198] = 3.0; - algebraic[0] = 1.0; - algebraic[1] = 2.0; + computedConstants[169] = NAN; + computedConstants[179] = 123.0; + computedConstants[180] = 123.456789; + computedConstants[181] = 123.0e99; + computedConstants[182] = 123.456789e99; + computedConstants[184] = 1.0; + computedConstants[185] = 0.0; + computedConstants[186] = 2.71828182845905; + computedConstants[187] = 3.14159265358979; + computedConstants[188] = INFINITY; + computedConstants[189] = NAN; + computedConstants[205] = 1.0; + computedConstants[206] = 3.0; + algebraic[3] = 1.0; + algebraic[4] = 2.0; } void computeComputedConstants(double *constants, double *computedConstants) @@ -222,9 +207,9 @@ void computeComputedConstants(double *constants, double *computedConstants) computedConstants[6] = leq(constants[0], constants[1]); computedConstants[7] = constants[0]/leq(constants[1], constants[2]); computedConstants[8] = gt(constants[0], constants[1]); - computedConstants[9] = constants[0]/gt(constants[1], constants[2]); + computedConstants[9] = constants[0]/gt(constants[2], constants[1]); computedConstants[10] = geq(constants[0], constants[1]); - computedConstants[11] = constants[0]/geq(constants[1], constants[2]); + computedConstants[11] = constants[0]/geq(constants[2], constants[1]); computedConstants[12] = and(constants[0], constants[1]); computedConstants[13] = and(constants[0], and(constants[1], constants[2])); computedConstants[14] = and(lt(constants[0], constants[1]), gt(constants[2], constants[3])); @@ -241,165 +226,172 @@ void computeComputedConstants(double *constants, double *computedConstants) computedConstants[25] = and(lt(constants[0], constants[1]), pow(constants[2], constants[3])); computedConstants[26] = and(lt(constants[0], constants[1]), pow(constants[2], 1.0/constants[3])); computedConstants[27] = constants[0]/and(constants[1], constants[2]); - computedConstants[28] = or(constants[0], constants[1]); - computedConstants[29] = or(constants[0], or(constants[1], constants[2])); - computedConstants[30] = or(lt(constants[0], constants[1]), gt(constants[2], constants[3])); - computedConstants[31] = or(constants[0]+constants[1], gt(constants[2], constants[3])); - computedConstants[32] = or(constants[0], gt(constants[1], constants[2])); - computedConstants[33] = or(constants[0]-constants[1], gt(constants[2], constants[3])); - computedConstants[34] = or(-constants[0], gt(constants[1], constants[2])); - computedConstants[35] = or(pow(constants[0], constants[1]), gt(constants[2], constants[3])); - computedConstants[36] = or(pow(constants[0], 1.0/constants[1]), gt(constants[2], constants[3])); - computedConstants[37] = or(lt(constants[0], constants[1]), constants[2]+constants[3]); - computedConstants[38] = or(lt(constants[0], constants[1]), constants[2]); - computedConstants[39] = or(lt(constants[0], constants[1]), constants[2]-constants[3]); - computedConstants[40] = or(lt(constants[0], constants[1]), -constants[2]); - computedConstants[41] = or(lt(constants[0], constants[1]), pow(constants[2], constants[3])); - computedConstants[42] = or(lt(constants[0], constants[1]), pow(constants[2], 1.0/constants[3])); - computedConstants[43] = constants[0]/or(constants[1], constants[2]); - computedConstants[44] = xor(constants[0], constants[1]); - computedConstants[45] = xor(constants[0], xor(constants[1], constants[2])); - computedConstants[46] = xor(lt(constants[0], constants[1]), gt(constants[2], constants[3])); - computedConstants[47] = xor(constants[0]+constants[1], gt(constants[2], constants[3])); - computedConstants[48] = xor(constants[0], gt(constants[1], constants[2])); - computedConstants[49] = xor(constants[0]-constants[1], gt(constants[2], constants[3])); - computedConstants[50] = xor(-constants[0], gt(constants[1], constants[2])); - computedConstants[51] = xor(pow(constants[0], constants[1]), gt(constants[2], constants[3])); - computedConstants[52] = xor(pow(constants[0], 1.0/constants[1]), gt(constants[2], constants[3])); - computedConstants[53] = xor(lt(constants[0], constants[1]), constants[2]+constants[3]); - computedConstants[54] = xor(lt(constants[0], constants[1]), constants[2]); - computedConstants[55] = xor(lt(constants[0], constants[1]), constants[2]-constants[3]); - computedConstants[56] = xor(lt(constants[0], constants[1]), -constants[2]); - computedConstants[57] = xor(lt(constants[0], constants[1]), pow(constants[2], constants[3])); - computedConstants[58] = xor(lt(constants[0], constants[1]), pow(constants[2], 1.0/constants[3])); - computedConstants[59] = constants[0]/xor(constants[1], constants[2]); - computedConstants[60] = not(constants[0]); - computedConstants[61] = constants[0]+constants[1]+constants[2]; - computedConstants[62] = lt(constants[0], constants[1])+gt(constants[2], constants[3]); - computedConstants[63] = constants[0]; - computedConstants[64] = constants[0]-constants[1]; - computedConstants[65] = lt(constants[0], constants[1])-gt(constants[2], constants[3]); - computedConstants[66] = lt(constants[0], constants[1])-(constants[2]+constants[3]); - computedConstants[67] = lt(constants[0], constants[1])-constants[2]; - computedConstants[68] = constants[0]-(-constants[1]); - computedConstants[69] = constants[0]-(-constants[1]*constants[2]); - computedConstants[70] = -constants[0]; - computedConstants[71] = -lt(constants[0], constants[1]); - computedConstants[72] = constants[0]*constants[1]; - computedConstants[73] = constants[0]*constants[1]*constants[2]; - computedConstants[74] = lt(constants[0], constants[1])*gt(constants[2], constants[3]); - computedConstants[75] = (constants[0]+constants[1])*gt(constants[2], constants[3]); - computedConstants[76] = constants[0]*gt(constants[1], constants[2]); - computedConstants[77] = (constants[0]-constants[1])*gt(constants[2], constants[3]); - computedConstants[78] = -constants[0]*gt(constants[1], constants[2]); - computedConstants[79] = lt(constants[0], constants[1])*(constants[2]+constants[3]); - computedConstants[80] = lt(constants[0], constants[1])*constants[2]; - computedConstants[81] = lt(constants[0], constants[1])*(constants[2]-constants[3]); - computedConstants[82] = lt(constants[0], constants[1])*-constants[2]; - computedConstants[83] = constants[0]/constants[1]; - computedConstants[84] = lt(constants[0], constants[1])/gt(constants[3], constants[2]); - computedConstants[85] = (constants[0]+constants[1])/gt(constants[3], constants[2]); - computedConstants[86] = constants[0]/gt(constants[2], constants[1]); - computedConstants[87] = (constants[0]-constants[1])/gt(constants[3], constants[2]); - computedConstants[88] = -constants[0]/gt(constants[2], constants[1]); - computedConstants[89] = lt(constants[0], constants[1])/(constants[2]+constants[3]); - computedConstants[90] = lt(constants[0], constants[1])/constants[2]; - computedConstants[91] = lt(constants[0], constants[1])/(constants[2]-constants[3]); - computedConstants[92] = lt(constants[0], constants[1])/-constants[2]; - computedConstants[93] = lt(constants[0], constants[1])/(constants[2]*constants[3]); - computedConstants[94] = lt(constants[0], constants[1])/(constants[2]/constants[3]); - computedConstants[95] = sqrt(constants[0]); - computedConstants[96] = pow(constants[0], 2.0); - computedConstants[97] = pow(constants[0], 3.0); - computedConstants[98] = pow(constants[0], constants[1]); - computedConstants[99] = pow(leq(constants[0], constants[1]), geq(constants[2], constants[3])); - computedConstants[100] = pow(constants[0]+constants[1], geq(constants[2], constants[3])); - computedConstants[101] = pow(constants[0], geq(constants[1], constants[2])); - computedConstants[102] = pow(constants[0]-constants[1], geq(constants[2], constants[3])); - computedConstants[103] = pow(-constants[0], geq(constants[1], constants[2])); - computedConstants[104] = pow(constants[0]*constants[1], geq(constants[2], constants[3])); - computedConstants[105] = pow(constants[0]/constants[1], geq(constants[2], constants[3])); - computedConstants[106] = pow(leq(constants[0], constants[1]), constants[2]+constants[3]); - computedConstants[107] = pow(leq(constants[0], constants[1]), constants[2]); - computedConstants[108] = pow(leq(constants[0], constants[1]), constants[2]-constants[3]); - computedConstants[109] = pow(leq(constants[0], constants[1]), -constants[2]); - computedConstants[110] = pow(leq(constants[0], constants[1]), constants[2]*constants[3]); - computedConstants[111] = pow(leq(constants[0], constants[1]), constants[2]/constants[3]); - computedConstants[112] = pow(leq(constants[0], constants[1]), pow(constants[2], constants[3])); - computedConstants[113] = pow(leq(constants[0], constants[1]), pow(constants[2], 1.0/constants[3])); - computedConstants[114] = sqrt(constants[0]); - computedConstants[115] = sqrt(constants[0]); - computedConstants[116] = pow(constants[0], 1.0/3.0); - computedConstants[117] = pow(constants[0], 1.0/constants[1]); - computedConstants[118] = pow(lt(constants[0], constants[1]), 1.0/gt(constants[3], constants[2])); - computedConstants[119] = pow(constants[0]+constants[1], 1.0/gt(constants[3], constants[2])); - computedConstants[120] = pow(constants[0], 1.0/gt(constants[2], constants[1])); - computedConstants[121] = pow(constants[0]-constants[1], 1.0/gt(constants[3], constants[2])); - computedConstants[122] = pow(-constants[0], 1.0/gt(constants[2], constants[1])); - computedConstants[123] = pow(constants[0]*constants[1], 1.0/gt(constants[3], constants[2])); - computedConstants[124] = pow(constants[0]/constants[1], 1.0/gt(constants[3], constants[2])); - computedConstants[125] = pow(lt(constants[0], constants[1]), 1.0/(constants[2]+constants[3])); - computedConstants[126] = pow(lt(constants[0], constants[1]), 1.0/constants[2]); - computedConstants[127] = pow(lt(constants[0], constants[1]), 1.0/(constants[2]-constants[3])); - computedConstants[128] = pow(lt(constants[0], constants[1]), 1.0/-constants[2]); - computedConstants[129] = pow(lt(constants[0], constants[1]), 1.0/(constants[2]*constants[3])); - computedConstants[130] = pow(lt(constants[0], constants[1]), 1.0/(constants[2]/constants[3])); - computedConstants[131] = pow(lt(constants[0], constants[1]), 1.0/pow(constants[2], constants[3])); - computedConstants[132] = pow(lt(constants[0], constants[1]), 1.0/pow(constants[2], 1.0/constants[3])); - computedConstants[133] = fabs(constants[0]); - computedConstants[134] = exp(constants[0]); - computedConstants[135] = log(constants[0]); + computedConstants[28] = or(lt(constants[0], constants[1]), gt(constants[2], constants[3])); + computedConstants[29] = or(constants[0]+constants[1], gt(constants[2], constants[3])); + computedConstants[30] = or(constants[0], gt(constants[1], constants[2])); + computedConstants[31] = or(constants[0]-constants[1], gt(constants[2], constants[3])); + computedConstants[32] = or(-constants[0], gt(constants[1], constants[2])); + computedConstants[33] = or(pow(constants[0], constants[1]), gt(constants[2], constants[3])); + computedConstants[34] = or(pow(constants[0], 1.0/constants[1]), gt(constants[2], constants[3])); + computedConstants[35] = or(lt(constants[0], constants[1]), constants[2]+constants[3]); + computedConstants[36] = or(lt(constants[0], constants[1]), constants[2]); + computedConstants[37] = or(lt(constants[0], constants[1]), constants[2]-constants[3]); + computedConstants[38] = or(lt(constants[0], constants[1]), -constants[2]); + computedConstants[39] = or(lt(constants[0], constants[1]), pow(constants[2], constants[3])); + computedConstants[40] = or(lt(constants[0], constants[1]), pow(constants[2], 1.0/constants[3])); + computedConstants[41] = constants[0]/or(constants[1], constants[2]); + computedConstants[42] = xor(constants[0], constants[1]); + computedConstants[43] = xor(constants[0], xor(constants[1], constants[2])); + computedConstants[44] = xor(lt(constants[0], constants[1]), gt(constants[2], constants[3])); + computedConstants[45] = xor(constants[0]+constants[1], gt(constants[2], constants[3])); + computedConstants[46] = xor(constants[0], gt(constants[1], constants[2])); + computedConstants[47] = xor(constants[0]-constants[1], gt(constants[2], constants[3])); + computedConstants[48] = xor(-constants[0], gt(constants[1], constants[2])); + computedConstants[49] = xor(pow(constants[0], constants[1]), gt(constants[2], constants[3])); + computedConstants[50] = xor(pow(constants[0], 1.0/constants[1]), gt(constants[2], constants[3])); + computedConstants[51] = xor(lt(constants[0], constants[1]), constants[2]+constants[3]); + computedConstants[52] = xor(lt(constants[0], constants[1]), constants[2]); + computedConstants[53] = xor(lt(constants[0], constants[1]), constants[2]-constants[3]); + computedConstants[54] = xor(lt(constants[0], constants[1]), -constants[2]); + computedConstants[55] = xor(lt(constants[0], constants[1]), pow(constants[2], constants[3])); + computedConstants[56] = xor(lt(constants[0], constants[1]), pow(constants[2], 1.0/constants[3])); + computedConstants[57] = not(constants[0]); + computedConstants[58] = constants[0]+constants[1]+constants[2]; + computedConstants[59] = lt(constants[0], constants[1])+gt(constants[2], constants[3]); + computedConstants[60] = constants[0]; + computedConstants[61] = constants[0]-constants[1]; + computedConstants[62] = lt(constants[0], constants[1])-gt(constants[2], constants[3]); + computedConstants[63] = lt(constants[0], constants[1])-(constants[2]+constants[3]); + computedConstants[64] = lt(constants[0], constants[1])-constants[2]; + computedConstants[65] = constants[0]-(-constants[1]); + computedConstants[66] = constants[0]-(-constants[1]*constants[2]); + computedConstants[67] = -constants[0]; + computedConstants[68] = -lt(constants[0], constants[1]); + computedConstants[69] = constants[0]*constants[1]; + computedConstants[70] = constants[0]*constants[1]*constants[2]; + computedConstants[71] = lt(constants[0], constants[1])*gt(constants[2], constants[3]); + computedConstants[72] = (constants[0]+constants[1])*gt(constants[2], constants[3]); + computedConstants[73] = constants[0]*gt(constants[1], constants[2]); + computedConstants[74] = (constants[0]-constants[1])*gt(constants[2], constants[3]); + computedConstants[75] = -constants[0]*gt(constants[1], constants[2]); + computedConstants[76] = lt(constants[0], constants[1])*(constants[2]+constants[3]); + computedConstants[77] = lt(constants[0], constants[1])*constants[2]; + computedConstants[78] = lt(constants[0], constants[1])*(constants[2]-constants[3]); + computedConstants[79] = lt(constants[0], constants[1])*-constants[2]; + computedConstants[80] = constants[0]/constants[1]; + computedConstants[81] = lt(constants[0], constants[1])/gt(constants[3], constants[2]); + computedConstants[82] = (constants[0]+constants[1])/gt(constants[3], constants[2]); + computedConstants[83] = constants[0]/gt(constants[2], constants[1]); + computedConstants[84] = (constants[0]-constants[1])/gt(constants[3], constants[2]); + computedConstants[85] = -constants[0]/gt(constants[2], constants[1]); + computedConstants[86] = lt(constants[0], constants[1])/(constants[2]+constants[3]); + computedConstants[87] = lt(constants[0], constants[1])/constants[2]; + computedConstants[88] = lt(constants[0], constants[1])/(constants[2]-constants[3]); + computedConstants[89] = lt(constants[0], constants[1])/-constants[2]; + computedConstants[90] = lt(constants[0], constants[1])/(constants[2]*constants[3]); + computedConstants[91] = lt(constants[0], constants[1])/(constants[2]/constants[3]); + computedConstants[92] = sqrt(constants[0]); + computedConstants[93] = pow(constants[0], 2.0); + computedConstants[94] = pow(constants[0], 3.0); + computedConstants[95] = pow(constants[0], constants[1]); + computedConstants[96] = pow(leq(constants[0], constants[1]), geq(constants[2], constants[3])); + computedConstants[97] = pow(constants[0]+constants[1], geq(constants[2], constants[3])); + computedConstants[98] = pow(constants[0], geq(constants[1], constants[2])); + computedConstants[99] = pow(constants[0]-constants[1], geq(constants[2], constants[3])); + computedConstants[100] = pow(-constants[0], geq(constants[1], constants[2])); + computedConstants[101] = pow(constants[0]*constants[1], geq(constants[2], constants[3])); + computedConstants[102] = pow(constants[0]/constants[1], geq(constants[2], constants[3])); + computedConstants[103] = pow(leq(constants[0], constants[1]), constants[2]+constants[3]); + computedConstants[104] = pow(leq(constants[0], constants[1]), constants[2]); + computedConstants[105] = pow(leq(constants[0], constants[1]), constants[2]-constants[3]); + computedConstants[106] = pow(leq(constants[0], constants[1]), -constants[2]); + computedConstants[107] = pow(leq(constants[0], constants[1]), constants[2]*constants[3]); + computedConstants[108] = pow(leq(constants[0], constants[1]), constants[2]/constants[3]); + computedConstants[109] = pow(leq(constants[0], constants[1]), pow(constants[2], constants[3])); + computedConstants[110] = pow(leq(constants[0], constants[1]), pow(constants[2], 1.0/constants[3])); + computedConstants[111] = sqrt(constants[0]); + computedConstants[112] = sqrt(constants[0]); + computedConstants[113] = pow(constants[0], 1.0/0.5); + computedConstants[114] = pow(constants[0], 1.0/3.0); + computedConstants[115] = pow(constants[0], 1.0/constants[1]); + computedConstants[116] = pow(lt(constants[0], constants[1]), 1.0/gt(constants[3], constants[2])); + computedConstants[117] = pow(constants[0]+constants[1], 1.0/gt(constants[3], constants[2])); + computedConstants[118] = pow(constants[0], 1.0/gt(constants[2], constants[1])); + computedConstants[119] = pow(constants[0]-constants[1], 1.0/gt(constants[3], constants[2])); + computedConstants[120] = pow(-constants[0], 1.0/gt(constants[2], constants[1])); + computedConstants[121] = pow(constants[0]*constants[1], 1.0/gt(constants[3], constants[2])); + computedConstants[122] = pow(constants[0]/constants[1], 1.0/gt(constants[3], constants[2])); + computedConstants[123] = pow(lt(constants[0], constants[1]), 1.0/(constants[2]+constants[3])); + computedConstants[124] = pow(lt(constants[0], constants[1]), 1.0/constants[2]); + computedConstants[125] = pow(lt(constants[0], constants[1]), 1.0/(constants[2]-constants[3])); + computedConstants[126] = pow(lt(constants[0], constants[1]), 1.0/-constants[2]); + computedConstants[127] = pow(lt(constants[0], constants[1]), 1.0/(constants[2]*constants[3])); + computedConstants[128] = pow(lt(constants[0], constants[1]), 1.0/(constants[2]/constants[3])); + computedConstants[129] = pow(lt(constants[0], constants[1]), 1.0/pow(constants[2], constants[3])); + computedConstants[130] = pow(lt(constants[0], constants[1]), 1.0/pow(constants[2], 1.0/constants[3])); + computedConstants[131] = fabs(constants[0]); + computedConstants[132] = exp(constants[0]); + computedConstants[133] = log(constants[0]); + computedConstants[134] = log10(constants[0]); + computedConstants[135] = log(constants[0])/log(2.0); computedConstants[136] = log10(constants[0]); - computedConstants[137] = log(constants[0])/log(2.0); - computedConstants[138] = log10(constants[0]); - computedConstants[139] = log(constants[0])/log(constants[1]); - computedConstants[140] = ceil(constants[0]); - computedConstants[141] = floor(constants[0]); - computedConstants[142] = min(constants[0], constants[1]); - computedConstants[143] = min(constants[0], min(constants[1], constants[2])); - computedConstants[144] = max(constants[0], constants[1]); - computedConstants[145] = max(constants[0], max(constants[1], constants[2])); - computedConstants[146] = fmod(constants[0], constants[1]); - computedConstants[147] = sin(constants[0]); - computedConstants[148] = cos(constants[0]); - computedConstants[149] = tan(constants[0]); - computedConstants[150] = sec(constants[0]); - computedConstants[151] = csc(constants[0]); - computedConstants[152] = cot(constants[0]); - computedConstants[153] = sinh(constants[0]); - computedConstants[154] = cosh(constants[0]); - computedConstants[155] = tanh(constants[0]); - computedConstants[156] = sech(constants[0]); - computedConstants[157] = csch(constants[0]); - computedConstants[158] = coth(constants[0]); - computedConstants[159] = asin(constants[0]); - computedConstants[160] = acos(constants[0]); - computedConstants[161] = atan(constants[0]); - computedConstants[162] = asec(constants[0]); - computedConstants[163] = acsc(constants[0]); - computedConstants[164] = acot(constants[0]); - computedConstants[165] = asinh(constants[0]); - computedConstants[166] = acosh(constants[0]); - computedConstants[167] = atanh(constants[0]/2.0); - computedConstants[168] = asech(constants[0]); - computedConstants[169] = acsch(constants[0]); - computedConstants[170] = acoth(2.0*constants[0]); - computedConstants[171] = (gt(constants[0], constants[1]))?constants[0]:NAN; - computedConstants[172] = (gt(constants[0], constants[1]))?constants[0]:constants[2]; - computedConstants[173] = (gt(constants[0], constants[1]))?constants[0]:(gt(constants[2], constants[3]))?constants[2]:(gt(constants[4], constants[5]))?constants[4]:NAN; - computedConstants[174] = (gt(constants[0], constants[1]))?constants[0]:(gt(constants[2], constants[3]))?constants[2]:(gt(constants[4], constants[5]))?constants[4]:constants[6]; - computedConstants[175] = 123.0+((gt(constants[0], constants[1]))?constants[0]:NAN); - computedConstants[180] = constants[0]; - computedConstants[187] = and(constants[0], constants[1])+((gt(constants[2], constants[3]))?constants[1]:NAN)+constants[4]+and(constants[5], constants[6]); - computedConstants[188] = and(constants[0], constants[1])-(((gt(constants[2], constants[3]))?constants[1]:NAN)-(constants[4]-((gt(constants[2], constants[3]))?constants[1]:NAN)))-and(constants[5], constants[6]); - computedConstants[189] = and(constants[0], constants[1])*((gt(constants[2], constants[3]))?constants[1]:NAN)*constants[4]*((gt(constants[2], constants[3]))?constants[1]:NAN)*and(constants[5], constants[6]); - computedConstants[190] = and(constants[0], constants[1])/(((gt(constants[2], constants[3]))?constants[1]:NAN)/(constants[4]/((gt(constants[2], constants[3]))?constants[1]:NAN))); - computedConstants[191] = and(or(constants[0], constants[1]), and(xor(constants[0], constants[1]), and((gt(constants[2], constants[3]))?constants[1]:NAN, and(and(and(constants[4], (gt(constants[2], constants[3]))?constants[1]:NAN), xor(constants[0], constants[1])), or(constants[0], constants[1]))))); - computedConstants[192] = or(and(constants[0], constants[1]), or(xor(constants[0], constants[1]), or((gt(constants[2], constants[3]))?constants[1]:NAN, or(or(or(constants[4], (gt(constants[2], constants[3]))?constants[1]:NAN), xor(constants[0], constants[1])), and(constants[0], constants[1]))))); - computedConstants[193] = xor(and(constants[0], constants[1]), xor(or(constants[0], constants[1]), xor((gt(constants[2], constants[3]))?constants[1]:NAN, xor(xor(xor(constants[4], (gt(constants[2], constants[3]))?constants[1]:NAN), or(constants[0], constants[1])), and(constants[0], constants[1]))))); - computedConstants[194] = pow(and(constants[0], constants[1]), pow((gt(constants[2], constants[3]))?constants[1]:NAN, pow(pow(constants[4], (gt(constants[2], constants[3]))?constants[1]:NAN), and(constants[0], constants[1])))); - computedConstants[195] = pow(pow(pow(and(constants[0], constants[1]), 1.0/pow((gt(constants[2], constants[3]))?constants[1]:NAN, 1.0/constants[4])), 1.0/((gt(constants[2], constants[3]))?constants[1]:NAN)), 1.0/and(constants[0], constants[1])); - computedConstants[196] = -and(constants[0], constants[1])+-((gt(constants[2], constants[3]))?constants[1]:NAN); + computedConstants[137] = log(constants[0])/log(constants[1]); + computedConstants[138] = ceil(constants[0]); + computedConstants[139] = floor(constants[0]); + computedConstants[140] = fmin(constants[0], constants[1]); + computedConstants[141] = fmin(constants[0], fmin(constants[1], constants[2])); + computedConstants[142] = fmax(constants[0], constants[1]); + computedConstants[143] = fmax(constants[0], fmax(constants[1], constants[2])); + computedConstants[144] = fmod(constants[0], constants[1]); + computedConstants[145] = sin(constants[0]); + computedConstants[146] = cos(constants[0]); + computedConstants[147] = tan(constants[0]); + computedConstants[148] = sec(constants[0]); + computedConstants[149] = csc(constants[0]); + computedConstants[150] = cot(constants[0]); + computedConstants[151] = sinh(constants[0]); + computedConstants[152] = cosh(constants[0]); + computedConstants[153] = tanh(constants[0]); + computedConstants[154] = sech(constants[0]); + computedConstants[155] = csch(constants[0]); + computedConstants[156] = coth(constants[0]); + computedConstants[157] = asin(constants[0]); + computedConstants[158] = acos(constants[0]); + computedConstants[159] = atan(constants[0]); + computedConstants[160] = asec(constants[0]); + computedConstants[161] = acsc(constants[0]); + computedConstants[162] = acot(constants[0]); + computedConstants[163] = asinh(constants[0]); + computedConstants[164] = acosh(constants[0]); + computedConstants[165] = atanh(constants[0]/2.0); + computedConstants[166] = asech(constants[0]); + computedConstants[167] = acsch(constants[0]); + computedConstants[168] = acoth(2.0*constants[0]); + computedConstants[170] = (gt(constants[0], constants[1]))?constants[0]:NAN; + computedConstants[171] = (lt(constants[0], constants[1]))?constants[0]:NAN; + computedConstants[172] = constants[0]; + computedConstants[173] = (gt(constants[0], constants[1]))?constants[0]:constants[2]; + computedConstants[174] = (gt(constants[0], constants[1]))?constants[0]:(gt(constants[2], constants[3]))?constants[2]:(gt(constants[4], constants[5]))?constants[4]:NAN; + computedConstants[175] = (lt(constants[0], constants[1]))?constants[0]:(gt(constants[2], constants[3]))?constants[2]:(gt(constants[4], constants[5]))?constants[4]:NAN; + computedConstants[176] = (gt(constants[0], constants[1]))?constants[0]:(gt(constants[2], constants[3]))?constants[2]:(gt(constants[4], constants[5]))?constants[4]:constants[6]; + computedConstants[177] = 123.0+((gt(constants[0], constants[1]))?constants[0]:NAN); + computedConstants[178] = 123.0+((lt(constants[0], constants[1]))?constants[0]:NAN); + computedConstants[183] = constants[0]; + computedConstants[190] = and(constants[0], constants[1])+((gt(constants[2], constants[3]))?constants[1]:NAN)+constants[4]+and(constants[5], constants[6]); + computedConstants[191] = and(constants[0], constants[1])+((lt(constants[2], constants[3]))?constants[1]:NAN)+constants[4]+and(constants[5], constants[6]); + computedConstants[192] = and(constants[0], constants[1])-(((gt(constants[2], constants[3]))?constants[1]:NAN)-(constants[4]-((gt(constants[2], constants[3]))?constants[1]:NAN)))-and(constants[5], constants[6]); + computedConstants[193] = and(constants[0], constants[1])-(((lt(constants[2], constants[3]))?constants[1]:NAN)-(constants[4]-((lt(constants[2], constants[3]))?constants[1]:NAN)))-and(constants[5], constants[6]); + computedConstants[194] = and(constants[0], constants[1])*((gt(constants[2], constants[3]))?constants[1]:NAN)*constants[4]*((gt(constants[2], constants[3]))?constants[1]:NAN)*and(constants[5], constants[6]); + computedConstants[195] = and(constants[0], constants[1])*((lt(constants[2], constants[3]))?constants[1]:NAN)*constants[4]*((lt(constants[2], constants[3]))?constants[1]:NAN)*and(constants[5], constants[6]); + computedConstants[196] = and(constants[0], constants[1])/(((gt(constants[2], constants[3]))?constants[1]:NAN)/(constants[4]/((gt(constants[2], constants[3]))?constants[1]:NAN))); + computedConstants[197] = and(constants[0], constants[1])/(((lt(constants[2], constants[3]))?constants[1]:NAN)/(constants[4]/((lt(constants[2], constants[3]))?constants[1]:NAN))); + computedConstants[198] = and(or(constants[0], constants[1]), and(xor(constants[0], constants[1]), and((gt(constants[2], constants[3]))?constants[1]:NAN, and(and(and(constants[4], (gt(constants[2], constants[3]))?constants[1]:NAN), xor(constants[0], constants[1])), or(constants[0], constants[1]))))); + computedConstants[199] = or(and(constants[0], constants[1]), or(xor(constants[0], constants[1]), or((gt(constants[2], constants[3]))?constants[1]:NAN, or(or(or(constants[4], (gt(constants[2], constants[3]))?constants[1]:NAN), xor(constants[0], constants[1])), and(constants[0], constants[1]))))); + computedConstants[200] = xor(and(constants[0], constants[1]), xor(or(constants[0], constants[1]), xor((gt(constants[2], constants[3]))?constants[1]:NAN, xor(xor(xor(constants[4], (gt(constants[2], constants[3]))?constants[1]:NAN), or(constants[0], constants[1])), and(constants[0], constants[1]))))); + computedConstants[201] = pow(and(constants[0], constants[1]), pow((gt(constants[2], constants[3]))?constants[1]:NAN, pow(pow(constants[4], (gt(constants[2], constants[3]))?constants[1]:NAN), and(constants[0], constants[1])))); + computedConstants[202] = pow(pow(pow(and(constants[0], constants[1]), 1.0/pow((gt(constants[2], constants[3]))?constants[1]:NAN, 1.0/constants[4])), 1.0/((gt(constants[2], constants[3]))?constants[1]:NAN)), 1.0/and(constants[0], constants[1])); + computedConstants[203] = -and(constants[0], constants[1])+-((gt(constants[2], constants[3]))?constants[1]:NAN); + computedConstants[204] = -and(constants[0], constants[1])+-((lt(constants[2], constants[3]))?constants[1]:NAN); } void computeRates(double voi, double *states, double *rates, double *constants, double *computedConstants, double *algebraic, double *externals, ExternalVariable externalVariable) @@ -409,6 +401,9 @@ void computeRates(double voi, double *states, double *rates, double *constants, void computeVariables(double voi, double *states, double *rates, double *constants, double *computedConstants, double *algebraic, double *externals, ExternalVariable externalVariable) { + algebraic[0] = or(states[0], states[0]); + algebraic[1] = or(states[0], or(states[0], constants[0])); + algebraic[2] = constants[0]/xor(constants[1], states[0]); externals[0] = externalVariable(voi, states, rates, constants, computedConstants, algebraic, externals, 0); findRoot0(voi, states, rates, constants, computedConstants, algebraic, externals); } diff --git a/tests/resources/coverage/generator/model.out b/tests/resources/coverage/generator/model.out index 84c6417ef6..326fdee8d4 100644 --- a/tests/resources/coverage/generator/model.out +++ b/tests/resources/coverage/generator/model.out @@ -2,16 +2,6 @@ #include "customheaderfile.h" -double min(double x, double y) -{ - return (x < y)?x:y; -} - -double max(double x, double y) -{ - return (x > y)?x:y; -} - double sec(double x) { return 1.0/cos(x); @@ -59,23 +49,17 @@ double acot(double x) double asech(double x) { - double oneOverX = 1.0/x; - - return log(oneOverX+sqrt(oneOverX*oneOverX-1.0)); + return acosh(1.0/x); } double acsch(double x) { - double oneOverX = 1.0/x; - - return log(oneOverX+sqrt(oneOverX*oneOverX+1.0)); + return asinh(1.0/x); } double acoth(double x) { - double oneOverX = 1.0/x; - - return 0.5*log((1.0+oneOverX)/(1.0-oneOverX)); + return atanh(1.0/x); } typedef struct { @@ -101,11 +85,11 @@ void objectiveFunction0(double *u, double *f, void *data) double *algebraic = ((RootFindingInfo *) data)->algebraic; double *externals = ((RootFindingInfo *) data)->externals; - algebraic[0] = u[0]; - algebraic[1] = u[1]; + algebraic[3] = u[0]; + algebraic[4] = u[1]; - f[0] = algebraic[0]+algebraic[1]+states[0]-0.0; - f[1] = algebraic[0]-algebraic[1]-(computedConstants[197]+computedConstants[198]); + f[0] = algebraic[3]+algebraic[4]+states[0]-0.0; + f[1] = algebraic[3]-algebraic[4]-(computedConstants[205]+computedConstants[206]); } void findRoot0(double voi, double *states, double *rates, double *constants, double *computedConstants, double *algebraic, double *externals) @@ -113,13 +97,13 @@ void findRoot0(double voi, double *states, double *rates, double *constants, dou RootFindingInfo rfi = { voi, states, rates, constants, computedConstants, algebraic, externals }; double u[2]; - u[0] = algebraic[0]; - u[1] = algebraic[1]; + u[0] = algebraic[3]; + u[1] = algebraic[4]; nlaSolve(objectiveFunction0, u, 2, &rfi); - algebraic[0] = u[0]; - algebraic[1] = u[1]; + algebraic[3] = u[0]; + algebraic[4] = u[1]; } void computeComputedConstants(double *constants, double *computedConstants) @@ -133,9 +117,9 @@ void computeComputedConstants(double *constants, double *computedConstants) computedConstants[6] = constants[0] <= constants[1]; computedConstants[7] = constants[0]/(constants[1] <= constants[2]); computedConstants[8] = constants[0] > constants[1]; - computedConstants[9] = constants[0]/(constants[1] > constants[2]); + computedConstants[9] = constants[0]/(constants[2] > constants[1]); computedConstants[10] = constants[0] >= constants[1]; - computedConstants[11] = constants[0]/(constants[1] >= constants[2]); + computedConstants[11] = constants[0]/(constants[2] >= constants[1]); computedConstants[12] = constants[0] && constants[1]; computedConstants[13] = constants[0] && constants[1] && constants[2]; computedConstants[14] = (constants[0] < constants[1]) && (constants[2] > constants[3]); @@ -152,165 +136,172 @@ void computeComputedConstants(double *constants, double *computedConstants) computedConstants[25] = (constants[0] < constants[1]) && (constants[2]^^constants[3]); computedConstants[26] = (constants[0] < constants[1]) && (constants[2]^^(1.0/constants[3])); computedConstants[27] = constants[0]/(constants[1] && constants[2]); - computedConstants[28] = constants[0] || constants[1]; - computedConstants[29] = constants[0] || constants[1] || constants[2]; - computedConstants[30] = (constants[0] < constants[1]) || (constants[2] > constants[3]); - computedConstants[31] = (constants[0]+constants[1]) || (constants[2] > constants[3]); - computedConstants[32] = constants[0] || (constants[1] > constants[2]); - computedConstants[33] = (constants[0]-constants[1]) || (constants[2] > constants[3]); - computedConstants[34] = -constants[0] || (constants[1] > constants[2]); - computedConstants[35] = (constants[0]^^constants[1]) || (constants[2] > constants[3]); - computedConstants[36] = (constants[0]^^(1.0/constants[1])) || (constants[2] > constants[3]); - computedConstants[37] = (constants[0] < constants[1]) || (constants[2]+constants[3]); - computedConstants[38] = (constants[0] < constants[1]) || constants[2]; - computedConstants[39] = (constants[0] < constants[1]) || (constants[2]-constants[3]); - computedConstants[40] = (constants[0] < constants[1]) || -constants[2]; - computedConstants[41] = (constants[0] < constants[1]) || (constants[2]^^constants[3]); - computedConstants[42] = (constants[0] < constants[1]) || (constants[2]^^(1.0/constants[3])); - computedConstants[43] = constants[0]/(constants[1] || constants[2]); - computedConstants[44] = constants[0]^constants[1]; - computedConstants[45] = constants[0]^constants[1]^constants[2]; - computedConstants[46] = (constants[0] < constants[1])^(constants[2] > constants[3]); - computedConstants[47] = (constants[0]+constants[1])^(constants[2] > constants[3]); - computedConstants[48] = constants[0]^(constants[1] > constants[2]); - computedConstants[49] = (constants[0]-constants[1])^(constants[2] > constants[3]); - computedConstants[50] = -constants[0]^(constants[1] > constants[2]); - computedConstants[51] = (constants[0]^^constants[1])^(constants[2] > constants[3]); - computedConstants[52] = (constants[0]^^(1.0/constants[1]))^(constants[2] > constants[3]); - computedConstants[53] = (constants[0] < constants[1])^(constants[2]+constants[3]); - computedConstants[54] = (constants[0] < constants[1])^constants[2]; - computedConstants[55] = (constants[0] < constants[1])^(constants[2]-constants[3]); - computedConstants[56] = (constants[0] < constants[1])^-constants[2]; - computedConstants[57] = (constants[0] < constants[1])^(constants[2]^^constants[3]); - computedConstants[58] = (constants[0] < constants[1])^(constants[2]^^(1.0/constants[3])); - computedConstants[59] = constants[0]/(constants[1]^constants[2]); - computedConstants[60] = !constants[0]; - computedConstants[61] = constants[0]+constants[1]+constants[2]; - computedConstants[62] = (constants[0] < constants[1])+(constants[2] > constants[3]); - computedConstants[63] = constants[0]; - computedConstants[64] = constants[0]-constants[1]; - computedConstants[65] = (constants[0] < constants[1])-(constants[2] > constants[3]); - computedConstants[66] = (constants[0] < constants[1])-(constants[2]+constants[3]); - computedConstants[67] = (constants[0] < constants[1])-constants[2]; - computedConstants[68] = constants[0]-(-constants[1]); - computedConstants[69] = constants[0]-(-constants[1]*constants[2]); - computedConstants[70] = -constants[0]; - computedConstants[71] = -(constants[0] < constants[1]); - computedConstants[72] = constants[0]*constants[1]; - computedConstants[73] = constants[0]*constants[1]*constants[2]; - computedConstants[74] = (constants[0] < constants[1])*(constants[2] > constants[3]); - computedConstants[75] = (constants[0]+constants[1])*(constants[2] > constants[3]); - computedConstants[76] = constants[0]*(constants[1] > constants[2]); - computedConstants[77] = (constants[0]-constants[1])*(constants[2] > constants[3]); - computedConstants[78] = -constants[0]*(constants[1] > constants[2]); - computedConstants[79] = (constants[0] < constants[1])*(constants[2]+constants[3]); - computedConstants[80] = (constants[0] < constants[1])*constants[2]; - computedConstants[81] = (constants[0] < constants[1])*(constants[2]-constants[3]); - computedConstants[82] = (constants[0] < constants[1])*-constants[2]; - computedConstants[83] = constants[0]/constants[1]; - computedConstants[84] = (constants[0] < constants[1])/(constants[3] > constants[2]); - computedConstants[85] = (constants[0]+constants[1])/(constants[3] > constants[2]); - computedConstants[86] = constants[0]/(constants[2] > constants[1]); - computedConstants[87] = (constants[0]-constants[1])/(constants[3] > constants[2]); - computedConstants[88] = -constants[0]/(constants[2] > constants[1]); - computedConstants[89] = (constants[0] < constants[1])/(constants[2]+constants[3]); - computedConstants[90] = (constants[0] < constants[1])/constants[2]; - computedConstants[91] = (constants[0] < constants[1])/(constants[2]-constants[3]); - computedConstants[92] = (constants[0] < constants[1])/-constants[2]; - computedConstants[93] = (constants[0] < constants[1])/(constants[2]*constants[3]); - computedConstants[94] = (constants[0] < constants[1])/(constants[2]/constants[3]); - computedConstants[95] = sqrt(constants[0]); - computedConstants[96] = sqr(constants[0]); - computedConstants[97] = constants[0]^^3.0; - computedConstants[98] = constants[0]^^constants[1]; - computedConstants[99] = (constants[0] <= constants[1])^^(constants[2] >= constants[3]); - computedConstants[100] = (constants[0]+constants[1])^^(constants[2] >= constants[3]); - computedConstants[101] = constants[0]^^(constants[1] >= constants[2]); - computedConstants[102] = (constants[0]-constants[1])^^(constants[2] >= constants[3]); - computedConstants[103] = (-constants[0])^^(constants[1] >= constants[2]); - computedConstants[104] = (constants[0]*constants[1])^^(constants[2] >= constants[3]); - computedConstants[105] = (constants[0]/constants[1])^^(constants[2] >= constants[3]); - computedConstants[106] = (constants[0] <= constants[1])^^(constants[2]+constants[3]); - computedConstants[107] = (constants[0] <= constants[1])^^constants[2]; - computedConstants[108] = (constants[0] <= constants[1])^^constants[2]-constants[3]; - computedConstants[109] = (constants[0] <= constants[1])^^-constants[2]; - computedConstants[110] = (constants[0] <= constants[1])^^(constants[2]*constants[3]); - computedConstants[111] = (constants[0] <= constants[1])^^(constants[2]/constants[3]); - computedConstants[112] = (constants[0] <= constants[1])^^(constants[2]^^constants[3]); - computedConstants[113] = (constants[0] <= constants[1])^^(constants[2]^^(1.0/constants[3])); - computedConstants[114] = sqrt(constants[0]); - computedConstants[115] = sqrt(constants[0]); - computedConstants[116] = constants[0]^^(1.0/3.0); - computedConstants[117] = constants[0]^^(1.0/constants[1]); - computedConstants[118] = (constants[0] < constants[1])^^(1.0/(constants[3] > constants[2])); - computedConstants[119] = (constants[0]+constants[1])^^(1.0/(constants[3] > constants[2])); - computedConstants[120] = constants[0]^^(1.0/(constants[2] > constants[1])); - computedConstants[121] = (constants[0]-constants[1])^^(1.0/(constants[3] > constants[2])); - computedConstants[122] = (-constants[0])^^(1.0/(constants[2] > constants[1])); - computedConstants[123] = (constants[0]*constants[1])^^(1.0/(constants[3] > constants[2])); - computedConstants[124] = (constants[0]/constants[1])^^(1.0/(constants[3] > constants[2])); - computedConstants[125] = (constants[0] < constants[1])^^(1.0/(constants[2]+constants[3])); - computedConstants[126] = (constants[0] < constants[1])^^(1.0/constants[2]); - computedConstants[127] = (constants[0] < constants[1])^^(1.0/(constants[2]-constants[3])); - computedConstants[128] = (constants[0] < constants[1])^^(1.0/(-constants[2])); - computedConstants[129] = (constants[0] < constants[1])^^(1.0/(constants[2]*constants[3])); - computedConstants[130] = (constants[0] < constants[1])^^(1.0/(constants[2]/constants[3])); - computedConstants[131] = (constants[0] < constants[1])^^(1.0/(constants[2]^^constants[3])); - computedConstants[132] = (constants[0] < constants[1])^^(1.0/(constants[2]^^(1.0/constants[3]))); - computedConstants[133] = fabs(constants[0]); - computedConstants[134] = exp(constants[0]); - computedConstants[135] = log(constants[0]); + computedConstants[28] = (constants[0] < constants[1]) || (constants[2] > constants[3]); + computedConstants[29] = (constants[0]+constants[1]) || (constants[2] > constants[3]); + computedConstants[30] = constants[0] || (constants[1] > constants[2]); + computedConstants[31] = (constants[0]-constants[1]) || (constants[2] > constants[3]); + computedConstants[32] = -constants[0] || (constants[1] > constants[2]); + computedConstants[33] = (constants[0]^^constants[1]) || (constants[2] > constants[3]); + computedConstants[34] = (constants[0]^^(1.0/constants[1])) || (constants[2] > constants[3]); + computedConstants[35] = (constants[0] < constants[1]) || (constants[2]+constants[3]); + computedConstants[36] = (constants[0] < constants[1]) || constants[2]; + computedConstants[37] = (constants[0] < constants[1]) || (constants[2]-constants[3]); + computedConstants[38] = (constants[0] < constants[1]) || -constants[2]; + computedConstants[39] = (constants[0] < constants[1]) || (constants[2]^^constants[3]); + computedConstants[40] = (constants[0] < constants[1]) || (constants[2]^^(1.0/constants[3])); + computedConstants[41] = constants[0]/(constants[1] || constants[2]); + computedConstants[42] = constants[0]^constants[1]; + computedConstants[43] = constants[0]^constants[1]^constants[2]; + computedConstants[44] = (constants[0] < constants[1])^(constants[2] > constants[3]); + computedConstants[45] = (constants[0]+constants[1])^(constants[2] > constants[3]); + computedConstants[46] = constants[0]^(constants[1] > constants[2]); + computedConstants[47] = (constants[0]-constants[1])^(constants[2] > constants[3]); + computedConstants[48] = -constants[0]^(constants[1] > constants[2]); + computedConstants[49] = (constants[0]^^constants[1])^(constants[2] > constants[3]); + computedConstants[50] = (constants[0]^^(1.0/constants[1]))^(constants[2] > constants[3]); + computedConstants[51] = (constants[0] < constants[1])^(constants[2]+constants[3]); + computedConstants[52] = (constants[0] < constants[1])^constants[2]; + computedConstants[53] = (constants[0] < constants[1])^(constants[2]-constants[3]); + computedConstants[54] = (constants[0] < constants[1])^-constants[2]; + computedConstants[55] = (constants[0] < constants[1])^(constants[2]^^constants[3]); + computedConstants[56] = (constants[0] < constants[1])^(constants[2]^^(1.0/constants[3])); + computedConstants[57] = !constants[0]; + computedConstants[58] = constants[0]+constants[1]+constants[2]; + computedConstants[59] = (constants[0] < constants[1])+(constants[2] > constants[3]); + computedConstants[60] = constants[0]; + computedConstants[61] = constants[0]-constants[1]; + computedConstants[62] = (constants[0] < constants[1])-(constants[2] > constants[3]); + computedConstants[63] = (constants[0] < constants[1])-(constants[2]+constants[3]); + computedConstants[64] = (constants[0] < constants[1])-constants[2]; + computedConstants[65] = constants[0]-(-constants[1]); + computedConstants[66] = constants[0]-(-constants[1]*constants[2]); + computedConstants[67] = -constants[0]; + computedConstants[68] = -(constants[0] < constants[1]); + computedConstants[69] = constants[0]*constants[1]; + computedConstants[70] = constants[0]*constants[1]*constants[2]; + computedConstants[71] = (constants[0] < constants[1])*(constants[2] > constants[3]); + computedConstants[72] = (constants[0]+constants[1])*(constants[2] > constants[3]); + computedConstants[73] = constants[0]*(constants[1] > constants[2]); + computedConstants[74] = (constants[0]-constants[1])*(constants[2] > constants[3]); + computedConstants[75] = -constants[0]*(constants[1] > constants[2]); + computedConstants[76] = (constants[0] < constants[1])*(constants[2]+constants[3]); + computedConstants[77] = (constants[0] < constants[1])*constants[2]; + computedConstants[78] = (constants[0] < constants[1])*(constants[2]-constants[3]); + computedConstants[79] = (constants[0] < constants[1])*-constants[2]; + computedConstants[80] = constants[0]/constants[1]; + computedConstants[81] = (constants[0] < constants[1])/(constants[3] > constants[2]); + computedConstants[82] = (constants[0]+constants[1])/(constants[3] > constants[2]); + computedConstants[83] = constants[0]/(constants[2] > constants[1]); + computedConstants[84] = (constants[0]-constants[1])/(constants[3] > constants[2]); + computedConstants[85] = -constants[0]/(constants[2] > constants[1]); + computedConstants[86] = (constants[0] < constants[1])/(constants[2]+constants[3]); + computedConstants[87] = (constants[0] < constants[1])/constants[2]; + computedConstants[88] = (constants[0] < constants[1])/(constants[2]-constants[3]); + computedConstants[89] = (constants[0] < constants[1])/-constants[2]; + computedConstants[90] = (constants[0] < constants[1])/(constants[2]*constants[3]); + computedConstants[91] = (constants[0] < constants[1])/(constants[2]/constants[3]); + computedConstants[92] = sqrt(constants[0]); + computedConstants[93] = sqr(constants[0]); + computedConstants[94] = constants[0]^^3.0; + computedConstants[95] = constants[0]^^constants[1]; + computedConstants[96] = (constants[0] <= constants[1])^^(constants[2] >= constants[3]); + computedConstants[97] = (constants[0]+constants[1])^^(constants[2] >= constants[3]); + computedConstants[98] = constants[0]^^(constants[1] >= constants[2]); + computedConstants[99] = (constants[0]-constants[1])^^(constants[2] >= constants[3]); + computedConstants[100] = (-constants[0])^^(constants[1] >= constants[2]); + computedConstants[101] = (constants[0]*constants[1])^^(constants[2] >= constants[3]); + computedConstants[102] = (constants[0]/constants[1])^^(constants[2] >= constants[3]); + computedConstants[103] = (constants[0] <= constants[1])^^(constants[2]+constants[3]); + computedConstants[104] = (constants[0] <= constants[1])^^constants[2]; + computedConstants[105] = (constants[0] <= constants[1])^^constants[2]-constants[3]; + computedConstants[106] = (constants[0] <= constants[1])^^-constants[2]; + computedConstants[107] = (constants[0] <= constants[1])^^(constants[2]*constants[3]); + computedConstants[108] = (constants[0] <= constants[1])^^(constants[2]/constants[3]); + computedConstants[109] = (constants[0] <= constants[1])^^(constants[2]^^constants[3]); + computedConstants[110] = (constants[0] <= constants[1])^^(constants[2]^^(1.0/constants[3])); + computedConstants[111] = sqrt(constants[0]); + computedConstants[112] = sqrt(constants[0]); + computedConstants[113] = sqr(constants[0]); + computedConstants[114] = constants[0]^^(1.0/3.0); + computedConstants[115] = constants[0]^^(1.0/constants[1]); + computedConstants[116] = (constants[0] < constants[1])^^(1.0/(constants[3] > constants[2])); + computedConstants[117] = (constants[0]+constants[1])^^(1.0/(constants[3] > constants[2])); + computedConstants[118] = constants[0]^^(1.0/(constants[2] > constants[1])); + computedConstants[119] = (constants[0]-constants[1])^^(1.0/(constants[3] > constants[2])); + computedConstants[120] = (-constants[0])^^(1.0/(constants[2] > constants[1])); + computedConstants[121] = (constants[0]*constants[1])^^(1.0/(constants[3] > constants[2])); + computedConstants[122] = (constants[0]/constants[1])^^(1.0/(constants[3] > constants[2])); + computedConstants[123] = (constants[0] < constants[1])^^(1.0/(constants[2]+constants[3])); + computedConstants[124] = (constants[0] < constants[1])^^(1.0/constants[2]); + computedConstants[125] = (constants[0] < constants[1])^^(1.0/(constants[2]-constants[3])); + computedConstants[126] = (constants[0] < constants[1])^^(1.0/(-constants[2])); + computedConstants[127] = (constants[0] < constants[1])^^(1.0/(constants[2]*constants[3])); + computedConstants[128] = (constants[0] < constants[1])^^(1.0/(constants[2]/constants[3])); + computedConstants[129] = (constants[0] < constants[1])^^(1.0/(constants[2]^^constants[3])); + computedConstants[130] = (constants[0] < constants[1])^^(1.0/(constants[2]^^(1.0/constants[3]))); + computedConstants[131] = fabs(constants[0]); + computedConstants[132] = exp(constants[0]); + computedConstants[133] = log(constants[0]); + computedConstants[134] = log10(constants[0]); + computedConstants[135] = log(constants[0])/log(2.0); computedConstants[136] = log10(constants[0]); - computedConstants[137] = log(constants[0])/log(2.0); - computedConstants[138] = log10(constants[0]); - computedConstants[139] = log(constants[0])/log(constants[1]); - computedConstants[140] = ceil(constants[0]); - computedConstants[141] = floor(constants[0]); - computedConstants[142] = min(constants[0], constants[1]); - computedConstants[143] = min(constants[0], min(constants[1], constants[2])); - computedConstants[144] = max(constants[0], constants[1]); - computedConstants[145] = max(constants[0], max(constants[1], constants[2])); - computedConstants[146] = fmod(constants[0], constants[1]); - computedConstants[147] = sin(constants[0]); - computedConstants[148] = cos(constants[0]); - computedConstants[149] = tan(constants[0]); - computedConstants[150] = sec(constants[0]); - computedConstants[151] = csc(constants[0]); - computedConstants[152] = cot(constants[0]); - computedConstants[153] = sinh(constants[0]); - computedConstants[154] = cosh(constants[0]); - computedConstants[155] = tanh(constants[0]); - computedConstants[156] = sech(constants[0]); - computedConstants[157] = csch(constants[0]); - computedConstants[158] = coth(constants[0]); - computedConstants[159] = asin(constants[0]); - computedConstants[160] = acos(constants[0]); - computedConstants[161] = atan(constants[0]); - computedConstants[162] = asec(constants[0]); - computedConstants[163] = acsc(constants[0]); - computedConstants[164] = acot(constants[0]); - computedConstants[165] = asinh(constants[0]); - computedConstants[166] = acosh(constants[0]); - computedConstants[167] = atanh(constants[0]/2.0); - computedConstants[168] = asech(constants[0]); - computedConstants[169] = acsch(constants[0]); - computedConstants[170] = acoth(2.0*constants[0]); - computedConstants[171] = piecewise(constants[0] > constants[1], constants[0], NAN); - computedConstants[172] = piecewise(constants[0] > constants[1], constants[0], constants[2]); - computedConstants[173] = piecewise(constants[0] > constants[1], constants[0], piecewise(constants[2] > constants[3], constants[2], piecewise(constants[4] > constants[5], constants[4], NAN))); - computedConstants[174] = piecewise(constants[0] > constants[1], constants[0], piecewise(constants[2] > constants[3], constants[2], piecewise(constants[4] > constants[5], constants[4], constants[6]))); - computedConstants[175] = 123.0+piecewise(constants[0] > constants[1], constants[0], NAN); - computedConstants[180] = constants[0]; - computedConstants[187] = (constants[0] && constants[1])+piecewise(constants[2] > constants[3], constants[1], NAN)+constants[4]+(constants[5] && constants[6]); - computedConstants[188] = (constants[0] && constants[1])-(piecewise(constants[2] > constants[3], constants[1], NAN)-(constants[4]-piecewise(constants[2] > constants[3], constants[1], NAN)))-(constants[5] && constants[6]); - computedConstants[189] = (constants[0] && constants[1])*piecewise(constants[2] > constants[3], constants[1], NAN)*constants[4]*piecewise(constants[2] > constants[3], constants[1], NAN)*(constants[5] && constants[6]); - computedConstants[190] = (constants[0] && constants[1])/(piecewise(constants[2] > constants[3], constants[1], NAN)/(constants[4]/piecewise(constants[2] > constants[3], constants[1], NAN))); - computedConstants[191] = (constants[0] || constants[1]) && (constants[0]^constants[1]) && piecewise(constants[2] > constants[3], constants[1], NAN) && constants[4] && piecewise(constants[2] > constants[3], constants[1], NAN) && (constants[0]^constants[1]) && (constants[0] || constants[1]); - computedConstants[192] = (constants[0] && constants[1]) || (constants[0]^constants[1]) || piecewise(constants[2] > constants[3], constants[1], NAN) || constants[4] || piecewise(constants[2] > constants[3], constants[1], NAN) || (constants[0]^constants[1]) || (constants[0] && constants[1]); - computedConstants[193] = (constants[0] && constants[1])^(constants[0] || constants[1])^piecewise(constants[2] > constants[3], constants[1], NAN)^constants[4]^piecewise(constants[2] > constants[3], constants[1], NAN)^(constants[0] || constants[1])^(constants[0] && constants[1]); - computedConstants[194] = (constants[0] && constants[1])^^(piecewise(constants[2] > constants[3], constants[1], NAN)^^(constants[4]^^piecewise(constants[2] > constants[3], constants[1], NAN)^^(constants[0] && constants[1]))); - computedConstants[195] = (constants[0] && constants[1])^^(1.0/(piecewise(constants[2] > constants[3], constants[1], NAN)^^(1.0/constants[4])))^^(1.0/piecewise(constants[2] > constants[3], constants[1], NAN))^^(1.0/(constants[0] && constants[1])); - computedConstants[196] = -(constants[0] && constants[1])+-piecewise(constants[2] > constants[3], constants[1], NAN); + computedConstants[137] = log(constants[0])/log(constants[1]); + computedConstants[138] = ceil(constants[0]); + computedConstants[139] = floor(constants[0]); + computedConstants[140] = fmin(constants[0], constants[1]); + computedConstants[141] = fmin(constants[0], fmin(constants[1], constants[2])); + computedConstants[142] = fmax(constants[0], constants[1]); + computedConstants[143] = fmax(constants[0], fmax(constants[1], constants[2])); + computedConstants[144] = fmod(constants[0], constants[1]); + computedConstants[145] = sin(constants[0]); + computedConstants[146] = cos(constants[0]); + computedConstants[147] = tan(constants[0]); + computedConstants[148] = sec(constants[0]); + computedConstants[149] = csc(constants[0]); + computedConstants[150] = cot(constants[0]); + computedConstants[151] = sinh(constants[0]); + computedConstants[152] = cosh(constants[0]); + computedConstants[153] = tanh(constants[0]); + computedConstants[154] = sech(constants[0]); + computedConstants[155] = csch(constants[0]); + computedConstants[156] = coth(constants[0]); + computedConstants[157] = asin(constants[0]); + computedConstants[158] = acos(constants[0]); + computedConstants[159] = atan(constants[0]); + computedConstants[160] = asec(constants[0]); + computedConstants[161] = acsc(constants[0]); + computedConstants[162] = acot(constants[0]); + computedConstants[163] = asinh(constants[0]); + computedConstants[164] = acosh(constants[0]); + computedConstants[165] = atanh(constants[0]/2.0); + computedConstants[166] = asech(constants[0]); + computedConstants[167] = acsch(constants[0]); + computedConstants[168] = acoth(2.0*constants[0]); + computedConstants[170] = piecewise(constants[0] > constants[1], constants[0], NAN); + computedConstants[171] = piecewise(constants[0] < constants[1], constants[0], NAN); + computedConstants[172] = constants[0]; + computedConstants[173] = piecewise(constants[0] > constants[1], constants[0], constants[2]); + computedConstants[174] = piecewise(constants[0] > constants[1], constants[0], piecewise(constants[2] > constants[3], constants[2], piecewise(constants[4] > constants[5], constants[4], NAN))); + computedConstants[175] = piecewise(constants[0] < constants[1], constants[0], piecewise(constants[2] > constants[3], constants[2], piecewise(constants[4] > constants[5], constants[4], NAN))); + computedConstants[176] = piecewise(constants[0] > constants[1], constants[0], piecewise(constants[2] > constants[3], constants[2], piecewise(constants[4] > constants[5], constants[4], constants[6]))); + computedConstants[177] = 123.0+piecewise(constants[0] > constants[1], constants[0], NAN); + computedConstants[178] = 123.0+piecewise(constants[0] < constants[1], constants[0], NAN); + computedConstants[183] = constants[0]; + computedConstants[190] = (constants[0] && constants[1])+piecewise(constants[2] > constants[3], constants[1], NAN)+constants[4]+(constants[5] && constants[6]); + computedConstants[191] = (constants[0] && constants[1])+piecewise(constants[2] < constants[3], constants[1], NAN)+constants[4]+(constants[5] && constants[6]); + computedConstants[192] = (constants[0] && constants[1])-(piecewise(constants[2] > constants[3], constants[1], NAN)-(constants[4]-piecewise(constants[2] > constants[3], constants[1], NAN)))-(constants[5] && constants[6]); + computedConstants[193] = (constants[0] && constants[1])-(piecewise(constants[2] < constants[3], constants[1], NAN)-(constants[4]-piecewise(constants[2] < constants[3], constants[1], NAN)))-(constants[5] && constants[6]); + computedConstants[194] = (constants[0] && constants[1])*piecewise(constants[2] > constants[3], constants[1], NAN)*constants[4]*piecewise(constants[2] > constants[3], constants[1], NAN)*(constants[5] && constants[6]); + computedConstants[195] = (constants[0] && constants[1])*piecewise(constants[2] < constants[3], constants[1], NAN)*constants[4]*piecewise(constants[2] < constants[3], constants[1], NAN)*(constants[5] && constants[6]); + computedConstants[196] = (constants[0] && constants[1])/(piecewise(constants[2] > constants[3], constants[1], NAN)/(constants[4]/piecewise(constants[2] > constants[3], constants[1], NAN))); + computedConstants[197] = (constants[0] && constants[1])/(piecewise(constants[2] < constants[3], constants[1], NAN)/(constants[4]/piecewise(constants[2] < constants[3], constants[1], NAN))); + computedConstants[198] = (constants[0] || constants[1]) && (constants[0]^constants[1]) && piecewise(constants[2] > constants[3], constants[1], NAN) && constants[4] && piecewise(constants[2] > constants[3], constants[1], NAN) && (constants[0]^constants[1]) && (constants[0] || constants[1]); + computedConstants[199] = (constants[0] && constants[1]) || (constants[0]^constants[1]) || piecewise(constants[2] > constants[3], constants[1], NAN) || constants[4] || piecewise(constants[2] > constants[3], constants[1], NAN) || (constants[0]^constants[1]) || (constants[0] && constants[1]); + computedConstants[200] = (constants[0] && constants[1])^(constants[0] || constants[1])^piecewise(constants[2] > constants[3], constants[1], NAN)^constants[4]^piecewise(constants[2] > constants[3], constants[1], NAN)^(constants[0] || constants[1])^(constants[0] && constants[1]); + computedConstants[201] = (constants[0] && constants[1])^^(piecewise(constants[2] > constants[3], constants[1], NAN)^^(constants[4]^^piecewise(constants[2] > constants[3], constants[1], NAN)^^(constants[0] && constants[1]))); + computedConstants[202] = (constants[0] && constants[1])^^(1.0/(piecewise(constants[2] > constants[3], constants[1], NAN)^^(1.0/constants[4])))^^(1.0/piecewise(constants[2] > constants[3], constants[1], NAN))^^(1.0/(constants[0] && constants[1])); + computedConstants[203] = -(constants[0] && constants[1])+-piecewise(constants[2] > constants[3], constants[1], NAN); + computedConstants[204] = -(constants[0] && constants[1])+-piecewise(constants[2] < constants[3], constants[1], NAN); } void computeRates(double voi, double *states, double *rates, double *constants, double *computedConstants, double *algebraic, double *externals, ExternalVariable externalVariable) diff --git a/tests/resources/coverage/generator/model.py b/tests/resources/coverage/generator/model.py index d8a33ebfb8..acff4123de 100644 --- a/tests/resources/coverage/generator/model.py +++ b/tests/resources/coverage/generator/model.py @@ -9,8 +9,8 @@ STATE_COUNT = 1 CONSTANT_COUNT = 7 -COMPUTED_CONSTANT_COUNT = 199 -ALGEBRAIC_COUNT = 2 +COMPUTED_CONSTANT_COUNT = 207 +ALGEBRAIC_COUNT = 5 EXTERNAL_COUNT = 1 VOI_INFO = {"name": "t", "units": "second", "component": "my_component"} @@ -58,8 +58,6 @@ {"name": "eqnAndParenthesesRightPower", "units": "dimensionless", "component": "my_component"}, {"name": "eqnAndParenthesesRightRoot", "units": "dimensionless", "component": "my_component"}, {"name": "eqnAndCoverageParentheses", "units": "dimensionless", "component": "my_component"}, - {"name": "eqnOr", "units": "dimensionless", "component": "my_component"}, - {"name": "eqnOrMultiple", "units": "dimensionless", "component": "my_component"}, {"name": "eqnOrParentheses", "units": "dimensionless", "component": "my_component"}, {"name": "eqnOrParenthesesLeftPlusWith", "units": "dimensionless", "component": "my_component"}, {"name": "eqnOrParenthesesLeftPlusWithout", "units": "dimensionless", "component": "my_component"}, @@ -89,7 +87,6 @@ {"name": "eqnXorParenthesesRightMinusWithout", "units": "dimensionless", "component": "my_component"}, {"name": "eqnXorParenthesesRightPower", "units": "dimensionless", "component": "my_component"}, {"name": "eqnXorParenthesesRightRoot", "units": "dimensionless", "component": "my_component"}, - {"name": "eqnXorCoverageParentheses", "units": "dimensionless", "component": "my_component"}, {"name": "eqnNot", "units": "dimensionless", "component": "my_component"}, {"name": "eqnPlusMultiple", "units": "dimensionless", "component": "my_component"}, {"name": "eqnPlusParentheses", "units": "dimensionless", "component": "my_component"}, @@ -146,6 +143,7 @@ {"name": "eqnPowerParenthesesRightRoot", "units": "dimensionless", "component": "my_component"}, {"name": "eqnRootSqrt", "units": "dimensionless", "component": "my_component"}, {"name": "eqnRootSqrtOther", "units": "dimensionless", "component": "my_component"}, + {"name": "eqnRootSqr", "units": "dimensionless", "component": "my_component"}, {"name": "eqnRootCube", "units": "dimensionless", "component": "my_component"}, {"name": "eqnRootCi", "units": "dimensionless", "component": "my_component"}, {"name": "eqnRootParentheses", "units": "dimensionless", "component": "my_component"}, @@ -201,11 +199,16 @@ {"name": "eqnArcsech", "units": "dimensionless", "component": "my_component"}, {"name": "eqnArccsch", "units": "dimensionless", "component": "my_component"}, {"name": "eqnArccoth", "units": "dimensionless", "component": "my_component"}, + {"name": "eqnPiecewise", "units": "dimensionless", "component": "my_component"}, {"name": "eqnPiecewisePiece", "units": "dimensionless", "component": "my_component"}, + {"name": "eqnPiecewisePiece2", "units": "dimensionless", "component": "my_component"}, + {"name": "eqnPiecewiseOtherwise", "units": "dimensionless", "component": "my_component"}, {"name": "eqnPiecewisePieceOtherwise", "units": "dimensionless", "component": "my_component"}, {"name": "eqnPiecewisePiecePiecePiece", "units": "dimensionless", "component": "my_component"}, + {"name": "eqnPiecewisePiecePiecePiece2", "units": "dimensionless", "component": "my_component"}, {"name": "eqnPiecewisePiecePiecePieceOtherwise", "units": "dimensionless", "component": "my_component"}, {"name": "eqnWithPiecewise", "units": "dimensionless", "component": "my_component"}, + {"name": "eqnWithPiecewise2", "units": "dimensionless", "component": "my_component"}, {"name": "eqnCnInteger", "units": "dimensionless", "component": "my_component"}, {"name": "eqnCnDouble", "units": "dimensionless", "component": "my_component"}, {"name": "eqnCnIntegerWithExponent", "units": "dimensionless", "component": "my_component"}, @@ -218,20 +221,28 @@ {"name": "eqnInfinity", "units": "dimensionless", "component": "my_component"}, {"name": "eqnNotanumber", "units": "dimensionless", "component": "my_component"}, {"name": "eqnCoverageForPlusOperator", "units": "dimensionless", "component": "my_component"}, + {"name": "eqnCoverageForPlusOperator2", "units": "dimensionless", "component": "my_component"}, {"name": "eqnCoverageForMinusOperator", "units": "dimensionless", "component": "my_component"}, + {"name": "eqnCoverageForMinusOperator2", "units": "dimensionless", "component": "my_component"}, {"name": "eqnCoverageForTimesOperator", "units": "dimensionless", "component": "my_component"}, + {"name": "eqnCoverageForTimesOperator2", "units": "dimensionless", "component": "my_component"}, {"name": "eqnCoverageForDivideOperator", "units": "dimensionless", "component": "my_component"}, + {"name": "eqnCoverageForDivideOperator2", "units": "dimensionless", "component": "my_component"}, {"name": "eqnCoverageForAndOperator", "units": "dimensionless", "component": "my_component"}, {"name": "eqnCoverageForOrOperator", "units": "dimensionless", "component": "my_component"}, {"name": "eqnCoverageForXorOperator", "units": "dimensionless", "component": "my_component"}, {"name": "eqnCoverageForPowerOperator", "units": "dimensionless", "component": "my_component"}, {"name": "eqnCoverageForRootOperator", "units": "dimensionless", "component": "my_component"}, {"name": "eqnCoverageForMinusUnary", "units": "dimensionless", "component": "my_component"}, + {"name": "eqnCoverageForMinusUnary2", "units": "dimensionless", "component": "my_component"}, {"name": "eqnComputedConstant1", "units": "dimensionless", "component": "my_component"}, {"name": "eqnComputedConstant2", "units": "dimensionless", "component": "my_component"} ] ALGEBRAIC_INFO = [ + {"name": "eqnOr", "units": "dimensionless", "component": "my_component"}, + {"name": "eqnOrMultiple", "units": "dimensionless", "component": "my_component"}, + {"name": "eqnXorCoverageParentheses", "units": "dimensionless", "component": "my_component"}, {"name": "eqnNlaVariable1", "units": "dimensionless", "component": "my_component"}, {"name": "eqnNlaVariable2", "units": "dimensionless", "component": "my_component"} ] @@ -326,21 +337,15 @@ def acot(x): def asech(x): - one_over_x = 1.0/x - - return log(one_over_x+sqrt(one_over_x*one_over_x-1.0)) + return acosh(1.0/x) def acsch(x): - one_over_x = 1.0/x - - return log(one_over_x+sqrt(one_over_x*one_over_x+1.0)) + return asinh(1.0/x) def acoth(x): - one_over_x = 1.0/x - - return 0.5*log((1.0+one_over_x)/(1.0-one_over_x)) + return atanh(1.0/x) def create_states_array(): @@ -375,23 +380,23 @@ def objective_function_0(u, f, data): algebraic = data[5] externals = data[6] - algebraic[0] = u[0] - algebraic[1] = u[1] + algebraic[3] = u[0] + algebraic[4] = u[1] - f[0] = algebraic[0]+algebraic[1]+states[0]-0.0 - f[1] = algebraic[0]-algebraic[1]-(computed_constants[197]+computed_constants[198]) + f[0] = algebraic[3]+algebraic[4]+states[0]-0.0 + f[1] = algebraic[3]-algebraic[4]-(computed_constants[205]+computed_constants[206]) def find_root_0(voi, states, rates, constants, computed_constants, algebraic, externals): u = [nan]*2 - u[0] = algebraic[0] - u[1] = algebraic[1] + u[0] = algebraic[3] + u[1] = algebraic[4] u = nla_solve(objective_function_0, u, 2, [voi, states, rates, constants, computed_constants, algebraic, externals]) - algebraic[0] = u[0] - algebraic[1] = u[1] + algebraic[3] = u[0] + algebraic[4] = u[1] def initialise_variables(states, rates, constants, computed_constants, algebraic): @@ -403,20 +408,21 @@ def initialise_variables(states, rates, constants, computed_constants, algebraic constants[4] = 5.0 constants[5] = 6.0 constants[6] = 7.0 - computed_constants[176] = 123.0 - computed_constants[177] = 123.456789 - computed_constants[178] = 123.0e99 - computed_constants[179] = 123.456789e99 - computed_constants[181] = 1.0 - computed_constants[182] = 0.0 - computed_constants[183] = 2.71828182845905 - computed_constants[184] = 3.14159265358979 - computed_constants[185] = inf - computed_constants[186] = nan - computed_constants[197] = 1.0 - computed_constants[198] = 3.0 - algebraic[0] = 1.0 - algebraic[1] = 2.0 + computed_constants[169] = nan + computed_constants[179] = 123.0 + computed_constants[180] = 123.456789 + computed_constants[181] = 123.0e99 + computed_constants[182] = 123.456789e99 + computed_constants[184] = 1.0 + computed_constants[185] = 0.0 + computed_constants[186] = 2.71828182845905 + computed_constants[187] = 3.14159265358979 + computed_constants[188] = inf + computed_constants[189] = nan + computed_constants[205] = 1.0 + computed_constants[206] = 3.0 + algebraic[3] = 1.0 + algebraic[4] = 2.0 def compute_computed_constants(constants, computed_constants): @@ -429,9 +435,9 @@ def compute_computed_constants(constants, computed_constants): computed_constants[6] = leq_func(constants[0], constants[1]) computed_constants[7] = constants[0]/leq_func(constants[1], constants[2]) computed_constants[8] = gt_func(constants[0], constants[1]) - computed_constants[9] = constants[0]/gt_func(constants[1], constants[2]) + computed_constants[9] = constants[0]/gt_func(constants[2], constants[1]) computed_constants[10] = geq_func(constants[0], constants[1]) - computed_constants[11] = constants[0]/geq_func(constants[1], constants[2]) + computed_constants[11] = constants[0]/geq_func(constants[2], constants[1]) computed_constants[12] = and_func(constants[0], constants[1]) computed_constants[13] = and_func(constants[0], and_func(constants[1], constants[2])) computed_constants[14] = and_func(lt_func(constants[0], constants[1]), gt_func(constants[2], constants[3])) @@ -448,165 +454,172 @@ def compute_computed_constants(constants, computed_constants): computed_constants[25] = and_func(lt_func(constants[0], constants[1]), pow(constants[2], constants[3])) computed_constants[26] = and_func(lt_func(constants[0], constants[1]), pow(constants[2], 1.0/constants[3])) computed_constants[27] = constants[0]/and_func(constants[1], constants[2]) - computed_constants[28] = or_func(constants[0], constants[1]) - computed_constants[29] = or_func(constants[0], or_func(constants[1], constants[2])) - computed_constants[30] = or_func(lt_func(constants[0], constants[1]), gt_func(constants[2], constants[3])) - computed_constants[31] = or_func(constants[0]+constants[1], gt_func(constants[2], constants[3])) - computed_constants[32] = or_func(constants[0], gt_func(constants[1], constants[2])) - computed_constants[33] = or_func(constants[0]-constants[1], gt_func(constants[2], constants[3])) - computed_constants[34] = or_func(-constants[0], gt_func(constants[1], constants[2])) - computed_constants[35] = or_func(pow(constants[0], constants[1]), gt_func(constants[2], constants[3])) - computed_constants[36] = or_func(pow(constants[0], 1.0/constants[1]), gt_func(constants[2], constants[3])) - computed_constants[37] = or_func(lt_func(constants[0], constants[1]), constants[2]+constants[3]) - computed_constants[38] = or_func(lt_func(constants[0], constants[1]), constants[2]) - computed_constants[39] = or_func(lt_func(constants[0], constants[1]), constants[2]-constants[3]) - computed_constants[40] = or_func(lt_func(constants[0], constants[1]), -constants[2]) - computed_constants[41] = or_func(lt_func(constants[0], constants[1]), pow(constants[2], constants[3])) - computed_constants[42] = or_func(lt_func(constants[0], constants[1]), pow(constants[2], 1.0/constants[3])) - computed_constants[43] = constants[0]/or_func(constants[1], constants[2]) - computed_constants[44] = xor_func(constants[0], constants[1]) - computed_constants[45] = xor_func(constants[0], xor_func(constants[1], constants[2])) - computed_constants[46] = xor_func(lt_func(constants[0], constants[1]), gt_func(constants[2], constants[3])) - computed_constants[47] = xor_func(constants[0]+constants[1], gt_func(constants[2], constants[3])) - computed_constants[48] = xor_func(constants[0], gt_func(constants[1], constants[2])) - computed_constants[49] = xor_func(constants[0]-constants[1], gt_func(constants[2], constants[3])) - computed_constants[50] = xor_func(-constants[0], gt_func(constants[1], constants[2])) - computed_constants[51] = xor_func(pow(constants[0], constants[1]), gt_func(constants[2], constants[3])) - computed_constants[52] = xor_func(pow(constants[0], 1.0/constants[1]), gt_func(constants[2], constants[3])) - computed_constants[53] = xor_func(lt_func(constants[0], constants[1]), constants[2]+constants[3]) - computed_constants[54] = xor_func(lt_func(constants[0], constants[1]), constants[2]) - computed_constants[55] = xor_func(lt_func(constants[0], constants[1]), constants[2]-constants[3]) - computed_constants[56] = xor_func(lt_func(constants[0], constants[1]), -constants[2]) - computed_constants[57] = xor_func(lt_func(constants[0], constants[1]), pow(constants[2], constants[3])) - computed_constants[58] = xor_func(lt_func(constants[0], constants[1]), pow(constants[2], 1.0/constants[3])) - computed_constants[59] = constants[0]/xor_func(constants[1], constants[2]) - computed_constants[60] = not_func(constants[0]) - computed_constants[61] = constants[0]+constants[1]+constants[2] - computed_constants[62] = lt_func(constants[0], constants[1])+gt_func(constants[2], constants[3]) - computed_constants[63] = constants[0] - computed_constants[64] = constants[0]-constants[1] - computed_constants[65] = lt_func(constants[0], constants[1])-gt_func(constants[2], constants[3]) - computed_constants[66] = lt_func(constants[0], constants[1])-(constants[2]+constants[3]) - computed_constants[67] = lt_func(constants[0], constants[1])-constants[2] - computed_constants[68] = constants[0]-(-constants[1]) - computed_constants[69] = constants[0]-(-constants[1]*constants[2]) - computed_constants[70] = -constants[0] - computed_constants[71] = -lt_func(constants[0], constants[1]) - computed_constants[72] = constants[0]*constants[1] - computed_constants[73] = constants[0]*constants[1]*constants[2] - computed_constants[74] = lt_func(constants[0], constants[1])*gt_func(constants[2], constants[3]) - computed_constants[75] = (constants[0]+constants[1])*gt_func(constants[2], constants[3]) - computed_constants[76] = constants[0]*gt_func(constants[1], constants[2]) - computed_constants[77] = (constants[0]-constants[1])*gt_func(constants[2], constants[3]) - computed_constants[78] = -constants[0]*gt_func(constants[1], constants[2]) - computed_constants[79] = lt_func(constants[0], constants[1])*(constants[2]+constants[3]) - computed_constants[80] = lt_func(constants[0], constants[1])*constants[2] - computed_constants[81] = lt_func(constants[0], constants[1])*(constants[2]-constants[3]) - computed_constants[82] = lt_func(constants[0], constants[1])*-constants[2] - computed_constants[83] = constants[0]/constants[1] - computed_constants[84] = lt_func(constants[0], constants[1])/gt_func(constants[3], constants[2]) - computed_constants[85] = (constants[0]+constants[1])/gt_func(constants[3], constants[2]) - computed_constants[86] = constants[0]/gt_func(constants[2], constants[1]) - computed_constants[87] = (constants[0]-constants[1])/gt_func(constants[3], constants[2]) - computed_constants[88] = -constants[0]/gt_func(constants[2], constants[1]) - computed_constants[89] = lt_func(constants[0], constants[1])/(constants[2]+constants[3]) - computed_constants[90] = lt_func(constants[0], constants[1])/constants[2] - computed_constants[91] = lt_func(constants[0], constants[1])/(constants[2]-constants[3]) - computed_constants[92] = lt_func(constants[0], constants[1])/-constants[2] - computed_constants[93] = lt_func(constants[0], constants[1])/(constants[2]*constants[3]) - computed_constants[94] = lt_func(constants[0], constants[1])/(constants[2]/constants[3]) - computed_constants[95] = sqrt(constants[0]) - computed_constants[96] = pow(constants[0], 2.0) - computed_constants[97] = pow(constants[0], 3.0) - computed_constants[98] = pow(constants[0], constants[1]) - computed_constants[99] = pow(leq_func(constants[0], constants[1]), geq_func(constants[2], constants[3])) - computed_constants[100] = pow(constants[0]+constants[1], geq_func(constants[2], constants[3])) - computed_constants[101] = pow(constants[0], geq_func(constants[1], constants[2])) - computed_constants[102] = pow(constants[0]-constants[1], geq_func(constants[2], constants[3])) - computed_constants[103] = pow(-constants[0], geq_func(constants[1], constants[2])) - computed_constants[104] = pow(constants[0]*constants[1], geq_func(constants[2], constants[3])) - computed_constants[105] = pow(constants[0]/constants[1], geq_func(constants[2], constants[3])) - computed_constants[106] = pow(leq_func(constants[0], constants[1]), constants[2]+constants[3]) - computed_constants[107] = pow(leq_func(constants[0], constants[1]), constants[2]) - computed_constants[108] = pow(leq_func(constants[0], constants[1]), constants[2]-constants[3]) - computed_constants[109] = pow(leq_func(constants[0], constants[1]), -constants[2]) - computed_constants[110] = pow(leq_func(constants[0], constants[1]), constants[2]*constants[3]) - computed_constants[111] = pow(leq_func(constants[0], constants[1]), constants[2]/constants[3]) - computed_constants[112] = pow(leq_func(constants[0], constants[1]), pow(constants[2], constants[3])) - computed_constants[113] = pow(leq_func(constants[0], constants[1]), pow(constants[2], 1.0/constants[3])) - computed_constants[114] = sqrt(constants[0]) - computed_constants[115] = sqrt(constants[0]) - computed_constants[116] = pow(constants[0], 1.0/3.0) - computed_constants[117] = pow(constants[0], 1.0/constants[1]) - computed_constants[118] = pow(lt_func(constants[0], constants[1]), 1.0/gt_func(constants[3], constants[2])) - computed_constants[119] = pow(constants[0]+constants[1], 1.0/gt_func(constants[3], constants[2])) - computed_constants[120] = pow(constants[0], 1.0/gt_func(constants[2], constants[1])) - computed_constants[121] = pow(constants[0]-constants[1], 1.0/gt_func(constants[3], constants[2])) - computed_constants[122] = pow(-constants[0], 1.0/gt_func(constants[2], constants[1])) - computed_constants[123] = pow(constants[0]*constants[1], 1.0/gt_func(constants[3], constants[2])) - computed_constants[124] = pow(constants[0]/constants[1], 1.0/gt_func(constants[3], constants[2])) - computed_constants[125] = pow(lt_func(constants[0], constants[1]), 1.0/(constants[2]+constants[3])) - computed_constants[126] = pow(lt_func(constants[0], constants[1]), 1.0/constants[2]) - computed_constants[127] = pow(lt_func(constants[0], constants[1]), 1.0/(constants[2]-constants[3])) - computed_constants[128] = pow(lt_func(constants[0], constants[1]), 1.0/-constants[2]) - computed_constants[129] = pow(lt_func(constants[0], constants[1]), 1.0/(constants[2]*constants[3])) - computed_constants[130] = pow(lt_func(constants[0], constants[1]), 1.0/(constants[2]/constants[3])) - computed_constants[131] = pow(lt_func(constants[0], constants[1]), 1.0/pow(constants[2], constants[3])) - computed_constants[132] = pow(lt_func(constants[0], constants[1]), 1.0/pow(constants[2], 1.0/constants[3])) - computed_constants[133] = fabs(constants[0]) - computed_constants[134] = exp(constants[0]) - computed_constants[135] = log(constants[0]) + computed_constants[28] = or_func(lt_func(constants[0], constants[1]), gt_func(constants[2], constants[3])) + computed_constants[29] = or_func(constants[0]+constants[1], gt_func(constants[2], constants[3])) + computed_constants[30] = or_func(constants[0], gt_func(constants[1], constants[2])) + computed_constants[31] = or_func(constants[0]-constants[1], gt_func(constants[2], constants[3])) + computed_constants[32] = or_func(-constants[0], gt_func(constants[1], constants[2])) + computed_constants[33] = or_func(pow(constants[0], constants[1]), gt_func(constants[2], constants[3])) + computed_constants[34] = or_func(pow(constants[0], 1.0/constants[1]), gt_func(constants[2], constants[3])) + computed_constants[35] = or_func(lt_func(constants[0], constants[1]), constants[2]+constants[3]) + computed_constants[36] = or_func(lt_func(constants[0], constants[1]), constants[2]) + computed_constants[37] = or_func(lt_func(constants[0], constants[1]), constants[2]-constants[3]) + computed_constants[38] = or_func(lt_func(constants[0], constants[1]), -constants[2]) + computed_constants[39] = or_func(lt_func(constants[0], constants[1]), pow(constants[2], constants[3])) + computed_constants[40] = or_func(lt_func(constants[0], constants[1]), pow(constants[2], 1.0/constants[3])) + computed_constants[41] = constants[0]/or_func(constants[1], constants[2]) + computed_constants[42] = xor_func(constants[0], constants[1]) + computed_constants[43] = xor_func(constants[0], xor_func(constants[1], constants[2])) + computed_constants[44] = xor_func(lt_func(constants[0], constants[1]), gt_func(constants[2], constants[3])) + computed_constants[45] = xor_func(constants[0]+constants[1], gt_func(constants[2], constants[3])) + computed_constants[46] = xor_func(constants[0], gt_func(constants[1], constants[2])) + computed_constants[47] = xor_func(constants[0]-constants[1], gt_func(constants[2], constants[3])) + computed_constants[48] = xor_func(-constants[0], gt_func(constants[1], constants[2])) + computed_constants[49] = xor_func(pow(constants[0], constants[1]), gt_func(constants[2], constants[3])) + computed_constants[50] = xor_func(pow(constants[0], 1.0/constants[1]), gt_func(constants[2], constants[3])) + computed_constants[51] = xor_func(lt_func(constants[0], constants[1]), constants[2]+constants[3]) + computed_constants[52] = xor_func(lt_func(constants[0], constants[1]), constants[2]) + computed_constants[53] = xor_func(lt_func(constants[0], constants[1]), constants[2]-constants[3]) + computed_constants[54] = xor_func(lt_func(constants[0], constants[1]), -constants[2]) + computed_constants[55] = xor_func(lt_func(constants[0], constants[1]), pow(constants[2], constants[3])) + computed_constants[56] = xor_func(lt_func(constants[0], constants[1]), pow(constants[2], 1.0/constants[3])) + computed_constants[57] = not_func(constants[0]) + computed_constants[58] = constants[0]+constants[1]+constants[2] + computed_constants[59] = lt_func(constants[0], constants[1])+gt_func(constants[2], constants[3]) + computed_constants[60] = constants[0] + computed_constants[61] = constants[0]-constants[1] + computed_constants[62] = lt_func(constants[0], constants[1])-gt_func(constants[2], constants[3]) + computed_constants[63] = lt_func(constants[0], constants[1])-(constants[2]+constants[3]) + computed_constants[64] = lt_func(constants[0], constants[1])-constants[2] + computed_constants[65] = constants[0]-(-constants[1]) + computed_constants[66] = constants[0]-(-constants[1]*constants[2]) + computed_constants[67] = -constants[0] + computed_constants[68] = -lt_func(constants[0], constants[1]) + computed_constants[69] = constants[0]*constants[1] + computed_constants[70] = constants[0]*constants[1]*constants[2] + computed_constants[71] = lt_func(constants[0], constants[1])*gt_func(constants[2], constants[3]) + computed_constants[72] = (constants[0]+constants[1])*gt_func(constants[2], constants[3]) + computed_constants[73] = constants[0]*gt_func(constants[1], constants[2]) + computed_constants[74] = (constants[0]-constants[1])*gt_func(constants[2], constants[3]) + computed_constants[75] = -constants[0]*gt_func(constants[1], constants[2]) + computed_constants[76] = lt_func(constants[0], constants[1])*(constants[2]+constants[3]) + computed_constants[77] = lt_func(constants[0], constants[1])*constants[2] + computed_constants[78] = lt_func(constants[0], constants[1])*(constants[2]-constants[3]) + computed_constants[79] = lt_func(constants[0], constants[1])*-constants[2] + computed_constants[80] = constants[0]/constants[1] + computed_constants[81] = lt_func(constants[0], constants[1])/gt_func(constants[3], constants[2]) + computed_constants[82] = (constants[0]+constants[1])/gt_func(constants[3], constants[2]) + computed_constants[83] = constants[0]/gt_func(constants[2], constants[1]) + computed_constants[84] = (constants[0]-constants[1])/gt_func(constants[3], constants[2]) + computed_constants[85] = -constants[0]/gt_func(constants[2], constants[1]) + computed_constants[86] = lt_func(constants[0], constants[1])/(constants[2]+constants[3]) + computed_constants[87] = lt_func(constants[0], constants[1])/constants[2] + computed_constants[88] = lt_func(constants[0], constants[1])/(constants[2]-constants[3]) + computed_constants[89] = lt_func(constants[0], constants[1])/-constants[2] + computed_constants[90] = lt_func(constants[0], constants[1])/(constants[2]*constants[3]) + computed_constants[91] = lt_func(constants[0], constants[1])/(constants[2]/constants[3]) + computed_constants[92] = sqrt(constants[0]) + computed_constants[93] = pow(constants[0], 2.0) + computed_constants[94] = pow(constants[0], 3.0) + computed_constants[95] = pow(constants[0], constants[1]) + computed_constants[96] = pow(leq_func(constants[0], constants[1]), geq_func(constants[2], constants[3])) + computed_constants[97] = pow(constants[0]+constants[1], geq_func(constants[2], constants[3])) + computed_constants[98] = pow(constants[0], geq_func(constants[1], constants[2])) + computed_constants[99] = pow(constants[0]-constants[1], geq_func(constants[2], constants[3])) + computed_constants[100] = pow(-constants[0], geq_func(constants[1], constants[2])) + computed_constants[101] = pow(constants[0]*constants[1], geq_func(constants[2], constants[3])) + computed_constants[102] = pow(constants[0]/constants[1], geq_func(constants[2], constants[3])) + computed_constants[103] = pow(leq_func(constants[0], constants[1]), constants[2]+constants[3]) + computed_constants[104] = pow(leq_func(constants[0], constants[1]), constants[2]) + computed_constants[105] = pow(leq_func(constants[0], constants[1]), constants[2]-constants[3]) + computed_constants[106] = pow(leq_func(constants[0], constants[1]), -constants[2]) + computed_constants[107] = pow(leq_func(constants[0], constants[1]), constants[2]*constants[3]) + computed_constants[108] = pow(leq_func(constants[0], constants[1]), constants[2]/constants[3]) + computed_constants[109] = pow(leq_func(constants[0], constants[1]), pow(constants[2], constants[3])) + computed_constants[110] = pow(leq_func(constants[0], constants[1]), pow(constants[2], 1.0/constants[3])) + computed_constants[111] = sqrt(constants[0]) + computed_constants[112] = sqrt(constants[0]) + computed_constants[113] = pow(constants[0], 1.0/0.5) + computed_constants[114] = pow(constants[0], 1.0/3.0) + computed_constants[115] = pow(constants[0], 1.0/constants[1]) + computed_constants[116] = pow(lt_func(constants[0], constants[1]), 1.0/gt_func(constants[3], constants[2])) + computed_constants[117] = pow(constants[0]+constants[1], 1.0/gt_func(constants[3], constants[2])) + computed_constants[118] = pow(constants[0], 1.0/gt_func(constants[2], constants[1])) + computed_constants[119] = pow(constants[0]-constants[1], 1.0/gt_func(constants[3], constants[2])) + computed_constants[120] = pow(-constants[0], 1.0/gt_func(constants[2], constants[1])) + computed_constants[121] = pow(constants[0]*constants[1], 1.0/gt_func(constants[3], constants[2])) + computed_constants[122] = pow(constants[0]/constants[1], 1.0/gt_func(constants[3], constants[2])) + computed_constants[123] = pow(lt_func(constants[0], constants[1]), 1.0/(constants[2]+constants[3])) + computed_constants[124] = pow(lt_func(constants[0], constants[1]), 1.0/constants[2]) + computed_constants[125] = pow(lt_func(constants[0], constants[1]), 1.0/(constants[2]-constants[3])) + computed_constants[126] = pow(lt_func(constants[0], constants[1]), 1.0/-constants[2]) + computed_constants[127] = pow(lt_func(constants[0], constants[1]), 1.0/(constants[2]*constants[3])) + computed_constants[128] = pow(lt_func(constants[0], constants[1]), 1.0/(constants[2]/constants[3])) + computed_constants[129] = pow(lt_func(constants[0], constants[1]), 1.0/pow(constants[2], constants[3])) + computed_constants[130] = pow(lt_func(constants[0], constants[1]), 1.0/pow(constants[2], 1.0/constants[3])) + computed_constants[131] = fabs(constants[0]) + computed_constants[132] = exp(constants[0]) + computed_constants[133] = log(constants[0]) + computed_constants[134] = log10(constants[0]) + computed_constants[135] = log(constants[0])/log(2.0) computed_constants[136] = log10(constants[0]) - computed_constants[137] = log(constants[0])/log(2.0) - computed_constants[138] = log10(constants[0]) - computed_constants[139] = log(constants[0])/log(constants[1]) - computed_constants[140] = ceil(constants[0]) - computed_constants[141] = floor(constants[0]) - computed_constants[142] = min(constants[0], constants[1]) - computed_constants[143] = min(constants[0], min(constants[1], constants[2])) - computed_constants[144] = max(constants[0], constants[1]) - computed_constants[145] = max(constants[0], max(constants[1], constants[2])) - computed_constants[146] = fmod(constants[0], constants[1]) - computed_constants[147] = sin(constants[0]) - computed_constants[148] = cos(constants[0]) - computed_constants[149] = tan(constants[0]) - computed_constants[150] = sec(constants[0]) - computed_constants[151] = csc(constants[0]) - computed_constants[152] = cot(constants[0]) - computed_constants[153] = sinh(constants[0]) - computed_constants[154] = cosh(constants[0]) - computed_constants[155] = tanh(constants[0]) - computed_constants[156] = sech(constants[0]) - computed_constants[157] = csch(constants[0]) - computed_constants[158] = coth(constants[0]) - computed_constants[159] = asin(constants[0]) - computed_constants[160] = acos(constants[0]) - computed_constants[161] = atan(constants[0]) - computed_constants[162] = asec(constants[0]) - computed_constants[163] = acsc(constants[0]) - computed_constants[164] = acot(constants[0]) - computed_constants[165] = asinh(constants[0]) - computed_constants[166] = acosh(constants[0]) - computed_constants[167] = atanh(constants[0]/2.0) - computed_constants[168] = asech(constants[0]) - computed_constants[169] = acsch(constants[0]) - computed_constants[170] = acoth(2.0*constants[0]) - computed_constants[171] = constants[0] if gt_func(constants[0], constants[1]) else nan - computed_constants[172] = constants[0] if gt_func(constants[0], constants[1]) else constants[2] - computed_constants[173] = constants[0] if gt_func(constants[0], constants[1]) else constants[2] if gt_func(constants[2], constants[3]) else constants[4] if gt_func(constants[4], constants[5]) else nan - computed_constants[174] = constants[0] if gt_func(constants[0], constants[1]) else constants[2] if gt_func(constants[2], constants[3]) else constants[4] if gt_func(constants[4], constants[5]) else constants[6] - computed_constants[175] = 123.0+(constants[0] if gt_func(constants[0], constants[1]) else nan) - computed_constants[180] = constants[0] - computed_constants[187] = and_func(constants[0], constants[1])+(constants[1] if gt_func(constants[2], constants[3]) else nan)+constants[4]+and_func(constants[5], constants[6]) - computed_constants[188] = and_func(constants[0], constants[1])-((constants[1] if gt_func(constants[2], constants[3]) else nan)-(constants[4]-(constants[1] if gt_func(constants[2], constants[3]) else nan)))-and_func(constants[5], constants[6]) - computed_constants[189] = and_func(constants[0], constants[1])*(constants[1] if gt_func(constants[2], constants[3]) else nan)*constants[4]*(constants[1] if gt_func(constants[2], constants[3]) else nan)*and_func(constants[5], constants[6]) - computed_constants[190] = and_func(constants[0], constants[1])/((constants[1] if gt_func(constants[2], constants[3]) else nan)/(constants[4]/(constants[1] if gt_func(constants[2], constants[3]) else nan))) - computed_constants[191] = and_func(or_func(constants[0], constants[1]), and_func(xor_func(constants[0], constants[1]), and_func(constants[1] if gt_func(constants[2], constants[3]) else nan, and_func(and_func(and_func(constants[4], constants[1] if gt_func(constants[2], constants[3]) else nan), xor_func(constants[0], constants[1])), or_func(constants[0], constants[1]))))) - computed_constants[192] = or_func(and_func(constants[0], constants[1]), or_func(xor_func(constants[0], constants[1]), or_func(constants[1] if gt_func(constants[2], constants[3]) else nan, or_func(or_func(or_func(constants[4], constants[1] if gt_func(constants[2], constants[3]) else nan), xor_func(constants[0], constants[1])), and_func(constants[0], constants[1]))))) - computed_constants[193] = xor_func(and_func(constants[0], constants[1]), xor_func(or_func(constants[0], constants[1]), xor_func(constants[1] if gt_func(constants[2], constants[3]) else nan, xor_func(xor_func(xor_func(constants[4], constants[1] if gt_func(constants[2], constants[3]) else nan), or_func(constants[0], constants[1])), and_func(constants[0], constants[1]))))) - computed_constants[194] = pow(and_func(constants[0], constants[1]), pow(constants[1] if gt_func(constants[2], constants[3]) else nan, pow(pow(constants[4], constants[1] if gt_func(constants[2], constants[3]) else nan), and_func(constants[0], constants[1])))) - computed_constants[195] = pow(pow(pow(and_func(constants[0], constants[1]), 1.0/pow(constants[1] if gt_func(constants[2], constants[3]) else nan, 1.0/constants[4])), 1.0/(constants[1] if gt_func(constants[2], constants[3]) else nan)), 1.0/and_func(constants[0], constants[1])) - computed_constants[196] = -and_func(constants[0], constants[1])+-(constants[1] if gt_func(constants[2], constants[3]) else nan) + computed_constants[137] = log(constants[0])/log(constants[1]) + computed_constants[138] = ceil(constants[0]) + computed_constants[139] = floor(constants[0]) + computed_constants[140] = min(constants[0], constants[1]) + computed_constants[141] = min(constants[0], min(constants[1], constants[2])) + computed_constants[142] = max(constants[0], constants[1]) + computed_constants[143] = max(constants[0], max(constants[1], constants[2])) + computed_constants[144] = fmod(constants[0], constants[1]) + computed_constants[145] = sin(constants[0]) + computed_constants[146] = cos(constants[0]) + computed_constants[147] = tan(constants[0]) + computed_constants[148] = sec(constants[0]) + computed_constants[149] = csc(constants[0]) + computed_constants[150] = cot(constants[0]) + computed_constants[151] = sinh(constants[0]) + computed_constants[152] = cosh(constants[0]) + computed_constants[153] = tanh(constants[0]) + computed_constants[154] = sech(constants[0]) + computed_constants[155] = csch(constants[0]) + computed_constants[156] = coth(constants[0]) + computed_constants[157] = asin(constants[0]) + computed_constants[158] = acos(constants[0]) + computed_constants[159] = atan(constants[0]) + computed_constants[160] = asec(constants[0]) + computed_constants[161] = acsc(constants[0]) + computed_constants[162] = acot(constants[0]) + computed_constants[163] = asinh(constants[0]) + computed_constants[164] = acosh(constants[0]) + computed_constants[165] = atanh(constants[0]/2.0) + computed_constants[166] = asech(constants[0]) + computed_constants[167] = acsch(constants[0]) + computed_constants[168] = acoth(2.0*constants[0]) + computed_constants[170] = constants[0] if gt_func(constants[0], constants[1]) else nan + computed_constants[171] = constants[0] if lt_func(constants[0], constants[1]) else nan + computed_constants[172] = constants[0] + computed_constants[173] = constants[0] if gt_func(constants[0], constants[1]) else constants[2] + computed_constants[174] = constants[0] if gt_func(constants[0], constants[1]) else constants[2] if gt_func(constants[2], constants[3]) else constants[4] if gt_func(constants[4], constants[5]) else nan + computed_constants[175] = constants[0] if lt_func(constants[0], constants[1]) else constants[2] if gt_func(constants[2], constants[3]) else constants[4] if gt_func(constants[4], constants[5]) else nan + computed_constants[176] = constants[0] if gt_func(constants[0], constants[1]) else constants[2] if gt_func(constants[2], constants[3]) else constants[4] if gt_func(constants[4], constants[5]) else constants[6] + computed_constants[177] = 123.0+(constants[0] if gt_func(constants[0], constants[1]) else nan) + computed_constants[178] = 123.0+(constants[0] if lt_func(constants[0], constants[1]) else nan) + computed_constants[183] = constants[0] + computed_constants[190] = and_func(constants[0], constants[1])+(constants[1] if gt_func(constants[2], constants[3]) else nan)+constants[4]+and_func(constants[5], constants[6]) + computed_constants[191] = and_func(constants[0], constants[1])+(constants[1] if lt_func(constants[2], constants[3]) else nan)+constants[4]+and_func(constants[5], constants[6]) + computed_constants[192] = and_func(constants[0], constants[1])-((constants[1] if gt_func(constants[2], constants[3]) else nan)-(constants[4]-(constants[1] if gt_func(constants[2], constants[3]) else nan)))-and_func(constants[5], constants[6]) + computed_constants[193] = and_func(constants[0], constants[1])-((constants[1] if lt_func(constants[2], constants[3]) else nan)-(constants[4]-(constants[1] if lt_func(constants[2], constants[3]) else nan)))-and_func(constants[5], constants[6]) + computed_constants[194] = and_func(constants[0], constants[1])*(constants[1] if gt_func(constants[2], constants[3]) else nan)*constants[4]*(constants[1] if gt_func(constants[2], constants[3]) else nan)*and_func(constants[5], constants[6]) + computed_constants[195] = and_func(constants[0], constants[1])*(constants[1] if lt_func(constants[2], constants[3]) else nan)*constants[4]*(constants[1] if lt_func(constants[2], constants[3]) else nan)*and_func(constants[5], constants[6]) + computed_constants[196] = and_func(constants[0], constants[1])/((constants[1] if gt_func(constants[2], constants[3]) else nan)/(constants[4]/(constants[1] if gt_func(constants[2], constants[3]) else nan))) + computed_constants[197] = and_func(constants[0], constants[1])/((constants[1] if lt_func(constants[2], constants[3]) else nan)/(constants[4]/(constants[1] if lt_func(constants[2], constants[3]) else nan))) + computed_constants[198] = and_func(or_func(constants[0], constants[1]), and_func(xor_func(constants[0], constants[1]), and_func(constants[1] if gt_func(constants[2], constants[3]) else nan, and_func(and_func(and_func(constants[4], constants[1] if gt_func(constants[2], constants[3]) else nan), xor_func(constants[0], constants[1])), or_func(constants[0], constants[1]))))) + computed_constants[199] = or_func(and_func(constants[0], constants[1]), or_func(xor_func(constants[0], constants[1]), or_func(constants[1] if gt_func(constants[2], constants[3]) else nan, or_func(or_func(or_func(constants[4], constants[1] if gt_func(constants[2], constants[3]) else nan), xor_func(constants[0], constants[1])), and_func(constants[0], constants[1]))))) + computed_constants[200] = xor_func(and_func(constants[0], constants[1]), xor_func(or_func(constants[0], constants[1]), xor_func(constants[1] if gt_func(constants[2], constants[3]) else nan, xor_func(xor_func(xor_func(constants[4], constants[1] if gt_func(constants[2], constants[3]) else nan), or_func(constants[0], constants[1])), and_func(constants[0], constants[1]))))) + computed_constants[201] = pow(and_func(constants[0], constants[1]), pow(constants[1] if gt_func(constants[2], constants[3]) else nan, pow(pow(constants[4], constants[1] if gt_func(constants[2], constants[3]) else nan), and_func(constants[0], constants[1])))) + computed_constants[202] = pow(pow(pow(and_func(constants[0], constants[1]), 1.0/pow(constants[1] if gt_func(constants[2], constants[3]) else nan, 1.0/constants[4])), 1.0/(constants[1] if gt_func(constants[2], constants[3]) else nan)), 1.0/and_func(constants[0], constants[1])) + computed_constants[203] = -and_func(constants[0], constants[1])+-(constants[1] if gt_func(constants[2], constants[3]) else nan) + computed_constants[204] = -and_func(constants[0], constants[1])+-(constants[1] if lt_func(constants[2], constants[3]) else nan) def compute_rates(voi, states, rates, constants, computed_constants, algebraic, externals, external_variable): @@ -614,5 +627,8 @@ def compute_rates(voi, states, rates, constants, computed_constants, algebraic, def compute_variables(voi, states, rates, constants, computed_constants, algebraic, externals, external_variable): + algebraic[0] = or_func(states[0], states[0]) + algebraic[1] = or_func(states[0], or_func(states[0], constants[0])) + algebraic[2] = constants[0]/xor_func(constants[1], states[0]) externals[0] = external_variable(voi, states, rates, constants, computed_constants, algebraic, externals, 0) find_root_0(voi, states, rates, constants, computed_constants, algebraic, externals) diff --git a/tests/resources/coverage/generator/model.modified.profile.c b/tests/resources/coverage/generator/model.xor.c similarity index 65% rename from tests/resources/coverage/generator/model.modified.profile.c rename to tests/resources/coverage/generator/model.xor.c index 6bbe6f4075..9861b1a292 100644 --- a/tests/resources/coverage/generator/model.modified.profile.c +++ b/tests/resources/coverage/generator/model.xor.c @@ -10,8 +10,8 @@ const char LIBCELLML_VERSION[] = "0.6.0"; const size_t STATE_COUNT = 1; const size_t CONSTANT_COUNT = 7; -const size_t COMPUTED_CONSTANT_COUNT = 199; -const size_t ALGEBRAIC_COUNT = 2; +const size_t COMPUTED_CONSTANT_COUNT = 207; +const size_t ALGEBRAIC_COUNT = 5; const size_t EXTERNAL_COUNT = 1; const VariableInfo VOI_INFO = {"t", "second", "my_component"}; @@ -59,8 +59,6 @@ const VariableInfo COMPUTED_CONSTANT_INFO[] = { {"eqnAndParenthesesRightPower", "dimensionless", "my_component"}, {"eqnAndParenthesesRightRoot", "dimensionless", "my_component"}, {"eqnAndCoverageParentheses", "dimensionless", "my_component"}, - {"eqnOr", "dimensionless", "my_component"}, - {"eqnOrMultiple", "dimensionless", "my_component"}, {"eqnOrParentheses", "dimensionless", "my_component"}, {"eqnOrParenthesesLeftPlusWith", "dimensionless", "my_component"}, {"eqnOrParenthesesLeftPlusWithout", "dimensionless", "my_component"}, @@ -90,7 +88,6 @@ const VariableInfo COMPUTED_CONSTANT_INFO[] = { {"eqnXorParenthesesRightMinusWithout", "dimensionless", "my_component"}, {"eqnXorParenthesesRightPower", "dimensionless", "my_component"}, {"eqnXorParenthesesRightRoot", "dimensionless", "my_component"}, - {"eqnXorCoverageParentheses", "dimensionless", "my_component"}, {"eqnNot", "dimensionless", "my_component"}, {"eqnPlusMultiple", "dimensionless", "my_component"}, {"eqnPlusParentheses", "dimensionless", "my_component"}, @@ -147,6 +144,7 @@ const VariableInfo COMPUTED_CONSTANT_INFO[] = { {"eqnPowerParenthesesRightRoot", "dimensionless", "my_component"}, {"eqnRootSqrt", "dimensionless", "my_component"}, {"eqnRootSqrtOther", "dimensionless", "my_component"}, + {"eqnRootSqr", "dimensionless", "my_component"}, {"eqnRootCube", "dimensionless", "my_component"}, {"eqnRootCi", "dimensionless", "my_component"}, {"eqnRootParentheses", "dimensionless", "my_component"}, @@ -202,11 +200,16 @@ const VariableInfo COMPUTED_CONSTANT_INFO[] = { {"eqnArcsech", "dimensionless", "my_component"}, {"eqnArccsch", "dimensionless", "my_component"}, {"eqnArccoth", "dimensionless", "my_component"}, + {"eqnPiecewise", "dimensionless", "my_component"}, {"eqnPiecewisePiece", "dimensionless", "my_component"}, + {"eqnPiecewisePiece2", "dimensionless", "my_component"}, + {"eqnPiecewiseOtherwise", "dimensionless", "my_component"}, {"eqnPiecewisePieceOtherwise", "dimensionless", "my_component"}, {"eqnPiecewisePiecePiecePiece", "dimensionless", "my_component"}, + {"eqnPiecewisePiecePiecePiece2", "dimensionless", "my_component"}, {"eqnPiecewisePiecePiecePieceOtherwise", "dimensionless", "my_component"}, {"eqnWithPiecewise", "dimensionless", "my_component"}, + {"eqnWithPiecewise2", "dimensionless", "my_component"}, {"eqnCnInteger", "dimensionless", "my_component"}, {"eqnCnDouble", "dimensionless", "my_component"}, {"eqnCnIntegerWithExponent", "dimensionless", "my_component"}, @@ -219,20 +222,28 @@ const VariableInfo COMPUTED_CONSTANT_INFO[] = { {"eqnInfinity", "dimensionless", "my_component"}, {"eqnNotanumber", "dimensionless", "my_component"}, {"eqnCoverageForPlusOperator", "dimensionless", "my_component"}, + {"eqnCoverageForPlusOperator2", "dimensionless", "my_component"}, {"eqnCoverageForMinusOperator", "dimensionless", "my_component"}, + {"eqnCoverageForMinusOperator2", "dimensionless", "my_component"}, {"eqnCoverageForTimesOperator", "dimensionless", "my_component"}, + {"eqnCoverageForTimesOperator2", "dimensionless", "my_component"}, {"eqnCoverageForDivideOperator", "dimensionless", "my_component"}, + {"eqnCoverageForDivideOperator2", "dimensionless", "my_component"}, {"eqnCoverageForAndOperator", "dimensionless", "my_component"}, {"eqnCoverageForOrOperator", "dimensionless", "my_component"}, {"eqnCoverageForXorOperator", "dimensionless", "my_component"}, {"eqnCoverageForPowerOperator", "dimensionless", "my_component"}, {"eqnCoverageForRootOperator", "dimensionless", "my_component"}, {"eqnCoverageForMinusUnary", "dimensionless", "my_component"}, + {"eqnCoverageForMinusUnary2", "dimensionless", "my_component"}, {"eqnComputedConstant1", "dimensionless", "my_component"}, {"eqnComputedConstant2", "dimensionless", "my_component"} }; const VariableInfo ALGEBRAIC_INFO[] = { + {"eqnOr", "dimensionless", "my_component"}, + {"eqnOrMultiple", "dimensionless", "my_component"}, + {"eqnXorCoverageParentheses", "dimensionless", "my_component"}, {"eqnNlaVariable1", "dimensionless", "my_component"}, {"eqnNlaVariable2", "dimensionless", "my_component"} }; @@ -241,21 +252,11 @@ const VariableInfo EXTERNAL_INFO[] = { {"eqnPlus", "dimensionless", "my_component"} }; -double xor(double x, double y) +double XOR(double x, double y) { return (x != 0.0) ^ (y != 0.0); } -double min(double x, double y) -{ - return (x < y)?x:y; -} - -double max(double x, double y) -{ - return (x > y)?x:y; -} - double sec(double x) { return 1.0/cos(x); @@ -303,26 +304,20 @@ double acot(double x) double asech(double x) { - double oneOverX = 1.0/x; - - return log(oneOverX+sqrt(oneOverX*oneOverX-1.0)); + return acosh(1.0/x); } double acsch(double x) { - double oneOverX = 1.0/x; - - return log(oneOverX+sqrt(oneOverX*oneOverX+1.0)); + return asinh(1.0/x); } double acoth(double x) { - double oneOverX = 1.0/x; - - return 0.5*log((1.0+oneOverX)/(1.0-oneOverX)); + return atanh(1.0/x); } -double * createStatesVector() +double * createStatesArray() { double *res = (double *) malloc(STATE_COUNT*sizeof(double)); @@ -405,11 +400,11 @@ void objectiveFunction0(double *u, double *f, void *data) double *algebraic = ((RootFindingInfo *) data)->algebraic; double *externals = ((RootFindingInfo *) data)->externals; - algebraic[0] = u[0]; - algebraic[1] = u[1]; + algebraic[3] = u[0]; + algebraic[4] = u[1]; - f[0] = algebraic[0]+algebraic[1]+states[0]-0.0; - f[1] = algebraic[0]-algebraic[1]-(computedConstants[197]+computedConstants[198]); + f[0] = algebraic[3]+algebraic[4]+states[0]-0.0; + f[1] = algebraic[3]-algebraic[4]-(computedConstants[205]+computedConstants[206]); } void findRoot0(double voi, double *states, double *rates, double *constants, double *computedConstants, double *algebraic, double *externals) @@ -417,13 +412,13 @@ void findRoot0(double voi, double *states, double *rates, double *constants, dou RootFindingInfo rfi = { voi, states, rates, constants, computedConstants, algebraic, externals }; double u[2]; - u[0] = algebraic[0]; - u[1] = algebraic[1]; + u[0] = algebraic[3]; + u[1] = algebraic[4]; nlaSolve(objectiveFunction0, u, 2, &rfi); - algebraic[0] = u[0]; - algebraic[1] = u[1]; + algebraic[3] = u[0]; + algebraic[4] = u[1]; } void initialiseVariables(double *states, double *rates, double *constants, double *computedConstants, double *algebraic) @@ -436,20 +431,21 @@ void initialiseVariables(double *states, double *rates, double *constants, doubl constants[4] = 5.0; constants[5] = 6.0; constants[6] = 7.0; - computedConstants[176] = 123.0; - computedConstants[177] = 123.456789; - computedConstants[178] = 123.0e99; - computedConstants[179] = 123.456789e99; - computedConstants[181] = 1.0; - computedConstants[182] = 0.0; - computedConstants[183] = 2.71828182845905; - computedConstants[184] = 3.14159265358979; - computedConstants[185] = INFINITY; - computedConstants[186] = NAN; - computedConstants[197] = 1.0; - computedConstants[198] = 3.0; - algebraic[0] = 1.0; - algebraic[1] = 2.0; + computedConstants[169] = NAN; + computedConstants[179] = 123.0; + computedConstants[180] = 123.456789; + computedConstants[181] = 123.0e99; + computedConstants[182] = 123.456789e99; + computedConstants[184] = 1.0; + computedConstants[185] = 0.0; + computedConstants[186] = 2.71828182845905; + computedConstants[187] = 3.14159265358979; + computedConstants[188] = INFINITY; + computedConstants[189] = NAN; + computedConstants[205] = 1.0; + computedConstants[206] = 3.0; + algebraic[3] = 1.0; + algebraic[4] = 2.0; } void computeComputedConstants(double *constants, double *computedConstants) @@ -463,9 +459,9 @@ void computeComputedConstants(double *constants, double *computedConstants) computedConstants[6] = constants[0] <= constants[1]; computedConstants[7] = constants[0]/(constants[1] <= constants[2]); computedConstants[8] = constants[0] > constants[1]; - computedConstants[9] = constants[0]/(constants[1] > constants[2]); + computedConstants[9] = constants[0]/(constants[2] > constants[1]); computedConstants[10] = constants[0] >= constants[1]; - computedConstants[11] = constants[0]/(constants[1] >= constants[2]); + computedConstants[11] = constants[0]/(constants[2] >= constants[1]); computedConstants[12] = constants[0] && constants[1]; computedConstants[13] = constants[0] && constants[1] && constants[2]; computedConstants[14] = (constants[0] < constants[1]) && (constants[2] > constants[3]); @@ -482,165 +478,172 @@ void computeComputedConstants(double *constants, double *computedConstants) computedConstants[25] = (constants[0] < constants[1]) && pow(constants[2], constants[3]); computedConstants[26] = (constants[0] < constants[1]) && pow(constants[2], 1.0/constants[3]); computedConstants[27] = constants[0]/(constants[1] && constants[2]); - computedConstants[28] = constants[0] || constants[1]; - computedConstants[29] = constants[0] || constants[1] || constants[2]; - computedConstants[30] = (constants[0] < constants[1]) || (constants[2] > constants[3]); - computedConstants[31] = (constants[0]+constants[1]) || (constants[2] > constants[3]); - computedConstants[32] = constants[0] || (constants[1] > constants[2]); - computedConstants[33] = (constants[0]-constants[1]) || (constants[2] > constants[3]); - computedConstants[34] = -constants[0] || (constants[1] > constants[2]); - computedConstants[35] = pow(constants[0], constants[1]) || (constants[2] > constants[3]); - computedConstants[36] = pow(constants[0], 1.0/constants[1]) || (constants[2] > constants[3]); - computedConstants[37] = (constants[0] < constants[1]) || (constants[2]+constants[3]); - computedConstants[38] = (constants[0] < constants[1]) || constants[2]; - computedConstants[39] = (constants[0] < constants[1]) || (constants[2]-constants[3]); - computedConstants[40] = (constants[0] < constants[1]) || -constants[2]; - computedConstants[41] = (constants[0] < constants[1]) || pow(constants[2], constants[3]); - computedConstants[42] = (constants[0] < constants[1]) || pow(constants[2], 1.0/constants[3]); - computedConstants[43] = constants[0]/(constants[1] || constants[2]); - computedConstants[44] = xor(constants[0], constants[1]); - computedConstants[45] = xor(constants[0], xor(constants[1], constants[2])); - computedConstants[46] = xor(constants[0] < constants[1], constants[2] > constants[3]); - computedConstants[47] = xor(constants[0]+constants[1], constants[2] > constants[3]); - computedConstants[48] = xor(constants[0], constants[1] > constants[2]); - computedConstants[49] = xor(constants[0]-constants[1], constants[2] > constants[3]); - computedConstants[50] = xor(-constants[0], constants[1] > constants[2]); - computedConstants[51] = xor(pow(constants[0], constants[1]), constants[2] > constants[3]); - computedConstants[52] = xor(pow(constants[0], 1.0/constants[1]), constants[2] > constants[3]); - computedConstants[53] = xor(constants[0] < constants[1], constants[2]+constants[3]); - computedConstants[54] = xor(constants[0] < constants[1], constants[2]); - computedConstants[55] = xor(constants[0] < constants[1], constants[2]-constants[3]); - computedConstants[56] = xor(constants[0] < constants[1], -constants[2]); - computedConstants[57] = xor(constants[0] < constants[1], pow(constants[2], constants[3])); - computedConstants[58] = xor(constants[0] < constants[1], pow(constants[2], 1.0/constants[3])); - computedConstants[59] = constants[0]/xor(constants[1], constants[2]); - computedConstants[60] = !constants[0]; - computedConstants[61] = constants[0]+constants[1]+constants[2]; - computedConstants[62] = (constants[0] < constants[1])+(constants[2] > constants[3]); - computedConstants[63] = constants[0]; - computedConstants[64] = constants[0]-constants[1]; - computedConstants[65] = (constants[0] < constants[1])-(constants[2] > constants[3]); - computedConstants[66] = (constants[0] < constants[1])-(constants[2]+constants[3]); - computedConstants[67] = (constants[0] < constants[1])-constants[2]; - computedConstants[68] = constants[0]-(-constants[1]); - computedConstants[69] = constants[0]-(-constants[1]*constants[2]); - computedConstants[70] = -constants[0]; - computedConstants[71] = -(constants[0] < constants[1]); - computedConstants[72] = constants[0]*constants[1]; - computedConstants[73] = constants[0]*constants[1]*constants[2]; - computedConstants[74] = (constants[0] < constants[1])*(constants[2] > constants[3]); - computedConstants[75] = (constants[0]+constants[1])*(constants[2] > constants[3]); - computedConstants[76] = constants[0]*(constants[1] > constants[2]); - computedConstants[77] = (constants[0]-constants[1])*(constants[2] > constants[3]); - computedConstants[78] = -constants[0]*(constants[1] > constants[2]); - computedConstants[79] = (constants[0] < constants[1])*(constants[2]+constants[3]); - computedConstants[80] = (constants[0] < constants[1])*constants[2]; - computedConstants[81] = (constants[0] < constants[1])*(constants[2]-constants[3]); - computedConstants[82] = (constants[0] < constants[1])*-constants[2]; - computedConstants[83] = constants[0]/constants[1]; - computedConstants[84] = (constants[0] < constants[1])/(constants[3] > constants[2]); - computedConstants[85] = (constants[0]+constants[1])/(constants[3] > constants[2]); - computedConstants[86] = constants[0]/(constants[2] > constants[1]); - computedConstants[87] = (constants[0]-constants[1])/(constants[3] > constants[2]); - computedConstants[88] = -constants[0]/(constants[2] > constants[1]); - computedConstants[89] = (constants[0] < constants[1])/(constants[2]+constants[3]); - computedConstants[90] = (constants[0] < constants[1])/constants[2]; - computedConstants[91] = (constants[0] < constants[1])/(constants[2]-constants[3]); - computedConstants[92] = (constants[0] < constants[1])/-constants[2]; - computedConstants[93] = (constants[0] < constants[1])/(constants[2]*constants[3]); - computedConstants[94] = (constants[0] < constants[1])/(constants[2]/constants[3]); - computedConstants[95] = sqrt(constants[0]); - computedConstants[96] = pow(constants[0], 2.0); - computedConstants[97] = pow(constants[0], 3.0); - computedConstants[98] = pow(constants[0], constants[1]); - computedConstants[99] = pow(constants[0] <= constants[1], constants[2] >= constants[3]); - computedConstants[100] = pow(constants[0]+constants[1], constants[2] >= constants[3]); - computedConstants[101] = pow(constants[0], constants[1] >= constants[2]); - computedConstants[102] = pow(constants[0]-constants[1], constants[2] >= constants[3]); - computedConstants[103] = pow(-constants[0], constants[1] >= constants[2]); - computedConstants[104] = pow(constants[0]*constants[1], constants[2] >= constants[3]); - computedConstants[105] = pow(constants[0]/constants[1], constants[2] >= constants[3]); - computedConstants[106] = pow(constants[0] <= constants[1], constants[2]+constants[3]); - computedConstants[107] = pow(constants[0] <= constants[1], constants[2]); - computedConstants[108] = pow(constants[0] <= constants[1], constants[2]-constants[3]); - computedConstants[109] = pow(constants[0] <= constants[1], -constants[2]); - computedConstants[110] = pow(constants[0] <= constants[1], constants[2]*constants[3]); - computedConstants[111] = pow(constants[0] <= constants[1], constants[2]/constants[3]); - computedConstants[112] = pow(constants[0] <= constants[1], pow(constants[2], constants[3])); - computedConstants[113] = pow(constants[0] <= constants[1], pow(constants[2], 1.0/constants[3])); - computedConstants[114] = sqrt(constants[0]); - computedConstants[115] = sqrt(constants[0]); - computedConstants[116] = pow(constants[0], 1.0/3.0); - computedConstants[117] = pow(constants[0], 1.0/constants[1]); - computedConstants[118] = pow(constants[0] < constants[1], 1.0/(constants[3] > constants[2])); - computedConstants[119] = pow(constants[0]+constants[1], 1.0/(constants[3] > constants[2])); - computedConstants[120] = pow(constants[0], 1.0/(constants[2] > constants[1])); - computedConstants[121] = pow(constants[0]-constants[1], 1.0/(constants[3] > constants[2])); - computedConstants[122] = pow(-constants[0], 1.0/(constants[2] > constants[1])); - computedConstants[123] = pow(constants[0]*constants[1], 1.0/(constants[3] > constants[2])); - computedConstants[124] = pow(constants[0]/constants[1], 1.0/(constants[3] > constants[2])); - computedConstants[125] = pow(constants[0] < constants[1], 1.0/(constants[2]+constants[3])); - computedConstants[126] = pow(constants[0] < constants[1], 1.0/constants[2]); - computedConstants[127] = pow(constants[0] < constants[1], 1.0/(constants[2]-constants[3])); - computedConstants[128] = pow(constants[0] < constants[1], 1.0/-constants[2]); - computedConstants[129] = pow(constants[0] < constants[1], 1.0/(constants[2]*constants[3])); - computedConstants[130] = pow(constants[0] < constants[1], 1.0/(constants[2]/constants[3])); - computedConstants[131] = pow(constants[0] < constants[1], 1.0/pow(constants[2], constants[3])); - computedConstants[132] = pow(constants[0] < constants[1], 1.0/pow(constants[2], 1.0/constants[3])); - computedConstants[133] = fabs(constants[0]); - computedConstants[134] = exp(constants[0]); - computedConstants[135] = log(constants[0]); + computedConstants[28] = (constants[0] < constants[1]) || (constants[2] > constants[3]); + computedConstants[29] = (constants[0]+constants[1]) || (constants[2] > constants[3]); + computedConstants[30] = constants[0] || (constants[1] > constants[2]); + computedConstants[31] = (constants[0]-constants[1]) || (constants[2] > constants[3]); + computedConstants[32] = -constants[0] || (constants[1] > constants[2]); + computedConstants[33] = pow(constants[0], constants[1]) || (constants[2] > constants[3]); + computedConstants[34] = pow(constants[0], 1.0/constants[1]) || (constants[2] > constants[3]); + computedConstants[35] = (constants[0] < constants[1]) || (constants[2]+constants[3]); + computedConstants[36] = (constants[0] < constants[1]) || constants[2]; + computedConstants[37] = (constants[0] < constants[1]) || (constants[2]-constants[3]); + computedConstants[38] = (constants[0] < constants[1]) || -constants[2]; + computedConstants[39] = (constants[0] < constants[1]) || pow(constants[2], constants[3]); + computedConstants[40] = (constants[0] < constants[1]) || pow(constants[2], 1.0/constants[3]); + computedConstants[41] = constants[0]/(constants[1] || constants[2]); + computedConstants[42] = XOR(constants[0], constants[1]); + computedConstants[43] = XOR(constants[0], XOR(constants[1], constants[2])); + computedConstants[44] = XOR(constants[0] < constants[1], constants[2] > constants[3]); + computedConstants[45] = XOR(constants[0]+constants[1], constants[2] > constants[3]); + computedConstants[46] = XOR(constants[0], constants[1] > constants[2]); + computedConstants[47] = XOR(constants[0]-constants[1], constants[2] > constants[3]); + computedConstants[48] = XOR(-constants[0], constants[1] > constants[2]); + computedConstants[49] = XOR(pow(constants[0], constants[1]), constants[2] > constants[3]); + computedConstants[50] = XOR(pow(constants[0], 1.0/constants[1]), constants[2] > constants[3]); + computedConstants[51] = XOR(constants[0] < constants[1], constants[2]+constants[3]); + computedConstants[52] = XOR(constants[0] < constants[1], constants[2]); + computedConstants[53] = XOR(constants[0] < constants[1], constants[2]-constants[3]); + computedConstants[54] = XOR(constants[0] < constants[1], -constants[2]); + computedConstants[55] = XOR(constants[0] < constants[1], pow(constants[2], constants[3])); + computedConstants[56] = XOR(constants[0] < constants[1], pow(constants[2], 1.0/constants[3])); + computedConstants[57] = !constants[0]; + computedConstants[58] = constants[0]+constants[1]+constants[2]; + computedConstants[59] = (constants[0] < constants[1])+(constants[2] > constants[3]); + computedConstants[60] = constants[0]; + computedConstants[61] = constants[0]-constants[1]; + computedConstants[62] = (constants[0] < constants[1])-(constants[2] > constants[3]); + computedConstants[63] = (constants[0] < constants[1])-(constants[2]+constants[3]); + computedConstants[64] = (constants[0] < constants[1])-constants[2]; + computedConstants[65] = constants[0]-(-constants[1]); + computedConstants[66] = constants[0]-(-constants[1]*constants[2]); + computedConstants[67] = -constants[0]; + computedConstants[68] = -(constants[0] < constants[1]); + computedConstants[69] = constants[0]*constants[1]; + computedConstants[70] = constants[0]*constants[1]*constants[2]; + computedConstants[71] = (constants[0] < constants[1])*(constants[2] > constants[3]); + computedConstants[72] = (constants[0]+constants[1])*(constants[2] > constants[3]); + computedConstants[73] = constants[0]*(constants[1] > constants[2]); + computedConstants[74] = (constants[0]-constants[1])*(constants[2] > constants[3]); + computedConstants[75] = -constants[0]*(constants[1] > constants[2]); + computedConstants[76] = (constants[0] < constants[1])*(constants[2]+constants[3]); + computedConstants[77] = (constants[0] < constants[1])*constants[2]; + computedConstants[78] = (constants[0] < constants[1])*(constants[2]-constants[3]); + computedConstants[79] = (constants[0] < constants[1])*-constants[2]; + computedConstants[80] = constants[0]/constants[1]; + computedConstants[81] = (constants[0] < constants[1])/(constants[3] > constants[2]); + computedConstants[82] = (constants[0]+constants[1])/(constants[3] > constants[2]); + computedConstants[83] = constants[0]/(constants[2] > constants[1]); + computedConstants[84] = (constants[0]-constants[1])/(constants[3] > constants[2]); + computedConstants[85] = -constants[0]/(constants[2] > constants[1]); + computedConstants[86] = (constants[0] < constants[1])/(constants[2]+constants[3]); + computedConstants[87] = (constants[0] < constants[1])/constants[2]; + computedConstants[88] = (constants[0] < constants[1])/(constants[2]-constants[3]); + computedConstants[89] = (constants[0] < constants[1])/-constants[2]; + computedConstants[90] = (constants[0] < constants[1])/(constants[2]*constants[3]); + computedConstants[91] = (constants[0] < constants[1])/(constants[2]/constants[3]); + computedConstants[92] = sqrt(constants[0]); + computedConstants[93] = pow(constants[0], 2.0); + computedConstants[94] = pow(constants[0], 3.0); + computedConstants[95] = pow(constants[0], constants[1]); + computedConstants[96] = pow(constants[0] <= constants[1], constants[2] >= constants[3]); + computedConstants[97] = pow(constants[0]+constants[1], constants[2] >= constants[3]); + computedConstants[98] = pow(constants[0], constants[1] >= constants[2]); + computedConstants[99] = pow(constants[0]-constants[1], constants[2] >= constants[3]); + computedConstants[100] = pow(-constants[0], constants[1] >= constants[2]); + computedConstants[101] = pow(constants[0]*constants[1], constants[2] >= constants[3]); + computedConstants[102] = pow(constants[0]/constants[1], constants[2] >= constants[3]); + computedConstants[103] = pow(constants[0] <= constants[1], constants[2]+constants[3]); + computedConstants[104] = pow(constants[0] <= constants[1], constants[2]); + computedConstants[105] = pow(constants[0] <= constants[1], constants[2]-constants[3]); + computedConstants[106] = pow(constants[0] <= constants[1], -constants[2]); + computedConstants[107] = pow(constants[0] <= constants[1], constants[2]*constants[3]); + computedConstants[108] = pow(constants[0] <= constants[1], constants[2]/constants[3]); + computedConstants[109] = pow(constants[0] <= constants[1], pow(constants[2], constants[3])); + computedConstants[110] = pow(constants[0] <= constants[1], pow(constants[2], 1.0/constants[3])); + computedConstants[111] = sqrt(constants[0]); + computedConstants[112] = sqrt(constants[0]); + computedConstants[113] = pow(constants[0], 1.0/0.5); + computedConstants[114] = pow(constants[0], 1.0/3.0); + computedConstants[115] = pow(constants[0], 1.0/constants[1]); + computedConstants[116] = pow(constants[0] < constants[1], 1.0/(constants[3] > constants[2])); + computedConstants[117] = pow(constants[0]+constants[1], 1.0/(constants[3] > constants[2])); + computedConstants[118] = pow(constants[0], 1.0/(constants[2] > constants[1])); + computedConstants[119] = pow(constants[0]-constants[1], 1.0/(constants[3] > constants[2])); + computedConstants[120] = pow(-constants[0], 1.0/(constants[2] > constants[1])); + computedConstants[121] = pow(constants[0]*constants[1], 1.0/(constants[3] > constants[2])); + computedConstants[122] = pow(constants[0]/constants[1], 1.0/(constants[3] > constants[2])); + computedConstants[123] = pow(constants[0] < constants[1], 1.0/(constants[2]+constants[3])); + computedConstants[124] = pow(constants[0] < constants[1], 1.0/constants[2]); + computedConstants[125] = pow(constants[0] < constants[1], 1.0/(constants[2]-constants[3])); + computedConstants[126] = pow(constants[0] < constants[1], 1.0/-constants[2]); + computedConstants[127] = pow(constants[0] < constants[1], 1.0/(constants[2]*constants[3])); + computedConstants[128] = pow(constants[0] < constants[1], 1.0/(constants[2]/constants[3])); + computedConstants[129] = pow(constants[0] < constants[1], 1.0/pow(constants[2], constants[3])); + computedConstants[130] = pow(constants[0] < constants[1], 1.0/pow(constants[2], 1.0/constants[3])); + computedConstants[131] = fabs(constants[0]); + computedConstants[132] = exp(constants[0]); + computedConstants[133] = log(constants[0]); + computedConstants[134] = log10(constants[0]); + computedConstants[135] = log(constants[0])/log(2.0); computedConstants[136] = log10(constants[0]); - computedConstants[137] = log(constants[0])/log(2.0); - computedConstants[138] = log10(constants[0]); - computedConstants[139] = log(constants[0])/log(constants[1]); - computedConstants[140] = ceil(constants[0]); - computedConstants[141] = floor(constants[0]); - computedConstants[142] = min(constants[0], constants[1]); - computedConstants[143] = min(constants[0], min(constants[1], constants[2])); - computedConstants[144] = max(constants[0], constants[1]); - computedConstants[145] = max(constants[0], max(constants[1], constants[2])); - computedConstants[146] = fmod(constants[0], constants[1]); - computedConstants[147] = sin(constants[0]); - computedConstants[148] = cos(constants[0]); - computedConstants[149] = tan(constants[0]); - computedConstants[150] = sec(constants[0]); - computedConstants[151] = csc(constants[0]); - computedConstants[152] = cot(constants[0]); - computedConstants[153] = sinh(constants[0]); - computedConstants[154] = cosh(constants[0]); - computedConstants[155] = tanh(constants[0]); - computedConstants[156] = sech(constants[0]); - computedConstants[157] = csch(constants[0]); - computedConstants[158] = coth(constants[0]); - computedConstants[159] = asin(constants[0]); - computedConstants[160] = acos(constants[0]); - computedConstants[161] = atan(constants[0]); - computedConstants[162] = asec(constants[0]); - computedConstants[163] = acsc(constants[0]); - computedConstants[164] = acot(constants[0]); - computedConstants[165] = asinh(constants[0]); - computedConstants[166] = acosh(constants[0]); - computedConstants[167] = atanh(constants[0]/2.0); - computedConstants[168] = asech(constants[0]); - computedConstants[169] = acsch(constants[0]); - computedConstants[170] = acoth(2.0*constants[0]); - computedConstants[171] = (constants[0] > constants[1])?constants[0]:NAN; - computedConstants[172] = (constants[0] > constants[1])?constants[0]:constants[2]; - computedConstants[173] = (constants[0] > constants[1])?constants[0]:(constants[2] > constants[3])?constants[2]:(constants[4] > constants[5])?constants[4]:NAN; - computedConstants[174] = (constants[0] > constants[1])?constants[0]:(constants[2] > constants[3])?constants[2]:(constants[4] > constants[5])?constants[4]:constants[6]; - computedConstants[175] = 123.0+((constants[0] > constants[1])?constants[0]:NAN); - computedConstants[180] = constants[0]; - computedConstants[187] = (constants[0] && constants[1])+((constants[2] > constants[3])?constants[1]:NAN)+constants[4]+(constants[5] && constants[6]); - computedConstants[188] = (constants[0] && constants[1])-(((constants[2] > constants[3])?constants[1]:NAN)-(constants[4]-((constants[2] > constants[3])?constants[1]:NAN)))-(constants[5] && constants[6]); - computedConstants[189] = (constants[0] && constants[1])*((constants[2] > constants[3])?constants[1]:NAN)*constants[4]*((constants[2] > constants[3])?constants[1]:NAN)*(constants[5] && constants[6]); - computedConstants[190] = (constants[0] && constants[1])/(((constants[2] > constants[3])?constants[1]:NAN)/(constants[4]/((constants[2] > constants[3])?constants[1]:NAN))); - computedConstants[191] = (constants[0] || constants[1]) && xor(constants[0], constants[1]) && ((constants[2] > constants[3])?constants[1]:NAN) && constants[4] && ((constants[2] > constants[3])?constants[1]:NAN) && xor(constants[0], constants[1]) && (constants[0] || constants[1]); - computedConstants[192] = (constants[0] && constants[1]) || xor(constants[0], constants[1]) || ((constants[2] > constants[3])?constants[1]:NAN) || constants[4] || ((constants[2] > constants[3])?constants[1]:NAN) || xor(constants[0], constants[1]) || (constants[0] && constants[1]); - computedConstants[193] = xor(constants[0] && constants[1], xor(constants[0] || constants[1], xor((constants[2] > constants[3])?constants[1]:NAN, xor(xor(xor(constants[4], (constants[2] > constants[3])?constants[1]:NAN), constants[0] || constants[1]), constants[0] && constants[1])))); - computedConstants[194] = pow(constants[0] && constants[1], pow((constants[2] > constants[3])?constants[1]:NAN, pow(pow(constants[4], (constants[2] > constants[3])?constants[1]:NAN), constants[0] && constants[1]))); - computedConstants[195] = pow(pow(pow(constants[0] && constants[1], 1.0/pow((constants[2] > constants[3])?constants[1]:NAN, 1.0/constants[4])), 1.0/((constants[2] > constants[3])?constants[1]:NAN)), 1.0/(constants[0] && constants[1])); - computedConstants[196] = -(constants[0] && constants[1])+-((constants[2] > constants[3])?constants[1]:NAN); + computedConstants[137] = log(constants[0])/log(constants[1]); + computedConstants[138] = ceil(constants[0]); + computedConstants[139] = floor(constants[0]); + computedConstants[140] = fmin(constants[0], constants[1]); + computedConstants[141] = fmin(constants[0], fmin(constants[1], constants[2])); + computedConstants[142] = fmax(constants[0], constants[1]); + computedConstants[143] = fmax(constants[0], fmax(constants[1], constants[2])); + computedConstants[144] = fmod(constants[0], constants[1]); + computedConstants[145] = sin(constants[0]); + computedConstants[146] = cos(constants[0]); + computedConstants[147] = tan(constants[0]); + computedConstants[148] = sec(constants[0]); + computedConstants[149] = csc(constants[0]); + computedConstants[150] = cot(constants[0]); + computedConstants[151] = sinh(constants[0]); + computedConstants[152] = cosh(constants[0]); + computedConstants[153] = tanh(constants[0]); + computedConstants[154] = sech(constants[0]); + computedConstants[155] = csch(constants[0]); + computedConstants[156] = coth(constants[0]); + computedConstants[157] = asin(constants[0]); + computedConstants[158] = acos(constants[0]); + computedConstants[159] = atan(constants[0]); + computedConstants[160] = asec(constants[0]); + computedConstants[161] = acsc(constants[0]); + computedConstants[162] = acot(constants[0]); + computedConstants[163] = asinh(constants[0]); + computedConstants[164] = acosh(constants[0]); + computedConstants[165] = atanh(constants[0]/2.0); + computedConstants[166] = asech(constants[0]); + computedConstants[167] = acsch(constants[0]); + computedConstants[168] = acoth(2.0*constants[0]); + computedConstants[170] = (constants[0] > constants[1])?constants[0]:NAN; + computedConstants[171] = (constants[0] < constants[1])?constants[0]:NAN; + computedConstants[172] = constants[0]; + computedConstants[173] = (constants[0] > constants[1])?constants[0]:constants[2]; + computedConstants[174] = (constants[0] > constants[1])?constants[0]:(constants[2] > constants[3])?constants[2]:(constants[4] > constants[5])?constants[4]:NAN; + computedConstants[175] = (constants[0] < constants[1])?constants[0]:(constants[2] > constants[3])?constants[2]:(constants[4] > constants[5])?constants[4]:NAN; + computedConstants[176] = (constants[0] > constants[1])?constants[0]:(constants[2] > constants[3])?constants[2]:(constants[4] > constants[5])?constants[4]:constants[6]; + computedConstants[177] = 123.0+((constants[0] > constants[1])?constants[0]:NAN); + computedConstants[178] = 123.0+((constants[0] < constants[1])?constants[0]:NAN); + computedConstants[183] = constants[0]; + computedConstants[190] = (constants[0] && constants[1])+((constants[2] > constants[3])?constants[1]:NAN)+constants[4]+(constants[5] && constants[6]); + computedConstants[191] = (constants[0] && constants[1])+((constants[2] < constants[3])?constants[1]:NAN)+constants[4]+(constants[5] && constants[6]); + computedConstants[192] = (constants[0] && constants[1])-(((constants[2] > constants[3])?constants[1]:NAN)-(constants[4]-((constants[2] > constants[3])?constants[1]:NAN)))-(constants[5] && constants[6]); + computedConstants[193] = (constants[0] && constants[1])-(((constants[2] < constants[3])?constants[1]:NAN)-(constants[4]-((constants[2] < constants[3])?constants[1]:NAN)))-(constants[5] && constants[6]); + computedConstants[194] = (constants[0] && constants[1])*((constants[2] > constants[3])?constants[1]:NAN)*constants[4]*((constants[2] > constants[3])?constants[1]:NAN)*(constants[5] && constants[6]); + computedConstants[195] = (constants[0] && constants[1])*((constants[2] < constants[3])?constants[1]:NAN)*constants[4]*((constants[2] < constants[3])?constants[1]:NAN)*(constants[5] && constants[6]); + computedConstants[196] = (constants[0] && constants[1])/(((constants[2] > constants[3])?constants[1]:NAN)/(constants[4]/((constants[2] > constants[3])?constants[1]:NAN))); + computedConstants[197] = (constants[0] && constants[1])/(((constants[2] < constants[3])?constants[1]:NAN)/(constants[4]/((constants[2] < constants[3])?constants[1]:NAN))); + computedConstants[198] = (constants[0] || constants[1]) && XOR(constants[0], constants[1]) && ((constants[2] > constants[3])?constants[1]:NAN) && constants[4] && ((constants[2] > constants[3])?constants[1]:NAN) && XOR(constants[0], constants[1]) && (constants[0] || constants[1]); + computedConstants[199] = (constants[0] && constants[1]) || XOR(constants[0], constants[1]) || ((constants[2] > constants[3])?constants[1]:NAN) || constants[4] || ((constants[2] > constants[3])?constants[1]:NAN) || XOR(constants[0], constants[1]) || (constants[0] && constants[1]); + computedConstants[200] = XOR(constants[0] && constants[1], XOR(constants[0] || constants[1], XOR((constants[2] > constants[3])?constants[1]:NAN, XOR(XOR(XOR(constants[4], (constants[2] > constants[3])?constants[1]:NAN), constants[0] || constants[1]), constants[0] && constants[1])))); + computedConstants[201] = pow(constants[0] && constants[1], pow((constants[2] > constants[3])?constants[1]:NAN, pow(pow(constants[4], (constants[2] > constants[3])?constants[1]:NAN), constants[0] && constants[1]))); + computedConstants[202] = pow(pow(pow(constants[0] && constants[1], 1.0/pow((constants[2] > constants[3])?constants[1]:NAN, 1.0/constants[4])), 1.0/((constants[2] > constants[3])?constants[1]:NAN)), 1.0/(constants[0] && constants[1])); + computedConstants[203] = -(constants[0] && constants[1])+-((constants[2] > constants[3])?constants[1]:NAN); + computedConstants[204] = -(constants[0] && constants[1])+-((constants[2] < constants[3])?constants[1]:NAN); } void computeRates(double voi, double *states, double *rates, double *constants, double *computedConstants, double *algebraic, double *externals, ExternalVariable externalVariable) @@ -650,6 +653,9 @@ void computeRates(double voi, double *states, double *rates, double *constants, void computeVariables(double voi, double *states, double *rates, double *constants, double *computedConstants, double *algebraic, double *externals, ExternalVariable externalVariable) { + algebraic[0] = states[0] || states[0]; + algebraic[1] = states[0] || states[0] || constants[0]; + algebraic[2] = constants[0]/XOR(constants[1], states[0]); externals[0] = externalVariable(voi, states, rates, constants, computedConstants, algebraic, externals, 0); findRoot0(voi, states, rates, constants, computedConstants, algebraic, externals); } diff --git a/tests/resources/coverage/generator/model.modified.profile.h b/tests/resources/coverage/generator/model.xor.h similarity index 98% rename from tests/resources/coverage/generator/model.modified.profile.h rename to tests/resources/coverage/generator/model.xor.h index 882fbaead8..93d1cdae9d 100644 --- a/tests/resources/coverage/generator/model.modified.profile.h +++ b/tests/resources/coverage/generator/model.xor.h @@ -26,7 +26,7 @@ extern const VariableInfo COMPUTED_CONSTANT_INFO[]; extern const VariableInfo ALGEBRAIC_INFO[]; extern const VariableInfo EXTERNAL_INFO[]; -double * createStatesVector(); +double * createStatesArray(); double * createConstantsArray(); double * createComputedConstantsArray(); double * createAlgebraicArray(); diff --git a/tests/resources/coverage/generator/model.modified.profile.py b/tests/resources/coverage/generator/model.xor.py similarity index 71% rename from tests/resources/coverage/generator/model.modified.profile.py rename to tests/resources/coverage/generator/model.xor.py index 8462eba392..8fc5da945f 100644 --- a/tests/resources/coverage/generator/model.modified.profile.py +++ b/tests/resources/coverage/generator/model.xor.py @@ -9,8 +9,8 @@ STATE_COUNT = 1 CONSTANT_COUNT = 7 -COMPUTED_CONSTANT_COUNT = 199 -ALGEBRAIC_COUNT = 2 +COMPUTED_CONSTANT_COUNT = 207 +ALGEBRAIC_COUNT = 5 EXTERNAL_COUNT = 1 VOI_INFO = {"name": "t", "units": "second", "component": "my_component"} @@ -58,8 +58,6 @@ {"name": "eqnAndParenthesesRightPower", "units": "dimensionless", "component": "my_component"}, {"name": "eqnAndParenthesesRightRoot", "units": "dimensionless", "component": "my_component"}, {"name": "eqnAndCoverageParentheses", "units": "dimensionless", "component": "my_component"}, - {"name": "eqnOr", "units": "dimensionless", "component": "my_component"}, - {"name": "eqnOrMultiple", "units": "dimensionless", "component": "my_component"}, {"name": "eqnOrParentheses", "units": "dimensionless", "component": "my_component"}, {"name": "eqnOrParenthesesLeftPlusWith", "units": "dimensionless", "component": "my_component"}, {"name": "eqnOrParenthesesLeftPlusWithout", "units": "dimensionless", "component": "my_component"}, @@ -89,7 +87,6 @@ {"name": "eqnXorParenthesesRightMinusWithout", "units": "dimensionless", "component": "my_component"}, {"name": "eqnXorParenthesesRightPower", "units": "dimensionless", "component": "my_component"}, {"name": "eqnXorParenthesesRightRoot", "units": "dimensionless", "component": "my_component"}, - {"name": "eqnXorCoverageParentheses", "units": "dimensionless", "component": "my_component"}, {"name": "eqnNot", "units": "dimensionless", "component": "my_component"}, {"name": "eqnPlusMultiple", "units": "dimensionless", "component": "my_component"}, {"name": "eqnPlusParentheses", "units": "dimensionless", "component": "my_component"}, @@ -146,6 +143,7 @@ {"name": "eqnPowerParenthesesRightRoot", "units": "dimensionless", "component": "my_component"}, {"name": "eqnRootSqrt", "units": "dimensionless", "component": "my_component"}, {"name": "eqnRootSqrtOther", "units": "dimensionless", "component": "my_component"}, + {"name": "eqnRootSqr", "units": "dimensionless", "component": "my_component"}, {"name": "eqnRootCube", "units": "dimensionless", "component": "my_component"}, {"name": "eqnRootCi", "units": "dimensionless", "component": "my_component"}, {"name": "eqnRootParentheses", "units": "dimensionless", "component": "my_component"}, @@ -201,11 +199,16 @@ {"name": "eqnArcsech", "units": "dimensionless", "component": "my_component"}, {"name": "eqnArccsch", "units": "dimensionless", "component": "my_component"}, {"name": "eqnArccoth", "units": "dimensionless", "component": "my_component"}, + {"name": "eqnPiecewise", "units": "dimensionless", "component": "my_component"}, {"name": "eqnPiecewisePiece", "units": "dimensionless", "component": "my_component"}, + {"name": "eqnPiecewisePiece2", "units": "dimensionless", "component": "my_component"}, + {"name": "eqnPiecewiseOtherwise", "units": "dimensionless", "component": "my_component"}, {"name": "eqnPiecewisePieceOtherwise", "units": "dimensionless", "component": "my_component"}, {"name": "eqnPiecewisePiecePiecePiece", "units": "dimensionless", "component": "my_component"}, + {"name": "eqnPiecewisePiecePiecePiece2", "units": "dimensionless", "component": "my_component"}, {"name": "eqnPiecewisePiecePiecePieceOtherwise", "units": "dimensionless", "component": "my_component"}, {"name": "eqnWithPiecewise", "units": "dimensionless", "component": "my_component"}, + {"name": "eqnWithPiecewise2", "units": "dimensionless", "component": "my_component"}, {"name": "eqnCnInteger", "units": "dimensionless", "component": "my_component"}, {"name": "eqnCnDouble", "units": "dimensionless", "component": "my_component"}, {"name": "eqnCnIntegerWithExponent", "units": "dimensionless", "component": "my_component"}, @@ -218,20 +221,28 @@ {"name": "eqnInfinity", "units": "dimensionless", "component": "my_component"}, {"name": "eqnNotanumber", "units": "dimensionless", "component": "my_component"}, {"name": "eqnCoverageForPlusOperator", "units": "dimensionless", "component": "my_component"}, + {"name": "eqnCoverageForPlusOperator2", "units": "dimensionless", "component": "my_component"}, {"name": "eqnCoverageForMinusOperator", "units": "dimensionless", "component": "my_component"}, + {"name": "eqnCoverageForMinusOperator2", "units": "dimensionless", "component": "my_component"}, {"name": "eqnCoverageForTimesOperator", "units": "dimensionless", "component": "my_component"}, + {"name": "eqnCoverageForTimesOperator2", "units": "dimensionless", "component": "my_component"}, {"name": "eqnCoverageForDivideOperator", "units": "dimensionless", "component": "my_component"}, + {"name": "eqnCoverageForDivideOperator2", "units": "dimensionless", "component": "my_component"}, {"name": "eqnCoverageForAndOperator", "units": "dimensionless", "component": "my_component"}, {"name": "eqnCoverageForOrOperator", "units": "dimensionless", "component": "my_component"}, {"name": "eqnCoverageForXorOperator", "units": "dimensionless", "component": "my_component"}, {"name": "eqnCoverageForPowerOperator", "units": "dimensionless", "component": "my_component"}, {"name": "eqnCoverageForRootOperator", "units": "dimensionless", "component": "my_component"}, {"name": "eqnCoverageForMinusUnary", "units": "dimensionless", "component": "my_component"}, + {"name": "eqnCoverageForMinusUnary2", "units": "dimensionless", "component": "my_component"}, {"name": "eqnComputedConstant1", "units": "dimensionless", "component": "my_component"}, {"name": "eqnComputedConstant2", "units": "dimensionless", "component": "my_component"} ] ALGEBRAIC_INFO = [ + {"name": "eqnOr", "units": "dimensionless", "component": "my_component"}, + {"name": "eqnOrMultiple", "units": "dimensionless", "component": "my_component"}, + {"name": "eqnXorCoverageParentheses", "units": "dimensionless", "component": "my_component"}, {"name": "eqnNlaVariable1", "units": "dimensionless", "component": "my_component"}, {"name": "eqnNlaVariable2", "units": "dimensionless", "component": "my_component"} ] @@ -273,7 +284,7 @@ def or_func(x, y): return 1.0 if bool(x) | bool(y) else 0.0 -def xor_func(x, y): +def XOR_FUNC(x, y): return 1.0 if bool(x) ^ bool(y) else 0.0 @@ -326,24 +337,18 @@ def acot(x): def asech(x): - one_over_x = 1.0/x - - return log(one_over_x+sqrt(one_over_x*one_over_x-1.0)) + return acosh(1.0/x) def acsch(x): - one_over_x = 1.0/x - - return log(one_over_x+sqrt(one_over_x*one_over_x+1.0)) + return asinh(1.0/x) def acoth(x): - one_over_x = 1.0/x - - return 0.5*log((1.0+one_over_x)/(1.0-one_over_x)) + return atanh(1.0/x) -def create_states_vector(): +def create_states_array(): return [nan]*STATE_COUNT @@ -375,23 +380,23 @@ def objective_function_0(u, f, data): algebraic = data[5] externals = data[6] - algebraic[0] = u[0] - algebraic[1] = u[1] + algebraic[3] = u[0] + algebraic[4] = u[1] - f[0] = algebraic[0]+algebraic[1]+states[0]-0.0 - f[1] = algebraic[0]-algebraic[1]-(computed_constants[197]+computed_constants[198]) + f[0] = algebraic[3]+algebraic[4]+states[0]-0.0 + f[1] = algebraic[3]-algebraic[4]-(computed_constants[205]+computed_constants[206]) def find_root_0(voi, states, rates, constants, computed_constants, algebraic, externals): u = [nan]*2 - u[0] = algebraic[0] - u[1] = algebraic[1] + u[0] = algebraic[3] + u[1] = algebraic[4] u = nla_solve(objective_function_0, u, 2, [voi, states, rates, constants, computed_constants, algebraic, externals]) - algebraic[0] = u[0] - algebraic[1] = u[1] + algebraic[3] = u[0] + algebraic[4] = u[1] def initialise_variables(states, rates, constants, computed_constants, algebraic): @@ -403,20 +408,21 @@ def initialise_variables(states, rates, constants, computed_constants, algebraic constants[4] = 5.0 constants[5] = 6.0 constants[6] = 7.0 - computed_constants[176] = 123.0 - computed_constants[177] = 123.456789 - computed_constants[178] = 123.0e99 - computed_constants[179] = 123.456789e99 - computed_constants[181] = 1.0 - computed_constants[182] = 0.0 - computed_constants[183] = 2.71828182845905 - computed_constants[184] = 3.14159265358979 - computed_constants[185] = inf - computed_constants[186] = nan - computed_constants[197] = 1.0 - computed_constants[198] = 3.0 - algebraic[0] = 1.0 - algebraic[1] = 2.0 + computed_constants[169] = nan + computed_constants[179] = 123.0 + computed_constants[180] = 123.456789 + computed_constants[181] = 123.0e99 + computed_constants[182] = 123.456789e99 + computed_constants[184] = 1.0 + computed_constants[185] = 0.0 + computed_constants[186] = 2.71828182845905 + computed_constants[187] = 3.14159265358979 + computed_constants[188] = inf + computed_constants[189] = nan + computed_constants[205] = 1.0 + computed_constants[206] = 3.0 + algebraic[3] = 1.0 + algebraic[4] = 2.0 def compute_computed_constants(constants, computed_constants): @@ -429,9 +435,9 @@ def compute_computed_constants(constants, computed_constants): computed_constants[6] = leq_func(constants[0], constants[1]) computed_constants[7] = constants[0]/leq_func(constants[1], constants[2]) computed_constants[8] = gt_func(constants[0], constants[1]) - computed_constants[9] = constants[0]/gt_func(constants[1], constants[2]) + computed_constants[9] = constants[0]/gt_func(constants[2], constants[1]) computed_constants[10] = geq_func(constants[0], constants[1]) - computed_constants[11] = constants[0]/geq_func(constants[1], constants[2]) + computed_constants[11] = constants[0]/geq_func(constants[2], constants[1]) computed_constants[12] = and_func(constants[0], constants[1]) computed_constants[13] = and_func(constants[0], and_func(constants[1], constants[2])) computed_constants[14] = and_func(lt_func(constants[0], constants[1]), gt_func(constants[2], constants[3])) @@ -448,165 +454,172 @@ def compute_computed_constants(constants, computed_constants): computed_constants[25] = and_func(lt_func(constants[0], constants[1]), pow(constants[2], constants[3])) computed_constants[26] = and_func(lt_func(constants[0], constants[1]), pow(constants[2], 1.0/constants[3])) computed_constants[27] = constants[0]/and_func(constants[1], constants[2]) - computed_constants[28] = or_func(constants[0], constants[1]) - computed_constants[29] = or_func(constants[0], or_func(constants[1], constants[2])) - computed_constants[30] = or_func(lt_func(constants[0], constants[1]), gt_func(constants[2], constants[3])) - computed_constants[31] = or_func(constants[0]+constants[1], gt_func(constants[2], constants[3])) - computed_constants[32] = or_func(constants[0], gt_func(constants[1], constants[2])) - computed_constants[33] = or_func(constants[0]-constants[1], gt_func(constants[2], constants[3])) - computed_constants[34] = or_func(-constants[0], gt_func(constants[1], constants[2])) - computed_constants[35] = or_func(pow(constants[0], constants[1]), gt_func(constants[2], constants[3])) - computed_constants[36] = or_func(pow(constants[0], 1.0/constants[1]), gt_func(constants[2], constants[3])) - computed_constants[37] = or_func(lt_func(constants[0], constants[1]), constants[2]+constants[3]) - computed_constants[38] = or_func(lt_func(constants[0], constants[1]), constants[2]) - computed_constants[39] = or_func(lt_func(constants[0], constants[1]), constants[2]-constants[3]) - computed_constants[40] = or_func(lt_func(constants[0], constants[1]), -constants[2]) - computed_constants[41] = or_func(lt_func(constants[0], constants[1]), pow(constants[2], constants[3])) - computed_constants[42] = or_func(lt_func(constants[0], constants[1]), pow(constants[2], 1.0/constants[3])) - computed_constants[43] = constants[0]/or_func(constants[1], constants[2]) - computed_constants[44] = xor_func(constants[0], constants[1]) - computed_constants[45] = xor_func(constants[0], xor_func(constants[1], constants[2])) - computed_constants[46] = xor_func(lt_func(constants[0], constants[1]), gt_func(constants[2], constants[3])) - computed_constants[47] = xor_func(constants[0]+constants[1], gt_func(constants[2], constants[3])) - computed_constants[48] = xor_func(constants[0], gt_func(constants[1], constants[2])) - computed_constants[49] = xor_func(constants[0]-constants[1], gt_func(constants[2], constants[3])) - computed_constants[50] = xor_func(-constants[0], gt_func(constants[1], constants[2])) - computed_constants[51] = xor_func(pow(constants[0], constants[1]), gt_func(constants[2], constants[3])) - computed_constants[52] = xor_func(pow(constants[0], 1.0/constants[1]), gt_func(constants[2], constants[3])) - computed_constants[53] = xor_func(lt_func(constants[0], constants[1]), constants[2]+constants[3]) - computed_constants[54] = xor_func(lt_func(constants[0], constants[1]), constants[2]) - computed_constants[55] = xor_func(lt_func(constants[0], constants[1]), constants[2]-constants[3]) - computed_constants[56] = xor_func(lt_func(constants[0], constants[1]), -constants[2]) - computed_constants[57] = xor_func(lt_func(constants[0], constants[1]), pow(constants[2], constants[3])) - computed_constants[58] = xor_func(lt_func(constants[0], constants[1]), pow(constants[2], 1.0/constants[3])) - computed_constants[59] = constants[0]/xor_func(constants[1], constants[2]) - computed_constants[60] = not_func(constants[0]) - computed_constants[61] = constants[0]+constants[1]+constants[2] - computed_constants[62] = lt_func(constants[0], constants[1])+gt_func(constants[2], constants[3]) - computed_constants[63] = constants[0] - computed_constants[64] = constants[0]-constants[1] - computed_constants[65] = lt_func(constants[0], constants[1])-gt_func(constants[2], constants[3]) - computed_constants[66] = lt_func(constants[0], constants[1])-(constants[2]+constants[3]) - computed_constants[67] = lt_func(constants[0], constants[1])-constants[2] - computed_constants[68] = constants[0]-(-constants[1]) - computed_constants[69] = constants[0]-(-constants[1]*constants[2]) - computed_constants[70] = -constants[0] - computed_constants[71] = -lt_func(constants[0], constants[1]) - computed_constants[72] = constants[0]*constants[1] - computed_constants[73] = constants[0]*constants[1]*constants[2] - computed_constants[74] = lt_func(constants[0], constants[1])*gt_func(constants[2], constants[3]) - computed_constants[75] = (constants[0]+constants[1])*gt_func(constants[2], constants[3]) - computed_constants[76] = constants[0]*gt_func(constants[1], constants[2]) - computed_constants[77] = (constants[0]-constants[1])*gt_func(constants[2], constants[3]) - computed_constants[78] = -constants[0]*gt_func(constants[1], constants[2]) - computed_constants[79] = lt_func(constants[0], constants[1])*(constants[2]+constants[3]) - computed_constants[80] = lt_func(constants[0], constants[1])*constants[2] - computed_constants[81] = lt_func(constants[0], constants[1])*(constants[2]-constants[3]) - computed_constants[82] = lt_func(constants[0], constants[1])*-constants[2] - computed_constants[83] = constants[0]/constants[1] - computed_constants[84] = lt_func(constants[0], constants[1])/gt_func(constants[3], constants[2]) - computed_constants[85] = (constants[0]+constants[1])/gt_func(constants[3], constants[2]) - computed_constants[86] = constants[0]/gt_func(constants[2], constants[1]) - computed_constants[87] = (constants[0]-constants[1])/gt_func(constants[3], constants[2]) - computed_constants[88] = -constants[0]/gt_func(constants[2], constants[1]) - computed_constants[89] = lt_func(constants[0], constants[1])/(constants[2]+constants[3]) - computed_constants[90] = lt_func(constants[0], constants[1])/constants[2] - computed_constants[91] = lt_func(constants[0], constants[1])/(constants[2]-constants[3]) - computed_constants[92] = lt_func(constants[0], constants[1])/-constants[2] - computed_constants[93] = lt_func(constants[0], constants[1])/(constants[2]*constants[3]) - computed_constants[94] = lt_func(constants[0], constants[1])/(constants[2]/constants[3]) - computed_constants[95] = sqrt(constants[0]) - computed_constants[96] = pow(constants[0], 2.0) - computed_constants[97] = pow(constants[0], 3.0) - computed_constants[98] = pow(constants[0], constants[1]) - computed_constants[99] = pow(leq_func(constants[0], constants[1]), geq_func(constants[2], constants[3])) - computed_constants[100] = pow(constants[0]+constants[1], geq_func(constants[2], constants[3])) - computed_constants[101] = pow(constants[0], geq_func(constants[1], constants[2])) - computed_constants[102] = pow(constants[0]-constants[1], geq_func(constants[2], constants[3])) - computed_constants[103] = pow(-constants[0], geq_func(constants[1], constants[2])) - computed_constants[104] = pow(constants[0]*constants[1], geq_func(constants[2], constants[3])) - computed_constants[105] = pow(constants[0]/constants[1], geq_func(constants[2], constants[3])) - computed_constants[106] = pow(leq_func(constants[0], constants[1]), constants[2]+constants[3]) - computed_constants[107] = pow(leq_func(constants[0], constants[1]), constants[2]) - computed_constants[108] = pow(leq_func(constants[0], constants[1]), constants[2]-constants[3]) - computed_constants[109] = pow(leq_func(constants[0], constants[1]), -constants[2]) - computed_constants[110] = pow(leq_func(constants[0], constants[1]), constants[2]*constants[3]) - computed_constants[111] = pow(leq_func(constants[0], constants[1]), constants[2]/constants[3]) - computed_constants[112] = pow(leq_func(constants[0], constants[1]), pow(constants[2], constants[3])) - computed_constants[113] = pow(leq_func(constants[0], constants[1]), pow(constants[2], 1.0/constants[3])) - computed_constants[114] = sqrt(constants[0]) - computed_constants[115] = sqrt(constants[0]) - computed_constants[116] = pow(constants[0], 1.0/3.0) - computed_constants[117] = pow(constants[0], 1.0/constants[1]) - computed_constants[118] = pow(lt_func(constants[0], constants[1]), 1.0/gt_func(constants[3], constants[2])) - computed_constants[119] = pow(constants[0]+constants[1], 1.0/gt_func(constants[3], constants[2])) - computed_constants[120] = pow(constants[0], 1.0/gt_func(constants[2], constants[1])) - computed_constants[121] = pow(constants[0]-constants[1], 1.0/gt_func(constants[3], constants[2])) - computed_constants[122] = pow(-constants[0], 1.0/gt_func(constants[2], constants[1])) - computed_constants[123] = pow(constants[0]*constants[1], 1.0/gt_func(constants[3], constants[2])) - computed_constants[124] = pow(constants[0]/constants[1], 1.0/gt_func(constants[3], constants[2])) - computed_constants[125] = pow(lt_func(constants[0], constants[1]), 1.0/(constants[2]+constants[3])) - computed_constants[126] = pow(lt_func(constants[0], constants[1]), 1.0/constants[2]) - computed_constants[127] = pow(lt_func(constants[0], constants[1]), 1.0/(constants[2]-constants[3])) - computed_constants[128] = pow(lt_func(constants[0], constants[1]), 1.0/-constants[2]) - computed_constants[129] = pow(lt_func(constants[0], constants[1]), 1.0/(constants[2]*constants[3])) - computed_constants[130] = pow(lt_func(constants[0], constants[1]), 1.0/(constants[2]/constants[3])) - computed_constants[131] = pow(lt_func(constants[0], constants[1]), 1.0/pow(constants[2], constants[3])) - computed_constants[132] = pow(lt_func(constants[0], constants[1]), 1.0/pow(constants[2], 1.0/constants[3])) - computed_constants[133] = fabs(constants[0]) - computed_constants[134] = exp(constants[0]) - computed_constants[135] = log(constants[0]) + computed_constants[28] = or_func(lt_func(constants[0], constants[1]), gt_func(constants[2], constants[3])) + computed_constants[29] = or_func(constants[0]+constants[1], gt_func(constants[2], constants[3])) + computed_constants[30] = or_func(constants[0], gt_func(constants[1], constants[2])) + computed_constants[31] = or_func(constants[0]-constants[1], gt_func(constants[2], constants[3])) + computed_constants[32] = or_func(-constants[0], gt_func(constants[1], constants[2])) + computed_constants[33] = or_func(pow(constants[0], constants[1]), gt_func(constants[2], constants[3])) + computed_constants[34] = or_func(pow(constants[0], 1.0/constants[1]), gt_func(constants[2], constants[3])) + computed_constants[35] = or_func(lt_func(constants[0], constants[1]), constants[2]+constants[3]) + computed_constants[36] = or_func(lt_func(constants[0], constants[1]), constants[2]) + computed_constants[37] = or_func(lt_func(constants[0], constants[1]), constants[2]-constants[3]) + computed_constants[38] = or_func(lt_func(constants[0], constants[1]), -constants[2]) + computed_constants[39] = or_func(lt_func(constants[0], constants[1]), pow(constants[2], constants[3])) + computed_constants[40] = or_func(lt_func(constants[0], constants[1]), pow(constants[2], 1.0/constants[3])) + computed_constants[41] = constants[0]/or_func(constants[1], constants[2]) + computed_constants[42] = XOR_FUNC(constants[0], constants[1]) + computed_constants[43] = XOR_FUNC(constants[0], XOR_FUNC(constants[1], constants[2])) + computed_constants[44] = XOR_FUNC(lt_func(constants[0], constants[1]), gt_func(constants[2], constants[3])) + computed_constants[45] = XOR_FUNC(constants[0]+constants[1], gt_func(constants[2], constants[3])) + computed_constants[46] = XOR_FUNC(constants[0], gt_func(constants[1], constants[2])) + computed_constants[47] = XOR_FUNC(constants[0]-constants[1], gt_func(constants[2], constants[3])) + computed_constants[48] = XOR_FUNC(-constants[0], gt_func(constants[1], constants[2])) + computed_constants[49] = XOR_FUNC(pow(constants[0], constants[1]), gt_func(constants[2], constants[3])) + computed_constants[50] = XOR_FUNC(pow(constants[0], 1.0/constants[1]), gt_func(constants[2], constants[3])) + computed_constants[51] = XOR_FUNC(lt_func(constants[0], constants[1]), constants[2]+constants[3]) + computed_constants[52] = XOR_FUNC(lt_func(constants[0], constants[1]), constants[2]) + computed_constants[53] = XOR_FUNC(lt_func(constants[0], constants[1]), constants[2]-constants[3]) + computed_constants[54] = XOR_FUNC(lt_func(constants[0], constants[1]), -constants[2]) + computed_constants[55] = XOR_FUNC(lt_func(constants[0], constants[1]), pow(constants[2], constants[3])) + computed_constants[56] = XOR_FUNC(lt_func(constants[0], constants[1]), pow(constants[2], 1.0/constants[3])) + computed_constants[57] = not_func(constants[0]) + computed_constants[58] = constants[0]+constants[1]+constants[2] + computed_constants[59] = lt_func(constants[0], constants[1])+gt_func(constants[2], constants[3]) + computed_constants[60] = constants[0] + computed_constants[61] = constants[0]-constants[1] + computed_constants[62] = lt_func(constants[0], constants[1])-gt_func(constants[2], constants[3]) + computed_constants[63] = lt_func(constants[0], constants[1])-(constants[2]+constants[3]) + computed_constants[64] = lt_func(constants[0], constants[1])-constants[2] + computed_constants[65] = constants[0]-(-constants[1]) + computed_constants[66] = constants[0]-(-constants[1]*constants[2]) + computed_constants[67] = -constants[0] + computed_constants[68] = -lt_func(constants[0], constants[1]) + computed_constants[69] = constants[0]*constants[1] + computed_constants[70] = constants[0]*constants[1]*constants[2] + computed_constants[71] = lt_func(constants[0], constants[1])*gt_func(constants[2], constants[3]) + computed_constants[72] = (constants[0]+constants[1])*gt_func(constants[2], constants[3]) + computed_constants[73] = constants[0]*gt_func(constants[1], constants[2]) + computed_constants[74] = (constants[0]-constants[1])*gt_func(constants[2], constants[3]) + computed_constants[75] = -constants[0]*gt_func(constants[1], constants[2]) + computed_constants[76] = lt_func(constants[0], constants[1])*(constants[2]+constants[3]) + computed_constants[77] = lt_func(constants[0], constants[1])*constants[2] + computed_constants[78] = lt_func(constants[0], constants[1])*(constants[2]-constants[3]) + computed_constants[79] = lt_func(constants[0], constants[1])*-constants[2] + computed_constants[80] = constants[0]/constants[1] + computed_constants[81] = lt_func(constants[0], constants[1])/gt_func(constants[3], constants[2]) + computed_constants[82] = (constants[0]+constants[1])/gt_func(constants[3], constants[2]) + computed_constants[83] = constants[0]/gt_func(constants[2], constants[1]) + computed_constants[84] = (constants[0]-constants[1])/gt_func(constants[3], constants[2]) + computed_constants[85] = -constants[0]/gt_func(constants[2], constants[1]) + computed_constants[86] = lt_func(constants[0], constants[1])/(constants[2]+constants[3]) + computed_constants[87] = lt_func(constants[0], constants[1])/constants[2] + computed_constants[88] = lt_func(constants[0], constants[1])/(constants[2]-constants[3]) + computed_constants[89] = lt_func(constants[0], constants[1])/-constants[2] + computed_constants[90] = lt_func(constants[0], constants[1])/(constants[2]*constants[3]) + computed_constants[91] = lt_func(constants[0], constants[1])/(constants[2]/constants[3]) + computed_constants[92] = sqrt(constants[0]) + computed_constants[93] = pow(constants[0], 2.0) + computed_constants[94] = pow(constants[0], 3.0) + computed_constants[95] = pow(constants[0], constants[1]) + computed_constants[96] = pow(leq_func(constants[0], constants[1]), geq_func(constants[2], constants[3])) + computed_constants[97] = pow(constants[0]+constants[1], geq_func(constants[2], constants[3])) + computed_constants[98] = pow(constants[0], geq_func(constants[1], constants[2])) + computed_constants[99] = pow(constants[0]-constants[1], geq_func(constants[2], constants[3])) + computed_constants[100] = pow(-constants[0], geq_func(constants[1], constants[2])) + computed_constants[101] = pow(constants[0]*constants[1], geq_func(constants[2], constants[3])) + computed_constants[102] = pow(constants[0]/constants[1], geq_func(constants[2], constants[3])) + computed_constants[103] = pow(leq_func(constants[0], constants[1]), constants[2]+constants[3]) + computed_constants[104] = pow(leq_func(constants[0], constants[1]), constants[2]) + computed_constants[105] = pow(leq_func(constants[0], constants[1]), constants[2]-constants[3]) + computed_constants[106] = pow(leq_func(constants[0], constants[1]), -constants[2]) + computed_constants[107] = pow(leq_func(constants[0], constants[1]), constants[2]*constants[3]) + computed_constants[108] = pow(leq_func(constants[0], constants[1]), constants[2]/constants[3]) + computed_constants[109] = pow(leq_func(constants[0], constants[1]), pow(constants[2], constants[3])) + computed_constants[110] = pow(leq_func(constants[0], constants[1]), pow(constants[2], 1.0/constants[3])) + computed_constants[111] = sqrt(constants[0]) + computed_constants[112] = sqrt(constants[0]) + computed_constants[113] = pow(constants[0], 1.0/0.5) + computed_constants[114] = pow(constants[0], 1.0/3.0) + computed_constants[115] = pow(constants[0], 1.0/constants[1]) + computed_constants[116] = pow(lt_func(constants[0], constants[1]), 1.0/gt_func(constants[3], constants[2])) + computed_constants[117] = pow(constants[0]+constants[1], 1.0/gt_func(constants[3], constants[2])) + computed_constants[118] = pow(constants[0], 1.0/gt_func(constants[2], constants[1])) + computed_constants[119] = pow(constants[0]-constants[1], 1.0/gt_func(constants[3], constants[2])) + computed_constants[120] = pow(-constants[0], 1.0/gt_func(constants[2], constants[1])) + computed_constants[121] = pow(constants[0]*constants[1], 1.0/gt_func(constants[3], constants[2])) + computed_constants[122] = pow(constants[0]/constants[1], 1.0/gt_func(constants[3], constants[2])) + computed_constants[123] = pow(lt_func(constants[0], constants[1]), 1.0/(constants[2]+constants[3])) + computed_constants[124] = pow(lt_func(constants[0], constants[1]), 1.0/constants[2]) + computed_constants[125] = pow(lt_func(constants[0], constants[1]), 1.0/(constants[2]-constants[3])) + computed_constants[126] = pow(lt_func(constants[0], constants[1]), 1.0/-constants[2]) + computed_constants[127] = pow(lt_func(constants[0], constants[1]), 1.0/(constants[2]*constants[3])) + computed_constants[128] = pow(lt_func(constants[0], constants[1]), 1.0/(constants[2]/constants[3])) + computed_constants[129] = pow(lt_func(constants[0], constants[1]), 1.0/pow(constants[2], constants[3])) + computed_constants[130] = pow(lt_func(constants[0], constants[1]), 1.0/pow(constants[2], 1.0/constants[3])) + computed_constants[131] = fabs(constants[0]) + computed_constants[132] = exp(constants[0]) + computed_constants[133] = log(constants[0]) + computed_constants[134] = log10(constants[0]) + computed_constants[135] = log(constants[0])/log(2.0) computed_constants[136] = log10(constants[0]) - computed_constants[137] = log(constants[0])/log(2.0) - computed_constants[138] = log10(constants[0]) - computed_constants[139] = log(constants[0])/log(constants[1]) - computed_constants[140] = ceil(constants[0]) - computed_constants[141] = floor(constants[0]) - computed_constants[142] = min(constants[0], constants[1]) - computed_constants[143] = min(constants[0], min(constants[1], constants[2])) - computed_constants[144] = max(constants[0], constants[1]) - computed_constants[145] = max(constants[0], max(constants[1], constants[2])) - computed_constants[146] = fmod(constants[0], constants[1]) - computed_constants[147] = sin(constants[0]) - computed_constants[148] = cos(constants[0]) - computed_constants[149] = tan(constants[0]) - computed_constants[150] = sec(constants[0]) - computed_constants[151] = csc(constants[0]) - computed_constants[152] = cot(constants[0]) - computed_constants[153] = sinh(constants[0]) - computed_constants[154] = cosh(constants[0]) - computed_constants[155] = tanh(constants[0]) - computed_constants[156] = sech(constants[0]) - computed_constants[157] = csch(constants[0]) - computed_constants[158] = coth(constants[0]) - computed_constants[159] = asin(constants[0]) - computed_constants[160] = acos(constants[0]) - computed_constants[161] = atan(constants[0]) - computed_constants[162] = asec(constants[0]) - computed_constants[163] = acsc(constants[0]) - computed_constants[164] = acot(constants[0]) - computed_constants[165] = asinh(constants[0]) - computed_constants[166] = acosh(constants[0]) - computed_constants[167] = atanh(constants[0]/2.0) - computed_constants[168] = asech(constants[0]) - computed_constants[169] = acsch(constants[0]) - computed_constants[170] = acoth(2.0*constants[0]) - computed_constants[171] = constants[0] if gt_func(constants[0], constants[1]) else nan - computed_constants[172] = constants[0] if gt_func(constants[0], constants[1]) else constants[2] - computed_constants[173] = constants[0] if gt_func(constants[0], constants[1]) else constants[2] if gt_func(constants[2], constants[3]) else constants[4] if gt_func(constants[4], constants[5]) else nan - computed_constants[174] = constants[0] if gt_func(constants[0], constants[1]) else constants[2] if gt_func(constants[2], constants[3]) else constants[4] if gt_func(constants[4], constants[5]) else constants[6] - computed_constants[175] = 123.0+(constants[0] if gt_func(constants[0], constants[1]) else nan) - computed_constants[180] = constants[0] - computed_constants[187] = and_func(constants[0], constants[1])+(constants[1] if gt_func(constants[2], constants[3]) else nan)+constants[4]+and_func(constants[5], constants[6]) - computed_constants[188] = and_func(constants[0], constants[1])-((constants[1] if gt_func(constants[2], constants[3]) else nan)-(constants[4]-(constants[1] if gt_func(constants[2], constants[3]) else nan)))-and_func(constants[5], constants[6]) - computed_constants[189] = and_func(constants[0], constants[1])*(constants[1] if gt_func(constants[2], constants[3]) else nan)*constants[4]*(constants[1] if gt_func(constants[2], constants[3]) else nan)*and_func(constants[5], constants[6]) - computed_constants[190] = and_func(constants[0], constants[1])/((constants[1] if gt_func(constants[2], constants[3]) else nan)/(constants[4]/(constants[1] if gt_func(constants[2], constants[3]) else nan))) - computed_constants[191] = and_func(or_func(constants[0], constants[1]), and_func(xor_func(constants[0], constants[1]), and_func(constants[1] if gt_func(constants[2], constants[3]) else nan, and_func(and_func(and_func(constants[4], constants[1] if gt_func(constants[2], constants[3]) else nan), xor_func(constants[0], constants[1])), or_func(constants[0], constants[1]))))) - computed_constants[192] = or_func(and_func(constants[0], constants[1]), or_func(xor_func(constants[0], constants[1]), or_func(constants[1] if gt_func(constants[2], constants[3]) else nan, or_func(or_func(or_func(constants[4], constants[1] if gt_func(constants[2], constants[3]) else nan), xor_func(constants[0], constants[1])), and_func(constants[0], constants[1]))))) - computed_constants[193] = xor_func(and_func(constants[0], constants[1]), xor_func(or_func(constants[0], constants[1]), xor_func(constants[1] if gt_func(constants[2], constants[3]) else nan, xor_func(xor_func(xor_func(constants[4], constants[1] if gt_func(constants[2], constants[3]) else nan), or_func(constants[0], constants[1])), and_func(constants[0], constants[1]))))) - computed_constants[194] = pow(and_func(constants[0], constants[1]), pow(constants[1] if gt_func(constants[2], constants[3]) else nan, pow(pow(constants[4], constants[1] if gt_func(constants[2], constants[3]) else nan), and_func(constants[0], constants[1])))) - computed_constants[195] = pow(pow(pow(and_func(constants[0], constants[1]), 1.0/pow(constants[1] if gt_func(constants[2], constants[3]) else nan, 1.0/constants[4])), 1.0/(constants[1] if gt_func(constants[2], constants[3]) else nan)), 1.0/and_func(constants[0], constants[1])) - computed_constants[196] = -and_func(constants[0], constants[1])+-(constants[1] if gt_func(constants[2], constants[3]) else nan) + computed_constants[137] = log(constants[0])/log(constants[1]) + computed_constants[138] = ceil(constants[0]) + computed_constants[139] = floor(constants[0]) + computed_constants[140] = min(constants[0], constants[1]) + computed_constants[141] = min(constants[0], min(constants[1], constants[2])) + computed_constants[142] = max(constants[0], constants[1]) + computed_constants[143] = max(constants[0], max(constants[1], constants[2])) + computed_constants[144] = fmod(constants[0], constants[1]) + computed_constants[145] = sin(constants[0]) + computed_constants[146] = cos(constants[0]) + computed_constants[147] = tan(constants[0]) + computed_constants[148] = sec(constants[0]) + computed_constants[149] = csc(constants[0]) + computed_constants[150] = cot(constants[0]) + computed_constants[151] = sinh(constants[0]) + computed_constants[152] = cosh(constants[0]) + computed_constants[153] = tanh(constants[0]) + computed_constants[154] = sech(constants[0]) + computed_constants[155] = csch(constants[0]) + computed_constants[156] = coth(constants[0]) + computed_constants[157] = asin(constants[0]) + computed_constants[158] = acos(constants[0]) + computed_constants[159] = atan(constants[0]) + computed_constants[160] = asec(constants[0]) + computed_constants[161] = acsc(constants[0]) + computed_constants[162] = acot(constants[0]) + computed_constants[163] = asinh(constants[0]) + computed_constants[164] = acosh(constants[0]) + computed_constants[165] = atanh(constants[0]/2.0) + computed_constants[166] = asech(constants[0]) + computed_constants[167] = acsch(constants[0]) + computed_constants[168] = acoth(2.0*constants[0]) + computed_constants[170] = constants[0] if gt_func(constants[0], constants[1]) else nan + computed_constants[171] = constants[0] if lt_func(constants[0], constants[1]) else nan + computed_constants[172] = constants[0] + computed_constants[173] = constants[0] if gt_func(constants[0], constants[1]) else constants[2] + computed_constants[174] = constants[0] if gt_func(constants[0], constants[1]) else constants[2] if gt_func(constants[2], constants[3]) else constants[4] if gt_func(constants[4], constants[5]) else nan + computed_constants[175] = constants[0] if lt_func(constants[0], constants[1]) else constants[2] if gt_func(constants[2], constants[3]) else constants[4] if gt_func(constants[4], constants[5]) else nan + computed_constants[176] = constants[0] if gt_func(constants[0], constants[1]) else constants[2] if gt_func(constants[2], constants[3]) else constants[4] if gt_func(constants[4], constants[5]) else constants[6] + computed_constants[177] = 123.0+(constants[0] if gt_func(constants[0], constants[1]) else nan) + computed_constants[178] = 123.0+(constants[0] if lt_func(constants[0], constants[1]) else nan) + computed_constants[183] = constants[0] + computed_constants[190] = and_func(constants[0], constants[1])+(constants[1] if gt_func(constants[2], constants[3]) else nan)+constants[4]+and_func(constants[5], constants[6]) + computed_constants[191] = and_func(constants[0], constants[1])+(constants[1] if lt_func(constants[2], constants[3]) else nan)+constants[4]+and_func(constants[5], constants[6]) + computed_constants[192] = and_func(constants[0], constants[1])-((constants[1] if gt_func(constants[2], constants[3]) else nan)-(constants[4]-(constants[1] if gt_func(constants[2], constants[3]) else nan)))-and_func(constants[5], constants[6]) + computed_constants[193] = and_func(constants[0], constants[1])-((constants[1] if lt_func(constants[2], constants[3]) else nan)-(constants[4]-(constants[1] if lt_func(constants[2], constants[3]) else nan)))-and_func(constants[5], constants[6]) + computed_constants[194] = and_func(constants[0], constants[1])*(constants[1] if gt_func(constants[2], constants[3]) else nan)*constants[4]*(constants[1] if gt_func(constants[2], constants[3]) else nan)*and_func(constants[5], constants[6]) + computed_constants[195] = and_func(constants[0], constants[1])*(constants[1] if lt_func(constants[2], constants[3]) else nan)*constants[4]*(constants[1] if lt_func(constants[2], constants[3]) else nan)*and_func(constants[5], constants[6]) + computed_constants[196] = and_func(constants[0], constants[1])/((constants[1] if gt_func(constants[2], constants[3]) else nan)/(constants[4]/(constants[1] if gt_func(constants[2], constants[3]) else nan))) + computed_constants[197] = and_func(constants[0], constants[1])/((constants[1] if lt_func(constants[2], constants[3]) else nan)/(constants[4]/(constants[1] if lt_func(constants[2], constants[3]) else nan))) + computed_constants[198] = and_func(or_func(constants[0], constants[1]), and_func(XOR_FUNC(constants[0], constants[1]), and_func(constants[1] if gt_func(constants[2], constants[3]) else nan, and_func(and_func(and_func(constants[4], constants[1] if gt_func(constants[2], constants[3]) else nan), XOR_FUNC(constants[0], constants[1])), or_func(constants[0], constants[1]))))) + computed_constants[199] = or_func(and_func(constants[0], constants[1]), or_func(XOR_FUNC(constants[0], constants[1]), or_func(constants[1] if gt_func(constants[2], constants[3]) else nan, or_func(or_func(or_func(constants[4], constants[1] if gt_func(constants[2], constants[3]) else nan), XOR_FUNC(constants[0], constants[1])), and_func(constants[0], constants[1]))))) + computed_constants[200] = XOR_FUNC(and_func(constants[0], constants[1]), XOR_FUNC(or_func(constants[0], constants[1]), XOR_FUNC(constants[1] if gt_func(constants[2], constants[3]) else nan, XOR_FUNC(XOR_FUNC(XOR_FUNC(constants[4], constants[1] if gt_func(constants[2], constants[3]) else nan), or_func(constants[0], constants[1])), and_func(constants[0], constants[1]))))) + computed_constants[201] = pow(and_func(constants[0], constants[1]), pow(constants[1] if gt_func(constants[2], constants[3]) else nan, pow(pow(constants[4], constants[1] if gt_func(constants[2], constants[3]) else nan), and_func(constants[0], constants[1])))) + computed_constants[202] = pow(pow(pow(and_func(constants[0], constants[1]), 1.0/pow(constants[1] if gt_func(constants[2], constants[3]) else nan, 1.0/constants[4])), 1.0/(constants[1] if gt_func(constants[2], constants[3]) else nan)), 1.0/and_func(constants[0], constants[1])) + computed_constants[203] = -and_func(constants[0], constants[1])+-(constants[1] if gt_func(constants[2], constants[3]) else nan) + computed_constants[204] = -and_func(constants[0], constants[1])+-(constants[1] if lt_func(constants[2], constants[3]) else nan) def compute_rates(voi, states, rates, constants, computed_constants, algebraic, externals, external_variable): @@ -614,5 +627,8 @@ def compute_rates(voi, states, rates, constants, computed_constants, algebraic, def compute_variables(voi, states, rates, constants, computed_constants, algebraic, externals, external_variable): + algebraic[0] = or_func(states[0], states[0]) + algebraic[1] = or_func(states[0], or_func(states[0], constants[0])) + algebraic[2] = constants[0]/XOR_FUNC(constants[1], states[0]) externals[0] = external_variable(voi, states, rates, constants, computed_constants, algebraic, externals, 0) find_root_0(voi, states, rates, constants, computed_constants, algebraic, externals) diff --git a/tests/resources/generator/cellml_slc_example/model.c b/tests/resources/generator/cellml_slc_example/model.c new file mode 100644 index 0000000000..1436a03f37 --- /dev/null +++ b/tests/resources/generator/cellml_slc_example/model.c @@ -0,0 +1,92 @@ +/* The content of this file was generated using the C profile of libCellML 0.6.0. */ + +#include "model.h" + +#include +#include + +const char VERSION[] = "0.6.0"; +const char LIBCELLML_VERSION[] = "0.6.0"; + +const size_t CONSTANT_COUNT = 9; +const size_t COMPUTED_CONSTANT_COUNT = 1; +const size_t ALGEBRAIC_COUNT = 0; + +const VariableInfo CONSTANT_INFO[] = { + {"E", "fmol", "SLC_template3_ss"}, + {"P_0", "per_fmol_sec4", "SLC_template3_ss"}, + {"q_Ao", "fmol", "SLC_template3_ss"}, + {"P_1", "per_fmol_sec4", "SLC_template3_ss"}, + {"q_Ai", "fmol", "SLC_template3_ss"}, + {"P_2", "per_fmol_sec3", "SLC_template3_ss"}, + {"P_5", "per_sec3", "SLC_template3_ss"}, + {"P_4", "per_fmol2_sec3", "SLC_template3_ss"}, + {"P_3", "per_fmol_sec3", "SLC_template3_ss"} +}; + +const VariableInfo COMPUTED_CONSTANT_INFO[] = { + {"v", "fmol_per_sec", "SLC_template3_ss"} +}; + +const VariableInfo ALGEBRAIC_INFO[] = { +}; + +double * createConstantsArray() +{ + double *res = (double *) malloc(CONSTANT_COUNT*sizeof(double)); + + for (size_t i = 0; i < CONSTANT_COUNT; ++i) { + res[i] = NAN; + } + + return res; +} + +double * createComputedConstantsArray() +{ + double *res = (double *) malloc(COMPUTED_CONSTANT_COUNT*sizeof(double)); + + for (size_t i = 0; i < COMPUTED_CONSTANT_COUNT; ++i) { + res[i] = NAN; + } + + return res; +} + +double * createAlgebraicArray() +{ + double *res = (double *) malloc(ALGEBRAIC_COUNT*sizeof(double)); + + for (size_t i = 0; i < ALGEBRAIC_COUNT; ++i) { + res[i] = NAN; + } + + return res; +} + +void deleteArray(double *array) +{ + free(array); +} + +void initialiseVariables(double *constants, double *computedConstants, double *algebraic) +{ + constants[0] = 1.1; + constants[1] = 21262500.0; + constants[2] = 150.0; + constants[3] = 3402000.0; + constants[4] = 2.0; + constants[5] = 2902500.0; + constants[6] = 810000.0; + constants[7] = 247140.0; + constants[8] = 2902500.0; +} + +void computeComputedConstants(double *constants, double *computedConstants) +{ + computedConstants[0] = constants[0]*(constants[1]*constants[2]-constants[3]*constants[4])/(constants[5]*constants[4]+constants[8]*constants[2]+constants[7]*constants[4]*constants[2]+constants[6]); +} + +void computeVariables(double *constants, double *computedConstants, double *algebraic) +{ +} diff --git a/tests/resources/generator/cellml_slc_example/model.h b/tests/resources/generator/cellml_slc_example/model.h new file mode 100644 index 0000000000..661f80fa6f --- /dev/null +++ b/tests/resources/generator/cellml_slc_example/model.h @@ -0,0 +1,32 @@ +/* The content of this file was generated using the C profile of libCellML 0.6.0. */ + +#pragma once + +#include + +extern const char VERSION[]; +extern const char LIBCELLML_VERSION[]; + +extern const size_t CONSTANT_COUNT; +extern const size_t COMPUTED_CONSTANT_COUNT; +extern const size_t ALGEBRAIC_COUNT; + +typedef struct { + char name[5]; + char units[15]; + char component[17]; +} VariableInfo; + +extern const VariableInfo CONSTANT_INFO[]; +extern const VariableInfo COMPUTED_CONSTANT_INFO[]; +extern const VariableInfo ALGEBRAIC_INFO[]; + +double * createConstantsArray(); +double * createComputedConstantsArray(); +double * createAlgebraicArray(); + +void deleteArray(double *array); + +void initialiseVariables(double *constants, double *computedConstants, double *algebraic); +void computeComputedConstants(double *constants, double *computedConstants); +void computeVariables(double *constants, double *computedConstants, double *algebraic); diff --git a/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.algebraic.c b/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.algebraic.external.c similarity index 99% rename from tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.algebraic.c rename to tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.algebraic.external.c index a7c7bbde73..0ff0c4489f 100644 --- a/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.algebraic.c +++ b/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.algebraic.external.c @@ -1,6 +1,6 @@ /* The content of this file was generated using the C profile of libCellML 0.6.0. */ -#include "model.algebraic.h" +#include "model.algebraic.external.h" #include #include diff --git a/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.algebraic.h b/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.algebraic.external.h similarity index 100% rename from tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.algebraic.h rename to tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.algebraic.external.h diff --git a/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.algebraic.py b/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.algebraic.external.py similarity index 100% rename from tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.algebraic.py rename to tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.algebraic.external.py diff --git a/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.computed.constant.c b/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.computed.constant.external.c similarity index 99% rename from tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.computed.constant.c rename to tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.computed.constant.external.c index 3c6887b968..5862270578 100644 --- a/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.computed.constant.c +++ b/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.computed.constant.external.c @@ -1,6 +1,6 @@ /* The content of this file was generated using the C profile of libCellML 0.6.0. */ -#include "model.computed.constant.h" +#include "model.computed.constant.external.h" #include #include diff --git a/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.computed.constant.h b/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.computed.constant.external.h similarity index 100% rename from tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.computed.constant.h rename to tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.computed.constant.external.h diff --git a/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.computed.constant.py b/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.computed.constant.external.py similarity index 100% rename from tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.computed.constant.py rename to tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.computed.constant.external.py diff --git a/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.constant.c b/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.constant.external.c similarity index 99% rename from tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.constant.c rename to tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.constant.external.c index 12ff7e8eef..62631ccd62 100644 --- a/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.constant.c +++ b/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.constant.external.c @@ -1,6 +1,6 @@ /* The content of this file was generated using the C profile of libCellML 0.6.0. */ -#include "model.constant.h" +#include "model.constant.external.h" #include #include diff --git a/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.constant.h b/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.constant.external.h similarity index 100% rename from tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.constant.h rename to tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.constant.external.h diff --git a/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.constant.py b/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.constant.external.py similarity index 100% rename from tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.constant.py rename to tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.constant.external.py diff --git a/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.dependent.algebraic.c b/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.dependent.algebraic.external.c similarity index 99% rename from tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.dependent.algebraic.c rename to tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.dependent.algebraic.external.c index 7cd82fc2f7..e357c309c0 100644 --- a/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.dependent.algebraic.c +++ b/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.dependent.algebraic.external.c @@ -1,6 +1,6 @@ /* The content of this file was generated using the C profile of libCellML 0.6.0. */ -#include "model.dependent.algebraic.h" +#include "model.dependent.algebraic.external.h" #include #include diff --git a/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.dependent.algebraic.h b/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.dependent.algebraic.external.h similarity index 100% rename from tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.dependent.algebraic.h rename to tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.dependent.algebraic.external.h diff --git a/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.dependent.algebraic.py b/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.dependent.algebraic.external.py similarity index 100% rename from tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.dependent.algebraic.py rename to tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.dependent.algebraic.external.py diff --git a/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.dependent.computed.constant.c b/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.dependent.computed.constant.external.c similarity index 99% rename from tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.dependent.computed.constant.c rename to tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.dependent.computed.constant.external.c index 50c6630bd3..2948224f4d 100644 --- a/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.dependent.computed.constant.c +++ b/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.dependent.computed.constant.external.c @@ -1,6 +1,6 @@ /* The content of this file was generated using the C profile of libCellML 0.6.0. */ -#include "model.dependent.computed.constant.h" +#include "model.dependent.computed.constant.external.h" #include #include diff --git a/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.dependent.computed.constant.h b/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.dependent.computed.constant.external.h similarity index 100% rename from tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.dependent.computed.constant.h rename to tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.dependent.computed.constant.external.h diff --git a/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.dependent.computed.constant.py b/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.dependent.computed.constant.external.py similarity index 100% rename from tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.dependent.computed.constant.py rename to tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.dependent.computed.constant.external.py diff --git a/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.dependent.constant.c b/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.dependent.constant.external.c similarity index 99% rename from tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.dependent.constant.c rename to tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.dependent.constant.external.c index 7ee290663e..55adde719b 100644 --- a/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.dependent.constant.c +++ b/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.dependent.constant.external.c @@ -1,6 +1,6 @@ /* The content of this file was generated using the C profile of libCellML 0.6.0. */ -#include "model.dependent.constant.h" +#include "model.dependent.constant.external.h" #include #include diff --git a/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.dependent.constant.h b/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.dependent.constant.external.h similarity index 100% rename from tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.dependent.constant.h rename to tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.dependent.constant.external.h diff --git a/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.dependent.constant.py b/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.dependent.constant.external.py similarity index 100% rename from tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.dependent.constant.py rename to tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.dependent.constant.external.py diff --git a/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.dependent.state.c b/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.dependent.state.external.c similarity index 99% rename from tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.dependent.state.c rename to tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.dependent.state.external.c index 56be82f194..b9bca59ba5 100644 --- a/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.dependent.state.c +++ b/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.dependent.state.external.c @@ -1,6 +1,6 @@ /* The content of this file was generated using the C profile of libCellML 0.6.0. */ -#include "model.dependent.state.h" +#include "model.dependent.state.external.h" #include #include diff --git a/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.dependent.state.h b/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.dependent.state.external.h similarity index 100% rename from tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.dependent.state.h rename to tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.dependent.state.external.h diff --git a/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.dependent.state.py b/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.dependent.state.external.py similarity index 100% rename from tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.dependent.state.py rename to tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.dependent.state.external.py diff --git a/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.state.c b/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.state.external.c similarity index 99% rename from tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.state.c rename to tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.state.external.c index 3acf0bc178..0e3ca00d59 100644 --- a/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.state.c +++ b/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.state.external.c @@ -1,6 +1,6 @@ /* The content of this file was generated using the C profile of libCellML 0.6.0. */ -#include "model.state.h" +#include "model.state.external.h" #include #include diff --git a/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.state.h b/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.state.external.h similarity index 100% rename from tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.state.h rename to tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.state.external.h diff --git a/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.state.py b/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.state.external.py similarity index 100% rename from tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.state.py rename to tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.state.external.py diff --git a/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model_unknown_vars_on_rhs.cellml b/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.unknown.vars.on.rhs.cellml similarity index 100% rename from tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model_unknown_vars_on_rhs.cellml rename to tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.unknown.vars.on.rhs.cellml From 5a3a19e8fc3df2becdfd95a5a4d2337060aa4540 Mon Sep 17 00:00:00 2001 From: Alan Garny Date: Wed, 23 Oct 2024 11:17:12 +1300 Subject: [PATCH 10/10] Tests: improved our coverage. --- tests/coverage/coverage.cpp | 55 +++++++++++-------------------------- 1 file changed, 16 insertions(+), 39 deletions(-) diff --git a/tests/coverage/coverage.cpp b/tests/coverage/coverage.cpp index 9cbbd6fe8d..e3f169f146 100644 --- a/tests/coverage/coverage.cpp +++ b/tests/coverage/coverage.cpp @@ -627,53 +627,30 @@ TEST(Coverage, generator) EXPECT_EQ(size_t(1), analyserModel->equation(0)->states().size()); EXPECT_NE(nullptr, analyserModel->equation(0)->state(0)); EXPECT_EQ(nullptr, analyserModel->equation(0)->state(analyserModel->equation(0)->stateCount())); - /*---GRY--- STILL NEEDED? - EXPECT_NE(nullptr, analyserModel->equation(199)); - EXPECT_NE(size_t(0), analyserModel->equation(199)->dependencyCount()); - EXPECT_NE(size_t(0), analyserModel->equation(199)->dependencies().size()); - EXPECT_NE(nullptr, analyserModel->equation(199)->dependency(0)); - EXPECT_EQ(nullptr, analyserModel->equation(199)->dependency(analyserModel->equation(199)->dependencyCount())); - EXPECT_EQ(size_t(1), analyserModel->equation(199)->nlaSiblingCount()); - EXPECT_EQ(size_t(1), analyserModel->equation(199)->nlaSiblings().size()); - EXPECT_NE(nullptr, analyserModel->equation(199)->nlaSibling(0)); - EXPECT_EQ(nullptr, analyserModel->equation(199)->nlaSibling(analyserModel->equation(199)->nlaSiblingCount())); - EXPECT_EQ(size_t(0), analyserModel->equation(199)->computedConstantCount()); - EXPECT_EQ(size_t(0), analyserModel->equation(199)->computedConstants().size()); - EXPECT_EQ(nullptr, analyserModel->equation(199)->computedConstant(0)); - EXPECT_EQ(nullptr, analyserModel->equation(199)->computedConstant(analyserModel->equation(199)->computedConstantCount())); - EXPECT_NE(size_t(0), analyserModel->equation(199)->algebraicCount()); - EXPECT_NE(size_t(0), analyserModel->equation(199)->algebraic().size()); - EXPECT_NE(nullptr, analyserModel->equation(199)->algebraic(0)); - EXPECT_EQ(nullptr, analyserModel->equation(199)->algebraic(analyserModel->equation(199)->algebraicCount())); - EXPECT_EQ(size_t(0), analyserModel->equation(199)->externalCount()); - EXPECT_EQ(size_t(0), analyserModel->equation(199)->externals().size()); - EXPECT_EQ(nullptr, analyserModel->equation(199)->external(0)); - EXPECT_EQ(nullptr, analyserModel->equation(199)->external(analyserModel->equation(199)->externalCount())); EXPECT_EQ(nullptr, analyserModel->equation(analyserModel->equationCount())); - */ for (const auto &equation : analyserModel->equations()) { + equation->dependencyCount(); + equation->dependency(0); + equation->dependency(equation->dependencyCount()); + equation->nlaSiblingCount(); + equation->nlaSibling(0); + equation->nlaSibling(equation->nlaSiblingCount()); + equation->computedConstantCount(); + equation->computedConstant(0); + equation->computedConstant(equation->computedConstantCount()); + equation->algebraicCount(); + equation->algebraic(0); + equation->algebraic(equation->algebraicCount()); + equation->externalCount(); + equation->external(0); + equation->external(equation->externalCount()); + checkAstTypeAsString(equation->ast()); } auto generator = libcellml::Generator::create(); - EXPECT_EQ(nullptr, analyserModel->voi()->initialisingVariable()); - - for (size_t i = 0; i < analyserModel->stateCount(); ++i) { - EXPECT_NE(nullptr, analyserModel->state(i)->initialisingVariable()); - } - - for (size_t i = 0; i < analyserModel->constantCount(); ++i) { - EXPECT_NE(nullptr, analyserModel->constant(i)->initialisingVariable()); - } - - /*---GRY--- STILL NEEDED? - for (size_t i = 0; i < analyserModel->algebraicCount(); ++i) { - EXPECT_NE(nullptr, analyserModel->algebraic(i)->initialisingVariable()); - } - */ - EXPECT_EQ(nullptr, generator->model()); EXPECT_EQ(EMPTY_STRING, generator->interfaceCode()); EXPECT_EQ(EMPTY_STRING, generator->implementationCode());