/** * Copyright (C) 2009 - present by OpenGamma Inc. and the OpenGamma group of companies * * Please see distribution for license. */ package com.opengamma.strata.math.impl.integration; import static org.testng.AssertJUnit.assertEquals; import java.util.function.Function; import org.testng.annotations.Test; /** * Test. */ @Test public class RungeKuttaIntegrator1DTest { private static final double ROOT_2PI = Math.sqrt(2.0 * java.lang.Math.PI); private static final Function<Double, Double> CUBE = new Function<Double, Double>() { @Override public Double apply(final Double x) { return x * x * x; } }; private static final Function<Double, Double> TRIANGLE = new Function<Double, Double>() { @Override public Double apply(final Double x) { if (x > 1.0 || x < 0.0) return x - Math.floor(x); return x; } }; private static final Function<Double, Double> MIX_NORM = new Function<Double, Double>() { private final double[] W = new double[] {0.2, 0.2, 0.2, 0.2, 0.2 }; private final double[] MU = new double[] {0.0, -0.4, 0.5, 0.0, 0.01234583 }; private final double[] SIGMA = new double[] {3.0, 0.1, 5.0, 0.001, 0.0001 }; @SuppressWarnings("synthetic-access") @Override public Double apply(final Double x) { final int n = W.length; double res = 0.0; double expo; for (int i = 0; i < n; i++) { expo = (x - MU[i]) * (x - MU[i]) / SIGMA[i] / SIGMA[i]; res += W[i] * Math.exp(-0.5 * expo) / ROOT_2PI / SIGMA[i]; } return res; } }; private static final Function<Double, Double> SIN_INV_X = new Function<Double, Double>() { @Override public Double apply(final Double x) { final double eps = 1e-127; if (Math.abs(x) < eps) return 0.0; return Math.sin(1.0 / x); } }; @Test(expectedExceptions = IllegalArgumentException.class) public void testNegativeAbsTol() { new RungeKuttaIntegrator1D(-1.0); } @Test(expectedExceptions = IllegalArgumentException.class) public void testNegativeRelTol() { new RungeKuttaIntegrator1D(1e-7, -1.0); } @Test(expectedExceptions = IllegalArgumentException.class) public void testLessTahnOneStep() { new RungeKuttaIntegrator1D(0); } @Test public void test() { final double eps = 1e-9; final int minSteps = 10; final Integrator1D<Double, Double> integrator = new RungeKuttaIntegrator1D(eps, eps, minSteps); double lower = 0; double upper = 2.0; assertEquals(4.0, integrator.integrate(CUBE, lower, upper), eps); lower = 0.0; upper = 1.5; assertEquals(0.625, integrator.integrate(TRIANGLE, lower, upper), eps); lower = -30; upper = 30; assertEquals(1.0, integrator.integrate(MIX_NORM, lower, upper), eps); } @Test public void testCutoff() { final double eps = 1e-9; final int minSteps = 10; final Integrator1D<Double, Double> integrator = new RungeKuttaIntegrator1D(eps, eps, minSteps); final double lower = -1.0; final double upper = 1.0; assertEquals(0.0, integrator.integrate(SIN_INV_X, lower, upper), eps); } }