001    /*
002     * Licensed to the Apache Software Foundation (ASF) under one or more
003     * contributor license agreements.  See the NOTICE file distributed with
004     * this work for additional information regarding copyright ownership.
005     * The ASF licenses this file to You under the Apache License, Version 2.0
006     * (the "License"); you may not use this file except in compliance with
007     * the License.  You may obtain a copy of the License at
008     *
009     *      http://www.apache.org/licenses/LICENSE-2.0
010     *
011     * Unless required by applicable law or agreed to in writing, software
012     * distributed under the License is distributed on an "AS IS" BASIS,
013     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     * See the License for the specific language governing permissions and
015     * limitations under the License.
016     */
017    package org.apache.commons.math.analysis.integration;
018    
019    import org.apache.commons.math.ConvergingAlgorithmImpl;
020    import org.apache.commons.math.MathRuntimeException;
021    import org.apache.commons.math.analysis.UnivariateRealFunction;
022    import org.apache.commons.math.exception.util.LocalizedFormats;
023    import org.apache.commons.math.exception.NullArgumentException;
024    
025    /**
026     * Provide a default implementation for several generic functions.
027     *
028     * @version $Revision: 1072409 $ $Date: 2011-02-19 19:50:36 +0100 (sam. 19 f??vr. 2011) $
029     * @since 1.2
030     */
031    public abstract class UnivariateRealIntegratorImpl
032        extends ConvergingAlgorithmImpl implements UnivariateRealIntegrator {
033    
034        /** Serializable version identifier. */
035        private static final long serialVersionUID = 6248808456637441533L;
036    
037        /** minimum number of iterations */
038        protected int minimalIterationCount;
039    
040        /** default minimum number of iterations */
041        protected int defaultMinimalIterationCount;
042    
043        /** indicates whether an integral has been computed */
044        protected boolean resultComputed = false;
045    
046        /** the last computed integral */
047        protected double result;
048    
049        /**
050         * The integrand function.
051         *
052         * @deprecated as of 2.0 the integrand function is passed as an argument
053         * to the {@link #integrate(UnivariateRealFunction, double, double)}method.
054         */
055        @Deprecated
056        protected UnivariateRealFunction f;
057    
058        /**
059         * Construct an integrator with given iteration count and accuracy.
060         *
061         * @param f the integrand function
062         * @param defaultMaximalIterationCount maximum number of iterations
063         * @throws IllegalArgumentException if f is null or the iteration
064         * limits are not valid
065         * @deprecated as of 2.0 the integrand function is passed as an argument
066         * to the {@link #integrate(UnivariateRealFunction, double, double)}method.
067         */
068        @Deprecated
069        protected UnivariateRealIntegratorImpl(final UnivariateRealFunction f,
070                                               final int defaultMaximalIterationCount)
071            throws IllegalArgumentException {
072            super(defaultMaximalIterationCount, 1.0e-15);
073            if (f == null) {
074                throw new NullArgumentException(LocalizedFormats.FUNCTION);
075            }
076    
077            this.f = f;
078    
079            // parameters that are problem specific
080            setRelativeAccuracy(1.0e-6);
081            this.defaultMinimalIterationCount = 3;
082            this.minimalIterationCount = defaultMinimalIterationCount;
083    
084            verifyIterationCount();
085        }
086    
087        /**
088         * Construct an integrator with given iteration count and accuracy.
089         *
090         * @param defaultMaximalIterationCount maximum number of iterations
091         * @throws IllegalArgumentException if f is null or the iteration
092         * limits are not valid
093         */
094        protected UnivariateRealIntegratorImpl(final int defaultMaximalIterationCount)
095            throws IllegalArgumentException {
096            super(defaultMaximalIterationCount, 1.0e-15);
097    
098            // parameters that are problem specific
099            setRelativeAccuracy(1.0e-6);
100            this.defaultMinimalIterationCount = 3;
101            this.minimalIterationCount = defaultMinimalIterationCount;
102    
103            verifyIterationCount();
104        }
105    
106        /**
107         * Access the last computed integral.
108         *
109         * @return the last computed integral
110         * @throws IllegalStateException if no integral has been computed
111         */
112        public double getResult() throws IllegalStateException {
113            if (resultComputed) {
114                return result;
115            } else {
116                throw MathRuntimeException.createIllegalStateException(LocalizedFormats.NO_RESULT_AVAILABLE);
117            }
118        }
119    
120        /**
121         * Convenience function for implementations.
122         *
123         * @param newResult the result to set
124         * @param iterationCount the iteration count to set
125         */
126        protected final void setResult(double newResult, int iterationCount) {
127            this.result         = newResult;
128            this.iterationCount = iterationCount;
129            this.resultComputed = true;
130        }
131    
132        /**
133         * Convenience function for implementations.
134         */
135        protected final void clearResult() {
136            this.iterationCount = 0;
137            this.resultComputed = false;
138        }
139    
140        /** {@inheritDoc} */
141        public void setMinimalIterationCount(int count) {
142            minimalIterationCount = count;
143        }
144    
145        /** {@inheritDoc} */
146        public int getMinimalIterationCount() {
147            return minimalIterationCount;
148        }
149    
150        /** {@inheritDoc} */
151        public void resetMinimalIterationCount() {
152            minimalIterationCount = defaultMinimalIterationCount;
153        }
154    
155        /**
156         * Verifies that the endpoints specify an interval.
157         *
158         * @param lower lower endpoint
159         * @param upper upper endpoint
160         * @throws IllegalArgumentException if not interval
161         */
162        protected void verifyInterval(double lower, double upper) throws
163            IllegalArgumentException {
164            if (lower >= upper) {
165                throw MathRuntimeException.createIllegalArgumentException(
166                        LocalizedFormats.ENDPOINTS_NOT_AN_INTERVAL,
167                        lower, upper);
168            }
169        }
170    
171        /**
172         * Verifies that the upper and lower limits of iterations are valid.
173         *
174         * @throws IllegalArgumentException if not valid
175         */
176        protected void verifyIterationCount() throws IllegalArgumentException {
177            if ((minimalIterationCount <= 0) || (maximalIterationCount <= minimalIterationCount)) {
178                throw MathRuntimeException.createIllegalArgumentException(
179                        LocalizedFormats.INVALID_ITERATIONS_LIMITS,
180                        minimalIterationCount, maximalIterationCount);
181            }
182        }
183    }