} catch (EventException e) {
throw new EmbeddedEventException(e);
}
}
};
final BrentSolver solver = new BrentSolver(convergence);
if (ga * gb >= 0) {
// this is a corner case:
// - there was an event near ta,
// - there is another event between ta and tb
// - when ta was computed, convergence was reached on the "wrong side" of the interval
// this implies that the real sign of ga is the same as gb, so we need to slightly
// shift ta to make sure ga and gb get opposite signs and the solver won't complain
// about bracketing
final double epsilon = (forward ? 0.25 : -0.25) * convergence;
for (int k = 0; (k < 4) && (ga * gb > 0); ++k) {
ta += epsilon;
try {
ga = f.value(ta);
} catch (FunctionEvaluationException ex) {
throw new DerivativeException(ex);
}
}
if (ga * gb > 0) {
// this should never happen
throw new MathInternalError();
}
}
final double root;
try {
root = (ta <= tb) ?
solver.solve(maxIterationCount, f, ta, tb) :
solver.solve(maxIterationCount, f, tb, ta);
} catch (FunctionEvaluationException ex) {
throw new DerivativeException(ex);
}
if ((!Double.isNaN(previousEventTime)) &&