QuarticRootFinder { public static ImmutableList<Complex> find(double a, double b, double c, double d, double e) { if (a == 0) { return CubicRootFinder.find(b, c, d, e); } b = b / a; c = c / a; d = d / a; e = e / a; Complex yToXAdjustment = new Complex(-b / 4, 0); double p = c - 3 * Math.pow(b, 2) / 8; double q = d + (Math.pow(b, 3) / 8) - (b * c / 2); double r = e - (3 * Math.pow(b, 4) / 256) + (Math.pow(b, 2) * c / 16) - (b * d / 4); if (p == 0 && q == 0 && r == 0) { return ImmutableList.of(yToXAdjustment, yToXAdjustment, yToXAdjustment, yToXAdjustment); } ImmutableList<Complex> rootsOfCubic = CubicRootFinder.find(1, p, (Math.pow(p, 2) / 4) - r, -Math.pow(q, 2) / 8); Complex m = rootsOfCubic.stream() .filter(complex -> Math.abs(complex.getImaginary()) > EPSILON || Math.abs(complex.getReal()) > EPSILON) .findFirst() .orElseThrow(() -> new IllegalStateException("No non-zero solution for m found")); Complex yRoot1 = calculateRoot(p, q, m, true, true); Complex yRoot2 = calculateRoot(p, q, m, true, false); Complex yRoot3 = calculateRoot(p, q, m, false, true); Complex yRoot4 = calculateRoot(p, q, m, false, false); return ImmutableList.of( yRoot1.add(yToXAdjustment), yRoot2.add(yToXAdjustment), yRoot3.add(yToXAdjustment), yRoot4.add(yToXAdjustment)); } private  QuarticRootFinder(); static ImmutableList<Complex> find(double a, double b, double c, double d, double e);  }
@Test void find_whenGivenQuadraticEquation_thenReturnsCorrectRoots() { ImmutableList<Complex> roots = QuarticRootFinder.find(0, 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 = QuarticRootFinder.find(0, 0, 0, 2, 1); ImmutableList<Pair<Double, Double>> expectedRoots = ImmutableList.of( Pair.of(-0.5, 0.0) ); assertEquals(expectedRoots, roots); }
@Test void find_whenQuarticHasFourRealRoots_thenReturnsCorrectRoots() { ImmutableList<Complex> roots = QuarticRootFinder.find(3, 6, -123, -126, 1080); ImmutableList<Pair<Double, Double>> expectedRoots = ImmutableList.of( Pair.of(5.0, 0.0), Pair.of(3.0, 0.0), Pair.of(-4.0, 0.0), Pair.of(-6.0, 0.0) ); assertEquals(expectedRoots, roots); }
@Test void find_whenTrivialQuarticGiven_thenReturnsCorrectRoots() { ImmutableList<Complex> roots = QuarticRootFinder.find(1, 0, 0, 0, 0); ImmutableList<Pair<Double, Double>> expectedRoots = ImmutableList.of( Pair.of(0.0, 0.0), Pair.of(0.0, 0.0), Pair.of(0.0, 0.0), Pair.of(0.0, 0.0) ); assertEquals(expectedRoots, roots); }
@Test void find_whenQuarticHasFourEqualRealRoots_thenReturnsCorrectRoots() { ImmutableList<Complex> roots = QuarticRootFinder.find(1, -4, 6, -4, 1); ImmutableList<Pair<Double, Double>> expectedRoots = ImmutableList.of( Pair.of(1.0, 0.0), Pair.of(1.0, 0.0), Pair.of(1.0, 0.0), Pair.of(1.0, 0.0) ); assertEquals(expectedRoots, roots); }
@Test void find_whenQuarticHasTwoPairsOfEqualRealRoots_thenReturnsCorrectRoots() { ImmutableList<Complex> roots = QuarticRootFinder.find(1, 0, -2, 0, 1); ImmutableList<Pair<Double, Double>> expectedRoots = ImmutableList.of( Pair.of(1.0, 0.0), Pair.of(1.0, 0.0), Pair.of(-1.0, 0.0), Pair.of(-1.0, 0.0) ); assertEquals(expectedRoots, roots); }
@Test void find_whenQuarticHasTwoComplexAndTwoRealRoots_thenReturnsCorrectRoots() { ImmutableList<Complex> roots = QuarticRootFinder.find(-20, 5, 17, -29, 87); ImmutableList<Pair<Double, Double>> expectedRoots = ImmutableList.of( Pair.of(1.4876, 0.0), Pair.of(0.2222, 1.2996), Pair.of(0.2222, -1.2996), Pair.of(-1.6820, 0.0) ); assertEquals(expectedRoots, roots); }
@Test void find_whenQuarticHasFourComplexRoots_thenReturnsCorrectRoots() { ImmutableList<Complex> roots = QuarticRootFinder.find(1, 1, 3, -1, 12); ImmutableList<Pair<Double, Double>> expectedRoots = ImmutableList.of( Pair.of(-1.3122, 1.7320), Pair.of(0.8122, 1.3717), Pair.of(0.8122, -1.3717), Pair.of(-1.3122, -1.7320) ); assertEquals(expectedRoots, roots); }
@Test void find_whenGivenCubicEquation_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); }