Ejemplo n.º 1
0
        /// <summary>Gets the (complex) roots of the polynomial.
        /// </summary>
        /// <param name="roots">The roots (output).</param>
        /// <param name="rootFinderApproach">The root finder approach. Some implementations for polynomials with degree up to 3 ignore this parameter because of known analytic solutions.</param>
        /// <remarks>Each root of the polynomial given by the current instance will be added to <paramref name="roots" />, i.e. <see cref="Degree" /> elements.
        /// <para><paramref name="roots" /> will <c>not</c> be cleared before adding roots.</para>
        /// </remarks>
        public void GetRoots(IList <Complex> roots, IPolynomialRootFinder rootFinderApproach)
        {
            GetRoots(m_AbsoluteCoefficient, m_FirstOrderCoefficient, m_SecondOrderCoefficient, out Complex firstRoot, out Complex secondRoot);

            roots.Add(firstRoot);
            roots.Add(secondRoot);
        }
        /// <summary>Gets the real roots of the polynomial.
        /// </summary>
        /// <param name="realRoots">The real-valued roots (output).</param>
        /// <param name="rootFinderApproach">The root finder approach. Some implementations for polynomials with degree up to 3 ignore this parameter because of known analytic solutions.</param>
        /// <param name="imaginaryZeroTolerance">The (positive) tolerance taken into account to indicate whether a complex number is interpreted as real number.</param>
        /// <returns>The number or real roots added to <paramref name="realRoots" />.</returns>
        /// <remarks>
        /// The real roots of the polynomial given by the current instance will be added to <paramref name="realRoots" />. Roots are added with respect to their
        /// multiplicity, i.e. a root may add more than once in <paramref name="realRoots" />.
        /// <para><paramref name="realRoots" /> will <c>not</c> be cleared before adding real roots.</para>
        /// </remarks>
        public int GetRealRoots(IList <double> realRoots, IPolynomialRootFinder rootFinderApproach, double imaginaryZeroTolerance = MachineConsts.Epsilon)
        {
            // the implementation is based on §5.6, Numerical recipes, H. Press
            Complex sqrt = Complex.Sqrt(m_FirstOrderCoefficient * m_FirstOrderCoefficient - 4.0 * m_SecondOrderCoefficient * m_AbsoluteCoefficient);

            // compute the correct sign of the sqrt:
            if ((m_FirstOrderCoefficient * sqrt).Real < 0)
            {
                sqrt *= -1.0;
            }
            Complex q  = -0.5 * (m_FirstOrderCoefficient + sqrt);
            Complex x1 = q / m_SecondOrderCoefficient;
            Complex x2 = m_AbsoluteCoefficient / q;

            int numberOfRealRoots = 0;

            imaginaryZeroTolerance = Math.Min(MachineConsts.Epsilon, Math.Max(0, imaginaryZeroTolerance));

            if (Math.Abs(x1.Imaginary) < imaginaryZeroTolerance)
            {
                realRoots.Add(x1.Real);
                numberOfRealRoots++;
            }
            if (Math.Abs(x2.Imaginary) < imaginaryZeroTolerance)
            {
                realRoots.Add(x2.Real);
                numberOfRealRoots++;
            }
            return(numberOfRealRoots);
        }
        /// <summary>Gets the real roots of the polynomial.
        /// </summary>
        /// <param name="realRoots">The real-valued roots (output).</param>
        /// <param name="rootFinderApproach">The root finder approach. Some implementations for polynomials with degree up to 3 ignore this parameter because of known analytic solutions.</param>
        /// <param name="imaginaryZeroTolerance">The (positive) tolerance taken into account to indicate whether a complex number is interpreted as real number.</param>
        /// <returns>The number or real roots added to <paramref name="realRoots" />.</returns>
        /// <remarks>
        /// The real roots of the polynomial given by the current instance will be added to <paramref name="realRoots" />. Roots are added with respect to their
        /// multiplicity, i.e. a root may add more than once in <paramref name="realRoots" />.
        /// <para><paramref name="realRoots" /> will <c>not</c> be cleared before adding real roots.</para>
        /// </remarks>
        public int GetRealRoots(IList <double> realRoots, IPolynomialRootFinder rootFinderApproach, double imaginaryZeroTolerance = MachineConsts.Epsilon)
        {
            // the implementation is based on §5.6, Numerical recipes, H. Press

            // normalized coefficients, i.e. x^3 + a * x^2 + b * x + c
            Complex a = m_SecondOrderCoefficient / m_ThirdOrderCoefficient;
            Complex b = m_FirstOrderCoefficient / m_ThirdOrderCoefficient;
            Complex c = m_AbsoluteCoefficient / m_ThirdOrderCoefficient;

            Complex q = (a * a - 3.0 * b) / 9.0;
            Complex r = (2 * a * a * a - 9.0 * a * b + 27.0 * c) / 54.0;

            Complex sqrt = Complex.Sqrt(r * r - q * q * q);

            // compute the correct sign, i.e. such that \Re(r*sqrt) >= 0
            if ((r * sqrt).Real < 0)
            {
                sqrt *= -1.0;
            }

            /* Compute 'A = - (r + sqrt)^{1/3}', but keep in mind, that the cubic root is not unique defined.
             * In general, if z = r * e^{i t}, we have
             *
             * z^{1/3} = exp(1/3 * ln z)
             *         = r^{1/3} * exp(i*t/3), r^{1/3} * exp(i *(t/3 + 2\pi/3)), r^{1/3} * exp(i *(t/3 - 2\pi/3)).
             *
             * Here, we choose the first root.
             */
            Complex radicant = (r + sqrt);
            Complex A        = -Math.Pow(Complex.Abs(radicant), 1.0 / 3.0) * Complex.Exp(new Complex(0, Math.Atan2(radicant.Imaginary, radicant.Real) / 3.0));
            Complex B        = (A == 0.0) ? 0.0 : q / A; // It is not necessary to take into account any tolerance here

            int    numberOfRoots = 0;
            double epsilon       = Math.Min(MachineConsts.Epsilon, Math.Max(0, imaginaryZeroTolerance));

            Complex root1 = (A + B) - a / 3.0;

            if (Math.Abs(root1.Imaginary) < epsilon)
            {
                realRoots.Add(root1.Real);
                numberOfRoots++;
            }
            Complex firstRootPart  = -0.5 * (A + B) - a / 3.0;
            Complex secondRootPart = MathConsts.Sqrt3 / 2.0 * (A - B);

            if (Math.Abs(firstRootPart.Imaginary + secondRootPart.Real) < epsilon)
            {
                realRoots.Add(firstRootPart.Real - secondRootPart.Imaginary);
                numberOfRoots++;
            }
            if (Math.Abs(firstRootPart.Imaginary - secondRootPart.Real) < epsilon)
            {
                realRoots.Add(firstRootPart.Real + secondRootPart.Imaginary);
                numberOfRoots++;
            }
            return(numberOfRoots);
        }
Ejemplo n.º 4
0
        /// <summary>Gets the real roots of the polynomial.
        /// </summary>
        /// <param name="realRoots">The real-valued roots (output).</param>
        /// <param name="rootFinderApproach">The root finder approach. Some implementations for polynomials with degree up to 3 ignore this parameter because of known analytic solutions.</param>
        /// <param name="imaginaryZeroTolerance">The (positive) tolerance taken into account to indicate whether a complex number is interpreted as real number.</param>
        /// <returns>The number or real roots added to <paramref name="realRoots" />.</returns>
        /// <remarks>
        /// The real roots of the polynomial given by the current instance will be added to <paramref name="realRoots" />. Roots are added with respect to their
        /// multiplicity, i.e. a root may add more than once in <paramref name="realRoots" />.
        /// <para><paramref name="realRoots" /> will <c>not</c> be cleared before adding real roots.</para>
        /// </remarks>
        public int GetRealRoots(IList <double> realRoots, IPolynomialRootFinder rootFinderApproach, double imaginaryZeroTolerance = MachineConsts.Epsilon)
        {
            Complex complexRoot = unchecked (-m_AbsoluteCoefficient / m_FirstOrderCoefficient);

            if (Math.Abs(complexRoot.Imaginary) < Math.Min(Math.Max(0, imaginaryZeroTolerance), MachineConsts.Epsilon))
            {
                realRoots.Add(complexRoot.Real);
                return(1);
            }
            return(0);
        }
Ejemplo n.º 5
0
 /// <summary>Gets the real roots of the polynomial.
 /// </summary>
 /// <param name="realRoots">The real-valued roots (output).</param>
 /// <param name="rootFinderApproach">The root finder approach. Some implementations for polynomials with degree up to 3 ignore this parameter because of known analytic solutions.</param>
 /// <param name="imaginaryZeroTolerance">The (positive) tolerance taken into account to indicate whether a complex number is interpreted as real number.</param>
 /// <returns>The number or real roots added to <paramref name="realRoots" />.</returns>
 /// <remarks>
 /// The real roots of the polynomial given by the current instance will be added to <paramref name="realRoots" />. Roots are added with respect to their
 /// multiplicity, i.e. a root may add more than once in <paramref name="realRoots" />.
 /// <para><paramref name="realRoots" /> will <c>not</c> be cleared before adding real roots.</para>
 /// </remarks>
 public int GetRealRoots(IList <double> realRoots, IPolynomialRootFinder rootFinderApproach, double imaginaryZeroTolerance = MachineConsts.Epsilon)
 {
     return(rootFinderApproach.GetRealRoots(m_Degree, m_Coefficients, realRoots, imaginaryZeroTolerance));
 }
Ejemplo n.º 6
0
 /// <summary>Gets the (complex) roots of the polynomial.
 /// </summary>
 /// <param name="roots">The roots (output).</param>
 /// <param name="rootFinderApproach">The root finder approach. Some implementations for polynomials with degree up to 3 ignore this parameter because of known analytic solutions.</param>
 /// <remarks>Each root of the polynomial given by the current instance will be added to <paramref name="roots" />, i.e. <see cref="Degree" /> elements.
 /// <para><paramref name="roots" /> will <c>not</c> be cleared before adding roots.</para>
 /// </remarks>
 public void GetRoots(IList <Complex> roots, IPolynomialRootFinder rootFinderApproach)
 {
     rootFinderApproach.GetRoots(m_Degree, m_Coefficients, roots);
 }
Ejemplo n.º 7
0
 /// <summary>Gets the real roots of the polynomial.
 /// </summary>
 /// <param name="realRoots">The real-valued roots (output).</param>
 /// <param name="rootFinderApproach">The root finder approach. Some implementations for polynomials with degree up to 3 ignore this parameter because of known analytic solutions.</param>
 /// <param name="imaginaryZeroTolerance">The (positive) tolerance taken into account to indicate whether a complex number is interpreted as real number.</param>
 /// <returns>The number or real roots added to <paramref name="realRoots" />.</returns>
 /// <remarks>
 /// The real roots of the polynomial given by the current instance will be added to <paramref name="realRoots" />. Roots are added with respect to their
 /// multiplicity, i.e. a root may add more than once in <paramref name="realRoots" />.
 /// <para><paramref name="realRoots" /> will <c>not</c> be cleared before adding real roots.</para>
 /// </remarks>
 public int GetRealRoots(IList <double> realRoots, IPolynomialRootFinder rootFinderApproach, double imaginaryZeroTolerance = MachineConsts.Epsilon)
 {
     return(0);
 }
Ejemplo n.º 8
0
 /// <summary>Gets the (complex) roots of the polynomial.
 /// </summary>
 /// <param name="roots">The roots (output).</param>
 /// <param name="rootFinderApproach">The root finder approach. Some implementations for polynomials with degree up to 3 ignore this parameter because of known analytic solutions.</param>
 /// <remarks>
 /// Each root of the polynomial given by the current instance will be added to <paramref name="roots" />, i.e. <see cref="Degree" /> elements.
 /// <para><paramref name="roots" /> will <c>not</c> be cleared before adding roots.</para>
 /// </remarks>
 public void GetRoots(IList <Complex> roots, IPolynomialRootFinder rootFinderApproach)
 {
 }
 /// <summary>Gets the real roots of the polynomial.
 /// </summary>
 /// <param name="realRoots">The real-valued roots (output).</param>
 /// <param name="rootFinderApproach">The root finder approach. Some implementations for polynomials with degree up to 3 ignore this parameter because of known analytic solutions.</param>
 /// <param name="imaginaryZeroTolerance">The (positive) tolerance taken into account to indicate whether a complex number is interpreted as real number.</param>
 /// <returns>The number or real roots added to <paramref name="realRoots" />.</returns>
 /// <remarks>
 /// The real roots of the polynomial given by the current instance will be added to <paramref name="realRoots" />. Roots are added with respect to their
 /// multiplicity, i.e. a root may add more than once in <paramref name="realRoots" />.
 /// <para><paramref name="realRoots" /> will <c>not</c> be cleared before adding real roots.</para>
 /// </remarks>
 public int GetRealRoots(IList <double> realRoots, IPolynomialRootFinder rootFinderApproach, double imaginaryZeroTolerance = MachineConsts.Epsilon)
 {
     return(GetRealRoots(m_AbsoluteCoefficient, m_FirstOrderCoefficient, m_SecondOrderCoefficient, m_ThirdOrderCoefficient, m_FourthOrderCoefficient, realRoots, imaginaryZeroTolerance));
 }
Ejemplo n.º 10
0
 /// <summary>Gets the real roots of the polynomial.
 /// </summary>
 /// <param name="realRoots">The real-valued roots (output).</param>
 /// <param name="rootFinderApproach">The root finder approach. Some implementations for polynomials with degree up to 3 ignore this parameter because of known analytic solutions.</param>
 /// <param name="imaginaryZeroTolerance">The (positive) tolerance taken into account to indicate whether a complex number is interpreted as real number.</param>
 /// <returns>The number or real roots added to <paramref name="realRoots" />.</returns>
 /// <remarks>
 /// The real roots of the polynomial given by the current instance will be added to <paramref name="realRoots" />. Roots are added with respect to their
 /// multiplicity, i.e. a root may add more than once in <paramref name="realRoots" />.
 /// <para><paramref name="realRoots" /> will <c>not</c> be cleared before adding real roots.</para>
 /// </remarks>
 public int GetRealRoots(IList <double> realRoots, IPolynomialRootFinder rootFinderApproach, double imaginaryZeroTolerance = MachineConsts.Epsilon)
 {
     realRoots.Add(unchecked (m_AbsoluteCoefficient / m_FirstOrderCoefficient));
     return(1);
 }
Ejemplo n.º 11
0
 /// <summary>Gets the (complex) roots of the polynomial.
 /// </summary>
 /// <param name="roots">The roots (output).</param>
 /// <param name="rootFinderApproach">The root finder approach. Some implementations for polynomials with degree up to 3 ignore this parameter because of known analytic solutions.</param>
 /// <remarks>
 /// Each root of the polynomial given by the current instance will be added to <paramref name="roots" />, i.e. <see cref="Degree" /> elements.
 /// <para><paramref name="roots" /> will <c>not</c> be cleared before adding roots.</para>
 /// </remarks>
 public void GetRoots(IList <Complex> roots, IPolynomialRootFinder rootFinderApproach)
 {
     roots.Add(unchecked (m_AbsoluteCoefficient / m_FirstOrderCoefficient));  // the highest coefficient is always != 0.0, but maybe near 0.0
 }
 /// <summary>Initializes a new instance of the <see cref="LaguerrePolynomialRootFinder"/> class.
 /// </summary>
 public LaguerrePolynomialRootFinder()
 {
     StandardPolishing    = new RootFinder(true);
     StandardNonPolishing = new RootFinder(false);
 }