void determineFullTraversal(nodeptr p, tree *tr)
{
  nodeptr q = p->back;
  int k;

  tr->td[0].ti[0].pNumber = p->number;
  tr->td[0].ti[0].qNumber = q->number;

  for(k = 0; k < tr->numBranches; k++)        
    tr->td[0].ti[0].qz[k] = q->z[k];    

  assert(isTip(p->number, tr->mxtips));

  tr->td[0].count = 1; 
  computeFullTraversalInfo(q, &(tr->td[0].ti[0]),  &(tr->td[0].count), tr->mxtips, tr->numBranches); 
  computeFullTraversalInfo(p, &(tr->td[0].ti[0]),  &(tr->td[0].count), tr->mxtips, tr->numBranches);
}
void determineFullTraversal(nodeptr p, tree *tr)
{
  nodeptr q = p->back;
  int k;

  tr->td[0].ti[0].pNumber = p->number;
  tr->td[0].ti[0].qNumber = q->number;

  for(k = 0; k < tr->numBranches; k++)        
    tr->td[0].ti[0].qz[k] = q->z[k];    

#ifdef _BASTIEN 
  if(tr->doBastienStuff)
    {
      for(k = 0; k < tr->numBranches; k++) 
	{	
	  assert(q->secondDerivative[k] == q->back->secondDerivative[k]);
	  assert(p->secondDerivative[k] == p->back->secondDerivative[k]);
	  assert(q->secondDerivativeValid[k] && q->back->secondDerivativeValid[k]);
	  assert(p->secondDerivativeValid[k] && p->back->secondDerivativeValid[k]);
	}
      
      for(k = 0; k < tr->numBranches; k++)
	{
	  tr->td[0].ti[0].secondDerivativeQ[k] = q->secondDerivative[k];
	  tr->td[0].ti[0].secondDerivativeP[k] = p->secondDerivative[k];     
	}

      //printf("Start %f %f\n", q->secondDerivative[0],  p->secondDerivative[0]);
    }
#endif	    

  assert(isTip(p->number, tr->mxtips));

  tr->td[0].count = 1; 
  computeFullTraversalInfo(tr, q, &(tr->td[0].ti[0]),  &(tr->td[0].count), tr->mxtips, tr->numBranches); 
  computeFullTraversalInfo(tr, p, &(tr->td[0].ti[0]),  &(tr->td[0].count), tr->mxtips, tr->numBranches);
}
void computeFullTraversalInfo(nodeptr p, traversalInfo *ti, int *counter, int maxTips, int numBranches)
{
  if(isTip(p->number, maxTips))
    return; 

  {     
    int i;
    nodeptr q = p->next->back;
    nodeptr r = p->next->next->back;

    /* set xnode info at this point */

    p->x = 1;
    p->next->x = 0;
    p->next->next->x = 0;     

    if(isTip(r->number, maxTips) && isTip(q->number, maxTips))
      {	  
	ti[*counter].tipCase = TIP_TIP; 
	ti[*counter].pNumber = p->number;
	ti[*counter].qNumber = q->number;
	ti[*counter].rNumber = r->number;

	for(i = 0; i < numBranches; i++)
	  {
	    double z;
	    z = q->z[i];
	    z = (z > zmin) ? log(z) : log(zmin);
	    ti[*counter].qz[i] = z;

	    z = r->z[i];
	    z = (z > zmin) ? log(z) : log(zmin);
	    ti[*counter].rz[i] = z;	    
	  }     
	*counter = *counter + 1;
      }  
    else
      {
	if(isTip(r->number, maxTips) || isTip(q->number, maxTips))
	  {		
	    nodeptr tmp;

	    if(isTip(r->number, maxTips))
	      {
		tmp = r;
		r = q;
		q = tmp;
	      }
	    
	    computeFullTraversalInfo(r, ti, counter, maxTips, numBranches);	
	    	   
	    ti[*counter].tipCase = TIP_INNER; 
	    ti[*counter].pNumber = p->number;
	    ti[*counter].qNumber = q->number;
	    ti[*counter].rNumber = r->number;

	    for(i = 0; i < numBranches; i++)
	      {
		double z;
		z = q->z[i];
		z = (z > zmin) ? log(z) : log(zmin);
		ti[*counter].qz[i] = z;
		
		z = r->z[i];
		z = (z > zmin) ? log(z) : log(zmin);
		ti[*counter].rz[i] = z;		
	      }   
	    
	    *counter = *counter + 1;
	  }
	else
	  {	 	  
	    computeFullTraversalInfo(q, ti, counter, maxTips, numBranches);	       
	    computeFullTraversalInfo(r, ti, counter, maxTips, numBranches);
	   
	    ti[*counter].tipCase = INNER_INNER; 
	    ti[*counter].pNumber = p->number;
	    ti[*counter].qNumber = q->number;
	    ti[*counter].rNumber = r->number;
	    for(i = 0; i < numBranches; i++)
	      {
		double z;
		z = q->z[i];
		z = (z > zmin) ? log(z) : log(zmin);
		ti[*counter].qz[i] = z;
		
		z = r->z[i];
		z = (z > zmin) ? log(z) : log(zmin);
		ti[*counter].rz[i] = z;		
	      }   
	    
	    *counter = *counter + 1;
	  }
      }    
  }
}
void computeFullTraversalInfo(tree *tr, nodeptr p, traversalInfo *ti, int *counter, int maxTips, int numBranches)
{
  if(isTip(p->number, maxTips))
    return; 

  {     
    int i;
    nodeptr q = p->next->back;
    nodeptr r = p->next->next->back;

#ifdef _HET
    boolean
      parentIsTip;
    
    if(isTip(p->back->number, maxTips))      
      parentIsTip = TRUE;            
    else      
      parentIsTip = FALSE;
#endif

    /* set xnode info at this point */

    p->x = 1;
    p->next->x = 0;
    p->next->next->x = 0;     

    if(isTip(r->number, maxTips) && isTip(q->number, maxTips))
      {	  
	ti[*counter].tipCase = TIP_TIP; 
	ti[*counter].pNumber = p->number;
	ti[*counter].qNumber = q->number;
	ti[*counter].rNumber = r->number;
#ifdef _HET
	ti[*counter].parentIsTip = parentIsTip;
#endif
	for(i = 0; i < numBranches; i++)
	  {
	    double z;

	    z = q->z[i];
	    z = (z > zmin) ? log(z) : log(zmin);
	    ti[*counter].qz[i] = z;

	    z = r->z[i];
	    z = (z > zmin) ? log(z) : log(zmin);
	    ti[*counter].rz[i] = z;	    

#ifdef _BASTIEN
	    if(tr->doBastienStuff)
	      {
		assert(q->secondDerivative[i] == q->back->secondDerivative[i]);
		assert(r->secondDerivative[i] == r->back->secondDerivative[i]);
		assert(q->secondDerivativeValid[i] && q->back->secondDerivativeValid[i]);
		assert(r->secondDerivativeValid[i] && r->back->secondDerivativeValid[i]);
	      }


	    ti[*counter].secondDerivativeQ[i] = q->secondDerivative[i];
	    ti[*counter].secondDerivativeR[i] = r->secondDerivative[i];
#endif
	  }     
	*counter = *counter + 1;
      }  
    else
      {
	if(isTip(r->number, maxTips) || isTip(q->number, maxTips))
	  {		
	    nodeptr tmp;

	    if(isTip(r->number, maxTips))
	      {
		tmp = r;
		r = q;
		q = tmp;
	      }
	    
	    computeFullTraversalInfo(tr, r, ti, counter, maxTips, numBranches);	
	    	   
	    ti[*counter].tipCase = TIP_INNER; 
	    ti[*counter].pNumber = p->number;
	    ti[*counter].qNumber = q->number;
	    ti[*counter].rNumber = r->number;
#ifdef _HET
	    ti[*counter].parentIsTip = parentIsTip;
#endif
	    for(i = 0; i < numBranches; i++)
	      {
		double z;
		z = q->z[i];
		z = (z > zmin) ? log(z) : log(zmin);
		ti[*counter].qz[i] = z;
		
		z = r->z[i];
		z = (z > zmin) ? log(z) : log(zmin);
		ti[*counter].rz[i] = z;		

#ifdef _BASTIEN
		if(tr->doBastienStuff)
		  {
		    assert(q->secondDerivative[i] == q->back->secondDerivative[i]);
		    assert(r->secondDerivative[i] == r->back->secondDerivative[i]);
		    assert(q->secondDerivativeValid[i] && q->back->secondDerivativeValid[i]);
		    assert(r->secondDerivativeValid[i] && r->back->secondDerivativeValid[i]);
		  }

		ti[*counter].secondDerivativeQ[i] = q->secondDerivative[i];
		ti[*counter].secondDerivativeR[i] = r->secondDerivative[i];
#endif
	      }   
	    
	    *counter = *counter + 1;
	  }
	else
	  {	 	  
	    computeFullTraversalInfo(tr, q, ti, counter, maxTips, numBranches);	       
	    computeFullTraversalInfo(tr, r, ti, counter, maxTips, numBranches);
	   
	    ti[*counter].tipCase = INNER_INNER; 
	    ti[*counter].pNumber = p->number;
	    ti[*counter].qNumber = q->number;
	    ti[*counter].rNumber = r->number;
#ifdef _HET
	    ti[*counter].parentIsTip = parentIsTip;
#endif

	    for(i = 0; i < numBranches; i++)
	      {
		double z;
		z = q->z[i];
		z = (z > zmin) ? log(z) : log(zmin);
		ti[*counter].qz[i] = z;
		
		z = r->z[i];
		z = (z > zmin) ? log(z) : log(zmin);
		ti[*counter].rz[i] = z;		

#ifdef _BASTIEN
		if(tr->doBastienStuff)
		  {
		    assert(q->secondDerivative[i] == q->back->secondDerivative[i]);
		    assert(r->secondDerivative[i] == r->back->secondDerivative[i]);
		    assert(q->secondDerivativeValid[i] && q->back->secondDerivativeValid[i]);
		    assert(r->secondDerivativeValid[i] && r->back->secondDerivativeValid[i]);
		  }
		
		ti[*counter].secondDerivativeQ[i] = q->secondDerivative[i];
		ti[*counter].secondDerivativeR[i] = r->secondDerivative[i];
#endif
	      }   
	    
	    *counter = *counter + 1;
	  }
      }    
  }
}