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