void NNIupdateAverages( double[][] A, edge e, edge par, edge skew, 
		edge swap, edge fixed )
	{
		node v;
		edge elooper;
		v = e.head;
		//first, v
		A[e.head.index][e.head.index] =  
			(swap.bottomsize* 
			((skew.bottomsize*A[skew.head.index][swap.head.index]
			+ fixed.bottomsize*A[fixed.head.index][swap.head.index]) 
			/ e.bottomsize) +
			par.topsize*
			((skew.bottomsize*A[skew.head.index][par.head.index]
			+ fixed.bottomsize*A[fixed.head.index][par.head.index]) 
			/ e.bottomsize)
			) / e.topsize; 
		// next, we loop over all the edges 
		// which are below e
		elooper = e.findBottomLeft(); 
		while ( e != elooper )  
		{
			A[e.head.index][elooper.head.index] = 
				A[elooper.head.index][v.index] 
		        = (swap.bottomsize*A[elooper.head.index][swap.head.index] +
	   	        par.topsize*A[elooper.head.index][par.head.index]) 
	            / e.topsize;
                elooper = depthFirstTraverse(elooper);
		}
		// next we loop over all the edges below and
	    // including swap
		elooper = swap.findBottomLeft();   
		while (swap != elooper)
		{
			A[e.head.index][elooper.head.index] = 
				A[elooper.head.index][e.head.index]
				= (skew.bottomsize * A[elooper.head.index][skew.head.index] + 
				fixed.bottomsize*A[elooper.head.index][fixed.head.index]) 
				/ e.bottomsize;
			elooper = depthFirstTraverse(elooper);
		}
		// now elooper = skew
		A[e.head.index][elooper.head.index] = 
			A[elooper.head.index][e.head.index]
			= (skew.bottomsize * A[elooper.head.index][skew.head.index] + 
			fixed.bottomsize* A[elooper.head.index][fixed.head.index])	
			/ e.bottomsize;

		// finally, we loop over all the edges in the tree 
 		// on the far side of parEdge
		elooper = root.leftEdge;
		while ((elooper != swap) && (elooper != e)) //start a top-first traversal
		{
			A[e.head.index][elooper.head.index] = 
				A[elooper.head.index][e.head.index]
				= (skew.bottomsize * A[elooper.head.index][skew.head.index] 
				+ fixed.bottomsize* A[elooper.head.index][fixed.head.index]) 
				/ e.bottomsize;
			elooper = topFirstTraverse(elooper);
		}
		// At this point, elooper = par.
		// We finish the top-first traversal, excluding the subtree below par
		elooper = par.moveUpRight();
		while ( null != elooper )
		{
			A[e.head.index][elooper.head.index] 
			    = A[elooper.head.index][e.head.index]
			    = (skew.bottomsize * A[elooper.head.index][skew.head.index] + 
			    fixed.bottomsize* A[elooper.head.index][fixed.head.index]) 
			    / e.bottomsize;
			elooper = topFirstTraverse(elooper);
		}
	}