From 35a87f68e658572d0ca1608d4a58bf00451bd10c Mon Sep 17 00:00:00 2001 From: Sarah Keating Date: Tue, 18 Nov 2025 12:43:26 +0000 Subject: [PATCH 1/8] add more derivatives --- src/sbml/math/ASTNode.cpp | 156 +++++++++++++++++- src/sbml/math/ASTNode.h | 4 +- .../math/test/TestDerivativeFunctions.cpp | 113 ++++++++----- 3 files changed, 231 insertions(+), 42 deletions(-) diff --git a/src/sbml/math/ASTNode.cpp b/src/sbml/math/ASTNode.cpp index 238970c86c..34e733d4f1 100644 --- a/src/sbml/math/ASTNode.cpp +++ b/src/sbml/math/ASTNode.cpp @@ -4338,7 +4338,15 @@ ASTNode::derivative(const std::string& variable) case AST_FUNCTION_ABS: derivative = derivativeAbs(variable); break; - + case AST_FUNCTION_ARCCOS: + derivative = derivativeArccos(variable); + break; + //case AST_FUNCTION_ARCSIN: + // derivative = derivativeArcsin(variable); + // break; + //case AST_FUNCTION_ARCTAN: + // derivative = derivativeArctan(variable); + // break; default: @@ -4718,6 +4726,152 @@ ASTNode::derivativeAbs(const std::string& variable) return derivative; } +ASTNode* +ASTNode::derivativeArccos(const std::string& variable) +{ + + ASTNode* copy = deepCopy(); + copy->decompose(); + ASTNode* derivative = NULL; + ASTNode* minusOne = new ASTNode(AST_REAL); + minusOne->setValue(-1.0); + ASTNode* two = new ASTNode(AST_REAL); + two->setValue(2.0); + ASTNode* one = new ASTNode(AST_REAL); + one->setValue(1.0); + ASTNode* minus_half = new ASTNode(AST_REAL); + minus_half->setValue(-0.5); + + ASTNode* sqrt = new ASTNode(AST_FUNCTION_POWER); + ASTNode* bracket_minus = new ASTNode(AST_MINUS); + + //d(arccos(x)/dx = -1/sqrt(1-x^2) + //d(arccos(A)/dx = dA/dx * -1/sqrt(1-A^2) + + ASTNode* derivA = getChild(0)->derivative(variable); + + if (derivA != NULL) + { + ASTNode* Asquared = new ASTNode(AST_POWER); + Asquared->addChild(getChild(0)->deepCopy()); + Asquared->addChild(two->deepCopy()); + + bracket_minus->addChild(one->deepCopy()); + bracket_minus->addChild(Asquared->deepCopy()); + + sqrt->addChild(bracket_minus->deepCopy()); + sqrt->addChild(minus_half->deepCopy()); + + derivative = new ASTNode(AST_TIMES); + derivative->addChild(derivA->deepCopy()); + derivative->addChild(minusOne->deepCopy()); + derivative->addChild(sqrt->deepCopy()); + + derivative->decompose(); + + delete Asquared; + } + delete copy; + delete minusOne; + delete two; + delete bracket_minus; + delete minus_half; + delete one; + delete derivA; + return derivative; +} +//ASTNode* +//ASTNode::derivativeArcsin(const std::string& variable) +//{ +// ASTNode* copy = deepCopy(); +// copy->decompose(); +// ASTNode* derivative = NULL; +// ASTNode* two = new ASTNode(AST_REAL); +// two->setValue(2.0); +// ASTNode* sqrt = new ASTNode(AST_FUNCTION_POWER); +// ASTNode* bracket = new ASTNode(AST_MINUS); +// ASTNode* one = new ASTNode(AST_REAL); +// one->setValue(1.0); +// +// //d(arcsin(x)/dx = 1/sqrt(1-x^2) +// //d(arcsin(A)/dx = dA/dx * 1/sqrt(1-A^2) +// +// if (getChild(0)->derivative(variable) != NULL) +// { +// bracket->addChild(one->deepCopy()); +// ASTNode* power = new ASTNode(AST_POWER); +// power->addChild(getChild(0)->deepCopy()); +// power->addChild(two->deepCopy()); +// bracket->addChild(power->deepCopy()); +// +// sqrt->addChild(bracket->deepCopy()); +// ASTNode* oneNode = new ASTNode(AST_REAL); +// oneNode->setValue(1.0); +// sqrt->addChild(oneNode->deepCopy()); +// +// derivative = new ASTNode(AST_TIMES); +// derivative->addChild(getChild(0)->derivative(variable)); +// derivative->addChild(sqrt->deepCopy()); +// +// derivative->decompose(); +// +// delete power; +// delete oneNode; +// } +// delete copy; +// delete two; +// delete bracket; +// delete one; +// return derivative; +//} +//ASTNode* +//ASTNode::derivativeArctan(const std::string& variable) +//{ +// ASTNode* copy = deepCopy(); +// copy->decompose(); +// ASTNode* derivative = NULL; +// ASTNode* two = new ASTNode(AST_REAL); +// two->setValue(2.0); +// ASTNode* bracket = new ASTNode(AST_PLUS); +// ASTNode* one = new ASTNode(AST_REAL); +// one->setValue(1.0); +// +// //d(arctan(x)/dx = 1/(1+x^2) +// //d(arctan(A)/dx = dA/dx * 1/(1+A^2) +// +// if (getChild(0)->derivative(variable) != NULL) +// { +// bracket->addChild(one->deepCopy()); +// ASTNode* power = new ASTNode(AST_POWER); +// power->addChild(getChild(0)->deepCopy()); +// power->addChild(two->deepCopy()); +// bracket->addChild(power->deepCopy()); +// +// derivative = new ASTNode(AST_TIMES); +// derivative->addChild(getChild(0)->derivative(variable)); +// ASTNode* divide = new ASTNode(AST_DIVIDE); +// ASTNode* oneNode = new ASTNode(AST_REAL); +// oneNode->setValue(1.0); +// divide->addChild(oneNode->deepCopy()); +// divide->addChild(bracket->deepCopy()); +// derivative->addChild(divide->deepCopy()); +// +// derivative->decompose(); +// +// delete power; +// delete oneNode; +// delete divide; +// } +// delete copy; +// delete two; +// delete bracket; +// delete one; +// return derivative; +//} + + + + XMLNamespaces* ASTNode::getDeclaredNamespaces() const { diff --git a/src/sbml/math/ASTNode.h b/src/sbml/math/ASTNode.h index d9bfc45e74..511abd2828 100644 --- a/src/sbml/math/ASTNode.h +++ b/src/sbml/math/ASTNode.h @@ -2467,7 +2467,9 @@ setValue(value, 0); ASTNode* derivativeLn(const std::string& variable); ASTNode* derivativeExp(const std::string& variable); ASTNode* derivativeAbs(const std::string& variable); - + ASTNode* derivativeArccos(const std::string& variable); + //ASTNode* derivativeArcsin(const std::string& variable); + //ASTNode* derivativeArctan(const std::string& variable); /* * produce three vectors of the child index of the ASTNodes diff --git a/src/sbml/math/test/TestDerivativeFunctions.cpp b/src/sbml/math/test/TestDerivativeFunctions.cpp index bbd64833c0..e728f68fc2 100644 --- a/src/sbml/math/test/TestDerivativeFunctions.cpp +++ b/src/sbml/math/test/TestDerivativeFunctions.cpp @@ -63,7 +63,23 @@ LIBSBML_CPP_NAMESPACE_USE /** @endcond */ CK_CPPSTART +static bool +equals(const char* expected, const char* actual) +{ + if (!strcmp(expected, actual)) return true; + + printf("\nStrings are not equal:\n"); + printf("Expected:\n[%s]\n", expected); + printf("Actual:\n[%s]\n", actual); + return false; +} + +static bool +formulas_equal(const char* expected, ASTNode* actual) +{ + return equals(expected, SBML_formulaToL3String(actual)); +} START_TEST (test_deriv_const) { @@ -1033,6 +1049,22 @@ START_TEST(test_deriv_abs2) } END_TEST +START_TEST(test_deriv_arccos) +{ + const std::string& x = "x"; + ASTNode* n = SBML_parseL3Formula("arccos(x)"); + fail_unless(n != NULL); + + const char* expected = "-1 * (1 - x^2)^-0.5"; + + ASTNode* deriv = n->derivative(x); + + fail_unless(formulas_equal(expected, deriv) == true); + delete n; + delete deriv; +} +END_TEST + START_TEST(test_deriv_not_implemented ) { ASTNode* n = readMathMLFromString( @@ -1068,46 +1100,47 @@ create_suite_TestDerivativeFunctions() TCase *tcase = tcase_create("TestDerivFunctions"); tcase_add_test(tcase, test_deriv_const); - tcase_add_test(tcase, test_deriv_var); - tcase_add_test(tcase, test_deriv_var1); - tcase_add_test(tcase, test_deriv_plus); - tcase_add_test(tcase, test_deriv_plus1); - tcase_add_test(tcase, test_deriv_plus2); - tcase_add_test(tcase, test_deriv_plus3); - tcase_add_test(tcase, test_deriv_plus4); - tcase_add_test(tcase, test_deriv_times); - tcase_add_test(tcase, test_deriv_times1); - tcase_add_test(tcase, test_deriv_times2); - tcase_add_test(tcase, test_deriv_divide); - tcase_add_test(tcase, test_deriv_divide1); - tcase_add_test(tcase, test_deriv_divide2); - tcase_add_test(tcase, test_deriv_divide3); - tcase_add_test(tcase, test_deriv_divide4); - tcase_add_test(tcase, test_deriv_minus); - tcase_add_test(tcase, test_deriv_minus1); - tcase_add_test(tcase, test_deriv_minus2); - tcase_add_test(tcase, test_deriv_minus3); - tcase_add_test(tcase, test_deriv_minus4); - tcase_add_test(tcase, test_deriv_power); - tcase_add_test(tcase, test_deriv_power1); - tcase_add_test(tcase, test_deriv_power2); - tcase_add_test(tcase, test_deriv_power3); - tcase_add_test(tcase, test_deriv_power4); - tcase_add_test(tcase, test_deriv_root); - tcase_add_test(tcase, test_deriv_root1); - tcase_add_test(tcase, test_deriv_root2); - tcase_add_test(tcase, test_deriv_log); - tcase_add_test(tcase, test_deriv_log1); - tcase_add_test(tcase, test_deriv_log2); - tcase_add_test(tcase, test_deriv_ln); - tcase_add_test(tcase, test_deriv_ln1); - tcase_add_test(tcase, test_deriv_ln2); - tcase_add_test(tcase, test_deriv_exp); - tcase_add_test(tcase, test_deriv_exp1); - tcase_add_test(tcase, test_deriv_exp2); - tcase_add_test(tcase, test_deriv_abs); - tcase_add_test(tcase, test_deriv_abs1); - tcase_add_test(tcase, test_deriv_abs2); + //tcase_add_test(tcase, test_deriv_var); + //tcase_add_test(tcase, test_deriv_var1); + //tcase_add_test(tcase, test_deriv_plus); + //tcase_add_test(tcase, test_deriv_plus1); + //tcase_add_test(tcase, test_deriv_plus2); + //tcase_add_test(tcase, test_deriv_plus3); + //tcase_add_test(tcase, test_deriv_plus4); + //tcase_add_test(tcase, test_deriv_times); + //tcase_add_test(tcase, test_deriv_times1); + //tcase_add_test(tcase, test_deriv_times2); + //tcase_add_test(tcase, test_deriv_divide); + //tcase_add_test(tcase, test_deriv_divide1); + //tcase_add_test(tcase, test_deriv_divide2); + //tcase_add_test(tcase, test_deriv_divide3); + //tcase_add_test(tcase, test_deriv_divide4); + //tcase_add_test(tcase, test_deriv_minus); + //tcase_add_test(tcase, test_deriv_minus1); + //tcase_add_test(tcase, test_deriv_minus2); + //tcase_add_test(tcase, test_deriv_minus3); + //tcase_add_test(tcase, test_deriv_minus4); + //tcase_add_test(tcase, test_deriv_power); + //tcase_add_test(tcase, test_deriv_power1); + //tcase_add_test(tcase, test_deriv_power2); + //tcase_add_test(tcase, test_deriv_power3); + //tcase_add_test(tcase, test_deriv_power4); + //tcase_add_test(tcase, test_deriv_root); + //tcase_add_test(tcase, test_deriv_root1); + //tcase_add_test(tcase, test_deriv_root2); + //tcase_add_test(tcase, test_deriv_log); + //tcase_add_test(tcase, test_deriv_log1); + //tcase_add_test(tcase, test_deriv_log2); + //tcase_add_test(tcase, test_deriv_ln); + //tcase_add_test(tcase, test_deriv_ln1); + //tcase_add_test(tcase, test_deriv_ln2); + //tcase_add_test(tcase, test_deriv_exp); + //tcase_add_test(tcase, test_deriv_exp1); + //tcase_add_test(tcase, test_deriv_exp2); + //tcase_add_test(tcase, test_deriv_abs); + //tcase_add_test(tcase, test_deriv_abs1); + //tcase_add_test(tcase, test_deriv_abs2); + tcase_add_test(tcase, test_deriv_arccos); tcase_add_test(tcase, test_deriv_not_implemented); From 31d69e45336cc9ee964bef46905843d321feb130 Mon Sep 17 00:00:00 2001 From: Sarah Keating Date: Tue, 18 Nov 2025 13:25:05 +0000 Subject: [PATCH 2/8] more tests --- .../math/test/TestDerivativeFunctions.cpp | 39 +++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/src/sbml/math/test/TestDerivativeFunctions.cpp b/src/sbml/math/test/TestDerivativeFunctions.cpp index e728f68fc2..31770c0f39 100644 --- a/src/sbml/math/test/TestDerivativeFunctions.cpp +++ b/src/sbml/math/test/TestDerivativeFunctions.cpp @@ -1065,6 +1065,43 @@ START_TEST(test_deriv_arccos) } END_TEST +START_TEST(test_deriv_arccos1) +{ + const std::string& x = "x"; + ASTNode* n = SBML_parseL3Formula("arccos(x^3)"); + fail_unless(n != NULL); + ASTNode* deriv = n->derivative(x); + + const char* expected = "-3 * x^2 * (1 - x^3^2)^-0.5"; + //cout << SBML_formulaToL3String(deriv) << endl; + //cout << expected << endl; + + + fail_unless(formulas_equal(expected, deriv) == true); + delete n; + delete deriv; +} +END_TEST + +START_TEST(test_deriv_arccos2) +{ + const std::string& x = "x"; + ASTNode* n = SBML_parseL3Formula("arccos((x^3)+2*x)"); + fail_unless(n != NULL); + ASTNode* deriv = n->derivative(x); + + const char* expected = "-2 * (1 - (x^3 + 2 * x)^2)^-0.5 + -3 * x^2 * (1 - (x^3 + 2 * x)^2)^-0.5"; + cout << SBML_formulaToL3String(deriv) << endl; + cout << expected << endl; + + + fail_unless(formulas_equal(expected, deriv) == true); + delete n; + delete deriv; +} +END_TEST + + START_TEST(test_deriv_not_implemented ) { ASTNode* n = readMathMLFromString( @@ -1141,6 +1178,8 @@ create_suite_TestDerivativeFunctions() //tcase_add_test(tcase, test_deriv_abs1); //tcase_add_test(tcase, test_deriv_abs2); tcase_add_test(tcase, test_deriv_arccos); + tcase_add_test(tcase, test_deriv_arccos1); + tcase_add_test(tcase, test_deriv_arccos2); tcase_add_test(tcase, test_deriv_not_implemented); From 7692e02c623fd84bb50f1ffb820845adcafe83f9 Mon Sep 17 00:00:00 2001 From: Sarah Keating Date: Sat, 6 Dec 2025 13:29:03 +0000 Subject: [PATCH 3/8] adding more derivative functions --- src/sbml/math/ASTNode.cpp | 202 ++++++++++++++++++++------------------ src/sbml/math/ASTNode.h | 4 +- 2 files changed, 109 insertions(+), 97 deletions(-) diff --git a/src/sbml/math/ASTNode.cpp b/src/sbml/math/ASTNode.cpp index 34e733d4f1..1e2ba49fca 100644 --- a/src/sbml/math/ASTNode.cpp +++ b/src/sbml/math/ASTNode.cpp @@ -4341,13 +4341,12 @@ ASTNode::derivative(const std::string& variable) case AST_FUNCTION_ARCCOS: derivative = derivativeArccos(variable); break; - //case AST_FUNCTION_ARCSIN: - // derivative = derivativeArcsin(variable); - // break; - //case AST_FUNCTION_ARCTAN: - // derivative = derivativeArctan(variable); - // break; - + case AST_FUNCTION_ARCSIN: + derivative = derivativeArcsin(variable); + break; + case AST_FUNCTION_ARCTAN: + derivative = derivativeArctan(variable); + break; default: break; @@ -4780,94 +4779,107 @@ ASTNode::derivativeArccos(const std::string& variable) delete derivA; return derivative; } -//ASTNode* -//ASTNode::derivativeArcsin(const std::string& variable) -//{ -// ASTNode* copy = deepCopy(); -// copy->decompose(); -// ASTNode* derivative = NULL; -// ASTNode* two = new ASTNode(AST_REAL); -// two->setValue(2.0); -// ASTNode* sqrt = new ASTNode(AST_FUNCTION_POWER); -// ASTNode* bracket = new ASTNode(AST_MINUS); -// ASTNode* one = new ASTNode(AST_REAL); -// one->setValue(1.0); -// -// //d(arcsin(x)/dx = 1/sqrt(1-x^2) -// //d(arcsin(A)/dx = dA/dx * 1/sqrt(1-A^2) -// -// if (getChild(0)->derivative(variable) != NULL) -// { -// bracket->addChild(one->deepCopy()); -// ASTNode* power = new ASTNode(AST_POWER); -// power->addChild(getChild(0)->deepCopy()); -// power->addChild(two->deepCopy()); -// bracket->addChild(power->deepCopy()); -// -// sqrt->addChild(bracket->deepCopy()); -// ASTNode* oneNode = new ASTNode(AST_REAL); -// oneNode->setValue(1.0); -// sqrt->addChild(oneNode->deepCopy()); -// -// derivative = new ASTNode(AST_TIMES); -// derivative->addChild(getChild(0)->derivative(variable)); -// derivative->addChild(sqrt->deepCopy()); -// -// derivative->decompose(); -// -// delete power; -// delete oneNode; -// } -// delete copy; -// delete two; -// delete bracket; -// delete one; -// return derivative; -//} -//ASTNode* -//ASTNode::derivativeArctan(const std::string& variable) -//{ -// ASTNode* copy = deepCopy(); -// copy->decompose(); -// ASTNode* derivative = NULL; -// ASTNode* two = new ASTNode(AST_REAL); -// two->setValue(2.0); -// ASTNode* bracket = new ASTNode(AST_PLUS); -// ASTNode* one = new ASTNode(AST_REAL); -// one->setValue(1.0); -// -// //d(arctan(x)/dx = 1/(1+x^2) -// //d(arctan(A)/dx = dA/dx * 1/(1+A^2) -// -// if (getChild(0)->derivative(variable) != NULL) -// { -// bracket->addChild(one->deepCopy()); -// ASTNode* power = new ASTNode(AST_POWER); -// power->addChild(getChild(0)->deepCopy()); -// power->addChild(two->deepCopy()); -// bracket->addChild(power->deepCopy()); -// -// derivative = new ASTNode(AST_TIMES); -// derivative->addChild(getChild(0)->derivative(variable)); -// ASTNode* divide = new ASTNode(AST_DIVIDE); -// ASTNode* oneNode = new ASTNode(AST_REAL); -// oneNode->setValue(1.0); -// divide->addChild(oneNode->deepCopy()); -// divide->addChild(bracket->deepCopy()); -// derivative->addChild(divide->deepCopy()); -// -// derivative->decompose(); -// -// delete power; -// delete oneNode; -// delete divide; -// } -// delete copy; -// delete two; -// delete bracket; -// delete one; -// return derivative; -//} +ASTNode* +ASTNode::derivativeArcsin(const std::string& variable) +{ + ASTNode* copy = deepCopy(); + copy->decompose(); + ASTNode* derivative = NULL; + ASTNode* two = new ASTNode(AST_REAL); + two->setValue(2.0); + ASTNode* one = new ASTNode(AST_REAL); + one->setValue(1.0); + ASTNode* minus_half = new ASTNode(AST_REAL); + minus_half->setValue(-0.5); + + ASTNode* sqrt = new ASTNode(AST_FUNCTION_POWER); + ASTNode* bracket_minus = new ASTNode(AST_MINUS); + + //d(arcsin(x)/dx = 1/sqrt(1-x^2) + //d(arcsin(A)/dx = dA/dx * 1/sqrt(1-A^2) + + ASTNode* derivA = getChild(0)->derivative(variable); + + if (derivA != NULL) + { + ASTNode* Asquared = new ASTNode(AST_POWER); + Asquared->addChild(getChild(0)->deepCopy()); + Asquared->addChild(two->deepCopy()); + + bracket_minus->addChild(one->deepCopy()); + bracket_minus->addChild(Asquared->deepCopy()); + + sqrt->addChild(bracket_minus->deepCopy()); + sqrt->addChild(minus_half->deepCopy()); + + derivative = new ASTNode(AST_TIMES); + derivative->addChild(derivA->deepCopy()); + derivative->addChild(sqrt->deepCopy()); + + derivative->decompose(); + + delete Asquared; + } + delete copy; + delete two; + delete bracket_minus; + delete minus_half; + delete one; + delete derivA; + return derivative; + +} + +ASTNode* +ASTNode::derivativeArctan(const std::string& variable) +{ + ASTNode* copy = deepCopy(); + copy->decompose(); + ASTNode* derivative = NULL; + ASTNode* two = new ASTNode(AST_REAL); + two->setValue(2.0); + ASTNode* one = new ASTNode(AST_REAL); + one->setValue(1.0); + ASTNode* minus_one = new ASTNode(AST_REAL); + minus_one->setValue(-1.0); + + ASTNode* power = new ASTNode(AST_FUNCTION_POWER); + ASTNode* bracket_plus = new ASTNode(AST_PLUS); + + //d(arctan(x)/dx = 1/(1+x^2) + //d(arctan(A)/dx = dA/dx * 1/(1+A^2) + + ASTNode* derivA = getChild(0)->derivative(variable); + + if (derivA != NULL) + { + ASTNode* Asquared = new ASTNode(AST_POWER); + Asquared->addChild(getChild(0)->deepCopy()); + Asquared->addChild(two->deepCopy()); + + bracket_plus->addChild(one->deepCopy()); + bracket_plus->addChild(Asquared->deepCopy()); + + power->addChild(bracket_plus->deepCopy()); + power->addChild(minus_one->deepCopy()); + + derivative = new ASTNode(AST_TIMES); + derivative->addChild(derivA->deepCopy()); + derivative->addChild(power->deepCopy()); + + derivative->decompose(); + + delete Asquared; + } + delete copy; + delete two; + delete one; + delete minus_one; + delete bracket_plus; + delete power; + delete derivA; + return derivative; +} diff --git a/src/sbml/math/ASTNode.h b/src/sbml/math/ASTNode.h index 511abd2828..c3df84296b 100644 --- a/src/sbml/math/ASTNode.h +++ b/src/sbml/math/ASTNode.h @@ -2468,8 +2468,8 @@ setValue(value, 0); ASTNode* derivativeExp(const std::string& variable); ASTNode* derivativeAbs(const std::string& variable); ASTNode* derivativeArccos(const std::string& variable); - //ASTNode* derivativeArcsin(const std::string& variable); - //ASTNode* derivativeArctan(const std::string& variable); + ASTNode* derivativeArcsin(const std::string& variable); + ASTNode* derivativeArctan(const std::string& variable); /* * produce three vectors of the child index of the ASTNodes From 757bad0a16fbea3aff39c8e2e2d875306ec8835d Mon Sep 17 00:00:00 2001 From: Sarah Keating Date: Thu, 18 Dec 2025 13:54:05 +0000 Subject: [PATCH 4/8] Implements missing derivative functions Adds derivative functions for trigonometric and hyperbolic functions, including their inverses. This completes the implementation of the derivative function for ASTNodes. --- src/sbml/math/ASTNode.cpp | 1591 +++++++++++++++++++++++++++++++------ src/sbml/math/ASTNode.h | 24 +- 2 files changed, 1358 insertions(+), 257 deletions(-) diff --git a/src/sbml/math/ASTNode.cpp b/src/sbml/math/ASTNode.cpp index 1e2ba49fca..94e48f2488 100644 --- a/src/sbml/math/ASTNode.cpp +++ b/src/sbml/math/ASTNode.cpp @@ -4338,15 +4338,78 @@ ASTNode::derivative(const std::string& variable) case AST_FUNCTION_ABS: derivative = derivativeAbs(variable); break; + case AST_FUNCTION_ARCSIN: + derivative = derivativeArcsin(variable); + break; case AST_FUNCTION_ARCCOS: derivative = derivativeArccos(variable); break; - case AST_FUNCTION_ARCSIN: - derivative = derivativeArcsin(variable); - break; case AST_FUNCTION_ARCTAN: - derivative = derivativeArctan(variable); - break; + derivative = derivativeArctan(variable); + break; + case AST_FUNCTION_SIN: + derivative = derivativeSin(variable); + break; + case AST_FUNCTION_COS: + derivative = derivativeCos(variable); + break; + case AST_FUNCTION_TAN: + derivative = derivativeTan(variable); + break; + case AST_FUNCTION_COT: + derivative = derivativeCot(variable); + break; + case AST_FUNCTION_SEC: + derivative = derivativeSec(variable); + break; + case AST_FUNCTION_CSC: + derivative = derivativeCsc(variable); + break; + case AST_FUNCTION_SINH: + derivative = derivativeSinh(variable); + break; + case AST_FUNCTION_COSH: + derivative = derivativeCosh(variable); + break; + case AST_FUNCTION_TANH: + derivative = derivativeTanh(variable); + break; + case AST_FUNCTION_COTH: + derivative = derivativeCoth(variable); + break; + case AST_FUNCTION_SECH: + derivative = derivativeSech(variable); + break; + case AST_FUNCTION_CSCH: + derivative = derivativeCsch(variable); + break; + case AST_FUNCTION_ARCSINH: + derivative = derivativeArcsinh(variable); + break; + case AST_FUNCTION_ARCCOSH: + derivative = derivativeArccosh(variable); + break; + case AST_FUNCTION_ARCTANH: + derivative = derivativeArctanh(variable); + break; + case AST_FUNCTION_ARCCOT: + derivative = derivativeArccot(variable); + break; + case AST_FUNCTION_ARCSEC: + derivative = derivativeArcsec(variable); + break; + case AST_FUNCTION_ARCCSC: + derivative = derivativeArccsc(variable); + break; + case AST_FUNCTION_ARCCOTH: + derivative = derivativeArccoth(variable); + break; + case AST_FUNCTION_ARCSECH: + derivative = derivativeArcsech(variable); + break; + case AST_FUNCTION_ARCCSCH: + derivative = derivativeArccsch(variable); + break; default: break; @@ -4356,11 +4419,10 @@ ASTNode::derivative(const std::string& variable) delete zero; delete copy; return derivative; - } -ASTNode* -ASTNode::derivativePlus(const std::string& variable) +ASTNode * +ASTNode::derivativePlus(const std::string &variable) { ASTNode *copy = deepCopy(); copy->decompose(); @@ -4368,10 +4430,10 @@ ASTNode::derivativePlus(const std::string& variable) zero->setValue(0.0); // d (A + B)/dx = dA/dx + dB/dx - ASTNode * derivative = new ASTNode(AST_PLUS); + ASTNode *derivative = new ASTNode(AST_PLUS); for (unsigned int n = 0; n < copy->getNumChildren(); ++n) { - ASTNode* child_der = copy->getChild(n)->derivative(variable); + ASTNode *child_der = copy->getChild(n)->derivative(variable); if (child_der && !(child_der->exactlyEqual(*zero))) { derivative->addChild(child_der->deepCopy()); @@ -4385,19 +4447,18 @@ ASTNode::derivativePlus(const std::string& variable) return derivative; } - -ASTNode* -ASTNode::derivativeMinus(const std::string& variable) +ASTNode * +ASTNode::derivativeMinus(const std::string &variable) { ASTNode *copy = deepCopy(); copy->decompose(); ASTNode *zero = new ASTNode(AST_REAL); zero->setValue(0.0); - ASTNode * derivative = NULL; + ASTNode *derivative = NULL; // d (A - B)/dx = dA/dx - dB/dx - ASTNode* child_derA = copy->getChild(0)->derivative(variable); - ASTNode* child_derB = copy->getChild(1)->derivative(variable); + ASTNode *child_derA = copy->getChild(0)->derivative(variable); + ASTNode *child_derB = copy->getChild(1)->derivative(variable); if (!child_derB || child_derB->exactlyEqual(*zero)) { derivative = child_derA->deepCopy(); @@ -4423,21 +4484,21 @@ ASTNode::derivativeMinus(const std::string& variable) return derivative; } -ASTNode* -ASTNode::derivativeTimes(const std::string& variable) +ASTNode * +ASTNode::derivativeTimes(const std::string &variable) { ASTNode *copy = this->deepCopy(); copy->decompose(); copy->reduceToBinary(); ASTNode *zero = new ASTNode(AST_REAL); zero->setValue(0.0); - ASTNode * derivative = NULL; - ASTNode * term1 = NULL; - ASTNode * term2 = NULL; + ASTNode *derivative = NULL; + ASTNode *term1 = NULL; + ASTNode *term2 = NULL; // d(A*B)/dx = B * dA/dx + A * dB/dx - ASTNode* child_derA = copy->getChild(0)->derivative(variable); - ASTNode* child_derB = copy->getChild(1)->derivative(variable); + ASTNode *child_derA = copy->getChild(0)->derivative(variable); + ASTNode *child_derB = copy->getChild(1)->derivative(variable); if (!child_derB || child_derB->exactlyEqual(*zero)) { derivative = new ASTNode(AST_TIMES); @@ -4459,11 +4520,10 @@ ASTNode::derivativeTimes(const std::string& variable) term2 = new ASTNode(AST_TIMES); term2->addChild(copy->getChild(0)->deepCopy()); term2->addChild(child_derB->deepCopy()); - + derivative = new ASTNode(AST_PLUS); derivative->addChild(term1->deepCopy()); derivative->addChild(term2->deepCopy()); - } derivative->decompose(); @@ -4477,8 +4537,8 @@ ASTNode::derivativeTimes(const std::string& variable) return derivative; } -ASTNode* -ASTNode::derivativeDivide(const std::string& variable) +ASTNode * +ASTNode::derivativeDivide(const std::string &variable) { ASTNode *copy = deepCopy(); copy->decompose(); @@ -4486,18 +4546,18 @@ ASTNode::derivativeDivide(const std::string& variable) zero->setValue(0.0); ASTNode *two = new ASTNode(AST_REAL); two->setValue(2.0); - ASTNode * derivative = NULL; - ASTNode * nominator = NULL; - ASTNode * term1 = NULL; - ASTNode * term2 = NULL; + ASTNode *derivative = NULL; + ASTNode *nominator = NULL; + ASTNode *term1 = NULL; + ASTNode *term2 = NULL; // d(A/B)/dx = (B * dA/dx - A * dB/dx)/B^2 ASTNode *denominator = new ASTNode(AST_POWER); denominator->addChild(copy->getChild(1)->deepCopy()); denominator->addChild(two->deepCopy()); - ASTNode* child_derA = copy->getChild(0)->derivative(variable); - ASTNode* child_derB = copy->getChild(1)->derivative(variable); + ASTNode *child_derA = copy->getChild(0)->derivative(variable); + ASTNode *child_derB = copy->getChild(1)->derivative(variable); if (child_derB && child_derB->exactlyEqual(*zero)) { nominator = new ASTNode(AST_TIMES); @@ -4509,7 +4569,7 @@ ASTNode::derivativeDivide(const std::string& variable) term1 = new ASTNode(AST_TIMES); term1->addChild(copy->getChild(0)->deepCopy()); term1->addChild(child_derB->deepCopy()); - + nominator = new ASTNode(AST_MINUS); nominator->addChild(term1->deepCopy()); } @@ -4524,25 +4584,25 @@ ASTNode::derivativeDivide(const std::string& variable) } else if (child_derB == NULL) { - term1 = new ASTNode(AST_TIMES); - term1->addChild(copy->getChild(1)->deepCopy()); - term1->addChild(child_derA->deepCopy()); + term1 = new ASTNode(AST_TIMES); + term1->addChild(copy->getChild(1)->deepCopy()); + term1->addChild(child_derA->deepCopy()); - nominator = term1->deepCopy(); + nominator = term1->deepCopy(); } else { - term1 = new ASTNode(AST_TIMES); - term1->addChild(copy->getChild(1)->deepCopy()); - term1->addChild(child_derA->deepCopy()); + term1 = new ASTNode(AST_TIMES); + term1->addChild(copy->getChild(1)->deepCopy()); + term1->addChild(child_derA->deepCopy()); - term2 = new ASTNode(AST_TIMES); - term2->addChild(copy->getChild(0)->deepCopy()); - term2->addChild(child_derB->deepCopy()); + term2 = new ASTNode(AST_TIMES); + term2->addChild(copy->getChild(0)->deepCopy()); + term2->addChild(child_derB->deepCopy()); - nominator = new ASTNode(AST_MINUS); - nominator->addChild(term1->deepCopy()); - nominator->addChild(term2->deepCopy()); + nominator = new ASTNode(AST_MINUS); + nominator->addChild(term1->deepCopy()); + nominator->addChild(term2->deepCopy()); } derivative = new ASTNode(AST_DIVIDE); @@ -4563,8 +4623,8 @@ ASTNode::derivativeDivide(const std::string& variable) return derivative; } -ASTNode* -ASTNode::derivativePower(const std::string& variable) +ASTNode * +ASTNode::derivativePower(const std::string &variable) { ASTNode *copy = deepCopy(); copy->decompose(); @@ -4572,12 +4632,12 @@ ASTNode::derivativePower(const std::string& variable) ASTNode *mult = new ASTNode(AST_REAL); ASTNode *power = new ASTNode(AST_POWER); - ASTNode * derivative = NULL; + ASTNode *derivative = NULL; // dA^n/dx where n is number = nA^(n-1) if (copy->getChild(1)->isNumber()) - { - ASTNode* A = copy->getChild(0); + { + ASTNode *A = copy->getChild(0); double n = copy->getChild(1)->getValue(); exp->setValue(n - 1); power->addChild(A->deepCopy()); @@ -4599,307 +4659,1328 @@ ASTNode::derivativePower(const std::string& variable) return derivative; } -ASTNode* -ASTNode::derivativeLog(const std::string& variable) +ASTNode * +ASTNode::derivativeLog(const std::string &variable) { ASTNode *copy = deepCopy(); copy->decompose(); - ASTNode * derivative = NULL; + ASTNode *derivative = NULL; - //d(log(base, x)/dx = 1/(ln(base) * x) - //d(log(base,A)/dx = dA/dx / (ln(base) *A) + // d(log(base, x)/dx = 1/(ln(base) * x) + // d(log(base,A)/dx = dA/dx / (ln(base) *A) // in log function child0 is base if (getChild(1)->derivative(variable) != NULL) { - ASTNode* ln = new ASTNode(AST_FUNCTION_LN); - ASTNode* number = new ASTNode(AST_REAL); - number->setValue((double)(copy->getChild(0)->getValue())); - ln->addChild(number->deepCopy()); + ASTNode *ln = new ASTNode(AST_FUNCTION_LN); + ASTNode *number = new ASTNode(AST_REAL); + number->setValue((double)(copy->getChild(0)->getValue())); + ln->addChild(number->deepCopy()); - ASTNode* times = new ASTNode(AST_TIMES); - times->addChild(ln->deepCopy()); - times->addChild(copy->getChild(1)->deepCopy()); + ASTNode *times = new ASTNode(AST_TIMES); + times->addChild(ln->deepCopy()); + times->addChild(copy->getChild(1)->deepCopy()); - derivative = new ASTNode(AST_DIVIDE); - derivative->addChild(getChild(1)->derivative(variable)); - derivative->addChild(times->deepCopy()); + derivative = new ASTNode(AST_DIVIDE); + derivative->addChild(getChild(1)->derivative(variable)); + derivative->addChild(times->deepCopy()); + derivative->decompose(); - derivative->decompose(); + delete number; + delete ln; + delete times; + } + delete copy; + return derivative; +} +ASTNode * +ASTNode::derivativeLn(const std::string &variable) +{ + ASTNode *copy = deepCopy(); + copy->decompose(); + ASTNode *derivative = NULL; + + // d(ln(x)/dx = 1/(x) + // d(ln(A)/dx = dA/dx / (A) - delete number; - delete ln; - delete times; + if (getChild(0)->derivative(variable) != NULL) + { + derivative = new ASTNode(AST_DIVIDE); + derivative->addChild(getChild(0)->derivative(variable)); + derivative->addChild(getChild(0)->deepCopy()); + + derivative->decompose(); } delete copy; return derivative; } -ASTNode* -ASTNode::derivativeLn(const std::string& variable) +ASTNode * +ASTNode::derivativeExp(const std::string &variable) { ASTNode *copy = deepCopy(); copy->decompose(); - ASTNode * derivative = NULL; + ASTNode *derivative = NULL; + + // d(exp(x)/dx = exp(x) + // d(exp(A)/dx = dA/dx * exp(A) + + if (getChild(0)->derivative(variable) != NULL) + { + derivative = new ASTNode(AST_TIMES); + derivative->addChild(getChild(0)->derivative(variable)); + derivative->addChild(copy->deepCopy()); + + derivative->decompose(); + } + delete copy; + return derivative; +} + +ASTNode * +ASTNode::derivativeAbs(const std::string &variable) +{ + ASTNode *copy = deepCopy(); + copy->decompose(); + ASTNode *derivative = NULL; + ASTNode *one = new ASTNode(AST_REAL); + one->setValue(1.0); + ASTNode *divide = new ASTNode(AST_DIVIDE); + + // d(abs(x)/dx = x/abs(x) + // d(abs(A)/dx = dA/dx * (A/abs(A)) - //d(ln(x)/dx = 1/(x) - //d(ln(A)/dx = dA/dx / (A) - if (getChild(0)->derivative(variable) != NULL) { + if (getChild(0)->derivative(variable)->exactlyEqual(*one)) + { derivative = new ASTNode(AST_DIVIDE); - derivative->addChild(getChild(0)->derivative(variable)); derivative->addChild(getChild(0)->deepCopy()); + derivative->addChild(copy->deepCopy()); + + derivative->decompose(); + } + else + { + derivative = new ASTNode(AST_TIMES); + + divide->addChild(getChild(0)->deepCopy()); + divide->addChild(copy->deepCopy()); + derivative->addChild(getChild(0)->derivative(variable)->deepCopy()); + derivative->addChild(divide->deepCopy()); derivative->decompose(); + } } delete copy; + delete one; + delete divide; return derivative; } -ASTNode* -ASTNode::derivativeExp(const std::string& variable) +ASTNode * +ASTNode::derivativeArccos(const std::string &variable) { + ASTNode *copy = deepCopy(); copy->decompose(); - ASTNode * derivative = NULL; + ASTNode *derivative = NULL; + ASTNode *minusOne = new ASTNode(AST_REAL); + minusOne->setValue(-1.0); + ASTNode *two = new ASTNode(AST_REAL); + two->setValue(2.0); + ASTNode *one = new ASTNode(AST_REAL); + one->setValue(1.0); + ASTNode *minus_half = new ASTNode(AST_REAL); + minus_half->setValue(-0.5); - //d(exp(x)/dx = exp(x) - //d(exp(A)/dx = dA/dx * exp(A) + ASTNode *sqrt = new ASTNode(AST_FUNCTION_POWER); + ASTNode *bracket_minus = new ASTNode(AST_MINUS); - if (getChild(0)->derivative(variable) != NULL) + // d(arccos(x)/dx = -1/sqrt(1-x^2) + // d(arccos(A)/dx = dA/dx * -1/sqrt(1-A^2) + + ASTNode *derivA = getChild(0)->derivative(variable); + + if (derivA != NULL) { - derivative = new ASTNode(AST_TIMES); - derivative->addChild(getChild(0)->derivative(variable)); - derivative->addChild(copy->deepCopy()); + ASTNode *Asquared = new ASTNode(AST_POWER); + Asquared->addChild(getChild(0)->deepCopy()); + Asquared->addChild(two->deepCopy()); - derivative->decompose(); + bracket_minus->addChild(one->deepCopy()); + bracket_minus->addChild(Asquared->deepCopy()); + + sqrt->addChild(bracket_minus->deepCopy()); + sqrt->addChild(minus_half->deepCopy()); + + derivative = new ASTNode(AST_TIMES); + derivative->addChild(derivA->deepCopy()); + derivative->addChild(minusOne->deepCopy()); + derivative->addChild(sqrt->deepCopy()); + + derivative->decompose(); + + delete Asquared; } delete copy; + delete minusOne; + delete two; + delete bracket_minus; + delete minus_half; + delete one; + delete derivA; return derivative; } +ASTNode * +ASTNode::derivativeArccosh(const std::string &variable) -ASTNode* -ASTNode::derivativeAbs(const std::string& variable) { - ASTNode* copy = deepCopy(); - copy->decompose(); - ASTNode* derivative = NULL; - ASTNode* one = new ASTNode(AST_REAL); - one->setValue(1.0); - ASTNode* divide = new ASTNode(AST_DIVIDE); - //d(abs(x)/dx = x/abs(x) - //d(abs(A)/dx = dA/dx * (A/abs(A)) + ASTNode *copy = deepCopy(); + copy->decompose(); + ASTNode *derivative = NULL; + ASTNode *two = new ASTNode(AST_REAL); + two->setValue(2.0); + ASTNode *one = new ASTNode(AST_REAL); + one->setValue(1.0); + ASTNode *minus_half = new ASTNode(AST_REAL); + minus_half->setValue(-0.5); + + ASTNode *sqrt = new ASTNode(AST_FUNCTION_POWER); + ASTNode *bracket_minus = new ASTNode(AST_MINUS); - if (getChild(0)->derivative(variable) != NULL) - { - if (getChild(0)->derivative(variable)->exactlyEqual(*one)) - { - derivative = new ASTNode(AST_DIVIDE); - derivative->addChild(getChild(0)->deepCopy()); - derivative->addChild(copy->deepCopy()); + // d(arccosh(x)/dx = 1/sqrt(x^2-1) + // d(arccosh(A)/dx = dA/dx * 1/sqrt(A^2-1) - derivative->decompose(); - } - else - { - derivative = new ASTNode(AST_TIMES); + ASTNode *derivA = getChild(0)->derivative(variable); + + if (derivA != NULL) + { + ASTNode *Asquared = new ASTNode(AST_POWER); + Asquared->addChild(getChild(0)->deepCopy()); + Asquared->addChild(two->deepCopy()); - divide->addChild(getChild(0)->deepCopy()); - divide->addChild(copy->deepCopy()); + bracket_minus->addChild(Asquared->deepCopy()); + bracket_minus->addChild(one->deepCopy()); - derivative->addChild(getChild(0)->derivative(variable)->deepCopy()); - derivative->addChild(divide->deepCopy()); + sqrt->addChild(bracket_minus->deepCopy()); + sqrt->addChild(minus_half->deepCopy()); - derivative->decompose(); - } - } - delete copy; - delete one; - delete divide; - return derivative; + derivative = new ASTNode(AST_TIMES); + derivative->addChild(derivA->deepCopy()); + derivative->addChild(sqrt->deepCopy()); + + derivative->decompose(); + + delete Asquared; + } + delete copy; + delete two; + delete bracket_minus; + delete minus_half; + delete one; + delete derivA; + return derivative; } -ASTNode* -ASTNode::derivativeArccos(const std::string& variable) +ASTNode * +ASTNode::derivativeArccot(const std::string &variable) + { - ASTNode* copy = deepCopy(); - copy->decompose(); - ASTNode* derivative = NULL; - ASTNode* minusOne = new ASTNode(AST_REAL); - minusOne->setValue(-1.0); - ASTNode* two = new ASTNode(AST_REAL); - two->setValue(2.0); - ASTNode* one = new ASTNode(AST_REAL); - one->setValue(1.0); - ASTNode* minus_half = new ASTNode(AST_REAL); - minus_half->setValue(-0.5); + ASTNode *copy = deepCopy(); + copy->decompose(); + ASTNode *derivative = NULL; + ASTNode *two = new ASTNode(AST_REAL); + two->setValue(2.0); + ASTNode *one = new ASTNode(AST_REAL); + one->setValue(1.0); + ASTNode *minusOne = new ASTNode(AST_REAL); + minusOne->setValue(-1.0); + ASTNode *minus_one = new ASTNode(AST_REAL); + minus_one->setValue(-1.0); - ASTNode* sqrt = new ASTNode(AST_FUNCTION_POWER); - ASTNode* bracket_minus = new ASTNode(AST_MINUS); + ASTNode *power = new ASTNode(AST_FUNCTION_POWER); + ASTNode *bracket_plus = new ASTNode(AST_PLUS); - //d(arccos(x)/dx = -1/sqrt(1-x^2) - //d(arccos(A)/dx = dA/dx * -1/sqrt(1-A^2) + // d(arccot(x)/dx = -1/(1+x^2) + // d(arccot(A)/dx = dA/dx * -1/(1+A^2) - ASTNode* derivA = getChild(0)->derivative(variable); + ASTNode *derivA = getChild(0)->derivative(variable); - if (derivA != NULL) - { - ASTNode* Asquared = new ASTNode(AST_POWER); - Asquared->addChild(getChild(0)->deepCopy()); - Asquared->addChild(two->deepCopy()); + if (derivA != NULL) + { + ASTNode *Asquared = new ASTNode(AST_POWER); + Asquared->addChild(getChild(0)->deepCopy()); + Asquared->addChild(two->deepCopy()); - bracket_minus->addChild(one->deepCopy()); - bracket_minus->addChild(Asquared->deepCopy()); + bracket_plus->addChild(one->deepCopy()); + bracket_plus->addChild(Asquared->deepCopy()); - sqrt->addChild(bracket_minus->deepCopy()); - sqrt->addChild(minus_half->deepCopy()); + power->addChild(bracket_plus->deepCopy()); + power->addChild(minus_one->deepCopy()); - derivative = new ASTNode(AST_TIMES); - derivative->addChild(derivA->deepCopy()); - derivative->addChild(minusOne->deepCopy()); - derivative->addChild(sqrt->deepCopy()); + derivative = new ASTNode(AST_TIMES); + derivative->addChild(derivA->deepCopy()); + derivative->addChild(minusOne->deepCopy()); + derivative->addChild(power->deepCopy()); - derivative->decompose(); + derivative->decompose(); - delete Asquared; - } - delete copy; - delete minusOne; - delete two; - delete bracket_minus; - delete minus_half; - delete one; - delete derivA; - return derivative; + delete Asquared; + } + delete copy; + delete two; + delete one; + delete minusOne; + delete minus_one; + delete bracket_plus; + delete power; + delete derivA; + return derivative; } -ASTNode* -ASTNode::derivativeArcsin(const std::string& variable) + +ASTNode * +ASTNode::derivativeArccoth(const std::string &variable) + { - ASTNode* copy = deepCopy(); - copy->decompose(); - ASTNode* derivative = NULL; - ASTNode* two = new ASTNode(AST_REAL); - two->setValue(2.0); - ASTNode* one = new ASTNode(AST_REAL); - one->setValue(1.0); - ASTNode* minus_half = new ASTNode(AST_REAL); - minus_half->setValue(-0.5); - ASTNode* sqrt = new ASTNode(AST_FUNCTION_POWER); - ASTNode* bracket_minus = new ASTNode(AST_MINUS); + ASTNode *copy = deepCopy(); + copy->decompose(); + ASTNode *derivative = NULL; + ASTNode *two = new ASTNode(AST_REAL); + two->setValue(2.0); + ASTNode *one = new ASTNode(AST_REAL); + one->setValue(1.0); + ASTNode *minus_one = new ASTNode(AST_REAL); + minus_one->setValue(-1.0); - //d(arcsin(x)/dx = 1/sqrt(1-x^2) - //d(arcsin(A)/dx = dA/dx * 1/sqrt(1-A^2) + ASTNode *power = new ASTNode(AST_FUNCTION_POWER); + ASTNode *bracket_minus = new ASTNode(AST_MINUS); - ASTNode* derivA = getChild(0)->derivative(variable); + // d(arccoth(x)/dx = 1/(1-x^2) + // d(arccoth(A)/dx = dA/dx * 1/(1-A^2) - if (derivA != NULL) - { - ASTNode* Asquared = new ASTNode(AST_POWER); - Asquared->addChild(getChild(0)->deepCopy()); - Asquared->addChild(two->deepCopy()); + ASTNode *derivA = getChild(0)->derivative(variable); - bracket_minus->addChild(one->deepCopy()); - bracket_minus->addChild(Asquared->deepCopy()); + if (derivA != NULL) + { + ASTNode *Asquared = new ASTNode(AST_POWER); + Asquared->addChild(getChild(0)->deepCopy()); + Asquared->addChild(two->deepCopy()); - sqrt->addChild(bracket_minus->deepCopy()); - sqrt->addChild(minus_half->deepCopy()); + bracket_minus->addChild(one->deepCopy()); + bracket_minus->addChild(Asquared->deepCopy()); - derivative = new ASTNode(AST_TIMES); - derivative->addChild(derivA->deepCopy()); - derivative->addChild(sqrt->deepCopy()); + power->addChild(bracket_minus->deepCopy()); + power->addChild(minus_one->deepCopy()); - derivative->decompose(); + derivative = new ASTNode(AST_TIMES); + derivative->addChild(derivA->deepCopy()); + derivative->addChild(power->deepCopy()); - delete Asquared; - } - delete copy; - delete two; - delete bracket_minus; - delete minus_half; - delete one; - delete derivA; - return derivative; + derivative->decompose(); + delete Asquared; + } + delete copy; + delete two; + delete one; + delete minus_one; + delete bracket_minus; + delete power; + delete derivA; + return derivative; } -ASTNode* -ASTNode::derivativeArctan(const std::string& variable) -{ - ASTNode* copy = deepCopy(); - copy->decompose(); - ASTNode* derivative = NULL; - ASTNode* two = new ASTNode(AST_REAL); - two->setValue(2.0); - ASTNode* one = new ASTNode(AST_REAL); - one->setValue(1.0); - ASTNode* minus_one = new ASTNode(AST_REAL); - minus_one->setValue(-1.0); - - ASTNode* power = new ASTNode(AST_FUNCTION_POWER); - ASTNode* bracket_plus = new ASTNode(AST_PLUS); - - //d(arctan(x)/dx = 1/(1+x^2) - //d(arctan(A)/dx = dA/dx * 1/(1+A^2) - - ASTNode* derivA = getChild(0)->derivative(variable); - - if (derivA != NULL) - { - ASTNode* Asquared = new ASTNode(AST_POWER); - Asquared->addChild(getChild(0)->deepCopy()); - Asquared->addChild(two->deepCopy()); +ASTNode * +ASTNode::derivativeArccsc(const std::string &variable) - bracket_plus->addChild(one->deepCopy()); - bracket_plus->addChild(Asquared->deepCopy()); +{ - power->addChild(bracket_plus->deepCopy()); - power->addChild(minus_one->deepCopy()); + ASTNode *copy = deepCopy(); + copy->decompose(); + ASTNode *derivative = NULL; + ASTNode *two = new ASTNode(AST_REAL); + two->setValue(2.0); + ASTNode *one = new ASTNode(AST_REAL); + one->setValue(1.0); + ASTNode *minusOne = new ASTNode(AST_REAL); + minusOne->setValue(-1.0); + ASTNode *minus_half = new ASTNode(AST_REAL); + minus_half->setValue(-0.5); + ASTNode *minus_one = new ASTNode(AST_REAL); + minus_one->setValue(-1.0); - derivative = new ASTNode(AST_TIMES); - derivative->addChild(derivA->deepCopy()); - derivative->addChild(power->deepCopy()); + ASTNode *sqrt = new ASTNode(AST_FUNCTION_POWER); + ASTNode *bracket_minus = new ASTNode(AST_MINUS); + ASTNode *Apower = new ASTNode(AST_FUNCTION_POWER); - derivative->decompose(); + // d(arccsc(x)/dx = -1/(x*sqrt(x^2-1)) + // d(arccsc(A)/dx = dA/dx * -1/(A*sqrt(A^2-1)) - delete Asquared; - } - delete copy; - delete two; - delete one; - delete minus_one; - delete bracket_plus; - delete power; - delete derivA; - return derivative; -} + ASTNode *derivA = getChild(0)->derivative(variable); + if (derivA != NULL) + { + ASTNode *Asquared = new ASTNode(AST_POWER); + Asquared->addChild(getChild(0)->deepCopy()); + Asquared->addChild(two->deepCopy()); + bracket_minus->addChild(Asquared->deepCopy()); + bracket_minus->addChild(one->deepCopy()); + sqrt->addChild(bracket_minus->deepCopy()); + sqrt->addChild(minus_half->deepCopy()); -XMLNamespaces* -ASTNode::getDeclaredNamespaces() const -{ - return mNamespaces; + Apower->addChild(getChild(0)->deepCopy()); + Apower->addChild(minus_one->deepCopy()); + + derivative = new ASTNode(AST_TIMES); + derivative->addChild(derivA->deepCopy()); + derivative->addChild(minusOne->deepCopy()); + derivative->addChild(Apower->deepCopy()); + derivative->addChild(sqrt->deepCopy()); + + derivative->decompose(); + + delete Asquared; + } + delete copy; + delete two; + delete one; + delete minusOne; + delete bracket_minus; + delete minus_half; + delete minus_one; + delete Apower; + delete derivA; + return derivative; } +ASTNode * +ASTNode::derivativeArccsch(const std::string &variable) -void -ASTNode::setDeclaredNamespaces(const XMLNamespaces* xmlns) { - mNamespaces = xmlns->clone(); + + ASTNode *copy = deepCopy(); + copy->decompose(); + ASTNode *derivative = NULL; + ASTNode *two = new ASTNode(AST_REAL); + two->setValue(2.0); + ASTNode *one = new ASTNode(AST_REAL); + one->setValue(1.0); + ASTNode *minusOne = new ASTNode(AST_REAL); + minusOne->setValue(-1.0); + ASTNode *minus_half = new ASTNode(AST_REAL); + minus_half->setValue(-0.5); + ASTNode *minus_one = new ASTNode(AST_REAL); + minus_one->setValue(-1.0); + + ASTNode *sqrt = new ASTNode(AST_FUNCTION_POWER); + ASTNode *bracket_plus = new ASTNode(AST_PLUS); + ASTNode *Apower = new ASTNode(AST_FUNCTION_POWER); + + // d(arccsch(x)/dx = -1/(x*sqrt(1+x^2)) + // d(arccsch(A)/dx = dA/dx * -1/(A*sqrt(1+A^2)) + + ASTNode *derivA = getChild(0)->derivative(variable); + + if (derivA != NULL) + { + ASTNode *Asquared = new ASTNode(AST_POWER); + Asquared->addChild(getChild(0)->deepCopy()); + Asquared->addChild(two->deepCopy()); + + bracket_plus->addChild(one->deepCopy()); + bracket_plus->addChild(Asquared->deepCopy()); + + sqrt->addChild(bracket_plus->deepCopy()); + sqrt->addChild(minus_half->deepCopy()); + + Apower->addChild(getChild(0)->deepCopy()); + Apower->addChild(minus_one->deepCopy()); + + derivative = new ASTNode(AST_TIMES); + derivative->addChild(derivA->deepCopy()); + derivative->addChild(minusOne->deepCopy()); + derivative->addChild(Apower->deepCopy()); + derivative->addChild(sqrt->deepCopy()); + + derivative->decompose(); + + delete Asquared; + } + delete copy; + delete two; + delete one; + delete minusOne; + delete bracket_plus; + delete minus_half; + delete minus_one; + delete Apower; + delete derivA; + return derivative; } +ASTNode * +ASTNode::derivativeArcsec(const std::string &variable) -void -ASTNode::unsetDeclaredNamespaces() +{ + + ASTNode *copy = deepCopy(); + copy->decompose(); + ASTNode *derivative = NULL; + ASTNode *two = new ASTNode(AST_REAL); + two->setValue(2.0); + ASTNode *one = new ASTNode(AST_REAL); + one->setValue(1.0); + ASTNode *minus_half = new ASTNode(AST_REAL); + minus_half->setValue(-0.5); + ASTNode *minus_one = new ASTNode(AST_REAL); + minus_one->setValue(-1.0); + + ASTNode *sqrt = new ASTNode(AST_FUNCTION_POWER); + ASTNode *bracket_minus = new ASTNode(AST_MINUS); + ASTNode *Apower = new ASTNode(AST_FUNCTION_POWER); + + // d(arcsec(x)/dx = 1/(x*sqrt(x^2-1)) + // d(arcsec(A)/dx = dA/dx * 1/(A*sqrt(A^2-1)) + + ASTNode *derivA = getChild(0)->derivative(variable); + + if (derivA != NULL) + { + ASTNode *Asquared = new ASTNode(AST_POWER); + Asquared->addChild(getChild(0)->deepCopy()); + Asquared->addChild(two->deepCopy()); + + bracket_minus->addChild(Asquared->deepCopy()); + bracket_minus->addChild(one->deepCopy()); + + sqrt->addChild(bracket_minus->deepCopy()); + sqrt->addChild(minus_half->deepCopy()); + + Apower->addChild(getChild(0)->deepCopy()); + Apower->addChild(minus_one->deepCopy()); + + derivative = new ASTNode(AST_TIMES); + derivative->addChild(derivA->deepCopy()); + derivative->addChild(Apower->deepCopy()); + derivative->addChild(sqrt->deepCopy()); + + derivative->decompose(); + + delete Asquared; + } + delete copy; + delete two; + delete one; + delete bracket_minus; + delete minus_half; + delete minus_one; + delete Apower; + delete derivA; + return derivative; +} + +ASTNode * +ASTNode::derivativeArcsech(const std::string &variable) + +{ + + ASTNode *copy = deepCopy(); + copy->decompose(); + ASTNode *derivative = NULL; + ASTNode *two = new ASTNode(AST_REAL); + two->setValue(2.0); + ASTNode *one = new ASTNode(AST_REAL); + one->setValue(1.0); + ASTNode *minusOne = new ASTNode(AST_REAL); + minusOne->setValue(-1.0); + ASTNode *minus_half = new ASTNode(AST_REAL); + minus_half->setValue(-0.5); + ASTNode *minus_one = new ASTNode(AST_REAL); + minus_one->setValue(-1.0); + + ASTNode *sqrt = new ASTNode(AST_FUNCTION_POWER); + ASTNode *bracket_minus = new ASTNode(AST_MINUS); + ASTNode *Apower = new ASTNode(AST_FUNCTION_POWER); + + // d(arcsech(x)/dx = -1/(x*sqrt(1-x^2)) + // d(arcsech(A)/dx = dA/dx * -1/(A*sqrt(1-A^2)) + + ASTNode *derivA = getChild(0)->derivative(variable); + + if (derivA != NULL) + { + ASTNode *Asquared = new ASTNode(AST_POWER); + Asquared->addChild(getChild(0)->deepCopy()); + Asquared->addChild(two->deepCopy()); + + bracket_minus->addChild(one->deepCopy()); + bracket_minus->addChild(Asquared->deepCopy()); + + sqrt->addChild(bracket_minus->deepCopy()); + sqrt->addChild(minus_half->deepCopy()); + + Apower->addChild(getChild(0)->deepCopy()); + Apower->addChild(minus_one->deepCopy()); + + derivative = new ASTNode(AST_TIMES); + derivative->addChild(derivA->deepCopy()); + derivative->addChild(minusOne->deepCopy()); + derivative->addChild(Apower->deepCopy()); + derivative->addChild(sqrt->deepCopy()); + + derivative->decompose(); + + delete Asquared; + } + delete copy; + delete two; + delete one; + delete minusOne; + delete bracket_minus; + delete minus_half; + delete minus_one; + delete Apower; + delete derivA; + return derivative; +} + +ASTNode * +ASTNode::derivativeArcsin(const std::string &variable) +{ + ASTNode *copy = deepCopy(); + copy->decompose(); + ASTNode *derivative = NULL; + ASTNode *two = new ASTNode(AST_REAL); + two->setValue(2.0); + ASTNode *one = new ASTNode(AST_REAL); + one->setValue(1.0); + ASTNode *minus_half = new ASTNode(AST_REAL); + minus_half->setValue(-0.5); + + ASTNode *sqrt = new ASTNode(AST_FUNCTION_POWER); + ASTNode *bracket_minus = new ASTNode(AST_MINUS); + + // d(arcsin(x)/dx = 1/sqrt(1-x^2) + // d(arcsin(A)/dx = dA/dx * 1/sqrt(1-A^2) + + ASTNode *derivA = getChild(0)->derivative(variable); + + if (derivA != NULL) + { + ASTNode *Asquared = new ASTNode(AST_POWER); + Asquared->addChild(getChild(0)->deepCopy()); + Asquared->addChild(two->deepCopy()); + + bracket_minus->addChild(one->deepCopy()); + bracket_minus->addChild(Asquared->deepCopy()); + + sqrt->addChild(bracket_minus->deepCopy()); + sqrt->addChild(minus_half->deepCopy()); + + derivative = new ASTNode(AST_TIMES); + derivative->addChild(derivA->deepCopy()); + derivative->addChild(sqrt->deepCopy()); + + derivative->decompose(); + + delete Asquared; + } + delete copy; + delete two; + delete bracket_minus; + delete minus_half; + delete one; + delete derivA; + return derivative; +} + +ASTNode * +ASTNode::derivativeArcsinh(const std::string &variable) + +{ + + ASTNode *copy = deepCopy(); + copy->decompose(); + ASTNode *derivative = NULL; + ASTNode *two = new ASTNode(AST_REAL); + two->setValue(2.0); + ASTNode *one = new ASTNode(AST_REAL); + one->setValue(1.0); + ASTNode *minus_half = new ASTNode(AST_REAL); + minus_half->setValue(-0.5); + + ASTNode *sqrt = new ASTNode(AST_FUNCTION_POWER); + ASTNode *bracket_plus = new ASTNode(AST_PLUS); + + // d(arcsinh(x)/dx = 1/sqrt(1+x^2) + // d(arcsinh(A)/dx = dA/dx * 1/sqrt(1+A^2) + + ASTNode *derivA = getChild(0)->derivative(variable); + + if (derivA != NULL) + { + ASTNode *Asquared = new ASTNode(AST_POWER); + Asquared->addChild(getChild(0)->deepCopy()); + Asquared->addChild(two->deepCopy()); + + bracket_plus->addChild(one->deepCopy()); + bracket_plus->addChild(Asquared->deepCopy()); + + sqrt->addChild(bracket_plus->deepCopy()); + sqrt->addChild(minus_half->deepCopy()); + + derivative = new ASTNode(AST_TIMES); + derivative->addChild(derivA->deepCopy()); + derivative->addChild(sqrt->deepCopy()); + + derivative->decompose(); + + delete Asquared; + } + delete copy; + delete two; + delete bracket_plus; + delete minus_half; + delete one; + delete derivA; + return derivative; +} + +ASTNode * +ASTNode::derivativeArctan(const std::string &variable) +{ + ASTNode *copy = deepCopy(); + copy->decompose(); + ASTNode *derivative = NULL; + ASTNode *two = new ASTNode(AST_REAL); + two->setValue(2.0); + ASTNode *one = new ASTNode(AST_REAL); + one->setValue(1.0); + ASTNode *minus_one = new ASTNode(AST_REAL); + minus_one->setValue(-1.0); + + ASTNode *power = new ASTNode(AST_FUNCTION_POWER); + ASTNode *bracket_plus = new ASTNode(AST_PLUS); + + // d(arctan(x)/dx = 1/(1+x^2) + // d(arctan(A)/dx = dA/dx * 1/(1+A^2) + + ASTNode *derivA = getChild(0)->derivative(variable); + + if (derivA != NULL) + { + ASTNode *Asquared = new ASTNode(AST_POWER); + Asquared->addChild(getChild(0)->deepCopy()); + Asquared->addChild(two->deepCopy()); + + bracket_plus->addChild(one->deepCopy()); + bracket_plus->addChild(Asquared->deepCopy()); + + power->addChild(bracket_plus->deepCopy()); + power->addChild(minus_one->deepCopy()); + + derivative = new ASTNode(AST_TIMES); + derivative->addChild(derivA->deepCopy()); + derivative->addChild(power->deepCopy()); + + derivative->decompose(); + + delete Asquared; + } + delete copy; + delete two; + delete one; + delete minus_one; + delete bracket_plus; + delete power; + delete derivA; + return derivative; +} + +ASTNode * +ASTNode::derivativeArctanh(const std::string &variable) + +{ + + ASTNode *copy = deepCopy(); + copy->decompose(); + ASTNode *derivative = NULL; + ASTNode *two = new ASTNode(AST_REAL); + two->setValue(2.0); + ASTNode *one = new ASTNode(AST_REAL); + one->setValue(1.0); + ASTNode *minus_one = new ASTNode(AST_REAL); + minus_one->setValue(-1.0); + + ASTNode *power = new ASTNode(AST_FUNCTION_POWER); + ASTNode *bracket_minus = new ASTNode(AST_MINUS); + + // d(arctanh(x)/dx = 1/(1-x^2) + // d(arctanh(A)/dx = dA/dx * 1/(1-A^2) + + ASTNode *derivA = getChild(0)->derivative(variable); + + if (derivA != NULL) + { + ASTNode *Asquared = new ASTNode(AST_POWER); + Asquared->addChild(getChild(0)->deepCopy()); + Asquared->addChild(two->deepCopy()); + + bracket_minus->addChild(one->deepCopy()); + bracket_minus->addChild(Asquared->deepCopy()); + + power->addChild(bracket_minus->deepCopy()); + power->addChild(minus_one->deepCopy()); + + derivative = new ASTNode(AST_TIMES); + derivative->addChild(derivA->deepCopy()); + derivative->addChild(power->deepCopy()); + + derivative->decompose(); + + delete Asquared; + } + delete copy; + delete two; + delete one; + delete minus_one; + delete bracket_minus; + delete power; + delete derivA; + return derivative; +} + +ASTNode * +ASTNode::derivativeCos(const std::string &variable) + +{ + + ASTNode *copy = deepCopy(); + copy->decompose(); + ASTNode *derivative = NULL; + ASTNode *minusOne = new ASTNode(AST_REAL); + minusOne->setValue(-1.0); + + // d(cos(x)/dx = -sin(x) + // d(cos(A)/dx = dA/dx * -sin(A) + + ASTNode *derivA = getChild(0)->derivative(variable); + + if (derivA != NULL) + { + ASTNode *sinA = new ASTNode(AST_FUNCTION_SIN); + sinA->addChild(getChild(0)->deepCopy()); + + derivative = new ASTNode(AST_TIMES); + derivative->addChild(derivA->deepCopy()); + derivative->addChild(minusOne->deepCopy()); + derivative->addChild(sinA->deepCopy()); + + derivative->decompose(); + + delete sinA; + } + delete copy; + delete minusOne; + delete derivA; + return derivative; +} + +ASTNode * +ASTNode::derivativeCosh(const std::string &variable) + +{ + + ASTNode *copy = deepCopy(); + copy->decompose(); + ASTNode *derivative = NULL; + + // d(cosh(x)/dx = sinh(x) + // d(cosh(A)/dx = dA/dx * sinh(A) + + ASTNode *derivA = getChild(0)->derivative(variable); + + if (derivA != NULL) + { + ASTNode *sinhA = new ASTNode(AST_FUNCTION_SINH); + sinhA->addChild(getChild(0)->deepCopy()); + + derivative = new ASTNode(AST_TIMES); + derivative->addChild(derivA->deepCopy()); + derivative->addChild(sinhA->deepCopy()); + + derivative->decompose(); + + delete sinhA; + } + delete copy; + delete derivA; + return derivative; +} + +ASTNode * +ASTNode::derivativeCot(const std::string &variable) + +{ + + ASTNode *copy = deepCopy(); + copy->decompose(); + ASTNode *derivative = NULL; + ASTNode *two = new ASTNode(AST_REAL); + two->setValue(2.0); + ASTNode *minusOne = new ASTNode(AST_REAL); + minusOne->setValue(-1.0); + ASTNode *minus_two = new ASTNode(AST_REAL); + minus_two->setValue(-2.0); + + // d(cot(x)/dx = -1/sin^2(x) = -csc^2(x) + // d(cot(A)/dx = dA/dx * -1/sin^2(A) + + ASTNode *derivA = getChild(0)->derivative(variable); + + if (derivA != NULL) + { + ASTNode *sinA = new ASTNode(AST_FUNCTION_SIN); + sinA->addChild(getChild(0)->deepCopy()); + + ASTNode *sinAsquared = new ASTNode(AST_FUNCTION_POWER); + sinAsquared->addChild(sinA->deepCopy()); + sinAsquared->addChild(minus_two->deepCopy()); + + derivative = new ASTNode(AST_TIMES); + derivative->addChild(derivA->deepCopy()); + derivative->addChild(minusOne->deepCopy()); + derivative->addChild(sinAsquared->deepCopy()); + + derivative->decompose(); + + delete sinA; + delete sinAsquared; + } + delete copy; + delete two; + delete minusOne; + delete minus_two; + delete derivA; + return derivative; +} + +ASTNode * +ASTNode::derivativeCoth(const std::string &variable) + +{ + + ASTNode *copy = deepCopy(); + copy->decompose(); + ASTNode *derivative = NULL; + ASTNode *two = new ASTNode(AST_REAL); + two->setValue(2.0); + ASTNode *minusOne = new ASTNode(AST_REAL); + minusOne->setValue(-1.0); + ASTNode *minus_two = new ASTNode(AST_REAL); + minus_two->setValue(-2.0); + + // d(coth(x)/dx = -1/sinh^2(x) = -csch^2(x) + // d(coth(A)/dx = dA/dx * -1/sinh^2(A) + + ASTNode *derivA = getChild(0)->derivative(variable); + + if (derivA != NULL) + { + ASTNode *sinhA = new ASTNode(AST_FUNCTION_SINH); + sinhA->addChild(getChild(0)->deepCopy()); + + ASTNode *sinhAsquared = new ASTNode(AST_FUNCTION_POWER); + sinhAsquared->addChild(sinhA->deepCopy()); + sinhAsquared->addChild(minus_two->deepCopy()); + + derivative = new ASTNode(AST_TIMES); + derivative->addChild(derivA->deepCopy()); + derivative->addChild(minusOne->deepCopy()); + derivative->addChild(sinhAsquared->deepCopy()); + + derivative->decompose(); + + delete sinhA; + delete sinhAsquared; + } + delete copy; + delete two; + delete minusOne; + delete minus_two; + delete derivA; + return derivative; +} + +ASTNode* +ASTNode::derivativeCsc(const std::string& variable) +{ + ASTNode* copy = deepCopy(); + copy->decompose(); + ASTNode* derivative = NULL; + ASTNode* two = new ASTNode(AST_REAL); + two->setValue(2.0); + ASTNode* minusOne = new ASTNode(AST_REAL); + minusOne->setValue(-1.0); + ASTNode* minus_two = new ASTNode(AST_REAL); + minus_two->setValue(-2.0); + + //d(csc(x)/dx = -csc(x)*cot(x) = -cos(x)/sin^2(x) + //d(csc(A)/dx = dA/dx * -cos(A)/sin^2(A) + + ASTNode* derivA = getChild(0)->derivative(variable); + + if (derivA != NULL) + { + ASTNode* cosA = new ASTNode(AST_FUNCTION_COS); + cosA->addChild(getChild(0)->deepCopy()); + + ASTNode* sinA = new ASTNode(AST_FUNCTION_SIN); + sinA->addChild(getChild(0)->deepCopy()); + + ASTNode* sinAsquared = new ASTNode(AST_FUNCTION_POWER); + sinAsquared->addChild(sinA->deepCopy()); + sinAsquared->addChild(minus_two->deepCopy()); + + derivative = new ASTNode(AST_TIMES); + derivative->addChild(derivA->deepCopy()); + derivative->addChild(minusOne->deepCopy()); + derivative->addChild(cosA->deepCopy()); + derivative->addChild(sinAsquared->deepCopy()); + + derivative->decompose(); + + delete cosA; + delete sinA; + delete sinAsquared; + } + delete copy; + delete two; + delete minusOne; + delete minus_two; + delete derivA; + return derivative; + + } + +ASTNode * +ASTNode::derivativeSin(const std::string &variable) + +{ + + ASTNode *copy = deepCopy(); + copy->decompose(); + ASTNode *derivative = NULL; + + // d(sin(x)/dx = cos(x) + // d(sin(A)/dx = dA/dx * cos(A) + + ASTNode *derivA = getChild(0)->derivative(variable); + + if (derivA != NULL) + { + ASTNode *cosA = new ASTNode(AST_FUNCTION_COS); + cosA->addChild(getChild(0)->deepCopy()); + + derivative = new ASTNode(AST_TIMES); + derivative->addChild(derivA->deepCopy()); + derivative->addChild(cosA->deepCopy()); + + derivative->decompose(); + + delete cosA; + } + delete copy; + delete derivA; + return derivative; +} + +ASTNode* +ASTNode::derivativeCsch(const std::string& variable) +{ + ASTNode* copy = deepCopy(); + copy->decompose(); + ASTNode* derivative = NULL; + ASTNode* two = new ASTNode(AST_REAL); + two->setValue(2.0); + ASTNode* minusOne = new ASTNode(AST_REAL); + minusOne->setValue(-1.0); + ASTNode* minus_two = new ASTNode(AST_REAL); + minus_two->setValue(-2.0); + + //d(csch(x)/dx = -csch(x)*coth(x) = -cosh(x)/sinh^2(x) + //d(csch(A)/dx = dA/dx * -cosh(A)/sinh^2(A) + + ASTNode* derivA = getChild(0)->derivative(variable); + + if (derivA != NULL) + { + ASTNode* coshA = new ASTNode(AST_FUNCTION_COSH); + coshA->addChild(getChild(0)->deepCopy()); + + ASTNode* sinhA = new ASTNode(AST_FUNCTION_SINH); + sinhA->addChild(getChild(0)->deepCopy()); + + ASTNode* sinhAsquared = new ASTNode(AST_FUNCTION_POWER); + sinhAsquared->addChild(sinhA->deepCopy()); + sinhAsquared->addChild(minus_two->deepCopy()); + + derivative = new ASTNode(AST_TIMES); + derivative->addChild(derivA->deepCopy()); + derivative->addChild(minusOne->deepCopy()); + derivative->addChild(coshA->deepCopy()); + derivative->addChild(sinhAsquared->deepCopy()); + + derivative->decompose(); + + delete coshA; + delete sinhA; + delete sinhAsquared; + } + delete copy; + delete two; + delete minusOne; + delete minus_two; + delete derivA; + return derivative; +} + +ASTNode * +ASTNode::derivativeSinh(const std::string &variable) + +{ + + ASTNode *copy = deepCopy(); + copy->decompose(); + ASTNode *derivative = NULL; + + // d(sinh(x)/dx = cosh(x) + // d(sinh(A)/dx = dA/dx * cosh(A) + + ASTNode *derivA = getChild(0)->derivative(variable); + + if (derivA != NULL) + { + ASTNode *coshA = new ASTNode(AST_FUNCTION_COSH); + coshA->addChild(getChild(0)->deepCopy()); + + derivative = new ASTNode(AST_TIMES); + derivative->addChild(derivA->deepCopy()); + derivative->addChild(coshA->deepCopy()); + + derivative->decompose(); + + delete coshA; + } + delete copy; + delete derivA; + return derivative; +} + +ASTNode * +ASTNode::derivativeTan(const std::string &variable) + +{ + + ASTNode *copy = deepCopy(); + copy->decompose(); + ASTNode *derivative = NULL; + ASTNode *two = new ASTNode(AST_REAL); + two->setValue(2.0); + ASTNode *minus_two = new ASTNode(AST_REAL); + minus_two->setValue(-2.0); + + // d(tan(x)/dx = 1/cos^2(x) = sec^2(x) + // d(tan(A)/dx = dA/dx * 1/cos^2(A) + + ASTNode *derivA = getChild(0)->derivative(variable); + + if (derivA != NULL) + { + ASTNode *cosA = new ASTNode(AST_FUNCTION_COS); + cosA->addChild(getChild(0)->deepCopy()); + + ASTNode *cosAsquared = new ASTNode(AST_FUNCTION_POWER); + cosAsquared->addChild(cosA->deepCopy()); + cosAsquared->addChild(minus_two->deepCopy()); + + derivative = new ASTNode(AST_TIMES); + derivative->addChild(derivA->deepCopy()); + derivative->addChild(cosAsquared->deepCopy()); + + derivative->decompose(); + + delete cosA; + delete cosAsquared; + } + delete copy; + delete two; + delete minus_two; + delete derivA; + return derivative; +} + +ASTNode * +ASTNode::derivativeTanh(const std::string &variable) + +{ + + ASTNode *copy = deepCopy(); + copy->decompose(); + ASTNode *derivative = NULL; + ASTNode *two = new ASTNode(AST_REAL); + two->setValue(2.0); + ASTNode *minus_two = new ASTNode(AST_REAL); + minus_two->setValue(-2.0); + + // d(tanh(x)/dx = 1/cosh^2(x) = sech^2(x) + // d(tanh(A)/dx = dA/dx * 1/cosh^2(A) + + ASTNode *derivA = getChild(0)->derivative(variable); + + if (derivA != NULL) + { + ASTNode *coshA = new ASTNode(AST_FUNCTION_COSH); + coshA->addChild(getChild(0)->deepCopy()); + + ASTNode *coshAsquared = new ASTNode(AST_FUNCTION_POWER); + coshAsquared->addChild(coshA->deepCopy()); + coshAsquared->addChild(minus_two->deepCopy()); + + derivative = new ASTNode(AST_TIMES); + derivative->addChild(derivA->deepCopy()); + derivative->addChild(coshAsquared->deepCopy()); + + derivative->decompose(); + + delete coshA; + delete coshAsquared; + } + delete copy; + delete two; + delete minus_two; + delete derivA; + return derivative; +} + +ASTNode * +ASTNode::derivativeSech(const std::string &variable) +{ + ASTNode *copy = deepCopy(); + copy->decompose(); + ASTNode *derivative = NULL; + ASTNode *two = new ASTNode(AST_REAL); + two->setValue(2.0); + ASTNode *minusOne = new ASTNode(AST_REAL); + minusOne->setValue(-1.0); + ASTNode *minus_two = new ASTNode(AST_REAL); + minus_two->setValue(-2.0); + + // d(sech(x)/dx = -sech(x)*tanh(x) = -sinh(x)/cosh^2(x) + // d(sech(A)/dx = dA/dx * -sinh(A)/cosh^2(A) + + ASTNode *derivA = getChild(0)->derivative(variable); + + if (derivA != NULL) + { + ASTNode *sinhA = new ASTNode(AST_FUNCTION_SINH); + sinhA->addChild(getChild(0)->deepCopy()); + + ASTNode *coshA = new ASTNode(AST_FUNCTION_COSH); + coshA->addChild(getChild(0)->deepCopy()); + + ASTNode *coshAsquared = new ASTNode(AST_FUNCTION_POWER); + coshAsquared->addChild(coshA->deepCopy()); + coshAsquared->addChild(minus_two->deepCopy()); + + derivative = new ASTNode(AST_TIMES); + derivative->addChild(derivA->deepCopy()); + derivative->addChild(minusOne->deepCopy()); + derivative->addChild(sinhA->deepCopy()); + derivative->addChild(coshAsquared->deepCopy()); + + derivative->decompose(); + + delete sinhA; + delete coshA; + delete coshAsquared; + } + delete copy; + delete two; + delete minusOne; + delete minus_two; + delete derivA; + return derivative; +} + +ASTNode* +ASTNode::derivativeSec(const std::string& variable) +{ + ASTNode* copy = deepCopy(); + copy->decompose(); + ASTNode* derivative = NULL; + ASTNode* two = new ASTNode(AST_REAL); + two->setValue(2.0); + ASTNode* minus_two = new ASTNode(AST_REAL); + minus_two->setValue(-2.0); + + //d(sec(x)/dx = sec(x)*tan(x) = sin(x)/cos^2(x) + //d(sec(A)/dx = dA/dx * sin(A)/cos^2(A) + + ASTNode* derivA = getChild(0)->derivative(variable); + + if (derivA != NULL) + { + ASTNode* sinA = new ASTNode(AST_FUNCTION_SIN); + sinA->addChild(getChild(0)->deepCopy()); + + ASTNode* cosA = new ASTNode(AST_FUNCTION_COS); + cosA->addChild(getChild(0)->deepCopy()); + + ASTNode* cosAsquared = new ASTNode(AST_FUNCTION_POWER); + cosAsquared->addChild(cosA->deepCopy()); + cosAsquared->addChild(minus_two->deepCopy()); + + derivative = new ASTNode(AST_TIMES); + derivative->addChild(derivA->deepCopy()); + derivative->addChild(sinA->deepCopy()); + derivative->addChild(cosAsquared->deepCopy()); + + derivative->decompose(); + + delete sinA; + delete cosA; + delete cosAsquared; + } + delete copy; + delete two; + delete minus_two; + delete derivA; + return derivative; +} + +XMLNamespaces * +ASTNode::getDeclaredNamespaces() const +{ + return mNamespaces; +} + +void ASTNode::setDeclaredNamespaces(const XMLNamespaces *xmlns) +{ + mNamespaces = xmlns->clone(); +} + +void ASTNode::unsetDeclaredNamespaces() { if (mNamespaces != NULL) { diff --git a/src/sbml/math/ASTNode.h b/src/sbml/math/ASTNode.h index c3df84296b..5bc4eb7516 100644 --- a/src/sbml/math/ASTNode.h +++ b/src/sbml/math/ASTNode.h @@ -2468,9 +2468,29 @@ setValue(value, 0); ASTNode* derivativeExp(const std::string& variable); ASTNode* derivativeAbs(const std::string& variable); ASTNode* derivativeArccos(const std::string& variable); - ASTNode* derivativeArcsin(const std::string& variable); ASTNode* derivativeArctan(const std::string& variable); - + ASTNode* derivativeArcsin(const std::string& variable); + ASTNode* derivativeSin(const std::string& variable); + ASTNode* derivativeCos(const std::string& variable); + ASTNode* derivativeTan(const std::string& variable); + ASTNode* derivativeCosh(const std::string& variable); + ASTNode* derivativeCot(const std::string& variable); + ASTNode* derivativeArcsinh(const std::string& variable); + ASTNode* derivativeArccosh(const std::string& variable); + ASTNode* derivativeArctanh(const std::string& variable); + ASTNode* derivativeArccot(const std::string& variable); + ASTNode* derivativeArcsec(const std::string& variable); + ASTNode* derivativeArccsc(const std::string& variable); + ASTNode* derivativeArccoth(const std::string& variable); + ASTNode* derivativeArcsech(const std::string& variable); + ASTNode* derivativeArccsch(const std::string& variable); + ASTNode* derivativeSinh(const std::string& variable); + ASTNode* derivativeTanh(const std::string& variable); + ASTNode* derivativeCoth(const std::string& variable); + ASTNode* derivativeSech(const std::string& variable); + ASTNode* derivativeCsch(const std::string& variable); + ASTNode* derivativeSec(const std::string& variable); + ASTNode* derivativeCsc(const std::string& variable); /* * produce three vectors of the child index of the ASTNodes * numbers : any nodes representing just a number From 419680fe91576e6962eeaf3d12b721ed5f43b4bc Mon Sep 17 00:00:00 2001 From: Sarah Keating Date: Tue, 23 Dec 2025 15:32:50 +0000 Subject: [PATCH 5/8] implement all derivatives --- .../math/test/TestDerivativeFunctions.cpp | 1049 ++++++++++++++++- 1 file changed, 990 insertions(+), 59 deletions(-) diff --git a/src/sbml/math/test/TestDerivativeFunctions.cpp b/src/sbml/math/test/TestDerivativeFunctions.cpp index 31770c0f39..5378daef78 100644 --- a/src/sbml/math/test/TestDerivativeFunctions.cpp +++ b/src/sbml/math/test/TestDerivativeFunctions.cpp @@ -1073,9 +1073,6 @@ START_TEST(test_deriv_arccos1) ASTNode* deriv = n->derivative(x); const char* expected = "-3 * x^2 * (1 - x^3^2)^-0.5"; - //cout << SBML_formulaToL3String(deriv) << endl; - //cout << expected << endl; - fail_unless(formulas_equal(expected, deriv) == true); delete n; @@ -1091,9 +1088,6 @@ START_TEST(test_deriv_arccos2) ASTNode* deriv = n->derivative(x); const char* expected = "-2 * (1 - (x^3 + 2 * x)^2)^-0.5 + -3 * x^2 * (1 - (x^3 + 2 * x)^2)^-0.5"; - cout << SBML_formulaToL3String(deriv) << endl; - cout << expected << endl; - fail_unless(formulas_equal(expected, deriv) == true); delete n; @@ -1101,29 +1095,922 @@ START_TEST(test_deriv_arccos2) } END_TEST +START_TEST(test_deriv_arctan) +{ + const std::string& x = "x"; + ASTNode* n = SBML_parseL3Formula("arctan(x)"); + fail_unless(n != NULL); + + const char* expected = "(1 + x^2)^-1"; -START_TEST(test_deriv_not_implemented ) + ASTNode* deriv = n->derivative(x); + + fail_unless(formulas_equal(expected, deriv) == true); + delete n; + delete deriv; +} +END_TEST + +START_TEST(test_deriv_arctan1) { - ASTNode* n = readMathMLFromString( - "" - " " - " " - " x " - " " - "" - ); + const std::string& x = "x"; + ASTNode* n = SBML_parseL3Formula("arctan(x^2)"); + fail_unless(n != NULL); + + const char* expected = "2 * x * (1 + x^2^2)^-1"; + + ASTNode* deriv = n->derivative(x); + + fail_unless(formulas_equal(expected, deriv) == true); + delete n; + delete deriv; +} +END_TEST +START_TEST(test_deriv_arcsin) +{ + const std::string& x = "x"; + ASTNode* n = SBML_parseL3Formula("arcsin(x)"); fail_unless(n != NULL); + + const char* expected = "(1 - x^2)^-0.5"; + + ASTNode* deriv = n->derivative(x); + + fail_unless(formulas_equal(expected, deriv) == true); + delete n; + delete deriv; +} +END_TEST + +START_TEST(test_deriv_arcsin1) +{ const std::string& x = "x"; + ASTNode* n = SBML_parseL3Formula("arcsin(3*x^2+2*x)"); + fail_unless(n != NULL); - L3ParserSettings ps; - ps.setParseCollapseMinus(true); - ASTNode* node = SBML_parseL3FormulaWithSettings("sin(x)", &ps); + const char* expected = "2 * (1 - (3 * x^2 + 2 * x)^2)^-0.5 + 6 * x * (1 - (3 * x^2 + 2 * x)^2)^-0.5"; ASTNode* deriv = n->derivative(x); - fail_unless(deriv == NULL); + fail_unless(formulas_equal(expected, deriv) == true); delete n; + delete deriv; +} +END_TEST + + +START_TEST(test_deriv_sin) +{ +const std::string& x = "x"; +ASTNode* n = SBML_parseL3Formula("sin(x)"); +fail_unless(n != NULL); + + +const char* expected = "cos(x)"; + +ASTNode* deriv = n->derivative(x); + +fail_unless(formulas_equal(expected, deriv) == true); +delete n; +delete deriv; + + + +} +END_TEST + +START_TEST(test_deriv_sin1) +{ +const std::string& x = "x"; +ASTNode* n = SBML_parseL3Formula("sin(3*x^2+2*x)"); +fail_unless(n != NULL); + + +const char* expected = "(2 + 6 * x) * cos(3 * x^2 + 2 * x)"; + +ASTNode* deriv = n->derivative(x); + +fail_unless(formulas_equal(expected, deriv) == true); +delete n; +delete deriv; + + + +} +END_TEST + +START_TEST(test_deriv_cos) +{ +const std::string& x = "x"; +ASTNode* n = SBML_parseL3Formula("cos(x)"); +fail_unless(n != NULL); + + +const char* expected = "-1 * sin(x)"; + +ASTNode* deriv = n->derivative(x); + +fail_unless(formulas_equal(expected, deriv) == true); +delete n; +delete deriv; + + + +} +END_TEST + +START_TEST(test_deriv_cos1) +{ +const std::string& x = "x"; +ASTNode* n = SBML_parseL3Formula("cos(3*x^2+2*x)"); +fail_unless(n != NULL); + + +const char* expected = "-2 * sin(3 * x^2 + 2 * x) + -6 * x * sin(3 * x^2 + 2 * x)"; + +ASTNode* deriv = n->derivative(x); + +fail_unless(formulas_equal(expected, deriv) == true); +delete n; +delete deriv; + + + +} +END_TEST + +START_TEST(test_deriv_tan) +{ +const std::string& x = "x"; +ASTNode* n = SBML_parseL3Formula("tan(x)"); +fail_unless(n != NULL); + + +const char* expected = "cos(x)^-2"; + +ASTNode* deriv = n->derivative(x); + +fail_unless(formulas_equal(expected, deriv) == true); +delete n; +delete deriv; + + + +} +END_TEST + +START_TEST(test_deriv_tan1) +{ +const std::string& x = "x"; +ASTNode* n = SBML_parseL3Formula("tan(3*x^2+2*x)"); +fail_unless(n != NULL); + + +const char* expected = "2 * cos(3 * x^2 + 2 * x)^-2 + 6 * x * cos(3 * x^2 + 2 * x)^-2"; + +ASTNode* deriv = n->derivative(x); + +fail_unless(formulas_equal(expected, deriv) == true); +delete n; +delete deriv; + + + +} +END_TEST + +START_TEST(test_deriv_cosh) +{ +const std::string& x = "x"; +ASTNode* n = SBML_parseL3Formula("cosh(x)"); +fail_unless(n != NULL); + + +const char* expected = "sinh(x)"; + +ASTNode* deriv = n->derivative(x); + +fail_unless(formulas_equal(expected, deriv) == true); +delete n; +delete deriv; + + + +} +END_TEST + +START_TEST(test_deriv_cosh1) +{ +const std::string& x = "x"; +ASTNode* n = SBML_parseL3Formula("cosh(3*x^2+2*x)"); +fail_unless(n != NULL); + + +const char* expected = "2 * sinh(3 * x^2 + 2 * x) + 6 * x * sinh(3 * x^2 + 2 * x)"; + +ASTNode* deriv = n->derivative(x); + +fail_unless(formulas_equal(expected, deriv) == true); +delete n; +delete deriv; + + + +} +END_TEST + +START_TEST(test_deriv_cot) +{ +const std::string& x = "x"; +ASTNode* n = SBML_parseL3Formula("cot(x)"); +fail_unless(n != NULL); + + +const char* expected = "-1 * sin(x)^-2"; + +ASTNode* deriv = n->derivative(x); + +fail_unless(formulas_equal(expected, deriv) == true); +delete n; +delete deriv; + + + +} +END_TEST + +START_TEST(test_deriv_cot1) +{ +const std::string& x = "x"; +ASTNode* n = SBML_parseL3Formula("cot(3*x^2+2*x)"); +fail_unless(n != NULL); + + +const char* expected = "-2 * sin(3 * x^2 + 2 * x)^-2 + -6 * x * sin(3 * x^2 + 2 * x)^-2"; + +ASTNode* deriv = n->derivative(x); + +fail_unless(formulas_equal(expected, deriv) == true); +delete n; +delete deriv; + + + +} +END_TEST + +START_TEST(test_deriv_sinh) +{ +const std::string& x = "x"; +ASTNode* n = SBML_parseL3Formula("sinh(x)"); +fail_unless(n != NULL); + + +const char* expected = "cosh(x)"; + +ASTNode* deriv = n->derivative(x); + +fail_unless(formulas_equal(expected, deriv) == true); +delete n; +delete deriv; + + + +} +END_TEST + +START_TEST(test_deriv_sinh1) +{ +const std::string& x = "x"; +ASTNode* n = SBML_parseL3Formula("sinh(3*x^2+2*x)"); +fail_unless(n != NULL); + + +const char* expected = "2 * cosh(3 * x^2 + 2 * x) + 6 * x * cosh(3 * x^2 + 2 * x)"; + +ASTNode* deriv = n->derivative(x); + +fail_unless(formulas_equal(expected, deriv) == true); +delete n; +delete deriv; + + + +} +END_TEST + +START_TEST(test_deriv_tanh) +{ +const std::string& x = "x"; +ASTNode* n = SBML_parseL3Formula("tanh(x)"); +fail_unless(n != NULL); + + +const char* expected = "cosh(x)^-2"; + +ASTNode* deriv = n->derivative(x); + +fail_unless(formulas_equal(expected, deriv) == true); +delete n; +delete deriv; + + + +} +END_TEST + +START_TEST(test_deriv_tanh1) +{ +const std::string& x = "x"; +ASTNode* n = SBML_parseL3Formula("tanh(3*x^2+2*x)"); +fail_unless(n != NULL); + + +const char* expected = "2 * cosh(3 * x^2 + 2 * x)^-2 + 6 * x * cosh(3 * x^2 + 2 * x)^-2"; + +ASTNode* deriv = n->derivative(x); + +fail_unless(formulas_equal(expected, deriv) == true); +delete n; +delete deriv; + + + +} +END_TEST + +START_TEST(test_deriv_coth) +{ +const std::string& x = "x"; +ASTNode* n = SBML_parseL3Formula("coth(x)"); +fail_unless(n != NULL); + + +const char* expected = "-1 * sinh(x)^-2"; + +ASTNode* deriv = n->derivative(x); + +fail_unless(formulas_equal(expected, deriv) == true); +delete n; +delete deriv; + + + +} +END_TEST + +START_TEST(test_deriv_coth1) +{ +const std::string& x = "x"; +ASTNode* n = SBML_parseL3Formula("coth(3*x^2+2*x)"); +fail_unless(n != NULL); + + +const char* expected = "-2 * sinh(3 * x^2 + 2 * x)^-2 + -6 * x * sinh(3 * x^2 + 2 * x)^-2"; + +ASTNode* deriv = n->derivative(x); + +fail_unless(formulas_equal(expected, deriv) == true); +delete n; +delete deriv; + + + +} +END_TEST + +START_TEST(test_deriv_sec) +{ +const std::string& x = "x"; +ASTNode* n = SBML_parseL3Formula("sec(x)"); +fail_unless(n != NULL); + + +const char* expected = "sin(x) * cos(x)^-2"; + +ASTNode* deriv = n->derivative(x); + +fail_unless(formulas_equal(expected, deriv) == true); +delete n; +delete deriv; + + + +} +END_TEST + +START_TEST(test_deriv_sec1) +{ +const std::string& x = "x"; +ASTNode* n = SBML_parseL3Formula("sec(3*x^2+2*x)"); +fail_unless(n != NULL); + + +const char* expected = "2 * cos(3 * x^2 + 2 * x)^-2 * sin(3 * x^2 + 2 * x) + 6 * x * cos(3 * x^2 + 2 * x)^-2 * sin(3 * x^2 + 2 * x)"; + +ASTNode* deriv = n->derivative(x); + +fail_unless(formulas_equal(expected, deriv) == true); +delete n; +delete deriv; + + + +} +END_TEST + +START_TEST(test_deriv_csc) +{ +const std::string& x = "x"; +ASTNode* n = SBML_parseL3Formula("csc(x)"); +fail_unless(n != NULL); + + +const char* expected = "-1 * cos(x) * sin(x)^-2"; + +ASTNode* deriv = n->derivative(x); + +fail_unless(formulas_equal(expected, deriv) == true); +delete n; +delete deriv; + + + +} +END_TEST + +START_TEST(test_deriv_csc1) +{ +const std::string& x = "x"; +ASTNode* n = SBML_parseL3Formula("csc(3*x^2+2*x)"); +fail_unless(n != NULL); + + +const char* expected = "-2 * sin(3 * x^2 + 2 * x)^-2 * cos(3 * x^2 + 2 * x) + -6 * x * sin(3 * x^2 + 2 * x)^-2 * cos(3 * x^2 + 2 * x)"; + +ASTNode* deriv = n->derivative(x); + +fail_unless(formulas_equal(expected, deriv) == true); +delete n; +delete deriv; + + + +} +END_TEST + +START_TEST(test_deriv_sech) +{ +const std::string& x = "x"; +ASTNode* n = SBML_parseL3Formula("sech(x)"); +fail_unless(n != NULL); + + +const char* expected = "-1 * sinh(x) * cosh(x)^-2"; + +ASTNode* deriv = n->derivative(x); + +fail_unless(formulas_equal(expected, deriv) == true); +delete n; +delete deriv; + + + +} +END_TEST + +START_TEST(test_deriv_sech1) +{ +const std::string& x = "x"; +ASTNode* n = SBML_parseL3Formula("sech(3*x^2+2*x)"); +fail_unless(n != NULL); + + +const char* expected = "-2 * cosh(3 * x^2 + 2 * x)^-2 * sinh(3 * x^2 + 2 * x) + -6 * x * cosh(3 * x^2 + 2 * x)^-2 * sinh(3 * x^2 + 2 * x)"; + +ASTNode* deriv = n->derivative(x); + +fail_unless(formulas_equal(expected, deriv) == true); +delete n; +delete deriv; + + + +} +END_TEST + +START_TEST(test_deriv_csch) +{ +const std::string& x = "x"; +ASTNode* n = SBML_parseL3Formula("csch(x)"); +fail_unless(n != NULL); + + +const char* expected = "-1 * cosh(x) * sinh(x)^-2"; + +ASTNode* deriv = n->derivative(x); + +fail_unless(formulas_equal(expected, deriv) == true); +delete n; +delete deriv; + + + +} +END_TEST + +START_TEST(test_deriv_csch1) +{ +const std::string& x = "x"; +ASTNode* n = SBML_parseL3Formula("csch(3*x^2+2*x)"); +fail_unless(n != NULL); + + +const char* expected = "-2 * sinh(3 * x^2 + 2 * x)^-2 * cosh(3 * x^2 + 2 * x) + -6 * x * sinh(3 * x^2 + 2 * x)^-2 * cosh(3 * x^2 + 2 * x)"; + +ASTNode* deriv = n->derivative(x); + +fail_unless(formulas_equal(expected, deriv) == true); +delete n; +delete deriv; + + + +} +END_TEST + +START_TEST(test_deriv_arcsinh) +{ +const std::string& x = "x"; +ASTNode* n = SBML_parseL3Formula("arcsinh(x)"); +fail_unless(n != NULL); + + +const char* expected = "(1 + x^2)^-0.5"; + +ASTNode* deriv = n->derivative(x); + +fail_unless(formulas_equal(expected, deriv) == true); +delete n; +delete deriv; + + + +} +END_TEST + +START_TEST(test_deriv_arcsinh1) +{ +const std::string& x = "x"; +ASTNode* n = SBML_parseL3Formula("arcsinh(3*x^2+2*x)"); +fail_unless(n != NULL); + + +const char* expected = "2 * (1 + (3 * x^2 + 2 * x)^2)^-0.5 + 6 * x * (1 + (3 * x^2 + 2 * x)^2)^-0.5"; + +ASTNode* deriv = n->derivative(x); + +fail_unless(formulas_equal(expected, deriv) == true); +delete n; +delete deriv; + + + +} +END_TEST + +START_TEST(test_deriv_arccosh) +{ +const std::string& x = "x"; +ASTNode* n = SBML_parseL3Formula("arccosh(x)"); +fail_unless(n != NULL); + + +const char* expected = "(x^2 - 1)^-0.5"; + +ASTNode* deriv = n->derivative(x); + +fail_unless(formulas_equal(expected, deriv) == true); +delete n; +delete deriv; + + + +} +END_TEST + +START_TEST(test_deriv_arccosh1) +{ +const std::string& x = "x"; +ASTNode* n = SBML_parseL3Formula("arccosh(3*x^2+2*x)"); +fail_unless(n != NULL); + + +const char* expected = "2 * ((3 * x^2 + 2 * x)^2 - 1)^-0.5 + 6 * x * ((3 * x^2 + 2 * x)^2 - 1)^-0.5"; + +ASTNode* deriv = n->derivative(x); + +fail_unless(formulas_equal(expected, deriv) == true); +delete n; +delete deriv; + + + +} +END_TEST + +START_TEST(test_deriv_arctanh) +{ +const std::string& x = "x"; +ASTNode* n = SBML_parseL3Formula("arctanh(x)"); +fail_unless(n != NULL); + + +const char* expected = "(1 - x^2)^-1"; + +ASTNode* deriv = n->derivative(x); + +fail_unless(formulas_equal(expected, deriv) == true); +delete n; +delete deriv; + + + +} +END_TEST + +START_TEST(test_deriv_arctanh1) +{ +const std::string& x = "x"; +ASTNode* n = SBML_parseL3Formula("arctanh(3*x^2+2*x)"); +fail_unless(n != NULL); + + +const char* expected = "2 * (1 - (3 * x^2 + 2 * x)^2)^-1 + 6 * x * (1 - (3 * x^2 + 2 * x)^2)^-1"; + +ASTNode* deriv = n->derivative(x); + +fail_unless(formulas_equal(expected, deriv) == true); +delete n; +delete deriv; + + + +} +END_TEST + +START_TEST(test_deriv_arccot) +{ +const std::string& x = "x"; +ASTNode* n = SBML_parseL3Formula("arccot(x)"); +fail_unless(n != NULL); + + +const char* expected = "-1 * (1 + x^2)^-1"; + +ASTNode* deriv = n->derivative(x); + +fail_unless(formulas_equal(expected, deriv) == true); +delete n; +delete deriv; + + + +} +END_TEST + +START_TEST(test_deriv_arccot1) +{ +const std::string& x = "x"; +ASTNode* n = SBML_parseL3Formula("arccot(3*x^2+2*x)"); +fail_unless(n != NULL); + + +const char* expected = "-2 * (1 + (3 * x^2 + 2 * x)^2)^-1 + -6 * x * (1 + (3 * x^2 + 2 * x)^2)^-1"; + +ASTNode* deriv = n->derivative(x); + +fail_unless(formulas_equal(expected, deriv) == true); +delete n; +delete deriv; + + + +} +END_TEST + +START_TEST(test_deriv_arcsec) +{ +const std::string& x = "x"; +ASTNode* n = SBML_parseL3Formula("arcsec(x)"); +fail_unless(n != NULL); + + +const char* expected = "x^-1 * (x^2 - 1)^-0.5"; + +ASTNode* deriv = n->derivative(x); + +fail_unless(formulas_equal(expected, deriv) == true); +delete n; +delete deriv; + + + +} +END_TEST + +START_TEST(test_deriv_arcsec1) +{ +const std::string& x = "x"; +ASTNode* n = SBML_parseL3Formula("arcsec(3*x^2+2*x)"); +fail_unless(n != NULL); + + +const char* expected = "2 * ((3 * x^2 + 2 * x)^2 - 1)^-0.5 * (3 * x^2 + 2 * x)^-1 + 6 * x * ((3 * x^2 + 2 * x)^2 - 1)^-0.5 * (3 * x^2 + 2 * x)^-1"; + +ASTNode* deriv = n->derivative(x); + +fail_unless(formulas_equal(expected, deriv) == true); +delete n; +delete deriv; + + + +} +END_TEST + +START_TEST(test_deriv_arccsc) +{ +const std::string& x = "x"; +ASTNode* n = SBML_parseL3Formula("arccsc(x)"); +fail_unless(n != NULL); + + +const char* expected = "-1 * x^-1 * (x^2 - 1)^-0.5"; + +ASTNode* deriv = n->derivative(x); + +fail_unless(formulas_equal(expected, deriv) == true); +delete n; +delete deriv; + + + +} +END_TEST + +START_TEST(test_deriv_arccsc1) +{ +const std::string& x = "x"; +ASTNode* n = SBML_parseL3Formula("arccsc(3*x^2+2*x)"); +fail_unless(n != NULL); + + +const char* expected = "-2 * ((3 * x^2 + 2 * x)^2 - 1)^-0.5 * (3 * x^2 + 2 * x)^-1 + -6 * x * ((3 * x^2 + 2 * x)^2 - 1)^-0.5 * (3 * x^2 + 2 * x)^-1"; + +ASTNode* deriv = n->derivative(x); + +fail_unless(formulas_equal(expected, deriv) == true); +delete n; +delete deriv; + + + +} +END_TEST + +START_TEST(test_deriv_arccoth) +{ +const std::string& x = "x"; +ASTNode* n = SBML_parseL3Formula("arccoth(x)"); +fail_unless(n != NULL); + + +const char* expected = "(1 - x^2)^-1"; + +ASTNode* deriv = n->derivative(x); + +fail_unless(formulas_equal(expected, deriv) == true); +delete n; +delete deriv; + + + +} +END_TEST + +START_TEST(test_deriv_arccoth1) +{ +const std::string& x = "x"; +ASTNode* n = SBML_parseL3Formula("arccoth(3*x^2+2*x)"); +fail_unless(n != NULL); + + +const char* expected = "2 * (1 - (3 * x^2 + 2 * x)^2)^-1 + 6 * x * (1 - (3 * x^2 + 2 * x)^2)^-1"; + +ASTNode* deriv = n->derivative(x); + +fail_unless(formulas_equal(expected, deriv) == true); +delete n; +delete deriv; + + + +} +END_TEST + +START_TEST(test_deriv_arcsech) +{ +const std::string& x = "x"; +ASTNode* n = SBML_parseL3Formula("arcsech(x)"); +fail_unless(n != NULL); + + +const char* expected = "-1 * x^-1 * (1 - x^2)^-0.5"; + +ASTNode* deriv = n->derivative(x); + +fail_unless(formulas_equal(expected, deriv) == true); +delete n; +delete deriv; + + + +} +END_TEST + +START_TEST(test_deriv_arcsech1) +{ +const std::string& x = "x"; +ASTNode* n = SBML_parseL3Formula("arcsech(3*x^2+2*x)"); +fail_unless(n != NULL); + + +const char* expected = "-2 * (1 - (3 * x^2 + 2 * x)^2)^-0.5 * (3 * x^2 + 2 * x)^-1 + -6 * x * (1 - (3 * x^2 + 2 * x)^2)^-0.5 * (3 * x^2 + 2 * x)^-1"; + +ASTNode* deriv = n->derivative(x); + +fail_unless(formulas_equal(expected, deriv) == true); +delete n; +delete deriv; + + + +} +END_TEST + +START_TEST(test_deriv_arccsch) +{ +const std::string& x = "x"; +ASTNode* n = SBML_parseL3Formula("arccsch(x)"); +fail_unless(n != NULL); + + +const char* expected = "-1 * x^-1 * (1 + x^2)^-0.5"; + +ASTNode* deriv = n->derivative(x); + +fail_unless(formulas_equal(expected, deriv) == true); +delete n; +delete deriv; + + + +} +END_TEST + +START_TEST(test_deriv_arccsch1) +{ +const std::string& x = "x"; +ASTNode* n = SBML_parseL3Formula("arccsch(3*x^2+2*x)"); +fail_unless(n != NULL); + + +const char* expected = "-2 * (1 + (3 * x^2 + 2 * x)^2)^-0.5 * (3 * x^2 + 2 * x)^-1 + -6 * x * (1 + (3 * x^2 + 2 * x)^2)^-0.5 * (3 * x^2 + 2 * x)^-1"; + +ASTNode* deriv = n->derivative(x); + +fail_unless(formulas_equal(expected, deriv) == true); +delete n; +delete deriv; + + + +} +END_TEST + +START_TEST(test_deriv_not_implemented ) +{ + const std::string& x = "x"; + + L3ParserSettings ps; + ps.setParseCollapseMinus(true); + ASTNode* node = SBML_parseL3FormulaWithSettings("foo(x)", &ps); + + ASTNode* deriv = node->derivative(x); + + fail_unless(deriv == NULL); delete node; delete deriv; } @@ -1137,49 +2024,93 @@ create_suite_TestDerivativeFunctions() TCase *tcase = tcase_create("TestDerivFunctions"); tcase_add_test(tcase, test_deriv_const); - //tcase_add_test(tcase, test_deriv_var); - //tcase_add_test(tcase, test_deriv_var1); - //tcase_add_test(tcase, test_deriv_plus); - //tcase_add_test(tcase, test_deriv_plus1); - //tcase_add_test(tcase, test_deriv_plus2); - //tcase_add_test(tcase, test_deriv_plus3); - //tcase_add_test(tcase, test_deriv_plus4); - //tcase_add_test(tcase, test_deriv_times); - //tcase_add_test(tcase, test_deriv_times1); - //tcase_add_test(tcase, test_deriv_times2); - //tcase_add_test(tcase, test_deriv_divide); - //tcase_add_test(tcase, test_deriv_divide1); - //tcase_add_test(tcase, test_deriv_divide2); - //tcase_add_test(tcase, test_deriv_divide3); - //tcase_add_test(tcase, test_deriv_divide4); - //tcase_add_test(tcase, test_deriv_minus); - //tcase_add_test(tcase, test_deriv_minus1); - //tcase_add_test(tcase, test_deriv_minus2); - //tcase_add_test(tcase, test_deriv_minus3); - //tcase_add_test(tcase, test_deriv_minus4); - //tcase_add_test(tcase, test_deriv_power); - //tcase_add_test(tcase, test_deriv_power1); - //tcase_add_test(tcase, test_deriv_power2); - //tcase_add_test(tcase, test_deriv_power3); - //tcase_add_test(tcase, test_deriv_power4); - //tcase_add_test(tcase, test_deriv_root); - //tcase_add_test(tcase, test_deriv_root1); - //tcase_add_test(tcase, test_deriv_root2); - //tcase_add_test(tcase, test_deriv_log); - //tcase_add_test(tcase, test_deriv_log1); - //tcase_add_test(tcase, test_deriv_log2); - //tcase_add_test(tcase, test_deriv_ln); - //tcase_add_test(tcase, test_deriv_ln1); - //tcase_add_test(tcase, test_deriv_ln2); - //tcase_add_test(tcase, test_deriv_exp); - //tcase_add_test(tcase, test_deriv_exp1); - //tcase_add_test(tcase, test_deriv_exp2); - //tcase_add_test(tcase, test_deriv_abs); - //tcase_add_test(tcase, test_deriv_abs1); - //tcase_add_test(tcase, test_deriv_abs2); + tcase_add_test(tcase, test_deriv_var); + tcase_add_test(tcase, test_deriv_var1); + tcase_add_test(tcase, test_deriv_plus); + tcase_add_test(tcase, test_deriv_plus1); + tcase_add_test(tcase, test_deriv_plus2); + tcase_add_test(tcase, test_deriv_plus3); + tcase_add_test(tcase, test_deriv_plus4); + tcase_add_test(tcase, test_deriv_times); + tcase_add_test(tcase, test_deriv_times1); + tcase_add_test(tcase, test_deriv_times2); + tcase_add_test(tcase, test_deriv_divide); + tcase_add_test(tcase, test_deriv_divide1); + tcase_add_test(tcase, test_deriv_divide2); + tcase_add_test(tcase, test_deriv_divide3); + tcase_add_test(tcase, test_deriv_divide4); + tcase_add_test(tcase, test_deriv_minus); + tcase_add_test(tcase, test_deriv_minus1); + tcase_add_test(tcase, test_deriv_minus2); + tcase_add_test(tcase, test_deriv_minus3); + tcase_add_test(tcase, test_deriv_minus4); + tcase_add_test(tcase, test_deriv_power); + tcase_add_test(tcase, test_deriv_power1); + tcase_add_test(tcase, test_deriv_power2); + tcase_add_test(tcase, test_deriv_power3); + tcase_add_test(tcase, test_deriv_power4); + tcase_add_test(tcase, test_deriv_root); + tcase_add_test(tcase, test_deriv_root1); + tcase_add_test(tcase, test_deriv_root2); + tcase_add_test(tcase, test_deriv_log); + tcase_add_test(tcase, test_deriv_log1); + tcase_add_test(tcase, test_deriv_log2); + tcase_add_test(tcase, test_deriv_ln); + tcase_add_test(tcase, test_deriv_ln1); + tcase_add_test(tcase, test_deriv_ln2); + tcase_add_test(tcase, test_deriv_exp); + tcase_add_test(tcase, test_deriv_exp1); + tcase_add_test(tcase, test_deriv_exp2); + tcase_add_test(tcase, test_deriv_abs); + tcase_add_test(tcase, test_deriv_abs1); + tcase_add_test(tcase, test_deriv_abs2); tcase_add_test(tcase, test_deriv_arccos); tcase_add_test(tcase, test_deriv_arccos1); tcase_add_test(tcase, test_deriv_arccos2); + tcase_add_test(tcase, test_deriv_arctan); + tcase_add_test(tcase, test_deriv_arctan1); + tcase_add_test(tcase, test_deriv_arcsin); + tcase_add_test(tcase, test_deriv_arcsin1); + tcase_add_test(tcase, test_deriv_cos); + tcase_add_test(tcase, test_deriv_cos1); + tcase_add_test(tcase, test_deriv_tan); + tcase_add_test(tcase, test_deriv_tan1); + tcase_add_test(tcase, test_deriv_cosh); + tcase_add_test(tcase, test_deriv_cosh1); + tcase_add_test(tcase, test_deriv_cot); + tcase_add_test(tcase, test_deriv_cot1); + tcase_add_test(tcase, test_deriv_sinh); + tcase_add_test(tcase, test_deriv_sinh1); + tcase_add_test(tcase, test_deriv_tanh); + tcase_add_test(tcase, test_deriv_tanh1); + tcase_add_test(tcase, test_deriv_coth); + tcase_add_test(tcase, test_deriv_coth1); + tcase_add_test(tcase, test_deriv_sec); + tcase_add_test(tcase, test_deriv_sec1); + tcase_add_test(tcase, test_deriv_csc); + tcase_add_test(tcase, test_deriv_csc1); + tcase_add_test(tcase, test_deriv_sech); + tcase_add_test(tcase, test_deriv_sech1); + tcase_add_test(tcase, test_deriv_csch); + tcase_add_test(tcase, test_deriv_csch1); + tcase_add_test(tcase, test_deriv_arcsinh); + tcase_add_test(tcase, test_deriv_arcsinh1); + tcase_add_test(tcase, test_deriv_arccosh); + tcase_add_test(tcase, test_deriv_arccosh1); + tcase_add_test(tcase, test_deriv_arctanh); + tcase_add_test(tcase, test_deriv_arctanh1); + tcase_add_test(tcase, test_deriv_arccot); + tcase_add_test(tcase, test_deriv_arccot1); + tcase_add_test(tcase, test_deriv_arcsec); + tcase_add_test(tcase, test_deriv_arcsec1); + tcase_add_test(tcase, test_deriv_arccsc); + tcase_add_test(tcase, test_deriv_arccsc1); + tcase_add_test(tcase, test_deriv_arccoth); + tcase_add_test(tcase, test_deriv_arccoth1); + tcase_add_test(tcase, test_deriv_arcsech); + tcase_add_test(tcase, test_deriv_arcsech1); + tcase_add_test(tcase, test_deriv_arccsch); + tcase_add_test(tcase, test_deriv_arccsch1); tcase_add_test(tcase, test_deriv_not_implemented); From b511ff30f0d9b22ec3efec5653e101a0f948b665 Mon Sep 17 00:00:00 2001 From: Sarah Keating Date: Sun, 28 Dec 2025 12:02:45 +0000 Subject: [PATCH 6/8] add header --- src/sbml/math/test/TestDerivativeFunctions.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/sbml/math/test/TestDerivativeFunctions.cpp b/src/sbml/math/test/TestDerivativeFunctions.cpp index 5378daef78..0ce4e3ac19 100644 --- a/src/sbml/math/test/TestDerivativeFunctions.cpp +++ b/src/sbml/math/test/TestDerivativeFunctions.cpp @@ -48,6 +48,7 @@ #include #include +#include #include #include From f900cf50bf8c6ba1e071051b3ac544ba9af767f1 Mon Sep 17 00:00:00 2001 From: "Frank T. Bergmann" Date: Thu, 8 Jan 2026 12:23:07 +0100 Subject: [PATCH 7/8] - fix crashes on 0 args --- src/sbml/math/ASTNode.cpp | 14 +-- .../math/test/TestDerivativeFunctions.cpp | 119 +++++++++++++++++- 2 files changed, 125 insertions(+), 8 deletions(-) diff --git a/src/sbml/math/ASTNode.cpp b/src/sbml/math/ASTNode.cpp index 94e48f2488..13fe658214 100644 --- a/src/sbml/math/ASTNode.cpp +++ b/src/sbml/math/ASTNode.cpp @@ -3900,7 +3900,7 @@ ASTNode::simplify() } // if we have 1 * x * ... dont need 1 - if (mType == AST_TIMES && util_isEqual(getChild(0)->getValue(), 1.0)) + if (mType == AST_TIMES && numChildren > 0 && util_isEqual(getChild(0)->getValue(), 1.0)) { ASTNode * newNode = new ASTNode(AST_TIMES); for (unsigned int i = 1; i < numChildren; ++i) @@ -3913,7 +3913,7 @@ ASTNode::simplify() } // if we have A - A should be 0 - if (mType == AST_MINUS && getChild(0)->exactlyEqual(*getChild(1))) + if (mType == AST_MINUS && numChildren > 0 && getChild(0)->exactlyEqual(*getChild(1))) { ASTNode* child = zero->deepCopy(); (*this) = *(child); @@ -3924,7 +3924,7 @@ ASTNode::simplify() // or n + a + a should get n + 2*a // or n + a + b + b should get n + a + 2*b - if (mType == AST_PLUS) + if (mType == AST_PLUS && numChildren > 0) { bool match = false; unsigned int i; @@ -3948,21 +3948,21 @@ ASTNode::simplify() } } // if we have A/A should be 1 - if (mType == AST_DIVIDE && getChild(0)->exactlyEqual(*getChild(1))) + if (mType == AST_DIVIDE && numChildren > 1 && getChild(0)->exactlyEqual(*getChild(1))) { ASTNode* child = one->deepCopy(); (*this) = *(child); delete child; } // if we have A^1 just have A - if ((mType == AST_POWER || mType == AST_FUNCTION_POWER) && getChild(1)->exactlyEqual(*one)) + if ((mType == AST_POWER || mType == AST_FUNCTION_POWER) && numChildren > 1 && getChild(1)->exactlyEqual(*one)) { ASTNode* child = getChild(0)->deepCopy(); (*this) = *(child); delete child; } // if we have A^0 just have 1 - if ((mType == AST_POWER || mType == AST_FUNCTION_POWER) && getChild(1)->exactlyEqual(*zero)) + if ((mType == AST_POWER || mType == AST_FUNCTION_POWER) && numChildren > 1 && getChild(1)->exactlyEqual(*zero)) { ASTNode* child = one->deepCopy(); (*this) = *(child); @@ -4190,7 +4190,7 @@ ASTNode::decompose() } } } - else if (getType() == AST_DIVIDE) + else if (getType() == AST_DIVIDE && getNumChildren() > 0) { type = getChild(0)->getType(); if (type == AST_PLUS || type == AST_MINUS) diff --git a/src/sbml/math/test/TestDerivativeFunctions.cpp b/src/sbml/math/test/TestDerivativeFunctions.cpp index 0ce4e3ac19..0aa6546d24 100644 --- a/src/sbml/math/test/TestDerivativeFunctions.cpp +++ b/src/sbml/math/test/TestDerivativeFunctions.cpp @@ -79,7 +79,7 @@ equals(const char* expected, const char* actual) static bool formulas_equal(const char* expected, ASTNode* actual) { - return equals(expected, SBML_formulaToL3String(actual)); + return equals(expected, SBML_formulaToL3String(actual)); } START_TEST (test_deriv_const) @@ -174,6 +174,20 @@ START_TEST(test_deriv_plus) delete n; delete node; delete deriv; + + // test 0 args: + n = readMathMLFromString( + "" + " " + " " + " " + "" + ); + + deriv = n->derivative(x); + + delete n; + delete deriv; } END_TEST @@ -299,6 +313,25 @@ START_TEST(test_deriv_times) delete n; delete node; delete deriv; + + // also check that it does not crash on no args: + n = readMathMLFromString( + "" + " " + " " + " " + "" + ); + + deriv = n->derivative(x); + + // should be 0 + fail_unless(deriv->isNumber() == true); + fail_unless(deriv->getValue() == 0.0); + + delete n; + delete deriv; + } END_TEST @@ -361,6 +394,19 @@ START_TEST(test_deriv_divide) delete n; delete node; delete deriv; + + // test 0 args: + n = readMathMLFromString( + "" + " " + " " + " " + "" + ); + deriv = n->derivative(x); + + delete n; + delete deriv; } END_TEST @@ -484,6 +530,23 @@ START_TEST(test_deriv_minus) delete n; delete node; delete deriv; + + + // test 0 args + n = readMathMLFromString( + "" + " " + " " + " " + "" + ); + + deriv = n->derivative(x); + + delete n; + delete deriv; + + } END_TEST @@ -613,6 +676,19 @@ START_TEST(test_deriv_power) delete n; delete node; delete deriv; + + // test 0 arg + n = readMathMLFromString( + "" + " " + " " + " " + "" + ); + + deriv = n->derivative(x); + delete n; + delete deriv; } END_TEST @@ -810,6 +886,19 @@ START_TEST(test_deriv_log) delete n; delete node; delete deriv; + + // test 0 args: + n = readMathMLFromString( + "" + " " + " " + " " + ""); + + deriv = n->derivative(x); + + delete n; + delete deriv; } END_TEST @@ -957,6 +1046,20 @@ START_TEST(test_deriv_exp) delete n; delete node; delete deriv; + + // test 0 args: + n = readMathMLFromString( + "" + " " + " " + " " + "" + ); + + deriv = n->derivative(x); + + delete n; + delete deriv; } END_TEST @@ -1016,6 +1119,20 @@ START_TEST(test_deriv_abs) delete n; delete node; delete deriv; + + // test 0 args + n = readMathMLFromString( + "" + " " + " " + " " + "" + ); + + deriv = n->derivative(x); + + delete n; + delete deriv; } END_TEST From 2c1e3141ecb30d305407b1bd554a544fe2af82d9 Mon Sep 17 00:00:00 2001 From: "Frank T. Bergmann" Date: Thu, 8 Jan 2026 13:03:25 +0100 Subject: [PATCH 8/8] - apparently this test now passes --- src/sbml/conversion/test/TestSBMLRateRuleConverter.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sbml/conversion/test/TestSBMLRateRuleConverter.cpp b/src/sbml/conversion/test/TestSBMLRateRuleConverter.cpp index 52b455cc27..3fa7681e1d 100644 --- a/src/sbml/conversion/test/TestSBMLRateRuleConverter.cpp +++ b/src/sbml/conversion/test/TestSBMLRateRuleConverter.cpp @@ -369,7 +369,7 @@ START_TEST(test_crash_converter) delete math; rule_rn_converter->setDocument(doc); - fail_unless(rule_rn_converter->convert() == LIBSBML_OPERATION_FAILED); + fail_unless(rule_rn_converter->convert() == LIBSBML_OPERATION_SUCCESS); delete doc; }