1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.hipparchus.analysis.differentiation;
19
20 import org.hipparchus.Field;
21 import org.hipparchus.UnitTestUtils;
22 import org.hipparchus.complex.Complex;
23 import org.hipparchus.complex.ComplexField;
24 import org.hipparchus.util.Binary64;
25 import org.hipparchus.util.FastMath;
26 import org.hipparchus.util.MathUtils;
27 import org.hipparchus.util.Precision;
28 import org.junit.jupiter.api.Test;
29
30 import java.util.Arrays;
31 import java.util.List;
32
33 import static org.junit.jupiter.api.Assertions.assertEquals;
34 import static org.junit.jupiter.api.Assertions.assertFalse;
35 import static org.junit.jupiter.api.Assertions.assertTrue;
36
37
38
39
40 class FieldDerivativeStructureComplexTest extends FieldDerivativeStructureAbstractTest<Complex> {
41
42 @Override
43 protected Field<Complex> getField() {
44 return ComplexField.getInstance();
45 }
46
47 @Override
48 @Test
49 public void testComposeField() {
50 doTestComposeField(new double[] { 1.0e-100, 5.0e-14, 2.0e-13, 3.0e-13, 2.0e-13, 1.0e-100 });
51 }
52
53 @Override
54 @Test
55 public void testComposePrimitive() {
56 doTestComposePrimitive(new double[] { 1.0e-100, 5.0e-14, 2.0e-13, 3.0e-13, 2.0e-13, 1.0e-100 });
57 }
58
59 @Override
60 @Test
61 public void testHypotNoOverflow() {
62 doTestHypotNoOverflow(180);
63 }
64
65 @Override
66 @Test
67 public void testLinearCombinationReference() {
68 doTestLinearCombinationReference(x -> build(x), 4.8e-16, 1.0);
69 }
70
71 @Override
72 @Test
73 public void testLinearCombination1DSDS() {
74 doTestLinearCombination1DSDS(1.0e-15);
75 }
76
77 @Override
78 @Test
79 public void testLinearCombination1FieldDS() {
80 doTestLinearCombination1FieldDS(1.0e-15);
81 }
82
83 @Override
84 @Test
85 public void testLinearCombination1DoubleDS() {
86 doTestLinearCombination1DoubleDS(1.0e-15);
87 }
88
89 @Override
90 @Test
91 public void testAtan2() {
92 double[] epsilon = new double[] { 9.0e-16, 3.0e-15, 2.9e-14, 1.0e-12, 8.0e-11 };
93 for (int maxOrder = 0; maxOrder < 5; ++maxOrder) {
94 final FDSFactory<Complex> factory = buildFactory(2, maxOrder);
95 for (double x = -1.7; x < 2; x += 0.2) {
96 FieldDerivativeStructure<Complex> dsX = factory.variable(0, x);
97 for (double y = -1.7; y < 2; y += 0.2) {
98 FieldDerivativeStructure<Complex> dsY = factory.variable(1, y);
99 FieldDerivativeStructure<Complex> atan2 = FieldDerivativeStructure.atan2(dsY, dsX);
100 FieldDerivativeStructure<Complex> ref = dsY.divide(dsX).atan();
101 if (x < 0) {
102 ref = (y < 0) ? ref.subtract(FastMath.PI) : ref.add(FastMath.PI);
103 }
104 double fullTurns = MathUtils.normalizeAngle(atan2.getValue().getReal(), ref.getValue().getReal()) - atan2.getValue().getReal();
105 atan2 = atan2.add(fullTurns);
106 FieldDerivativeStructure<Complex> zero = atan2.subtract(ref);
107 for (int n = 0; n <= maxOrder; ++n) {
108 for (int m = 0; m <= maxOrder; ++m) {
109 if (n + m <= maxOrder) {
110 assertEquals(0, zero.getPartialDerivative(n, m).getReal(), epsilon[n + m]);
111 }
112 }
113 }
114 }
115 }
116 }
117 }
118
119 @Override
120 @Test
121 public void testAtan2SpecialCases() {
122 assertTrue(build(+0.0).atan2(build(+0.0)).isNaN());
123 assertTrue(build(-0.0).atan2(build(+0.0)).isNaN());
124 assertTrue(build(+0.0).atan2(build(-0.0)).isNaN());
125 assertTrue(build(-0.0).atan2(build(-0.0)).isNaN());
126 }
127
128 @Test
129 public void testAtan2SpecialCasesDerivatives() {
130
131 final FDSFactory<Complex> factory = buildFactory(2, 2);
132 FieldDerivativeStructure<Complex> pp =
133 FieldDerivativeStructure.atan2(factory.variable(1, buildScalar(+0.0)), factory.variable(1, buildScalar(+0.0)));
134 assertTrue(pp.getValue().isNaN());
135
136 FieldDerivativeStructure<Complex> pn =
137 FieldDerivativeStructure.atan2(factory.variable(1, buildScalar(+0.0)), factory.variable(1, buildScalar(-0.0)));
138 assertTrue(pn.getValue().isNaN());
139
140 FieldDerivativeStructure<Complex> np =
141 FieldDerivativeStructure.atan2(factory.variable(1, buildScalar(-0.0)), factory.variable(1, buildScalar(+0.0)));
142 assertTrue(np.getValue().isNaN());
143
144 FieldDerivativeStructure<Complex> nn =
145 FieldDerivativeStructure.atan2(factory.variable(1, buildScalar(-0.0)), factory.variable(1, buildScalar(-0.0)));
146 assertTrue(nn.getValue().isNaN());
147
148 }
149
150 @Override
151 @Test
152 public void testPowDoubleDS() {
153 for (int maxOrder = 1; maxOrder < 5; ++maxOrder) {
154
155 final FDSFactory<Complex> factory = buildFactory(3, maxOrder);
156 FieldDerivativeStructure<Complex> x = factory.variable(0, 0.1);
157 FieldDerivativeStructure<Complex> y = factory.variable(1, 0.2);
158 FieldDerivativeStructure<Complex> z = factory.variable(2, 0.3);
159 List<FieldDerivativeStructure<Complex>> list = Arrays.asList(x, y, z,
160 x.add(y).add(z),
161 x.multiply(y).multiply(z));
162
163 for (FieldDerivativeStructure<Complex> ds : list) {
164
165 for (double a : new double[] { 0.0, 0.1, 1.0, 2.0, 5.0 }) {
166 FieldDerivativeStructure<Complex> reference = (a == 0) ?
167 x.getField().getZero() :
168 factory.constant(a).pow(ds);
169 FieldDerivativeStructure<Complex> result = FieldDerivativeStructure.pow(a, ds);
170 checkEquals(reference, result, 2.0e-14 * FastMath.abs(reference.getReal()));
171 }
172
173 }
174
175
176 FieldDerivativeStructure<Complex> negEvenInteger = FieldDerivativeStructure.pow(-2.0, factory.variable(0, 2.0));
177 assertEquals(4.0, negEvenInteger.getReal(), 1.0e-15);
178 assertTrue(Double.isNaN(negEvenInteger.getPartialDerivative(1, 0, 0).getReal()));
179 FieldDerivativeStructure<Complex> negOddInteger = FieldDerivativeStructure.pow(-2.0, factory.variable(0, 3.0));
180 assertEquals(-8.0, negOddInteger.getReal(), 1.0e-15);
181 assertTrue(Double.isNaN(negOddInteger.getPartialDerivative(1, 0, 0).getReal()));
182 FieldDerivativeStructure<Complex> negNonInteger = FieldDerivativeStructure.pow(-2.0, factory.variable(0, 2.001));
183 assertEquals(4.0027537969708465469, negNonInteger.getValue().getReal(), 2.0e-15);
184 assertEquals(0.012575063293019489803, negNonInteger.getValue().getImaginary(), 2.0e-15);
185 assertTrue(Double.isNaN(negNonInteger.getPartialDerivative(1, 0, 0).getReal()));
186
187 FieldDerivativeStructure<Complex> zeroNeg = FieldDerivativeStructure.pow(0.0, factory.variable(0, -1.0));
188 assertTrue(Double.isNaN(zeroNeg.getReal()));
189 assertTrue(Double.isNaN(zeroNeg.getPartialDerivative(1, 0, 0).getReal()));
190 FieldDerivativeStructure<Complex> posNeg = FieldDerivativeStructure.pow(2.0, factory.variable(0, -2.0));
191 assertEquals(1.0 / 4.0, posNeg.getReal(), 1.0e-15);
192 assertEquals(FastMath.log(2.0) / 4.0, posNeg.getPartialDerivative(1, 0, 0).getReal(), 1.0e-15);
193
194
195 FieldDerivativeStructure<Complex> zeroDsZeroDouble = factory.variable(0, 0.0).pow(0.0);
196 boolean first = true;
197 for (final Complex d : zeroDsZeroDouble.getAllDerivatives()) {
198 if (first) {
199 assertEquals(1.0, d.getReal(), Precision.EPSILON);
200 first = false;
201 } else {
202 assertEquals(0.0, d.getReal(), Precision.SAFE_MIN);
203 }
204 }
205 FieldDerivativeStructure<Complex> zeroDsZeroInt = factory.variable(0, 0.0).pow(0);
206 first = true;
207 for (final Complex d : zeroDsZeroInt.getAllDerivatives()) {
208 if (first) {
209 assertEquals(1.0, d.getReal(), Precision.EPSILON);
210 first = false;
211 } else {
212 assertEquals(0.0, d.getReal(), Precision.SAFE_MIN);
213 }
214 }
215
216
217 FieldDerivativeStructure<Complex> u = factory.variable(1, -0.0).pow(0.25);
218 for (int i0 = 0; i0 <= maxOrder; ++i0) {
219 for (int i1 = 0; i1 <= maxOrder; ++i1) {
220 for (int i2 = 0; i2 <= maxOrder; ++i2) {
221 if (i0 + i1 + i2 <= maxOrder) {
222 assertEquals(0.0, u.getPartialDerivative(i0, i1, i2).getReal(), 1.0e-10);
223 }
224 }
225 }
226 }
227 }
228
229 }
230
231 @Override
232 @Test
233 public void testLog10() {
234 for (double x = -0.9; x < 0.9; x += 0.05) {
235 if (x <= 0) {
236 assertTrue(Double.isNaN(FastMath.log10(x)));
237 assertFalse(build(x).log10().getValue().isNaN());
238 } else {
239 checkRelative(FastMath.log10(x), build(x).log10());
240 }
241 }
242 }
243
244 @Override
245 @Test
246 public void testRootN() {
247 for (double x = -0.9; x < 0.9; x += 0.05) {
248 for (int n = 1; n < 5; ++n) {
249 if (x < 0) {
250
251 final double doubleRoot = new Binary64(x).rootN(n).getReal();
252 if (n % 2 == 0) {
253 assertTrue(Double.isNaN(doubleRoot));
254 } else {
255 assertTrue(doubleRoot < 0);
256 }
257 assertEquals(FastMath.PI / n, build(x).rootN(n).getValue().getArgument(), 1.0e-15);
258 } else {
259 checkRelative(FastMath.pow(x, 1.0 / n), build(x).rootN(n));
260 }
261 }
262 }
263 }
264
265 @Override
266 @Test
267 public void testRootNSingularity() {
268 doTestRootNSingularity(false);
269 }
270
271 @Override
272 @Test
273 public void testCbrt() {
274 for (double x = -0.9; x < 0.9; x += 0.05) {
275 if ( x < 0) {
276
277 assertTrue(FastMath.cbrt(x) < 0);
278 assertEquals(FastMath.PI / 3, build(x).cbrt().getValue().getArgument(), 1.0e-15);
279 } else {
280 checkRelative(FastMath.cbrt(x), build(x).cbrt());
281 }
282 }
283 }
284
285 @Test
286 void testCbrtComplex() {
287 Complex z = new Complex(15, 2);
288 UnitTestUtils.customAssertEquals(z, z.square().multiply(z).cbrt(), 1.0e-14);
289 Complex branchCutPlus = new Complex(-8.0, +0.0);
290 Complex cbrtPlus = branchCutPlus.cbrt();
291 UnitTestUtils.customAssertEquals(branchCutPlus, cbrtPlus.multiply(cbrtPlus).multiply(cbrtPlus), 1.0e-14);
292 assertEquals(1.0, cbrtPlus.getReal(), 1.0e-15);
293 assertEquals(FastMath.sqrt(3.0), cbrtPlus.getImaginary(), 1.0e-15);
294 Complex branchCutMinus = new Complex(-8.0, -0.0);
295 Complex cbrtMinus = branchCutMinus.cbrt();
296 UnitTestUtils.customAssertEquals(branchCutMinus, cbrtMinus.multiply(cbrtMinus).multiply(cbrtMinus), 1.0e-14);
297 assertEquals(1.0, cbrtMinus.getReal(), 1.0e-15);
298 assertEquals(-FastMath.sqrt(3.0), cbrtMinus.getImaginary(), 1.0e-15);
299 }
300
301 @Override
302 @Test
303 public void testPowField() {
304 for (double x = -0.9; x < 0.9; x += 0.05) {
305 for (double y = 0.1; y < 4; y += 0.2) {
306 if ( x < 0) {
307
308 assertTrue(Double.isNaN(FastMath.pow(x, y)));
309 assertFalse(build(x).pow(build(y)).isNaN());
310 } else {
311 checkRelative(FastMath.pow(x, y), build(x).pow(build(y)));
312 }
313 }
314 }
315 }
316
317 @Override
318 @Test
319 public void testPowDouble() {
320 for (double x = -0.9; x < 0.9; x += 0.05) {
321 for (double y = 0.1; y < 4; y += 0.2) {
322 if ( x < 0) {
323
324 assertTrue(Double.isNaN(FastMath.pow(x, y)));
325 assertFalse(build(x).pow(y).isNaN());
326 } else {
327 checkRelative(FastMath.pow(x, y), build(x).pow(y));
328 }
329 }
330 }
331 }
332
333 }