/// <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))); }
/// <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)); }