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/TrapezoidalRule.html">
24   * Trapezoidal 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   * The function should be integrable.</p>
29   *  
30   * @version $Revision: 620312 $ $Date: 2008-02-10 12:28:59 -0700 (Sun, 10 Feb 2008) $
31   * @since 1.2
32   */
33  public class TrapezoidIntegrator extends UnivariateRealIntegratorImpl {
34  
35      /** serializable version identifier */
36      private static final long serialVersionUID = 4978222553983172543L;
37  
38      /** intermediate result */
39      private double s;
40  
41      /**
42       * Construct an integrator for the given function.
43       * 
44       * @param f function to integrate
45       */
46      public TrapezoidIntegrator(UnivariateRealFunction f) {
47          super(f, 64);
48      }
49  
50      /**
51       * Compute the n-th stage integral of trapezoid rule. This function
52       * should only be called by API <code>integrate()</code> in the package.
53       * To save time it does not verify arguments - caller does.
54       * <p>
55       * The interval is divided equally into 2^n sections rather than an
56       * arbitrary m sections because this configuration can best utilize the
57       * alrealy computed values.</p>
58       *
59       * @param min the lower bound for the interval
60       * @param max the upper bound for the interval
61       * @param n the stage of 1/2 refinement, n = 0 is no refinement
62       * @return the value of n-th stage integral
63       * @throws FunctionEvaluationException if an error occurs evaluating the
64       * function
65       */
66      double stage(double min, double max, int n) throws
67          FunctionEvaluationException {
68          
69          long i, np;
70          double x, spacing, sum = 0;
71          
72          if (n == 0) {
73              s = 0.5 * (max - min) * (f.value(min) + f.value(max));
74              return s;
75          } else {
76              np = 1L << (n-1);           // number of new points in this stage
77              spacing = (max - min) / np; // spacing between adjacent new points
78              x = min + 0.5 * spacing;    // the first new point
79              for (i = 0; i < np; i++) {
80                  sum += f.value(x);
81                  x += spacing;
82              }
83              // add the new sum to previously calculated result
84              s = 0.5 * (s + sum * spacing);
85              return s;
86          }
87      }
88  
89      /**
90       * Integrate the function in the given interval.
91       * 
92       * @param min the lower bound for the interval
93       * @param max the upper bound for the interval
94       * @return the value of integral
95       * @throws MaxIterationsExceededException if the maximum iteration count is exceeded
96       * or the integrator detects convergence problems otherwise
97       * @throws FunctionEvaluationException if an error occurs evaluating the
98       * function
99       * @throws IllegalArgumentException if any parameters are invalid
100      */
101     public double integrate(double min, double max) throws MaxIterationsExceededException,
102         FunctionEvaluationException, IllegalArgumentException {
103         
104         int i = 1;
105         double t, oldt;
106         
107         clearResult();
108         verifyInterval(min, max);
109         verifyIterationCount();
110 
111         oldt = stage(min, max, 0);
112         while (i <= maximalIterationCount) {
113             t = stage(min, max, i);
114             if (i >= minimalIterationCount) {
115                 if (Math.abs(t - oldt) <= Math.abs(relativeAccuracy * oldt)) {
116                     setResult(t, i);
117                     return result;
118                 }
119             }
120             oldt = t;
121             i++;
122         }
123         throw new MaxIterationsExceededException(maximalIterationCount);
124     }
125 
126     /**
127      * Verifies that the iteration limits are valid and within the range.
128      * 
129      * @throws IllegalArgumentException if not
130      */
131     protected void verifyIterationCount() throws IllegalArgumentException {
132         super.verifyIterationCount();
133         // at most 64 bisection refinements
134         if (maximalIterationCount > 64) {
135             throw new IllegalArgumentException
136                 ("Iteration upper limit out of [0, 64] range: " +
137                 maximalIterationCount);
138         }
139     }
140 }