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 */ 017package org.apache.commons.math3.analysis.integration; 018 019import org.apache.commons.math3.exception.MaxCountExceededException; 020import org.apache.commons.math3.exception.NotStrictlyPositiveException; 021import org.apache.commons.math3.exception.NumberIsTooLargeException; 022import org.apache.commons.math3.exception.NumberIsTooSmallException; 023import org.apache.commons.math3.exception.TooManyEvaluationsException; 024import org.apache.commons.math3.util.FastMath; 025 026/** 027 * Implements <a href="http://mathworld.wolfram.com/SimpsonsRule.html"> 028 * Simpson's Rule</a> for integration of real univariate functions. For 029 * reference, see <b>Introduction to Numerical Analysis</b>, ISBN 038795452X, 030 * chapter 3. 031 * <p> 032 * This implementation employs the basic trapezoid rule to calculate Simpson's 033 * rule.</p> 034 * 035 * @since 1.2 036 */ 037public class SimpsonIntegrator extends BaseAbstractUnivariateIntegrator { 038 039 /** Maximal number of iterations for Simpson. */ 040 public static final int SIMPSON_MAX_ITERATIONS_COUNT = 64; 041 042 /** 043 * Build a Simpson integrator with given accuracies and iterations counts. 044 * @param relativeAccuracy relative accuracy of the result 045 * @param absoluteAccuracy absolute accuracy of the result 046 * @param minimalIterationCount minimum number of iterations 047 * @param maximalIterationCount maximum number of iterations 048 * (must be less than or equal to {@link #SIMPSON_MAX_ITERATIONS_COUNT}) 049 * @exception NotStrictlyPositiveException if minimal number of iterations 050 * is not strictly positive 051 * @exception NumberIsTooSmallException if maximal number of iterations 052 * is lesser than or equal to the minimal number of iterations 053 * @exception NumberIsTooLargeException if maximal number of iterations 054 * is greater than {@link #SIMPSON_MAX_ITERATIONS_COUNT} 055 */ 056 public SimpsonIntegrator(final double relativeAccuracy, 057 final double absoluteAccuracy, 058 final int minimalIterationCount, 059 final int maximalIterationCount) 060 throws NotStrictlyPositiveException, NumberIsTooSmallException, NumberIsTooLargeException { 061 super(relativeAccuracy, absoluteAccuracy, minimalIterationCount, maximalIterationCount); 062 if (maximalIterationCount > SIMPSON_MAX_ITERATIONS_COUNT) { 063 throw new NumberIsTooLargeException(maximalIterationCount, 064 SIMPSON_MAX_ITERATIONS_COUNT, false); 065 } 066 } 067 068 /** 069 * Build a Simpson integrator with given iteration counts. 070 * @param minimalIterationCount minimum number of iterations 071 * @param maximalIterationCount maximum number of iterations 072 * (must be less than or equal to {@link #SIMPSON_MAX_ITERATIONS_COUNT}) 073 * @exception NotStrictlyPositiveException if minimal number of iterations 074 * is not strictly positive 075 * @exception NumberIsTooSmallException if maximal number of iterations 076 * is lesser than or equal to the minimal number of iterations 077 * @exception NumberIsTooLargeException if maximal number of iterations 078 * is greater than {@link #SIMPSON_MAX_ITERATIONS_COUNT} 079 */ 080 public SimpsonIntegrator(final int minimalIterationCount, 081 final int maximalIterationCount) 082 throws NotStrictlyPositiveException, NumberIsTooSmallException, NumberIsTooLargeException { 083 super(minimalIterationCount, maximalIterationCount); 084 if (maximalIterationCount > SIMPSON_MAX_ITERATIONS_COUNT) { 085 throw new NumberIsTooLargeException(maximalIterationCount, 086 SIMPSON_MAX_ITERATIONS_COUNT, false); 087 } 088 } 089 090 /** 091 * Construct an integrator with default settings. 092 * (max iteration count set to {@link #SIMPSON_MAX_ITERATIONS_COUNT}) 093 */ 094 public SimpsonIntegrator() { 095 super(DEFAULT_MIN_ITERATIONS_COUNT, SIMPSON_MAX_ITERATIONS_COUNT); 096 } 097 098 /** {@inheritDoc} */ 099 @Override 100 protected double doIntegrate() 101 throws TooManyEvaluationsException, MaxCountExceededException { 102 103 TrapezoidIntegrator qtrap = new TrapezoidIntegrator(); 104 if (getMinimalIterationCount() == 1) { 105 return (4 * qtrap.stage(this, 1) - qtrap.stage(this, 0)) / 3.0; 106 } 107 108 // Simpson's rule requires at least two trapezoid stages. 109 double olds = 0; 110 double oldt = qtrap.stage(this, 0); 111 while (true) { 112 final double t = qtrap.stage(this, getIterations()); 113 incrementCount(); 114 final double s = (4 * t - oldt) / 3.0; 115 if (getIterations() >= getMinimalIterationCount()) { 116 final double delta = FastMath.abs(s - olds); 117 final double rLimit = 118 getRelativeAccuracy() * (FastMath.abs(olds) + FastMath.abs(s)) * 0.5; 119 if ((delta <= rLimit) || (delta <= getAbsoluteAccuracy())) { 120 return s; 121 } 122 } 123 olds = s; 124 oldt = t; 125 } 126 127 } 128 129}