Esempio n. 1
0
        /// <overloads>
        /// There are two permuations of the constructor, both require a parameter corresponding
        /// to the left-most column of a Toeplitz matrix.
        /// </overloads>
        /// <summary>
        /// Constructor with <c>ComplexDoubleVector</c> parameter.
        /// </summary>
        /// <param name="T">The left-most column of the Toeplitz matrix.</param>
        /// <exception cref="ArgumentNullException">
        /// <B>T</B> is a null reference.
        /// </exception>
        /// <exception cref="RankException">
        /// The length of <B>T</B> is zero.
        /// </exception>
        public ComplexDoubleSymmetricLevinson(IROComplexDoubleVector T)
        {
            // check parameter
            if (T == null)
            {
                throw new System.ArgumentNullException("T");
            }
            else if (T.Length == 0)
            {
                throw new RankException("The length of T is zero.");
            }

            // save the vector
            m_LeftColumn = new ComplexDoubleVector(T);
            m_Order      = m_LeftColumn.Length;

            // allocate memory for lower triangular matrix
            m_LowerTriangle = new Complex[m_Order][];
            for (int i = 0; i < m_Order; i++)
            {
                m_LowerTriangle[i] = new Complex[i + 1];
            }

            // allocate memory for diagonal
            m_Diagonal = new Complex[m_Order];
        }
Esempio n. 2
0
 public static IComplexDoubleMatrix AU(IComplexDoubleMatrix A, IROComplexDoubleVector u, int r1, int r2, int c1, int c2)
 {
     if (r2 < r1)
     {
         return(A);
     }
     return(AU(A, u, r1, r2, c1, c2, new ComplexDoubleVector(r2 - r1 + 1)));
 }
Esempio n. 3
0
 public static IComplexDoubleMatrix UA(IROComplexDoubleVector u, IComplexDoubleMatrix A, int r1, int r2, int c1, int c2)
 {
     if (c1 > c2)
     {
         return(A);
     }
     return(UA(u, A, r1, r2, c1, c2, new ComplexDoubleVector(c2 - c1 + 1)));
 }
        /// <overloads>
        /// Solve a symmetric square Toeplitz system.
        /// </overloads>
        /// <summary>
        /// Solve a symmetric square Toeplitz system with a right-side vector.
        /// </summary>
        /// <param name="Y">The right-hand side of the system.</param>
        /// <returns>The solution vector.</returns>
        /// <exception cref="ArgumentNullException">
        /// Parameter <B>Y</B> is a null reference.
        /// </exception>
        /// <exception cref="RankException">
        /// The length of <B>Y</B> is not equal to the number of rows in the Toeplitz matrix.
        /// </exception>
        /// <exception cref="SingularMatrixException">
        /// The Toeplitz matrix or one of the the leading sub-matrices is singular.
        /// </exception>
        /// <remarks>
        /// This member solves the linear system <B>TX</B> = <B>Y</B>, where <B>T</B> is
        /// the symmetric square Toeplitz matrix, <B>X</B> is the unknown solution vector
        /// and <B>Y</B> is a known vector.
        /// <para>
        /// The class implicitly decomposes the inverse Toeplitz matrix into a <b>UDL</b> factorisation
        /// using the Levinson algorithm, and then calculates the solution vector.
        /// </para>
        /// </remarks>
        public ComplexDoubleVector Solve(IROComplexDoubleVector Y)
        {
            ComplexDoubleVector X;

            // check parameters
            if (Y == null)
            {
                throw new System.ArgumentNullException("Y");
            }
            else if (m_Order != Y.Length)
            {
                throw new RankException("The length of Y is not equal to the number of rows in the Toeplitz matrix.");
            }

            Compute();

            if (m_IsSingular == true)
            {
                throw new SingularMatrixException("The Toeplitz matrix or one of the the leading sub-matrices is singular.");
            }

            int     i, j, l; // index/loop variables
            Complex Inner;   // inner product
            Complex G;       // scaling constant

            Complex[] A;     // reference to current order coefficients

            // allocate memory for solution
            X = new ComplexDoubleVector(m_Order)
            {
                // setup zero order solution
                [0] = Y[0] / m_LeftColumn[0]
            };

            // solve systems of increasing order
            for (i = 1; i < m_Order; i++)
            {
                // calculate inner product
                Inner = Y[i];
                for (j = 0, l = i; j < i; j++, l--)
                {
                    Inner -= X[j] * m_LeftColumn[l];
                }
                // get the current predictor coefficients row
                A = m_LowerTriangle[i];

                // update the solution vector
                G = Inner * m_Diagonal[i];
                for (j = 0; j <= i; j++)
                {
                    X[j] += G * A[j];
                }
            }

            return(X);
        }
        private ComplexDoubleVector Pivot(IROComplexDoubleVector B)
        {
            ComplexDoubleVector ret = new ComplexDoubleVector(B.Length);

            for (int i = 0; i < pivots.Length; i++)
            {
                ret.data[i] = B[pivots[i]];
            }
            return(ret);
        }
Esempio n. 6
0
        ///<summary>Solves a system on linear equations, AX=B, where A is the factored matrixed.</summary>
        ///<param name="B">RHS side of the system.</param>
        ///<returns>the solution vector, X.</returns>
        ///<exception cref="ArgumentNullException">B is null.</exception>
        ///<exception cref="NotPositiveDefiniteException">A is not positive definite.</exception>
        ///<exception cref="ArgumentException">The number of rows of A and the length of B must be the same.</exception>
        public ComplexDoubleVector Solve(IROComplexDoubleVector B)
        {
            if (B == null)
            {
                throw new System.ArgumentNullException("B cannot be null.");
            }
            Compute();
            if (!ispd)
            {
                throw new NotPositiveDefiniteException();
            }
            else
            {
                if (B.Length != order)
                {
                    throw new System.ArgumentException("The length of B must be the same as the order of the matrix.");
                }
#if MANAGED
                // Copy right hand side.
                var X = new ComplexDoubleVector(B);
                // Solve L*Y = B;
                for (int i = 0; i < order; i++)
                {
                    Complex sum = B[i];
                    for (int k = i - 1; k >= 0; k--)
                    {
                        sum -= l.data[i][k] * X.data[k];
                    }
                    X.data[i] = sum / l.data[i][i];
                }
                // Solve L'*X = Y;
                for (int i = order - 1; i >= 0; i--)
                {
                    Complex sum = X.data[i];
                    for (int k = i + 1; k < order; k++)
                    {
                        sum -= ComplexMath.Conjugate(l.data[k][i]) * X.data[k];
                    }
                    X.data[i] = sum / ComplexMath.Conjugate(l.data[i][i]);
                }

                return(X);
#else
                Complex[] rhs = ComplexDoubleMatrix.ToLinearComplexArray(B);
                Lapack.Potrs.Compute(Lapack.UpLo.Lower, order, 1, l.data, order, rhs, B.Length);
                ComplexDoubleVector ret = new ComplexDoubleVector(order, B.Length);
                ret.data = rhs;
                return(ret);
#endif
            }
        }
Esempio n. 7
0
        /// <summary>
        /// This algorithm determines the mean backward prediction error using the model stored in this instance. See remarks for details.
        /// </summary>
        /// <param name="x">Signal for which to determine the mean backward prediction error.</param>
        /// <returns>Mean backward prediction error.</returns>
        /// <remarks>
        /// 1. The prediction is done non recursively, i.e. part of the signal (the signal window) is used to predict the signal value before, and this predicted signal value is
        /// then compared with the original signal value stored in x to build the sum of errors. But the predicted signal value is <b>not</b> used to make further predictions.
        /// Instead, the signal window is moved by one point to the left and another prediction is made, with the original signal in x. This is repeated until the first point (index 0)
        /// is predicted. The return value is the square root of the sum of squared differences between predicted signal values and original values, divided by the number of predicted values.
        /// The number of predicted values is the length of the signal x minus the number of coefficents of the model.
        /// </remarks>
        public double GetMeanPredictionErrorNonrecursivelyBackward(IROComplexDoubleVector x)
        {
            int    last   = x.Length - _numberOfCoefficients;
            double sumsqr = 0;

            for (int i = last - 1; i >= 0; 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];
                }
                sumsqr += (x[i] - sum).GetModulusSquared();
            }
            return(Math.Sqrt(sumsqr / (last)));
        }
        /// <overloads>
        /// Solve a square Toeplitz system.
        /// </overloads>
        /// <summary>
        /// Solve a square Toeplitz system with a right-side vector.
        /// </summary>
        /// <param name="Y">The right-hand side of the system.</param>
        /// <returns>The solution vector.</returns>
        /// <exception cref="ArgumentNullException">
        /// Parameter <B>Y</B> is a null reference.
        /// </exception>
        /// <exception cref="RankException">
        /// The length of Y is not equal to the number of rows in the Toeplitz matrix.
        /// </exception>
        /// <exception cref="SingularMatrixException">
        /// The Toeplitz matrix or one of the the leading sub-matrices is singular.
        /// </exception>
        /// <remarks>
        /// This member solves the linear system <B>TX</B> = <B>Y</B>, where <B>T</B> is
        /// the square Toeplitz matrix, <B>X</B> is the unknown solution vector
        /// and <B>Y</B> is a known vector.
        /// <para>
        /// The class implicitly decomposes the inverse Toeplitz matrix into a <b>UDL</b> factorisation
        /// using the Levinson algorithm, before calculating the solution vector.
        /// </para>
        /// </remarks>
        public ComplexDoubleVector Solve(IROComplexDoubleVector Y)
        {
            ComplexDoubleVector X;
            Complex             Inner;
            int i, j;

            // check parameters
            if (Y == null)
            {
                throw new System.ArgumentNullException("Y");
            }
            else if (m_Order != Y.Length)
            {
                throw new RankException("The length of Y is not equal to the number of rows in the Toeplitz matrix.");
            }

            Compute();

            if (m_IsSingular == true)
            {
                throw new SingularMatrixException("One of the leading sub-matrices is singular.");
            }

            // allocate memory for solution
            Complex[] A, B;
            X = new ComplexDoubleVector(m_Order);

            for (i = 0; i < m_Order; i++)
            {
                A = m_LowerTriangle[i];
                B = m_UpperTriangle[i];

                Inner = Y[i];
                for (j = 0; j < i; j++)
                {
                    Inner += A[j] * Y[j];
                }
                Inner *= m_Diagonal[i];

                X[i] = Inner;
                for (j = 0; j < i; j++)
                {
                    X[j] += Inner * B[j];
                }
            }
            return(X);
        }
        /// <summary>
        /// Invert a symmetric square Toeplitz matrix.
        /// </summary>
        /// <param name="T">The left-most column of the symmetric Toeplitz matrix.</param>
        /// <returns>The inverse matrix.</returns>
        /// <exception cref="ArgumentNullException">
        /// <B>T</B> is a null reference.
        /// </exception>
        /// <exception cref="RankException">
        /// The length of <B>T</B> must be greater than zero.
        /// </exception>
        /// <exception cref="SingularMatrixException">
        /// The Toeplitz matrix or one of the the leading sub-matrices is singular.
        /// </exception>
        /// <remarks>
        /// This static member combines the <b>UDL</b> decomposition and Trench's algorithm into a
        /// single algorithm. When compared to the non-static member it requires minimal data storage
        /// and suffers from no speed penalty.
        /// <para>
        /// Trench's algorithm requires <b>N</b> squared FLOPS, compared to <b>N</b> cubed FLOPS
        /// if we simply solved a linear Toeplitz system with a right-side identity matrix (<b>N</b> is the matrix order).
        /// </para>
        /// </remarks>
        public static ComplexDoubleMatrix Inverse(IROComplexDoubleVector T)
        {
            ComplexDoubleMatrix X;

            // check parameters
            if (T == null)
            {
                throw new System.ArgumentNullException("T");
            }
            else if (T.Length < 1)
            {
                throw new System.RankException("The length of T must be greater than zero.");
            }
            else if (T.Length == 1)
            {
                X = new ComplexDoubleMatrix(1)
                {
Esempio n. 10
0
        ///<summary>Solves a system on linear equations, AX=B, where A is the factored matrixed.</summary>
        ///<param name="B">RHS side of the system.</param>
        ///<returns>the solution vector, X.</returns>
        ///<exception cref="ArgumentNullException">B is null.</exception>
        ///<exception cref="SingularMatrixException">A is singular.</exception>
        ///<exception cref="ArgumentException">The number of rows of A and the length of B must be the same.</exception>
        public ComplexDoubleVector Solve(IROComplexDoubleVector B)
        {
            if (B == null)
            {
                throw new System.ArgumentNullException("B cannot be null.");
            }
            Compute();
            if (singular)
            {
                throw new SingularMatrixException();
            }
            else
            {
                if (B.Length != order)
                {
                    throw new System.ArgumentException("The length of B must be the same as the order of the matrix.");
                }
#if MANAGED
                // Copy right hand side with pivoting
                ComplexDoubleVector X = Pivot(B);

                // Solve L*Y = B(piv,:)
                for (int k = 0; k < order; k++)
                {
                    for (int i = k + 1; i < order; i++)
                    {
                        X[i] -= X[k] * factor[i][k];
                    }
                }
                // Solve U*X = Y;
                for (int k = order - 1; k >= 0; k--)
                {
                    X[k] /= factor[k][k];
                    for (int i = 0; i < k; i++)
                    {
                        X[i] -= X[k] * factor[i][k];
                    }
                }
                return(X);
#else
                Complex[] rhs = ComplexDoubleMatrix.ToLinearComplexArray(B);
                Lapack.Getrs.Compute(Lapack.Transpose.NoTrans, order, 1, factor, order, pivots, rhs, rhs.Length);
                return(new ComplexDoubleVector(rhs));
#endif
            }
        }
Esempio n. 11
0
        /// <summary>
        /// This algorithm determines the mean forward prediction error using the model stored in this instance. See remarks for details.
        /// </summary>
        /// <param name="x">Signal for which to determine the mean forward prediction error.</param>
        /// <returns>Mean backward prediction error.</returns>
        /// <remarks>
        /// 1. The prediction is done non recursively, i.e. part of the signal (the signal window) is used to predict the signal value immediately after the window, and this predicted signal value is
        /// then compared with the original signal value stored in x to build the sum of errors. But the predicted signal value is <b>not</b> used to make further predictions.
        /// Instead, the signal window is moved by one point to the right and another prediction is made, with the original signal in x. This is repeated until the last point
        /// is predicted. The return value is the square root of the sum of squared differences between predicted signal values and original values, divided by the number of predicted values.
        /// The number of predicted values is the length of the signal x minus the number of coefficents of the model.
        /// </remarks>
        public double GetMeanPredictionErrorNonrecursivelyForward(IROComplexDoubleVector x)
        {
            int    first  = _numberOfCoefficients;
            int    last   = x.Length;
            double sumsqr = 0;

            for (int i = first; 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];
                }
                sumsqr += (x[i] - sum).GetModulusSquared();
            }
            return(Math.Sqrt(sumsqr / (last - first)));
        }
Esempio n. 12
0
        /// <summary>
        /// Constructor with <c>ComplexDoubleVector</c> parameters.
        /// </summary>
        /// <param name="col">The left-most column of the Toeplitz matrix.</param>
        /// <param name="row">The top-most row of the Toeplitz matrix.</param>
        /// <exception cref="ArgumentNullException">
        /// <B>col</B> is a null reference,
        /// <para>or</para>
        /// <para><B>row</B> is a null reference.</para>
        /// </exception>
        /// <exception cref="RankException">
        /// The length col <B>col</B> is zero,
        /// <para>or</para>
        /// <para>the length of <B>col</B> does not match that of <B>row</B>.</para>
        /// </exception>
        /// <exception cref="ArithmeticException">
        /// The values of the first element of <B>col</B> and <B>row</B> are not equal.
        /// </exception>
        public ComplexDoubleLevinson(IROComplexDoubleVector col, IROComplexDoubleVector row)
        {
            // check parameters
            if (col == null)
            {
                throw new System.ArgumentNullException("col");
            }
            else if (col.Length == 0)
            {
                throw new RankException("The length of col is zero.");
            }
            else if (row == null)
            {
                throw new System.ArgumentNullException("row");
            }
            else if (col.Length != row.Length)
            {
                throw new RankException("The lengths of col and row are not equal.");
            }
            else if (col[0] != row[0])
            {
                throw new ArithmeticException("The values of the first element of col and row are not equal.");
            }

            // save the vectors
            m_LeftColumn = new ComplexDoubleVector(col);
            m_TopRow     = new ComplexDoubleVector(row);
            m_Order      = m_LeftColumn.Length;

            // allocate memory for lower triangular matrix
            m_LowerTriangle = new Complex[m_Order][];
            for (int i = 0; i < m_Order; i++)
            {
                m_LowerTriangle[i] = new Complex[i + 1];
            }

            // allocate memory for diagonal
            m_Diagonal = new Complex[m_Order];

            // allocate memory for upper triangular matrix
            m_UpperTriangle = new Complex[m_Order][];
            for (int i = 0; i < m_Order; i++)
            {
                m_UpperTriangle[i] = new Complex[i + 1];
            }
        }
Esempio n. 13
0
 ///<summary>Constructor for <c>ComplexDoubleVector</c> to deep copy from a <see cref="IROComplexDoubleVector" /></summary>
 ///<param name="src"><c>ComplexDoubleVector</c> to deep copy into <c>ComplexDoubleVector</c>.</param>
 ///<exception cref="ArgumentNullException">Exception thrown if null passed as 'src' parameter.</exception>
 public ComplexDoubleVector(IROComplexDoubleVector src)
 {
     if (src == null)
     {
         throw new ArgumentNullException("IROComplexDoubleVector cannot be null");
     }
     if (src is ComplexDoubleVector)
     {
         data = (Complex[])(((ComplexDoubleVector)src).data.Clone());
     }
     else
     {
         data = new Complex[src.Length];
         for (int i = 0; i < src.Length; ++i)
         {
             data[i] = src[i];
         }
     }
 }
Esempio n. 14
0
        public static IComplexDoubleMatrix UA(IROComplexDoubleVector u, IComplexDoubleMatrix A, int r1, int r2, int c1, int c2, IComplexDoubleVector v)
        {
            if (r2 < r1 || c2 < c1)
            {
                return(A);
            }

            if (r2 - r1 + 1 > u.Length)
            {
                throw new ArgumentException("Householder vector too short.", "u");
            }

            if (c2 - c1 + 1 > v.Length)
            {
                throw new ArgumentException("Work vector too short.", "v");
            }

            for (int j = c1; j <= c2; j++)
            {
                v[j - c1] = Complex.Zero;
            }

            for (int i = r1; i <= r2; i++)
            {
                for (int j = c1; j <= c2; j++)
                {
                    v[j - c1] = new Complex(v[j - c1].Real + u[i - r1].Real * A[i, j].Real + u[i - r1].Imag * A[i, j].Imag,
                                            v[j - c1].Imag + u[i - r1].Real * A[i, j].Imag - u[i - r1].Imag * A[i, j].Real);
                }
            }

            for (int i = r1; i <= r2; i++)
            {
                for (int j = c1; j <= c2; j++)
                {
                    A[i, j] = new Complex(A[i, j].Real - u[i - r1].Real * v[j - c1].Real + u[i - r1].Imag * v[j - c1].Imag,
                                          A[i, j].Imag - u[i - r1].Real * v[j - c1].Imag - u[i - r1].Imag * v[j - c1].Real);
                }
            }
            return(A);
        }
Esempio n. 15
0
        /// <summary>
        /// Transforms from a compact complex representation (nyquist frequency value put in imaginary part of first element) to real representation.
        /// </summary>
        /// <param name="src">Stores the  complex spectrum.</param>
        /// <param name="destination">After return, stores the spectrum in normalized real representation. The length of the vector has to be equal to the length of the FFT. </param>
        public static void FromRepresentationCompactComplexToReal(IROComplexDoubleVector src, IVector <double> destination)
        {
            bool isEven = 0 == (destination.Length % 2);
            int  destLen2;

            if (isEven)
            {
                destLen2              = destination.Length / 2;
                destination[0]        = src[0].Re;
                destination[destLen2] = src[0].Im;
                ;
            }
            else // odd
            {
                destLen2       = (destination.Length - 1) / 2;
                destination[0] = src[0].Re;
            }
            for (int i = 1, j = destination.Length - 1; i < j; i++, j--)
            {
                destination[i] = src[i].Re;
                destination[j] = src[i].Im;
            }
        }
    /// <summary>
    /// Invert a symmetric square Toeplitz matrix.
    /// </summary>
    /// <param name="T">The left-most column of the symmetric Toeplitz matrix.</param>
    /// <returns>The inverse matrix.</returns>
    /// <exception cref="ArgumentNullException">
    /// <B>T</B> is a null reference.
    /// </exception>
    /// <exception cref="RankException">
    /// The length of <B>T</B> must be greater than zero.
    /// </exception>
    /// <exception cref="SingularMatrixException">
    /// The Toeplitz matrix or one of the the leading sub-matrices is singular.
    /// </exception>
    /// <remarks>
    /// This static member combines the <b>UDL</b> decomposition and Trench's algorithm into a
    /// single algorithm. When compared to the non-static member it requires minimal data storage
    /// and suffers from no speed penalty.
    /// <para>
    /// Trench's algorithm requires <b>N</b> squared FLOPS, compared to <b>N</b> cubed FLOPS
    /// if we simply solved a linear Toeplitz system with a right-side identity matrix (<b>N</b> is the matrix order).
    /// </para>
    /// </remarks>
    public static ComplexDoubleMatrix Inverse(IROComplexDoubleVector T)
    {

      ComplexDoubleMatrix X;

      // check parameters
      if (T == null)
      {
        throw new System.ArgumentNullException("T");
      }
      else if (T.Length < 1)
      {
        throw new System.RankException("The length of T must be greater than zero.");
      }
      else if (T.Length == 1)
      {
        X = new ComplexDoubleMatrix(1);
        X[0, 0] = Complex.One / T[0];
      }
      else
      {

        int N = T.Length;
        Complex f, g;
        int i, j, l, k, m, n;
        X = new ComplexDoubleMatrix(N);

        // calculate the predictor coefficients
        ComplexDoubleVector Y = ComplexDoubleSymmetricLevinson.YuleWalker(T);

        // calculate gamma
        f = T[0];
        for (i = 1, j = 0; i < N; i++, j++)
        {
          f += T[i] * Y[j];
        }
        g = Complex.One / f;

        // calculate first row of inverse
        X[0, 0] = g;
        for (i = 1, j = 0; i < N; i++, j++)
        {
          X[0, i] = g * Y[j];
        }

        // calculate successive rows of upper wedge
        for (i = 0, j = 1, k = N - 2; i < N / 2; i++, j++, k--)
        {
          for (l = j, m = i, n = N-1-j; l < N - j; l++, m++, n--)
          {
            X[j, l] = X[i, m] + g * (Y[i] * Y[m] - Y[k] * Y[n]);
          }
        }

        // this is symmetric matrix ...
        for (i = 0; i <= N / 2; i++)
        {
          for (j = i + 1; j < N - i; j++)
          {
            X[j, i] = X[i, j];
          }
        }

        // and a persymmetric matrix.
        for (i = 0, j = N - 1; i < N; i++, j--)
        {
          for (k = 0, l = N - 1; k < j; k++, l--)
          {
            X[l, j] = X[i, k];
          }
        }

      }

      return X;
    }
    /// <overloads>
    /// Solve a symmetric square Toeplitz system.
    /// </overloads>
    /// <summary>
    /// Solve a symmetric square Toeplitz system with a right-side vector.
    /// </summary>
    /// <param name="Y">The right-hand side of the system.</param>
    /// <returns>The solution vector.</returns>
    /// <exception cref="ArgumentNullException">
    /// Parameter <B>Y</B> is a null reference.
    /// </exception>
    /// <exception cref="RankException">
    /// The length of <B>Y</B> is not equal to the number of rows in the Toeplitz matrix.
    /// </exception>
    /// <exception cref="SingularMatrixException">
    /// The Toeplitz matrix or one of the the leading sub-matrices is singular.
    /// </exception>
    /// <remarks>
    /// This member solves the linear system <B>TX</B> = <B>Y</B>, where <B>T</B> is
    /// the symmetric square Toeplitz matrix, <B>X</B> is the unknown solution vector
    /// and <B>Y</B> is a known vector.
    /// <para>
    /// The class implicitly decomposes the inverse Toeplitz matrix into a <b>UDL</b> factorisation
    /// using the Levinson algorithm, and then calculates the solution vector.
    /// </para>
    /// </remarks>
    public ComplexDoubleVector Solve(IROComplexDoubleVector Y)
    {
      ComplexDoubleVector X;

      // check parameters
      if (Y == null)
      {
        throw new System.ArgumentNullException("Y");
      }
      else if (m_Order != Y.Length)
      {
        throw new RankException("The length of Y is not equal to the number of rows in the Toeplitz matrix.");
      }

      Compute();

      if (m_IsSingular == true)
      {
        throw new SingularMatrixException("The Toeplitz matrix or one of the the leading sub-matrices is singular.");
      }

      int i, j, l;      // index/loop variables
      Complex Inner;      // inner product
      Complex G;        // scaling constant
      Complex[] A;        // reference to current order coefficients

      // allocate memory for solution
      X = new ComplexDoubleVector(m_Order);

      // setup zero order solution
      X[0] = Y[0] / m_LeftColumn[0];

      // solve systems of increasing order
      for (i = 1; i < m_Order; i++)
      {
        // calculate inner product
        Inner = Y[i];
        for (j = 0, l = i; j < i; j++, l--)
        {
          Inner -= X[j] * m_LeftColumn[l];
        }
        // get the current predictor coefficients row
        A = m_LowerTriangle[i];

        // update the solution vector
        G = Inner * m_Diagonal[i];
        for (j = 0; j <= i; j++)
        {
          X[j] += G * A[j];
        }

      }

      return X;
    }
    ///<summary>Solves a system on linear equations, AX=B, where A is the factored matrixed.</summary>
    ///<param name="B">RHS side of the system.</param>
    ///<returns>the solution vector, X.</returns>  
    ///<exception cref="ArgumentNullException">B is null.</exception>
    ///<exception cref="NotPositiveDefiniteException">A is not positive definite.</exception>
    ///<exception cref="ArgumentException">The number of rows of A and the length of B must be the same.</exception>
    public ComplexDoubleVector Solve (IROComplexDoubleVector B) 
    {
      if ( B == null ) 
      {
        throw new System.ArgumentNullException("B cannot be null.");
      }
      Compute();
      if ( !ispd ) 
      {
        throw new NotPositiveDefiniteException();
      } 
      else 
      {
        if ( B.Length != order ) 
        {
          throw new System.ArgumentException("The length of B must be the same as the order of the matrix." );
        }
#if MANAGED
        // Copy right hand side.
        ComplexDoubleVector X = new ComplexDoubleVector(B);
        // Solve L*Y = B;
        for (int i = 0; i < order; i++) 
        {
          Complex sum = B[i];
          for (int k = i-1; k >= 0; k--) 
          {
            sum -= l.data[i][k] * X.data[k];
          }
          X.data[i] = sum / l.data[i][i];
        }
        // Solve L'*X = Y;
        for (int i =order-1; i >= 0; i--) 
        {
          Complex sum = X.data[i];
          for (int k = i+1; k < order; k++) 
          {
            sum -= ComplexMath.Conjugate(l.data[k][i]) * X.data[k];
          }
          X.data[i] = sum / ComplexMath.Conjugate(l.data[i][i]);
        }

        return X;

#else
                Complex[] rhs = ComplexDoubleMatrix.ToLinearComplexArray(B);
                Lapack.Potrs.Compute(Lapack.UpLo.Lower,order,1,l.data,order,rhs,B.Length);
                ComplexDoubleVector ret = new ComplexDoubleVector(order,B.Length);
                ret.data = rhs;
                return ret;
#endif
      }
    }
Esempio n. 19
0
 /// <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);
 }
Esempio n. 20
0
		public static IComplexDoubleMatrix UA(IROComplexDoubleVector u, IComplexDoubleMatrix A, int r1, int r2, int c1, int c2)
		{
			if (c1 > c2)
			{
				return A;
			}
			return UA(u, A, r1, r2, c1, c2, new ComplexDoubleVector(c2 - c1 + 1));
		}
Esempio n. 21
0
        /// <summary>
        /// Invert a square Toeplitz matrix.
        /// </summary>
        /// <param name="col">The left-most column of the Toeplitz matrix.</param>
        /// <param name="row">The top-most row of the Toeplitz matrix.</param>
        /// <returns>The inverse matrix.</returns>
        /// <exception cref="ArgumentNullException">
        /// <B>col</B> is a null reference.
        /// <para>or</para>
        /// <para><B>row</B> is a null reference.</para>
        /// </exception>
        /// <exception cref="RankException">
        /// The length of <B>col</B> is 0,
        /// <para>or</para>
        /// <para>the lengths of <B>col</B> and <B>row</B> are not equal.</para>
        /// </exception>
        /// <exception cref="SingularMatrixException">
        /// The Toeplitz matrix or one of the the leading sub-matrices is singular.
        /// </exception>
        /// <exception cref="ArithmeticException">
        /// The values of the first element of <B>col</B> and <B>row</B> are not equal.
        /// </exception>
        /// <remarks>
        /// This static member combines the <b>UDL</b> decomposition and Trench's algorithm into a
        /// single algorithm. It requires minimal data storage, compared to the non-static member
        /// and suffers from no speed penalty in comparision.
        /// <para>
        /// Trench's algorithm requires <b>N</b> squared FLOPS, compared to <b>N</b> cubed FLOPS
        /// if we simply solved a linear Toeplitz system with a right-side identity matrix (<b>N</b> is the matrix order).
        /// </para>
        /// </remarks>
        public static ComplexDoubleMatrix Inverse(IROComplexDoubleVector col, IROComplexDoubleVector row)
        {
            // check parameters
            if (col == null)
            {
                throw new System.ArgumentNullException("col");
            }
            else if (col.Length == 0)
            {
                throw new RankException("The length of col is zero.");
            }
            else if (row == null)
            {
                throw new System.ArgumentNullException("row");
            }
            else if (col.Length != row.Length)
            {
                throw new RankException("The lengths of col and row are not equal.");
            }
            else if (col[0] != row[0])
            {
                throw new ArithmeticException("The values of the first element of col and row are not equal.");
            }

            // check if leading diagonal is zero
            if (col[0] == Complex.Zero)
            {
                throw new SingularMatrixException("One of the leading sub-matrices is singular.");
            }

            // decompose matrix
            int order = col.Length;

            Complex[] A = new Complex[order];
            Complex[] B = new Complex[order];
            Complex[] Z = new Complex[order];
            Complex   Q, S, Ke, Kr, e;
            int       i, j, k, l;

            // setup the zero order solution
            A[0] = Complex.One;
            B[0] = Complex.One;
            e    = Complex.One / col[0];

            for (i = 1; i < order; i++)
            {
                // calculate inner products
                Q = Complex.Zero;
                for (j = 0, l = 1; j < i; j++, l++)
                {
                    Q += col[l] * A[j];
                }

                S = Complex.Zero;
                for (j = 0, l = 1; j < i; j++, l++)
                {
                    S += row[l] * B[j];
                }

                // reflection coefficients
                Kr = -S * e;
                Ke = -Q * e;

                // update lower triangle (in temporary storage)
                Z[0] = Complex.Zero;
                Array.Copy(A, 0, Z, 1, i);
                for (j = 0, l = i - 1; j < i; j++, l--)
                {
                    Z[j] += Ke * B[l];
                }

                // update upper triangle
                for (j = i; j > 0; j--)
                {
                    B[j] = B[j - 1];
                }

                B[0] = Complex.Zero;
                for (j = 0, l = i - 1; j < i; j++, l--)
                {
                    B[j] += Kr * A[l];
                }

                // copy from temporary storage to lower triangle
                Array.Copy(Z, 0, A, 0, i + 1);

                // check for singular sub-matrix)
                if (Ke * Kr == Complex.One)
                {
                    throw new SingularMatrixException("One of the leading sub-matrices is singular.");
                }

                // update diagonal
                e = e / (Complex.One - Ke * Kr);
            }

            // calculate the inverse
            ComplexDoubleMatrix I = new ComplexDoubleMatrix(order);     // the solution matrix
            Complex             A1, B1;

#if MANAGED
            Complex[] current, previous;              // references to rows in the solution

            // setup the first row in wedge
            current = I.data[0];
            for (i = 0, j = order - 1; i < order; i++, j--)
            {
                current[i] = e * B[j];
            }

            // calculate values in the rest of the wedge
            for (i = 1; i < order; i++)
            {
                previous   = current;
                current    = I.data[i];
                A1         = e * A[order - i - 1];
                B1         = e * B[i - 1];
                current[0] = A1;
                for (j = 1, k = 0, l = order - 2; j < order - i; j++, k++, l--)
                {
                    current[j] = previous[k] + A1 * B[l] - B1 * A[k];
                }
            }
#else
            // setup the first row in wedge
            for (i = 0, j = order - 1; i < order; i++, j--)
            {
                I[0, i] = e * B[j];
            }

            // calculate values in the rest of the wedge
            for (i = 1; i < order; i++)
            {
                A1      = e * A[order - i - 1];
                B1      = e * B[i - 1];
                I[i, 0] = A1;
                for (j = 1, k = 0, l = order - 2; j < order - i; j++, k++, l--)
                {
                    I[i, j] = I[i - 1, k] + A1 * B[l] - B1 * A[k];
                }
            }
#endif

            // inverse is a persymmetric matrix.
            for (i = 0, j = order - 1; i < order; i++, j--)
            {
                for (k = 0, l = order - 1; k < j; k++, l--)
                {
                    I[l, j] = I[i, k];
                }
            }

            return(I);
        }
 ///<summary>Constructor for <c>ComplexDoubleVector</c> to deep copy from a <see cref="IROComplexDoubleVector" /></summary>
 ///<param name="src"><c>ComplexDoubleVector</c> to deep copy into <c>ComplexDoubleVector</c>.</param>
 ///<exception cref="ArgumentNullException">Exception thrown if null passed as 'src' parameter.</exception>
 public ComplexDoubleVector(IROComplexDoubleVector src)
 {
   if (src == null)
   {
     throw new ArgumentNullException("IROComplexDoubleVector cannot be null");
   }
   if (src is ComplexDoubleVector)
   {
     data = (Complex[])(((ComplexDoubleVector)src).data.Clone());
   }
   else
   {
     data = new Complex[src.Length];
     for (int i = 0; i < src.Length; ++i)
     {
       data[i] = src[i];
     }
   }
 }
Esempio n. 23
0
        /// <overloads>
        /// Solve a symmetric square Toeplitz system.
        /// </overloads>
        /// <summary>
        /// Solve a symmetric square Toeplitz system with a right-side vector.
        /// </summary>
        /// <param name="T">The left-most column of the Toeplitz matrix.</param>
        /// <param name="Y">The right-side vector of the system.</param>
        /// <returns>The solution vector.</returns>
        /// <exception cref="ArgumentNullException">
        /// <B>T</B> and/or <B>Y</B> are null references
        /// </exception>
        /// <exception cref="RankException">
        /// The length of <B>T</B> does not match the length of <B>Y</B>.
        /// </exception>
        /// <exception cref="SingularMatrixException">
        /// The Toeplitz matrix or one of the the leading sub-matrices is singular.
        /// </exception>
        /// <remarks>
        /// This method solves the linear system <B>AX</B> = <B>Y</B>. Where
        /// <B>T</B> is a symmetric square Toeplitz matrix, <B>X</B> is an unknown
        /// vector and <B>Y</B> is a known vector.
        /// <para>
        /// This static member combines the <b>UDL</b> decomposition and the calculation of the solution into a
        /// single algorithm. When compared to the non-static member it requires minimal data storage
        /// and suffers from no speed penalty.
        /// </para>
        /// </remarks>
        public static ComplexDoubleVector Solve(IROComplexDoubleVector T, IROComplexDoubleVector Y)
        {
            ComplexDoubleVector X;

            // check parameters
            if (T == null)
            {
                throw new System.ArgumentNullException("T");
            }
            else if (Y == null)
            {
                throw new System.ArgumentNullException("Y");
            }
            else if (T.Length != Y.Length)
            {
                throw new RankException("The length of T and Y are not equal.");
            }
            else
            {
                // allocate memory
                int N = T.Length;
                X = new ComplexDoubleVector(N);      // solution vector
                Complex e;                           // prediction error

                // setup zero order solution
                e = T[0];
                if (e == Complex.Zero)
                {
                    throw new SingularMatrixException("The Toeplitz matrix or one of the the leading sub-matrices is singular.");
                }
                X[0] = Y[0] / T[0];

                if (N > 1)
                {
                    ComplexDoubleVector a = new ComplexDoubleVector(N - 1); // prediction coefficients
                    ComplexDoubleVector Z = new ComplexDoubleVector(N - 1); // temporary storage vector
                    Complex             g;                                  // reflection coefficient
                    Complex             inner;                              // inner product
                    Complex             k;
                    int i, j, l;

                    // calculate solution for successive orders
                    for (i = 1; i < N; i++)
                    {
                        // calculate first inner product
                        inner = T[i];
                        for (j = 0, l = i - 1; j < i - 1; j++, l--)
                        {
                            inner += a[j] * T[l];
                        }

                        // update predictor coefficients
                        g = -(inner / e);
                        for (j = 0, l = i - 2; j < i - 1; j++, l--)
                        {
                            Z[j] = a[j] + g * a[l];
                        }

                        // copy vector
                        for (j = 0; j < i - 1; j++)
                        {
                            a[j] = Z[j];
                        }

                        a[i - 1] = g;

                        e *= (Complex.One - g * g);
                        if (e == Complex.Zero)
                        {
                            throw new SingularMatrixException("The Toeplitz matrix or one of the the leading sub-matrices is singular.");
                        }

                        // calculate second inner product
                        inner = Y[i];
                        for (j = 0, l = i; j < i; j++, l--)
                        {
                            inner -= X[j] * T[l];
                        }

                        // update solution vector
                        k = inner / e;
                        for (j = 0, l = i - 1; j < i; j++, l--)
                        {
                            X[j] = X[j] + k * a[l];
                        }
                        X[j] = k;
                    }
                }
            }

            return(X);
        }
Esempio n. 24
0
        /// <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)));
        }
Esempio n. 25
0
 /// <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="numberOfCoefficients">Number of coefficients of the model.</param>
 public void Execute(IROComplexDoubleVector x, int numberOfCoefficients)
 {
     EnsureAllocation(x.Length, numberOfCoefficients);
     _meanSquareError = Execution(x, _AkWrapper, null, null, this);
 }
Esempio n. 26
0
 /// <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));
 }
Esempio n. 27
0
 /// <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));
 }
Esempio n. 28
0
		/// <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);
		}
Esempio n. 29
0
		/// <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="numberOfCoefficients">Number of coefficients of the model.</param>
		public void Execute(IROComplexDoubleVector x, int numberOfCoefficients)
		{
			EnsureAllocation(x.Length, numberOfCoefficients);
			_meanSquareError = Execution(x, _AkWrapper, null, null, this);
		}
Esempio n. 30
0
		public static IComplexDoubleMatrix AU(IComplexDoubleMatrix A, IROComplexDoubleVector u, int r1, int r2, int c1, int c2)
		{
			if (r2 < r1)
			{
				return A;
			}
			return AU(A, u, r1, r2, c1, c2, new ComplexDoubleVector(r2 - r1 + 1));
		}
Esempio n. 31
0
		/// <summary>
		/// This algorithm determines the mean forward prediction error using the model stored in this instance. See remarks for details.
		/// </summary>
		/// <param name="x">Signal for which to determine the mean forward prediction error.</param>
		/// <returns>Mean backward prediction error.</returns>
		/// <remarks>
		/// 1. The prediction is done non recursively, i.e. part of the signal (the signal window) is used to predict the signal value immediately after the window, and this predicted signal value is
		/// then compared with the original signal value stored in x to build the sum of errors. But the predicted signal value is <b>not</b> used to make further predictions.
		/// Instead, the signal window is moved by one point to the right and another prediction is made, with the original signal in x. This is repeated until the last point
		/// is predicted. The return value is the square root of the sum of squared differences between predicted signal values and original values, divided by the number of predicted values.
		/// The number of predicted values is the length of the signal x minus the number of coefficents of the model.
		/// </remarks>
		public double GetMeanPredictionErrorNonrecursivelyForward(IROComplexDoubleVector x)
		{
			int first = _numberOfCoefficients;
			int last = x.Length;
			double sumsqr = 0;
			for (int i = first; 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];
				}
				sumsqr += (x[i] - sum).GetModulusSquared();
			}
			return Math.Sqrt(sumsqr / (last - first));
		}
Esempio n. 32
0
		/// <summary>
		/// Constructor with <c>ComplexDoubleVector</c> parameters.
		/// </summary>
		/// <param name="col">The left-most column of the Toeplitz matrix.</param>
		/// <param name="row">The top-most row of the Toeplitz matrix.</param>
		/// <exception cref="ArgumentNullException">
		/// <B>col</B> is a null reference,
		/// <para>or</para>
		/// <para><B>row</B> is a null reference.</para>
		/// </exception>
		/// <exception cref="RankException">
		/// The length col <B>col</B> is zero,
		/// <para>or</para>
		/// <para>the length of <B>col</B> does not match that of <B>row</B>.</para>
		/// </exception>
		/// <exception cref="ArithmeticException">
		/// The values of the first element of <B>col</B> and <B>row</B> are not equal.
		/// </exception>
		public ComplexDoubleLevinson(IROComplexDoubleVector col, IROComplexDoubleVector row)
		{
			// check parameters
			if (col == null)
			{
				throw new System.ArgumentNullException("col");
			}
			else if (col.Length == 0)
			{
				throw new RankException("The length of col is zero.");
			}
			else if (row == null)
			{
				throw new System.ArgumentNullException("row");
			}
			else if (col.Length != row.Length)
			{
				throw new RankException("The lengths of col and row are not equal.");
			}
			else if (col[0] != row[0])
			{
				throw new ArithmeticException("The values of the first element of col and row are not equal.");
			}

			// save the vectors
			m_LeftColumn = new ComplexDoubleVector(col);
			m_TopRow = new ComplexDoubleVector(row);
			m_Order = m_LeftColumn.Length;

			// allocate memory for lower triangular matrix
			m_LowerTriangle = new Complex[m_Order][];
			for (int i = 0; i < m_Order; i++)
			{
				m_LowerTriangle[i] = new Complex[i + 1];
			}

			// allocate memory for diagonal
			m_Diagonal = new Complex[m_Order];

			// allocate memory for upper triangular matrix
			m_UpperTriangle = new Complex[m_Order][];
			for (int i = 0; i < m_Order; i++)
			{
				m_UpperTriangle[i] = new Complex[i + 1];
			}
		}
Esempio n. 33
0
        /// <summary>
        /// Solve a square Toeplitz system with a right-side matrix.
        /// </summary>
        /// <param name="col">The left-most column of the Toeplitz matrix.</param>
        /// <param name="row">The top-most row of the Toeplitz matrix.</param>
        /// <param name="Y">The right-side matrix of the system.</param>
        /// <returns>The solution matrix.</returns>
        /// <exception cref="ArgumentNullException">
        /// <EM>col</EM> is a null reference,
        /// <para>or</para>
        /// <para><EM>row</EM> is a null reference,</para>
        /// <para>or</para>
        /// <para><EM>Y</EM> is a null reference.</para>
        /// </exception>
        /// <exception cref="RankException">
        /// The length of <EM>col</EM> is 0,
        /// <para>or</para>
        /// <para>the lengths of <EM>col</EM> and <EM>row</EM> are not equal,</para>
        /// <para>or</para>
        /// <para>the number of rows in <EM>Y</EM> does not the length of <EM>col</EM> and <EM>row</EM>.</para>
        /// </exception>
        /// <exception cref="SingularMatrixException">
        /// The Toeplitz matrix or one of the the leading sub-matrices is singular.
        /// </exception>
        /// <exception cref="ArithmeticException">
        /// The values of the first element of <EM>col</EM> and <EM>row</EM> are not equal.
        /// </exception>
        /// <remarks>
        /// This method solves the linear system <B>AX</B> = <B>Y</B>. Where
        /// <B>T</B> is a square Toeplitz matrix, <B>X</B> is an unknown
        /// matrix and <B>Y</B> is a known matrix.
        /// <para>
        /// The classic Levinson algorithm is used to solve the system. The algorithm
        /// assumes that all the leading sub-matrices of the Toeplitz matrix are
        /// non-singular. When a sub-matrix is near singular, accuracy will
        /// be degraded. This member requires approximately <B>N</B> squared
        /// FLOPS to calculate a solution, where <B>N</B> is the matrix order.
        /// </para>
        /// <para>
        /// This static method has minimal storage requirements as it combines
        /// the <b>UDL</b> decomposition with the calculation of the solution vector
        /// in a single algorithm.
        /// </para>
        /// </remarks>
        public static ComplexDoubleMatrix Solve(IROComplexDoubleVector col, IROComplexDoubleVector row, IROComplexDoubleMatrix Y)
        {
            // check parameters
            if (col == null)
            {
                throw new System.ArgumentNullException("col");
            }
            else if (col.Length == 0)
            {
                throw new RankException("The length of col is zero.");
            }
            else if (row == null)
            {
                throw new System.ArgumentNullException("row");
            }
            else if (col.Length != row.Length)
            {
                throw new RankException("The lengths of col and row are not equal.");
            }
            else if (col[0] != row[0])
            {
                throw new ArithmeticException("The values of the first element of col and row are not equal.");
            }
            else if (Y == null)
            {
                throw new System.ArgumentNullException("Y");
            }
            else if (col.Length != Y.Columns)
            {
                throw new RankException("The numer of rows in Y does not match the length of col and row.");
            }

            // check if leading diagonal is zero
            if (col[0] == Complex.Zero)
            {
                throw new SingularMatrixException("One of the leading sub-matrices is singular.");
            }

            // decompose matrix
            int order = col.Length;

            Complex[]           A = new Complex[order];
            Complex[]           B = new Complex[order];
            Complex[]           Z = new Complex[order];
            ComplexDoubleMatrix X = new ComplexDoubleMatrix(order);
            Complex             Q, S, Ke, Kr, e;
            Complex             Inner;
            int i, j, l;

            // setup the zero order solution
            A[0] = Complex.One;
            B[0] = Complex.One;
            e    = Complex.One / col[0];
            X.SetRow(0, e * ComplexDoubleVector.GetRow(Y, 0));

            for (i = 1; i < order; i++)
            {
                // calculate inner products
                Q = Complex.Zero;
                for (j = 0, l = 1; j < i; j++, l++)
                {
                    Q += col[l] * A[j];
                }

                S = Complex.Zero;
                for (j = 0, l = 1; j < i; j++, l++)
                {
                    S += row[l] * B[j];
                }

                // reflection coefficients
                Kr = -S * e;
                Ke = -Q * e;

                // update lower triangle (in temporary storage)
                Z[0] = Complex.Zero;
                Array.Copy(A, 0, Z, 1, i);
                for (j = 0, l = i - 1; j < i; j++, l--)
                {
                    Z[j] += Ke * B[l];
                }

                // update upper triangle
                for (j = i; j > 0; j--)
                {
                    B[j] = B[j - 1];
                }

                B[0] = Complex.Zero;
                for (j = 0, l = i - 1; j < i; j++, l--)
                {
                    B[j] += Kr * A[l];
                }

                // copy from temporary storage to lower triangle
                Array.Copy(Z, 0, A, 0, i + 1);

                // check for singular sub-matrix)
                if (Ke * Kr == Complex.One)
                {
                    throw new SingularMatrixException("One of the leading sub-matrices is singular.");
                }

                // update diagonal
                e = e / (Complex.One - Ke * Kr);

                for (l = 0; l < Y.Rows; l++)
                {
                    ComplexDoubleVector W = X.GetColumn(l);
                    ComplexDoubleVector M = ComplexDoubleVector.GetColumn(Y, l);

                    Inner = M[i];
                    for (j = 0; j < i; j++)
                    {
                        Inner += A[j] * M[j];
                    }
                    Inner *= e;

                    W[i] = Inner;
                    for (j = 0; j < i; j++)
                    {
                        W[j] += Inner * B[j];
                    }

                    X.SetColumn(l, W);
                }
            }

            return(X);
        }
Esempio n. 34
0
		/// <summary>
		/// Invert a square Toeplitz matrix.
		/// </summary>
		/// <param name="col">The left-most column of the Toeplitz matrix.</param>
		/// <param name="row">The top-most row of the Toeplitz matrix.</param>
		/// <returns>The inverse matrix.</returns>
		/// <exception cref="ArgumentNullException">
		/// <B>col</B> is a null reference.
		/// <para>or</para>
		/// <para><B>row</B> is a null reference.</para>
		/// </exception>
		/// <exception cref="RankException">
		/// The length of <B>col</B> is 0,
		/// <para>or</para>
		/// <para>the lengths of <B>col</B> and <B>row</B> are not equal.</para>
		/// </exception>
		/// <exception cref="SingularMatrixException">
		/// The Toeplitz matrix or one of the the leading sub-matrices is singular.
		/// </exception>
		/// <exception cref="ArithmeticException">
		/// The values of the first element of <B>col</B> and <B>row</B> are not equal.
		/// </exception>
		/// <remarks>
		/// This static member combines the <b>UDL</b> decomposition and Trench's algorithm into a
		/// single algorithm. It requires minimal data storage, compared to the non-static member
		/// and suffers from no speed penalty in comparision.
		/// <para>
		/// Trench's algorithm requires <b>N</b> squared FLOPS, compared to <b>N</b> cubed FLOPS
		/// if we simply solved a linear Toeplitz system with a right-side identity matrix (<b>N</b> is the matrix order).
		/// </para>
		/// </remarks>
		public static ComplexDoubleMatrix Inverse(IROComplexDoubleVector col, IROComplexDoubleVector row)
		{
			// check parameters
			if (col == null)
			{
				throw new System.ArgumentNullException("col");
			}
			else if (col.Length == 0)
			{
				throw new RankException("The length of col is zero.");
			}
			else if (row == null)
			{
				throw new System.ArgumentNullException("row");
			}
			else if (col.Length != row.Length)
			{
				throw new RankException("The lengths of col and row are not equal.");
			}
			else if (col[0] != row[0])
			{
				throw new ArithmeticException("The values of the first element of col and row are not equal.");
			}

			// check if leading diagonal is zero
			if (col[0] == Complex.Zero)
			{
				throw new SingularMatrixException("One of the leading sub-matrices is singular.");
			}

			// decompose matrix
			int order = col.Length;
			Complex[] A = new Complex[order];
			Complex[] B = new Complex[order];
			Complex[] Z = new Complex[order];
			Complex Q, S, Ke, Kr, e;
			int i, j, k, l;

			// setup the zero order solution
			A[0] = Complex.One;
			B[0] = Complex.One;
			e = Complex.One / col[0];

			for (i = 1; i < order; i++)
			{
				// calculate inner products
				Q = Complex.Zero;
				for (j = 0, l = 1; j < i; j++, l++)
				{
					Q += col[l] * A[j];
				}

				S = Complex.Zero;
				for (j = 0, l = 1; j < i; j++, l++)
				{
					S += row[l] * B[j];
				}

				// reflection coefficients
				Kr = -S * e;
				Ke = -Q * e;

				// update lower triangle (in temporary storage)
				Z[0] = Complex.Zero;
				Array.Copy(A, 0, Z, 1, i);
				for (j = 0, l = i - 1; j < i; j++, l--)
				{
					Z[j] += Ke * B[l];
				}

				// update upper triangle
				for (j = i; j > 0; j--)
				{
					B[j] = B[j - 1];
				}

				B[0] = Complex.Zero;
				for (j = 0, l = i - 1; j < i; j++, l--)
				{
					B[j] += Kr * A[l];
				}

				// copy from temporary storage to lower triangle
				Array.Copy(Z, 0, A, 0, i + 1);

				// check for singular sub-matrix)
				if (Ke * Kr == Complex.One)
				{
					throw new SingularMatrixException("One of the leading sub-matrices is singular.");
				}

				// update diagonal
				e = e / (Complex.One - Ke * Kr);
			}

			// calculate the inverse
			ComplexDoubleMatrix I = new ComplexDoubleMatrix(order);           // the solution matrix
			Complex A1, B1;

#if MANAGED
			Complex[] current, previous;                    // references to rows in the solution

			// setup the first row in wedge
			current = I.data[0];
			for (i = 0, j = order - 1; i < order; i++, j--)
			{
				current[i] = e * B[j];
			}

			// calculate values in the rest of the wedge
			for (i = 1; i < order; i++)
			{
				previous = current;
				current = I.data[i];
				A1 = e * A[order - i - 1];
				B1 = e * B[i - 1];
				current[0] = A1;
				for (j = 1, k = 0, l = order - 2; j < order - i; j++, k++, l--)
				{
					current[j] = previous[k] + A1 * B[l] - B1 * A[k];
				}
			}

#else

      // setup the first row in wedge
      for (i = 0, j = order - 1; i < order; i++, j--)
      {
        I[0, i] = e * B[j];
      }

      // calculate values in the rest of the wedge
      for (i = 1; i < order; i++)
      {
        A1 = e * A[order - i - 1];
        B1 = e * B[i - 1];
        I[i, 0] = A1;
        for (j = 1, k = 0, l = order - 2; j < order - i; j++, k++, l--)
        {
          I[i, j] = I[i - 1, k] + A1 * B[l] - B1 * A[k];
        }
      }
#endif

			// inverse is a persymmetric matrix.
			for (i = 0, j = order - 1; i < order; i++, j--)
			{
				for (k = 0, l = order - 1; k < j; k++, l--)
				{
					I[l, j] = I[i, k];
				}
			}

			return I;
		}
Esempio n. 35
0
		/// <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);
		}
Esempio n. 36
0
		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;
		}
            public void Test(double[] arr)
            {
                double[] re = (double[])arr.Clone();
                double[] im = new double[arr.Length];

                double sum = 0;

                for (int i = 0; i < arr.Length; i++)
                {
                    sum += (arr[i] * arr[i]);
                }
                sum = Math.Sqrt(sum / arr.Length);
                double tol  = sum * arr.Length * 1E-14;
                double tol2 = arr.Length * 1E-14;

                // We transform the array
                var rft = new RealFourierTransform(arr.Length);

                rft.Transform(arr, FourierDirection.Forward);
                var wrapper = new RealFFTResultWrapper(arr);

                // we transform the re and im
                NativeFourierMethods.FourierTransformation(re, im, FourierDirection.Forward);

                // now compare the results
                // first the realpart
                var realpart = wrapper.RealPart;

                for (int i = 0; i < realpart.Length; i++)
                {
                    Assert.AreEqual(re[i], realpart[i], tol, string.Format("Testing realpart (len={0}, i={1})", arr.Length, i));
                }
                // now the imaginary part
                var imagpart = wrapper.ImaginaryPart;

                for (int i = 0; i < imagpart.Length; i++)
                {
                    Assert.AreEqual(im[i], imagpart[i], tol, string.Format("Testing imagpart (len={0}, i={1})", arr.Length, i));
                }

                // now the complex result
                IROComplexDoubleVector reimpart = wrapper.ComplexResult;

                for (int i = 0; i < reimpart.Length; i++)
                {
                    Assert.AreEqual(re[i], reimpart[i].Re, tol, string.Format("Testing ComplexResult.Re (len={0}, i={1})", arr.Length, i));
                    Assert.AreEqual(im[i], reimpart[i].Im, tol, string.Format("Testing ComplexResult.Im (len={0}, i={1})", arr.Length, i));
                }

                // now the amplitude part
                var amppart = wrapper.Amplitude;

                for (int i = 0; i < imagpart.Length; i++)
                {
                    double expected = Altaxo.Calc.RMath.Hypot(re[i], im[i]);
                    Assert.AreEqual(expected, amppart[i], tol, string.Format("Testing amplitude (len={0}, i={1})", arr.Length, i));
                }

                // now the phase part
                var phasepart = wrapper.Phase;

                for (int i = 0; i < imagpart.Length; i++)
                {
                    double ampl = Altaxo.Calc.RMath.Hypot(re[i], im[i]);
                    if (ampl < 1E-14 * arr.Length)
                    {
                        continue;
                    }
                    double expected = Math.Atan2(im[i], re[i]);
                    double actual   = phasepart[i];
                    if (Math.Abs(Math.Sin(expected) - Math.Sin(actual)) > tol2 || Math.Abs(Math.Cos(expected) - Math.Cos(actual)) > tol2)
                    {
                        Assert.Fail(string.Format("Testing phase (len={0}, i={1}, Expected={2}, Actual={3})", arr.Length, i, expected, actual));
                    }
                }
            }
    /// <summary>
    /// Solve a symmetric square Toeplitz system with a right-side matrix.
    /// </summary>
    /// <param name="T">The left-most column of the Toeplitz matrix.</param>
    /// <param name="Y">The right-side matrix of the system.</param>
    /// <returns>The solution matrix.</returns>
    /// <exception cref="ArgumentNullException">
    /// <B>T</B> and/or <B>Y</B> are null references
    /// </exception>
    /// <exception cref="RankException">
    /// The length of <B>T</B> does not match the number of rows in <B>Y</B>.
    /// </exception>
    /// <exception cref="SingularMatrixException">
    /// The Toeplitz matrix or one of the the leading sub-matrices is singular.
    /// </exception>
    /// <remarks>
    /// This method solves the linear system <B>AX</B> = <B>Y</B>. Where
    /// <B>T</B> is a symmetric square Toeplitz matrix, <B>X</B> is an unknown
    /// matrix and <B>Y</B> is a known matrix.
    /// <para>
    /// This static member combines the <b>UDL</b> decomposition and the calculation of the solution into a
    /// single algorithm. When compared to the non-static member it requires minimal data storage
    /// and suffers from no speed penalty.
    /// </para>
    /// </remarks>
    public static ComplexDoubleMatrix Solve(IROComplexDoubleVector T, IROComplexDoubleMatrix Y)
    {

      ComplexDoubleMatrix X;

      // check parameters
      if (T == null)
      {
        throw new System.ArgumentNullException("T");
      }
      else if (Y == null)
      {
        throw new System.ArgumentNullException("Y");
      }
      else if (T.Length != Y.Columns)
      {
        throw new RankException("The length of T and Y are not equal.");
      }
      else
      {

        // allocate memory
        int N = T.Length;
        int M = Y.Rows;
        X = new ComplexDoubleMatrix(N, M);                 // solution matrix
        ComplexDoubleVector Z = new ComplexDoubleVector(N);       // temporary storage vector
        Complex e;                                   // prediction error
        int i, j, l, m;

        // setup zero order solution
        e = T[0];
        if (e == Complex.Zero)
        {
          throw new SingularMatrixException("The Toeplitz matrix or one of the the leading sub-matrices is singular.");
        }
        for (m = 0; m < M; m++)
        {
          X[0, m] = Y[0,m] / T[0];
        }

        if (N > 1)
        {

          ComplexDoubleVector a = new ComplexDoubleVector(N - 1);   // prediction coefficients
          Complex p;                                   // reflection coefficient
          Complex inner;                               // inner product
          Complex k;

          // calculate solution for successive orders
          for (i = 1; i < N; i++)
          {

            // calculate first inner product
            inner = T[i];
            for (j = 0, l = i - 1; j < i - 1; j++, l--)
            {
              inner += a[j] * T[l];
            }

            // update predictor coefficients
            p = -(inner / e);
            for (j = 0, l = i - 2; j < i - 1; j++, l--)
            {
              Z[j] = a[j] + p * a[l];
            }

            // copy vector
            for (j = 0; j < i - 1; j++)
            {
              a[j] = Z[j];
            }

            a[i - 1] = p;
            e *= (Complex.One - p * p);

            if (e == Complex.Zero)
            {
              throw new SingularMatrixException("The Toeplitz matrix or one of the the leading sub-matrices is singular.");
            }

            // update the solution matrix
            for (m = 0; m < M; m++)
            {

              // retrieve a copy of solution column
              for (j = 0; j < i; j++)
              {
                Z[j] = X[j, m];
              }

              // calculate second inner product
              inner = Y[i, m];
              for (j = 0, l = i; j < i; j++, l--)
              {
                inner -= Z[j] * T[l];
              }

              // update solution vector
              k = inner / e;
              for (j = 0, l = i - 1; j < i; j++, l--)
              {
                Z[j] = Z[j] + k * a[l];
              }
              Z[j] = k;

              // store solution column in matrix
              for (j = 0; j <= i; j++)
              {
                X[j, m] = Z[j];
              }

            }

          }

        }

      }

      return X;
    }
Esempio n. 39
0
		/// <summary>
		/// Solve a square Toeplitz system with a right-side matrix.
		/// </summary>
		/// <param name="col">The left-most column of the Toeplitz matrix.</param>
		/// <param name="row">The top-most row of the Toeplitz matrix.</param>
		/// <param name="Y">The right-side matrix of the system.</param>
		/// <returns>The solution matrix.</returns>
		/// <exception cref="ArgumentNullException">
		/// <EM>col</EM> is a null reference,
		/// <para>or</para>
		/// <para><EM>row</EM> is a null reference,</para>
		/// <para>or</para>
		/// <para><EM>Y</EM> is a null reference.</para>
		/// </exception>
		/// <exception cref="RankException">
		/// The length of <EM>col</EM> is 0,
		/// <para>or</para>
		/// <para>the lengths of <EM>col</EM> and <EM>row</EM> are not equal,</para>
		/// <para>or</para>
		/// <para>the number of rows in <EM>Y</EM> does not the length of <EM>col</EM> and <EM>row</EM>.</para>
		/// </exception>
		/// <exception cref="SingularMatrixException">
		/// The Toeplitz matrix or one of the the leading sub-matrices is singular.
		/// </exception>
		/// <exception cref="ArithmeticException">
		/// The values of the first element of <EM>col</EM> and <EM>row</EM> are not equal.
		/// </exception>
		/// <remarks>
		/// This method solves the linear system <B>AX</B> = <B>Y</B>. Where
		/// <B>T</B> is a square Toeplitz matrix, <B>X</B> is an unknown
		/// matrix and <B>Y</B> is a known matrix.
		/// <para>
		/// The classic Levinson algorithm is used to solve the system. The algorithm
		/// assumes that all the leading sub-matrices of the Toeplitz matrix are
		/// non-singular. When a sub-matrix is near singular, accuracy will
		/// be degraded. This member requires approximately <B>N</B> squared
		/// FLOPS to calculate a solution, where <B>N</B> is the matrix order.
		/// </para>
		/// <para>
		/// This static method has minimal storage requirements as it combines
		/// the <b>UDL</b> decomposition with the calculation of the solution vector
		/// in a single algorithm.
		/// </para>
		/// </remarks>
		public static ComplexDoubleMatrix Solve(IROComplexDoubleVector col, IROComplexDoubleVector row, IROComplexDoubleMatrix Y)
		{
			// check parameters
			if (col == null)
			{
				throw new System.ArgumentNullException("col");
			}
			else if (col.Length == 0)
			{
				throw new RankException("The length of col is zero.");
			}
			else if (row == null)
			{
				throw new System.ArgumentNullException("row");
			}
			else if (col.Length != row.Length)
			{
				throw new RankException("The lengths of col and row are not equal.");
			}
			else if (col[0] != row[0])
			{
				throw new ArithmeticException("The values of the first element of col and row are not equal.");
			}
			else if (Y == null)
			{
				throw new System.ArgumentNullException("Y");
			}
			else if (col.Length != Y.Columns)
			{
				throw new RankException("The numer of rows in Y does not match the length of col and row.");
			}

			// check if leading diagonal is zero
			if (col[0] == Complex.Zero)
			{
				throw new SingularMatrixException("One of the leading sub-matrices is singular.");
			}

			// decompose matrix
			int order = col.Length;
			Complex[] A = new Complex[order];
			Complex[] B = new Complex[order];
			Complex[] Z = new Complex[order];
			ComplexDoubleMatrix X = new ComplexDoubleMatrix(order);
			Complex Q, S, Ke, Kr, e;
			Complex Inner;
			int i, j, l;

			// setup the zero order solution
			A[0] = Complex.One;
			B[0] = Complex.One;
			e = Complex.One / col[0];
			X.SetRow(0, e * ComplexDoubleVector.GetRow(Y, 0));

			for (i = 1; i < order; i++)
			{
				// calculate inner products
				Q = Complex.Zero;
				for (j = 0, l = 1; j < i; j++, l++)
				{
					Q += col[l] * A[j];
				}

				S = Complex.Zero;
				for (j = 0, l = 1; j < i; j++, l++)
				{
					S += row[l] * B[j];
				}

				// reflection coefficients
				Kr = -S * e;
				Ke = -Q * e;

				// update lower triangle (in temporary storage)
				Z[0] = Complex.Zero;
				Array.Copy(A, 0, Z, 1, i);
				for (j = 0, l = i - 1; j < i; j++, l--)
				{
					Z[j] += Ke * B[l];
				}

				// update upper triangle
				for (j = i; j > 0; j--)
				{
					B[j] = B[j - 1];
				}

				B[0] = Complex.Zero;
				for (j = 0, l = i - 1; j < i; j++, l--)
				{
					B[j] += Kr * A[l];
				}

				// copy from temporary storage to lower triangle
				Array.Copy(Z, 0, A, 0, i + 1);

				// check for singular sub-matrix)
				if (Ke * Kr == Complex.One)
				{
					throw new SingularMatrixException("One of the leading sub-matrices is singular.");
				}

				// update diagonal
				e = e / (Complex.One - Ke * Kr);

				for (l = 0; l < Y.Rows; l++)
				{
					ComplexDoubleVector W = X.GetColumn(l);
					ComplexDoubleVector M = ComplexDoubleVector.GetColumn(Y, l);

					Inner = M[i];
					for (j = 0; j < i; j++)
					{
						Inner += A[j] * M[j];
					}
					Inner *= e;

					W[i] = Inner;
					for (j = 0; j < i; j++)
					{
						W[j] += Inner * B[j];
					}

					X.SetColumn(l, W);
				}
			}

			return X;
		}
Esempio n. 40
0
 /// <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);
 }
Esempio n. 41
0
		/// <overloads>
		/// Solve a square Toeplitz system.
		/// </overloads>
		/// <summary>
		/// Solve a square Toeplitz system with a right-side vector.
		/// </summary>
		/// <param name="Y">The right-hand side of the system.</param>
		/// <returns>The solution vector.</returns>
		/// <exception cref="ArgumentNullException">
		/// Parameter <B>Y</B> is a null reference.
		/// </exception>
		/// <exception cref="RankException">
		/// The length of Y is not equal to the number of rows in the Toeplitz matrix.
		/// </exception>
		/// <exception cref="SingularMatrixException">
		/// The Toeplitz matrix or one of the the leading sub-matrices is singular.
		/// </exception>
		/// <remarks>
		/// This member solves the linear system <B>TX</B> = <B>Y</B>, where <B>T</B> is
		/// the square Toeplitz matrix, <B>X</B> is the unknown solution vector
		/// and <B>Y</B> is a known vector.
		/// <para>
		/// The class implicitly decomposes the inverse Toeplitz matrix into a <b>UDL</b> factorisation
		/// using the Levinson algorithm, before calculating the solution vector.
		/// </para>
		/// </remarks>
		public ComplexDoubleVector Solve(IROComplexDoubleVector Y)
		{
			ComplexDoubleVector X;
			Complex Inner;
			int i, j;

			// check parameters
			if (Y == null)
			{
				throw new System.ArgumentNullException("Y");
			}
			else if (m_Order != Y.Length)
			{
				throw new RankException("The length of Y is not equal to the number of rows in the Toeplitz matrix.");
			}

			Compute();

			if (m_IsSingular == true)
			{
				throw new SingularMatrixException("One of the leading sub-matrices is singular.");
			}

			// allocate memory for solution
			Complex[] A, B;
			X = new ComplexDoubleVector(m_Order);

			for (i = 0; i < m_Order; i++)
			{
				A = m_LowerTriangle[i];
				B = m_UpperTriangle[i];

				Inner = Y[i];
				for (j = 0; j < i; j++)
				{
					Inner += A[j] * Y[j];
				}
				Inner *= m_Diagonal[i];

				X[i] = Inner;
				for (j = 0; j < i; j++)
				{
					X[j] += Inner * B[j];
				}
			}
			return X;
		}
Esempio n. 42
0
		/// <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);
		}
Esempio n. 43
0
		/// <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);
		}
Esempio n. 44
0
		/// <summary>
		/// This algorithm determines the mean backward prediction error using the model stored in this instance. See remarks for details.
		/// </summary>
		/// <param name="x">Signal for which to determine the mean backward prediction error.</param>
		/// <returns>Mean backward prediction error.</returns>
		/// <remarks>
		/// 1. The prediction is done non recursively, i.e. part of the signal (the signal window) is used to predict the signal value before, and this predicted signal value is
		/// then compared with the original signal value stored in x to build the sum of errors. But the predicted signal value is <b>not</b> used to make further predictions.
		/// Instead, the signal window is moved by one point to the left and another prediction is made, with the original signal in x. This is repeated until the first point (index 0)
		/// is predicted. The return value is the square root of the sum of squared differences between predicted signal values and original values, divided by the number of predicted values.
		/// The number of predicted values is the length of the signal x minus the number of coefficents of the model.
		/// </remarks>
		public double GetMeanPredictionErrorNonrecursivelyBackward(IROComplexDoubleVector x)
		{
			int last = x.Length - _numberOfCoefficients;
			double sumsqr = 0;
			for (int i = last - 1; i >= 0; 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];
				}
				sumsqr += (x[i] - sum).GetModulusSquared();
			}
			return Math.Sqrt(sumsqr / (last));
		}
Esempio n. 45
0
		/// <summary>
		/// Transforms from a compact complex representation (nyquist frequency value put in imaginary part of first element) to real representation.
		/// </summary>
		/// <param name="src">Stores the  complex spectrum.</param>
		/// <param name="destination">After return, stores the spectrum in normalized real representation. The length of the vector has to be equal to the length of the FFT. </param>
		public static void FromRepresentationCompactComplexToReal(IROComplexDoubleVector src, IVector destination)
		{
			bool isEven = 0 == (destination.Length % 2);
			int destLen2;
			if (isEven)
			{
				destLen2 = destination.Length / 2;
				destination[0] = src[0].Re;
				destination[destLen2] = src[0].Im; ;
			}
			else // odd
			{
				destLen2 = (destination.Length - 1) / 2;
				destination[0] = src[0].Re;
			}
			for (int i = 1, j = destination.Length - 1; i < j; i++, j--)
			{
				destination[i] = src[i].Re;
				destination[j] = src[i].Im;
			}
		}
Esempio n. 46
0
        /// <summary>
        /// Solve a symmetric square Toeplitz system with a right-side matrix.
        /// </summary>
        /// <param name="T">The left-most column of the Toeplitz matrix.</param>
        /// <param name="Y">The right-side matrix of the system.</param>
        /// <returns>The solution matrix.</returns>
        /// <exception cref="ArgumentNullException">
        /// <B>T</B> and/or <B>Y</B> are null references
        /// </exception>
        /// <exception cref="RankException">
        /// The length of <B>T</B> does not match the number of rows in <B>Y</B>.
        /// </exception>
        /// <exception cref="SingularMatrixException">
        /// The Toeplitz matrix or one of the the leading sub-matrices is singular.
        /// </exception>
        /// <remarks>
        /// This method solves the linear system <B>AX</B> = <B>Y</B>. Where
        /// <B>T</B> is a symmetric square Toeplitz matrix, <B>X</B> is an unknown
        /// matrix and <B>Y</B> is a known matrix.
        /// <para>
        /// This static member combines the <b>UDL</b> decomposition and the calculation of the solution into a
        /// single algorithm. When compared to the non-static member it requires minimal data storage
        /// and suffers from no speed penalty.
        /// </para>
        /// </remarks>
        public static ComplexDoubleMatrix Solve(IROComplexDoubleVector T, IROComplexDoubleMatrix Y)
        {
            ComplexDoubleMatrix X;

            // check parameters
            if (T == null)
            {
                throw new System.ArgumentNullException("T");
            }
            else if (Y == null)
            {
                throw new System.ArgumentNullException("Y");
            }
            else if (T.Length != Y.Columns)
            {
                throw new RankException("The length of T and Y are not equal.");
            }
            else
            {
                // allocate memory
                int N = T.Length;
                int M = Y.Rows;
                X = new ComplexDoubleMatrix(N, M);                  // solution matrix
                ComplexDoubleVector Z = new ComplexDoubleVector(N); // temporary storage vector
                Complex             e;                              // prediction error
                int i, j, l, m;

                // setup zero order solution
                e = T[0];
                if (e == Complex.Zero)
                {
                    throw new SingularMatrixException("The Toeplitz matrix or one of the the leading sub-matrices is singular.");
                }
                for (m = 0; m < M; m++)
                {
                    X[0, m] = Y[0, m] / T[0];
                }

                if (N > 1)
                {
                    ComplexDoubleVector a = new ComplexDoubleVector(N - 1); // prediction coefficients
                    Complex             p;                                  // reflection coefficient
                    Complex             inner;                              // inner product
                    Complex             k;

                    // calculate solution for successive orders
                    for (i = 1; i < N; i++)
                    {
                        // calculate first inner product
                        inner = T[i];
                        for (j = 0, l = i - 1; j < i - 1; j++, l--)
                        {
                            inner += a[j] * T[l];
                        }

                        // update predictor coefficients
                        p = -(inner / e);
                        for (j = 0, l = i - 2; j < i - 1; j++, l--)
                        {
                            Z[j] = a[j] + p * a[l];
                        }

                        // copy vector
                        for (j = 0; j < i - 1; j++)
                        {
                            a[j] = Z[j];
                        }

                        a[i - 1] = p;
                        e       *= (Complex.One - p * p);

                        if (e == Complex.Zero)
                        {
                            throw new SingularMatrixException("The Toeplitz matrix or one of the the leading sub-matrices is singular.");
                        }

                        // update the solution matrix
                        for (m = 0; m < M; m++)
                        {
                            // retrieve a copy of solution column
                            for (j = 0; j < i; j++)
                            {
                                Z[j] = X[j, m];
                            }

                            // calculate second inner product
                            inner = Y[i, m];
                            for (j = 0, l = i; j < i; j++, l--)
                            {
                                inner -= Z[j] * T[l];
                            }

                            // update solution vector
                            k = inner / e;
                            for (j = 0, l = i - 1; j < i; j++, l--)
                            {
                                Z[j] = Z[j] + k * a[l];
                            }
                            Z[j] = k;

                            // store solution column in matrix
                            for (j = 0; j <= i; j++)
                            {
                                X[j, m] = Z[j];
                            }
                        }
                    }
                }
            }

            return(X);
        }
    /// <summary>
    /// Solve the Yule-Walker equations for a symmetric square Toeplitz system
    /// </summary>
    /// <param name="R">The left-most column of the Toeplitz matrix.</param>
    /// <returns>The solution vector.</returns>
    /// <exception cref="ArgumentNullException">
    /// <B>R</B> is a null reference.
    /// </exception>
    /// <exception cref="ArgumentOutOfRangeException">
    /// The length of <B>R</B> must be greater than one.
    /// </exception>
    /// <exception cref="SingularMatrixException">
    /// The Toeplitz matrix or one of the the leading sub-matrices is singular.
    /// </exception>
    /// <remarks>
    /// This member is used to solve the Yule-Walker system <B>AX</B> = -<B>a</B>,
    /// where <B>A</B> is a symmetric square Toeplitz matrix, constructed
    /// from the elements <B>R[0]</B>, ..., <B>R[N-2]</B> and
    /// the vector <B>a</B> is constructed from the elements
    /// <B>R[1]</B>, ..., <B>R[N-1]</B>.
    /// <para>
    /// Durbin's algorithm is used to solve the linear system. It requires
    /// approximately the <b>N</b> squared FLOPS to calculate the
    /// solution (<b>N</b> is the matrix order).
    /// </para>
    /// </remarks>
    public static ComplexDoubleVector YuleWalker(IROComplexDoubleVector R)
    {

      ComplexDoubleVector a;

      // check parameters
      if (R == null)
      {
        throw new System.ArgumentNullException("R");
      }
      else if (R.Length < 2)
      {
        throw new System.ArgumentOutOfRangeException("R", "The length of R must be greater than 1.");
      }
      else
      {

        int N = R.Length - 1;
        a = new ComplexDoubleVector(N);             // prediction coefficients
        ComplexDoubleVector Z = new ComplexDoubleVector(N);   // temporary storage vector
        Complex e;                    // predictor error
        Complex inner;                  // inner product
        Complex g;                    // reflection coefficient
        int i, j, l;

        // setup first order solution
        e = R[0];
        if (e == Complex.Zero)
        {
          throw new SingularMatrixException("The Toeplitz matrix or one of the the leading sub-matrices is singular.");
        }
        g = -R[1] / R[0];
        a[0] = g;

        // calculate solution for successive orders
        for (i = 1; i < N; i++)
        {

          e *= (Complex.One - g * g);
          if (e == Complex.Zero)
          {
            throw new SingularMatrixException("The Toeplitz matrix or one of the the leading sub-matrices is singular.");
          }

          // calculate inner product
          inner = R[i + 1];
          for (j = 0, l = i; j < i; j++, l--)
          {
            inner += a[j] * R[l];
          }

          // update prediction coefficients
          g = -(inner / e);
          for (j = 0, l = i - 1; j < i; j++, l--)
          {
            Z[j] = a[j] + g * a[l];
          }

          // copy vector
          for (j = 0; j < i; j++)
          {
            a[j] = Z[j];
          }

          a[i] = g;

        }
      }

      return a;
    }
Esempio n. 48
0
        /// <summary>
        /// Solve the Yule-Walker equations for a symmetric square Toeplitz system
        /// </summary>
        /// <param name="R">The left-most column of the Toeplitz matrix.</param>
        /// <returns>The solution vector.</returns>
        /// <exception cref="ArgumentNullException">
        /// <B>R</B> is a null reference.
        /// </exception>
        /// <exception cref="ArgumentOutOfRangeException">
        /// The length of <B>R</B> must be greater than one.
        /// </exception>
        /// <exception cref="SingularMatrixException">
        /// The Toeplitz matrix or one of the the leading sub-matrices is singular.
        /// </exception>
        /// <remarks>
        /// This member is used to solve the Yule-Walker system <B>AX</B> = -<B>a</B>,
        /// where <B>A</B> is a symmetric square Toeplitz matrix, constructed
        /// from the elements <B>R[0]</B>, ..., <B>R[N-2]</B> and
        /// the vector <B>a</B> is constructed from the elements
        /// <B>R[1]</B>, ..., <B>R[N-1]</B>.
        /// <para>
        /// Durbin's algorithm is used to solve the linear system. It requires
        /// approximately the <b>N</b> squared FLOPS to calculate the
        /// solution (<b>N</b> is the matrix order).
        /// </para>
        /// </remarks>
        public static ComplexDoubleVector YuleWalker(IROComplexDoubleVector R)
        {
            ComplexDoubleVector a;

            // check parameters
            if (R == null)
            {
                throw new System.ArgumentNullException("R");
            }
            else if (R.Length < 2)
            {
                throw new System.ArgumentOutOfRangeException("R", "The length of R must be greater than 1.");
            }
            else
            {
                int N = R.Length - 1;
                a = new ComplexDoubleVector(N);                     // prediction coefficients
                ComplexDoubleVector Z = new ComplexDoubleVector(N); // temporary storage vector
                Complex             e;                              // predictor error
                Complex             inner;                          // inner product
                Complex             g;                              // reflection coefficient
                int i, j, l;

                // setup first order solution
                e = R[0];
                if (e == Complex.Zero)
                {
                    throw new SingularMatrixException("The Toeplitz matrix or one of the the leading sub-matrices is singular.");
                }
                g    = -R[1] / R[0];
                a[0] = g;

                // calculate solution for successive orders
                for (i = 1; i < N; i++)
                {
                    e *= (Complex.One - g * g);
                    if (e == Complex.Zero)
                    {
                        throw new SingularMatrixException("The Toeplitz matrix or one of the the leading sub-matrices is singular.");
                    }

                    // calculate inner product
                    inner = R[i + 1];
                    for (j = 0, l = i; j < i; j++, l--)
                    {
                        inner += a[j] * R[l];
                    }

                    // update prediction coefficients
                    g = -(inner / e);
                    for (j = 0, l = i - 1; j < i; j++, l--)
                    {
                        Z[j] = a[j] + g * a[l];
                    }

                    // copy vector
                    for (j = 0; j < i; j++)
                    {
                        a[j] = Z[j];
                    }

                    a[i] = g;
                }
            }

            return(a);
        }
    /// <overloads>
    /// There are two permuations of the constructor, both require a parameter corresponding
    /// to the left-most column of a Toeplitz matrix.
    /// </overloads>
    /// <summary>
    /// Constructor with <c>ComplexDoubleVector</c> parameter.
    /// </summary>
    /// <param name="T">The left-most column of the Toeplitz matrix.</param>
    /// <exception cref="ArgumentNullException">
    /// <B>T</B> is a null reference.
    /// </exception>
    /// <exception cref="RankException">
    /// The length of <B>T</B> is zero.
    /// </exception>
    public ComplexDoubleSymmetricLevinson(IROComplexDoubleVector T)
    {
      // check parameter
      if (T == null)
      {
        throw new System.ArgumentNullException("T");
      }
      else if (T.Length == 0)
      {
        throw new RankException("The length of T is zero.");
      }

      // save the vector
      m_LeftColumn = new ComplexDoubleVector(T);
      m_Order = m_LeftColumn.Length;

      // allocate memory for lower triangular matrix
      m_LowerTriangle = new Complex[m_Order][];
      for (int i = 0; i < m_Order; i++)
      {
        m_LowerTriangle[i] = new Complex[i+1];
      }

      // allocate memory for diagonal
      m_Diagonal = new Complex[m_Order];

    }
Esempio n. 50
0
        /// <summary>
        /// Invert a symmetric square Toeplitz matrix.
        /// </summary>
        /// <param name="T">The left-most column of the symmetric Toeplitz matrix.</param>
        /// <returns>The inverse matrix.</returns>
        /// <exception cref="ArgumentNullException">
        /// <B>T</B> is a null reference.
        /// </exception>
        /// <exception cref="RankException">
        /// The length of <B>T</B> must be greater than zero.
        /// </exception>
        /// <exception cref="SingularMatrixException">
        /// The Toeplitz matrix or one of the the leading sub-matrices is singular.
        /// </exception>
        /// <remarks>
        /// This static member combines the <b>UDL</b> decomposition and Trench's algorithm into a
        /// single algorithm. When compared to the non-static member it requires minimal data storage
        /// and suffers from no speed penalty.
        /// <para>
        /// Trench's algorithm requires <b>N</b> squared FLOPS, compared to <b>N</b> cubed FLOPS
        /// if we simply solved a linear Toeplitz system with a right-side identity matrix (<b>N</b> is the matrix order).
        /// </para>
        /// </remarks>
        public static ComplexDoubleMatrix Inverse(IROComplexDoubleVector T)
        {
            ComplexDoubleMatrix X;

            // check parameters
            if (T == null)
            {
                throw new System.ArgumentNullException("T");
            }
            else if (T.Length < 1)
            {
                throw new System.RankException("The length of T must be greater than zero.");
            }
            else if (T.Length == 1)
            {
                X       = new ComplexDoubleMatrix(1);
                X[0, 0] = Complex.One / T[0];
            }
            else
            {
                int     N = T.Length;
                Complex f, g;
                int     i, j, l, k, m, n;
                X = new ComplexDoubleMatrix(N);

                // calculate the predictor coefficients
                ComplexDoubleVector Y = ComplexDoubleSymmetricLevinson.YuleWalker(T);

                // calculate gamma
                f = T[0];
                for (i = 1, j = 0; i < N; i++, j++)
                {
                    f += T[i] * Y[j];
                }
                g = Complex.One / f;

                // calculate first row of inverse
                X[0, 0] = g;
                for (i = 1, j = 0; i < N; i++, j++)
                {
                    X[0, i] = g * Y[j];
                }

                // calculate successive rows of upper wedge
                for (i = 0, j = 1, k = N - 2; i < N / 2; i++, j++, k--)
                {
                    for (l = j, m = i, n = N - 1 - j; l < N - j; l++, m++, n--)
                    {
                        X[j, l] = X[i, m] + g * (Y[i] * Y[m] - Y[k] * Y[n]);
                    }
                }

                // this is symmetric matrix ...
                for (i = 0; i <= N / 2; i++)
                {
                    for (j = i + 1; j < N - i; j++)
                    {
                        X[j, i] = X[i, j];
                    }
                }

                // and a persymmetric matrix.
                for (i = 0, j = N - 1; i < N; i++, j--)
                {
                    for (k = 0, l = N - 1; k < j; k++, l--)
                    {
                        X[l, j] = X[i, k];
                    }
                }
            }

            return(X);
        }
    /// <overloads>
    /// Solve a symmetric square Toeplitz system.
    /// </overloads>
    /// <summary>
    /// Solve a symmetric square Toeplitz system with a right-side vector.
    /// </summary>
    /// <param name="T">The left-most column of the Toeplitz matrix.</param>
    /// <param name="Y">The right-side vector of the system.</param>
    /// <returns>The solution vector.</returns>
    /// <exception cref="ArgumentNullException">
    /// <B>T</B> and/or <B>Y</B> are null references
    /// </exception>
    /// <exception cref="RankException">
    /// The length of <B>T</B> does not match the length of <B>Y</B>.
    /// </exception>
    /// <exception cref="SingularMatrixException">
    /// The Toeplitz matrix or one of the the leading sub-matrices is singular.
    /// </exception>
    /// <remarks>
    /// This method solves the linear system <B>AX</B> = <B>Y</B>. Where
    /// <B>T</B> is a symmetric square Toeplitz matrix, <B>X</B> is an unknown
    /// vector and <B>Y</B> is a known vector.
    /// <para>
    /// This static member combines the <b>UDL</b> decomposition and the calculation of the solution into a
    /// single algorithm. When compared to the non-static member it requires minimal data storage
    /// and suffers from no speed penalty.
    /// </para>
    /// </remarks>
    public static ComplexDoubleVector Solve(IROComplexDoubleVector T, IROComplexDoubleVector Y)
    {

      ComplexDoubleVector X;

      // check parameters
      if (T == null)
      {
        throw new System.ArgumentNullException("T");
      }
      else if (Y == null)
      {
        throw new System.ArgumentNullException("Y");
      }
      else if (T.Length != Y.Length)
      {
        throw new RankException("The length of T and Y are not equal.");
      }
      else
      {

        // allocate memory
        int N = T.Length;
        X = new ComplexDoubleVector(N);                    // solution vector
        Complex e;                                   // prediction error

        // setup zero order solution
        e = T[0];
        if (e == Complex.Zero)
        {
          throw new SingularMatrixException("The Toeplitz matrix or one of the the leading sub-matrices is singular.");
        }
        X[0] = Y[0] / T[0];

        if (N > 1)
        {
          ComplexDoubleVector a = new ComplexDoubleVector(N - 1);   // prediction coefficients
          ComplexDoubleVector Z = new ComplexDoubleVector(N - 1);   // temporary storage vector
          Complex g;                                   // reflection coefficient
          Complex inner;                               // inner product
          Complex k;
          int i, j, l;

          // calculate solution for successive orders
          for (i = 1; i < N; i++)
          {

            // calculate first inner product
            inner = T[i];
            for (j = 0, l = i - 1; j < i - 1; j++, l--)
            {
              inner += a[j] * T[l];
            }

            // update predictor coefficients
            g = -(inner / e);
            for (j = 0, l = i - 2; j < i - 1; j++, l--)
            {
              Z[j] = a[j] + g * a[l];
            }

            // copy vector
            for (j = 0; j < i - 1; j++)
            {
              a[j] = Z[j];
            }

            a[i - 1] = g;

            e *= (Complex.One - g * g);
            if (e == Complex.Zero)
            {
              throw new SingularMatrixException("The Toeplitz matrix or one of the the leading sub-matrices is singular.");
            }

            // calculate second inner product
            inner = Y[i];
            for (j = 0, l = i; j < i; j++, l--)
            {
              inner -= X[j] * T[l];
            }

            // update solution vector
            k = inner / e;
            for (j = 0, l = i - 1; j < i; j++, l--)
            {
              X[j] = X[j] + k * a[l];
            }
            X[j] = k;

          }

        }

      }

      return X;

    }
Esempio n. 52
0
		/// <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));
		}