// eigendecomposition (step 3)
int overshoot = (int) ((double) dimensions * OVERSHOOT_MULTIPLIER);
List<Double> eigenValues = new ArrayList<Double>(overshoot);
Matrix eigenVectors = new DenseMatrix(overshoot, dimensions);
DistributedRowMatrix U = performEigenDecomposition(conf, L, dimensions, overshoot, eigenValues, eigenVectors, outputCalc);
U.configure(new JobConf(conf));
eigenValues = eigenValues.subList(0, dimensions);
// here's where things get interesting: steps 4, 5, and 6 are unique
// to this algorithm, and depending on the final output, steps 1-3
// may be repeated as well