void updateSubTreeAfterNNI( double[][] A, node v, edge rootEdge, 
			node closer, node further, double dcoeff, direction d )
	{
		edge sib;
		switch ( d )
	    {
	    	case UP: //rootEdge is below the center edge of the NNI
	    		//recursive calls to subtrees, if necessary
	    		if ( null != rootEdge.head.leftEdge )
	    			updateSubTreeAfterNNI( A, v, rootEdge.head.leftEdge, 
	    				closer, further, 0.5*dcoeff,direction.UP );
	    		if ( null != rootEdge.head.rightEdge )
	    			updateSubTreeAfterNNI( A, v, rootEdge.head.rightEdge, 
	    				closer, further, 0.5*dcoeff,direction.UP );
	    		updatePair(A, rootEdge, rootEdge, closer, further, dcoeff, 
	    			direction.UP );
	    		sib = v.parentEdge.siblingEdge();
	    		A[rootEdge.head.index][v.index] = 
	    			A[v.index][rootEdge.head.index] = 
	    			0.5*A[rootEdge.head.index][sib.head.index] +
	    			0.5*A[rootEdge.head.index][v.parentEdge.tail.index];    
	    		break;
	    	case DOWN: // rootEdge is above the center edge of the NNI
	    		sib = rootEdge.siblingEdge();
	    		if ( null != sib )
	    			updateSubTreeAfterNNI( A, v, sib, closer, further, 
	    				0.5*dcoeff, direction.SKEW );
	    		if ( null != rootEdge.tail.parentEdge )
	    			updateSubTreeAfterNNI( A, v, rootEdge.tail.parentEdge, 
	    				closer, further, 0.5*dcoeff, direction.DOWN );
	    		updatePair( A, rootEdge, rootEdge, closer, further, dcoeff, 
	    			direction.DOWN );
	    		A[rootEdge.head.index][v.index] = 
	    			A[v.index][rootEdge.head.index] = 
	    			0.5*A[rootEdge.head.index][v.leftEdge.head.index] +
	    			0.5*A[rootEdge.head.index][v.rightEdge.head.index];
	    		break;
	    	case SKEW: // rootEdge is in subtree skew to v
	    		if (null != rootEdge.head.leftEdge)
	    			updateSubTreeAfterNNI( A, v, rootEdge.head.leftEdge, 
	    				closer, further, 0.5*dcoeff,direction.SKEW );
	    		if (null != rootEdge.head.rightEdge)
	    			updateSubTreeAfterNNI( A, v, rootEdge.head.rightEdge, 
	    				closer, further, 0.5*dcoeff,direction.SKEW );
	    		updatePair( A, rootEdge, rootEdge, closer, further, dcoeff, 
	    			direction.UP );
	    		A[rootEdge.head.index][v.index] = 
	    			A[v.index][rootEdge.head.index] = 
	    			0.5*A[rootEdge.head.index][v.leftEdge.head.index] +
	    			0.5*A[rootEdge.head.index][v.rightEdge.head.index];
	    		break;
	    }
	}