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 * https://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 18 /* 19 * This is not the original file distributed by the Apache Software Foundation 20 * It has been modified by the Hipparchus project 21 */ 22 package org.hipparchus.analysis.integration; 23 24 import org.hipparchus.CalculusFieldElement; 25 import org.hipparchus.Field; 26 import org.hipparchus.exception.LocalizedCoreFormats; 27 import org.hipparchus.exception.MathIllegalArgumentException; 28 import org.hipparchus.exception.MathIllegalStateException; 29 import org.hipparchus.util.FastMath; 30 31 /** 32 * Implements <a href="http://mathworld.wolfram.com/SimpsonsRule.html"> 33 * Simpson's Rule</a> for integration of real univariate functions. For 34 * reference, see <b>Introduction to Numerical Analysis</b>, ISBN 038795452X, 35 * chapter 3. 36 * <p> 37 * This implementation employs the basic trapezoid rule to calculate Simpson's 38 * rule.</p> 39 * @param <T> Type of the field elements. 40 * @since 2.0 41 */ 42 public class FieldSimpsonIntegrator<T extends CalculusFieldElement<T>> extends BaseAbstractFieldUnivariateIntegrator<T> { 43 44 /** Maximal number of iterations for Simpson. */ 45 public static final int SIMPSON_MAX_ITERATIONS_COUNT = 64; 46 47 /** 48 * Build a Simpson integrator with given accuracies and iterations counts. 49 * @param field field to which function argument and value belong 50 * @param relativeAccuracy relative accuracy of the result 51 * @param absoluteAccuracy absolute accuracy of the result 52 * @param minimalIterationCount minimum number of iterations 53 * @param maximalIterationCount maximum number of iterations 54 * (must be less than or equal to {@link #SIMPSON_MAX_ITERATIONS_COUNT}) 55 * @exception MathIllegalArgumentException if minimal number of iterations 56 * is not strictly positive 57 * @exception MathIllegalArgumentException if maximal number of iterations 58 * is lesser than or equal to the minimal number of iterations 59 * @exception MathIllegalArgumentException if maximal number of iterations 60 * is greater than {@link #SIMPSON_MAX_ITERATIONS_COUNT} 61 */ 62 public FieldSimpsonIntegrator(final Field<T> field, 63 final double relativeAccuracy, 64 final double absoluteAccuracy, 65 final int minimalIterationCount, 66 final int maximalIterationCount) 67 throws MathIllegalArgumentException { 68 super(field, relativeAccuracy, absoluteAccuracy, minimalIterationCount, maximalIterationCount); 69 if (maximalIterationCount > SIMPSON_MAX_ITERATIONS_COUNT) { 70 throw new MathIllegalArgumentException(LocalizedCoreFormats.NUMBER_TOO_LARGE_BOUND_EXCLUDED, 71 maximalIterationCount, SIMPSON_MAX_ITERATIONS_COUNT); 72 } 73 } 74 75 /** 76 * Build a Simpson integrator with given iteration counts. 77 * @param field field to which function argument and value belong 78 * @param minimalIterationCount minimum number of iterations 79 * @param maximalIterationCount maximum number of iterations 80 * (must be less than or equal to {@link #SIMPSON_MAX_ITERATIONS_COUNT}) 81 * @exception MathIllegalArgumentException if minimal number of iterations 82 * is not strictly positive 83 * @exception MathIllegalArgumentException if maximal number of iterations 84 * is lesser than or equal to the minimal number of iterations 85 * @exception MathIllegalArgumentException if maximal number of iterations 86 * is greater than {@link #SIMPSON_MAX_ITERATIONS_COUNT} 87 */ 88 public FieldSimpsonIntegrator(final Field<T> field, 89 final int minimalIterationCount, 90 final int maximalIterationCount) 91 throws MathIllegalArgumentException { 92 super(field, minimalIterationCount, maximalIterationCount); 93 if (maximalIterationCount > SIMPSON_MAX_ITERATIONS_COUNT) { 94 throw new MathIllegalArgumentException(LocalizedCoreFormats.NUMBER_TOO_LARGE_BOUND_EXCLUDED, 95 maximalIterationCount, SIMPSON_MAX_ITERATIONS_COUNT); 96 } 97 } 98 99 /** 100 * Construct an integrator with default settings. 101 * @param field field to which function argument and value belong 102 * (max iteration count set to {@link #SIMPSON_MAX_ITERATIONS_COUNT}) 103 */ 104 public FieldSimpsonIntegrator(final Field<T> field) { 105 super(field, DEFAULT_MIN_ITERATIONS_COUNT, SIMPSON_MAX_ITERATIONS_COUNT); 106 } 107 108 /** {@inheritDoc} */ 109 @Override 110 protected T doIntegrate() 111 throws MathIllegalStateException { 112 113 FieldTrapezoidIntegrator<T> qtrap = new FieldTrapezoidIntegrator<>(getField()); 114 if (getMinimalIterationCount() == 1) { 115 return qtrap.stage(this, 1).multiply(4).subtract(qtrap.stage(this, 0)).divide(3.0); 116 } 117 118 // Simpson's rule requires at least two trapezoid stages. 119 T olds = getField().getZero(); 120 T oldt = qtrap.stage(this, 0); 121 while (true) { 122 final T t = qtrap.stage(this, iterations.getCount()); 123 iterations.increment(); 124 final T s = t.multiply(4).subtract(oldt).divide(3.0); 125 if (iterations.getCount() >= getMinimalIterationCount()) { 126 final double delta = FastMath.abs(s.subtract(olds)).getReal(); 127 final double rLimit = FastMath.abs(olds).add(FastMath.abs(s)).multiply(0.5 * getRelativeAccuracy()).getReal(); 128 if ((delta <= rLimit) || (delta <= getAbsoluteAccuracy())) { 129 return s; 130 } 131 } 132 olds = s; 133 oldt = t; 134 } 135 136 } 137 138 }