org.jcurl.math.BisectionSolver.java Source code

Java tutorial

Introduction

Here is the source code for org.jcurl.math.BisectionSolver.java

Source

/*
 * jcurl java curling software framework http://www.jcurl.org Copyright (C)
 * 2005-2009 M. Rohrmoser
 * 
 * This program is free software; you can redistribute it and/or modify it under
 * the terms of the GNU General Public License as published by the Free Software
 * Foundation; either version 2 of the License, or (at your option) any later
 * version.
 * 
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
 * details.
 * 
 * You should have received a copy of the GNU General Public License along with
 * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
 * Place, Suite 330, Boston, MA 02111-1307 USA
 */

package org.jcurl.math;

import org.apache.commons.logging.Log;
import org.jcurl.core.log.JCLoggerFactory;

/**
 * Bisection root-finding algorithm.
 * 
 * @author <a href="mailto:m@jcurl.org">M. Rohrmoser </a>
 * @version $Id$
 */
public class BisectionSolver {
    private static final Log log = JCLoggerFactory.getLogger(BisectionSolver.class);

    /**
     * Bisection root-finding algorithm. Ported from
     * http://en.wikipedia.org/wiki/Bisection_method
     * 
     * @param f
     *            the function to test
     * @param y
     *            y value to find x for. 0 finds the root.
     * @param left
     *            lower end of the interval to scan
     * @param right
     *            upper end of the interval to scan
     * @param epsilon
     *            iteration stops when
     *            <code>Math.abs(right - left) <= epsilon</code>
     */
    public static double findRoot(final R1R1Function f, final double y, double left, double right,
            final double epsilon) {
        double lefty = f.at(left, 0);
        if (Double.isNaN(lefty))
            return Double.NaN;
        // check if left-y an right-y have opposite signs. Use signum to avoid
        // overflows.
        if (Math.signum(lefty) * f.at(right, 0) > 0)
            return Double.NaN;
        double midy = Double.NaN;
        while (Math.abs(right - left) > epsilon) {
            // Calculate midpoint of domain
            final double midpoint = (right + left) / 2;
            midy = f.at(midpoint, 0);
            if (log.isDebugEnabled())
                log.debug("f(" + left + ")=" + lefty + " f(" + midpoint + ")=" + midy + " f(" + right + ")=unused");
            if (Double.isNaN(midy))
                return Double.NaN;
            // examine midy
            if ((lefty - y) * (midy - y) > 0) {
                // Throw away left half
                left = midpoint;
                lefty = midy;
            } else
                // Throw away right half
                right = midpoint;
        }
        return (right + left) / 2;
    }
}