public static double hyperLogLog(int[] M) {
    
	int m = M.length;
	int b = (int) (Math.log(m) / Math.log(2)); // m = 2^b
	
	// Calculation of the result
	double sum = 0;
	for (int j = 0; j < m; j++)
	    sum += Math.pow(2, -M[j]);
	
	double e = alpha[b] * ((double) m) * ((double) m) / sum;
	
	// Second modification (first if statement):
	// corrections when e is comparatively small
	// with respect to m
	// Third modification (second if statement):
	// corrections to account for collision effects
	// due to the hash function
	if (e < 2.5 * m) {
	    double v = 0;
	    for (int i = 0; i < m; i++)
	    	if (M[i] == 0) v++;
	    
	    if (v != 0)
	    	e = m * Math.log(m / v);
	} else if (e > n / 30)
	    e = -n * Math.log(1 - e / n);

	return e;
    }