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