private void createMatrix() {
    try {
      ExecutorService executor =
          Executors.newFixedThreadPool(UJMPSettings.getInstance().getNumberOfThreads());

      Matrix x = getSource();

      double valueCount = x.getValueCount();
      long missingCount = (long) x.countMissing(Ret.NEW, Matrix.ALL).getEuklideanValue();
      double percent = ((int) Math.round((missingCount * 1000.0 / valueCount))) / 10.0;
      System.out.println("missing values: " + missingCount + " (" + percent + "%)");
      System.out.println("============================================");

      if (bestGuess == null) {
        bestGuess = getSource().impute(Ret.NEW, ImputationMethod.RowMean);
      }

      int run = 0;
      double d;
      do {
        System.out.println("Iteration " + run++);

        List<Future<Long>> futures = new ArrayList<Future<Long>>();

        imputed = Matrix.Factory.zeros(x.getSize());

        long t0 = System.currentTimeMillis();

        for (long c = 0; c < x.getColumnCount(); c++) {
          if (containsMissingValues(c)) {
            futures.add(executor.submit(new PredictColumn(c)));
          }
        }

        for (Future<Long> f : futures) {
          Long completedCols = f.get();
          long elapsedTime = System.currentTimeMillis() - t0;
          long remainingCols = x.getColumnCount() - completedCols;
          double colsPerMillisecond = (double) (completedCols + 1) / (double) elapsedTime;
          long remainingTime = (long) (remainingCols / colsPerMillisecond / 1000.0);
          System.out.println(
              (completedCols * 1000 / x.getColumnCount() / 10.0)
                  + "% completed ("
                  + remainingTime
                  + " seconds remaining)");
        }

        Matrix newBestGuess = bestGuess.times(decay).plus(imputed.times(1 - decay));

        for (int r = 0; r < getSource().getRowCount(); r++) {
          for (int c = 0; c < getSource().getColumnCount(); c++) {
            double value = getSource().getAsDouble(r, c);
            if (!MathUtil.isNaNOrInfinite(value)) {
              newBestGuess.setAsDouble(value, r, c);
            }
          }
        }

        d = newBestGuess.euklideanDistanceTo(bestGuess, true) / missingCount;
        System.out.println("delta: " + d);
        System.out.println("============================================");

        bestGuess = newBestGuess;
        bestGuess.exportTo().file(tempFile).asDenseCSV();

      } while (delta < d);

      executor.shutdown();

      imputed = bestGuess;

      if (imputed.containsMissingValues()) {
        throw new RuntimeException("Matrix has still missing values after imputation");
      }

    } catch (Exception e) {
      throw new RuntimeException(e);
    }
  }
 public PForEquidistant(final int first, final int last, final Object... objects) {
   this(UJMPSettings.getInstance().getNumberOfThreads(), first, last, objects);
 }