END_TEST


START_TEST (test_SBML_parseFormula_15)
{
  ASTNode_t *r = SBML_parseFormula("foo(1, bar)");
  ASTNode_t *c;


  fail_unless( ASTNode_getType(r) == AST_FUNCTION , NULL );
  fail_unless( !strcmp(ASTNode_getName(r), "foo") , NULL );
  fail_unless( ASTNode_getNumChildren(r) == 2     , NULL );

  c = ASTNode_getLeftChild(r);

  fail_unless( ASTNode_getType       (c) == AST_INTEGER, NULL );
  fail_unless( ASTNode_getInteger    (c) == 1, NULL );
  fail_unless( ASTNode_getNumChildren(c) == 0, NULL );

  c = ASTNode_getRightChild(r);

  fail_unless( ASTNode_getType(c) == AST_NAME     , NULL );
  fail_unless( !strcmp(ASTNode_getName(c), "bar") , NULL );
  fail_unless( ASTNode_getNumChildren(c) == 0     , NULL );

  ASTNode_free(r);
}
Example #2
0
END_TEST


START_TEST (test_FunctionDefinition_getArguments)
{
  const ASTNode_t *math; 

  ASTNode_t* math1 = SBML_parseFormula("lambda(x, y, x^y)");
  FunctionDefinition_setMath(FD, math1 );
  ASTNode_free(math1);

  fail_unless( FunctionDefinition_getNumArguments(FD) == 2 );


  math = FunctionDefinition_getArgument(FD, 0);

  fail_unless( math != NULL                        );
  fail_unless( ASTNode_isName(math)                );
  fail_unless( !strcmp(ASTNode_getName(math), "x") );
  fail_unless( ASTNode_getNumChildren(math) == 0   );

  math = FunctionDefinition_getArgument(FD, 1);

  fail_unless( math != NULL                        );
  fail_unless( ASTNode_isName(math)                );
  fail_unless( !strcmp(ASTNode_getName(math), "y") );
  fail_unless( ASTNode_getNumChildren(math) == 0   );

  fail_unless( FunctionDefinition_getArgument(FD, 0) ==
               FunctionDefinition_getArgumentByName(FD, "x") );

  fail_unless( FunctionDefinition_getArgument(FD, 1) ==
               FunctionDefinition_getArgumentByName(FD, "y") );
}
END_TEST


START_TEST (test_SBML_parseFormula_6)
{
  ASTNode_t *r = SBML_parseFormula("1 + 2");
  ASTNode_t *c;



  fail_unless( ASTNode_getType       (r) == AST_PLUS, NULL );
  fail_unless( ASTNode_getCharacter  (r) == '+', NULL );
  fail_unless( ASTNode_getNumChildren(r) == 2  , NULL );

  c = ASTNode_getLeftChild(r);

  fail_unless( ASTNode_getType       (c) == AST_INTEGER, NULL );
  fail_unless( ASTNode_getInteger    (c) == 1, NULL );
  fail_unless( ASTNode_getNumChildren(c) == 0, NULL );

  c = ASTNode_getRightChild(r);

  fail_unless( ASTNode_getType       (c) == AST_INTEGER, NULL );
  fail_unless( ASTNode_getInteger    (c) == 2, NULL );
  fail_unless( ASTNode_getNumChildren(c) == 0, NULL );

  ASTNode_free(r);
}
Example #4
0
void
printFunctionDefinition (unsigned int n, FunctionDefinition_t *fd)
{
  const ASTNode_t *math;
  char *formula;


  if ( FunctionDefinition_isSetMath(fd) )
  {
    math = FunctionDefinition_getMath(fd);

    /* Print function body. */
    if (ASTNode_getNumChildren(math) == 0)
    {
      printf("(no body defined)");
    }
    else
    {
      math    = ASTNode_getChild(math, ASTNode_getNumChildren(math) - 1);
      formula = SBML_formulaToDot(math);
      fprintf(fout, "subgraph cluster%u {\n", noClusters);
      fprintf(fout, "label=\"FunctionDefinition: %s\";\n%s\n", FunctionDefinition_getId(fd), formula);
      free(formula);
      noClusters++;
    }
  }
}
/**
 * Visits the given ASTNode as a unary minus.  For this node only the
 * traversal is preorder.
 */
void
L3FormulaFormatter_visitUMinus ( const ASTNode_t *parent,
                                 const ASTNode_t *node,
                                 StringBuffer_t  *sb, 
                                 const L3ParserSettings_t *settings )
{
  //Unary minus is *not* the highest precedence, since it is superceded by 'power'
  unsigned int group;
  
  //If we are supposed to collapse minuses, do so.
  if (L3ParserSettings_getParseCollapseMinus(settings)) {
    if (ASTNode_getNumChildren(node) == 1 &&
        ASTNode_isUMinus(ASTNode_getLeftChild(node))) {
      L3FormulaFormatter_visit(parent, ASTNode_getLeftChild(ASTNode_getLeftChild(node)), sb, settings);
      return;
    }
  }
  
  group = L3FormulaFormatter_isGrouped(parent, node, settings);

  if (group)
  {
    StringBuffer_appendChar(sb, '(');
  }
  StringBuffer_appendChar(sb, '-');
  L3FormulaFormatter_visit ( node, ASTNode_getLeftChild(node), sb, settings);
  if (group)
  {
    StringBuffer_appendChar(sb, ')');
  }
}
/**
 * Visits the given ASTNode as a function.  For this node only the
 * traversal is preorder.
 */
void
FormulaFormatter_visitFunction ( const ASTNode_t *parent,
                                 const ASTNode_t *node,
                                 StringBuffer_t  *sb )
{
  unsigned int numChildren = ASTNode_getNumChildren(node);
  unsigned int n;


  FormulaFormatter_format(sb, node);
  StringBuffer_appendChar(sb, '(');

  if (numChildren > 0)
  {
    FormulaFormatter_visit( node, ASTNode_getChild(node, 0), sb );
  }

  for (n = 1; n < numChildren; n++)
  {
    StringBuffer_appendChar(sb, ',');
    StringBuffer_appendChar(sb, ' ');
    FormulaFormatter_visit( node, ASTNode_getChild(node, n), sb );
  }

  StringBuffer_appendChar(sb, ')');
}
Example #7
0
/**
 * Since graphviz will interpret identical names as referring to
 * the same node presentation-wise it is better if each function node
 * has a unique name.
 * 
 * Returns the name of the function with the name of the first child
 * prepended
 *
 * THIS COULD BE DONE BETTER
 */
char *
FormulaGraphvizFormatter_FunctionGetUniqueName (const ASTNode_t *node)
{
  char           *s;
  StringBuffer_t *p   = StringBuffer_create(128);
  ASTNodeType_t  type = ASTNode_getType(node);
 
  if (ASTNode_getNumChildren(node) != 0)
  {
	const char* name = ASTNode_getName(ASTNode_getChild(node,0));
	if (name != NULL)
    StringBuffer_append(p, name);
  }
  else
  {
    StringBuffer_append(p, "unknown");
  }

  switch (type)
  {
    case AST_FUNCTION_ARCCOS:
      StringBuffer_append(p, "acos");
      break;

    case AST_FUNCTION_ARCSIN:
      StringBuffer_append(p, "asin");
      break;

    case AST_FUNCTION_ARCTAN:
      StringBuffer_append(p, "atan");
      break;

    case AST_FUNCTION_CEILING:
      StringBuffer_append(p, "ceil");
      break;

    case AST_FUNCTION_LN:
      StringBuffer_append(p, "log");
      break;

    case AST_FUNCTION_POWER:
      StringBuffer_append(p, "pow");
      break;

    default:
      if (ASTNode_getName(node) != NULL)
      {
        StringBuffer_append(p, ASTNode_getName(node));
      }
      break;
  }
  
  s = StringBuffer_toString(p);

  free(p);

  return s;
}
Example #8
0
END_TEST


START_TEST (test_SBML_parseFormula_10)
{
  ASTNode_t *r = SBML_parseFormula("1 + -2e100 / 3");
  ASTNode_t *c;


  fail_unless( ASTNode_getType       (r) == AST_PLUS, NULL );
  fail_unless( ASTNode_getCharacter  (r) == '+', NULL );
  fail_unless( ASTNode_getNumChildren(r) == 2  , NULL );

  c = ASTNode_getLeftChild(r);

  fail_unless( ASTNode_getType       (c) == AST_INTEGER, NULL );
  fail_unless( ASTNode_getInteger    (c) == 1, NULL );
  fail_unless( ASTNode_getNumChildren(c) == 0, NULL );

  c = ASTNode_getRightChild(r);

  fail_unless( ASTNode_getType       (c) == AST_DIVIDE, NULL );
  fail_unless( ASTNode_getCharacter  (c) == '/', NULL );
  fail_unless( ASTNode_getNumChildren(c) == 2  , NULL );

  c = ASTNode_getLeftChild(c);

  fail_unless( ASTNode_getType       (c) == AST_REAL_E, NULL );
  fail_unless( ASTNode_getMantissa   (c) ==  -2, NULL );
  fail_unless( ASTNode_getExponent   (c) == 100, NULL );
  fail_unless( ASTNode_getReal       (c) == -2e+100, NULL );
  fail_unless( ASTNode_getNumChildren(c) ==   0, NULL );

  c = ASTNode_getRightChild( ASTNode_getRightChild(r) );

  fail_unless( ASTNode_getType       (c) == AST_INTEGER, NULL );
  fail_unless( ASTNode_getInteger    (c) == 3, NULL );
  fail_unless( ASTNode_getNumChildren(c) == 0, NULL );

  ASTNode_free(r);
}
Example #9
0
void
printFunctionDefinition (unsigned int n, const FunctionDefinition_t *fd)
{
  const ASTNode_t *math;
  char *formula;


  if ( FunctionDefinition_isSetMath(fd) )
  {
    printf("FunctionDefinition %d, %s(", n, FunctionDefinition_getId(fd));

    math = FunctionDefinition_getMath(fd);

    /* Print function arguments. */
    if (ASTNode_getNumChildren(math) > 1)
    {
      printf("%s", ASTNode_getName( ASTNode_getLeftChild(math) ));

      for (n = 1; n < ASTNode_getNumChildren(math) - 1; ++n)
      {
        printf(", %s", ASTNode_getName( ASTNode_getChild(math, n) ));
      }
    }

    printf(") := ");

    /* Print function body. */
    if (ASTNode_getNumChildren(math) == 0)
    {
      printf("(no body defined)");
    }
    else
    {
      math    = ASTNode_getChild(math, ASTNode_getNumChildren(math) - 1);
      formula = SBML_formulaToString(math);
      printf("%s\n", formula);
      free(formula);
    }
  }
}
END_TEST


START_TEST (test_SBML_parseFormula_8)
{
  ASTNode_t *r = SBML_parseFormula("(1 - 2) * 3");
  ASTNode_t *c;


  fail_unless( ASTNode_getType       (r) == AST_TIMES, NULL );
  fail_unless( ASTNode_getCharacter  (r) == '*', NULL );
  fail_unless( ASTNode_getNumChildren(r) == 2  , NULL );

  c = ASTNode_getLeftChild(r);

  fail_unless( ASTNode_getType       (c) == AST_MINUS, NULL );
  fail_unless( ASTNode_getCharacter  (c) == '-', NULL );
  fail_unless( ASTNode_getNumChildren(c) == 2, NULL );

  c = ASTNode_getRightChild(r);

  fail_unless( ASTNode_getType       (c) == AST_INTEGER, NULL );
  fail_unless( ASTNode_getInteger    (c) == 3, NULL );
  fail_unless( ASTNode_getNumChildren(c) == 0, NULL );

  c = ASTNode_getLeftChild( ASTNode_getLeftChild(r) );

  fail_unless( ASTNode_getType       (c) == AST_INTEGER, NULL );
  fail_unless( ASTNode_getInteger    (c) == 1, NULL );
  fail_unless( ASTNode_getNumChildren(c) == 0, NULL );

  c = ASTNode_getRightChild( ASTNode_getLeftChild(r) );

  fail_unless( ASTNode_getType       (c) == AST_INTEGER, NULL );
  fail_unless( ASTNode_getInteger   (c)  == 2, NULL );
  fail_unless( ASTNode_getNumChildren(c) == 0, NULL );

  ASTNode_free(r);
}
END_TEST


START_TEST (test_SBML_parseFormula_2)
{
  ASTNode_t *r = SBML_parseFormula("2.1");


  fail_unless( ASTNode_getType       (r) == AST_REAL, NULL );
  fail_unless( ASTNode_getReal       (r) == 2.1, NULL );
  fail_unless( ASTNode_getNumChildren(r) ==   0, NULL );

  ASTNode_free(r);
}
END_TEST


START_TEST (test_SBML_parseFormula_negInf)
{
  ASTNode_t *r = SBML_parseFormula("-inf");


  fail_unless( ASTNode_getType(r)             == AST_REAL, NULL );
  fail_unless( util_isInf(ASTNode_getReal(r)) == -1, NULL );
  fail_unless( ASTNode_getNumChildren(r)      ==  0, NULL );

  ASTNode_free(r);
}
END_TEST


START_TEST (test_SBML_parseFormula_1)
{
  ASTNode_t *r = SBML_parseFormula("1");


  fail_unless( ASTNode_getType       (r) == AST_INTEGER, NULL );
  fail_unless( ASTNode_getInteger    (r) == 1, NULL );
  fail_unless( ASTNode_getNumChildren(r) == 0, NULL );

  ASTNode_free(r);
}
END_TEST


START_TEST (test_SBML_parseFormula_negZero)
{
  ASTNode_t *r = SBML_parseFormula("-0.0");


  fail_unless( ASTNode_getType(r)                 == AST_REAL, NULL );
  fail_unless( util_isNegZero(ASTNode_getReal(r)) == 1, NULL );
  fail_unless( ASTNode_getNumChildren(r)          == 0, NULL );

  ASTNode_free(r);
}
END_TEST


START_TEST (test_SBML_parseFormula_13)
{
  ASTNode_t *r = SBML_parseFormula("foo()");


  fail_unless( ASTNode_getType(r) == AST_FUNCTION , NULL );
  fail_unless( !strcmp(ASTNode_getName(r), "foo") , NULL );
  fail_unless( ASTNode_getNumChildren(r) == 0     , NULL );

  ASTNode_free(r);
}
END_TEST


START_TEST (test_SBML_parseFormula_3)
{
  ASTNode_t *r = SBML_parseFormula("2.1e5");


  fail_unless( ASTNode_getType       (r) == AST_REAL_E, NULL );
  fail_unless( ASTNode_getMantissa   (r) == 2.1, NULL );
  fail_unless( ASTNode_getExponent   (r) ==   5, NULL );
  fail_unless( ASTNode_getNumChildren(r) ==   0, NULL );

  ASTNode_free(r);
}
END_TEST


START_TEST (test_SBML_parseFormula_12)
{
  ASTNode_t *r = SBML_parseFormula("2 * foo^bar + 3.0");
  ASTNode_t *c;


  fail_unless( ASTNode_getType       (r) == AST_PLUS, NULL );
  fail_unless( ASTNode_getCharacter  (r) == '+', NULL );
  fail_unless( ASTNode_getNumChildren(r) == 2  , NULL );

  c = ASTNode_getLeftChild(r);

  fail_unless( ASTNode_getType       (c) == AST_TIMES, NULL );
  fail_unless( ASTNode_getCharacter  (c) == '*', NULL );
  fail_unless( ASTNode_getNumChildren(c) == 2  , NULL );

  c = ASTNode_getRightChild(r);

  fail_unless( ASTNode_getType       (c) == AST_REAL, NULL );
  fail_unless( ASTNode_getReal       (c) == 3.0, NULL );
  fail_unless( ASTNode_getNumChildren(c) == 0  , NULL );

  c = ASTNode_getLeftChild( ASTNode_getLeftChild(r) );

  fail_unless( ASTNode_getType       (c) == AST_INTEGER, NULL );
  fail_unless( ASTNode_getInteger    (c) == 2, NULL );
  fail_unless( ASTNode_getNumChildren(c) == 0, NULL );

  c = ASTNode_getRightChild( ASTNode_getLeftChild(r) );

  fail_unless( ASTNode_getType       (c) == AST_POWER, NULL );
  fail_unless( ASTNode_getCharacter  (c) == '^', NULL );
  fail_unless( ASTNode_getNumChildren(c) == 2  , NULL );

  c = ASTNode_getLeftChild( ASTNode_getRightChild( ASTNode_getLeftChild(r) ) );

  fail_unless( ASTNode_getType(c) == AST_NAME     , NULL );
  fail_unless( !strcmp(ASTNode_getName(c), "foo") , NULL );
  fail_unless( ASTNode_getNumChildren(c) == 0     , NULL );

  c = ASTNode_getRightChild( ASTNode_getRightChild( ASTNode_getLeftChild(r) ) );

  fail_unless( ASTNode_getType(c) == AST_NAME     , NULL );
  fail_unless( !strcmp(ASTNode_getName(c), "bar") , NULL );
  fail_unless( ASTNode_getNumChildren(c) == 0     , NULL );

  ASTNode_free(r);
}
void post_ev_alter_tree_structure(Model_t *m, ASTNode_t **node_p, ASTNode_t *parent, int child_order){
  ASTNode_t *divide_node, *times_node;
  ASTNode_t *compartment_node;
  ASTNode_t *node, *next_node;
  unsigned int i;
  Species_t *sp;

  node = *node_p;
  for(i=0; i<ASTNode_getNumChildren(node); i++){
    next_node = ASTNode_getChild(node, i);
    post_ev_alter_tree_structure(m, &next_node, *node_p, i);
  }
  if(ASTNode_getType(node) == AST_NAME){
    for(i=0; i<Model_getNumSpecies(m); i++){
      sp = (Species_t*)ListOf_get(Model_getListOfSpecies(m), i);
      if(strcmp(Species_getId(sp), ASTNode_getName(node)) == 0){
        if(!Species_getHasOnlySubstanceUnits(sp) && Compartment_getSpatialDimensions(Model_getCompartmentById(m, Species_getCompartment(sp))) != 0){/* use val/comp in calculation */
          divide_node = ASTNode_createWithType(AST_DIVIDE);
          compartment_node = ASTNode_createWithType(AST_NAME);
          ASTNode_setName(compartment_node, Compartment_getId(Model_getCompartmentById(m, Species_getCompartment(sp))));
          ASTNode_addChild(divide_node, node);
          ASTNode_addChild(divide_node, compartment_node);
          if(parent != NULL){
            ASTNode_replaceChild(parent, child_order, divide_node);
          }else{
            *node_p = divide_node;
          }
          node = *node_p;
          break;
        }else if(Species_getHasOnlySubstanceUnits(sp) && Species_isSetInitialConcentration(sp) && Compartment_getSpatialDimensions(Model_getCompartmentById(m, Species_getCompartment(sp))) != 0){/*  use val*comp in calculation */
          times_node = ASTNode_createWithType(AST_TIMES);
          compartment_node = ASTNode_createWithType(AST_NAME);
          ASTNode_setName(compartment_node, Compartment_getId(Model_getCompartmentById(m, Species_getCompartment(sp))));
          ASTNode_addChild(times_node, node);
          ASTNode_addChild(times_node, compartment_node);
          if(parent != NULL){
            ASTNode_replaceChild(parent, child_order, times_node);
          }else{
            *node_p = times_node;
          }
          node = *node_p;
          break;
        }
      }
    }
  }
  return;
}
/**
 * Visits the given ASTNode and continues the inorder traversal.
 */
void
L3FormulaFormatter_visitOther ( const ASTNode_t *parent,
                                const ASTNode_t *node,
                                StringBuffer_t  *sb, 
                                const L3ParserSettings_t *settings )
{
  unsigned int numChildren = ASTNode_getNumChildren(node);
  unsigned int group       = L3FormulaFormatter_isGrouped(parent, node, settings);
  unsigned int n;


  if (group)
  {
    StringBuffer_appendChar(sb, '(');
  }

  if (numChildren == 0) {
    L3FormulaFormatter_format(sb, node, settings);
  }

  else if (numChildren == 1)
  {
    //I believe this would only be called for invalid ASTNode setups,
    // but this could in theory occur.  This is the safest 
    // behavior I can think of.
    L3FormulaFormatter_format(sb, node, settings);
    StringBuffer_appendChar(sb, '(');
    L3FormulaFormatter_visit( node, ASTNode_getChild(node, 0), sb, settings);
    StringBuffer_appendChar(sb, ')');
  }

  else {
    L3FormulaFormatter_visit( node, ASTNode_getChild(node, 0), sb, settings);

    for (n = 1; n < numChildren; n++)
    {
      L3FormulaFormatter_format(sb, node, settings);
      L3FormulaFormatter_visit( node, ASTNode_getChild(node, n), sb, settings);
    }
  }

  if (group)
  {
    StringBuffer_appendChar(sb, ')');
  }
}
Example #20
0
/**
 * Visits the given ASTNode as a function.  For this node only the
 * traversal is preorder.
 * Writes the function as a directed graph and appends the result
 * to the StringBuffer.
 */
void
FormulaGraphvizFormatter_visitFunction (const ASTNode_t *parent,
                                        const ASTNode_t *node,
                                        StringBuffer_t  *sb )
{
  unsigned int numChildren = ASTNode_getNumChildren(node);
  unsigned int n;
  char         *name;
  char         *uniqueName;
  
  uniqueName = FormulaGraphvizFormatter_getUniqueName(node);
  name       = FormulaGraphvizFormatter_format(node);
  
  StringBuffer_append(sb, uniqueName);
  StringBuffer_append(sb, " [shape=box, label=");
  StringBuffer_append(sb, name);
  StringBuffer_append(sb, "];\n");

  if (parent != NULL) 
  {
    name = FormulaGraphvizFormatter_getUniqueName(node);
    uniqueName = FormulaGraphvizFormatter_getUniqueName(parent);
    
    if(strcmp(name, uniqueName)) 
    {
      StringBuffer_append(sb, uniqueName);
      StringBuffer_append(sb, " -> ");
      StringBuffer_append(sb, name);
      StringBuffer_append(sb, ";\n");
    }
  }

  if (numChildren > 0)
  {
    FormulaGraphvizFormatter_visit( node, ASTNode_getChild(node, 0), sb );
  }

  for (n = 1; n < numChildren; n++)
  {
    FormulaGraphvizFormatter_visit( node, ASTNode_getChild(node, n), sb );
  }

}
Example #21
0
END_TEST


START_TEST (test_FunctionDefinition_getBody)
{
  const ASTNode_t *math;

  ASTNode_t * math1 = SBML_parseFormula("lambda(x, x)");

  FunctionDefinition_setMath(FD, math1 );
  math = FunctionDefinition_getBody(FD);

  fail_unless( math != NULL                        );
  fail_unless( ASTNode_isName(math)                );
  fail_unless( !strcmp(ASTNode_getName(math), "x") );
  fail_unless( ASTNode_getNumChildren(math) == 0   );

  ASTNode_free(math1);
}
void pre_ev_alter_tree_structure(ASTNode_t **node_p, ASTNode_t *parent, int child_order, ASTNode_t *delay_math){
  unsigned int i;
  ASTNode_t *node, *next_node, *delay_node;

  node = *node_p;
  for(i=0; i<ASTNode_getNumChildren(node); i++){
    next_node = ASTNode_getChild(node, i);
    pre_ev_alter_tree_structure(&next_node, *node_p, i, delay_math);
  }
  if(ASTNode_getType(node) == AST_NAME){
    delay_node = ASTNode_createWithType(AST_FUNCTION_DELAY);
    ASTNode_addChild(delay_node, node);
    ASTNode_addChild(delay_node, delay_math);
    if(parent != NULL){
      ASTNode_replaceChild(parent, child_order, delay_node);
    }else{
      *node_p = delay_node;
    }
  }
}
Example #23
0
/**
 * Visits the given ASTNode and continues the inorder traversal.
 * Writes the function as a directed graph and appends the result
 * to the StringBuffer.
 */
void
FormulaGraphvizFormatter_visitOther (const ASTNode_t *parent,
                                     const ASTNode_t *node,
                                     StringBuffer_t  *sb )
{
  unsigned int numChildren = ASTNode_getNumChildren(node);
  char         *name;
  char         *uniqueName;

  if (numChildren > 0)
  {
    uniqueName = FormulaGraphvizFormatter_getUniqueName(node);
    name       = FormulaGraphvizFormatter_format(node);
    
    StringBuffer_append(sb, uniqueName);
    StringBuffer_append(sb, " [shape=box, label=");
    StringBuffer_append(sb, name);
    StringBuffer_append(sb, "];\n");
    
    FormulaGraphvizFormatter_visit( node, ASTNode_getLeftChild(node), sb );
  }

  if (parent != NULL) 
  {
    name       = FormulaGraphvizFormatter_getUniqueName(node);
    uniqueName = FormulaGraphvizFormatter_getUniqueName(parent);
    
    if(strcmp(name, uniqueName)) 
    {
      StringBuffer_append(sb, uniqueName);
      StringBuffer_append(sb, " -> ");
      StringBuffer_append(sb, name);
      StringBuffer_append(sb, ";\n");
    }
  }

  if (numChildren > 1)
  {
    FormulaGraphvizFormatter_visit( node, ASTNode_getRightChild(node), sb );
  }
}
END_TEST


START_TEST (test_SBML_parseFormula_11)
{
  ASTNode_t *r = SBML_parseFormula("1 - -foo / 3");
  ASTNode_t *c;



  fail_unless( ASTNode_getType       (r) == AST_MINUS, NULL );
  fail_unless( ASTNode_getCharacter  (r) == '-', NULL );
  fail_unless( ASTNode_getNumChildren(r) == 2  , NULL );

  c = ASTNode_getLeftChild(r);

  fail_unless( ASTNode_getType       (c) == AST_INTEGER, NULL );
  fail_unless( ASTNode_getInteger    (c) == 1, NULL );
  fail_unless( ASTNode_getNumChildren(c) == 0, NULL );

  c = ASTNode_getRightChild(r);

  fail_unless( ASTNode_getType       (c) == AST_DIVIDE, NULL );
  fail_unless( ASTNode_getCharacter  (c) == '/', NULL );
  fail_unless( ASTNode_getNumChildren(c) == 2, NULL );

  c = ASTNode_getLeftChild( ASTNode_getRightChild(r) );

  fail_unless( ASTNode_getType       (c) == AST_MINUS, NULL );
  fail_unless( ASTNode_getCharacter  (c) == '-', NULL );
  fail_unless( ASTNode_getNumChildren(c) == 1  , NULL );

  c = ASTNode_getLeftChild( ASTNode_getLeftChild( ASTNode_getRightChild(r) ) );

  fail_unless( ASTNode_getType(c) == AST_NAME     , NULL );
  fail_unless( !strcmp(ASTNode_getName(c), "foo") , NULL );
  fail_unless( ASTNode_getNumChildren(c) == 0     , NULL );

  c = ASTNode_getRightChild( ASTNode_getRightChild(r) );

  fail_unless( ASTNode_getType       (c) == AST_INTEGER, NULL );
  fail_unless( ASTNode_getInteger    (c) == 3, NULL );
  fail_unless( ASTNode_getNumChildren(c) == 0, NULL );

  ASTNode_free(r);
}
//This function determines if the node in question should be
// expressed in the form "functioname(children)" or if
// it should be expressed as "child1 [symbol] child2 [symbol] child3"
// etc.
int
L3FormulaFormatter_isFunction (const ASTNode_t *node, 
                               const L3ParserSettings_t *settings)
{
  if (node==NULL) return 0;
  switch(ASTNode_getType(node))
  {
  case AST_PLUS:
  case AST_TIMES:
  case AST_LOGICAL_AND:
  case AST_LOGICAL_OR:
    if (ASTNode_getNumChildren(node) >= 2) {
      return 0;
    }
    return 1;

  case AST_RELATIONAL_EQ:
  case AST_RELATIONAL_GEQ:
  case AST_RELATIONAL_GT:
  case AST_RELATIONAL_LEQ:
  case AST_RELATIONAL_LT:
    if (ASTNode_getNumChildren(node) == 2) {
      return 0;
    }
    return 1;

  case AST_MINUS:
    if (ASTNode_getNumChildren(node) == 1) {
      return 0;
    }
  case AST_DIVIDE:
  case AST_RELATIONAL_NEQ:
  case AST_POWER:
  case AST_FUNCTION_POWER:
    if (ASTNode_getNumChildren(node) == 2) {
      return 0;
    }
    return 1;

  case AST_LOGICAL_NOT:
    if (ASTNode_getNumChildren(node) == 1) {
      return 0;
    }
    return 1;

  case AST_INTEGER:
  case AST_REAL:
  case AST_REAL_E:
  case AST_RATIONAL:
  case AST_NAME:
  case AST_NAME_AVOGADRO:
  case AST_NAME_TIME:
  case AST_CONSTANT_E:
  case AST_CONSTANT_FALSE:
  case AST_CONSTANT_PI:
  case AST_CONSTANT_TRUE:
  /* new elements to the enum that should not get hit */
  case AST_QUALIFIER_BVAR:
  case AST_QUALIFIER_LOGBASE:
  case AST_QUALIFIER_DEGREE:
  case AST_SEMANTICS:
  case AST_CONSTRUCTOR_PIECE:
  case AST_CONSTRUCTOR_OTHERWISE:
    return 0;

  case AST_LOGICAL_XOR:
  case AST_LAMBDA:
  case AST_FUNCTION:
  case AST_FUNCTION_ABS:
  case AST_FUNCTION_ARCCOS:
  case AST_FUNCTION_ARCCOSH:
  case AST_FUNCTION_ARCCOT:
  case AST_FUNCTION_ARCCOTH:
  case AST_FUNCTION_ARCCSC:
  case AST_FUNCTION_ARCCSCH:
  case AST_FUNCTION_ARCSEC:
  case AST_FUNCTION_ARCSECH:
  case AST_FUNCTION_ARCSIN:
  case AST_FUNCTION_ARCSINH:
  case AST_FUNCTION_ARCTAN:
  case AST_FUNCTION_ARCTANH:
  case AST_FUNCTION_CEILING:
  case AST_FUNCTION_COS:
  case AST_FUNCTION_COSH:
  case AST_FUNCTION_COT:
  case AST_FUNCTION_COTH:
  case AST_FUNCTION_CSC:
  case AST_FUNCTION_CSCH:
  case AST_FUNCTION_DELAY:
  case AST_FUNCTION_EXP:
  case AST_FUNCTION_FACTORIAL:
  case AST_FUNCTION_FLOOR:
  case AST_FUNCTION_LN:
  case AST_FUNCTION_LOG:
  case AST_FUNCTION_PIECEWISE:
  case AST_FUNCTION_ROOT:
  case AST_FUNCTION_SEC:
  case AST_FUNCTION_SECH:
  case AST_FUNCTION_SIN:
  case AST_FUNCTION_SINH:
  case AST_FUNCTION_TAN:
  case AST_FUNCTION_TANH:
  case AST_UNKNOWN:
    return 1;

    /* this one will need work */
  case AST_ORIGINATES_IN_PACKAGE:
    return 0;
  }
  //Shouldn't ever get here
  assert(0);
  return 1;
}
Example #26
0
void check_AST(ASTNode_t* node, ASTNode_t* parent) {
    unsigned int i;
    int type;
    ASTNode_t *checker;
    if(node == NULL) {
        return;
    }
    checker = parent;
    for(i=0; i<ASTNode_getNumChildren(node); i++) {
        parent = node;
        check_AST(ASTNode_getChild(node, i), parent);
    }
    type = ASTNode_getType(node);
    switch(type) {
    case AST_PLUS:
        TRACE(("+ "));
        break;
    case AST_MINUS:
        TRACE(("- "));
        break;
    case AST_TIMES:
        TRACE(("* "));
        break;
    case AST_DIVIDE:
        TRACE(("/ "));
        break;
    case AST_POWER:
        TRACE(("pow "));
        break;
    case AST_INTEGER:
        TRACE(("integer(%ld) ", ASTNode_getInteger(node)));
        break;
    case AST_REAL:
        TRACE(("real(%lf) ", ASTNode_getReal(node)));
        break;
    case AST_REAL_E:
        TRACE(("real_E "));
        break;
    case AST_RATIONAL:
        TRACE(("rational "));
        break;
    case AST_NAME:
        TRACE(("name(%s) ", ASTNode_getName(node)));
        break;
    case AST_NAME_AVOGADRO:
        TRACE(("avogadro "));
        break;
    case AST_NAME_TIME:
        TRACE(("time "));
        break;
    case AST_CONSTANT_E:
        TRACE(("constant "));
        break;
    case AST_CONSTANT_FALSE:
        TRACE(("constant_false "));
        break;
    case AST_CONSTANT_PI:
        TRACE(("pi "));
        break;
    case AST_CONSTANT_TRUE:
        TRACE(("constant_true "));
        break;
    case AST_LAMBDA:
        TRACE(("lambda "));
        break;
    case AST_FUNCTION:
        TRACE(("function(%s) ", ASTNode_getName(node)));
        break;
    case AST_FUNCTION_ABS:
        TRACE(("abs "));
        break;
    case AST_FUNCTION_ARCCOS:
        TRACE(("arccos "));
        break;
    case AST_FUNCTION_ARCCOSH:
        TRACE(("arccosh "));
        break;
    case AST_FUNCTION_ARCCOT:
        TRACE(("arccot "));
        break;
    case AST_FUNCTION_ARCCOTH:
        TRACE(("arccoth "));
        break;
    case AST_FUNCTION_ARCCSC:
        TRACE(("arccsc "));
        break;
    case AST_FUNCTION_ARCCSCH:
        TRACE(("arccsch "));
        break;
    case AST_FUNCTION_ARCSEC:
        TRACE(("arcsec "));
        break;
    case AST_FUNCTION_ARCSECH:
        TRACE(("arcsech "));
        break;
    case AST_FUNCTION_ARCSIN:
        TRACE(("arcsin "));
        break;
    case AST_FUNCTION_ARCSINH:
        TRACE(("arcsinh "));
        break;
    case AST_FUNCTION_ARCTAN:
        TRACE(("arctan "));
        break;
    case AST_FUNCTION_ARCTANH:
        TRACE(("arctanh "));
        break;
    case AST_FUNCTION_CEILING:
        TRACE(("ceil "));
        break;
    case AST_FUNCTION_COS:
        TRACE(("cos "));
        break;
    case AST_FUNCTION_COSH:
        TRACE(("cosh "));
        break;
    case AST_FUNCTION_COT:
        TRACE(("cot "));
        break;
    case AST_FUNCTION_COTH:
        TRACE(("coth "));
        break;
    case AST_FUNCTION_CSC:
        TRACE(("csc "));
        break;
    case AST_FUNCTION_CSCH:
        TRACE(("csch "));
        break;
    case AST_FUNCTION_DELAY:
        TRACE(("delay "));
        break;
    case AST_FUNCTION_EXP:
        TRACE(("exp "));
        break;
    case AST_FUNCTION_FACTORIAL:
        TRACE(("! "));
        break;
    case AST_FUNCTION_FLOOR:
        TRACE(("floor "));
        break;
    case AST_FUNCTION_LN:
        TRACE(("ln "));
        break;
    case AST_FUNCTION_LOG:
        TRACE(("log10 "));
        break;
    case AST_FUNCTION_PIECEWISE:
        TRACE(("piecewise "));
        break;
    case AST_FUNCTION_POWER:
        TRACE(("f_pow "));
        break;
    case AST_FUNCTION_ROOT:
        TRACE(("sqrt "));
        break;
    case AST_FUNCTION_SEC:
        TRACE(("sec "));
        break;
    case AST_FUNCTION_SECH:
        TRACE(("sech "));
        break;
    case AST_FUNCTION_SIN:
        TRACE(("sin "));
        break;
    case AST_FUNCTION_SINH:
        TRACE(("sinh "));
        break;
    case AST_FUNCTION_TAN:
        TRACE(("tan "));
        break;
    case AST_FUNCTION_TANH:
        TRACE(("tanh "));
        break;
    case AST_LOGICAL_AND:
        TRACE(("and "));
        break;
    case AST_LOGICAL_NOT:
        TRACE(("not "));
        break;
    case AST_LOGICAL_OR:
        TRACE(("or "));
        break;
    case AST_LOGICAL_XOR:
        TRACE(("xor "));
        break;
    case AST_RELATIONAL_EQ:
        TRACE(("eq "));
        break;
    case AST_RELATIONAL_GEQ:
        TRACE(("geq "));
        break;
    case AST_RELATIONAL_GT:
        TRACE(("gt "));
        break;
    case AST_RELATIONAL_LEQ:
        TRACE(("leq "));
        break;
    case AST_RELATIONAL_LT:
        TRACE(("lt "));
        break;
    case AST_RELATIONAL_NEQ:
        TRACE(("neq "));
        break;
    case AST_UNKNOWN:
        TRACE(("unknown "));
        break;
    }
    if(checker == NULL) {
        TRACE(("\n\n"));
    }
}
Example #27
0
/**
 * The function evalAST(ASTNode_t) evaluates the formula of an
 * Abstract Syntax Tree by simple recursion and returns the result
 * as a double value.
 *
 * If variables (ASTNodeType_t AST_NAME) occur in the formula the user is
 * asked to provide a numerical value.  When evaluating ASTs within an SBML
 * document or simulating an SBML model this node type includes parameters
 * and variables of the model.  Parameters should be retrieved from the
 * SBML file, time and variables from current values of the simulation.
 *
 * Not implemented:
 *
 *  - PIECEWISE, LAMBDA, and the SBML model specific functions DELAY and
 *    TIME and user-defined functions.
 *
 *  - Complex numbers and/or checking for domains of trigonometric and root
 *    functions.
 *
 *  - Checking for precision and rounding errors.
 *
 * The Nodetypes AST_TIME, AST_DELAY and AST_PIECEWISE default to 0.  The
 * SBML DELAY function and unknown functions (SBML user-defined functions)
 * use the value of the left child (first argument to function) or 0 if the
 * node has no children.
 */
double
evalAST(ASTNode_t *n)
{
  int    i;
  double result;
  
  int       childnum = ASTNode_getNumChildren(n);
  ASTNode_t  **child = (ASTNode_t **) malloc(childnum * sizeof(ASTNode_t*));


  for (i = 0; i < childnum; i++)
  {
    child[i] = ASTNode_getChild(n, i);
  }

  switch (ASTNode_getType(n))
  {
  case AST_INTEGER:
    result = (double) ASTNode_getInteger(n);
    break;

  case AST_REAL:
    result = ASTNode_getReal(n);
    break;

  case AST_REAL_E:
    result = ASTNode_getReal(n);
    break;

  case AST_RATIONAL:
    result = ASTNode_getReal(n);
    break;
  
  case AST_NAME:
    {
      char *l;
      double var;
      printf("\n-------------MESSAGE FROM EVALUATION FUNCTION-------------\n");
      printf("Please enter a number for the variable!\n");
      printf("If you do not enter a valid number (empty or characters), the \n");
      printf("evaluation will proceed with a current internal value and the \n");
      printf("result will make no sense.\n");
      printf("%s=",ASTNode_getName(n));
      l = get_line(stdin);
      sscanf(l, "%lf", &var);
      free(l);
      printf("%s = %f\n", ASTNode_getName(n), var);
      printf("-----------------------END MESSAGE--------------------------\n\n");
      result = var;
    }
    break;

  case AST_FUNCTION_DELAY:
    printf("\n-------------MESSAGE FROM EVALUATION FUNCTION-------------\n");
    printf("Delays can only be evaluated during a time series simulation.\n");
    printf("The value of the first child (ie. the first argument to the function)\n");
    printf("is used for this evaluation. If the function node has no children the\n");
    printf("value defaults to 0.\n");
    printf("-----------------------END MESSAGE--------------------------\n\n");
    if(i>0)
      result = evalAST(child[0]);
    else
      result = 0.0;
    break;

  case AST_NAME_TIME:
    printf("\n-------------MESSAGE FROM EVALUATION FUNCTION-------------\n");
    printf("The time can only be evaluated during a time series simulation.\n");
    printf("The value of defaults to 0\n");
    printf("-----------------------END MESSAGE--------------------------\n\n");
    result = 0.0;
    break;

  case AST_CONSTANT_E:
    /* exp(1) is used to adjust exponentiale to machine precision */
    result = exp(1);
    break;

  case AST_CONSTANT_FALSE:
    result = 0.0;
    break;

  case AST_CONSTANT_PI:
    /* pi = 4 * atan 1  is used to adjust Pi to machine precision */
    result = 4.*atan(1.);
    break;

  case AST_CONSTANT_TRUE:
    result = 1.0;
    break;

  case AST_PLUS:
    result = evalAST(child[0]) + evalAST(child[1]);
    break;

  case AST_MINUS:
    if(childnum==1)
      result = - (evalAST(child[0]));
    else
      result = evalAST(child[0]) - evalAST(child[1]);
    break;

  case AST_TIMES:
    result = evalAST(child[0]) * evalAST(child[1]) ;
    break;

  case AST_DIVIDE:
    result = evalAST(child[0]) / evalAST(child[1]);
    break;

  case AST_POWER:
    result = pow(evalAST(child[0]),evalAST(child[1]));
    break;

  case AST_LAMBDA:
    printf("\n-------------MESSAGE FROM EVALUATION FUNCTION-------------\n");
    printf("This function is not implemented yet.\n");
    printf("The value defaults to 0.\n");
    printf("-----------------------END MESSAGE--------------------------\n\n");
    result = 0.0;
    break;

  case AST_FUNCTION:
    printf("\n-------------MESSAGE FROM EVALUATION FUNCTION-------------\n");
    printf("This function is not known.\n");
    printf("Within an SBML document new functions can be defined by the user or \n");
    printf("application. The value of the first child (ie. the first argument to \n");
    printf("the function) is used for this evaluation. If the function node has\n");
    printf("no children the value defaults to 0.\n");
    printf("-----------------------END MESSAGE--------------------------\n\n");
    if(childnum>0)
      result = evalAST(child[0]);
    else
      result = 0.0;
    break;

  case AST_FUNCTION_ABS:
    result = (double) fabs(evalAST(child[0]));
    break;

  case AST_FUNCTION_ARCCOS:
    result = acos(evalAST(child[0])) ;
    break;

  case AST_FUNCTION_ARCCOSH:
#ifndef WIN32
    result = acosh(evalAST(child[0]));
#else
	result = log(evalAST(child[0]) + SQR(evalAST(child[0]) * evalAST(child[0]) - 1.));
#endif
    break;
  case AST_FUNCTION_ARCCOT:
    /* arccot x =  arctan (1 / x) */
    result = atan(1./ evalAST(child[0]));
    break;

  case AST_FUNCTION_ARCCOTH:
    /* arccoth x = 1/2 * ln((x+1)/(x-1)) */
    result = ((1./2.)*log((evalAST(child[0])+1.)/(evalAST(child[0])-1.)) );
    break;

  case AST_FUNCTION_ARCCSC:
    /* arccsc(x) = Arctan(1 / sqrt((x - 1)(x + 1))) */
    result = atan( 1. / SQRT( (evalAST(child[0])-1.)*(evalAST(child[0])+1.) ) );
    break;

  case AST_FUNCTION_ARCCSCH:
    /* arccsch(x) = ln((1 + sqrt(1 + x^2)) / x) */
    result = log((1.+SQRT((1+SQR(evalAST(child[0]))))) /evalAST(child[0]));
    break;

  case AST_FUNCTION_ARCSEC:
    /* arcsec(x) = arctan(sqrt((x - 1)(x + 1))) */
    result = atan( SQRT( (evalAST(child[0])-1.)*(evalAST(child[0])+1.) ) );
    break;

  case AST_FUNCTION_ARCSECH:
    /* arcsech(x) = ln((1 + sqrt(1 - x^2)) / x) */
    result = log((1.+pow((1-SQR(evalAST(child[0]))),0.5))/evalAST(child[0]));
    break;

  case AST_FUNCTION_ARCSIN:
    result = asin(evalAST(child[0]));
    break;
  case AST_FUNCTION_ARCSINH:
#ifndef WIN32
    result = asinh(evalAST(child[0]));
#else
	result = log(evalAST(child[0]) + SQR(evalAST(child[0]) * evalAST(child[0]) + 1.));
#endif
    break;

  case AST_FUNCTION_ARCTAN:
    result = atan(evalAST(child[0]));
    break;
  case AST_FUNCTION_ARCTANH:
#ifndef WIN32
    result = atanh(evalAST(child[0]));
#else
	result = log((1. / evalAST(child[0]) + 1.) / (1. / evalAST(child[0]) - 1.)) / 2.;
#endif
    break;

  case AST_FUNCTION_CEILING:
    result = ceil(evalAST(child[0]));
    break;

  case AST_FUNCTION_COS:
    result = cos(evalAST(child[0]));
    break;
  case AST_FUNCTION_COSH:
    result = cosh(evalAST(child[0]));
    break;

  case AST_FUNCTION_COT:
    /* cot x = 1 / tan x */
    result = (1./tan(evalAST(child[0])));
    break;
  case AST_FUNCTION_COTH:
    /* coth x = cosh x / sinh x */
    result = cosh(evalAST(child[0])) / sinh(evalAST(child[0]));
    break;
  case AST_FUNCTION_CSC:
    /* csc x = 1 / sin x */
    result = (1./sin(evalAST(child[0])));
    break;

  case AST_FUNCTION_CSCH:
    /* csch x = 1 / cosh x  */
    result = (1./cosh(evalAST(child[0])));
    break;

  case AST_FUNCTION_EXP:
    result = exp(evalAST(child[0]));
    break;

  case AST_FUNCTION_FACTORIAL:
    {
      printf("\n-------------MESSAGE FROM EVALUATION FUNCTION-------------\n");
      printf("The factorial is only implemented for integer values. If a floating\n");
      printf("point number is passed, the floor value is used for calculation!\n");
      printf("-----------------------END MESSAGE--------------------------\n\n");
      i = (int)floor(evalAST(child[0]));
      for(result=1;i>1;--i)
        result *= i;
    }
    break;

  case AST_FUNCTION_FLOOR:
    result = floor(evalAST(child[0]));
    break;

  case AST_FUNCTION_LN:
    result = log(evalAST(child[0]));
    break;

  case AST_FUNCTION_LOG:
    result = log10(evalAST(child[0]));
    break;

  case AST_FUNCTION_PIECEWISE:
    printf("\n-------------MESSAGE FROM EVALUATION FUNCTION-------------\n");
    printf("This function is not implemented yet.\n");
    printf("The value defaults to 0.\n");
    printf("-----------------------END MESSAGE--------------------------\n\n");
    result = 0.0;
    break;

  case AST_FUNCTION_POWER:
    result = pow(evalAST(child[0]),evalAST(child[1]));
    break;

  case AST_FUNCTION_ROOT:
    result = pow(evalAST(child[1]),(1./evalAST(child[0])));
    break;

  case AST_FUNCTION_SEC:
    /* sec x = 1 / cos x */
    result = 1./cos(evalAST(child[0]));
    break;

  case AST_FUNCTION_SECH:
    /* sech x = 1 / sinh x */
    result = 1./sinh(evalAST(child[0]));
    break;

  case AST_FUNCTION_SIN:
    result = sin(evalAST(child[0]));
    break;

  case AST_FUNCTION_SINH:
    result = sinh(evalAST(child[0]));
    break;

  case AST_FUNCTION_TAN:
    result = tan(evalAST(child[0]));
    break;

  case AST_FUNCTION_TANH:
    result = tanh(evalAST(child[0]));
    break;

  case AST_LOGICAL_AND:
    result = (double) ((evalAST(child[0])) && (evalAST(child[1])));
    break;

  case AST_LOGICAL_NOT:
    result = (double) (!(evalAST(child[0])));
    break;

  case AST_LOGICAL_OR:
    result = (double) ((evalAST(child[0])) || (evalAST(child[1])));
    break;

  case AST_LOGICAL_XOR:
    result = (double) ((!(evalAST(child[0])) && (evalAST(child[1])))
                       || ((evalAST(child[0])) &&  !(evalAST(child[1]))));
    break;

  case AST_RELATIONAL_EQ :
    result = (double) ((evalAST(child[0])) == (evalAST(child[1])));
    break;

  case AST_RELATIONAL_GEQ:
    result = (double) ((evalAST(child[0])) >= (evalAST(child[1])));
    break;

  case AST_RELATIONAL_GT:
    result = (double) ((evalAST(child[0])) > (evalAST(child[1])));
    break;

  case AST_RELATIONAL_LEQ:
    result = (double) ((evalAST(child[0])) <= (evalAST(child[1])));
    break;

  case AST_RELATIONAL_LT :
    result = (double) ((evalAST(child[0])) < (evalAST(child[1])));
    break;

  default:
    result = 0;
    break;
  }

  free(child);

  return result;
}
Example #28
0
SBML_ODESOLVER_API double evaluateAST(ASTNode_t *n, cvodeData_t *data)
{
  int i, j, childnum;
  int found, datafound;
  int true;
  time_series_t *ts=data->model->time_series;
  double findtol=1e-5;
 
  ASTNodeType_t type;
  /* ASTNode_t **child; */

  /* value* are for intermediate values. */
  double value1, value2, value3, result;

  if ( n == NULL )
  {
    SolverError_error(FATAL_ERROR_TYPE,
		      SOLVER_ERROR_AST_UNKNOWN_NODE_TYPE,
		      "evaluateAST: empty Abstract Syntax Tree (AST).");
    return (0);
  }
  if ( ASTNode_isUnknown(n) )
  {
    SolverError_error(FATAL_ERROR_TYPE,
		      SOLVER_ERROR_AST_UNKNOWN_NODE_TYPE,
		      "evaluateAST: unknown ASTNode type");
  }
  result = 0;

  childnum = ASTNode_getNumChildren(n);
  type = ASTNode_getType(n);
  switch(type)
  {
  case AST_INTEGER:
    result = (double) ASTNode_getInteger(n);      
    break;
  case AST_REAL:
    result = ASTNode_getReal(n);
    break;
  case AST_REAL_E:
    result = ASTNode_getReal(n);
    break;      
  case AST_RATIONAL:
    result = ASTNode_getReal(n) ;
    break;
	
  case AST_NAME:
    /** VARIABLES:

    find the value of the variable in the data->value
    array. SOSlib's extension to libSBML's AST allows to add the
    index of the variable in this array to AST_NAME
    (ASTIndexName). If the ASTNode is not indexed, its array
    index is searched via the data->model->names array, which
    corresponds to the data->value array. For nodes with name
    `Time' or `time' the data->currenttime is returned.  If no
    value is found a fatal error is produced. */
    found = 0;
    if ( ASTNode_isSetIndex(n) )
    {
      if ( ASTNode_isSetData(n) )
      {

        /* if continuous data is observed, obtain interpolated result */  
        if ( (data->model->discrete_observation_data != 1) || (data->model->compute_vector_v != 1) )
	{
	  result = call(ASTNode_getIndex(n),
			data->currenttime, ts);

	}
	else  /* if discrete data is observed, simply obtain value from time_series */
	{
          datafound = 0;
          i = data->TimeSeriesIndex;
        
	    if ( fabs(data->currenttime - ts->time[i]) < findtol )
	    {    
	      result = ts->data[ASTNode_getIndex(n)][i];
              datafound++;
	    }
	
          if ( datafound != 1)
	  {	            
	    SolverError_error(FATAL_ERROR_TYPE,
			SOLVER_ERROR_AST_EVALUATION_FAILED_DISCRETE_DATA,
			"use of discrete time series data failed; none or several time points matching current time");
	    result = 0;
           /*  break;  */
	  }
          else found = 1;

	}
      }
      else
      {
	/* majority case: just return the
	   according value from data->values
	   from the index stored by SOSlib
	   ASTIndexNameNode sub-class of libSBML's ASTNode */
	result = data->value[ASTNode_getIndex(n)];
  
      }
      
       found++;
    }

    if ( found == 0 )
    {
      for ( j=0; j<data->nvalues; j++ )
      {
	if ( (strcmp(ASTNode_getName(n),data->model->names[j]) == 0) )
	{
	  
	  result = data->value[j];
	  found++;
	}
      }
    }

    if ( found == 0 )
    {
      SolverError_error(FATAL_ERROR_TYPE,
			SOLVER_ERROR_AST_EVALUATION_FAILED_MISSING_VALUE,
			"No value found for AST_NAME %s . Defaults to Zero "
			"to avoid program crash", ASTNode_getName(n));
      result = 0;
    }
    break;

  case AST_FUNCTION_DELAY:
    SolverError_error(FATAL_ERROR_TYPE,
		      SOLVER_ERROR_AST_EVALUATION_FAILED_DELAY,
		      "Solving ODEs with Delay is not implemented. "
		      "Defaults to 0 to avoid program crash");
    result = 0.0;
    break;
  case AST_NAME_TIME:
    result = (double) data->currenttime;
    break;
	
  case AST_CONSTANT_E:
    /** exp(1) is used to adjust exponentiale to machine precision */
    result = exp(1.);
    break;
  case AST_CONSTANT_FALSE:
    result = 0.0;
    break;
  case AST_CONSTANT_PI:
    /** pi = 4 * atan 1  is used to adjust Pi to machine precision */
    result = 4.*atan(1.);
    break;
  case AST_CONSTANT_TRUE:
    result = 1.0;
    break;

  case AST_PLUS:
    result = 0.0;
    for ( i=0; i<childnum; i++) 
      result += evaluateAST(child(n,i),data);   
    break;      
  case AST_MINUS:
    if ( childnum<2 )
      result = - (evaluateAST(child(n,0),data));
    else
      result = evaluateAST(child(n,0),data) - evaluateAST(child(n,1),data);
    break;
  case AST_TIMES:
    result = 1.0;
    for ( i=0; i<childnum; i++)
    {
      result *= evaluateAST(child(n,i),data);
      if (result == 0.0) break; /* small optimization by skipping the rest of children */
    }
    break;
  case AST_DIVIDE:
    result = evaluateAST(child(n,0),data) / evaluateAST(child(n,1),data);
    break;
  case AST_POWER:
    result = pow(evaluateAST(child(n,0),data),evaluateAST(child(n,1),data));
    break;
  case AST_LAMBDA:
    SolverError_error(FATAL_ERROR_TYPE,
		      SOLVER_ERROR_AST_EVALUATION_FAILED_LAMBDA,
		      "Lambda can only be used in SBML function definitions."
		      " Defaults to 0 to avoid program crash");
    result = 0.0;
    break;
    /** FUNCTIONS: */
  case AST_FUNCTION:
    /**  Evaluate external functions, if it was set with
	 setUserDefinedFunction */      
    if ( UsrDefFunc == NULL )
    {
      SolverError_error(FATAL_ERROR_TYPE,
			SOLVER_ERROR_AST_EVALUATION_FAILED_FUNCTION,
			"The function %s() has not been defined "
			"in the SBML input model or as an externally "
			"supplied function. Defaults to 0 to avoid "
			"program crash",
			ASTNode_getName(n));
      result = 0.0;
    }
    else
    {
      double *func_vals = NULL;
      ASSIGN_NEW_MEMORY_BLOCK(func_vals, childnum+1, double, 0);
      for ( i=0; i<childnum; i++ ) 
	func_vals[i] = evaluateAST(child(n,i), data);      
      result = UsrDefFunc((char *)ASTNode_getName(n), childnum, func_vals);
      free(func_vals);
    }
    break;
  case AST_FUNCTION_ABS:
    result = fabs(evaluateAST(child(n,0),data));
    break;
  case AST_FUNCTION_ARCCOS:
    result = acos(evaluateAST(child(n,0),data)) ;
    break;
  case AST_FUNCTION_ARCCOSH:
    result = aCosh(evaluateAST(child(n,0),data));
    break;
  case AST_FUNCTION_ARCCOT:
    /** arccot x =  arctan (1 / x) */
    result = atan(1./ evaluateAST(child(n,0),data));
    break;
  case AST_FUNCTION_ARCCOTH:
    /** arccoth x = 1/2 * ln((x+1)/(x-1)) */
    value1 = evaluateAST(child(n,0),data);
    result = log((value1 + 1) / (value1 - 1))/2;
    break;
  case AST_FUNCTION_ARCCSC:
    /** arccsc(x) = Arctan(1 / sqrt((x - 1)(x + 1))) */
    value1 = evaluateAST(child(n,0),data);
    result = atan(1/sqrt((value1-1)*(value1+1)));
    break;
  case AST_FUNCTION_ARCCSCH:
    /** arccsch(x) = ln((1/x) + sqrt((1/(x*x)) + 1)) */
    value1 = evaluateAST(child(n,0),data);
    result = log(1/value1 + sqrt(1/(value1*value1)+1));
    break;
  case AST_FUNCTION_ARCSEC:
    /** arcsec(x) = arccos(1/x) */
    result = acos(1/evaluateAST(child(n,0),data));
    break;
  case AST_FUNCTION_ARCSECH:
    /* arcsech(x) = arccosh(1/x) */
    result = aCosh( 1. /  evaluateAST(child(n,0),data));
    break;
  case AST_FUNCTION_ARCSIN:
    result = asin(evaluateAST(child(n,0),data));
    break;
  case AST_FUNCTION_ARCSINH:
    result = aSinh(evaluateAST(child(n,0),data));
    break;
  case AST_FUNCTION_ARCTAN:
    result = atan(evaluateAST(child(n,0),data));
    break;
  case AST_FUNCTION_ARCTANH:
    result = aTanh(evaluateAST(child(n,0),data));
    break;
  case AST_FUNCTION_CEILING:
    result = ceil(evaluateAST(child(n,0),data));
    break;
  case AST_FUNCTION_COS:
    result = cos(evaluateAST(child(n,0),data));
    break;
  case AST_FUNCTION_COSH:
    result = cosh(evaluateAST(child(n,0),data));
    break;
  case AST_FUNCTION_COT:
    /** cot x = 1 / tan x */
    result = (1./tan(evaluateAST(child(n,0),data)));
    break;
  case AST_FUNCTION_COTH:
    /** coth x = cosh x / sinh x */
    result = 1/tanh(evaluateAST(child(n,0),data));
    break;  
  case AST_FUNCTION_CSC:
    /** csc x = 1 / sin x */
    result = (1./sin(evaluateAST(child(n,0),data)));
    break;
  case AST_FUNCTION_CSCH:
    /** csch x = 1 / sinh x  */
    result = (1./sinh(evaluateAST(child(n,0),data)));
    break;
  case AST_FUNCTION_EXP:
    result = exp(evaluateAST(child(n,0),data));
    break;
  case AST_FUNCTION_FACTORIAL:
    {
      int j;
      value1 = evaluateAST(child(n,0),data);
      j = floor(value1);
      if ( value1 != j )
	SolverError_error(FATAL_ERROR_TYPE,
			  SOLVER_ERROR_AST_EVALUATION_FAILED_FLOAT_FACTORIAL,
			  "The factorial is only implemented."
			  "for integer values. The floor value of the "
			  "passed float is used for calculation!");

      for(result=1;j>1;--j)
	result *= j;
    }
    break;
  case AST_FUNCTION_FLOOR:
    result = floor(evaluateAST(child(n,0),data));
    break;
  case AST_FUNCTION_LN:
    result = log(evaluateAST(child(n,0),data));
    break;
  case AST_FUNCTION_LOG:
    /** log(x,y) = log10(y)/log10(x) (where x is the base)  */
    result = log10(evaluateAST(child(n,1),data)) /
      log10(evaluateAST(child(n,0),data));
    break;
  case AST_FUNCTION_PIECEWISE:
    /** Piecewise: */
    found = 0;
    /** Go through n pieces with 2 AST children for each piece, */
    for ( i=0; i<(childnum-1); i=i+2 )
    {
      if ( evaluateAST(child(n, i+1), data) )
      {
	found++;
	result = evaluateAST(child(n, i), data);
      }
    }
    /** odd number of AST children: if no piece was true, otherwise remains */
    /* i should be equal to childnum for even number piecewise AST
       and equal to childnum-1 for odd numbered piecewise ASTs */
    if ( i == childnum-1 && found == 0 )
    {
      found++;
      result = evaluateAST(child(n, i), data);
    }
    if ( found == 0 )
      SolverError_error(FATAL_ERROR_TYPE,
			SOLVER_ERROR_AST_EVALUATION_FAILED_PIECEWISE,
			"Piecewise function failed; no true piece");
    if ( found > 1 )
      SolverError_error(FATAL_ERROR_TYPE,
			SOLVER_ERROR_AST_EVALUATION_FAILED_PIECEWISE,
			"Piecewise function failed; several true pieces");
    break;
  case AST_FUNCTION_POWER:
    result = pow(evaluateAST(child(n,0),data),evaluateAST(child(n,1),data));
    break;
  case AST_FUNCTION_ROOT:
    /*!!! ALSO do this in compiled code */
    value1 = evaluateAST(child(n,1),data);
    value2 = evaluateAST(child(n,0),data);
    value3 = floor(value2);
    /* for odd root degrees, negative numbers are OK */
    if ( value2 == value3 ) /* check whether degree is integer */
    {
      if ( (value1 < 0) && ((int)value2 % 2 != 0) )
	result = - pow(fabs(value1), 1./value2);
      else
	result = pow(value1, 1./value2);	
    }
    else
      result = pow(value1, 1./value2);
    break;
  case AST_FUNCTION_SEC:
    /** sec x = 1 / cos x */
    result = 1./cos(evaluateAST(child(n,0),data));
    break;
  case AST_FUNCTION_SECH:
    /** sech x = 1 / cosh x */
    result = 1./cosh(evaluateAST(child(n,0),data));
    break;
  case AST_FUNCTION_SIN:
    result = sin(evaluateAST(child(n,0),data));
    break;
  case AST_FUNCTION_SINH:
    result = sinh(evaluateAST(child(n,0),data));
    break;
  case AST_FUNCTION_TAN:
    result = tan(evaluateAST(child(n,0),data));
    break;
  case AST_FUNCTION_TANH:
    result = tanh(evaluateAST(child(n,0),data));
    break;

  case AST_LOGICAL_AND:
    /** AND: all children must be true */
    true = 0;
    for ( i=0; i<childnum; i++ ) true += evaluateAST(child(n,i),data);
    if ( true == childnum ) result = 1.0;
    else result = 0.0;
    break;
  case AST_LOGICAL_NOT:
    result = (double) (!(evaluateAST(child(n,0),data)));
    break;
  case AST_LOGICAL_OR:
    /** OR: at least one child must be true */
    true = 0;
    for ( i=0; i<childnum; i++ ) true += evaluateAST(child(n,i),data);    
    if ( true > 0 ) result = 1.0;
    else result = 0.0;
    break;
  case AST_LOGICAL_XOR:
    /* n-ary: true if an odd number of children is true */
    true = 0;
    for ( i=0; i<childnum; i++ ) true += evaluateAST(child(n,i),data);    
    if ( true % 2 != 0 ) result = 1.0;
    else result = 0.0;
    break;
    /* !!! check n-ary definitions for relational operators !!! */
  case AST_RELATIONAL_EQ:
    /** n-ary: all children must be equal */
    result = 1.0;
    if (childnum <= 1) break;
    value1 = evaluateAST(child(n,0),data);
    for ( i=1; i<childnum; i++ )
      if ( value1 != evaluateAST(child(n,i),data) )
      {
        result = 0.0;
        break;
      }
    break;
  case AST_RELATIONAL_GEQ:
    /** n-ary: each child must be greater than or equal to the following */
    result = 1.0;
    if (childnum <= 1) break;
    value2 = evaluateAST(child(n,0),data);
    for ( i=1; i<childnum; i++ )
    {
      value1 = value2;
      value2 = evaluateAST(child(n,i),data);
      if (value1 < value2)
      {
        result = 0.0;
        break;
      }
    }
    break;
  case AST_RELATIONAL_GT:
    /** n-ary: each child must be greater than the following */
    result = 1.0;
    if (childnum <= 1) break;
    value2 = evaluateAST(child(n,0),data);
    for ( i=1; i<childnum; i++ )
    {
      value1 = value2;
      value2 = evaluateAST(child(n,i),data);
      if (value1 <= value2)
      {
        result = 0.0;
        break;
      }
    }
    break;
  case AST_RELATIONAL_LEQ:
    /** n-ary: each child must be lower than or equal to the following */
    result = 1.0;
    if (childnum <= 1) break;
    value2 = evaluateAST(child(n,0),data);
    for ( i=1; i<childnum; i++ )
    {
      value1 = value2;
      value2 = evaluateAST(child(n,i),data);
      if (value1 > value2)
      {
        result = 0.0;
        break;
      }
    }
    break;
  case AST_RELATIONAL_LT :
    /* n-ary: each child must be lower than the following */
    result = 1.0;
    if (childnum <= 1) break;
    value2 = evaluateAST(child(n,0),data);
    for ( i=1; i<childnum; i++ )
    {
      value1 = value2;
      value2 = evaluateAST(child(n,i),data);
      if (value1 >= value2)
      {
        result = 0.0;
        break;
      }
    }
    break;
  case AST_RELATIONAL_NEQ:
    /* binary "not equal" */
    result = (evaluateAST(child(n, 0), data) != evaluateAST(child(n, 1), data));
    break;
  default:
    SolverError_error(FATAL_ERROR_TYPE,
                      SOLVER_ERROR_AST_UNKNOWN_NODE_TYPE,
                      "evaluateAST: unknown ASTNode type: %d", type);
    result = 0;
    break;
  }
  
  return result;
}
/* Used by getL3Precedence and other functions below.
 */
int isTranslatedModulo (const ASTNode_t* node)
{
  const ASTNode_t* child;
  const ASTNode_t* c2;
  const ASTNode_t* x;
  const ASTNode_t* y;
  //In l3v2 there may be an actual 'modulo' ASTNode, but for now,
  // it's all mimicked by the piecewise function:
  // piecewise(x - y * ceil(x / y), xor(x < 0, y < 0), x - y * floor(x / y))

  if (ASTNode_getType(node) != AST_FUNCTION_PIECEWISE) return 0;
  if (ASTNode_getNumChildren(node) != 3) return 0;

  //x - y * ceil(x/y)
  child = ASTNode_getChild(node, 0);
  if (ASTNode_getType(child) != AST_MINUS) return 0;
  if (ASTNode_getNumChildren(child) != 2) return 0;
  x  = ASTNode_getChild(child, 0);

  c2 = ASTNode_getChild(child, 1);
  if (ASTNode_getType(c2) != AST_TIMES) return 0;
  if (ASTNode_getNumChildren(c2) != 2) return 0;
  y = ASTNode_getChild(c2, 0);
  c2 = ASTNode_getChild(c2, 1);
  if (ASTNode_getType(c2) != AST_FUNCTION_CEILING) return 0;
  if (ASTNode_getNumChildren(c2) != 1) return 0;
  c2 = ASTNode_getChild(c2, 0);
  if (ASTNode_getType(c2) != AST_DIVIDE) return 0;
  if (ASTNode_getNumChildren(c2) != 2) return 0;
  if (!equals(x, ASTNode_getChild(c2, 0))) return 0;
  if (!equals(y, ASTNode_getChild(c2, 1))) return 0;

  //xor(x<0, y<0)
  child = ASTNode_getChild(node, 1);
  if (ASTNode_getType(child) != AST_LOGICAL_XOR) return 0;
  if (ASTNode_getNumChildren(child) != 2) return 0;
  c2 = ASTNode_getChild(child, 0);
  if (ASTNode_getType(c2) != AST_RELATIONAL_LT) return 0;
  if (ASTNode_getNumChildren(c2) != 2) return 0;
  if (!equals(x, ASTNode_getChild(c2, 0))) return 0;
  if (ASTNode_getType(ASTNode_getChild(c2, 1)) != AST_INTEGER) return 0;
  if (ASTNode_getInteger(ASTNode_getChild(c2, 1)) != 0) return 0;
  c2 = ASTNode_getChild(child, 1);
  if (ASTNode_getType(c2) != AST_RELATIONAL_LT) return 0;
  if (ASTNode_getNumChildren(c2) != 2) return 0;
  if (!equals(y, ASTNode_getChild(c2, 0))) return 0;
  if (ASTNode_getType(ASTNode_getChild(c2, 1)) != AST_INTEGER) return 0;
  if (ASTNode_getInteger(ASTNode_getChild(c2, 1)) != 0) return 0;

  //x - y * floor(x/y)
  child = ASTNode_getChild(node, 2);
  if (ASTNode_getType(child) != AST_MINUS) return 0;
  if (ASTNode_getNumChildren(child) != 2) return 0;
  if (!equals(x, ASTNode_getChild(child, 0))) return 0;

  c2 = ASTNode_getChild(child, 1);
  if (ASTNode_getType(c2) != AST_TIMES) return 0;
  if (ASTNode_getNumChildren(c2) != 2) return 0;
  if (!equals(y, ASTNode_getChild(c2, 0))) return 0;
  c2 = ASTNode_getChild(c2, 1);
  if (ASTNode_getType(c2) != AST_FUNCTION_FLOOR) return 0;
  if (ASTNode_getNumChildren(c2) != 1) return 0;
  c2 = ASTNode_getChild(c2, 0);
  if (ASTNode_getType(c2) != AST_DIVIDE) return 0;
  if (ASTNode_getNumChildren(c2) != 2) return 0;
  if (!equals(x, ASTNode_getChild(c2, 0))) return 0;
  if (!equals(y, ASTNode_getChild(c2, 1))) return 0;

  return 1;
}
/*
 * @return the precedence of this ASTNode as defined in the L3 parser documentation.
 */
int getL3Precedence(const ASTNode_t* node)
{
  int precedence;
  unsigned int numchildren = ASTNode_getNumChildren(node);

  if ( !ASTNode_hasCorrectNumberArguments((ASTNode_t*)node) )
  {
    //If the number of arguments is wrong, it'll be treated like a function call.
    precedence = 8;
  }
  else if ( isTranslatedModulo(node) )
  {
    precedence = 5;
  }
  else
  {
    switch (ASTNode_getType(node))
    {
      case AST_POWER:
      case AST_FUNCTION_POWER:
        //Anything other than two children is caught above, since that's the only correct number of arguments.
        precedence = 7;
        break;

      case AST_LOGICAL_NOT:
        //Anything other than unary not is caught above, since that's the wrong number of arguments.
        precedence = 6;
        break;

      case AST_DIVIDE:
      case AST_TIMES:
        if (numchildren < 2) {
          //Written in functional form.
          precedence = 8;
        }
        else {
          precedence = 5;
        }
        break;

      case AST_MINUS:
        if (numchildren == 1) {
          //Unary minus
          precedence = 6;
          break;
        }
        //Fallthrough to:
      case AST_PLUS:
        if (numchildren < 2) {
          //Written in functional form (unary minus caught above)
          precedence = 8;
        }
        else {
          precedence = 4;
        }
        break;

      case AST_RELATIONAL_EQ:
      case AST_RELATIONAL_GEQ:
      case AST_RELATIONAL_GT:
      case AST_RELATIONAL_LEQ:
      case AST_RELATIONAL_LT:
      case AST_RELATIONAL_NEQ:
        //The relational symbols (==, >=, etc.) are only used when there are two children.
        if (numchildren == 2) {
          precedence = 3;
        }
        else {
          precedence = 8;
        }
        break;

      case AST_LOGICAL_AND:
      case AST_LOGICAL_OR:
        //The logical symbols && and || are only used when there are two or more children.
        if (numchildren < 2) {
          precedence = 8;
        }
        else {
          precedence = 2;
        }
        break;

      default:
        precedence = 8;
        break;
    }
  }

  return precedence;
}