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    
023    /**
024     * Provide a default implementation for several generic functions.
025     *
026     * @version $Revision: 811685 $ $Date: 2009-09-05 13:36:48 -0400 (Sat, 05 Sep 2009) $
027     * @since 1.2
028     */
029    public abstract class UnivariateRealIntegratorImpl
030        extends ConvergingAlgorithmImpl implements UnivariateRealIntegrator {
031    
032        /** Serializable version identifier. */
033        private static final long serialVersionUID = 6248808456637441533L;
034    
035        /** minimum number of iterations */
036        protected int minimalIterationCount;
037    
038        /** default minimum number of iterations */
039        protected int defaultMinimalIterationCount;
040    
041        /** indicates whether an integral has been computed */
042        protected boolean resultComputed = false;
043    
044        /** the last computed integral */
045        protected double result;
046    
047        /** The integrand functione.
048         * @deprecated as of 2.0 the integrand function is passed as an argument
049         * to the {@link #integrate(UnivariateRealFunction, double, double)}method. */
050        @Deprecated
051        protected UnivariateRealFunction f;
052    
053        /**
054         * Construct an integrator with given iteration count and accuracy.
055         *
056         * @param f the integrand function
057         * @param defaultMaximalIterationCount maximum number of iterations
058         * @throws IllegalArgumentException if f is null or the iteration
059         * limits are not valid
060         * @deprecated as of 2.0 the integrand function is passed as an argument
061         * to the {@link #integrate(UnivariateRealFunction, double, double)}method.
062         */
063        @Deprecated
064        protected UnivariateRealIntegratorImpl(final UnivariateRealFunction f,
065                                               final int defaultMaximalIterationCount)
066            throws IllegalArgumentException {
067            super(defaultMaximalIterationCount, 1.0e-15);
068            if (f == null) {
069                throw MathRuntimeException.createIllegalArgumentException("function is null");
070            }
071    
072            this.f = f;
073    
074            // parameters that are problem specific
075            setRelativeAccuracy(1.0e-6);
076            this.defaultMinimalIterationCount = 3;
077            this.minimalIterationCount = defaultMinimalIterationCount;
078    
079            verifyIterationCount();
080        }
081    
082        /**
083         * Construct an integrator with given iteration count and accuracy.
084         *
085         * @param defaultMaximalIterationCount maximum number of iterations
086         * @throws IllegalArgumentException if f is null or the iteration
087         * limits are not valid
088         */
089        protected UnivariateRealIntegratorImpl(final int defaultMaximalIterationCount)
090            throws IllegalArgumentException {
091            super(defaultMaximalIterationCount, 1.0e-15);
092    
093            // parameters that are problem specific
094            setRelativeAccuracy(1.0e-6);
095            this.defaultMinimalIterationCount = 3;
096            this.minimalIterationCount = defaultMinimalIterationCount;
097    
098            verifyIterationCount();
099        }
100    
101        /**
102         * Access the last computed integral.
103         *
104         * @return the last computed integral
105         * @throws IllegalStateException if no integral has been computed
106         */
107        public double getResult() throws IllegalStateException {
108            if (resultComputed) {
109                return result;
110            } else {
111                throw MathRuntimeException.createIllegalStateException("no result available");
112            }
113        }
114    
115        /**
116         * Convenience function for implementations.
117         *
118         * @param newResult the result to set
119         * @param iterationCount the iteration count to set
120         */
121        protected final void setResult(double newResult, int iterationCount) {
122            this.result         = newResult;
123            this.iterationCount = iterationCount;
124            this.resultComputed = true;
125        }
126    
127        /**
128         * Convenience function for implementations.
129         */
130        protected final void clearResult() {
131            this.iterationCount = 0;
132            this.resultComputed = false;
133        }
134    
135        /** {@inheritDoc} */
136        public void setMinimalIterationCount(int count) {
137            minimalIterationCount = count;
138        }
139    
140        /** {@inheritDoc} */
141        public int getMinimalIterationCount() {
142            return minimalIterationCount;
143        }
144    
145        /** {@inheritDoc} */
146        public void resetMinimalIterationCount() {
147            minimalIterationCount = defaultMinimalIterationCount;
148        }
149    
150        /**
151         * Verifies that the endpoints specify an interval.
152         *
153         * @param lower lower endpoint
154         * @param upper upper endpoint
155         * @throws IllegalArgumentException if not interval
156         */
157        protected void verifyInterval(double lower, double upper) throws
158            IllegalArgumentException {
159            if (lower >= upper) {
160                throw MathRuntimeException.createIllegalArgumentException(
161                        "endpoints do not specify an interval: [{0}, {1}]",
162                        lower, upper);
163            }
164        }
165    
166        /**
167         * Verifies that the upper and lower limits of iterations are valid.
168         *
169         * @throws IllegalArgumentException if not valid
170         */
171        protected void verifyIterationCount() throws IllegalArgumentException {
172            if ((minimalIterationCount <= 0) || (maximalIterationCount <= minimalIterationCount)) {
173                throw MathRuntimeException.createIllegalArgumentException(
174                        "invalid iteration limits: min={0}, max={1}",
175                        minimalIterationCount, maximalIterationCount);
176            }
177        }
178    }