blob: ff0290c71430d4e601cdfcfafedae049eefe6559 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.math4.legacy.analysis.solvers;
import org.apache.commons.math4.legacy.exception.TooManyEvaluationsException;
import org.apache.commons.math4.legacy.core.jdkmath.AccurateMath;
/**
* Implements the <a href="http://mathworld.wolfram.com/Bisection.html">
* bisection algorithm</a> for finding zeros of univariate real functions.
* <p>
* The function should be continuous but not necessarily smooth.</p>
*
*/
public class BisectionSolver extends AbstractUnivariateSolver {
/** Default absolute accuracy. */
private static final double DEFAULT_ABSOLUTE_ACCURACY = 1e-6;
/**
* Construct a solver with default accuracy (1e-6).
*/
public BisectionSolver() {
this(DEFAULT_ABSOLUTE_ACCURACY);
}
/**
* Construct a solver.
*
* @param absoluteAccuracy Absolute accuracy.
*/
public BisectionSolver(double absoluteAccuracy) {
super(absoluteAccuracy);
}
/**
* Construct a solver.
*
* @param relativeAccuracy Relative accuracy.
* @param absoluteAccuracy Absolute accuracy.
*/
public BisectionSolver(double relativeAccuracy,
double absoluteAccuracy) {
super(relativeAccuracy, absoluteAccuracy);
}
/**
* {@inheritDoc}
*/
@Override
protected double doSolve()
throws TooManyEvaluationsException {
double min = getMin();
double max = getMax();
verifyInterval(min, max);
final double absoluteAccuracy = getAbsoluteAccuracy();
double m;
double fm;
double fmin;
while (true) {
m = UnivariateSolverUtils.midpoint(min, max);
fmin = computeObjectiveValue(min);
fm = computeObjectiveValue(m);
if (fm * fmin > 0) {
// max and m bracket the root.
min = m;
} else {
// min and m bracket the root.
max = m;
}
if (AccurateMath.abs(max - min) <= absoluteAccuracy) {
m = UnivariateSolverUtils.midpoint(min, max);
return m;
}
}
}
}