diff --git a/src/Numerics/Statistics/Correlation.cs b/src/Numerics/Statistics/Correlation.cs
index fb096fa7..c48a2ef0 100644
--- a/src/Numerics/Statistics/Correlation.cs
+++ b/src/Numerics/Statistics/Correlation.cs
@@ -40,6 +40,126 @@ namespace MathNet.Numerics.Statistics
///
public static class Correlation
{
+
+
+ ///
+ /// autocorrelation function (ACF) based on fft (usually faster then direct brute force implementation) for all possible lags k
+ /// First element is hidden since ACF(k = 0) = 1
+ /// data array to calculate auto correlation for
+ /// an array with the ACF as a function of the lags k
+ public static double[] AutoCorrelation(double[] x)
+ {
+ return autoCorrFft(x, tmpk, 0, x.Length-1);
+ }
+
+ ///
+ /// autocorrelation function (ACF) based on fft (usually faster then direct brute force implementation) for lags
+ /// between kMin and kMax
+ /// First element is hidden since ACF(k = 0) = 1
+ /// the data array to calculate auto correlation for
+ /// max lag to calculate ACF for must be positive and smaller than x.Length-1
+ /// min lag to calculate ACF for (0 = no shift with acf=1) must be zero or positive and smaller than x.Length-1
+ public static double[] AutoCorrelation(double[] x, int kMax, int kMin = 0)
+ {
+ // assert max and min in proper order
+ var kMax2 = Math.Max(kMax, kMin);
+ var kMin2 = Math.Min(kMax, kMin);
+
+ return (CorrCov.autoCorrFft(x, kMin2, kMax2));
+ }
+
+
+ ///
+ /// autocorrelation function based on fft for lags k (faster than brute force calculation for big sample sizes).
+ /// First element is skipped since ACF(k = 0) = 1
+ /// the data array to calculate auto correlation for
+ /// array with lags to calculate ACF for
+ public static double[] AutoCorrelation(double[] x, int[] k)
+ {
+ if (k == null)
+ throw new ArgumentNullException("k");
+
+ if (k.Length < 1)
+ throw new ArgumentException("k");
+
+ // get acf between full range
+ var acf = autoCorrFft(x, k.Min(), k.Max());
+
+ // map output by indexing
+ var acfReturn = new double[k.Length];
+ for (int i = 0; i < acfReturn.Length; i++)
+ acfReturn[i] = acf[k[i]];
+
+ return acfReturn;
+ }
+
+ private static double[] autoCorrFft(double[] x, int k_low, int k_high)
+ {
+ if(x == null)
+ throw new ArgumentNullException("x");
+
+ if (k_low < 0 || k_low >= x.Length)
+ throw new ArgumentOutOfRangeException("kMin must be zero or positive and smaller than x.Length");
+ if (k_high < 0 || k_high >= x.Length)
+ throw new ArgumentOutOfRangeException("kMax must be positive and smaller than x.Length");
+
+ if (x.Length < 1)
+ return new double[0];
+
+ int N = x.Length; // Sample size
+
+ int[] idx = new int[k_high - k_low];
+ idx[0] = k_low;
+
+ for (int ii = 1; ii < idx.Length; ii++)
+ idx[ii] = idx[ii - 1] + 1;
+
+ int numLags = N - 1;
+ int nFFT = (int)Math.Pow(2, Euclid.CeilingToPowerOfTwo(N) + 1);
+
+ Complex[] x_fft = new Complex[nFFT];
+ Complex[] x_fft2 = new Complex[nFFT];
+
+ double x_dash = Statistics.Mean(x);
+
+ for (int ii = 0; ii < x_fft.Length; ii++)
+ {
+ if (ii < N)
+ x_fft[ii] = new Complex(x[ii] - x_dash, 0.0); // copy values in range and substract mean
+ else
+ x_fft[ii] = new Complex(0.0, 0.0); // pad all remaining points
+ }
+
+ Fourier.Forward(x_fft, FourierOptions.Matlab);
+
+
+ for (int ii = 0; ii < x_fft.Length; ii++)
+ {
+ x_fft2[ii] = Complex.Multiply(x_fft[ii], Complex.Conjugate(x_fft[ii]));
+ }
+
+ Fourier.Inverse(x_fft2, FourierOptions.Matlab);
+ double acf_Val1 = x_fft2[0].Real;
+
+ double[] acf_Vec = new double[idx.Length];
+ double[] acf_Val = new double[numLags];
+
+ // normalize such that acf[0] would be 1.0 and drop the first element
+ for (int ii = 0; ii < numLags; ii++)
+ {
+ acf_Val[ii] = x_fft2[ii + 1].Real / acf_Val1;
+
+ }
+
+ // only return requested lags
+ for (int ii = 0; ii < idx.Length; ii++)
+ {
+ acf_Vec[ii] = acf_Val[idx[ii]];
+ }
+
+ return (acf_Vec);
+ }
+
///
/// Computes the Pearson Product-Moment Correlation coefficient.
///