Beispiel #1
0
/**
 * Sets the type of an ASTNode based on the given MathML <ci> element.
 * Errors will be logged in the stream's SBMLErrorLog object.
 */
static void
setTypeCI (ASTNode& node, const XMLToken& element, XMLInputStream& stream)
{
  if (element.getName() == "csymbol")
  {
    string url;
    element.getAttributes().readInto("definitionURL", url);

    if ( url == URL_DELAY ) node.setType(AST_FUNCTION_DELAY);
    else if ( url == URL_TIME  ) node.setType(AST_NAME_TIME);
    else if ( url == URL_AVOGADRO  ) node.setType(AST_NAME_AVOGADRO);
    else 
    {
      static_cast <SBMLErrorLog*>
	        (stream.getErrorLog())->logError(BadCsymbolDefinitionURLValue,
          stream.getSBMLNamespaces()->getLevel(), 
          stream.getSBMLNamespaces()->getVersion());
    }
  }
  else if (element.getName() == "ci")
  {
    node.setDefinitionURL(element.getAttributes());
  }

  const string name = trim( stream.next().getCharacters() );
  node.setName( name.c_str() );
}
ASTNode* CEvaluationNodeVariable::toAST(const CCopasiDataModel* /*pDataModel*/) const
{
  ASTNode* node = new ASTNode();
  node->setType(AST_NAME);
  node->setName(this->getData().c_str());
  return node;
}
ASTNode* CEvaluationNodeLogical::toAST(const CCopasiDataModel* pDataModel) const
{
  SubType subType = (SubType)CEvaluationNode::subType(this->getType());
  ASTNode* node = new ASTNode();

  switch (subType)
    {
      case AND:
        node->setType(AST_LOGICAL_AND);
        break;
      case OR:
        node->setType(AST_LOGICAL_OR);
        break;
      case XOR:
        node->setType(AST_LOGICAL_XOR);
        break;
      case EQ:
        node->setType(AST_RELATIONAL_EQ);
        break;
      case NE:
        node->setType(AST_RELATIONAL_NEQ);
        break;
      case GT:
        node->setType(AST_RELATIONAL_GT);
        break;
      case GE:
        node->setType(AST_RELATIONAL_GEQ);
        break;
      case LT:
        node->setType(AST_RELATIONAL_LT);
        break;
      case LE:
        node->setType(AST_RELATIONAL_LEQ);
        break;
      case INVALID:
        break;
      default:
        subType = INVALID;
        break;
    }

  if (subType != INVALID)
    {
      const CEvaluationNode* child1 = dynamic_cast<const CEvaluationNode*>(this->getChild());
      const CEvaluationNode* child2 = dynamic_cast<const CEvaluationNode*>(child1->getSibling());
      node->addChild(child1->toAST(pDataModel));
      node->addChild(child2->toAST(pDataModel));
    }

  return node;
}
ASTNode* CEvaluationNodeNumber::toAST(const CDataModel* /* pDataModel */) const
{
  SubType subType = (SubType)this->subType();
  ASTNode* node = new ASTNode();
  double num1;
  double num2;
  const char * end;
  const char * str = mData.c_str();

  switch (subType)
    {
      case SubType::DOUBLE:
        node->setType(AST_REAL);
        node->setValue(*mpValue);
        break;

      case SubType::INTEGER:
        node->setType(AST_INTEGER);
        node->setValue((long)*mpValue);
        break;

      case SubType::ENOTATION:
        node->setType(AST_REAL_E);
        num2 = floor(log10(*mpValue));
        num1 = pow(10.0, log10(*mpValue) - num2);
        node->setValue(num1, (long)num2);
        break;

      case SubType::RATIONALE:
        node->setType(AST_RATIONAL);
        str++; // Skip the '('
        num1 = strToDouble(str, &end);
        end++; // Skip the '/'
        num2 = strToDouble(end, NULL);
        node->setValue((long)num1, (long)num2);
        break;

      case SubType::INVALID:
        break;
    }

  return node;
}
Beispiel #5
0
ASTNode* CEvaluationNodeConstant::toAST(const CCopasiDataModel* /*pDataModel*/) const
{
  SubType subType = (SubType)this->subType();
  ASTNode* node = new ASTNode();

  switch (subType)
    {
      case S_PI:
        node->setType(AST_CONSTANT_PI);
        break;

      case S_EXPONENTIALE:
        node->setType(AST_CONSTANT_E);
        break;

      case S_TRUE:
        node->setType(AST_CONSTANT_TRUE);
        break;

      case S_FALSE:
        node->setType(AST_CONSTANT_FALSE);
        break;

      case S_INFINITY:
        node->setType(AST_REAL);
        node->setValue(std::numeric_limits<C_FLOAT64>::infinity());
        break;

      case S_NAN:
      case S_INVALID:
        node->setType(AST_REAL);
        node->setValue(std::numeric_limits<C_FLOAT64>::quiet_NaN());
        break;
    }

  return node;
}
END_TEST


START_TEST(test_SBMLTransforms_evaluateAST)
{
  double temp;
  const char * mathml;
  ASTNode * node = new ASTNode();
  node->setValue((int)(2));
  
  fail_unless(SBMLTransforms::evaluateASTNode(node) == 2);

  node->setValue((double) (3.2));

  fail_unless(util_isEqual(SBMLTransforms::evaluateASTNode(node), 3.2));

  node->setValue((long)(1), (long)(4));

  fail_unless(util_isEqual(SBMLTransforms::evaluateASTNode(node), 0.25));

  node->setValue((double) (4.234), (int) (2));

  fail_unless(util_isEqual(SBMLTransforms::evaluateASTNode(node), 423.4));

  node->setType(AST_NAME_AVOGADRO);

  fail_unless(util_isEqual(SBMLTransforms::evaluateASTNode(node), 6.02214179e23));

  node->setType(AST_NAME_TIME);

  fail_unless(util_isEqual(SBMLTransforms::evaluateASTNode(node), 0.0));

  node->setType(AST_NAME);

  fail_unless(util_isNaN(SBMLTransforms::evaluateASTNode(node)));

  node->setType(AST_CONSTANT_E);

  fail_unless(util_isEqual(SBMLTransforms::evaluateASTNode(node), exp(1.0)));

  node->setType(AST_CONSTANT_FALSE);

  fail_unless(util_isEqual(SBMLTransforms::evaluateASTNode(node), 0.0));

  node->setType(AST_CONSTANT_PI);

  fail_unless(util_isEqual(SBMLTransforms::evaluateASTNode(node), 4.0*atan(1.0)));

  node->setType(AST_CONSTANT_TRUE);

  fail_unless(util_isEqual(SBMLTransforms::evaluateASTNode(node), 1.0));

  node = SBML_parseFormula("2.5 + 6.1");

  fail_unless(util_isEqual(SBMLTransforms::evaluateASTNode(node), 8.6));

  node = SBML_parseFormula("-4.3");

  fail_unless(util_isEqual(SBMLTransforms::evaluateASTNode(node), -4.3));

  node = SBML_parseFormula("9.2-4.3");

  temp = 9.2-4.3;
  fail_unless(util_isEqual(SBMLTransforms::evaluateASTNode(node), temp));

  node = SBML_parseFormula("2*3");

  fail_unless(util_isEqual(SBMLTransforms::evaluateASTNode(node), 6));

  node = SBML_parseFormula("1/5");

  fail_unless(util_isEqual(SBMLTransforms::evaluateASTNode(node), 0.2));

  node = SBML_parseFormula("pow(2, 3)");

  fail_unless(util_isEqual(SBMLTransforms::evaluateASTNode(node), 8));

  node = SBML_parseFormula("3^3");

  fail_unless(util_isEqual(SBMLTransforms::evaluateASTNode(node), 27));

  node = SBML_parseFormula("abs(-9.456)");

  fail_unless(util_isEqual(SBMLTransforms::evaluateASTNode(node), 9.456));

  node = SBML_parseFormula("ceil(9.456)");

  fail_unless(util_isEqual(SBMLTransforms::evaluateASTNode(node), 10));

  node = SBML_parseFormula("exp(2.0)");
  
  temp = exp(2.0);
  fail_unless(util_isEqual(SBMLTransforms::evaluateASTNode(node), temp));

  node = SBML_parseFormula("floor(2.04567)");

  fail_unless(util_isEqual(SBMLTransforms::evaluateASTNode(node), 2));

  node = SBML_parseFormula("ln(2.0)");

  temp = log(2.0);
  fail_unless(util_isEqual(SBMLTransforms::evaluateASTNode(node), temp));

  node = SBML_parseFormula("log10(100.0)");

  temp = log10(100.0);
  fail_unless(util_isEqual(SBMLTransforms::evaluateASTNode(node), temp));

  node = SBML_parseFormula("sin(2.0)");

  temp = sin(2.0);
  fail_unless(util_isEqual(SBMLTransforms::evaluateASTNode(node), temp));

  node = SBML_parseFormula("cos(4.1)");

  temp = cos(4.1);
  fail_unless(util_isEqual(SBMLTransforms::evaluateASTNode(node), temp));

  node = SBML_parseFormula("tan(0.345)");

  temp = tan(0.345);
  fail_unless(util_isEqual(SBMLTransforms::evaluateASTNode(node), temp));

  node = SBML_parseFormula("arcsin(0.456)");

  temp = asin(0.456);
  fail_unless(util_isEqual(SBMLTransforms::evaluateASTNode(node), temp));

  node = SBML_parseFormula("arccos(0.41)");

  temp = acos(0.41);
  fail_unless(util_isEqual(SBMLTransforms::evaluateASTNode(node), temp));

  node = SBML_parseFormula("arctan(0.345)");

  temp = atan(0.345);
  fail_unless(util_isEqual(SBMLTransforms::evaluateASTNode(node), temp));

  node = SBML_parseFormula("sinh(2.0)");

  temp = sinh(2.0);
  fail_unless(util_isEqual(SBMLTransforms::evaluateASTNode(node), temp));

  node = SBML_parseFormula("cosh(4.1)");

  temp = cosh(4.1);
  fail_unless(util_isEqual(SBMLTransforms::evaluateASTNode(node), temp));

  node = SBML_parseFormula("tanh(0.345)");

  temp = tanh(0.345);
  fail_unless(util_isEqual(SBMLTransforms::evaluateASTNode(node), temp));

  node = SBML_parseFormula("and(1, 0)");

  fail_unless(util_isEqual(SBMLTransforms::evaluateASTNode(node), 0.0));

  node = SBML_parseFormula("or(1, 0)");

  fail_unless(util_isEqual(SBMLTransforms::evaluateASTNode(node), 1.0));

  node = SBML_parseFormula("not(1)");

  fail_unless(util_isEqual(SBMLTransforms::evaluateASTNode(node), 0.0));

  node = SBML_parseFormula("xor(1, 0)");

  fail_unless(util_isEqual(SBMLTransforms::evaluateASTNode(node), 1.0));

  node = SBML_parseFormula("xor(1, 1)");

  fail_unless(util_isEqual(SBMLTransforms::evaluateASTNode(node), 0.0));

  node = SBML_parseFormula("eq(1, 2)");

  fail_unless(util_isEqual(SBMLTransforms::evaluateASTNode(node), 0.0));

  node = SBML_parseFormula("eq(1, 1)");

  fail_unless(util_isEqual(SBMLTransforms::evaluateASTNode(node), 1.0));

  node = SBML_parseFormula("geq(2,1)");

  fail_unless(util_isEqual(SBMLTransforms::evaluateASTNode(node), 1.0));

  node = SBML_parseFormula("geq(2,4)");

  fail_unless(util_isEqual(SBMLTransforms::evaluateASTNode(node), 0.0));

  node = SBML_parseFormula("geq(2,2)");

  fail_unless(util_isEqual(SBMLTransforms::evaluateASTNode(node), 1.0));

  node = SBML_parseFormula("gt(2,1)");

  fail_unless(util_isEqual(SBMLTransforms::evaluateASTNode(node), 1.0));

  node = SBML_parseFormula("gt(2,4)");

  fail_unless(util_isEqual(SBMLTransforms::evaluateASTNode(node), 0.0));

  node = SBML_parseFormula("leq(2,1)");

  fail_unless(util_isEqual(SBMLTransforms::evaluateASTNode(node), 0.0));

  node = SBML_parseFormula("leq(2,4)");

  fail_unless(util_isEqual(SBMLTransforms::evaluateASTNode(node), 1.0));

  node = SBML_parseFormula("leq(2,2)");

  fail_unless(util_isEqual(SBMLTransforms::evaluateASTNode(node), 1.0));

  node = SBML_parseFormula("lt(2,1)");

  fail_unless(util_isEqual(SBMLTransforms::evaluateASTNode(node), 0.0));

  node = SBML_parseFormula("lt(2,4)");

  fail_unless(util_isEqual(SBMLTransforms::evaluateASTNode(node), 1.0));
  
  node = SBML_parseFormula("neq(2,2)");

  fail_unless(util_isEqual(SBMLTransforms::evaluateASTNode(node), 0.0));

  node = SBML_parseFormula("neq(3,2)");

  fail_unless(util_isEqual(SBMLTransforms::evaluateASTNode(node), 1.0));

  node = SBML_parseFormula("cot(2.0)");

  temp = 1.0/tan(2.0);
  fail_unless(util_isEqual(SBMLTransforms::evaluateASTNode(node), temp));

  node = SBML_parseFormula("csc(4.1)");

  temp = 1.0/sin(4.1);
  fail_unless(util_isEqual(SBMLTransforms::evaluateASTNode(node), temp));

  node = SBML_parseFormula("sec(0.345)");

  temp = 1.0/cos(0.345);
  fail_unless(util_isEqual(SBMLTransforms::evaluateASTNode(node), temp));

  node = SBML_parseFormula("coth(2.0)");

  temp = cosh(2.0)/sinh(2.0);
  fail_unless(util_isEqual(SBMLTransforms::evaluateASTNode(node), temp));
  
  node = SBML_parseFormula("sech(2.0)");

  temp = 1.0/cosh(2.0);
  fail_unless(util_isEqual(SBMLTransforms::evaluateASTNode(node), temp));

  node = SBML_parseFormula("csch(2.0)");

  temp = 1.0/sinh(2.0);
  fail_unless(util_isEqual(SBMLTransforms::evaluateASTNode(node), temp));

  node = SBML_parseFormula("arccot(2.0)");

  temp = atan(1/2.0);
  fail_unless(util_isEqual(SBMLTransforms::evaluateASTNode(node), temp));

  node = SBML_parseFormula("arccsc(2.0)");

  temp = asin(1/2.0);
  fail_unless(util_isEqual(SBMLTransforms::evaluateASTNode(node), temp));

  node = SBML_parseFormula("arcsec(2.0)");

  temp = acos(1/2.0);
  fail_unless(util_isEqual(SBMLTransforms::evaluateASTNode(node), temp));

  node = SBML_parseFormula("arccosh(2.0)");

  temp = log(2.0 + pow(3.0, 0.5));
  fail_unless(util_isEqual(SBMLTransforms::evaluateASTNode(node), temp));

  node = SBML_parseFormula("arccoth(2.0)");

  temp = 0.5 * log(3.0);
  fail_unless(util_isEqual(SBMLTransforms::evaluateASTNode(node), temp));

  node = SBML_parseFormula("arcsech(0.2)");

  temp = log(2*pow(6, 0.5)+5);
  fail_unless(util_isEqual(SBMLTransforms::evaluateASTNode(node), temp));
  
  node = SBML_parseFormula("arccsch(0.2)");

  /* temp = log(5 +pow(26, 0.5));
   * only matches to 15 dp and therefore fails !!
   */
  temp = 2.312438341272753;
  fail_unless(util_isEqual(SBMLTransforms::evaluateASTNode(node), temp));

  node = SBML_parseFormula("arcsinh(3.0)");

  temp = log(3.0 +pow(10.0, 0.5));
  fail_unless(util_isEqual(SBMLTransforms::evaluateASTNode(node), temp));

  node = SBML_parseFormula("arctanh(0.2)");

  temp = 0.5 * log(1.5);
  fail_unless(util_isEqual(SBMLTransforms::evaluateASTNode(node), temp));

  node->setType(AST_FUNCTION_DELAY);

  fail_unless(util_isNaN(SBMLTransforms::evaluateASTNode(node)));

  node = SBML_parseFormula("factorial(3)");

  fail_unless(util_isEqual(SBMLTransforms::evaluateASTNode(node), 6));
  
  node= SBML_parseFormula("piecewise()");

  fail_unless(util_isNaN(SBMLTransforms::evaluateASTNode(node)));

  node= SBML_parseFormula("piecewise(1,false)");
  fail_unless(util_isNaN(SBMLTransforms::evaluateASTNode(node)));

  node= SBML_parseFormula("piecewise(1,true)");
  fail_unless(util_isEqual(SBMLTransforms::evaluateASTNode(node), 1));

  node = SBML_parseFormula("piecewise(1.0, true, 0.0)");
  temp = 1.0;
  fail_unless(util_isEqual(SBMLTransforms::evaluateASTNode(node), temp));

  node = SBML_parseFormula("piecewise(1.0, false, 0.0)");
  temp = 0.0;
  fail_unless(util_isEqual(SBMLTransforms::evaluateASTNode(node), temp));

  node = SBML_parseFormula("piecewise(4.5)");
  temp = 4.5;
  fail_unless(util_isEqual(SBMLTransforms::evaluateASTNode(node), temp));

  node = SBML_parseFormula("piecewise(4.5, false, 5.5, true)");
  temp = 5.5;
  fail_unless(util_isEqual(SBMLTransforms::evaluateASTNode(node), temp));

  node = SBML_parseFormula("piecewise(4.5, true, 5.5, false)");
  temp = 4.5;
  fail_unless(util_isEqual(SBMLTransforms::evaluateASTNode(node), temp));

  node = SBML_parseFormula("piecewise(4.5, false, 5.5, false, 6.5)");
  temp = 6.5;
  fail_unless(util_isEqual(SBMLTransforms::evaluateASTNode(node), temp));

  node= SBML_parseFormula("piecewise(4.5, true, 5.5, true)");

  fail_unless(util_isNaN(SBMLTransforms::evaluateASTNode(node)));

  node = SBML_parseFormula("piecewise(4.5, true, 4.5, true)");
  temp = 4.5;
  fail_unless(util_isEqual(SBMLTransforms::evaluateASTNode(node), temp));

  node = SBML_parseFormula("root(2, 4)");

  fail_unless(util_isEqual(SBMLTransforms::evaluateASTNode(node), 2));
  
  mathml = "<math xmlns=\"http://www.w3.org/1998/Math/MathML\">"
           "<apply><plus/></apply></math>";
  
  node = readMathMLFromString(mathml);

  temp = 0;
  fail_unless(util_isEqual(SBMLTransforms::evaluateASTNode(node), temp));

  mathml = "<math xmlns=\"http://www.w3.org/1998/Math/MathML\">"
           "<apply><plus/><cn>2.3</cn></apply></math>";
  
  node = readMathMLFromString(mathml);

  temp = 2.3;
  fail_unless(util_isEqual(SBMLTransforms::evaluateASTNode(node), temp));

  mathml = "<math xmlns=\"http://www.w3.org/1998/Math/MathML\">"
           "<apply><times/></apply></math>";
  
  node = readMathMLFromString(mathml);

  temp = 1.0;
  fail_unless(util_isEqual(SBMLTransforms::evaluateASTNode(node), temp));

  mathml = "<math xmlns=\"http://www.w3.org/1998/Math/MathML\">"
           "<apply><times/><cn>6.5</cn></apply></math>";
  
  node = readMathMLFromString(mathml);

  temp = 6.5;
  fail_unless(util_isEqual(SBMLTransforms::evaluateASTNode(node), temp));

}
ASTNode* CEvaluationNodeObject::toAST(const CCopasiDataModel* pDataModel) const
{
  ASTNode* node = new ASTNode();
  node->setType(AST_NAME);
  // since I can not get the model in which this node is located, I just
  // assume that it will always be the current global model.
  const CCopasiObject* object = pDataModel->getObject(mRegisteredObjectCN);
  assert(object);

  // if it is a reference, we get the parent of the reference
  if (object->isReference())
    {
      object = object->getObjectParent();
    }

  const CModelEntity* pME = dynamic_cast<const CModelEntity*>(object);

  if (pME != NULL)
    {
      const CModel* pModel = dynamic_cast<const CModel*>(pME);

      if (pModel != NULL)
        {
          node->setType(AST_NAME_TIME);
          node->setName("time");

          if (pModel->getInitialTime() != 0.0)
            {
              CCopasiMessage(CCopasiMessage::WARNING, MCSBML + 1);
            }
        }
      else
        {
          node->setName(pME->getSBMLId().c_str());
        }
    }
  else
    {
      const CCopasiParameter* pPara = dynamic_cast<const CCopasiParameter*>(object);

      if (pPara != NULL)
        {
          // now we have to use the common name as the name for the
          // node since we need to be able to identify local parameters
          // in arbitrary expressions for the export
          node->setName(pPara->getCN().c_str());
        }
      else
        {
          const CReaction* pReaction = dynamic_cast<const CReaction*>(object);

          if (pReaction)
            {
              node->setName(pReaction->getSBMLId().c_str());
            }
          else
            {
              fatalError();
            }
        }
    }

  return node;
}
END_TEST


START_TEST(test_SBMLTransforms_evaluateAST)
{
  double temp;
  ASTNode * node = new ASTNode();
  node->setValue((int)(2));
  
  fail_unless(SBMLTransforms::evaluateASTNode(node) == 2);

  node->setValue((double) (3.2));

  fail_unless(equalDouble(SBMLTransforms::evaluateASTNode(node), 3.2));

  node->setValue((long)(1), (long)(4));

  fail_unless(equalDouble(SBMLTransforms::evaluateASTNode(node), 0.25));

  node->setValue((double) (4.234), (int) (2));

  fail_unless(equalDouble(SBMLTransforms::evaluateASTNode(node), 423.4));

  node->setType(AST_NAME_AVOGADRO);

  fail_unless(equalDouble(SBMLTransforms::evaluateASTNode(node), 6.02214179e23));

  node->setType(AST_NAME_TIME);

  fail_unless(equalDouble(SBMLTransforms::evaluateASTNode(node), 0.0));

  node->setType(AST_NAME);

  fail_unless(isnan(SBMLTransforms::evaluateASTNode(node)));

  node->setType(AST_CONSTANT_E);

  fail_unless(equalDouble(SBMLTransforms::evaluateASTNode(node), exp(1.0)));

  node->setType(AST_CONSTANT_FALSE);

  fail_unless(equalDouble(SBMLTransforms::evaluateASTNode(node), 0.0));

  node->setType(AST_CONSTANT_PI);

  fail_unless(equalDouble(SBMLTransforms::evaluateASTNode(node), 4.0*atan(1.0)));

  node->setType(AST_CONSTANT_TRUE);

  fail_unless(equalDouble(SBMLTransforms::evaluateASTNode(node), 1.0));

  node = SBML_parseFormula("2.5 + 6.1");

  fail_unless(equalDouble(SBMLTransforms::evaluateASTNode(node), 8.6));

  node = SBML_parseFormula("-4.3");

  fail_unless(equalDouble(SBMLTransforms::evaluateASTNode(node), -4.3));

  node = SBML_parseFormula("9.2-4.3");

  temp = 9.2-4.3;
  fail_unless(equalDouble(SBMLTransforms::evaluateASTNode(node), temp));

  node = SBML_parseFormula("2*3");

  fail_unless(equalDouble(SBMLTransforms::evaluateASTNode(node), 6));

  node = SBML_parseFormula("1/5");

  fail_unless(equalDouble(SBMLTransforms::evaluateASTNode(node), 0.2));

  node = SBML_parseFormula("pow(2, 3)");

  fail_unless(equalDouble(SBMLTransforms::evaluateASTNode(node), 8));

  node = SBML_parseFormula("3^3");

  fail_unless(equalDouble(SBMLTransforms::evaluateASTNode(node), 27));

  node = SBML_parseFormula("abs(-9.456)");

  fail_unless(equalDouble(SBMLTransforms::evaluateASTNode(node), 9.456));

  node = SBML_parseFormula("ceil(9.456)");

  fail_unless(equalDouble(SBMLTransforms::evaluateASTNode(node), 10));

  node = SBML_parseFormula("exp(2.0)");
  
  temp = exp(2.0);
  fail_unless(equalDouble(SBMLTransforms::evaluateASTNode(node), temp));

  node = SBML_parseFormula("floor(2.04567)");

  fail_unless(equalDouble(SBMLTransforms::evaluateASTNode(node), 2));

  node = SBML_parseFormula("ln(2.0)");

  temp = log(2.0);
  fail_unless(equalDouble(SBMLTransforms::evaluateASTNode(node), temp));

  node = SBML_parseFormula("log10(100.0)");

  temp = log10(100.0);
  fail_unless(equalDouble(SBMLTransforms::evaluateASTNode(node), temp));

  node = SBML_parseFormula("sin(2.0)");

  temp = sin(2.0);
  fail_unless(equalDouble(SBMLTransforms::evaluateASTNode(node), temp));

  node = SBML_parseFormula("cos(4.1)");

  temp = cos(4.1);
  fail_unless(equalDouble(SBMLTransforms::evaluateASTNode(node), temp));

  node = SBML_parseFormula("tan(0.345)");

  temp = tan(0.345);
  fail_unless(equalDouble(SBMLTransforms::evaluateASTNode(node), temp));

  node = SBML_parseFormula("arcsin(0.456)");

  temp = asin(0.456);
  fail_unless(equalDouble(SBMLTransforms::evaluateASTNode(node), temp));

  node = SBML_parseFormula("arccos(0.41)");

  temp = acos(0.41);
  fail_unless(equalDouble(SBMLTransforms::evaluateASTNode(node), temp));

  node = SBML_parseFormula("arctan(0.345)");

  temp = atan(0.345);
  fail_unless(equalDouble(SBMLTransforms::evaluateASTNode(node), temp));

  node = SBML_parseFormula("sinh(2.0)");

  temp = sinh(2.0);
  fail_unless(equalDouble(SBMLTransforms::evaluateASTNode(node), temp));

  node = SBML_parseFormula("cosh(4.1)");

  temp = cosh(4.1);
  fail_unless(equalDouble(SBMLTransforms::evaluateASTNode(node), temp));

  node = SBML_parseFormula("tanh(0.345)");

  temp = tanh(0.345);
  fail_unless(equalDouble(SBMLTransforms::evaluateASTNode(node), temp));

  node = SBML_parseFormula("and(1, 0)");

  fail_unless(equalDouble(SBMLTransforms::evaluateASTNode(node), 0.0));

  node = SBML_parseFormula("or(1, 0)");

  fail_unless(equalDouble(SBMLTransforms::evaluateASTNode(node), 1.0));

  node = SBML_parseFormula("not(1)");

  fail_unless(equalDouble(SBMLTransforms::evaluateASTNode(node), 0.0));

  node = SBML_parseFormula("xor(1, 0)");

  fail_unless(equalDouble(SBMLTransforms::evaluateASTNode(node), 1.0));

  node = SBML_parseFormula("xor(1, 1)");

  fail_unless(equalDouble(SBMLTransforms::evaluateASTNode(node), 0.0));

  node = SBML_parseFormula("eq(1, 2)");

  fail_unless(equalDouble(SBMLTransforms::evaluateASTNode(node), 0.0));

  node = SBML_parseFormula("eq(1, 1)");

  fail_unless(equalDouble(SBMLTransforms::evaluateASTNode(node), 1.0));

  node = SBML_parseFormula("geq(2,1)");

  fail_unless(equalDouble(SBMLTransforms::evaluateASTNode(node), 1.0));

  node = SBML_parseFormula("geq(2,4)");

  fail_unless(equalDouble(SBMLTransforms::evaluateASTNode(node), 0.0));

  node = SBML_parseFormula("geq(2,2)");

  fail_unless(equalDouble(SBMLTransforms::evaluateASTNode(node), 1.0));

  node = SBML_parseFormula("gt(2,1)");

  fail_unless(equalDouble(SBMLTransforms::evaluateASTNode(node), 1.0));

  node = SBML_parseFormula("gt(2,4)");

  fail_unless(equalDouble(SBMLTransforms::evaluateASTNode(node), 0.0));

  node = SBML_parseFormula("leq(2,1)");

  fail_unless(equalDouble(SBMLTransforms::evaluateASTNode(node), 0.0));

  node = SBML_parseFormula("leq(2,4)");

  fail_unless(equalDouble(SBMLTransforms::evaluateASTNode(node), 1.0));

  node = SBML_parseFormula("leq(2,2)");

  fail_unless(equalDouble(SBMLTransforms::evaluateASTNode(node), 1.0));

  node = SBML_parseFormula("lt(2,1)");

  fail_unless(equalDouble(SBMLTransforms::evaluateASTNode(node), 0.0));

  node = SBML_parseFormula("lt(2,4)");

  fail_unless(equalDouble(SBMLTransforms::evaluateASTNode(node), 1.0));
  
  node = SBML_parseFormula("neq(2,2)");

  fail_unless(equalDouble(SBMLTransforms::evaluateASTNode(node), 0.0));

  node = SBML_parseFormula("neq(3,2)");

  fail_unless(equalDouble(SBMLTransforms::evaluateASTNode(node), 1.0));

  node = SBML_parseFormula("cot(2.0)");

  temp = 1.0/tan(2.0);
  fail_unless(equalDouble(SBMLTransforms::evaluateASTNode(node), temp));

  node = SBML_parseFormula("csc(4.1)");

  temp = 1.0/sin(4.1);
  fail_unless(equalDouble(SBMLTransforms::evaluateASTNode(node), temp));

  node = SBML_parseFormula("sec(0.345)");

  temp = 1.0/cos(0.345);
  fail_unless(equalDouble(SBMLTransforms::evaluateASTNode(node), temp));

  node = SBML_parseFormula("coth(2.0)");

  temp = cosh(2.0)/sinh(2.0);
  fail_unless(equalDouble(SBMLTransforms::evaluateASTNode(node), temp));
  
  node = SBML_parseFormula("sech(2.0)");

  temp = 1.0/cosh(2.0);
  fail_unless(equalDouble(SBMLTransforms::evaluateASTNode(node), temp));

  node = SBML_parseFormula("csch(2.0)");

  temp = 1.0/sinh(2.0);
  fail_unless(equalDouble(SBMLTransforms::evaluateASTNode(node), temp));

  node = SBML_parseFormula("arccot(2.0)");

  temp = atan(1/2.0);
  fail_unless(equalDouble(SBMLTransforms::evaluateASTNode(node), temp));

  node = SBML_parseFormula("arccsc(2.0)");

  temp = asin(1/2.0);
  fail_unless(equalDouble(SBMLTransforms::evaluateASTNode(node), temp));

  node = SBML_parseFormula("arcsec(2.0)");

  temp = acos(1/2.0);
  fail_unless(equalDouble(SBMLTransforms::evaluateASTNode(node), temp));

  node = SBML_parseFormula("arccosh(2.0)");

  temp = log(2.0 + pow(3.0, 0.5));
  fail_unless(equalDouble(SBMLTransforms::evaluateASTNode(node), temp));

  node = SBML_parseFormula("arccoth(2.0)");

  temp = 0.5 * log(3.0);
  fail_unless(equalDouble(SBMLTransforms::evaluateASTNode(node), temp));

  node = SBML_parseFormula("arcsech(0.2)");

  temp = log(2*pow(6, 0.5)+5);
  fail_unless(equalDouble(SBMLTransforms::evaluateASTNode(node), temp));
  
  node = SBML_parseFormula("arccsch(0.2)");

  /* temp = log(5 +pow(26, 0.5));
   * only matches to 15 dp and therefore fails !!
   */
  temp = 2.312438341272753;
  fail_unless(equalDouble(SBMLTransforms::evaluateASTNode(node), temp));

  node = SBML_parseFormula("arcsinh(3.0)");

  temp = log(3.0 +pow(10.0, 0.5));
  fail_unless(equalDouble(SBMLTransforms::evaluateASTNode(node), temp));

  node = SBML_parseFormula("arctanh(0.2)");

  temp = 0.5 * log(1.5);
  fail_unless(equalDouble(SBMLTransforms::evaluateASTNode(node), temp));

  node->setType(AST_FUNCTION_DELAY);

  fail_unless(isnan(SBMLTransforms::evaluateASTNode(node)));

  node = SBML_parseFormula("factorial(3)");

  fail_unless(equalDouble(SBMLTransforms::evaluateASTNode(node), 6));
  
  node->setType(AST_FUNCTION_PIECEWISE);

  fail_unless(isnan(SBMLTransforms::evaluateASTNode(node)));

  node = SBML_parseFormula("root(2, 4)");

  fail_unless(equalDouble(SBMLTransforms::evaluateASTNode(node), 2));
  
}
ASTNode* CEvaluationNodeFunction::toAST(const CCopasiDataModel* pDataModel) const
{
    SubType subType = (SubType)this->subType();
    ASTNode* node = new ASTNode();
    bool needFirstArg = true;

    switch (subType)
    {
    case S_INVALID:
        break;

    case S_LOG:
        node->setType(AST_FUNCTION_LN);
        break;

    case S_LOG10:
    {
        // log 10 needs two children, the log and the base
        node->setType(AST_FUNCTION_LOG);

        ASTNode* logBase = new ASTNode();
        logBase->setType(AST_INTEGER);
        logBase->setValue(10);
        node->addChild(logBase);

        break;
    }

    case S_EXP:
        node->setType(AST_FUNCTION_EXP);
        break;

    case S_SIN:
        node->setType(AST_FUNCTION_SIN);
        break;

    case S_COS:
        node->setType(AST_FUNCTION_COS);
        break;

    case S_TAN:
        node->setType(AST_FUNCTION_TAN);
        break;

    case S_SEC:
        node->setType(AST_FUNCTION_SEC);
        break;

    case S_CSC:
        node->setType(AST_FUNCTION_CSC);
        break;

    case S_COT:
        node->setType(AST_FUNCTION_COT);
        break;

    case S_SINH:
        node->setType(AST_FUNCTION_SINH);
        break;

    case S_COSH:
        node->setType(AST_FUNCTION_COSH);
        break;

    case S_TANH:
        node->setType(AST_FUNCTION_TANH);
        break;

    case S_SECH:
        node->setType(AST_FUNCTION_SECH);
        break;

    case S_CSCH:
        node->setType(AST_FUNCTION_CSCH);
        break;

    case S_COTH:
        node->setType(AST_FUNCTION_COTH);
        break;

    case S_ARCSIN:
        node->setType(AST_FUNCTION_ARCSIN);
        break;

    case S_ARCCOS:
        node->setType(AST_FUNCTION_ARCCOS);
        break;

    case S_ARCTAN:
        node->setType(AST_FUNCTION_ARCTAN);
        break;

    case S_ARCSEC:
        node->setType(AST_FUNCTION_ARCSEC);
        break;

    case S_ARCCSC:
        node->setType(AST_FUNCTION_ARCCSC);
        break;

    case S_ARCCOT:
        node->setType(AST_FUNCTION_ARCCOT);
        break;

    case S_ARCSINH:
        node->setType(AST_FUNCTION_ARCSINH);
        break;

    case S_ARCCOSH:
        node->setType(AST_FUNCTION_ARCCOSH);
        break;

    case S_ARCTANH:
        node->setType(AST_FUNCTION_ARCTANH);
        break;

    case S_ARCSECH:
        node->setType(AST_FUNCTION_ARCSECH);
        break;

    case S_ARCCSCH:
        node->setType(AST_FUNCTION_ARCCSCH);
        break;

    case S_ARCCOTH:
        node->setType(AST_FUNCTION_ARCCOTH);
        break;

    case S_SQRT:
        node->setType(AST_FUNCTION_ROOT);
        break;

    case S_ABS:
        node->setType(AST_FUNCTION_ABS);
        break;

    case S_CEIL:
        node->setType(AST_FUNCTION_CEILING);
        break;

    case S_FLOOR:
        node->setType(AST_FUNCTION_FLOOR);
        break;

    case S_FACTORIAL:
        node->setType(AST_FUNCTION_FACTORIAL);
        break;

    case S_MINUS:
        node->setType(AST_MINUS);
        break;

    case S_PLUS:
        // if this is the unary plus as I suspect,
        // the node will be replaced by its only child
        delete node;
        node = dynamic_cast<const CEvaluationNode*>(this->getChild())->toAST(pDataModel);
        break;

    case S_NOT:
        node->setType(AST_LOGICAL_NOT);
        break;

    case S_RUNIFORM:
    {
        needFirstArg = false;
        node->setType(AST_FUNCTION);
        node->setName("RUNIFORM");
        const CEvaluationNode* child = dynamic_cast<const CEvaluationNode*>(this->getChild());
        const CEvaluationNode* sibling = dynamic_cast<const CEvaluationNode*>(child->getSibling());
        node->addChild(child->toAST(pDataModel));
        node->addChild(sibling->toAST(pDataModel));
    }
    break;

    case S_RNORMAL:
    {
        needFirstArg = false;
        node->setType(AST_FUNCTION);
        node->setName("RNORMAL");
        const CEvaluationNode* child = dynamic_cast<const CEvaluationNode*>(this->getChild());
        const CEvaluationNode* sibling = dynamic_cast<const CEvaluationNode*>(child->getSibling());
        node->addChild(child->toAST(pDataModel));
        node->addChild(sibling->toAST(pDataModel));
    }
    break;

    case S_RGAMMA:
    {
        needFirstArg = false;
        node->setType(AST_FUNCTION);
        node->setName("RGAMMA");
        const CEvaluationNode* child = dynamic_cast<const CEvaluationNode*>(this->getChild());
        const CEvaluationNode* sibling = dynamic_cast<const CEvaluationNode*>(child->getSibling());
        node->addChild(child->toAST(pDataModel));
        node->addChild(sibling->toAST(pDataModel));
    }
    break;

    case S_RPOISSON:
    {
        needFirstArg = false;
        node->setType(AST_FUNCTION);
        node->setName("RPOISSON");
        const CEvaluationNode* child = dynamic_cast<const CEvaluationNode*>(this->getChild());
        node->addChild(child->toAST(pDataModel));
    }
    break;

    case S_MAX:
    {
        needFirstArg = false;
        node->setType(AST_FUNCTION);
        node->setName("MAX");
        const CEvaluationNode* child = dynamic_cast<const CEvaluationNode*>(this->getChild());
        const CEvaluationNode* sibling = dynamic_cast<const CEvaluationNode*>(child->getSibling());
        node->addChild(child->toAST(pDataModel));
        node->addChild(sibling->toAST(pDataModel));
    }
    break;

    case S_MIN:
    {
        needFirstArg = false;
        node->setType(AST_FUNCTION);
        node->setName("MIN");
        const CEvaluationNode* child = dynamic_cast<const CEvaluationNode*>(this->getChild());
        const CEvaluationNode* sibling = dynamic_cast<const CEvaluationNode*>(child->getSibling());
        node->addChild(child->toAST(pDataModel));
        node->addChild(sibling->toAST(pDataModel));
    }
    break;
        // :TODO: Bug 894: Implement me.
        //fatalError();
    break;
    }

    if (subType != S_INVALID)
    {
        // the following is a workaround for a bug in libsbml 3.1.1 and 3.2.0
        // where libsbml does not handle the case correctly that a root
        // function can have one or two children (MathML.cpp in function
        // writeFunctionRoot)
        if (subType == S_SQRT)
        {
            // add a degree node of value 2 as the first child
            ASTNode* pDegreeNode = new ASTNode();
            pDegreeNode->setType(AST_INTEGER);
            pDegreeNode->setValue(2);
            node->addChild(pDegreeNode);
        }

        if (needFirstArg)
        {
            const CEvaluationNode* child = dynamic_cast<const CEvaluationNode*>(this->getChild());
            node->addChild(child->toAST(pDataModel));
        }
    }

    return node;
}