@Test
  public void testConvergenceOnFunctionAccuracy() {
    BracketingNthOrderBrentSolverDFP solver =
        new BracketingNthOrderBrentSolverDFP(
            relativeAccuracy, absoluteAccuracy, field.newDfp(1.0e-20), 20);
    UnivariateDfpFunction f =
        new UnivariateDfpFunction() {
          public Dfp value(Dfp x) {
            Dfp one = field.getOne();
            Dfp oneHalf = one.divide(2);
            Dfp xMo = x.subtract(one);
            Dfp xMh = x.subtract(oneHalf);
            Dfp xPh = x.add(oneHalf);
            Dfp xPo = x.add(one);
            return xMo.multiply(xMh).multiply(x).multiply(xPh).multiply(xPo);
          }
        };

    Dfp result =
        solver.solve(
            20,
            f,
            field.newDfp(0.2),
            field.newDfp(0.9),
            field.newDfp(0.4),
            AllowedSolution.BELOW_SIDE);
    Assert.assertTrue(f.value(result).abs().lessThan(solver.getFunctionValueAccuracy()));
    Assert.assertTrue(f.value(result).negativeOrNull());
    Assert.assertTrue(
        result.subtract(field.newDfp(0.5)).subtract(solver.getAbsoluteAccuracy()).positiveOrNull());
    result =
        solver.solve(
            20,
            f,
            field.newDfp(-0.9),
            field.newDfp(-0.2),
            field.newDfp(-0.4),
            AllowedSolution.ABOVE_SIDE);
    Assert.assertTrue(f.value(result).abs().lessThan(solver.getFunctionValueAccuracy()));
    Assert.assertTrue(f.value(result).positiveOrNull());
    Assert.assertTrue(
        result.add(field.newDfp(0.5)).subtract(solver.getAbsoluteAccuracy()).negativeOrNull());
  }
 private void check(
     UnivariateDfpFunction f,
     int maxEval,
     double min,
     double max,
     AllowedSolution allowedSolution) {
   BracketingNthOrderBrentSolverDFP solver =
       new BracketingNthOrderBrentSolverDFP(
           relativeAccuracy, absoluteAccuracy, functionValueAccuracy, 20);
   Dfp xResult = solver.solve(maxEval, f, field.newDfp(min), field.newDfp(max), allowedSolution);
   Dfp yResult = f.value(xResult);
   switch (allowedSolution) {
     case ANY_SIDE:
       Assert.assertTrue(yResult.abs().lessThan(functionValueAccuracy.multiply(2)));
       break;
     case LEFT_SIDE:
       {
         boolean increasing = f.value(xResult).add(absoluteAccuracy).greaterThan(yResult);
         Assert.assertTrue(increasing ? yResult.negativeOrNull() : yResult.positiveOrNull());
         break;
       }
     case RIGHT_SIDE:
       {
         boolean increasing = f.value(xResult).add(absoluteAccuracy).greaterThan(yResult);
         Assert.assertTrue(increasing ? yResult.positiveOrNull() : yResult.negativeOrNull());
         break;
       }
     case BELOW_SIDE:
       Assert.assertTrue(yResult.negativeOrNull());
       break;
     case ABOVE_SIDE:
       Assert.assertTrue(yResult.positiveOrNull());
       break;
     default:
       // this should never happen
       throw new MathInternalError(null);
   }
 }