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