View Javadoc

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 org.apache.commons.math.FunctionEvaluationException;
20  import org.apache.commons.math.MaxIterationsExceededException;
21  
22  /**
23   * Implements the <a href="http://mathworld.wolfram.com/SimpsonsRule.html">
24   * Simpson's Rule</a> for integration of real univariate functions. For
25   * reference, see <b>Introduction to Numerical Analysis</b>, ISBN 038795452X,
26   * chapter 3.
27   * <p>
28   * This implementation employs basic trapezoid rule as building blocks to
29   * calculate the Simpson's rule of alternating 2/3 and 4/3.</p>
30   *  
31   * @version $Revision: 620312 $ $Date: 2008-02-10 12:28:59 -0700 (Sun, 10 Feb 2008) $
32   * @since 1.2
33   */
34  public class SimpsonIntegrator extends UnivariateRealIntegratorImpl {
35  
36      /** serializable version identifier */
37      private static final long serialVersionUID = 3405465123320678216L;
38  
39      /**
40       * Construct an integrator for the given function.
41       * 
42       * @param f function to integrate
43       */
44      public SimpsonIntegrator(UnivariateRealFunction f) {
45          super(f, 64);
46      }
47  
48      /**
49       * Integrate the function in the given interval.
50       * 
51       * @param min the lower bound for the interval
52       * @param max the upper bound for the interval
53       * @return the value of integral
54       * @throws MaxIterationsExceededException if the maximum iteration count is exceeded
55       * or the integrator detects convergence problems otherwise
56       * @throws FunctionEvaluationException if an error occurs evaluating the
57       * function
58       * @throws IllegalArgumentException if any parameters are invalid
59       */
60      public double integrate(double min, double max) throws MaxIterationsExceededException,
61          FunctionEvaluationException, IllegalArgumentException {
62          
63          int i = 1;
64          double s, olds, t, oldt;
65          
66          clearResult();
67          verifyInterval(min, max);
68          verifyIterationCount();
69  
70          TrapezoidIntegrator qtrap = new TrapezoidIntegrator(this.f);
71          if (minimalIterationCount == 1) {
72              s = (4 * qtrap.stage(min, max, 1) - qtrap.stage(min, max, 0)) / 3.0;
73              setResult(s, 1);
74              return result;
75          }
76          // Simpson's rule requires at least two trapezoid stages.
77          olds = 0;
78          oldt = qtrap.stage(min, max, 0);
79          while (i <= maximalIterationCount) {
80              t = qtrap.stage(min, max, i);
81              s = (4 * t - oldt) / 3.0;
82              if (i >= minimalIterationCount) {
83                  if (Math.abs(s - olds) <= Math.abs(relativeAccuracy * olds)) {
84                      setResult(s, i);
85                      return result;
86                  }
87              }
88              olds = s;
89              oldt = t;
90              i++;
91          }
92          throw new MaxIterationsExceededException(maximalIterationCount);
93      }
94  
95      /**
96       * Verifies that the iteration limits are valid and within the range.
97       * 
98       * @throws IllegalArgumentException if not
99       */
100     protected void verifyIterationCount() throws IllegalArgumentException {
101         super.verifyIterationCount();
102         // at most 64 bisection refinements
103         if (maximalIterationCount > 64) {
104             throw new IllegalArgumentException
105                 ("Iteration upper limit out of [0, 64] range: " +
106                 maximalIterationCount);
107         }
108     }
109 }