SSJ API Documentation
Stochastic Simulation in Java
Loading...
Searching...
No Matches
MathFunctionUtil.java
1/*
2 * Class: MathFunctionUtil
3 * Description:
4 * Environment: Java
5 * Software: SSJ
6 * Copyright (C) 2001 Pierre L'Ecuyer and Universite de Montreal
7 * Organization: DIRO, Universite de Montreal
8 * @author Éric Buist
9 * @since
10 *
11 *
12 * Licensed under the Apache License, Version 2.0 (the "License");
13 * you may not use this file except in compliance with the License.
14 * You may obtain a copy of the License at
15 *
16 * http://www.apache.org/licenses/LICENSE-2.0
17 *
18 * Unless required by applicable law or agreed to in writing, software
19 * distributed under the License is distributed on an "AS IS" BASIS,
20 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
21 * See the License for the specific language governing permissions and
22 * limitations under the License.
23 *
24 */
25package umontreal.ssj.functions;
26
27import umontreal.ssj.util.Misc;
28
35public class MathFunctionUtil {
36
40 public static double H = 1e-6;
41
42 private MathFunctionUtil() {
43 }
44
45 // For Gauss-Lobatto: nodes Cg and weights Wg
46 private static final double[] Cg = { 0, 0.17267316464601142812, 0.5, 0.82732683535398857188, 1 };
47 private static final double[] Wg = { 0.05, 0.27222222222222222222, 0.35555555555555555555, 0.27222222222222222222,
48 0.05 };
49
50 private static double[] fixBounds(MathFunction func, double a, double b, int numIntervals) {
51 // For functions which are 0 on parts of [a, b], shorten the interval
52 // [a, b] to the non-zero part of f(x). Returns the shortened interval.
53
54 final double h = (b - a) / numIntervals;
55 double x = b;
56 while ((0 == func.evaluate(x)) && (x > a))
57 x -= h;
58 if (x < b)
59 b = x + h;
60
61 x = a;
62 while ((0 == func.evaluate(x)) && (x < b))
63 x += h;
64 if (x > a)
65 a = x - h;
66 double[] D = { a, b };
67 return D;
68 }
69
73 public static int NUMINTERVALS = 1024;
74
92 public static double derivative(MathFunction func, double x) {
93 if (func instanceof MathFunctionWithFirstDerivative)
94 return ((MathFunctionWithFirstDerivative) func).derivative(x);
95 else if (func instanceof MathFunctionWithDerivative)
96 return ((MathFunctionWithDerivative) func).derivative(x, 1);
97 else
99 }
100
120 public static double derivative(MathFunction func, double x, int n) {
121 if (n == 0)
122 return func.evaluate(x);
123 else if (n == 1)
124 return derivative(func, x);
125 else if (func instanceof MathFunctionWithDerivative)
126 return ((MathFunctionWithDerivative) func).derivative(x, n);
127 else if (n % 2 == 0)
128 return finiteCenteredDifferenceDerivative(func, x, n, H);
129 else
130 return finiteDifferenceDerivative(func, x, n, H);
131 }
132
149 public static double finiteDifferenceDerivative(MathFunction func, double x, int n, double h) {
150 if (n < 0)
151 throw new IllegalArgumentException("n must not be negative");
152 if (n == 0)
153 return func.evaluate(x);
154 final double err = Math.pow(h, 1.0 / n);
155 final double[] values = new double[n + 1];
156 for (int i = 0; i < values.length; i++)
157 values[i] = func.evaluate(x + i * err);
158 for (int j = 0; j < n; j++) {
159 for (int i = 0; i < n - j; i++)
160 values[i] = values[i + 1] - values[i];
161 }
162 return values[0] / h;
163 }
164
174 public static double finiteCenteredDifferenceDerivative(MathFunction func, double x, double h) {
175 final double fplus = func.evaluate(x + h);
176 final double fminus = func.evaluate(x - h);
177 return (fplus - fminus) / (2 * h);
178 }
179
193 public static double finiteCenteredDifferenceDerivative(MathFunction func, double x, int n, double h) {
194 if (n < 0)
195 throw new IllegalArgumentException("n must not be negative");
196 if (n == 0)
197 return func.evaluate(x);
198 if (n % 2 == 1)
199 throw new IllegalArgumentException("n must be even");
200 final double err = Math.pow(h, 1.0 / n);
201 return finiteDifferenceDerivative(func, x - n * err / 2, n, h);
202 }
203
215 public static double[][] removeNaNs(double[] x, double[] y) {
216 if (x.length != y.length)
217 throw new IllegalArgumentException();
218 int numNaNs = 0;
219 for (int i = 0; i < x.length; i++)
220 if (Double.isNaN(x[i]) || Double.isNaN(y[i]))
221 ++numNaNs;
222 if (numNaNs == 0)
223 return new double[][] { x, y };
224 final double[] nx = new double[x.length - numNaNs];
225 final double[] ny = new double[y.length - numNaNs];
226 int j = 0;
227 for (int i = 0; i < x.length; i++)
228 if (!Double.isNaN(x[i]) && !Double.isNaN(y[i])) {
229 nx[j] = x[i];
230 ny[j++] = y[i];
231 }
232 return new double[][] { nx, ny };
233 }
234
248 public static double integral(MathFunction func, double a, double b) {
249 if (func instanceof MathFunctionWithIntegral)
250 return ((MathFunctionWithIntegral) func).integral(a, b);
251 else
252 return simpsonIntegral(func, a, b, NUMINTERVALS);
253 }
254
271 public static double simpsonIntegral(MathFunction func, double a, double b, int numIntervals) {
272 if (numIntervals % 2 != 0)
273 throw new IllegalArgumentException("numIntervals must be an even number");
274 if (Double.isInfinite(a) || Double.isInfinite(b) || Double.isNaN(a) || Double.isNaN(b))
275 throw new IllegalArgumentException("a and b must not be infinite or NaN");
276 if (b < a)
277 throw new IllegalArgumentException("b < a");
278 if (a == b)
279 return 0;
280 double[] D = fixBounds(func, a, b, numIntervals);
281 a = D[0];
282 b = D[1];
283 final double h = (b - a) / numIntervals;
284 final double h2 = 2 * h;
285 final int m = numIntervals / 2;
286 double sum = 0;
287 for (int i = 0; i < m - 1; i++) {
288 final double x = a + h + h2 * i;
289 sum += 4 * func.evaluate(x) + 2 * func.evaluate(x + h);
290 }
291 sum += func.evaluate(a) + func.evaluate(b) + 4 * func.evaluate(b - h);
292 return sum * h / 3;
293 }
294
311 public static double gaussLobatto(MathFunction func, double a, double b, double tol) {
312 if (b < a)
313 throw new IllegalArgumentException("b < a");
314 if (Double.isInfinite(a) || Double.isInfinite(b) || Double.isNaN(a) || Double.isNaN(b))
315 throw new IllegalArgumentException("a or b is infinite or NaN");
316 if (a == b)
317 return 0;
318 double r0 = simpleGaussLob(func, a, b);
319 final double h = (b - a) / 2;
320 double r1 = simpleGaussLob(func, a, a + h) + simpleGaussLob(func, a + h, b);
321 double maxi = Math.max(1.0, Math.abs(r1));
322 if (Math.abs(r0 - r1) <= tol * maxi)
323 return r1;
324 return gaussLobatto(func, a, a + h, tol) + gaussLobatto(func, a + h, b, tol);
325 }
326
327 private static double simpleGaussLob(MathFunction func, double a, double b) {
328 // Gauss-Lobatto integral over [a, b] with 5 nodes
329 if (a == b)
330 return 0;
331 final double h = b - a;
332 double sum = 0;
333 for (int i = 0; i < 5; i++) {
334 sum += Wg[i] * func.evaluate(a + h * Cg[i]);
335 }
336 return h * sum;
337 }
338
359 public static double gaussLobatto(MathFunction func, double a, double b, double tol, double[][] T) {
360 if (b < a)
361 throw new IllegalArgumentException("b < a");
362 if (a == b) {
363 T[0] = new double[1];
364 T[1] = new double[1];
365 T[0][0] = a;
366 T[1][0] = 0;
367 return 0;
368 }
369
370 int n = 1; // initial capacity
371 T[0] = new double[n];
372 T[1] = new double[n];
373 T[0][0] = a;
374 T[1][0] = 0;
375 int[] s = { 0 }; // actual number of intervals
376 double res = innerGaussLob(func, a, b, tol, T, s);
377 n = s[0] + 1;
378 double[] temp = new double[n];
379 System.arraycopy(T[0], 0, temp, 0, n);
380 T[0] = temp;
381 temp = new double[n];
382 System.arraycopy(T[1], 0, temp, 0, n);
383 T[1] = temp;
384 return res;
385 }
386
387 private static double innerGaussLob(MathFunction func, double a, double b, double tol, double[][] T, int[] s) {
388 double r0 = simpleGaussLob(func, a, b);
389 final double h = (b - a) / 2;
390 double r1 = simpleGaussLob(func, a, a + h) + simpleGaussLob(func, a + h, b);
391 if (Math.abs(r0 - r1) <= tol) {
392 ++s[0];
393 int len = s[0];
394 if (len >= T[0].length) {
395 double[] temp = new double[2 * len];
396 System.arraycopy(T[0], 0, temp, 0, len);
397 T[0] = temp;
398 temp = new double[2 * len];
399 System.arraycopy(T[1], 0, temp, 0, len);
400 T[1] = temp;
401 }
402 T[0][len] = b;
403 T[1][len] = r1;
404 return r1;
405 }
406
407 return innerGaussLob(func, a, a + h, tol, T, s) + innerGaussLob(func, a + h, b, tol, T, s);
408 }
409
410}
static int NUMINTERVALS
Default number of intervals for Simpson’s integral.
static double derivative(MathFunction func, double x)
Returns the first derivative of the function func evaluated at x.
static double finiteCenteredDifferenceDerivative(MathFunction func, double x, int n, double h)
Computes and returns an estimate of the th derivative of the function using finite centered differen...
static double simpsonIntegral(MathFunction func, double a, double b, int numIntervals)
Computes and returns an approximation of the integral of func over , using the Simpson’s method wit...
static double derivative(MathFunction func, double x, int n)
Returns the th derivative of function func evaluated at x.
static double H
Step length in to compute derivatives.
static double finiteDifferenceDerivative(MathFunction func, double x, int n, double h)
Computes and returns an estimate of the th derivative of the function .
static double gaussLobatto(MathFunction func, double a, double b, double tol)
Computes and returns a numerical approximation of the integral of.
static double[][] removeNaNs(double[] x, double[] y)
Removes any point (NaN, y) or (x, NaN) from x and y, and returns a 2D array containing the filtered p...
static double gaussLobatto(MathFunction func, double a, double b, double tol, double[][] T)
Similar to method gaussLobatto(MathFunction, double,double, double), but also returns in T[0] the sub...
static double integral(MathFunction func, double a, double b)
Returns the integral of the function func over .
static double finiteCenteredDifferenceDerivative(MathFunction func, double x, double h)
Returns , an estimate of the first derivative of using centered differences.
Represents a mathematical function whose th derivative can be computed using derivative(double,...
Represents a mathematical function whose derivative can be computed using derivative(double).
Represents a mathematical function whose integral can be computed by the integral(double,...
This interface should be implemented by classes which represent univariate mathematical functions.
double evaluate(double x)
Returns the value of the function evaluated at .