*/
	public double[][] computeDiffMatrix( )
	{
		// ignore 0th element to simplify indexing
		int s = versions.size()+1;
		// keep track of the length of each version
		int[] lengths = new int[s];
		// the length of j last time j and k were joined
		int[][] lastJoinJ = new int[s][s];
		// the length of k last time j and k were joined
		int[][] lastJoinK = new int[s][s];
		// the cost is the longest distance between any two 
		// versions since they were last joined
		int[][] costs = new int[s][s];
		for ( int i=0;i<pairs.size();i++ )
		{
			Pair p = pairs.get( i );
			// consider each combination of j and k, including j=k
			for ( int j=p.versions.nextSetBit(1);j>=1;j=p.versions.nextSetBit(j+1) )
			{
				for ( int k=p.versions.nextSetBit(j);k>=1;k=p.versions.nextSetBit(k+1) )
				{
					costs[j][k] += Math.max(
						lengths[j]-lastJoinJ[j][k],
						lengths[k]-lastJoinK[j][k]);
					costs[k][j] = costs[j][k];
					lastJoinJ[j][k] = lengths[j] + p.length();
					lastJoinK[j][k] = lengths[k] + p.length();
				}
				lengths[j] += p.length();
			}
		}
		double[][] diffs = new double[s-1][s-1];
		for ( int i=1;i<s;i++ )
		{
			for ( int j=1;j<s;j++ )
			{
				// normalise by the longer of the two lengths -1
				double denominator = Math.max(lengths[i],lengths[j])-1;
				diffs[i-1][j-1] = ((double)costs[i][j]) / denominator;
			}
		}
		return diffs;
	}