/// <summary> /// Predict values towards the start of the vector. The predicted values are then used to predict more values. See remarks for details. /// </summary> /// <param name="x">Signal which holds at least <see cref="NumberOfCoefficients"/> valid points (the signal window to start the prediction with) from index (lastPoint+1) to (lastPoint+NumberOfCoefficents). The predicted values are then stored in the first part of this vector from indices (lastPoint-count+1) to (lastPoint).</param> /// <param name="lastPoint">Index of the last point to predict.</param> /// <param name="count">Number of points to predict.</param> /// <remarks> /// The algorithm uses a signal window of <c>NumberOfCoefficients</c> signal points after the <c>lastPoint</c> to predict the value at <c>lastPoint</c>. /// Then the window is shifted by one towards the start of the vecctor, hence including the predicted value, and the point at <c>lastPoint-1</c> is predicted. The procedure is repeated until <c>count</c> points are predicted. /// </remarks> public void PredictRecursivelyBackward(IComplexDoubleVector x, int lastPoint, int count) { int first = lastPoint - count; for (int i = lastPoint; i > first; i--) { Complex sum = 0; for (int k = 1; k <= _numberOfCoefficients; k++) // note that Ak[0] is always 1 for technical reasons, thus we start here with index 1 { sum -= _Ak[k].GetConjugate() * x[i + k]; } x[i] = sum; } }
/// <summary> /// Predict values towards the end of the vector. The predicted values are then used to predict more values. See remarks for details. /// </summary> /// <param name="x">Signal which holds at least <see cref="NumberOfCoefficients"/> valid points (the signal window to start the prediction with) from index (firstPoint-NumberOfCoefficents) to (firstPoint-1). The predicted values are then stored in this vector.</param> /// <param name="firstPoint">Index of the first point to predict.</param> /// <param name="count">Number of points to predict.</param> /// <remarks> /// The algorithm uses a signal window of <c>NumberOfCoefficients</c> signal points before the <c>firstPoint</c> to predict the value at <c>firstPoint</c>. /// Then the window is shifted by one towards the end of the vecctor, hence including the predicted value, and the point at <c>firstPoint+1</c> is predicted. The procedure is repeated until <c>count</c> points are predicted. /// </remarks> public void PredictRecursivelyForward(IComplexDoubleVector x, int firstPoint, int count) { int last = firstPoint + count; for (int i = firstPoint; i < last; i++) { Complex sum = 0; for (int k = 1; k <= _numberOfCoefficients; k++) // note that Ak[0] is always 1 for technical reasons, thus we start here with index 1 { sum -= _Ak[k] * x[i - k]; } x[i] = sum; } }
/// <summary> /// Predict values towards the start of the vector. The predicted values are then used to predict more values. See remarks for details. /// </summary> /// <param name="x">Signal which holds at least <see cref="NumberOfCoefficients"/> valid points (the signal window to start the prediction with) from index (lastPoint+1) to (lastPoint+NumberOfCoefficents). The predicted values are then stored in the first part of this vector from indices (0) to (lastPoint).</param> /// <param name="lastPoint">Index of the last point to predict.</param> /// <remarks> /// The algorithm uses a signal window of <c>NumberOfCoefficients</c> signal points after the <c>lastPoint</c> to predict the value at <c>lastPoint</c>. /// Then the window is shifted by one towards the start of the vecctor, hence including the predicted value, and the point at <c>lastPoint-1</c> is predicted. The procedure is repeated until the value at index 0 is predicted. /// </remarks> public void PredictRecursivelyBackward(IComplexDoubleVector x, int lastPoint) { PredictRecursivelyBackward(x, lastPoint, lastPoint + 1); }
/// <summary> /// Predict values towards the end of the vector. The predicted values are then used to predict more values. See remarks for details. /// </summary> /// <param name="x">Signal which holds at least <see cref="NumberOfCoefficients"/> valid points (the signal window to start the prediction with) from index (firstPoint-NumberOfCoefficents) to (firstPoint-1). The predicted values are then stored in this vector.</param> /// <param name="firstPoint">Index of the first point to predict.</param> /// <remarks> /// The algorithm uses a signal window of <c>NumberOfCoefficients</c> signal points before the <c>firstPoint</c> to predict the value at <c>firstPoint</c>. /// Then the window is shifted by one towards the end of the vecctor, hence including the predicted value, and the point at <c>firstPoint+1</c> is predicted. The procedure is repeated until all points to the end of the vector are predicted. /// </remarks> public void PredictRecursivelyForward(IComplexDoubleVector x, int firstPoint) { PredictRecursivelyForward(x, firstPoint, x.Length - firstPoint); }
/// <summary> /// Uses the signal in vector x to build a model with <c>numberOfCoefficients</c> parameter. /// </summary> /// <param name="x">Signal for building the model.</param> /// <param name="coefficients">Vector to be filled with the coefficients of the model.</param> /// <param name="errors">Vector to be filled with the sum of forward and backward prediction error for every stage of the model.</param> /// <param name="reflectionCoefficients">Vector to be filled with the reflection coefficients.</param> public void Execute(IROComplexDoubleVector x, IComplexDoubleVector coefficients, IVector <double> errors, IComplexDoubleVector reflectionCoefficients) { _meanSquareError = Execution(x, coefficients, errors, reflectionCoefficients, this); }
/// <summary> /// Uses th signal in vector x to build a model with <c>numberOfCoefficients</c> parameter. /// </summary> /// <param name="x">Signal for building the model.</param> /// <param name="coefficients">Vector to be filled with the coefficients of the model.</param> public void Execute(IROComplexDoubleVector x, IComplexDoubleVector coefficients) { _meanSquareError = Execution(x, coefficients, null, null, this); }
/// <summary> /// Transforms from the real representation of a spectrum to the compact complex representation (nyquist frequency value put in imaginary part of first element). /// </summary> /// <param name="src">Real representation of the spectrum.</param> /// <param name="dest">On return, contains the complex spectrum.</param> public static void FromRepresentationRealToCompactComplex(IReadOnlyList <double> src, IComplexDoubleVector dest) { bool isEven = 0 == (src.Count % 2); int destLen2; if (isEven) { destLen2 = src.Count / 2; dest[0] = Complex.FromRealImaginary(src[0], src[destLen2]); } else // odd { destLen2 = (src.Count - 1) / 2; dest[0] = Complex.FromRealImaginary(src[0], 0); } for (int i = 1, j = src.Count - 1; i < j; i++, j--) { dest[i] = Complex.FromRealImaginary(src[i], src[j]); } }
/// <summary> /// Uses the signal in vector x to build a model with <c>numberOfCoefficients</c> parameter. /// </summary> /// <param name="x">Signal for building the model.</param> /// <param name="coefficients">Vector to be filled with the coefficients of the model.</param> /// <param name="errors">Vector to be filled with the sum of forward and backward prediction error for every stage of the model.</param> /// <param name="reflectionCoefficients">Vector to be filled with the reflection coefficients.</param> /// <returns>The mean square error of backward and forward prediction.</returns> public static double Execution(IROComplexDoubleVector x, IComplexDoubleVector coefficients, IVector <double> errors, IComplexDoubleVector reflectionCoefficients) { return(Execution(x, coefficients, errors, reflectionCoefficients, null)); }
/// <summary> /// Uses the signal in vector x to build a model with <c>numberOfCoefficients</c> parameter. /// </summary> /// <param name="x">Signal for building the model.</param> /// <param name="coefficients">Vector to be filled with the coefficients of the model.</param> /// <param name="errors">Vector to be filled with the sum of forward and backward prediction error for every stage of the model.</param> /// <param name="reflectionCoefficients">Vector to be filled with the reflection coefficients.</param> /// <returns>The mean square error of backward and forward prediction.</returns> public static double Execution(IROComplexDoubleVector x, IComplexDoubleVector coefficients, IVector errors, IComplexDoubleVector reflectionCoefficients) { return Execution(x, coefficients, errors, reflectionCoefficients, null); }
/// <summary> /// Uses the signal in vector x to build a model with <c>numberOfCoefficients</c> parameter. /// </summary> /// <param name="x">Signal for building the model.</param> /// <param name="coefficients">Vector to be filled with the coefficients of the model.</param> /// <returns>The mean square error of backward and forward prediction.</returns> public static double Execution(IROComplexDoubleVector x, IComplexDoubleVector coefficients) { return Execution(x, coefficients, null, null, null); }
/// <summary> /// Uses the signal in vector x to build a model with <c>numberOfCoefficients</c> parameter. /// </summary> /// <param name="x">Signal for building the model.</param> /// <param name="coefficients">Vector to be filled with the coefficients of the model.</param> /// <param name="errors">Vector to be filled with the sum of forward and backward prediction error for every stage of the model.</param> /// <param name="reflectionCoefficients">Vector to be filled with the reflection coefficients.</param> public void Execute(IROComplexDoubleVector x, IComplexDoubleVector coefficients, IVector errors, IComplexDoubleVector reflectionCoefficients) { _meanSquareError = Execution(x, coefficients, errors, reflectionCoefficients, this); }
/// <summary> /// Uses the signal in vector x to build a model with <c>numberOfCoefficients</c> parameter. /// </summary> /// <param name="x">Signal for building the model.</param> /// <param name="coefficients">Vector to be filled with the coefficients of the model.</param> /// <param name="errors">Vector to be filled with the sum of forward and backward prediction error for every stage of the model.</param> /// <param name="reflectionCoefficients">Vector to be filled with the reflection coefficients.</param> /// <param name="tempStorage">Instance of this class used to hold the temporary arrays.</param> /// <returns>The mean square error of backward and forward prediction.</returns> private static double Execution(IROComplexDoubleVector x, IComplexDoubleVector coefficients, IVector errors, IComplexDoubleVector reflectionCoefficients, BurgAlgorithmComplex tempStorage) { int N = x.Length - 1; int m = coefficients.Length; Complex[] Ak; // Prediction coefficients, Ak[0] is always 1 Complex[] b; // backward prediction errors Complex[] f; // forward prediction errors if (null != tempStorage) { tempStorage.EnsureAllocation(x.Length, coefficients.Length); Ak = tempStorage._Ak; b = tempStorage._b; f = tempStorage._f; for (int i = 1; i <= coefficients.Length; i++) Ak[i] = 0; } else { Ak = new Complex[coefficients.Length + 1]; b = new Complex[x.Length]; f = new Complex[x.Length]; } Ak[0] = 1; // Initialize forward and backward prediction errors with x for (int i = 0; i <= N; i++) f[i] = b[i] = x[i]; double Dk = 0; for (int i = 0; i <= N; i++) Dk += 2 * f[i].GetModulusSquared(); Dk -= f[0].GetModulusSquared() + b[N].GetModulusSquared(); // Burg recursion int k; double sumE = 0; // error sum for (k = 0; (k < m) && (Dk > 0); k++) { // Compute mu Complex mu = 0; for (int n = 0; n < N - k; n++) mu += f[n + k + 1] * b[n].GetConjugate(); mu *= (-2 / Dk); // Update Ak for (int n = 0; n <= (k + 1) / 2; n++) { Complex t1 = Ak[n] + mu * Ak[k + 1 - n].GetConjugate(); Complex t2 = Ak[k + 1 - n] + mu * Ak[n].GetConjugate(); Ak[n] = t1; Ak[k + 1 - n] = t2; } if (null != reflectionCoefficients) reflectionCoefficients[k] = Ak[k + 1]; // update forward and backward predition error with simultaneous total error calculation sumE = 0; for (int n = 0; n < N - k; n++) { Complex t1 = f[n + k + 1] + mu * b[n]; Complex t2 = b[n] + mu.GetConjugate() * f[n + k + 1]; f[n + k + 1] = t1; b[n] = t2; sumE += t1.GetModulusSquared() + t2.GetModulusSquared(); } if (null != errors) errors[k] = sumE / (2 * (N - k)); // Update Dk // Note that it is possible to update Dk without total error calculation because sumE = Dk*(1-mu.GetModulusSquared()) // but this will render the algorithm numerically unstable especially for higher orders and low noise Dk = sumE - (f[k + 1].GetModulusSquared() + b[N - k - 1].GetModulusSquared()); } // Assign coefficients for (int i = 0; i < m; i++) coefficients[i] = Ak[i + 1]; // Assign the rest of reflection coefficients and errors with zero // if not all stages could be calculated because Dk was zero or because of rounding effects smaller than zero for (int i = k + 1; i < m; i++) { if (null != reflectionCoefficients) reflectionCoefficients[i] = 0; if (null != errors) errors[i] = 0; } return sumE / (2 * (N - k)); }
/// <summary> /// Uses the signal in vector x to build a model with <c>numberOfCoefficients</c> parameter. /// </summary> /// <param name="x">Signal for building the model.</param> /// <param name="coefficients">Vector to be filled with the coefficients of the model.</param> /// <returns>The mean square error of backward and forward prediction.</returns> public static double Execution(IROComplexDoubleVector x, IComplexDoubleVector coefficients) { return(Execution(x, coefficients, null, null, null)); }
public static IComplexDoubleMatrix AU(IComplexDoubleMatrix A, IROComplexDoubleVector u, int r1, int r2, int c1, int c2, IComplexDoubleVector v) { if (r2 < r1 || c2 < c1) { return A; } if (c2 - c1 + 1 > u.Length) { throw new ArgumentException("Householder vector too short.", "u"); } if (r2 - r1 + 1 > v.Length) { throw new ArgumentException("Work vector too short.", "v"); } for (int i = r1; i <= r2; i++) { v[i - r1] = Complex.Zero; for (int j = c1; j <= c2; j++) { v[i - r1] = new Complex(v[i - r1].Real + A[i, j].Real * u[j - c1].Real - A[i, j].Imag * u[j - c1].Imag, v[i - r1].Imag + A[i, j].Real * u[j - c1].Imag + A[i, j].Imag * u[j - c1].Real); } } for (int i = r1; i <= r2; i++) { for (int j = c1; j <= c2; j++) { A[i, j] = new Complex(A[i, j].Real - v[i - r1].Real * u[j - c1].Real - v[i - r1].Imag * u[j - c1].Imag, A[i, j].Imag + v[i - r1].Real * u[j - c1].Imag - v[i - r1].Imag * u[j - c1].Real); } } return A; }
/// <summary> /// Uses the signal in vector x to build a model with <c>numberOfCoefficients</c> parameter. /// </summary> /// <param name="x">Signal for building the model.</param> /// <param name="coefficients">Vector to be filled with the coefficients of the model.</param> /// <param name="errors">Vector to be filled with the sum of forward and backward prediction error for every stage of the model.</param> /// <param name="reflectionCoefficients">Vector to be filled with the reflection coefficients.</param> /// <param name="tempStorage">Instance of this class used to hold the temporary arrays.</param> /// <returns>The mean square error of backward and forward prediction.</returns> private static double Execution(IROComplexDoubleVector x, IComplexDoubleVector coefficients, IVector <double> errors, IComplexDoubleVector reflectionCoefficients, BurgAlgorithmComplex tempStorage) { int N = x.Length - 1; int m = coefficients.Length; Complex[] Ak; // Prediction coefficients, Ak[0] is always 1 Complex[] b; // backward prediction errors Complex[] f; // forward prediction errors if (null != tempStorage) { tempStorage.EnsureAllocation(x.Length, coefficients.Length); Ak = tempStorage._Ak; b = tempStorage._b; f = tempStorage._f; for (int i = 1; i <= coefficients.Length; i++) { Ak[i] = 0; } } else { Ak = new Complex[coefficients.Length + 1]; b = new Complex[x.Length]; f = new Complex[x.Length]; } Ak[0] = 1; // Initialize forward and backward prediction errors with x for (int i = 0; i <= N; i++) { f[i] = b[i] = x[i]; } double Dk = 0; for (int i = 0; i <= N; i++) { Dk += 2 * f[i].GetModulusSquared(); } Dk -= f[0].GetModulusSquared() + b[N].GetModulusSquared(); // Burg recursion int k; double sumE = 0; // error sum for (k = 0; (k < m) && (Dk > 0); k++) { // Compute mu Complex mu = 0; for (int n = 0; n < N - k; n++) { mu += f[n + k + 1] * b[n].GetConjugate(); } mu *= (-2 / Dk); // Update Ak for (int n = 0; n <= (k + 1) / 2; n++) { Complex t1 = Ak[n] + mu * Ak[k + 1 - n].GetConjugate(); Complex t2 = Ak[k + 1 - n] + mu * Ak[n].GetConjugate(); Ak[n] = t1; Ak[k + 1 - n] = t2; } if (null != reflectionCoefficients) { reflectionCoefficients[k] = Ak[k + 1]; } // update forward and backward predition error with simultaneous total error calculation sumE = 0; for (int n = 0; n < N - k; n++) { Complex t1 = f[n + k + 1] + mu * b[n]; Complex t2 = b[n] + mu.GetConjugate() * f[n + k + 1]; f[n + k + 1] = t1; b[n] = t2; sumE += t1.GetModulusSquared() + t2.GetModulusSquared(); } if (null != errors) { errors[k] = sumE / (2 * (N - k)); } // Update Dk // Note that it is possible to update Dk without total error calculation because sumE = Dk*(1-mu.GetModulusSquared()) // but this will render the algorithm numerically unstable especially for higher orders and low noise Dk = sumE - (f[k + 1].GetModulusSquared() + b[N - k - 1].GetModulusSquared()); } // Assign coefficients for (int i = 0; i < m; i++) { coefficients[i] = Ak[i + 1]; } // Assign the rest of reflection coefficients and errors with zero // if not all stages could be calculated because Dk was zero or because of rounding effects smaller than zero for (int i = k + 1; i < m; i++) { if (null != reflectionCoefficients) { reflectionCoefficients[i] = 0; } if (null != errors) { errors[i] = 0; } } return(sumE / (2 * (N - k))); }
public static IComplexDoubleMatrix AU(IComplexDoubleMatrix A, IROComplexDoubleVector u, int r1, int r2, int c1, int c2, IComplexDoubleVector v) { if (r2 < r1 || c2 < c1) { return(A); } if (c2 - c1 + 1 > u.Length) { throw new ArgumentException("Householder vector too short.", "u"); } if (r2 - r1 + 1 > v.Length) { throw new ArgumentException("Work vector too short.", "v"); } for (int i = r1; i <= r2; i++) { v[i - r1] = Complex.Zero; for (int j = c1; j <= c2; j++) { v[i - r1] = new Complex(v[i - r1].Real + A[i, j].Real * u[j - c1].Real - A[i, j].Imag * u[j - c1].Imag, v[i - r1].Imag + A[i, j].Real * u[j - c1].Imag + A[i, j].Imag * u[j - c1].Real); } } for (int i = r1; i <= r2; i++) { for (int j = c1; j <= c2; j++) { A[i, j] = new Complex(A[i, j].Real - v[i - r1].Real * u[j - c1].Real - v[i - r1].Imag * u[j - c1].Imag, A[i, j].Imag + v[i - r1].Real * u[j - c1].Imag - v[i - r1].Imag * u[j - c1].Real); } } return(A); }
/// <summary> /// Transforms from the real representation of a spectrum to the compact complex representation (nyquist frequency value put in imaginary part of first element). /// </summary> /// <param name="src">Real representation of the spectrum.</param> /// <param name="dest">On return, contains the complex spectrum.</param> public static void FromRepresentationRealToCompactComplex(IROVector src, IComplexDoubleVector dest) { bool isEven = 0 == (src.Length % 2); int destLen2; if (isEven) { destLen2 = src.Length / 2; dest[0] = Complex.FromRealImaginary(src[0], src[destLen2]); } else // odd { destLen2 = (src.Length - 1) / 2; dest[0] = Complex.FromRealImaginary(src[0], 0); } for (int i = 1, j = src.Length - 1; i < j; i++, j--) { dest[i] = Complex.FromRealImaginary(src[i], src[j]); } }