/// <summary> /// This function computes the singular value decomposition of the trajectory matrix. /// This function only computes the singular values and the left singular vectors. /// </summary> /// <param name="singularValues">The output singular values of size L</param> /// <param name="leftSingularvectors">The output singular vectors of size L*L</param> public bool ComputeSvd(out Single[] singularValues, out Single[] leftSingularvectors) { Single[] covariance = new Single[_windowSize * _windowSize]; Single[] sVal; Single[] sVec; singularValues = new Single[_windowSize]; leftSingularvectors = new Single[_windowSize * _windowSize]; // Computing the covariance matrix of the trajectory matrix on the input series ComputeUnnormalizedTrajectoryCovarianceMat(covariance); // Computing the eigen decomposition of the covariance matrix //EigenUtils.EigenDecomposition(covariance, out sVal, out sVec); EigenUtils.MklSymmetricEigenDecomposition(covariance, _windowSize, out sVal, out sVec); var ind = new int[_windowSize]; int i; for (i = 0; i < _windowSize; ++i) { ind[i] = i; } Array.Sort(ind, (a, b) => sVal[b].CompareTo(sVal[a])); for (i = 0; i < _windowSize; ++i) { singularValues[i] = sVal[ind[i]]; Array.Copy(sVec, _windowSize * ind[i], leftSingularvectors, _windowSize * i, _windowSize); } return(true); }
/// <summary> /// Computes the real and the complex roots of a real monic polynomial represented as: /// coefficients[0] + coefficients[1] * X + coefficients[2] * X^2 + ... + coefficients[n-1] * X^(n-1) + X^n /// by computing the eigenvalues of the Companion matrix. (https://en.wikipedia.org/wiki/Companion_matrix) /// </summary> /// <param name="coefficients">The monic polynomial coefficients in the ascending order</param> /// <param name="roots">The computed (complex) roots</param> /// <param name="roundOffDigits">The number decimal digits to keep after round-off</param> /// <param name="doublePrecision">The machine precision</param> /// <returns>A boolean flag indicating whether the algorithm was successful.</returns> public static bool FindPolynomialRoots(Double[] coefficients, ref Complex[] roots, int roundOffDigits = 6, Double doublePrecision = 2.22 * 1e-100) { Contracts.CheckParam(doublePrecision > 0, nameof(doublePrecision), "The double precision must be positive."); Contracts.CheckParam(Utils.Size(coefficients) >= 1, nameof(coefficients), "There must be at least one input coefficient."); int i; int n = coefficients.Length; bool result = true; _tol = doublePrecision; if (Utils.Size(roots) < n) { roots = new Complex[n]; } // Extracting the zero roots for (i = 0; i < n; ++i) { if (IsZero(coefficients[i])) { roots[n - i - 1] = Complex.Zero; } else { break; } } if (i == n) // All zero roots { return(true); } if (i == n - 1) // Handling the linear case { roots[0] = new Complex(-coefficients[i], 0); } else if (i == n - 2) // Handling the quadratic case { FindQuadraticRoots(coefficients[i + 1], coefficients[i], out roots[0], out roots[1]); } else // Handling higher-order cases by computing the eigenvalues of the Companion matrix { var coeff = coefficients; if (i > 0) { coeff = new Double[n - i]; Array.Copy(coefficients, i, coeff, 0, n - i); } // REVIEW: the eigen decomposition of the companion matrix should be done using the FactorizedCompanionMatrix class // instead of MKL. //FactorizedCompanionMatrix companionMatrix = new FactorizedCompanionMatrix(coeff); //result = companionMatrix.ComputeEigenValues(ref roots); Double[] companionMatrix = null; var realPart = new Double[n - i]; var imaginaryPart = new Double[n - i]; var dummy = new Double[1]; CreateFullCompanionMatrix(coeff, ref companionMatrix); var info = EigenUtils.Dhseqr(EigenUtils.Layout.ColMajor, EigenUtils.Job.EigenValues, EigenUtils.Compz.None, n - i, 1, n - i, companionMatrix, n - i, realPart, imaginaryPart, dummy, n - i); if (info != 0) { return(false); } for (var j = 0; j < n - i; ++j) { roots[j] = new Complex(realPart[j], imaginaryPart[j]); } } return(result); }