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; } diff --git a/src/sbml/math/ASTNode.cpp b/src/sbml/math/ASTNode.cpp index 238970c86c..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) @@ -4338,8 +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_ARCTAN: + 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; @@ -4349,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(); @@ -4361,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()); @@ -4378,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(); @@ -4416,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); @@ -4452,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(); @@ -4470,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(); @@ -4479,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); @@ -4502,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()); } @@ -4517,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); @@ -4556,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(); @@ -4565,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()); @@ -4592,148 +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) + if (getChild(0)->derivative(variable) != NULL) + { + derivative = new ASTNode(AST_DIVIDE); + derivative->addChild(getChild(0)->derivative(variable)); + derivative->addChild(getChild(0)->deepCopy()); - delete number; - delete ln; - delete times; + 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); - 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()); + ASTNode *sqrt = new ASTNode(AST_FUNCTION_POWER); + ASTNode *bracket_minus = new ASTNode(AST_MINUS); - derivative->decompose(); - } - else - { - derivative = new ASTNode(AST_TIMES); + // d(arccosh(x)/dx = 1/sqrt(x^2-1) + // d(arccosh(A)/dx = dA/dx * 1/sqrt(A^2-1) + + ASTNode *derivA = getChild(0)->derivative(variable); - divide->addChild(getChild(0)->deepCopy()); - divide->addChild(copy->deepCopy()); + if (derivA != NULL) + { + ASTNode *Asquared = new ASTNode(AST_POWER); + Asquared->addChild(getChild(0)->deepCopy()); + Asquared->addChild(two->deepCopy()); - derivative->addChild(getChild(0)->derivative(variable)->deepCopy()); - derivative->addChild(divide->deepCopy()); + bracket_minus->addChild(Asquared->deepCopy()); + bracket_minus->addChild(one->deepCopy()); - derivative->decompose(); - } - } - delete copy; - delete one; - delete divide; - return derivative; + 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; } -XMLNamespaces* -ASTNode::getDeclaredNamespaces() const +ASTNode * +ASTNode::derivativeArccot(const std::string &variable) + { - return mNamespaces; + + 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 *power = new ASTNode(AST_FUNCTION_POWER); + ASTNode *bracket_plus = new ASTNode(AST_PLUS); + + // d(arccot(x)/dx = -1/(1+x^2) + // d(arccot(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(minusOne->deepCopy()); + derivative->addChild(power->deepCopy()); + + derivative->decompose(); + + delete Asquared; + } + delete copy; + delete two; + delete one; + delete minusOne; + delete minus_one; + delete bracket_plus; + delete power; + delete derivA; + return derivative; } +ASTNode * +ASTNode::derivativeArccoth(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 *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(arccoth(x)/dx = 1/(1-x^2) + // d(arccoth(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::derivativeArccsc(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 *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(arccsc(x)/dx = -1/(x*sqrt(x^2-1)) + // d(arccsc(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(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) + +{ + + 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) + +{ + + 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 d9bfc45e74..5bc4eb7516 100644 --- a/src/sbml/math/ASTNode.h +++ b/src/sbml/math/ASTNode.h @@ -2467,8 +2467,30 @@ 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* 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 diff --git a/src/sbml/math/test/TestDerivativeFunctions.cpp b/src/sbml/math/test/TestDerivativeFunctions.cpp index bbd64833c0..0aa6546d24 100644 --- a/src/sbml/math/test/TestDerivativeFunctions.cpp +++ b/src/sbml/math/test/TestDerivativeFunctions.cpp @@ -48,6 +48,7 @@ #include #include +#include #include #include @@ -63,7 +64,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) { @@ -157,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 @@ -282,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 @@ -344,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 @@ -467,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 @@ -596,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 @@ -793,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 @@ -940,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 @@ -999,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 @@ -1033,28 +1167,968 @@ START_TEST(test_deriv_abs2) } END_TEST -START_TEST(test_deriv_not_implemented ) +START_TEST(test_deriv_arccos) { - ASTNode* n = readMathMLFromString( - "" - " " - " " - " x " - " " - "" - ); + 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_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"; + + 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"; + + fail_unless(formulas_equal(expected, deriv) == true); + delete n; + delete deriv; +} +END_TEST + +START_TEST(test_deriv_arctan) +{ const std::string& x = "x"; + ASTNode* n = SBML_parseL3Formula("arctan(x)"); + fail_unless(n != NULL); - L3ParserSettings ps; - ps.setParseCollapseMinus(true); - ASTNode* node = SBML_parseL3FormulaWithSettings("sin(x)", &ps); + const char* expected = "(1 + x^2)^-1"; 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_arctan1) +{ + 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); + + 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_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; } @@ -1108,6 +2182,53 @@ create_suite_TestDerivativeFunctions() 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);