1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 package org.hipparchus.analysis.solvers;
24
25 import org.hipparchus.CalculusFieldElement;
26 import org.hipparchus.analysis.FieldUnivariateFunction;
27 import org.hipparchus.analysis.CalculusFieldUnivariateFunction;
28 import org.hipparchus.dfp.Dfp;
29 import org.hipparchus.dfp.DfpField;
30 import org.hipparchus.dfp.DfpMath;
31 import org.hipparchus.exception.MathIllegalArgumentException;
32 import org.hipparchus.exception.MathRuntimeException;
33 import org.hipparchus.util.FastMath;
34 import org.junit.Assert;
35 import org.junit.Before;
36 import org.junit.Test;
37
38
39
40
41
42 public final class FieldBracketingNthOrderBrentSolverTest {
43
44 @Test(expected=MathIllegalArgumentException.class)
45 public void testInsufficientOrder3() {
46 new FieldBracketingNthOrderBrentSolver<Dfp>(relativeAccuracy, absoluteAccuracy,
47 functionValueAccuracy, 1);
48 }
49
50 @Test
51 public void testConstructorOK() {
52 FieldBracketingNthOrderBrentSolver<Dfp> solver =
53 new FieldBracketingNthOrderBrentSolver<Dfp>(relativeAccuracy, absoluteAccuracy,
54 functionValueAccuracy, 2);
55 Assert.assertEquals(2, solver.getMaximalOrder());
56 }
57
58 @Test
59 public void testConvergenceOnFunctionAccuracy() {
60 FieldBracketingNthOrderBrentSolver<Dfp> solver =
61 new FieldBracketingNthOrderBrentSolver<Dfp>(relativeAccuracy, absoluteAccuracy,
62 field.newDfp(1.0e-20), 20);
63 FieldUnivariateFunction f = new FieldUnivariateFunction() {
64 public <T extends CalculusFieldElement<T>> T value(T x) {
65 T one = x.getField().getOne();
66 T oneHalf = one.divide(2);
67 T xMo = x.subtract(one);
68 T xMh = x.subtract(oneHalf);
69 T xPh = x.add(oneHalf);
70 T xPo = x.add(one);
71 return xMo.multiply(xMh).multiply(x).multiply(xPh).multiply(xPo);
72 }
73 };
74
75 Dfp result = solver.solve(20, f.toCalculusFieldUnivariateFunction(field), field.newDfp(0.2), field.newDfp(0.9),
76 field.newDfp(0.4), AllowedSolution.BELOW_SIDE);
77 Assert.assertTrue(f.value(result).abs().lessThan(solver.getFunctionValueAccuracy()));
78 Assert.assertTrue(f.value(result).negativeOrNull());
79 Assert.assertTrue(result.subtract(field.newDfp(0.5)).subtract(solver.getAbsoluteAccuracy()).positiveOrNull());
80 result = solver.solve(20, f.toCalculusFieldUnivariateFunction(field), field.newDfp(-0.9), field.newDfp(-0.2),
81 field.newDfp(-0.4), AllowedSolution.ABOVE_SIDE);
82 Assert.assertTrue(f.value(result).abs().lessThan(solver.getFunctionValueAccuracy()));
83 Assert.assertTrue(f.value(result).positiveOrNull());
84 Assert.assertTrue(result.add(field.newDfp(0.5)).subtract(solver.getAbsoluteAccuracy()).negativeOrNull());
85 }
86
87 @Test
88 public void testToleranceLessThanUlp() {
89
90 Dfp zero = field.getZero();
91 Dfp one = field.getOne();
92 CalculusFieldUnivariateFunction<Dfp> f = (x) -> x.getReal() <= 2.1 ? one.negate(): one;
93
94 FieldBracketingNthOrderBrentSolver<Dfp> solver =
95 new FieldBracketingNthOrderBrentSolver<>(zero, field.newDfp(1e-55), zero, 5);
96
97
98 Dfp result = solver.solve(200, f, zero, zero.add(5.0), AllowedSolution.LEFT_SIDE);
99 double difference = field.newDfp(2.1).subtract(result).abs().getReal();
100 Assert.assertTrue("difference: " + difference, difference < FastMath.ulp(2.1));
101 }
102
103 @Test
104 public void testNeta() {
105
106
107
108
109
110 for (AllowedSolution allowed : AllowedSolution.values()) {
111 check(new CalculusFieldUnivariateFunction<Dfp>() {
112 public Dfp value(Dfp x) {
113 return DfpMath.sin(x).subtract(x.divide(2));
114 }
115 }, 200, -2.0, 2.0, allowed);
116
117 check(new CalculusFieldUnivariateFunction<Dfp>() {
118 public Dfp value(Dfp x) {
119 return DfpMath.pow(x, 5).add(x).subtract(field.newDfp(10000));
120 }
121 }, 200, -5.0, 10.0, allowed);
122
123 check(new CalculusFieldUnivariateFunction<Dfp>() {
124 public Dfp value(Dfp x) {
125 return x.sqrt().subtract(field.getOne().divide(x)).subtract(field.newDfp(3));
126 }
127 }, 200, 0.001, 10.0, allowed);
128
129 check(new CalculusFieldUnivariateFunction<Dfp>() {
130 public Dfp value(Dfp x) {
131 return DfpMath.exp(x).add(x).subtract(field.newDfp(20));
132 }
133 }, 200, -5.0, 5.0, allowed);
134
135 check(new CalculusFieldUnivariateFunction<Dfp>() {
136 public Dfp value(Dfp x) {
137 return DfpMath.log(x).add(x.sqrt()).subtract(field.newDfp(5));
138 }
139 }, 200, 0.001, 10.0, allowed);
140
141 check(new CalculusFieldUnivariateFunction<Dfp>() {
142 public Dfp value(Dfp x) {
143 return x.subtract(field.getOne()).multiply(x).multiply(x).subtract(field.getOne());
144 }
145 }, 200, -0.5, 1.5, allowed);
146 }
147
148 }
149
150 private void check(CalculusFieldUnivariateFunction<Dfp> f, int maxEval, double min, double max,
151 AllowedSolution allowedSolution) {
152 FieldBracketingNthOrderBrentSolver<Dfp> solver =
153 new FieldBracketingNthOrderBrentSolver<Dfp>(relativeAccuracy, absoluteAccuracy,
154 functionValueAccuracy, 20);
155 Dfp xResult = solver.solve(maxEval, f, field.newDfp(min), field.newDfp(max),
156 allowedSolution);
157 Dfp yResult = f.value(xResult);
158 switch (allowedSolution) {
159 case ANY_SIDE :
160 Assert.assertTrue(yResult.abs().lessThan(functionValueAccuracy.multiply(2)));
161 break;
162 case LEFT_SIDE : {
163 boolean increasing = f.value(xResult).add(absoluteAccuracy).greaterThan(yResult);
164 Assert.assertTrue(increasing ? yResult.negativeOrNull() : yResult.positiveOrNull());
165 break;
166 }
167 case RIGHT_SIDE : {
168 boolean increasing = f.value(xResult).add(absoluteAccuracy).greaterThan(yResult);
169 Assert.assertTrue(increasing ? yResult.positiveOrNull() : yResult.negativeOrNull());
170 break;
171 }
172 case BELOW_SIDE :
173 Assert.assertTrue(yResult.negativeOrNull());
174 break;
175 case ABOVE_SIDE :
176 Assert.assertTrue(yResult.positiveOrNull());
177 break;
178 default :
179
180 throw new MathRuntimeException(null);
181 }
182 }
183
184 @Before
185 public void setUp() {
186 field = new DfpField(50);
187 absoluteAccuracy = field.newDfp(1.0e-45);
188 relativeAccuracy = field.newDfp(1.0e-45);
189 functionValueAccuracy = field.newDfp(1.0e-45);
190 }
191
192 private DfpField field;
193 private Dfp absoluteAccuracy;
194 private Dfp relativeAccuracy;
195 private Dfp functionValueAccuracy;
196
197 }