public static Double[] slidingWindow(Path path, HashFunction func, int b, int windowSize, int precision) {
    	
    	if (b <= 0 || b > 16)
    	    throw new AssertionError("hyperLogLog :  b <= 0 or b > 16");
    	
    	int m = 1 << b; // m = 2^b
    	int[] M = new int[m];
    	LinkedList<Double> result = new LinkedList<Double>();
    	
    	
    	double sum = m, eTimesSum = HyperLogLog.alpha[b] * ((double) m) * ((double) m),
    			n = Math.pow(2, 32);
    	
    	
    	// Invariant preserved :
    	// - timestamps.length == values.length
    	// - increasing values and decreasing timestamps
    	// - couple (timestamps, values) such that  currentTime - timestamps > windowSize,
    	// are removed as soon as possible (update function).
    	LinkedList<Integer>[] timestamps = new LinkedList[m], values = new LinkedList[m];
    	for (int i = 0; i < m; i++) {
    		timestamps[i] = new LinkedList<Integer>();
    		values[i] = new LinkedList<Integer>();
    	}
    	
    	
    	
    	int currentTime = 0;
    	
    	for (String s : new WordReader(path)) {
    	    long x = func.hashString(s);
    	    int j = (int) (x & (m - 1));
    	    int rho = Integer.numberOfTrailingZeros( (int) (x >>> b) ); // rho(w)
    	    
    	    // We insert rho in the queue preserving the invariants.
    	    insert( currentTime, rho, timestamps[j], values[j] );
    	    // Alternative : meilleure complexite en espace, pire en temps
    	    // update( currentTime - windowSize, timestamps[j], values[j] );
    	    
    		// We regularly evaluate and save the approximate number of words
    	    // corresponding to the current table M.
    		if (currentTime % precision == 0 && currentTime > windowSize) {
    			
    			sum = 0;
    			for (int k = 0; k < m; k++) {
    				update( currentTime - windowSize, timestamps[k], values[k] );
    				if ( values[k].isEmpty() )  M[k] = 0;
    				else M[k] = values[k].getLast();
    				sum += Math.pow(2, M[k]);
    			}
    			
    			// We evaluate the current estimation
    	    	double e = eTimesSum / sum;
    	    	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);
    	    	
    			// We save the current estimation
    			result.add( e );
    		}
    		
    		currentTime++;
    	}
    	
    	return result.toArray(new Double[0]);
    }