1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17 package org.apache.commons.math.analysis;
18
19 import java.io.Serializable;
20
21 /**
22 * Provide a default implementation for several generic functions.
23 *
24 * @version $Revision: 620312 $ $Date: 2008-02-10 12:28:59 -0700 (Sun, 10 Feb 2008) $
25 * @since 1.2
26 */
27 public abstract class UnivariateRealIntegratorImpl implements
28 UnivariateRealIntegrator, Serializable {
29
30 /** serializable version identifier */
31 static final long serialVersionUID = -3365294665201465048L;
32
33 /** maximum relative error */
34 protected double relativeAccuracy;
35
36 /** maximum number of iterations */
37 protected int maximalIterationCount;
38
39 /** minimum number of iterations */
40 protected int minimalIterationCount;
41
42 /** default maximum relative error */
43 protected double defaultRelativeAccuracy;
44
45 /** default maximum number of iterations */
46 protected int defaultMaximalIterationCount;
47
48 /** default minimum number of iterations */
49 protected int defaultMinimalIterationCount;
50
51 /** indicates whether an integral has been computed */
52 protected boolean resultComputed = false;
53
54 /** the last computed integral */
55 protected double result;
56
57 /** the last iteration count */
58 protected int iterationCount;
59
60 /** the integrand function */
61 protected UnivariateRealFunction f;
62
63 /**
64 * Construct an integrator with given iteration count and accuracy.
65 *
66 * @param f the integrand function
67 * @param defaultMaximalIterationCount maximum number of iterations
68 * @throws IllegalArgumentException if f is null or the iteration
69 * limits are not valid
70 */
71 protected UnivariateRealIntegratorImpl(
72 UnivariateRealFunction f,
73 int defaultMaximalIterationCount) throws IllegalArgumentException {
74
75 if (f == null) {
76 throw new IllegalArgumentException("Function can not be null.");
77 }
78
79 this.f = f;
80 // parameters that may depend on algorithm
81 this.defaultMaximalIterationCount = defaultMaximalIterationCount;
82 this.maximalIterationCount = defaultMaximalIterationCount;
83 // parameters that are problem specific
84 this.defaultRelativeAccuracy = 1E-6;
85 this.relativeAccuracy = defaultRelativeAccuracy;
86 this.defaultMinimalIterationCount = 3;
87 this.minimalIterationCount = defaultMinimalIterationCount;
88
89 verifyIterationCount();
90 }
91
92 /**
93 * Access the last computed integral.
94 *
95 * @return the last computed integral
96 * @throws IllegalStateException if no integral has been computed
97 */
98 public double getResult() throws IllegalStateException {
99 if (resultComputed) {
100 return result;
101 } else {
102 throw new IllegalStateException("No result available.");
103 }
104 }
105
106 /**
107 * Access the last iteration count.
108 *
109 * @return the last iteration count
110 * @throws IllegalStateException if no integral has been computed
111 */
112 public int getIterationCount() throws IllegalStateException {
113 if (resultComputed) {
114 return iterationCount;
115 } else {
116 throw new IllegalStateException("No result available.");
117 }
118 }
119
120 /**
121 * Convenience function for implementations.
122 *
123 * @param result the result to set
124 * @param iterationCount the iteration count to set
125 */
126 protected final void setResult(double result, int iterationCount) {
127 this.result = result;
128 this.iterationCount = iterationCount;
129 this.resultComputed = true;
130 }
131
132 /**
133 * Convenience function for implementations.
134 */
135 protected final void clearResult() {
136 this.resultComputed = false;
137 }
138
139 /**
140 * Set the upper limit for the number of iterations.
141 *
142 * @param count maximum number of iterations
143 */
144 public void setMaximalIterationCount(int count) {
145 maximalIterationCount = count;
146 }
147
148 /**
149 * Get the upper limit for the number of iterations.
150 *
151 * @return the actual upper limit
152 */
153 public int getMaximalIterationCount() {
154 return maximalIterationCount;
155 }
156
157 /**
158 * Reset the upper limit for the number of iterations to the default.
159 */
160 public void resetMaximalIterationCount() {
161 maximalIterationCount = defaultMaximalIterationCount;
162 }
163
164 /**
165 * Set the lower limit for the number of iterations.
166 *
167 * @param count minimum number of iterations
168 */
169 public void setMinimalIterationCount(int count) {
170 minimalIterationCount = count;
171 }
172
173 /**
174 * Get the lower limit for the number of iterations.
175 *
176 * @return the actual lower limit
177 */
178 public int getMinimalIterationCount() {
179 return minimalIterationCount;
180 }
181
182 /**
183 * Reset the lower limit for the number of iterations to the default.
184 */
185 public void resetMinimalIterationCount() {
186 minimalIterationCount = defaultMinimalIterationCount;
187 }
188
189 /**
190 * Set the relative accuracy.
191 *
192 * @param accuracy the relative accuracy
193 * @throws IllegalArgumentException if the accuracy can't be achieved by
194 * the integrator or is otherwise deemed unreasonable
195 */
196 public void setRelativeAccuracy(double accuracy) {
197 relativeAccuracy = accuracy;
198 }
199
200 /**
201 * Get the actual relative accuracy.
202 *
203 * @return the accuracy
204 */
205 public double getRelativeAccuracy() {
206 return relativeAccuracy;
207 }
208
209 /**
210 * Reset the relative accuracy to the default.
211 */
212 public void resetRelativeAccuracy() {
213 relativeAccuracy = defaultRelativeAccuracy;
214 }
215
216 /**
217 * Returns true if the arguments form a (strictly) increasing sequence
218 *
219 * @param start first number
220 * @param mid second number
221 * @param end third number
222 * @return true if the arguments form an increasing sequence
223 */
224 protected boolean isSequence(double start, double mid, double end) {
225 return (start < mid) && (mid < end);
226 }
227
228 /**
229 * Verifies that the endpoints specify an interval.
230 *
231 * @param lower lower endpoint
232 * @param upper upper endpoint
233 * @throws IllegalArgumentException if not interval
234 */
235 protected void verifyInterval(double lower, double upper) throws
236 IllegalArgumentException {
237 if (lower >= upper) {
238 throw new IllegalArgumentException
239 ("Endpoints do not specify an interval: [" + lower +
240 ", " + upper + "]");
241 }
242 }
243
244 /**
245 * Verifies that the upper and lower limits of iterations are valid.
246 *
247 * @throws IllegalArgumentException if not valid
248 */
249 protected void verifyIterationCount() throws IllegalArgumentException {
250 if (!isSequence(0, minimalIterationCount, maximalIterationCount+1)) {
251 throw new IllegalArgumentException
252 ("Invalid iteration limits: min=" + minimalIterationCount +
253 " max=" + maximalIterationCount);
254 }
255 }
256 }