CubicRootFinder { public static ImmutableList<Complex> find(double a, double b, double c, double d) { if (a == 0) { return QuadraticRootFinder.find(b, c, d); } ImmutableList.Builder<Complex> builder = ImmutableList.builder(); double f = ((3 * c / a) - (Math.pow(b, 2) / Math.pow(a, 2))) / 3d; double g = ((2 * Math.pow(b, 3))/ Math.pow(a, 3) - (9 * b * c) / Math.pow(a, 2) + (27 * d / a)) / 27; double h = (Math.pow(g, 2)/4) + (Math.pow(f, 3)/27); if ( h > 0 ) { double R = -(g/2) + Math.sqrt(h); double S = Math.cbrt(R); double T = -(g/2) - Math.sqrt(h); double U = Math.cbrt(T); Complex root1 = new Complex(S + U - (b / (3 * a)), 0d); Complex root2 = new Complex(-(S + U)/2 - (b / (3 * a)), ((S-U) * Math.sqrt(3))/2d); Complex root3 = new Complex(-(S + U)/2 - (b / (3 * a)), - ((S - U) * Math.sqrt(3))/2d); return builder.add(root1).add(root2).add(root3).build(); } if (f == 0 && g == 0 && h == 0) { Complex root = new Complex(-Math.cbrt(d/a), 0d); return builder.add(root).add(root).add(root).build(); } double i = Math.sqrt(((Math.pow(g, 2)/4) - h)); double j = Math.cbrt(i); double k = Math.acos(- (g / (2 * i))); double l = - j; double m = Math.cos(k /3); double n = Math.sqrt(3) * Math.sin(k / 3); double p = -(b / (3 * a)); double rootOne = 2 * j * Math.cos(k/3) - (b/ (3 *a)); double rootTwo = l * (m + n) + p; double rootThree = l * (m - n) + p; return builder.add(new Complex(rootOne, 0d)).add(new Complex(rootTwo, 0d)).add(new Complex(rootThree, 0d)).build(); } private  CubicRootFinder(); static ImmutableList<Complex> find(double a, double b, double c, double d);  }
@Test void find_whenAllThreeRootsAreReal_thenReturnsCorrectRoots() { ImmutableList<Complex> roots = CubicRootFinder.find(2, -4, -22, 24); ImmutableList<Pair<Double, Double>> expectedRoots = ImmutableList.of( Pair.of(4.0, 0.0), Pair.of(1.0, 0.0), Pair.of(-3.0, 0.0) ); assertEquals(expectedRoots, roots); }
@Test void find_whenAllRootsAreRealAndEqual_thenReturnsCorrectRoots() { ImmutableList<Complex> roots = CubicRootFinder.find(1, 6, 12, 8); ImmutableList<Pair<Double, Double>> expectedRoots = ImmutableList.of( Pair.of(-2.0, 0.0), Pair.of(-2.0, 0.0), Pair.of(-2.0, 0.0) ); assertEquals(expectedRoots, roots); }
@Test void find_whenOnlyOneRootIsReal_thenReturnsCorrectRoots() { ImmutableList<Complex> roots = CubicRootFinder.find(3, -10, 14, 27); ImmutableList<Pair<Double, Double>> expectedRoots = ImmutableList.of( Pair.of(-1.0, 0.0), Pair.of(2.1667, 2.075), Pair.of(2.1667, -2.075) ); assertEquals(expectedRoots, roots); }
@Test void find_whenGivenQuadraticEquation_thenReturnsCorrectRoots() { ImmutableList<Complex> roots = CubicRootFinder.find(0, 1, 2, 1); ImmutableList<Pair<Double, Double>> expectedRoots = ImmutableList.of( Pair.of(-1.0, 0.0), Pair.of(-1.0, 0.0) ); assertEquals(expectedRoots, roots); }
@Test void find_whenGivenLinearEquation_thenReturnsCorrectRoot() { ImmutableList<Complex> roots = CubicRootFinder.find(0, 0, 2, 1); ImmutableList<Pair<Double, Double>> expectedRoots = ImmutableList.of( Pair.of(-0.5, 0.0) ); assertEquals(expectedRoots, roots); }