public static double computeThreshold(ArrayList<Double> class1, ArrayList<Double> class2)
	{
		double threshold = 0;
		Collections.sort(class1);
		Collections.sort(class2);

		// Choose c1 as the most left-located class and c2 as the most right-located
		ArrayList<Double> c1, c2;
		if (class1.get(0) < class2.get(0)) {
			c1 = class1;
			c2 = class2;
		}
		else {
			c1 = class2;
			c2 = class1;
		}

		double lowerBound, upperBound;
		// Ideal case : data is well separated
		if (c1.get(c1.size() - 1) <= c2.get(0))
		{
			lowerBound = c1.get(c1.size() - 1);
			upperBound = c2.get(0);
			double marge = upperBound - lowerBound;
			threshold = lowerBound + marge / 2.0;
		}
		// Practical case : some data is mixed up
		else {
			ArrayList<Double> c1_marge_samples = new ArrayList<Double>();
			ArrayList<Double> c2_marge_samples = new ArrayList<Double>();
			lowerBound = c2.get(0);
			upperBound = c1.get(c1.size() - 1);

			// Get all data that is mixed up, between lower and upper boundaries
			for (Double v : c1) {
				if (v >= lowerBound && v <= upperBound)
					c1_marge_samples.add(v);
			}
			for (Double v : c2) {
				if (v >= lowerBound && v <= upperBound)
					c2_marge_samples.add(v);
			}

			threshold = dichotomyComputeBestThreshold(c1_marge_samples, c2_marge_samples, lowerBound, upperBound);
		}

		measureThresholdPerformances(c1, c2, threshold);
		return threshold;
	}