code: package ru.ifmo.nds;
  
  import java.io.IOException;
  import java.util.Arrays;
  import java.util.List;
  import java.util.concurrent.ThreadLocalRandom;
  import java.util.stream.Collectors;
  
  public class TortureTesting {
      private static final ThreadLocalRandom random = ThreadLocalRandom.current();
      private static double[][] generateCloud(int points, int dimension) {
          double[][] rv = new double[points][dimension];
          if (random.nextBoolean()) {
              for (int i = 0; i < points; ++i) {
                  for (int j = 0; j < dimension; ++j) {
                      rv[i][j] = random.nextDouble();
                  }
              }
          } else {
              for (int i = 0; i < points; ++i) {
                  for (int j = 0; j < dimension; ++j) {
                      rv[i][j] = random.nextInt(20);
                  }
              }
          }
          return rv;
      }
  
      private static void printPoint(StringBuilder sb, double[] point, int dimension) {
          sb.append(" {");
          for (int j = 0; j < dimension; ++j) {
              double v = point[j];
              int vi = (int) v;
              if (v == vi) {
                  sb.append(vi);
              } else {
                  sb.append(v);
              }
              if (j + 1 != dimension) {
                  sb.append(", ");
              } else {
                  sb.append("},");
              }
          }
      }
  
      private static void printInt(StringBuilder sb, int value, boolean notLast) {
          sb.append(" ").append(value);
          if (notLast) {
              sb.append(",");
          } else {
              sb.append("\n");
          }
      }
  
      private static final int WIDTH_IN_COLUMNS = 120;
      private static final String ARRAY_PREFIX = "               ";
  
      private static void printTest(int points, int dimension, double[][] instance, int[] reference) {
          System.out.println("        groupCheck(new double[][] {");
          StringBuilder sb = new StringBuilder();
          sb.append(ARRAY_PREFIX);
          for (int i = 0; i < points; ++i) {
              int length = sb.length();
              printPoint(sb, instance[i], dimension);
              if (sb.length() > WIDTH_IN_COLUMNS) {
                  sb.setLength(length);
                  System.out.println(sb);
                  sb.setLength(ARRAY_PREFIX.length());
                  printPoint(sb, instance[i], dimension);
              }
          }
          System.out.println(sb);
          System.out.println("        }, new int[] {");
  
          sb.setLength(ARRAY_PREFIX.length());
          for (int i = 0; i < points; ++i) {
              int length = sb.length();
              printInt(sb, reference[i], i + 1 != points);
              if (sb.length() > WIDTH_IN_COLUMNS) {
                  sb.setLength(length);
                  System.out.println(sb);
                  sb.setLength(ARRAY_PREFIX.length());
                  printInt(sb, reference[i], i + 1 != points);
              }
          }
          System.out.println(sb);
          System.out.println("        });");
      }
  
      public static void main(String[] args) throws IOException {
          int maxPoints = 10000;
          int maxDimension = 20;
          List<NonDominatedSortingFactory> sortingFactories = Arrays.asList(
                  FastNonDominatedSorting.getOriginalVersion(),
                  CornerSort.getInstance(),
                  DeductiveSort.getInstance(),
                  DominanceTree.getPresortInsertion(false, false),
                  DominanceTree.getPresortInsertion(true, true),
                  DominanceTree.getNoPresortInsertion(false),
                  DominanceTree.getNoPresortInsertion(true),
                  ENS.getENS_BS(),
                  ENS.getENS_SS(),
                  FastNonDominatedSorting.getLinearMemoryImplementation(),
                  JensenFortinBuzdalov.getFenwickSweepImplementation(1),
                  JensenFortinBuzdalov.getRedBlackTreeSweepImplementation(1),
                  JensenFortinBuzdalov.getRedBlackTreeSweepHybridFNDSImplementation(1),
                  JensenFortinBuzdalov.getRedBlackTreeSweepHybridENSImplementation(1),
                  JensenFortinBuzdalov.getRedBlackTreeSweepHybridNDTImplementation(8, 1),
                  JensenFortinBuzdalov.getRedBlackTreeSweepHybridNDTImplementation(1, 1),
                  BestOrderSort.getProteekImplementation(),
                  BestOrderSort.getImprovedImplementation(),
                  ENS.getENS_NDT(8),
                  ENS.getENS_NDT_Arrays(),
                  ENS.getENS_NDT_OneTree(8),
                  ENS.getENS_NDT_OneTree(1),
                  SumitMishraDivideConquer.getDCNS_BS(),
                  SumitMishraDivideConquer.getDCNS_SS(),
                  FilterSort.getInstance(),
                  SetIntersectionSort.getBitSetInstance()
          );
          List<NonDominatedSorting> sortings = sortingFactories
                  .stream()
                  .map(nonDominatedSortingFactory -> nonDominatedSortingFactory.getInstance(maxPoints, maxDimension))
                  .collect(Collectors.toList());
          while (System.in.available() == 0) {
              int points = 1 + random.nextInt(maxPoints);
              int dimension = 2 + random.nextInt(maxDimension - 1);
              int maxRank = random.nextBoolean() ? random.nextInt(points + 1) : (int) (Math.sqrt(random.nextInt(points)));
              System.out.println("Uniform hypercube with " + points
                      + " points, dimension " + dimension
                      + ", max rank " + maxRank);
              System.out.println();
              double[][] instance = generateCloud(points, dimension);
              double[][] instanceCopy = instance.clone();
              for (int i = 0; i < points; ++i) {
                  instanceCopy[i] = instanceCopy[i].clone();
              }
              int[] reference = null;
              int[] ranks = new int[points];
              for (NonDominatedSorting sorting : sortings) {
                  System.gc();
                  System.gc();
                  long t0 = System.currentTimeMillis();
                  try {
                      sorting.sort(instance, ranks, maxRank);
                      if (!Arrays.deepEquals(instanceCopy, instance)) {
                          throw new AssertionError("Test has been altered!");
                      }
                      long time = System.currentTimeMillis() - t0;
                      System.out.printf("%102s: %d ms%n", sorting.getName(), time);
                      if (reference == null) {
                          reference = ranks.clone();
                      } else {
                          for (int i = 0; i < points; ++i) {
                              if (reference[i] != ranks[i]) {
                                  throw new AssertionError("Ranks do not match: index " + i
                                          + " expected " + reference[i]
                                          + " found " + ranks[i]);
                              }
                          }
                      }
                  } catch (Throwable th) {
                      th.printStackTrace();
                      printTest(points, dimension, instance, reference);
                      System.exit(1);
                  }
              }
              System.out.println();
          }
      }
  }
  