From "Elementary Analytical Methods":
Given z^4 + a3z^3 + a2z^2 + a1z + a0 = 0, find the real root u1 of the cubic equation:
u^3 -a2u^2 + (a1a3 - 4a0)u - (a1^2 + a0a3^2 - 4aoa2) = 0
and determine the four roots of the quartic as solutions of the two quadratic equations
v^2 + [a3/2 +-(a3^2/4 + u1 - a2)^(1/2)]v + u1/2+-[(u1/2)^2-a0]^(1/2) = 0
If all roots of the cubic equation are real, use the value of u1 which gives real cooefficients in the *quadratic equation and select signs so that if
z^4 + a3z^3 + a2z^2 + a1z + a0 = (z^2 + p1z+ q1)(z^2 + p2z + q2)
then
p1 + p2 = a3, p1p2 + q1 + q2 = a2, p1q2 + p2q1 = a1, q1q2 = a0.
We begin by normalizing the polynomial.
cubicRoots: ARRAY [1..3] OF REAL;
cubicRootCount: NAT;
a3Over2, a3a3Over4, u1, u1Over2: REAL;
quadRoots1, quadRoots2: ARRAY [1..2] OF REAL;
quadRootCount1, quadRootCount2: NAT;
term1, term2: REAL;
IF a4 = 0 THEN {
[cubicRoots, cubicRootCount] ← CubicFormula [a3, a2, a1, a0];
FOR i:
NAT
IN [1..cubicRootCount]
DO
roots[i-1] ← cubicRoots[i];
ENDLOOP;
rootCount ← cubicRootCount;
RETURN};
a3 ← a3/a4; a2 ← a2/a4; a1 ← a1/a4; a0 ← a0/a4;
We continue by finding the roots of the cubic equation:
a3Over2 ← a3/2;
a3a3Over4 ← a3Over2*a3Over2;
[cubicRoots, cubicRootCount] ← CubicFormula[1, -a2, (a1*a3 - 4*a0), -(a1*a1 + a0*a3*a3 - 4*a0*a2)];
SELECT cubicRootCount FROM
1 => u1 ← cubicRoots[1];
2 => ERROR;
3 => {-- the hard case
Of the three roots, choose the first one which satifies both:
u1 >= a2-a3^2/4
(u1/2)^2 >= a0
a2Minusa3a3Over4: REAL ← a2 - a3a3Over4;
SELECT TRUE FROM
cubicRoots[1] >= a3a3Over4 AND cubicRoots[1]*cubicRoots[1]/4 >= a0 =>
u1 ← cubicRoots[1];
cubicRoots[2] >= a3a3Over4 AND cubicRoots[2]*cubicRoots[2]/4 >= a0 =>
u1 ← cubicRoots[2];
cubicRoots[3] >= a3a3Over4 AND cubicRoots[3]*cubicRoots[3]/4 >= a0 =>
u1 ← cubicRoots[3];
ENDCASE => ERROR;
};
ENDCASE => ERROR;
Finally we solve the two quadratic equations:
u1Over2 ← u1/2.0;
term1 ← RealFns.SqRt[a3a3Over4+u1-a2];
term2 ← RealFns.SqRt[u1Over2*u1Over2-a0];
[quadRoots1, quadRootCount1] ←
QuadraticFormula[1, a3Over2 + term1, u1Over2 + term2];
[quadRoots2, quadRootCount2] ←
QuadraticFormula[1, a3Over2 - term1, u1Over2 - term2];
rootCount ← 0;
IF quadRootCount1>0 THEN {roots[rootCount] ← quadRoots1[1];
rootCount ← rootCount + 1};
IF quadRootCount1>1 THEN {roots[rootCount] ← quadRoots1[2];
rootCount ← rootCount + 1};
IF quadRootCount2>0 THEN {roots[rootCount] ← quadRoots2[1];
rootCount ← rootCount + 1};
IF quadRootCount2>1 THEN {roots[rootCount] ← quadRoots2[2];
rootCount ← rootCount + 1};
}; -- end of Quartic Formula