001/*
002*   BracketRoot1D  -- A bracket around a root in a 1D function.
003*
004*   Copyright (C) 2010-2025, by Joseph A. Huwaldt. All rights reserved.
005*   
006*   This library is free software; you can redistribute it and/or
007*   modify it under the terms of the GNU Lesser General Public
008*   License as published by the Free Software Foundation; either
009*   version 2.1 of the License, or (at your option) any later version.
010*   
011*   This library is distributed in the hope that it will be useful,
012*   but WITHOUT ANY WARRANTY; without even the implied warranty of
013*   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
014*   Lesser General Public License for more details.
015*
016*   You should have received a copy of the GNU Lesser General Public License
017*   along with this program; if not, write to the Free Software
018*   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
019*   Or visit:  http://www.gnu.org/licenses/lgpl.html
020**/
021package jahuwaldt.tools.math;
022
023import java.util.List;
024import java.util.ArrayList;
025
026
027/**
028*  Represents the bracket around a root in a 1D function.
029*
030*  <p>  Modified by:  Joseph A. Huwaldt  </p>
031*
032*  @author   Joseph A. Huwaldt   Date:  October 8, 1997
033*  @version  February 18, 2025
034**/
035public class BracketRoot1D implements Comparable<BracketRoot1D> {
036        
037        /**
038        *  The lower bound of the bracket.
039        **/
040        public double x1 = 0;
041        
042        /**
043        *  The upper bound of the bracket.
044        **/
045        public double x2 = 0;
046        
047        
048        //-----------------------------------------------------------------------------------
049        /**
050        *  Construct a bracket around a root in a 1D function.
051        *
052        *  @param x1    The lower bound of the bracket.
053        *  @param x2    The upper bound of the bracket.
054        **/
055        public BracketRoot1D(double x1, double x2) {
056                if (x1 < x2) {
057                        this.x1 = x1;
058                        this.x2 = x2;
059                } else {
060                        this.x2 = x1;
061                        this.x1 = x2;
062                }
063        }
064        
065        /**
066        *  Given a function, <code>func</code>, defined on the interval <code>x1</code> to <code>x2</code>,
067        *  this routine subdivides the interval into <code>n</code> equally spaced segments,
068        *  and searches for zero crossings of the function.  Brackets around any zero crossings found
069        *  are returned.
070        *
071        *  @param func  The function that is being search for zero crossings.
072        *  @param x1    The start of the interval to be searched.
073        *  @param x2    The end of the interval to be searched.
074        *  @param n     The number segments to divide the interval into.
075        *  @return A list containing the brackets that were found.  Could be an empty list if no brackets are found.
076        *  @throws RootException if the Evaluatable1D throws a exception.
077        **/
078        public static List<BracketRoot1D> findBrackets(Evaluatable1D func, double x1, double x2, int n)  throws RootException {
079                List<BracketRoot1D> list = new ArrayList();
080                
081                //      Make sure that x2 is > x1.
082                if (x1 > x2) {
083                        double temp = x1;
084                        x1 = x2;
085                        x2 = temp;
086                }
087                
088                double dx = (x2 - x1)/n;
089                if (MathTools.isApproxZero(dx)) return list;
090                
091                double x = x1;
092                double fp = func.function(x);
093                for (int i=0; i < n; ++i) {
094                        x += dx;
095                        if (x > x2)     x = x2;
096                        double fc = func.function(x);
097                        if (fc*fp <= 0.0) {
098                                list.add(new BracketRoot1D(x - dx, x));
099                        }
100                        fp = fc;
101                }
102                
103                return list;
104        }
105        
106        
107        /**
108        *  Compares this object with the specified object for order.
109        *  Returns a negative integer, zero, or a positive integer as
110        *  this object is less than, equal to, or greater than the specified object.
111        *  This implementation compares the start of the bracket (x1) only.
112        **/
113    @Override
114        public int compareTo(BracketRoot1D o) {
115                return (this.x1 < o.x1 ? -1 : (this.x1 > o.x1 ? 1 : 0));
116        }
117        
118        /**
119        *  Return a String representation of this object.
120        **/
121    @Override
122        public String toString() {
123                StringBuilder buffer = new StringBuilder();
124                buffer.append('{');
125                buffer.append(x1);
126                buffer.append(",");
127                buffer.append(x2);
128                buffer.append('}');
129                return buffer.toString();
130        }
131        
132}