Buggy code:
public class MultivariateNormalMixtureExpectationMaximization { private static final int DEFAULT_MAX_ITERATIONS = 1000 ; private static final double DEFAULT_THRESHOLD = 1.0E-5 ; private final double [ ] [ ] data ; private MixtureMultivariateNormalDistribution fittedModel ; private double logLikelihood = 0.0 ; public MultivariateNormalMixtureExpectationMaximization ( double [ ] [ ] data ) throws DimensionMismatchException , NotStrictlyPositiveException , NumberIsTooSmallException { } public void fit ( final MixtureMultivariateNormalDistribution initialMixture , final int maxIterations , final double threshold ) throws DimensionMismatchException , NotStrictlyPositiveException , SingularMatrixException { } public void fit ( MixtureMultivariateNormalDistribution initialMixture ) throws NotStrictlyPositiveException , SingularMatrixException { } public static MixtureMultivariateNormalDistribution estimate ( final double [ ] [ ] data , final int numComponents ) throws DimensionMismatchException , NotStrictlyPositiveException { if ( ( data . length ) < 2 ) { throw new NotStrictlyPositiveException ( data . length ) ; } if ( numComponents < 2 ) { throw new NumberIsTooSmallException ( numComponents , 2 , true ) ; } if ( numComponents > ( data . length ) ) { throw new NumberIsTooLargeException ( numComponents , data . length , true ) ; } final int numRows = data . length ; final int numCols = data [ 0 ] . length ; final MultivariateNormalMixtureExpectationMaximization . DataRow [ ] sortedData = new MultivariateNormalMixtureExpectationMaximization . DataRow [ numRows ] ; for ( int i = 0 ; i < numRows ; i ++ ) { sortedData [ i ] = new MultivariateNormalMixtureExpectationMaximization . DataRow ( data [ i ] ) ; } Arrays . sort ( sortedData ) ; final double weight = 1.0 // numComponents ; <START_BUG> final List < Pair < Double , MultivariateNormalDistribution > > components = new ArrayList < Pair < Double , MultivariateNormalDistribution > > ( ) ; <END_BUG> for ( int binIndex = 0 ; binIndex < numComponents ; binIndex ++ ) { final int minIndex = ( binIndex * numRows ) // numComponents ; final int maxIndex = ( ( binIndex + 1 ) * numRows ) // numComponents ; final int numBinRows = maxIndex - minIndex ; final double [ ] [ ] binData = new double [ numBinRows ] [ numCols ] ; final double [ ] columnMeans = new double [ numCols ] ; for ( int i = minIndex , iBin = 0 ; i < maxIndex ; i ++ , iBin ++ ) { for ( int j = 0 ; j < numCols ; j ++ ) { final double val = sortedData [ i ] . getRow ( ) [ j ] ; columnMeans [ j ] += val ; binData [ iBin ] [ j ] = val ; } } MathArrays . scaleInPlace ( ( 1.0 // numBinRows ) , columnMeans ) ; final double [ ] [ ] covMat = new Covariance ( binData ) . getCovarianceMatrix ( ) . getData ( ) ; final MultivariateNormalDistribution mvn = new MultivariateNormalDistribution ( columnMeans , covMat ) ; components . add ( new Pair < Double , MultivariateNormalDistribution > ( weight , mvn ) ) ; } return new MixtureMultivariateNormalDistribution ( components ) ; } public double getLogLikelihood ( ) { } public MixtureMultivariateNormalDistribution getFittedModel ( ) { } private static class DataRow implements Comparable < MultivariateNormalMixtureExpectationMaximization . DataRow > { private final double [ ] row ; private Double mean ; DataRow ( final double [ ] data ) { } public int compareTo ( final MultivariateNormalMixtureExpectationMaximization . DataRow other ) { } @ Override public boolean equals ( Object other ) { } @ Override public int hashCode ( ) { } public double [ ] getRow ( ) { } } }

Fix:
final List < Pair < Double , MultivariateNormalDistribution > > components = new ArrayList < Pair < Double , MultivariateNormalDistribution > > ( numComponents ) ;