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.exception.LocalizedCoreFormats; 25 import org.hipparchus.exception.MathIllegalArgumentException; 26 import org.hipparchus.exception.MathIllegalStateException; 27 import org.hipparchus.util.FastMath; 28 29 /** 30 * Implements the <a href="http://mathworld.wolfram.com/TrapezoidalRule.html"> 31 * Trapezoid Rule</a> for integration of real univariate functions. For 32 * reference, see <b>Introduction to Numerical Analysis</b>, ISBN 038795452X, 33 * chapter 3. 34 * <p> 35 * The function should be integrable.</p> 36 * 37 */ 38 public class TrapezoidIntegrator extends BaseAbstractUnivariateIntegrator { 39 40 /** Maximum number of iterations for trapezoid. */ 41 public static final int TRAPEZOID_MAX_ITERATIONS_COUNT = 64; 42 43 /** Intermediate result. */ 44 private double s; 45 46 /** 47 * Build a trapezoid integrator with given accuracies and iterations counts. 48 * @param relativeAccuracy relative accuracy of the result 49 * @param absoluteAccuracy absolute accuracy of the result 50 * @param minimalIterationCount minimum number of iterations 51 * @param maximalIterationCount maximum number of iterations 52 * (must be less than or equal to {@link #TRAPEZOID_MAX_ITERATIONS_COUNT} 53 * @exception MathIllegalArgumentException if minimal number of iterations 54 * is not strictly positive 55 * @exception MathIllegalArgumentException if maximal number of iterations 56 * is lesser than or equal to the minimal number of iterations 57 * @exception MathIllegalArgumentException if maximal number of iterations 58 * is greater than {@link #TRAPEZOID_MAX_ITERATIONS_COUNT} 59 */ 60 public TrapezoidIntegrator(final double relativeAccuracy, 61 final double absoluteAccuracy, 62 final int minimalIterationCount, 63 final int maximalIterationCount) 64 throws MathIllegalArgumentException { 65 super(relativeAccuracy, absoluteAccuracy, minimalIterationCount, maximalIterationCount); 66 if (maximalIterationCount > TRAPEZOID_MAX_ITERATIONS_COUNT) { 67 throw new MathIllegalArgumentException(LocalizedCoreFormats.NUMBER_TOO_LARGE_BOUND_EXCLUDED, 68 maximalIterationCount, TRAPEZOID_MAX_ITERATIONS_COUNT); 69 } 70 } 71 72 /** 73 * Build a trapezoid integrator with given iteration counts. 74 * @param minimalIterationCount minimum number of iterations 75 * @param maximalIterationCount maximum number of iterations 76 * (must be less than or equal to {@link #TRAPEZOID_MAX_ITERATIONS_COUNT} 77 * @exception MathIllegalArgumentException if minimal number of iterations 78 * is not strictly positive 79 * @exception MathIllegalArgumentException if maximal number of iterations 80 * is lesser than or equal to the minimal number of iterations 81 * @exception MathIllegalArgumentException if maximal number of iterations 82 * is greater than {@link #TRAPEZOID_MAX_ITERATIONS_COUNT} 83 */ 84 public TrapezoidIntegrator(final int minimalIterationCount, 85 final int maximalIterationCount) 86 throws MathIllegalArgumentException { 87 super(minimalIterationCount, maximalIterationCount); 88 if (maximalIterationCount > TRAPEZOID_MAX_ITERATIONS_COUNT) { 89 throw new MathIllegalArgumentException(LocalizedCoreFormats.NUMBER_TOO_LARGE_BOUND_EXCLUDED, 90 maximalIterationCount, TRAPEZOID_MAX_ITERATIONS_COUNT); 91 } 92 } 93 94 /** 95 * Construct a trapezoid integrator with default settings. 96 * (max iteration count set to {@link #TRAPEZOID_MAX_ITERATIONS_COUNT}) 97 */ 98 public TrapezoidIntegrator() { 99 super(DEFAULT_MIN_ITERATIONS_COUNT, TRAPEZOID_MAX_ITERATIONS_COUNT); 100 } 101 102 /** 103 * Compute the n-th stage integral of trapezoid rule. This function 104 * should only be called by API <code>integrate()</code> in the package. 105 * To save time it does not verify arguments - caller does. 106 * <p> 107 * The interval is divided equally into 2^n sections rather than an 108 * arbitrary m sections because this configuration can best utilize the 109 * already computed values.</p> 110 * 111 * @param baseIntegrator integrator holding integration parameters 112 * @param n the stage of 1/2 refinement, n = 0 is no refinement 113 * @return the value of n-th stage integral 114 * @throws MathIllegalStateException if the maximal number of evaluations 115 * is exceeded. 116 */ 117 double stage(final BaseAbstractUnivariateIntegrator baseIntegrator, final int n) 118 throws MathIllegalStateException { 119 120 if (n == 0) { 121 final double max = baseIntegrator.getMax(); 122 final double min = baseIntegrator.getMin(); 123 s = 0.5 * (max - min) * 124 (baseIntegrator.computeObjectiveValue(min) + 125 baseIntegrator.computeObjectiveValue(max)); 126 return s; 127 } else { 128 final long np = 1L << (n-1); // number of new points in this stage 129 double sum = 0; 130 final double max = baseIntegrator.getMax(); 131 final double min = baseIntegrator.getMin(); 132 // spacing between adjacent new points 133 final double spacing = (max - min) / np; 134 double x = min + 0.5 * spacing; // the first new point 135 for (long i = 0; i < np; i++) { 136 sum += baseIntegrator.computeObjectiveValue(x); 137 x += spacing; 138 } 139 // add the new sum to previously calculated result 140 s = 0.5 * (s + sum * spacing); 141 return s; 142 } 143 } 144 145 /** {@inheritDoc} */ 146 @Override 147 protected double doIntegrate() 148 throws MathIllegalArgumentException, MathIllegalStateException { 149 150 double oldt = stage(this, 0); 151 iterations.increment(); 152 while (true) { 153 final int i = iterations.getCount(); 154 final double t = stage(this, i); 155 if (i >= getMinimalIterationCount()) { 156 final double delta = FastMath.abs(t - oldt); 157 final double rLimit = 158 getRelativeAccuracy() * (FastMath.abs(oldt) + FastMath.abs(t)) * 0.5; 159 if ((delta <= rLimit) || (delta <= getAbsoluteAccuracy())) { 160 return t; 161 } 162 } 163 oldt = t; 164 iterations.increment(); 165 } 166 167 } 168 169 }