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.differentiation;
24
25 import org.hipparchus.CalculusFieldElementAbstractTest;
26 import org.hipparchus.Field;
27 import org.hipparchus.UnitTestUtils;
28 import org.hipparchus.analysis.CalculusFieldMultivariateFunction;
29 import org.hipparchus.analysis.CalculusFieldMultivariateVectorFunction;
30 import org.hipparchus.analysis.polynomials.PolynomialFunction;
31 import org.hipparchus.exception.LocalizedCoreFormats;
32 import org.hipparchus.exception.MathIllegalArgumentException;
33 import org.hipparchus.random.RandomGenerator;
34 import org.hipparchus.random.Well1024a;
35 import org.hipparchus.random.Well19937a;
36 import org.hipparchus.util.ArithmeticUtils;
37 import org.hipparchus.util.Binary64Field;
38 import org.hipparchus.util.CombinatoricsUtils;
39 import org.hipparchus.util.FastMath;
40 import org.hipparchus.util.FieldSinCos;
41 import org.hipparchus.util.FieldSinhCosh;
42 import org.hipparchus.util.Precision;
43 import org.junit.jupiter.api.Test;
44
45 import java.util.ArrayList;
46 import java.util.Arrays;
47 import java.util.HashMap;
48 import java.util.List;
49 import java.util.Map;
50 import java.util.stream.IntStream;
51
52 import static org.junit.jupiter.api.Assertions.assertArrayEquals;
53 import static org.junit.jupiter.api.Assertions.assertEquals;
54 import static org.junit.jupiter.api.Assertions.assertNotEquals;
55 import static org.junit.jupiter.api.Assertions.assertSame;
56 import static org.junit.jupiter.api.Assertions.assertThrows;
57 import static org.junit.jupiter.api.Assertions.assertTrue;
58 import static org.junit.jupiter.api.Assertions.fail;
59
60
61
62
63 public class DerivativeStructureTest extends CalculusFieldElementAbstractTest<DerivativeStructure> {
64
65 @Override
66 protected DerivativeStructure build(final double x) {
67 return new DSFactory(2, 1).variable(0, x);
68 }
69
70 @Test
71 void testWrongVariableIndex() {
72 assertThrows(MathIllegalArgumentException.class, () -> {
73 new DSFactory(3, 1).variable(3, 1.0);
74 });
75 }
76
77 @Test
78 void testMissingOrders() {
79 assertThrows(MathIllegalArgumentException.class, () -> {
80 new DSFactory(3, 1).variable(0, 1.0).getPartialDerivative(0, 1);
81 });
82 }
83
84 @Test
85 void testTooLargeOrder() {
86 assertThrows(MathIllegalArgumentException.class, () -> {
87 new DSFactory(3, 1).variable(0, 1.0).getPartialDerivative(1, 1, 2);
88 });
89 }
90
91 @Test
92 void testVariableWithoutDerivative0() {
93 DerivativeStructure v = new DSFactory(1, 0).variable(0, 1.0);
94 assertEquals(1.0, v.getValue(), 1.0e-15);
95 }
96
97 @Test
98 void testVariableWithoutDerivative1() {
99 assertThrows(MathIllegalArgumentException.class, () -> {
100 DerivativeStructure v = new DSFactory(1, 0).variable(0, 1.0);
101 assertEquals(1.0, v.getPartialDerivative(1), 1.0e-15);
102 });
103 }
104
105 @Test
106 void testVariable() {
107 for (int maxOrder = 1; maxOrder < 5; ++maxOrder) {
108 DSFactory factory = new DSFactory(3, maxOrder);
109 checkF0F1(factory.variable(0, 1.0), 1.0, 1.0, 0.0, 0.0);
110 checkF0F1(factory.variable(1, 2.0), 2.0, 0.0, 1.0, 0.0);
111 checkF0F1(factory.variable(2, 3.0), 3.0, 0.0, 0.0, 1.0);
112 }
113 }
114
115 @Test
116 void testConstant() {
117 for (int maxOrder = 1; maxOrder < 5; ++maxOrder) {
118 DSFactory factory = new DSFactory(3, maxOrder);
119 checkF0F1(factory.constant(FastMath.PI), FastMath.PI, 0.0, 0.0, 0.0);
120 }
121 }
122
123 @Test
124 void testPrimitiveAdd() {
125 for (int maxOrder = 1; maxOrder < 5; ++maxOrder) {
126 DSFactory factory = new DSFactory(3, maxOrder);
127 checkF0F1(factory.variable(0, 1.0).add(5), 6.0, 1.0, 0.0, 0.0);
128 checkF0F1(factory.variable(1, 2.0).add(5), 7.0, 0.0, 1.0, 0.0);
129 checkF0F1(factory.variable(2, 3.0).add(5), 8.0, 0.0, 0.0, 1.0);
130 }
131 }
132
133 @Test
134 void testAdd() {
135 for (int maxOrder = 1; maxOrder < 5; ++maxOrder) {
136 DSFactory factory = new DSFactory(3, maxOrder);
137 DerivativeStructure x = factory.variable(0, 1.0);
138 DerivativeStructure y = factory.variable(1, 2.0);
139 DerivativeStructure z = factory.variable(2, 3.0);
140 DerivativeStructure xyz = x.add(y.add(z));
141 checkF0F1(xyz, x.getValue() + y.getValue() + z.getValue(), 1.0, 1.0, 1.0);
142 }
143 }
144
145 @Test
146 void testPrimitiveSubtract() {
147 for (int maxOrder = 1; maxOrder < 5; ++maxOrder) {
148 DSFactory factory = new DSFactory(3, maxOrder);
149 checkF0F1(factory.variable(0, 1.0).subtract(5), -4.0, 1.0, 0.0, 0.0);
150 checkF0F1(factory.variable(1, 2.0).subtract(5), -3.0, 0.0, 1.0, 0.0);
151 checkF0F1(factory.variable(2, 3.0).subtract(5), -2.0, 0.0, 0.0, 1.0);
152 }
153 }
154
155 @Test
156 void testSubtract() {
157 for (int maxOrder = 1; maxOrder < 5; ++maxOrder) {
158 DSFactory factory = new DSFactory(3, maxOrder);
159 DerivativeStructure x = factory.variable(0, 1.0);
160 DerivativeStructure y = factory.variable(1, 2.0);
161 DerivativeStructure z = factory.variable(2, 3.0);
162 DerivativeStructure xyz = x.subtract(y.subtract(z));
163 checkF0F1(xyz, x.getValue() - (y.getValue() - z.getValue()), 1.0, -1.0, 1.0);
164 }
165 }
166
167 @Test
168 void testPrimitiveMultiply() {
169 for (int maxOrder = 1; maxOrder < 5; ++maxOrder) {
170 DSFactory factory = new DSFactory(3, maxOrder);
171 checkF0F1(factory.variable(0, 1.0).multiply(5), 5.0, 5.0, 0.0, 0.0);
172 checkF0F1(factory.variable(1, 2.0).multiply(5), 10.0, 0.0, 5.0, 0.0);
173 checkF0F1(factory.variable(2, 3.0).multiply(5), 15.0, 0.0, 0.0, 5.0);
174 }
175 }
176
177 @Test
178 void testMultiply() {
179 for (int maxOrder = 1; maxOrder < 5; ++maxOrder) {
180 DSFactory factory = new DSFactory(3, maxOrder);
181 DerivativeStructure x = factory.variable(0, 1.0);
182 DerivativeStructure y = factory.variable(1, 2.0);
183 DerivativeStructure z = factory.variable(2, 3.0);
184 DerivativeStructure xyz = x.multiply(y.multiply(z));
185 for (int i = 0; i <= maxOrder; ++i) {
186 for (int j = 0; j <= maxOrder; ++j) {
187 for (int k = 0; k <= maxOrder; ++k) {
188 if (i + j + k <= maxOrder) {
189 assertEquals((i == 0 ? x.getValue() : (i == 1 ? 1.0 : 0.0)) *
190 (j == 0 ? y.getValue() : (j == 1 ? 1.0 : 0.0)) *
191 (k == 0 ? z.getValue() : (k == 1 ? 1.0 : 0.0)),
192 xyz.getPartialDerivative(i, j, k),
193 1.0e-15);
194 }
195 }
196 }
197 }
198 }
199 }
200
201 @Test
202 void testNegate() {
203 for (int maxOrder = 1; maxOrder < 5; ++maxOrder) {
204 DSFactory factory = new DSFactory(3, maxOrder);
205 checkF0F1(factory.variable(0, 1.0).negate(), -1.0, -1.0, 0.0, 0.0);
206 checkF0F1(factory.variable(1, 2.0).negate(), -2.0, 0.0, -1.0, 0.0);
207 checkF0F1(factory.variable(2, 3.0).negate(), -3.0, 0.0, 0.0, -1.0);
208 }
209 }
210
211 @Test
212 void testReciprocal() {
213 for (double x = 0.1; x < 1.2; x += 0.1) {
214 DerivativeStructure r = new DSFactory(1, 6).variable(0, x).reciprocal();
215 assertEquals(1 / x, r.getValue(), 1.0e-15);
216 for (int i = 1; i < r.getOrder(); ++i) {
217 double expected = ArithmeticUtils.pow(-1, i) * CombinatoricsUtils.factorial(i) /
218 FastMath.pow(x, i + 1);
219 assertEquals(expected, r.getPartialDerivative(i), 1.0e-15 * FastMath.abs(expected));
220 }
221 }
222 }
223
224 @Test
225 void testPow() {
226 for (int maxOrder = 1; maxOrder < 5; ++maxOrder) {
227 DSFactory factory = new DSFactory(3, maxOrder);
228 for (int n = 0; n < 10; ++n) {
229
230 DerivativeStructure x = factory.variable(0, 1.0);
231 DerivativeStructure y = factory.variable(1, 2.0);
232 DerivativeStructure z = factory.variable(2, 3.0);
233 List<DerivativeStructure> list = Arrays.asList(x, y, z,
234 x.add(y).add(z),
235 x.multiply(y).multiply(z));
236
237 if (n == 0) {
238 for (DerivativeStructure ds : list) {
239 checkEquals(ds.getField().getOne(), FastMath.pow(ds, n), 1.0e-15);
240 }
241 } else if (n == 1) {
242 for (DerivativeStructure ds : list) {
243 checkEquals(ds, FastMath.pow(ds, n), 1.0e-15);
244 }
245 } else {
246 for (DerivativeStructure ds : list) {
247 DerivativeStructure p = ds.getField().getOne();
248 for (int i = 0; i < n; ++i) {
249 p = p.multiply(ds);
250 }
251 checkEquals(p, FastMath.pow(ds, n), 1.0e-15);
252 }
253 }
254 }
255 }
256 }
257
258 @Test
259 void testPowDoubleDS() {
260 for (int maxOrder = 1; maxOrder < 5; ++maxOrder) {
261
262 DSFactory factory = new DSFactory(3, maxOrder);
263 DerivativeStructure x = factory.variable(0, 0.1);
264 DerivativeStructure y = factory.variable(1, 0.2);
265 DerivativeStructure z = factory.variable(2, 0.3);
266 List<DerivativeStructure> list = Arrays.asList(x, y, z,
267 x.add(y).add(z),
268 x.multiply(y).multiply(z));
269
270 for (DerivativeStructure ds : list) {
271
272 for (double a : new double[] { 0.0, 0.1, 1.0, 2.0, 5.0 }) {
273 DerivativeStructure reference = (a == 0) ?
274 x.getField().getZero() :
275 FastMath.pow(new DSFactory(3, maxOrder).constant(a), ds);
276 DerivativeStructure result = DerivativeStructure.pow(a, ds);
277 checkEquals(reference, result, 1.0e-15);
278 }
279
280 }
281
282
283 DerivativeStructure negEvenInteger = DerivativeStructure.pow(-2.0, factory.variable(0, 2.0));
284 assertEquals(4.0, negEvenInteger.getValue(), 1.0e-15);
285 assertTrue(Double.isNaN(negEvenInteger.getPartialDerivative(1, 0, 0)));
286 DerivativeStructure negOddInteger = DerivativeStructure.pow(-2.0, factory.variable(0, 3.0));
287 assertEquals(-8.0, negOddInteger.getValue(), 1.0e-15);
288 assertTrue(Double.isNaN(negOddInteger.getPartialDerivative(1, 0, 0)));
289 DerivativeStructure negNonInteger = DerivativeStructure.pow(-2.0, factory.variable(0, 2.001));
290 assertTrue(Double.isNaN(negNonInteger.getValue()));
291 assertTrue(Double.isNaN(negNonInteger.getPartialDerivative(1, 0, 0)));
292
293 DerivativeStructure zeroNeg = DerivativeStructure.pow(0.0, factory.variable(0, -1.0));
294 assertTrue(Double.isNaN(zeroNeg.getValue()));
295 assertTrue(Double.isNaN(zeroNeg.getPartialDerivative(1, 0, 0)));
296 DerivativeStructure posNeg = DerivativeStructure.pow(2.0, factory.variable(0, -2.0));
297 assertEquals(1.0 / 4.0, posNeg.getValue(), 1.0e-15);
298 assertEquals(FastMath.log(2.0) / 4.0, posNeg.getPartialDerivative(1, 0, 0), 1.0e-15);
299
300
301 DerivativeStructure zeroZero = DerivativeStructure.pow(0.0, factory.variable(0, 0.0));
302
303
304 assertEquals(1.0, zeroZero.getValue(), 1.0e-15);
305 assertEquals(Double.NEGATIVE_INFINITY, zeroZero.getPartialDerivative(1, 0, 0), 1.0e-15);
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328 assertTrue(Double.isNaN(zeroZero.getPartialDerivative(0, 1, 0)));
329 assertTrue(Double.isNaN(zeroZero.getPartialDerivative(0, 0, 1)));
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346 if (maxOrder > 1) {
347 assertTrue(Double.isNaN(zeroZero.getPartialDerivative(2, 0, 0)));
348 assertTrue(Double.isNaN(zeroZero.getPartialDerivative(0, 2, 0)));
349 assertTrue(Double.isNaN(zeroZero.getPartialDerivative(0, 0, 2)));
350 assertTrue(Double.isNaN(zeroZero.getPartialDerivative(1, 1, 0)));
351 assertTrue(Double.isNaN(zeroZero.getPartialDerivative(0, 1, 1)));
352 assertTrue(Double.isNaN(zeroZero.getPartialDerivative(1, 1, 0)));
353 }
354
355
356 DerivativeStructure zeroDsZeroDouble = factory.variable(0, 0.0).pow(0.0);
357 boolean first = true;
358 for (final double d : zeroDsZeroDouble.getAllDerivatives()) {
359 if (first) {
360 assertEquals(1.0, d, Precision.EPSILON);
361 first = false;
362 } else {
363 assertEquals(0.0, d, Precision.SAFE_MIN);
364 }
365 }
366 DerivativeStructure zeroDsZeroInt = factory.variable(0, 0.0).pow(0);
367 first = true;
368 for (final double d : zeroDsZeroInt.getAllDerivatives()) {
369 if (first) {
370 assertEquals(1.0, d, Precision.EPSILON);
371 first = false;
372 } else {
373 assertEquals(0.0, d, Precision.SAFE_MIN);
374 }
375 }
376
377
378 DerivativeStructure u = factory.variable(1, -0.0).pow(0.25);
379 for (int i0 = 0; i0 <= maxOrder; ++i0) {
380 for (int i1 = 0; i1 <= maxOrder; ++i1) {
381 for (int i2 = 0; i2 <= maxOrder; ++i2) {
382 if (i0 + i1 + i2 <= maxOrder) {
383 assertEquals(0.0, u.getPartialDerivative(i0, i1, i2), 1.0e-10);
384 }
385 }
386 }
387 }
388 }
389
390 }
391
392 @Test
393 public void testScalb() {
394 for (int maxOrder = 1; maxOrder < 5; ++maxOrder) {
395 DSFactory factory = new DSFactory(3, maxOrder);
396 DerivativeStructure x = factory.variable(0, 1.0);
397 DerivativeStructure y = factory.variable(1, 2.0);
398 DerivativeStructure z = factory.variable(2, 3.0);
399 DerivativeStructure xyz = x.multiply(y.multiply(z));
400 double s = 0.125;
401 for (int n = -3; n <= 3; ++n) {
402 DerivativeStructure scaled = xyz.scalb(n);
403 for (int i = 0; i <= maxOrder; ++i) {
404 for (int j = 0; j <= maxOrder; ++j) {
405 for (int k = 0; k <= maxOrder; ++k) {
406 if (i + j + k <= maxOrder) {
407 assertEquals((i == 0 ? x.getValue() : (i == 1 ? 1.0 : 0.0)) *
408 (j == 0 ? y.getValue() : (j == 1 ? 1.0 : 0.0)) *
409 (k == 0 ? z.getValue() : (k == 1 ? 1.0 : 0.0)) *
410 s,
411 scaled.getPartialDerivative(i, j, k),
412 1.0e-15);
413 }
414 }
415 }
416 }
417 s *= 2;
418 }
419 }
420 }
421
422 @Test
423 public void testUlp() {
424 final RandomGenerator random = new Well19937a(0x85d201920b5be954l);
425 for (int k = 0; k < 10000; ++k) {
426 int maxOrder = 1 + random.nextInt(5);
427 DSFactory factory = new DSFactory(3, maxOrder);
428 DerivativeStructure x = factory.variable(0, FastMath.scalb(2 * random.nextDouble() - 1, random.nextInt(600) - 300));
429 DerivativeStructure y = factory.variable(1, FastMath.scalb(2 * random.nextDouble() - 1, random.nextInt(600) - 300));
430 DerivativeStructure z = factory.variable(2, FastMath.scalb(2 * random.nextDouble() - 1, random.nextInt(600) - 300));
431 DerivativeStructure xyz = x.multiply(y.multiply(z));
432 DerivativeStructure ulp = xyz.ulp();
433 boolean first = true;
434 for (double d : ulp.getAllDerivatives()) {
435 assertEquals(first ? FastMath.ulp(xyz.getValue()) : 0.0, d, 1.0e-15 * FastMath.ulp(xyz.getValue()));
436 first = false;
437 }
438 }
439 }
440
441 @Test
442 void testExpression() {
443 DSFactory factory = new DSFactory(3, 5);
444 double epsilon = 2.5e-13;
445 for (double x = 0; x < 2; x += 0.2) {
446 DerivativeStructure dsX = factory.variable(0, x);
447 for (double y = 0; y < 2; y += 0.2) {
448 DerivativeStructure dsY = factory.variable(1, y);
449 for (double z = 0; z >- 2; z -= 0.2) {
450 DerivativeStructure dsZ = factory.variable(2, z);
451
452
453 DerivativeStructure ds =
454 dsX.linearCombination(1, dsX,
455 5, dsX.multiply(dsY),
456 -2, dsZ,
457 1, dsX.linearCombination(8, dsZ.multiply(dsX),
458 -1, dsY).pow(3));
459 DerivativeStructure dsOther =
460 dsX.linearCombination(1, dsX,
461 5, dsX.multiply(dsY),
462 -2, dsZ).add(dsX.linearCombination(8, dsZ.multiply(dsX),
463 -1, dsY).pow(3));
464 double f = x + 5 * x * y - 2 * z + FastMath.pow(8 * z * x - y, 3);
465 assertEquals(f, ds.getValue(),
466 FastMath.abs(epsilon * f));
467 assertEquals(f, dsOther.getValue(),
468 FastMath.abs(epsilon * f));
469
470
471 double dfdx = 1 + 5 * y + 24 * z * FastMath.pow(8 * z * x - y, 2);
472 assertEquals(dfdx, ds.getPartialDerivative(1, 0, 0),
473 FastMath.abs(epsilon * dfdx));
474 assertEquals(dfdx, dsOther.getPartialDerivative(1, 0, 0),
475 FastMath.abs(epsilon * dfdx));
476
477
478 double dfdxdy = 5 + 48 * z * (y - 8 * z * x);
479 assertEquals(dfdxdy, ds.getPartialDerivative(1, 1, 0),
480 FastMath.abs(epsilon * dfdxdy));
481 assertEquals(dfdxdy, dsOther.getPartialDerivative(1, 1, 0),
482 FastMath.abs(epsilon * dfdxdy));
483
484
485 double dfdxdydz = 48 * (y - 16 * z * x);
486 assertEquals(dfdxdydz, ds.getPartialDerivative(1, 1, 1),
487 FastMath.abs(epsilon * dfdxdydz));
488 assertEquals(dfdxdydz, dsOther.getPartialDerivative(1, 1, 1),
489 FastMath.abs(epsilon * dfdxdydz));
490
491 }
492
493 }
494 }
495 }
496
497 @Test
498 void testCompositionOneVariableX() {
499 double epsilon = 1.0e-13;
500 for (int maxOrder = 0; maxOrder < 5; ++maxOrder) {
501 DSFactory factory = new DSFactory(1, maxOrder);
502 for (double x = 0.1; x < 1.2; x += 0.1) {
503 DerivativeStructure dsX = factory.variable(0, x);
504 for (double y = 0.1; y < 1.2; y += 0.1) {
505 DerivativeStructure dsY = factory.constant(y);
506 DerivativeStructure f = dsX.divide(dsY).sqrt();
507 double f0 = FastMath.sqrt(x / y);
508 assertEquals(f0, f.getValue(), FastMath.abs(epsilon * f0));
509 if (f.getOrder() > 0) {
510 double f1 = 1 / (2 * FastMath.sqrt(x * y));
511 assertEquals(f1, f.getPartialDerivative(1), FastMath.abs(epsilon * f1));
512 if (f.getOrder() > 1) {
513 double f2 = -f1 / (2 * x);
514 assertEquals(f2, f.getPartialDerivative(2), FastMath.abs(epsilon * f2));
515 if (f.getOrder() > 2) {
516 double f3 = (f0 + x / (2 * y * f0)) / (4 * x * x * x);
517 assertEquals(f3, f.getPartialDerivative(3), FastMath.abs(epsilon * f3));
518 }
519 }
520 }
521 }
522 }
523 }
524 }
525
526 @Test
527 void testTrigo() {
528 double epsilon = 2.0e-12;
529 for (int maxOrder = 0; maxOrder < 5; ++maxOrder) {
530 DSFactory factory = new DSFactory(3, maxOrder);
531 for (double x = 0.1; x < 1.2; x += 0.1) {
532 DerivativeStructure dsX = factory.variable(0, x);
533 for (double y = 0.1; y < 1.2; y += 0.1) {
534 DerivativeStructure dsY = factory.variable(1, y);
535 for (double z = 0.1; z < 1.2; z += 0.1) {
536 DerivativeStructure dsZ = factory.variable(2, z);
537 DerivativeStructure f = FastMath.sin(dsX.divide(FastMath.cos(dsY).add(FastMath.tan(dsZ))));
538 double a = FastMath.cos(y) + FastMath.tan(z);
539 double f0 = FastMath.sin(x / a);
540 assertEquals(f0, f.getValue(), FastMath.abs(epsilon * f0));
541 if (f.getOrder() > 0) {
542 double dfdx = FastMath.cos(x / a) / a;
543 assertEquals(dfdx, f.getPartialDerivative(1, 0, 0), FastMath.abs(epsilon * dfdx));
544 double dfdy = x * FastMath.sin(y) * dfdx / a;
545 assertEquals(dfdy, f.getPartialDerivative(0, 1, 0), FastMath.abs(epsilon * dfdy));
546 double cz = FastMath.cos(z);
547 double cz2 = cz * cz;
548 double dfdz = -x * dfdx / (a * cz2);
549 assertEquals(dfdz, f.getPartialDerivative(0, 0, 1), FastMath.abs(epsilon * dfdz));
550 if (f.getOrder() > 1) {
551 double df2dx2 = -(f0 / (a * a));
552 assertEquals(df2dx2, f.getPartialDerivative(2, 0, 0), FastMath.abs(epsilon * df2dx2));
553 double df2dy2 = x * FastMath.cos(y) * dfdx / a -
554 x * x * FastMath.sin(y) * FastMath.sin(y) * f0 / (a * a * a * a) +
555 2 * FastMath.sin(y) * dfdy / a;
556 assertEquals(df2dy2, f.getPartialDerivative(0, 2, 0), FastMath.abs(epsilon * df2dy2));
557 double c4 = cz2 * cz2;
558 double df2dz2 = x * (2 * a * (1 - a * cz * FastMath.sin(z)) * dfdx - x * f0 / a ) / (a * a * a * c4);
559 assertEquals(df2dz2, f.getPartialDerivative(0, 0, 2), FastMath.abs(epsilon * df2dz2));
560 double df2dxdy = dfdy / x - x * FastMath.sin(y) * f0 / (a * a * a);
561 assertEquals(df2dxdy, f.getPartialDerivative(1, 1, 0), FastMath.abs(epsilon * df2dxdy));
562 }
563 }
564 }
565 }
566 }
567 }
568 }
569
570 @Test
571 void testSqrtDefinition() {
572 double[] epsilon = new double[] { 5.0e-16, 5.0e-16, 2.7e-15, 5.7e-14, 2.0e-12 };
573 for (int maxOrder = 0; maxOrder < 5; ++maxOrder) {
574 DSFactory factory = new DSFactory(1, maxOrder);
575 for (double x = 0.1; x < 1.2; x += 0.001) {
576 DerivativeStructure dsX = factory.variable(0, x);
577 DerivativeStructure sqrt1 = dsX.pow(0.5);
578 DerivativeStructure sqrt2 = FastMath.sqrt(dsX);
579 DerivativeStructure zero = sqrt1.subtract(sqrt2);
580 for (int n = 0; n <= maxOrder; ++n) {
581 assertEquals(0, zero.getPartialDerivative(n), epsilon[n]);
582 }
583 }
584 }
585 }
586
587 @Test
588 void testRootNSingularity() {
589 for (int n = 2; n < 10; ++n) {
590 for (int maxOrder = 0; maxOrder < 12; ++maxOrder) {
591 DSFactory factory = new DSFactory(1, maxOrder);
592 DerivativeStructure dsZero = factory.variable(0, 0.0);
593 DerivativeStructure rootN = dsZero.rootN(n);
594 assertEquals(0.0, rootN.getValue(), 1.0e-20);
595 if (maxOrder > 0) {
596 assertTrue(Double.isInfinite(rootN.getPartialDerivative(1)));
597 assertTrue(rootN.getPartialDerivative(1) > 0);
598 for (int order = 2; order <= maxOrder; ++order) {
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618 assertTrue(Double.isNaN(rootN.getPartialDerivative(order)));
619 }
620 }
621
622
623
624
625 double[] gDerivatives = new double[ 1 + maxOrder];
626 gDerivatives[0] = 0.0;
627 for (int k = 1; k <= maxOrder; ++k) {
628 gDerivatives[k] = FastMath.pow(-1.0, k + 1);
629 }
630 DerivativeStructure correctRoot = factory.build(gDerivatives).rootN(n);
631 assertEquals(0.0, correctRoot.getValue(), 1.0e-20);
632 if (maxOrder > 0) {
633 assertTrue(Double.isInfinite(correctRoot.getPartialDerivative(1)));
634 assertTrue(correctRoot.getPartialDerivative(1) > 0);
635 for (int order = 2; order <= maxOrder; ++order) {
636 assertTrue(Double.isInfinite(correctRoot.getPartialDerivative(order)));
637 if ((order % 2) == 0) {
638 assertTrue(correctRoot.getPartialDerivative(order) < 0);
639 } else {
640 assertTrue(correctRoot.getPartialDerivative(order) > 0);
641 }
642 }
643 }
644
645 }
646
647 }
648
649 }
650
651 @Test
652 void testSqrtPow2() {
653 double[] epsilon = new double[] { 1.0e-16, 3.0e-16, 2.0e-15, 6.0e-14, 6.0e-12 };
654 for (int maxOrder = 0; maxOrder < 5; ++maxOrder) {
655 DSFactory factory = new DSFactory(1, maxOrder);
656 for (double x = 0.1; x < 1.2; x += 0.001) {
657 DerivativeStructure dsX = factory.variable(0, x);
658 DerivativeStructure rebuiltX = dsX.multiply(dsX).sqrt();
659 DerivativeStructure zero = rebuiltX.subtract(dsX);
660 for (int n = 0; n <= maxOrder; ++n) {
661 assertEquals(0.0, zero.getPartialDerivative(n), epsilon[n]);
662 }
663 }
664 }
665 }
666
667 @Test
668 void testCbrtDefinition() {
669 double[] epsilon = new double[] { 4.0e-16, 9.0e-16, 6.0e-15, 2.0e-13, 4.0e-12 };
670 for (int maxOrder = 0; maxOrder < 5; ++maxOrder) {
671 DSFactory factory = new DSFactory(1, maxOrder);
672 for (double x = 0.1; x < 1.2; x += 0.001) {
673 DerivativeStructure dsX = factory.variable(0, x);
674 DerivativeStructure cbrt1 = dsX.pow(1.0 / 3.0);
675 DerivativeStructure cbrt2 = FastMath.cbrt(dsX);
676 DerivativeStructure zero = cbrt1.subtract(cbrt2);
677 for (int n = 0; n <= maxOrder; ++n) {
678 assertEquals(0, zero.getPartialDerivative(n), epsilon[n]);
679 }
680 }
681 }
682 }
683
684 @Test
685 void testCbrtPow3() {
686 double[] epsilon = new double[] { 1.0e-16, 5.0e-16, 8.0e-15, 3.0e-13, 4.0e-11 };
687 for (int maxOrder = 0; maxOrder < 5; ++maxOrder) {
688 DSFactory factory = new DSFactory(1, maxOrder);
689 for (double x = 0.1; x < 1.2; x += 0.001) {
690 DerivativeStructure dsX = factory.variable(0, x);
691 DerivativeStructure rebuiltX = dsX.multiply(dsX.multiply(dsX)).cbrt();
692 DerivativeStructure zero = rebuiltX.subtract(dsX);
693 for (int n = 0; n <= maxOrder; ++n) {
694 assertEquals(0.0, zero.getPartialDerivative(n), epsilon[n]);
695 }
696 }
697 }
698 }
699
700 @Test
701 void testPowReciprocalPow() {
702 double[] epsilon = new double[] { 2.0e-15, 2.0e-14, 3.0e-13, 8.0e-12, 3.0e-10 };
703 for (int maxOrder = 0; maxOrder < 5; ++maxOrder) {
704 DSFactory factory = new DSFactory(2, maxOrder);
705 for (double x = 0.1; x < 1.2; x += 0.01) {
706 DerivativeStructure dsX = factory.variable(0, x);
707 for (double y = 0.1; y < 1.2; y += 0.01) {
708 DerivativeStructure dsY = factory.variable(1, y);
709 DerivativeStructure rebuiltX = dsX.pow(dsY).pow(dsY.reciprocal());
710 DerivativeStructure zero = rebuiltX.subtract(dsX);
711 for (int n = 0; n <= maxOrder; ++n) {
712 for (int m = 0; m <= maxOrder; ++m) {
713 if (n + m <= maxOrder) {
714 assertEquals(0.0, zero.getPartialDerivative(n, m), epsilon[n + m]);
715 }
716 }
717 }
718 }
719 }
720 }
721 }
722
723 @Test
724 void testHypotDefinition() {
725 double epsilon = 1.0e-20;
726 for (int maxOrder = 0; maxOrder < 5; ++maxOrder) {
727 DSFactory factory = new DSFactory(2, maxOrder);
728 for (double x = -1.7; x < 2; x += 0.2) {
729 DerivativeStructure dsX = factory.variable(0, x);
730 for (double y = -1.7; y < 2; y += 0.2) {
731 DerivativeStructure dsY = factory.variable(1, y);
732 DerivativeStructure hypot = FastMath.hypot(dsY, dsX);
733 DerivativeStructure ref = dsX.multiply(dsX).add(dsY.multiply(dsY)).sqrt();
734 DerivativeStructure zero = hypot.subtract(ref);
735 for (int n = 0; n <= maxOrder; ++n) {
736 for (int m = 0; m <= maxOrder; ++m) {
737 if (n + m <= maxOrder) {
738 assertEquals(0, zero.getPartialDerivative(n, m), epsilon);
739 }
740 }
741 }
742 }
743 }
744 }
745 }
746
747 @Test
748 void testHypotNoOverflow() {
749
750 DSFactory factory = new DSFactory(2, 5);
751 DerivativeStructure dsX = factory.variable(0, +3.0e250);
752 DerivativeStructure dsY = factory.variable(1, -4.0e250);
753 DerivativeStructure hypot = FastMath.hypot(dsX, dsY);
754 assertEquals(5.0e250, hypot.getValue(), 1.0e235);
755 assertEquals(dsX.getValue() / hypot.getValue(), hypot.getPartialDerivative(1, 0), 1.0e-10);
756 assertEquals(dsY.getValue() / hypot.getValue(), hypot.getPartialDerivative(0, 1), 1.0e-10);
757
758 DerivativeStructure sqrt = dsX.multiply(dsX).add(dsY.multiply(dsY)).sqrt();
759 assertTrue(Double.isInfinite(sqrt.getValue()));
760
761 }
762
763 @Test
764 void testHypotNeglectible() {
765
766 DSFactory factory = new DSFactory(2, 5);
767 DerivativeStructure dsSmall = factory.variable(0, +3.0e-10);
768 DerivativeStructure dsLarge = factory.variable(1, -4.0e25);
769
770 assertEquals(dsLarge.abs().getValue(),
771 DerivativeStructure.hypot(dsSmall, dsLarge).getValue(),
772 1.0e-10);
773 assertEquals(0,
774 DerivativeStructure.hypot(dsSmall, dsLarge).getPartialDerivative(1, 0),
775 1.0e-10);
776 assertEquals(-1,
777 DerivativeStructure.hypot(dsSmall, dsLarge).getPartialDerivative(0, 1),
778 1.0e-10);
779
780 assertEquals(dsLarge.abs().getValue(),
781 DerivativeStructure.hypot(dsLarge, dsSmall).getValue(),
782 1.0e-10);
783 assertEquals(0,
784 DerivativeStructure.hypot(dsLarge, dsSmall).getPartialDerivative(1, 0),
785 1.0e-10);
786 assertEquals(-1,
787 DerivativeStructure.hypot(dsLarge, dsSmall).getPartialDerivative(0, 1),
788 1.0e-10);
789
790 }
791
792 @Test
793 void testHypotSpecial() {
794 DSFactory factory = new DSFactory(2, 5);
795 assertTrue(Double.isNaN(DerivativeStructure.hypot(factory.variable(0, Double.NaN),
796 factory.variable(0, +3.0e250)).getValue()));
797 assertTrue(Double.isNaN(DerivativeStructure.hypot(factory.variable(0, +3.0e250),
798 factory.variable(0, Double.NaN)).getValue()));
799 assertTrue(Double.isInfinite(DerivativeStructure.hypot(factory.variable(0, Double.POSITIVE_INFINITY),
800 factory.variable(0, +3.0e250)).getValue()));
801 assertTrue(Double.isInfinite(DerivativeStructure.hypot(factory.variable(0, +3.0e250),
802 factory.variable(0, Double.POSITIVE_INFINITY)).getValue()));
803 }
804
805 @Test
806 void testPrimitiveRemainder() {
807 double epsilon = 1.0e-15;
808 for (int maxOrder = 0; maxOrder < 5; ++maxOrder) {
809 DSFactory factory = new DSFactory(2, maxOrder);
810 for (double x = -1.7; x < 2; x += 0.2) {
811 DerivativeStructure dsX = factory.variable(0, x);
812 for (double y = -1.7; y < 2; y += 0.2) {
813 DerivativeStructure remainder = FastMath.IEEEremainder(dsX, y);
814 DerivativeStructure ref = dsX.subtract(x - FastMath.IEEEremainder(x, y));
815 DerivativeStructure zero = remainder.subtract(ref);
816 for (int n = 0; n <= maxOrder; ++n) {
817 for (int m = 0; m <= maxOrder; ++m) {
818 if (n + m <= maxOrder) {
819 assertEquals(0, zero.getPartialDerivative(n, m), epsilon);
820 }
821 }
822 }
823 }
824 }
825 }
826 }
827
828 @Test
829 void testRemainder() {
830 double epsilon = 2.0e-15;
831 for (int maxOrder = 0; maxOrder < 5; ++maxOrder) {
832 DSFactory factory = new DSFactory(2, maxOrder);
833 for (double x = -1.7; x < 2; x += 0.2) {
834 DerivativeStructure dsX = factory.variable(0, x);
835 for (double y = -1.7; y < 2; y += 0.2) {
836 DerivativeStructure dsY = factory.variable(1, y);
837 DerivativeStructure remainder = FastMath.IEEEremainder(dsX, dsY);
838 DerivativeStructure ref = dsX.subtract(dsY.multiply((x - FastMath.IEEEremainder(x, y)) / y));
839 DerivativeStructure zero = remainder.subtract(ref);
840 for (int n = 0; n <= maxOrder; ++n) {
841 for (int m = 0; m <= maxOrder; ++m) {
842 if (n + m <= maxOrder) {
843 assertEquals(0, zero.getPartialDerivative(n, m), epsilon);
844 }
845 }
846 }
847 }
848 }
849 }
850 }
851
852 @Override
853 @Test
854 public void testExp() {
855 double[] epsilon = new double[] { 1.0e-16, 1.0e-16, 1.0e-16, 1.0e-16, 1.0e-16 };
856 for (int maxOrder = 0; maxOrder < 5; ++maxOrder) {
857 DSFactory factory = new DSFactory(1, maxOrder);
858 for (double x = 0.1; x < 1.2; x += 0.001) {
859 double refExp = FastMath.exp(x);
860 DerivativeStructure exp = FastMath.exp(factory.variable(0, x));
861 for (int n = 0; n <= maxOrder; ++n) {
862 assertEquals(refExp, exp.getPartialDerivative(n), epsilon[n]);
863 }
864 }
865 }
866 }
867
868 @Test
869 void testExpm1Definition() {
870 double epsilon = 3.0e-16;
871 for (int maxOrder = 0; maxOrder < 5; ++maxOrder) {
872 DSFactory factory = new DSFactory(1, maxOrder);
873 for (double x = 0.1; x < 1.2; x += 0.001) {
874 DerivativeStructure dsX = factory.variable(0, x);
875 DerivativeStructure expm11 = FastMath.expm1(dsX);
876 DerivativeStructure expm12 = dsX.exp().subtract(dsX.getField().getOne());
877 DerivativeStructure zero = expm11.subtract(expm12);
878 for (int n = 0; n <= maxOrder; ++n) {
879 assertEquals(0, zero.getPartialDerivative(n), epsilon);
880 }
881 }
882 }
883 }
884
885 @Override
886 @Test
887 public void testLog() {
888 double[] epsilon = new double[] { 1.0e-16, 1.0e-16, 3.0e-14, 7.0e-13, 3.0e-11 };
889 for (int maxOrder = 0; maxOrder < 5; ++maxOrder) {
890 DSFactory factory = new DSFactory(1, maxOrder);
891 for (double x = 0.1; x < 1.2; x += 0.001) {
892 DerivativeStructure log = FastMath.log(factory.variable(0, x));
893 assertEquals(FastMath.log(x), log.getValue(), epsilon[0]);
894 for (int n = 1; n <= maxOrder; ++n) {
895 double refDer = -CombinatoricsUtils.factorial(n - 1) / FastMath.pow(-x, n);
896 assertEquals(refDer, log.getPartialDerivative(n), epsilon[n]);
897 }
898 }
899 }
900 }
901
902 @Test
903 void testLog1pDefinition() {
904 double epsilon = 3.0e-16;
905 for (int maxOrder = 0; maxOrder < 5; ++maxOrder) {
906 for (double x = 0.1; x < 1.2; x += 0.001) {
907 DSFactory factory = new DSFactory(1, maxOrder);
908 DerivativeStructure dsX = factory.variable(0, x);
909 DerivativeStructure log1p1 = FastMath.log1p(dsX);
910 DerivativeStructure log1p2 = FastMath.log(dsX.add(dsX.getField().getOne()));
911 DerivativeStructure zero = log1p1.subtract(log1p2);
912 for (int n = 0; n <= maxOrder; ++n) {
913 assertEquals(0, zero.getPartialDerivative(n), epsilon);
914 }
915 }
916 }
917 }
918
919 @Test
920 void testLog10Definition() {
921 double[] epsilon = new double[] { 3.0e-16, 9.0e-16, 8.0e-15, 3.0e-13, 8.0e-12 };
922 for (int maxOrder = 0; maxOrder < 5; ++maxOrder) {
923 DSFactory factory = new DSFactory(1, maxOrder);
924 for (double x = 0.1; x < 1.2; x += 0.001) {
925 DerivativeStructure dsX = factory.variable(0, x);
926 DerivativeStructure log101 = FastMath.log10(dsX);
927 DerivativeStructure log102 = dsX.log().divide(FastMath.log(10.0));
928 DerivativeStructure zero = log101.subtract(log102);
929 for (int n = 0; n <= maxOrder; ++n) {
930 assertEquals(0, zero.getPartialDerivative(n), epsilon[n]);
931 }
932 }
933 }
934 }
935
936 @Test
937 void testLogExp() {
938 double[] epsilon = new double[] { 2.0e-16, 2.0e-16, 3.0e-16, 2.0e-15, 6.0e-15 };
939 for (int maxOrder = 0; maxOrder < 5; ++maxOrder) {
940 DSFactory factory = new DSFactory(1, maxOrder);
941 for (double x = 0.1; x < 1.2; x += 0.001) {
942 DerivativeStructure dsX = factory.variable(0, x);
943 DerivativeStructure rebuiltX = dsX.exp().log();
944 DerivativeStructure zero = rebuiltX.subtract(dsX);
945 for (int n = 0; n <= maxOrder; ++n) {
946 assertEquals(0.0, zero.getPartialDerivative(n), epsilon[n]);
947 }
948 }
949 }
950 }
951
952 @Test
953 void testLog1pExpm1() {
954 double[] epsilon = new double[] { 6.0e-17, 3.0e-16, 5.0e-16, 9.0e-16, 6.0e-15 };
955 for (int maxOrder = 0; maxOrder < 5; ++maxOrder) {
956 DSFactory factory = new DSFactory(1, maxOrder);
957 for (double x = 0.1; x < 1.2; x += 0.001) {
958 DerivativeStructure dsX = factory.variable(0, x);
959 DerivativeStructure rebuiltX = dsX.expm1().log1p();
960 DerivativeStructure zero = rebuiltX.subtract(dsX);
961 for (int n = 0; n <= maxOrder; ++n) {
962 assertEquals(0.0, zero.getPartialDerivative(n), epsilon[n]);
963 }
964 }
965 }
966 }
967
968 @Test
969 void testLog10Power() {
970 double[] epsilon = new double[] { 3.0e-16, 3.0e-16, 9.0e-16, 6.0e-15, 6.0e-14 };
971 for (int maxOrder = 0; maxOrder < 5; ++maxOrder) {
972 DSFactory factory = new DSFactory(1, maxOrder);
973 for (double x = 0.1; x < 1.2; x += 0.001) {
974 DerivativeStructure dsX = factory.variable(0, x);
975 DerivativeStructure rebuiltX = factory.constant(10.0).pow(dsX).log10();
976 DerivativeStructure zero = rebuiltX.subtract(dsX);
977 for (int n = 0; n <= maxOrder; ++n) {
978 assertEquals(0, zero.getPartialDerivative(n), epsilon[n]);
979 }
980 }
981 }
982 }
983
984 @Test
985 void testSinCosSeparated() {
986 double epsilon = 5.0e-16;
987 for (int maxOrder = 0; maxOrder < 6; ++maxOrder) {
988 DSFactory factory = new DSFactory(1, maxOrder);
989 for (double x = 0.1; x < 1.2; x += 0.001) {
990 DerivativeStructure dsX = factory.variable(0, x);
991 DerivativeStructure sin = FastMath.sin(dsX);
992 DerivativeStructure cos = FastMath.cos(dsX);
993 double s = FastMath.sin(x);
994 double c = FastMath.cos(x);
995 for (int n = 0; n <= maxOrder; ++n) {
996 switch (n % 4) {
997 case 0 :
998 assertEquals( s, sin.getPartialDerivative(n), epsilon);
999 assertEquals( c, cos.getPartialDerivative(n), epsilon);
1000 break;
1001 case 1 :
1002 assertEquals( c, sin.getPartialDerivative(n), epsilon);
1003 assertEquals(-s, cos.getPartialDerivative(n), epsilon);
1004 break;
1005 case 2 :
1006 assertEquals(-s, sin.getPartialDerivative(n), epsilon);
1007 assertEquals(-c, cos.getPartialDerivative(n), epsilon);
1008 break;
1009 default :
1010 assertEquals(-c, sin.getPartialDerivative(n), epsilon);
1011 assertEquals( s, cos.getPartialDerivative(n), epsilon);
1012 break;
1013 }
1014 }
1015 }
1016 }
1017 }
1018
1019 @Test
1020 void testSinCosCombined() {
1021 double epsilon = 5.0e-16;
1022 for (int maxOrder = 0; maxOrder < 6; ++maxOrder) {
1023 DSFactory factory = new DSFactory(1, maxOrder);
1024 for (double x = 0.1; x < 1.2; x += 0.001) {
1025 DerivativeStructure dsX = factory.variable(0, x);
1026 FieldSinCos<DerivativeStructure> sinCos = FastMath.sinCos(dsX);
1027 double s = FastMath.sin(x);
1028 double c = FastMath.cos(x);
1029 for (int n = 0; n <= maxOrder; ++n) {
1030 switch (n % 4) {
1031 case 0 :
1032 assertEquals( s, sinCos.sin().getPartialDerivative(n), epsilon);
1033 assertEquals( c, sinCos.cos().getPartialDerivative(n), epsilon);
1034 break;
1035 case 1 :
1036 assertEquals( c, sinCos.sin().getPartialDerivative(n), epsilon);
1037 assertEquals(-s, sinCos.cos().getPartialDerivative(n), epsilon);
1038 break;
1039 case 2 :
1040 assertEquals(-s, sinCos.sin().getPartialDerivative(n), epsilon);
1041 assertEquals(-c, sinCos.cos().getPartialDerivative(n), epsilon);
1042 break;
1043 default :
1044 assertEquals(-c, sinCos.sin().getPartialDerivative(n), epsilon);
1045 assertEquals( s, sinCos.cos().getPartialDerivative(n), epsilon);
1046 break;
1047 }
1048 }
1049 }
1050 }
1051 }
1052
1053 @Test
1054 void testSinAsin() {
1055 double[] epsilon = new double[] { 3.0e-16, 5.0e-16, 3.0e-15, 2.0e-14, 4.0e-13 };
1056 for (int maxOrder = 0; maxOrder < 5; ++maxOrder) {
1057 DSFactory factory = new DSFactory(1, maxOrder);
1058 for (double x = 0.1; x < 1.2; x += 0.001) {
1059 DerivativeStructure dsX = factory.variable(0, x);
1060 DerivativeStructure rebuiltX = FastMath.asin(FastMath.sin(dsX));
1061 DerivativeStructure zero = rebuiltX.subtract(dsX);
1062 for (int n = 0; n <= maxOrder; ++n) {
1063 assertEquals(0.0, zero.getPartialDerivative(n), epsilon[n]);
1064 }
1065 }
1066 }
1067 }
1068
1069 @Test
1070 void testCosAcos() {
1071 double[] epsilon = new double[] { 6.0e-16, 6.0e-15, 2.0e-13, 4.0e-12, 2.0e-10 };
1072 for (int maxOrder = 0; maxOrder < 5; ++maxOrder) {
1073 DSFactory factory = new DSFactory(1, maxOrder);
1074 for (double x = 0.1; x < 1.2; x += 0.001) {
1075 DerivativeStructure dsX = factory.variable(0, x);
1076 DerivativeStructure rebuiltX = FastMath.acos(FastMath.cos(dsX));
1077 DerivativeStructure zero = rebuiltX.subtract(dsX);
1078 for (int n = 0; n <= maxOrder; ++n) {
1079 assertEquals(0.0, zero.getPartialDerivative(n), epsilon[n]);
1080 }
1081 }
1082 }
1083 }
1084
1085 @Test
1086 void testTanAtan() {
1087 double[] epsilon = new double[] { 6.0e-17, 2.0e-16, 2.0e-15, 4.0e-14, 2.0e-12 };
1088 for (int maxOrder = 0; maxOrder < 5; ++maxOrder) {
1089 DSFactory factory = new DSFactory(1, maxOrder);
1090 for (double x = 0.1; x < 1.2; x += 0.001) {
1091 DerivativeStructure dsX = factory.variable(0, x);
1092 DerivativeStructure rebuiltX = FastMath.atan(FastMath.tan(dsX));
1093 DerivativeStructure zero = rebuiltX.subtract(dsX);
1094 for (int n = 0; n <= maxOrder; ++n) {
1095 assertEquals(0.0, zero.getPartialDerivative(n), epsilon[n]);
1096 }
1097 }
1098 }
1099 }
1100
1101 @Test
1102 void testTangentDefinition() {
1103 double[] epsilon = new double[] { 5.0e-16, 2.7e-15, 3.0e-14, 5.0e-13, 2.0e-11 };
1104 for (int maxOrder = 0; maxOrder < 5; ++maxOrder) {
1105 DSFactory factory = new DSFactory(1, maxOrder);
1106 for (double x = 0.1; x < 1.2; x += 0.001) {
1107 DerivativeStructure dsX = factory.variable(0, x);
1108 DerivativeStructure tan1 = dsX.sin().divide(dsX.cos());
1109 DerivativeStructure tan2 = dsX.tan();
1110 DerivativeStructure zero = tan1.subtract(tan2);
1111 for (int n = 0; n <= maxOrder; ++n) {
1112 assertEquals(0, zero.getPartialDerivative(n), epsilon[n]);
1113 }
1114 }
1115 }
1116 }
1117
1118 @Override
1119 @Test
1120 public void testAtan2() {
1121 double[] epsilon = new double[] { 5.0e-16, 3.0e-15, 2.9e-14, 1.0e-12, 8.0e-11 };
1122 for (int maxOrder = 0; maxOrder < 5; ++maxOrder) {
1123 DSFactory factory = new DSFactory(2, maxOrder);
1124 for (double x = -1.7; x < 2; x += 0.2) {
1125 DerivativeStructure dsX = factory.variable(0, x);
1126 for (double y = -1.7; y < 2; y += 0.2) {
1127 DerivativeStructure dsY = factory.variable(1, y);
1128 DerivativeStructure atan2 = FastMath.atan2(dsY, dsX);
1129 DerivativeStructure ref = dsY.divide(dsX).atan();
1130 if (x < 0) {
1131 ref = (y < 0) ? ref.subtract(FastMath.PI) : ref.add(FastMath.PI);
1132 }
1133 DerivativeStructure zero = atan2.subtract(ref);
1134 for (int n = 0; n <= maxOrder; ++n) {
1135 for (int m = 0; m <= maxOrder; ++m) {
1136 if (n + m <= maxOrder) {
1137 assertEquals(0, zero.getPartialDerivative(n, m), epsilon[n + m]);
1138 }
1139 }
1140 }
1141 }
1142 }
1143 }
1144 }
1145
1146 @Test
1147 void testAtan2SpecialCasesDerivative() {
1148
1149 DSFactory factory = new DSFactory(2, 2);
1150 DerivativeStructure pp =
1151 DerivativeStructure.atan2(factory.variable(1, +0.0),
1152 factory.variable(1, +0.0));
1153 assertEquals(0, pp.getValue(), 1.0e-15);
1154 assertEquals(+1, FastMath.copySign(1, pp.getValue()), 1.0e-15);
1155
1156 DerivativeStructure pn =
1157 DerivativeStructure.atan2(factory.variable(1, +0.0),
1158 factory.variable(1, -0.0));
1159 assertEquals(FastMath.PI, pn.getValue(), 1.0e-15);
1160
1161 DerivativeStructure np =
1162 DerivativeStructure.atan2(factory.variable(1, -0.0),
1163 factory.variable(1, +0.0));
1164 assertEquals(0, np.getValue(), 1.0e-15);
1165 assertEquals(-1, FastMath.copySign(1, np.getValue()), 1.0e-15);
1166
1167 DerivativeStructure nn =
1168 DerivativeStructure.atan2(factory.variable(1, -0.0),
1169 factory.variable(1, -0.0));
1170 assertEquals(-FastMath.PI, nn.getValue(), 1.0e-15);
1171
1172 }
1173
1174 @Test
1175 void testSinhCoshCombined() {
1176 double epsilon = 5.0e-16;
1177 for (int maxOrder = 0; maxOrder < 6; ++maxOrder) {
1178 DSFactory factory = new DSFactory(1, maxOrder);
1179 for (double x = 0.1; x < 1.2; x += 0.001) {
1180 DerivativeStructure dsX = factory.variable(0, x);
1181 FieldSinhCosh<DerivativeStructure> sinhCosh = FastMath.sinhCosh(dsX);
1182 double sh = FastMath.sinh(x);
1183 double ch = FastMath.cosh(x);
1184 for (int n = 0; n <= maxOrder; ++n) {
1185 if (n % 2 == 0) {
1186 assertEquals(sh, sinhCosh.sinh().getPartialDerivative(n), epsilon);
1187 assertEquals(ch, sinhCosh.cosh().getPartialDerivative(n), epsilon);
1188 } else {
1189 assertEquals(ch, sinhCosh.sinh().getPartialDerivative(n), epsilon);
1190 assertEquals(sh, sinhCosh.cosh().getPartialDerivative(n), epsilon);
1191 }
1192 }
1193 }
1194 }
1195 }
1196
1197 @Test
1198 void testSinhDefinition() {
1199 double[] epsilon = new double[] { 3.0e-16, 3.0e-16, 5.0e-16, 2.0e-15, 6.0e-15 };
1200 for (int maxOrder = 0; maxOrder < 5; ++maxOrder) {
1201 DSFactory factory = new DSFactory(1, maxOrder);
1202 for (double x = 0.1; x < 1.2; x += 0.001) {
1203 DerivativeStructure dsX = factory.variable(0, x);
1204 DerivativeStructure sinh1 = dsX.exp().subtract(dsX.exp().reciprocal()).multiply(0.5);
1205 DerivativeStructure sinh2 = FastMath.sinh(dsX);
1206 DerivativeStructure zero = sinh1.subtract(sinh2);
1207 for (int n = 0; n <= maxOrder; ++n) {
1208 assertEquals(0, zero.getPartialDerivative(n), epsilon[n]);
1209 }
1210 }
1211 }
1212 }
1213
1214 @Test
1215 void testCoshDefinition() {
1216 double[] epsilon = new double[] { 3.0e-16, 3.0e-16, 5.0e-16, 2.0e-15, 6.0e-15 };
1217 for (int maxOrder = 0; maxOrder < 5; ++maxOrder) {
1218 DSFactory factory = new DSFactory(1, maxOrder);
1219 for (double x = 0.1; x < 1.2; x += 0.001) {
1220 DerivativeStructure dsX = factory.variable(0, x);
1221 DerivativeStructure cosh1 = dsX.exp().add(dsX.exp().reciprocal()).multiply(0.5);
1222 DerivativeStructure cosh2 = FastMath.cosh(dsX);
1223 DerivativeStructure zero = cosh1.subtract(cosh2);
1224 for (int n = 0; n <= maxOrder; ++n) {
1225 assertEquals(0, zero.getPartialDerivative(n), epsilon[n]);
1226 }
1227 }
1228 }
1229 }
1230
1231 @Test
1232 void testTanhDefinition() {
1233 double[] epsilon = new double[] { 3.0e-16, 5.0e-16, 7.0e-16, 3.0e-15, 2.0e-14 };
1234 for (int maxOrder = 0; maxOrder < 5; ++maxOrder) {
1235 DSFactory factory = new DSFactory(1, maxOrder);
1236 for (double x = 0.1; x < 1.2; x += 0.001) {
1237 DerivativeStructure dsX = factory.variable(0, x);
1238 DerivativeStructure tanh1 = dsX.exp().subtract(dsX.exp().reciprocal()).divide(dsX.exp().add(dsX.exp().reciprocal()));
1239 DerivativeStructure tanh2 = FastMath.tanh(dsX);
1240 DerivativeStructure zero = tanh1.subtract(tanh2);
1241 for (int n = 0; n <= maxOrder; ++n) {
1242 assertEquals(0, zero.getPartialDerivative(n), epsilon[n]);
1243 }
1244 }
1245 }
1246 }
1247
1248 @Test
1249 void testSinhAsinh() {
1250 double[] epsilon = new double[] { 3.0e-16, 3.0e-16, 4.0e-16, 7.0e-16, 3.0e-15, 8.0e-15 };
1251 for (int maxOrder = 0; maxOrder < 6; ++maxOrder) {
1252 DSFactory factory = new DSFactory(1, maxOrder);
1253 for (double x = 0.1; x < 1.2; x += 0.001) {
1254 DerivativeStructure dsX = factory.variable(0, x);
1255 DerivativeStructure rebuiltX = FastMath.asinh(dsX.sinh());
1256 DerivativeStructure zero = rebuiltX.subtract(dsX);
1257 for (int n = 0; n <= maxOrder; ++n) {
1258 assertEquals(0.0, zero.getPartialDerivative(n), epsilon[n]);
1259 }
1260 }
1261 }
1262 }
1263
1264 @Test
1265 void testCoshAcosh() {
1266 double[] epsilon = new double[] { 2.0e-15, 1.0e-14, 2.0e-13, 6.0e-12, 3.0e-10, 2.0e-8 };
1267 for (int maxOrder = 0; maxOrder < 6; ++maxOrder) {
1268 DSFactory factory = new DSFactory(1, maxOrder);
1269 for (double x = 0.1; x < 1.2; x += 0.001) {
1270 DerivativeStructure dsX = factory.variable(0, x);
1271 DerivativeStructure rebuiltX = FastMath.acosh(dsX.cosh());
1272 DerivativeStructure zero = rebuiltX.subtract(dsX);
1273 for (int n = 0; n <= maxOrder; ++n) {
1274 assertEquals(0.0, zero.getPartialDerivative(n), epsilon[n]);
1275 }
1276 }
1277 }
1278 }
1279
1280 @Test
1281 void testTanhAtanh() {
1282 double[] epsilon = new double[] { 3.0e-16, 2.0e-16, 7.0e-16, 4.0e-15, 3.0e-14, 4.0e-13 };
1283 for (int maxOrder = 0; maxOrder < 6; ++maxOrder) {
1284 DSFactory factory = new DSFactory(1, maxOrder);
1285 for (double x = 0.1; x < 1.2; x += 0.001) {
1286 DerivativeStructure dsX = factory.variable(0, x);
1287 DerivativeStructure rebuiltX = FastMath.atanh(dsX.tanh());
1288 DerivativeStructure zero = rebuiltX.subtract(dsX);
1289 for (int n = 0; n <= maxOrder; ++n) {
1290 assertEquals(0.0, zero.getPartialDerivative(n), epsilon[n]);
1291 }
1292 }
1293 }
1294 }
1295
1296 @Test
1297 void testCompositionOneVariableY() {
1298 double epsilon = 1.0e-13;
1299 for (int maxOrder = 0; maxOrder < 5; ++maxOrder) {
1300 DSFactory factory = new DSFactory(1, maxOrder);
1301 for (double x = 0.1; x < 1.2; x += 0.1) {
1302 DerivativeStructure dsX = factory.constant(x);
1303 for (double y = 0.1; y < 1.2; y += 0.1) {
1304 DerivativeStructure dsY = factory.variable(0, y);
1305 DerivativeStructure f = dsX.divide(dsY).sqrt();
1306 double f0 = FastMath.sqrt(x / y);
1307 assertEquals(f0, f.getValue(), FastMath.abs(epsilon * f0));
1308 if (f.getOrder() > 0) {
1309 double f1 = -x / (2 * y * y * f0);
1310 assertEquals(f1, f.getPartialDerivative(1), FastMath.abs(epsilon * f1));
1311 if (f.getOrder() > 1) {
1312 double f2 = (f0 - x / (4 * y * f0)) / (y * y);
1313 assertEquals(f2, f.getPartialDerivative(2), FastMath.abs(epsilon * f2));
1314 if (f.getOrder() > 2) {
1315 double f3 = (x / (8 * y * f0) - 2 * f0) / (y * y * y);
1316 assertEquals(f3, f.getPartialDerivative(3), FastMath.abs(epsilon * f3));
1317 }
1318 }
1319 }
1320 }
1321 }
1322 }
1323 }
1324
1325 @Test
1326 void testTaylorPolynomial() {
1327 DSFactory factory = new DSFactory(3, 4);
1328 for (double x = 0; x < 1.2; x += 0.1) {
1329 DerivativeStructure dsX = factory.variable(0, x);
1330 for (double y = 0; y < 1.2; y += 0.2) {
1331 DerivativeStructure dsY = factory.variable(1, y);
1332 for (double z = 0; z < 1.2; z += 0.2) {
1333 DerivativeStructure dsZ = factory.variable(2, z);
1334 DerivativeStructure f = dsX.multiply(dsY).add(dsZ).multiply(dsX).multiply(dsY);
1335 for (double dx = -0.2; dx < 0.2; dx += 0.2) {
1336 for (double dy = -0.2; dy < 0.2; dy += 0.1) {
1337 for (double dz = -0.2; dz < 0.2; dz += 0.1) {
1338 double ref = (x + dx) * (y + dy) * ((x + dx) * (y + dy) + (z + dz));
1339 assertEquals(ref, f.taylor(dx, dy, dz), 2.0e-15);
1340 }
1341 }
1342 }
1343 }
1344 }
1345 }
1346 }
1347
1348 @Test
1349 void testTaylorAtan2() {
1350 double[] expected = new double[] { 0.214, 0.0241, 0.00422, 6.48e-4, 8.04e-5 };
1351 double x0 = 0.1;
1352 double y0 = -0.3;
1353 for (int maxOrder = 0; maxOrder < 5; ++maxOrder) {
1354 DSFactory factory = new DSFactory(2, maxOrder);
1355 DerivativeStructure dsX = factory.variable(0, x0);
1356 DerivativeStructure dsY = factory.variable(1, y0);
1357 DerivativeStructure atan2 = DerivativeStructure.atan2(dsY, dsX);
1358 double maxError = 0;
1359 for (double dx = -0.05; dx < 0.05; dx += 0.001) {
1360 for (double dy = -0.05; dy < 0.05; dy += 0.001) {
1361 double ref = FastMath.atan2(y0 + dy, x0 + dx);
1362 maxError = FastMath.max(maxError, FastMath.abs(ref - atan2.taylor(dx, dy)));
1363 }
1364 }
1365 assertEquals(0.0, expected[maxOrder] - maxError, 0.01 * expected[maxOrder]);
1366 }
1367 }
1368
1369 @Test
1370 public void testAbs() {
1371
1372 DSFactory factory = new DSFactory(1, 1);
1373 DerivativeStructure minusOne = factory.variable(0, -1.0);
1374 assertEquals(+1.0, FastMath.abs(minusOne).getPartialDerivative(0), 1.0e-15);
1375 assertEquals(-1.0, FastMath.abs(minusOne).getPartialDerivative(1), 1.0e-15);
1376
1377 DerivativeStructure plusOne = factory.variable(0, +1.0);
1378 assertEquals(+1.0, FastMath.abs(plusOne).getPartialDerivative(0), 1.0e-15);
1379 assertEquals(+1.0, FastMath.abs(plusOne).getPartialDerivative(1), 1.0e-15);
1380
1381 DerivativeStructure minusZero = factory.variable(0, -0.0);
1382 assertEquals(+0.0, FastMath.abs(minusZero).getPartialDerivative(0), 1.0e-15);
1383 assertEquals(-1.0, FastMath.abs(minusZero).getPartialDerivative(1), 1.0e-15);
1384
1385 DerivativeStructure plusZero = factory.variable(0, +0.0);
1386 assertEquals(+0.0, FastMath.abs(plusZero).getPartialDerivative(0), 1.0e-15);
1387 assertEquals(+1.0, FastMath.abs(plusZero).getPartialDerivative(1), 1.0e-15);
1388
1389 }
1390
1391 @Override
1392 @Test
1393 public void testSign() {
1394
1395 DSFactory factory = new DSFactory(1, 1);
1396 DerivativeStructure minusOne = factory.variable(0, -1.0);
1397 assertEquals(-1.0, FastMath.sign(minusOne).getPartialDerivative(0), 1.0e-15);
1398 assertEquals( 0.0, FastMath.sign(minusOne).getPartialDerivative(1), 1.0e-15);
1399
1400 DerivativeStructure plusOne = factory.variable(0, +1.0);
1401 assertEquals(+1.0, FastMath.sign(plusOne).getPartialDerivative(0), 1.0e-15);
1402 assertEquals( 0.0, FastMath.sign(plusOne).getPartialDerivative(1), 1.0e-15);
1403
1404 DerivativeStructure minusZero = factory.variable(0, -0.0);
1405 assertEquals(-0.0, FastMath.sign(minusZero).getPartialDerivative(0), 1.0e-15);
1406 assertTrue(Double.doubleToLongBits(FastMath.sign(minusZero).getValue()) < 0);
1407 assertEquals( 0.0, FastMath.sign(minusZero).getPartialDerivative(1), 1.0e-15);
1408
1409 DerivativeStructure plusZero = factory.variable(0, +0.0);
1410 assertEquals(+0.0, FastMath.sign(plusZero).getPartialDerivative(0), 1.0e-15);
1411 assertEquals(0, Double.doubleToLongBits(FastMath.sign(plusZero).getValue()));
1412 assertEquals( 0.0, FastMath.sign(plusZero).getPartialDerivative(1), 1.0e-15);
1413
1414 }
1415
1416 @Test
1417 void testCeilFloorRintLong() {
1418
1419 DSFactory factory = new DSFactory(1, 1);
1420 DerivativeStructure x = factory.variable(0, -1.5);
1421 assertEquals(-1.5, x.getPartialDerivative(0), 1.0e-15);
1422 assertEquals(+1.0, x.getPartialDerivative(1), 1.0e-15);
1423 assertEquals(-1.0, FastMath.ceil(x).getPartialDerivative(0), 1.0e-15);
1424 assertEquals(+0.0, FastMath.ceil(x).getPartialDerivative(1), 1.0e-15);
1425 assertEquals(-2.0, FastMath.floor(x).getPartialDerivative(0), 1.0e-15);
1426 assertEquals(+0.0, FastMath.floor(x).getPartialDerivative(1), 1.0e-15);
1427 assertEquals(-2.0, FastMath.rint(x).getPartialDerivative(0), 1.0e-15);
1428 assertEquals(+0.0, FastMath.rint(x).getPartialDerivative(1), 1.0e-15);
1429 assertEquals(-2.0, x.subtract(x.getField().getOne()).rint().getPartialDerivative(0), 1.0e-15);
1430
1431 }
1432
1433 @Test
1434 void testCopySign() {
1435
1436 DSFactory factory = new DSFactory(1, 1);
1437 DerivativeStructure minusOne = factory.variable(0, -1.0);
1438 assertEquals(+1.0, FastMath.copySign(minusOne, +1.0).getPartialDerivative(0), 1.0e-15);
1439 assertEquals(-1.0, FastMath.copySign(minusOne, +1.0).getPartialDerivative(1), 1.0e-15);
1440 assertEquals(-1.0, FastMath.copySign(minusOne, -1.0).getPartialDerivative(0), 1.0e-15);
1441 assertEquals(+1.0, FastMath.copySign(minusOne, -1.0).getPartialDerivative(1), 1.0e-15);
1442 assertEquals(+1.0, FastMath.copySign(minusOne, +0.0).getPartialDerivative(0), 1.0e-15);
1443 assertEquals(-1.0, FastMath.copySign(minusOne, +0.0).getPartialDerivative(1), 1.0e-15);
1444 assertEquals(-1.0, FastMath.copySign(minusOne, -0.0).getPartialDerivative(0), 1.0e-15);
1445 assertEquals(+1.0, FastMath.copySign(minusOne, -0.0).getPartialDerivative(1), 1.0e-15);
1446 assertEquals(+1.0, FastMath.copySign(minusOne, Double.NaN).getPartialDerivative(0), 1.0e-15);
1447 assertEquals(-1.0, FastMath.copySign(minusOne, Double.NaN).getPartialDerivative(1), 1.0e-15);
1448
1449 DerivativeStructure plusOne = factory.variable(0, +1.0);
1450 assertEquals(+1.0, FastMath.copySign(plusOne, factory.constant(+1.0)).getPartialDerivative(0), 1.0e-15);
1451 assertEquals(+1.0, FastMath.copySign(plusOne, factory.constant(+1.0)).getPartialDerivative(1), 1.0e-15);
1452 assertEquals(-1.0, FastMath.copySign(plusOne, factory.constant(-1.0)).getPartialDerivative(0), 1.0e-15);
1453 assertEquals(-1.0, FastMath.copySign(plusOne, factory.constant(-1.0)).getPartialDerivative(1), 1.0e-15);
1454 assertEquals(+1.0, FastMath.copySign(plusOne, factory.constant(+0.0)).getPartialDerivative(0), 1.0e-15);
1455 assertEquals(+1.0, FastMath.copySign(plusOne, factory.constant(+0.0)).getPartialDerivative(1), 1.0e-15);
1456 assertEquals(-1.0, FastMath.copySign(plusOne, factory.constant(-0.0)).getPartialDerivative(0), 1.0e-15);
1457 assertEquals(-1.0, FastMath.copySign(plusOne, factory.constant(-0.0)).getPartialDerivative(1), 1.0e-15);
1458 assertEquals(+1.0, FastMath.copySign(plusOne, factory.constant(Double.NaN)).getPartialDerivative(0), 1.0e-15);
1459 assertEquals(+1.0, FastMath.copySign(plusOne, factory.constant(Double.NaN)).getPartialDerivative(1), 1.0e-15);
1460
1461 }
1462
1463 @Test
1464 void testToDegreesDefinition() {
1465 double epsilon = 3.0e-16;
1466 for (int maxOrder = 0; maxOrder < 6; ++maxOrder) {
1467 DSFactory factory = new DSFactory(1, maxOrder);
1468 for (double x = 0.1; x < 1.2; x += 0.001) {
1469 DerivativeStructure dsX = factory.variable(0, x);
1470 assertEquals(FastMath.toDegrees(x), dsX.toDegrees().getValue(), epsilon);
1471 for (int n = 1; n <= maxOrder; ++n) {
1472 if (n == 1) {
1473 assertEquals(180 / FastMath.PI, dsX.toDegrees().getPartialDerivative(1), epsilon);
1474 } else {
1475 assertEquals(0.0, dsX.toDegrees().getPartialDerivative(n), epsilon);
1476 }
1477 }
1478 }
1479 }
1480 }
1481
1482 @Test
1483 void testToRadiansDefinition() {
1484 double epsilon = 3.0e-16;
1485 for (int maxOrder = 0; maxOrder < 6; ++maxOrder) {
1486 DSFactory factory = new DSFactory(1, maxOrder);
1487 for (double x = 0.1; x < 1.2; x += 0.001) {
1488 DerivativeStructure dsX = factory.variable(0, x);
1489 assertEquals(FastMath.toRadians(x), dsX.toRadians().getValue(), epsilon);
1490 for (int n = 1; n <= maxOrder; ++n) {
1491 if (n == 1) {
1492 assertEquals(FastMath.PI / 180, dsX.toRadians().getPartialDerivative(1), epsilon);
1493 } else {
1494 assertEquals(0.0, dsX.toRadians().getPartialDerivative(n), epsilon);
1495 }
1496 }
1497 }
1498 }
1499 }
1500
1501 @Test
1502 void testDegRad() {
1503 double epsilon = 3.0e-16;
1504 for (int maxOrder = 0; maxOrder < 6; ++maxOrder) {
1505 DSFactory factory = new DSFactory(1, maxOrder);
1506 for (double x = 0.1; x < 1.2; x += 0.001) {
1507 DerivativeStructure dsX = factory.variable(0, x);
1508 DerivativeStructure rebuiltX = dsX.toDegrees().toRadians();
1509 DerivativeStructure zero = rebuiltX.subtract(dsX);
1510 for (int n = 0; n <= maxOrder; ++n) {
1511 assertEquals(0.0, zero.getPartialDerivative(n), epsilon);
1512 }
1513 }
1514 }
1515 }
1516
1517 @Test
1518 void testComposeMismatchedDimensions() {
1519 assertThrows(MathIllegalArgumentException.class, () -> {
1520 new DSFactory(1, 3).variable(0, 1.2).compose(new double[3]);
1521 });
1522 }
1523
1524 @Test
1525 void testCompose() {
1526 double[] epsilon = new double[] { 1.0e-20, 5.0e-14, 2.0e-13, 3.0e-13, 2.0e-13, 1.0e-20 };
1527 PolynomialFunction poly =
1528 new PolynomialFunction(new double[] { 1.0, 2.0, 3.0, 4.0, 5.0, 6.0 });
1529 for (int maxOrder = 0; maxOrder < 6; ++maxOrder) {
1530 DSFactory factory = new DSFactory(1, maxOrder);
1531 PolynomialFunction[] p = new PolynomialFunction[maxOrder + 1];
1532 p[0] = poly;
1533 for (int i = 1; i <= maxOrder; ++i) {
1534 p[i] = p[i - 1].polynomialDerivative();
1535 }
1536 for (double x = 0.1; x < 1.2; x += 0.001) {
1537 DerivativeStructure dsX = factory.variable(0, x);
1538 DerivativeStructure dsY1 = dsX.getField().getZero();
1539 for (int i = poly.degree(); i >= 0; --i) {
1540 dsY1 = dsY1.multiply(dsX).add(poly.getCoefficients()[i]);
1541 }
1542 double[] f = new double[maxOrder + 1];
1543 for (int i = 0; i < f.length; ++i) {
1544 f[i] = p[i].value(x);
1545 }
1546 DerivativeStructure dsY2 = dsX.compose(f);
1547 DerivativeStructure zero = dsY1.subtract(dsY2);
1548 for (int n = 0; n <= maxOrder; ++n) {
1549 assertEquals(0.0, zero.getPartialDerivative(n), epsilon[n]);
1550 }
1551 }
1552 }
1553 }
1554
1555 @Test
1556 void testIntegration() {
1557
1558 final RandomGenerator random = new Well19937a(0x87bb96d6e11557bdl);
1559 final DSFactory factory = new DSFactory(3, 7);
1560 final int size = factory.getCompiler().getSize();
1561 for (int count = 0; count < 100; ++count) {
1562 final double[] data = new double[size];
1563 for (int i = 0; i < size; i++) {
1564 data[i] = random.nextDouble();
1565 }
1566 final DerivativeStructure f = factory.build(data);
1567 final DerivativeStructure i2fIxIy = f.integrate(0, 1).integrate(1, 1);
1568 final DerivativeStructure i2fIyIx = f.integrate(1, 1).integrate(0, 1);
1569 checkEquals(i2fIxIy, i2fIyIx, 0.);
1570 }
1571 }
1572
1573 @Test
1574 void testIntegrationGreaterThanOrder() {
1575
1576
1577 final RandomGenerator random = new Well19937a(0x4744a847b11e4c6fl);
1578 final DSFactory factory = new DSFactory(3, 7);
1579 final int size = factory.getCompiler().getSize();
1580 for (int count = 0; count < 100; ++count) {
1581 final double[] data = new double[size];
1582 for (int i = 0; i < size; i++) {
1583 data[i] = random.nextDouble();
1584 }
1585 final DerivativeStructure f = factory.build(data);
1586 for (int index = 0; index < factory.getCompiler().getFreeParameters(); ++index) {
1587 final DerivativeStructure integ = f.integrate(index, factory.getCompiler().getOrder() + 1);
1588 checkEquals(factory.constant(0), integ, 0.);
1589 }
1590 }
1591 }
1592
1593 @Test
1594 void testIntegrationNoOp() {
1595
1596 final RandomGenerator random = new Well19937a(0x75a35152f30f644bl);
1597 final DSFactory factory = new DSFactory(3, 7);
1598 final int size = factory.getCompiler().getSize();
1599 for (int count = 0; count < 100; ++count) {
1600 final double[] data = new double[size];
1601 for (int i = 0; i < size; i++) {
1602 data[i] = random.nextDouble();
1603 }
1604 final DerivativeStructure f = factory.build(data);
1605 for (int index = 0; index < factory.getCompiler().getFreeParameters(); ++index) {
1606 final DerivativeStructure integ = f.integrate(index, 0);
1607 checkEquals(f, integ, 0.);
1608 }
1609 }
1610 }
1611
1612 @Test
1613 void testDifferentiationNoOp() {
1614
1615 final RandomGenerator random = new Well19937a(0x3b6ae4c2f1282949l);
1616 final DSFactory factory = new DSFactory(3, 7);
1617 final int size = factory.getCompiler().getSize();
1618 for (int count = 0; count < 100; ++count) {
1619 final double[] data = new double[size];
1620 for (int i = 0; i < size; i++) {
1621 data[i] = random.nextDouble();
1622 }
1623 final DerivativeStructure f = factory.build(data);
1624 for (int index = 0; index < factory.getCompiler().getFreeParameters(); ++index) {
1625 final DerivativeStructure integ = f.differentiate(index, 0);
1626 checkEquals(f, integ, 0.);
1627 }
1628 }
1629 }
1630
1631 @Test
1632 void testIntegrationDifferentiation() {
1633
1634
1635 final RandomGenerator random = new Well19937a(0x67fe66c05e5ee222l);
1636 final DSFactory factory = new DSFactory(1, 25);
1637 final int size = factory.getCompiler().getSize();
1638 for (int count = 0; count < 100; ++count) {
1639 final double[] data = new double[size];
1640 for (int i = 1; i < size - 1; i++) {
1641 data[i] = random.nextDouble();
1642 }
1643 final int indexVar = 0;
1644 final DerivativeStructure f = factory.build(data);
1645 final DerivativeStructure f2 = f.integrate(indexVar, 1).differentiate(indexVar, 1);
1646 final DerivativeStructure f3 = f.differentiate(indexVar, 1).integrate(indexVar, 1);
1647 checkEquals(f2, f, 0.);
1648 checkEquals(f2, f3, 0.);
1649
1650 final DerivativeStructure df = f.integrate(indexVar, -1);
1651 final DerivativeStructure df2 = f.differentiate(indexVar, 1);
1652 checkEquals(df, df2, 0.);
1653
1654 final DerivativeStructure fi = f.differentiate(indexVar, -1);
1655 final DerivativeStructure fi2 = f.integrate(indexVar, 1);
1656 checkEquals(fi, fi2, 0.);
1657 }
1658 }
1659
1660 @Test
1661 void testDifferentiation1() {
1662
1663 final int freeParam = 3;
1664 final int order = 5;
1665 final DSFactory factory = new DSFactory(freeParam, order);
1666 final DerivativeStructure f = factory.variable(0, 1.0);
1667 final int[] orders = new int[freeParam];
1668 orders[0] = 2;
1669 orders[1] = 1;
1670 orders[2] = 1;
1671 final double value = 10.;
1672 f.setDerivativeComponent(factory.getCompiler().getPartialDerivativeIndex(orders), value);
1673 final DerivativeStructure dfDx = f.differentiate(0, 1);
1674 orders[0] -= 1;
1675 assertEquals(1., dfDx.getPartialDerivative(new int[freeParam]), 0.);
1676 assertEquals(value, dfDx.getPartialDerivative(orders), 0.);
1677 checkEquals(factory.constant(0), f.differentiate(0, order + 1), 0.);
1678 }
1679
1680 @Test
1681 void testDifferentiation2() {
1682
1683 final RandomGenerator random = new Well19937a(0xec293aaee352de94l);
1684 final DSFactory factory = new DSFactory(5, 4);
1685 final int size = factory.getCompiler().getSize();
1686 for (int count = 0; count < 100; ++count) {
1687 final double[] data = new double[size];
1688 for (int i = 0; i < size; i++) {
1689 data[i] = random.nextDouble();
1690 }
1691 final DerivativeStructure f = factory.build(data);
1692 final DerivativeStructure d2fDx2 = f.differentiate(0, 1).differentiate(0, 1);
1693 final DerivativeStructure d2fDx2Bis = f.differentiate(0, 2);
1694 checkEquals(d2fDx2, d2fDx2Bis, 0.);
1695 }
1696 }
1697
1698 @Test
1699 void testDifferentiation3() {
1700
1701 final RandomGenerator random = new Well19937a(0x35409ecc1348e46cl);
1702 final DSFactory factory = new DSFactory(3, 7);
1703 final int size = factory.getCompiler().getSize();
1704 for (int count = 0; count < 100; ++count) {
1705 final double[] data = new double[size];
1706 for (int i = 0; i < size; i++) {
1707 data[i] = random.nextDouble();
1708 }
1709 final DerivativeStructure f = factory.build(data);
1710 final DerivativeStructure d2fDxDy = f.differentiate(0, 1).differentiate(1, 1);
1711 final DerivativeStructure d2fDyDx = f.differentiate(1, 1).differentiate(0, 1);
1712 checkEquals(d2fDxDy, d2fDyDx, 0.);
1713 }
1714 }
1715
1716 @Test
1717 void testField() {
1718 for (int maxOrder = 1; maxOrder < 5; ++maxOrder) {
1719 DSFactory factory = new DSFactory(3, maxOrder);
1720 DerivativeStructure x = factory.variable(0, 1.0);
1721 checkF0F1(x.getField().getZero(), 0.0, 0.0, 0.0, 0.0);
1722 checkF0F1(x.getField().getOne(), 1.0, 0.0, 0.0, 0.0);
1723 assertEquals(maxOrder, x.getField().getZero().getOrder());
1724 assertEquals(3, x.getField().getZero().getFreeParameters());
1725 assertEquals(DerivativeStructure.class, x.getField().getRuntimeClass());
1726 }
1727 }
1728
1729 @Test
1730 void testOneParameterConstructor() {
1731 double x = 1.2;
1732 double cos = FastMath.cos(x);
1733 double sin = FastMath.sin(x);
1734 DSFactory factory = new DSFactory(1, 4);
1735 DerivativeStructure yRef = factory.variable(0, x).cos();
1736 try {
1737 new DSFactory(1, 4).build(0.0, 0.0);
1738 fail("an exception should have been thrown");
1739 } catch (MathIllegalArgumentException dme) {
1740
1741 } catch (Exception e) {
1742 fail("wrong exceptionc caught " + e.getClass().getName());
1743 }
1744 double[] derivatives = new double[] { cos, -sin, -cos, sin, cos };
1745 DerivativeStructure y = factory.build(derivatives);
1746 checkEquals(yRef, y, 1.0e-15);
1747 UnitTestUtils.customAssertEquals(derivatives, y.getAllDerivatives(), 1.0e-15);
1748 }
1749
1750 @Test
1751 void testOneOrderConstructor() {
1752 DSFactory factory = new DSFactory(3, 1);
1753 double x = 1.2;
1754 double y = 2.4;
1755 double z = 12.5;
1756 DerivativeStructure xRef = factory.variable(0, x);
1757 DerivativeStructure yRef = factory.variable(1, y);
1758 DerivativeStructure zRef = factory.variable(2, z);
1759 try {
1760 new DSFactory(3, 1).build(x + y - z, 1.0, 1.0);
1761 fail("an exception should have been thrown");
1762 } catch (MathIllegalArgumentException dme) {
1763
1764 } catch (Exception e) {
1765 fail("wrong exceptionc caught " + e.getClass().getName());
1766 }
1767 double[] derivatives = new double[] { x + y - z, 1.0, 1.0, -1.0 };
1768 DerivativeStructure t = factory.build(derivatives);
1769 checkEquals(xRef.add(yRef.subtract(zRef)), t, 1.0e-15);
1770 UnitTestUtils.customAssertEquals(derivatives, xRef.add(yRef.subtract(zRef)).getAllDerivatives(), 1.0e-15);
1771 }
1772
1773 @Test
1774 void testLinearCombination1DSDS() {
1775 DSFactory factory = new DSFactory(6, 1);
1776 final DerivativeStructure[] a = new DerivativeStructure[] {
1777 factory.variable(0, -1321008684645961.0 / 268435456.0),
1778 factory.variable(1, -5774608829631843.0 / 268435456.0),
1779 factory.variable(2, -7645843051051357.0 / 8589934592.0)
1780 };
1781 final DerivativeStructure[] b = new DerivativeStructure[] {
1782 factory.variable(3, -5712344449280879.0 / 2097152.0),
1783 factory.variable(4, -4550117129121957.0 / 2097152.0),
1784 factory.variable(5, 8846951984510141.0 / 131072.0)
1785 };
1786
1787 final DerivativeStructure abSumInline = a[0].linearCombination(a[0], b[0], a[1], b[1], a[2], b[2]);
1788 final DerivativeStructure abSumArray = a[0].linearCombination(a, b);
1789
1790 assertEquals(abSumInline.getValue(), abSumArray.getValue(), 0);
1791 assertEquals(-1.8551294182586248737720779899, abSumInline.getValue(), 1.0e-15);
1792 assertEquals(b[0].getValue(), abSumInline.getPartialDerivative(1, 0, 0, 0, 0, 0), 1.0e-15);
1793 assertEquals(b[1].getValue(), abSumInline.getPartialDerivative(0, 1, 0, 0, 0, 0), 1.0e-15);
1794 assertEquals(b[2].getValue(), abSumInline.getPartialDerivative(0, 0, 1, 0, 0, 0), 1.0e-15);
1795 assertEquals(a[0].getValue(), abSumInline.getPartialDerivative(0, 0, 0, 1, 0, 0), 1.0e-15);
1796 assertEquals(a[1].getValue(), abSumInline.getPartialDerivative(0, 0, 0, 0, 1, 0), 1.0e-15);
1797 assertEquals(a[2].getValue(), abSumInline.getPartialDerivative(0, 0, 0, 0, 0, 1), 1.0e-15);
1798
1799 }
1800
1801 @Test
1802 void testLinearCombination1DoubleDS() {
1803 DSFactory factory = new DSFactory(3, 1);
1804 final double[] a = new double[] {
1805 -1321008684645961.0 / 268435456.0,
1806 -5774608829631843.0 / 268435456.0,
1807 -7645843051051357.0 / 8589934592.0
1808 };
1809 final DerivativeStructure[] b = new DerivativeStructure[] {
1810 factory.variable(0, -5712344449280879.0 / 2097152.0),
1811 factory.variable(1, -4550117129121957.0 / 2097152.0),
1812 factory.variable(2, 8846951984510141.0 / 131072.0)
1813 };
1814
1815 final DerivativeStructure abSumInline = b[0].linearCombination(a[0], b[0],
1816 a[1], b[1],
1817 a[2], b[2]);
1818 final DerivativeStructure abSumArray = b[0].linearCombination(a, b);
1819
1820 assertEquals(abSumInline.getValue(), abSumArray.getValue(), 0);
1821 assertEquals(-1.8551294182586248737720779899, abSumInline.getValue(), 1.0e-15);
1822 assertEquals(a[0], abSumInline.getPartialDerivative(1, 0, 0), 1.0e-15);
1823 assertEquals(a[1], abSumInline.getPartialDerivative(0, 1, 0), 1.0e-15);
1824 assertEquals(a[2], abSumInline.getPartialDerivative(0, 0, 1), 1.0e-15);
1825
1826 }
1827
1828 @Test
1829 void testLinearCombination2DSDS() {
1830
1831
1832 Well1024a random = new Well1024a(0xc6af886975069f11l);
1833
1834 DSFactory factory = new DSFactory(4, 1);
1835 for (int i = 0; i < 10000; ++i) {
1836 final DerivativeStructure[] u = new DerivativeStructure[factory.getCompiler().getFreeParameters()];
1837 final DerivativeStructure[] v = new DerivativeStructure[factory.getCompiler().getFreeParameters()];
1838 for (int j = 0; j < u.length; ++j) {
1839 u[j] = factory.variable(j, 1e17 * random.nextDouble());
1840 v[j] = factory.constant(1e17 * random.nextDouble());
1841 }
1842
1843 DerivativeStructure lin = u[0].linearCombination(u[0], v[0], u[1], v[1]);
1844 double ref = u[0].getValue() * v[0].getValue() +
1845 u[1].getValue() * v[1].getValue();
1846 assertEquals(ref, lin.getValue(), 1.0e-15 * FastMath.abs(ref));
1847 assertEquals(v[0].getValue(), lin.getPartialDerivative(1, 0, 0, 0), 1.0e-15 * FastMath.abs(v[0].getValue()));
1848 assertEquals(v[1].getValue(), lin.getPartialDerivative(0, 1, 0, 0), 1.0e-15 * FastMath.abs(v[1].getValue()));
1849
1850 lin = u[0].linearCombination(u[0], v[0], u[1], v[1], u[2], v[2]);
1851 ref = u[0].getValue() * v[0].getValue() +
1852 u[1].getValue() * v[1].getValue() +
1853 u[2].getValue() * v[2].getValue();
1854 assertEquals(ref, lin.getValue(), 1.0e-15 * FastMath.abs(ref));
1855 assertEquals(v[0].getValue(), lin.getPartialDerivative(1, 0, 0, 0), 1.0e-15 * FastMath.abs(v[0].getValue()));
1856 assertEquals(v[1].getValue(), lin.getPartialDerivative(0, 1, 0, 0), 1.0e-15 * FastMath.abs(v[1].getValue()));
1857 assertEquals(v[2].getValue(), lin.getPartialDerivative(0, 0, 1, 0), 1.0e-15 * FastMath.abs(v[2].getValue()));
1858
1859 lin = u[0].linearCombination(u[0], v[0], u[1], v[1], u[2], v[2], u[3], v[3]);
1860 ref = u[0].getValue() * v[0].getValue() +
1861 u[1].getValue() * v[1].getValue() +
1862 u[2].getValue() * v[2].getValue() +
1863 u[3].getValue() * v[3].getValue();
1864 assertEquals(ref, lin.getValue(), 1.0e-15 * FastMath.abs(ref));
1865 assertEquals(v[0].getValue(), lin.getPartialDerivative(1, 0, 0, 0), 1.0e-15 * FastMath.abs(v[0].getValue()));
1866 assertEquals(v[1].getValue(), lin.getPartialDerivative(0, 1, 0, 0), 1.0e-15 * FastMath.abs(v[1].getValue()));
1867 assertEquals(v[2].getValue(), lin.getPartialDerivative(0, 0, 1, 0), 1.0e-15 * FastMath.abs(v[2].getValue()));
1868 assertEquals(v[3].getValue(), lin.getPartialDerivative(0, 0, 0, 1), 1.0e-15 * FastMath.abs(v[3].getValue()));
1869
1870 }
1871 }
1872
1873 @Test
1874 void testLinearCombination2DoubleDS() {
1875
1876
1877 Well1024a random = new Well1024a(0xc6af886975069f11l);
1878
1879 DSFactory factory = new DSFactory(4, 1);
1880 for (int i = 0; i < 10000; ++i) {
1881 final double[] u = new double[4];
1882 final DerivativeStructure[] v = new DerivativeStructure[factory.getCompiler().getFreeParameters()];
1883 for (int j = 0; j < u.length; ++j) {
1884 u[j] = 1e17 * random.nextDouble();
1885 v[j] = factory.variable(j, 1e17 * random.nextDouble());
1886 }
1887
1888 DerivativeStructure lin = v[0].linearCombination(u[0], v[0], u[1], v[1]);
1889 double ref = u[0] * v[0].getValue() +
1890 u[1] * v[1].getValue();
1891 assertEquals(ref, lin.getValue(), 1.0e-15 * FastMath.abs(ref));
1892 assertEquals(u[0], lin.getPartialDerivative(1, 0, 0, 0), 1.0e-15 * FastMath.abs(v[0].getValue()));
1893 assertEquals(u[1], lin.getPartialDerivative(0, 1, 0, 0), 1.0e-15 * FastMath.abs(v[1].getValue()));
1894
1895 lin = v[0].linearCombination(u[0], v[0], u[1], v[1], u[2], v[2]);
1896 ref = u[0] * v[0].getValue() +
1897 u[1] * v[1].getValue() +
1898 u[2] * v[2].getValue();
1899 assertEquals(ref, lin.getValue(), 1.0e-15 * FastMath.abs(ref));
1900 assertEquals(u[0], lin.getPartialDerivative(1, 0, 0, 0), 1.0e-15 * FastMath.abs(v[0].getValue()));
1901 assertEquals(u[1], lin.getPartialDerivative(0, 1, 0, 0), 1.0e-15 * FastMath.abs(v[1].getValue()));
1902 assertEquals(u[2], lin.getPartialDerivative(0, 0, 1, 0), 1.0e-15 * FastMath.abs(v[2].getValue()));
1903
1904 lin = v[0].linearCombination(u[0], v[0], u[1], v[1], u[2], v[2], u[3], v[3]);
1905 ref = u[0] * v[0].getValue() +
1906 u[1] * v[1].getValue() +
1907 u[2] * v[2].getValue() +
1908 u[3] * v[3].getValue();
1909 assertEquals(ref, lin.getValue(), 1.0e-15 * FastMath.abs(ref));
1910 assertEquals(u[0], lin.getPartialDerivative(1, 0, 0, 0), 1.0e-15 * FastMath.abs(v[0].getValue()));
1911 assertEquals(u[1], lin.getPartialDerivative(0, 1, 0, 0), 1.0e-15 * FastMath.abs(v[1].getValue()));
1912 assertEquals(u[2], lin.getPartialDerivative(0, 0, 1, 0), 1.0e-15 * FastMath.abs(v[2].getValue()));
1913 assertEquals(u[3], lin.getPartialDerivative(0, 0, 0, 1), 1.0e-15 * FastMath.abs(v[3].getValue()));
1914
1915 }
1916 }
1917
1918 @Test
1919 void testSerialization() {
1920 DerivativeStructure a = new DSFactory(3, 2).variable(0, 1.3);
1921 DerivativeStructure b = (DerivativeStructure) UnitTestUtils.serializeAndRecover(a);
1922 assertEquals(a.getFreeParameters(), b.getFreeParameters());
1923 assertEquals(a.getOrder(), b.getOrder());
1924 checkEquals(a, b, 1.0e-15);
1925 }
1926
1927 @Test
1928 void testZero() {
1929 DerivativeStructure zero = new DSFactory(3, 2).variable(2, 17.0).getField().getZero();
1930 double[] a = zero.getAllDerivatives();
1931 assertEquals(10, a.length);
1932 for (int i = 0; i < a.length; ++i) {
1933 assertEquals(0.0, a[i], 1.0e-15);
1934 }
1935 }
1936
1937 @Test
1938 void testOne() {
1939 DerivativeStructure one = new DSFactory(3, 2).variable(2, 17.0).getField().getOne();
1940 double[] a = one.getAllDerivatives();
1941 assertEquals(10, a.length);
1942 for (int i = 0; i < a.length; ++i) {
1943 assertEquals(i == 0 ? 1.0 : 0.0, a[i], 1.0e-15);
1944 }
1945 }
1946
1947 @Test
1948 void testMap() {
1949 List<int[]> pairs = new ArrayList<>();
1950 for (int parameters = 1; parameters < 5; ++parameters) {
1951 for (int order = 0; order < 3; ++order) {
1952 pairs.add(new int[] { parameters, order });
1953 }
1954 }
1955 Map<Field<?>, Integer> map = new HashMap<>();
1956 for (int i = 0; i < 1000; ++i) {
1957
1958 int parameters = pairs.get(i % pairs.size())[0];
1959 int order = pairs.get(i % pairs.size())[1];
1960 map.put(new DSFactory(parameters, order).constant(17.0).getField(), 0);
1961 }
1962
1963
1964
1965 assertEquals(pairs.size(), map.size());
1966 @SuppressWarnings("unchecked")
1967 Field<DerivativeStructure> first = (Field<DerivativeStructure>) map.entrySet().iterator().next().getKey();
1968 assertEquals(first, first);
1969 assertNotEquals(first, Binary64Field.getInstance());
1970
1971 }
1972
1973 @Test
1974 void testRebaseConditions() {
1975 final DSFactory f32 = new DSFactory(3, 2);
1976 final DSFactory f22 = new DSFactory(2, 2);
1977 final DSFactory f31 = new DSFactory(3, 1);
1978 try {
1979 f32.variable(0, 0).rebase(f22.variable(0, 0), f22.variable(1, 1.0));
1980 } catch (MathIllegalArgumentException miae) {
1981 assertEquals(LocalizedCoreFormats.DIMENSIONS_MISMATCH, miae.getSpecifier());
1982 assertEquals(3, ((Integer) miae.getParts()[0]).intValue());
1983 assertEquals(2, ((Integer) miae.getParts()[1]).intValue());
1984 }
1985 try {
1986 f32.variable(0, 0).rebase(f31.variable(0, 0), f31.variable(1, 1.0), f31.variable(2, 2.0));
1987 } catch (MathIllegalArgumentException miae) {
1988 assertEquals(LocalizedCoreFormats.DIMENSIONS_MISMATCH, miae.getSpecifier());
1989 assertEquals(2, ((Integer) miae.getParts()[0]).intValue());
1990 assertEquals(1, ((Integer) miae.getParts()[1]).intValue());
1991 }
1992 }
1993
1994 @Test
1995 void testRebaseNoVariables() {
1996 final DerivativeStructure x = new DSFactory(0, 2).constant(1.0);
1997 assertSame(x, x.rebase());
1998 }
1999
2000 @Test
2001 void testRebaseValueMoreIntermediateThanBase() {
2002 doTestRebaseValue(createBaseVariables(new DSFactory(2, 4), 1.5, -2.0),
2003 q -> new DerivativeStructure[] {
2004 q[0].add(q[1].multiply(3)),
2005 q[0].log(),
2006 q[1].divide(q[0].sin())
2007 },
2008 new DSFactory(3, 4),
2009 p -> p[0].add(p[1].divide(p[2])),
2010 1.0e-15);
2011 }
2012
2013 @Test
2014 void testRebaseValueLessIntermediateThanBase() {
2015 doTestRebaseValue(createBaseVariables(new DSFactory(3, 4), 1.5, -2.0, 0.5),
2016 q -> new DerivativeStructure[] {
2017 q[0].add(q[1].multiply(3)),
2018 q[0].add(q[1]).subtract(q[2])
2019 },
2020 new DSFactory(2, 4),
2021 p -> p[0].multiply(p[1]),
2022 1.0e-15);
2023 }
2024
2025 @Test
2026 void testRebaseValueEqualIntermediateAndBase() {
2027 doTestRebaseValue(createBaseVariables(new DSFactory(2, 4), 1.5, -2.0),
2028 q -> new DerivativeStructure[] {
2029 q[0].add(q[1].multiply(3)),
2030 q[0].add(q[1])
2031 },
2032 new DSFactory(2, 4),
2033 p -> p[0].multiply(p[1]),
2034 1.0e-15);
2035 }
2036
2037 private void doTestRebaseValue(final DerivativeStructure[] q,
2038 final CalculusFieldMultivariateVectorFunction<DerivativeStructure> qToP,
2039 final DSFactory factoryP,
2040 final CalculusFieldMultivariateFunction<DerivativeStructure> f,
2041 final double tol) {
2042
2043
2044 final DerivativeStructure[] pBase = qToP.value(q);
2045
2046
2047 final DerivativeStructure ref = f.value(pBase);
2048
2049
2050 final DerivativeStructure[] pIntermediate = creatIntermediateVariables(factoryP, pBase);
2051
2052
2053 final DerivativeStructure fI = f.value(pIntermediate);
2054
2055
2056 final DerivativeStructure rebased = fI.rebase(pBase);
2057
2058 assertEquals(q[0].getFreeParameters(), ref.getFreeParameters());
2059 assertEquals(q[0].getOrder(), ref.getOrder());
2060 assertEquals(factoryP.getCompiler().getFreeParameters(), fI.getFreeParameters());
2061 assertEquals(factoryP.getCompiler().getOrder(), fI.getOrder());
2062 assertEquals(ref.getFreeParameters(), rebased.getFreeParameters());
2063 assertEquals(ref.getOrder(), rebased.getOrder());
2064
2065 checkEquals(ref, rebased, tol);
2066
2067
2068 checkEquals(composeWithTaylorMap(fI, pBase), rebased, tol);
2069
2070 }
2071
2072 @Test
2073 void testOrdersSum() {
2074 for (int i = 0; i < 6; ++i) {
2075 for (int j = 0; j < 4; ++j) {
2076 DSCompiler compiler = DSCompiler.getCompiler(i, j);
2077 for (int k = 0; k < compiler.getSize(); ++k) {
2078 assertEquals(IntStream.of(compiler.getPartialDerivativeOrders(k)).sum(),
2079 compiler.getPartialDerivativeOrdersSum(k));
2080 }
2081 }
2082 }
2083 }
2084
2085 @Test
2086 void testDivisionVersusAlternativeImplementation() {
2087 final DSFactory factory = new DSFactory(3, 10);
2088 final DerivativeStructure lhs = FastMath.cos(factory.variable(1, 2.5));
2089 final DerivativeStructure rhs = factory.variable(2, -4).multiply(factory.variable(0, -3.));
2090 compareDivisionToVersionViaPower(lhs, rhs, 1e-12);
2091 }
2092
2093 @Test
2094 void testReciprocalVersusAlternativeImplementation() {
2095 final DSFactory factory = new DSFactory(2, 15);
2096 final DerivativeStructure operand = factory.variable(0, 1.).
2097 add(factory.variable(1, 0.).multiply(2.));
2098 compareReciprocalToVersionViaPower(operand, 1e-15);
2099 }
2100
2101 @Test
2102 void testSqrtVersusRootN() {
2103 final DSFactory factory = new DSFactory(2, 8);
2104 DerivativeStructure ds = factory.variable(1, -2.).multiply(factory.variable(0, 1.));
2105 assertArrayEquals(ds.sqrt().getAllDerivatives(), ds.rootN(2).getAllDerivatives(), 1e-10);
2106 }
2107
2108 @Test
2109 void testRunTimeClass() {
2110 Field<DerivativeStructure> field = new DSFactory(3, 2).constant(0.0).getField();
2111 assertEquals(DerivativeStructure.class, field.getRuntimeClass());
2112 }
2113
2114 private void checkF0F1(DerivativeStructure ds, double value, double...derivatives) {
2115
2116
2117 assertEquals(derivatives.length, ds.getFreeParameters());
2118
2119
2120 assertEquals(value, ds.getValue(), 1.0e-15);
2121 assertEquals(value, ds.getPartialDerivative(new int[ds.getFreeParameters()]), 1.0e-15);
2122
2123
2124 for (int i = 0; i < derivatives.length; ++i) {
2125 int[] orders = new int[derivatives.length];
2126 orders[i] = 1;
2127 assertEquals(derivatives[i], ds.getPartialDerivative(orders), 1.0e-15);
2128 }
2129
2130 }
2131
2132 public static void checkEquals(DerivativeStructure ds1, DerivativeStructure ds2, double epsilon) {
2133
2134
2135 assertEquals(ds1.getFreeParameters(), ds2.getFreeParameters());
2136 assertEquals(ds1.getOrder(), ds2.getOrder());
2137
2138 int[] derivatives = new int[ds1.getFreeParameters()];
2139 int sum = 0;
2140 while (true) {
2141
2142 if (sum <= ds1.getOrder()) {
2143 assertEquals(ds1.getPartialDerivative(derivatives),
2144 ds2.getPartialDerivative(derivatives),
2145 epsilon);
2146 }
2147
2148 boolean increment = true;
2149 sum = 0;
2150 for (int i = derivatives.length - 1; i >= 0; --i) {
2151 if (increment) {
2152 if (derivatives[i] == ds1.getOrder()) {
2153 derivatives[i] = 0;
2154 } else {
2155 derivatives[i]++;
2156 increment = false;
2157 }
2158 }
2159 sum += derivatives[i];
2160 }
2161 if (increment) {
2162 return;
2163 }
2164
2165 }
2166
2167 }
2168
2169
2170
2171 private DerivativeStructure composeWithTaylorMap(final DerivativeStructure lhs, final DerivativeStructure[] rhs) {
2172
2173
2174 final DSFactory rhsFactory = rhs[0].getFactory();
2175 final TaylorExpansion[] rhsAsExpansions = new TaylorExpansion[rhs.length];
2176 for (int k = 0; k < rhs.length; k++) {
2177 final DerivativeStructure copied = new DerivativeStructure(rhsFactory, rhs[k].getAllDerivatives());
2178 copied.setDerivativeComponent(0, 0.);
2179 rhsAsExpansions[k] = new TaylorExpansion(copied);
2180 }
2181
2182 final TaylorExpansion lhsAsExpansion = new TaylorExpansion(lhs);
2183
2184
2185 TaylorExpansion te = new TaylorExpansion(rhsFactory.constant(lhs.getValue()));
2186 TaylorExpansion[][] powers = new TaylorExpansion[rhs.length][lhs.getOrder()];
2187
2188
2189 final double[] coefficients = lhsAsExpansion.coefficients;
2190 for (int j = 1; j < coefficients.length; j++) {
2191 if (coefficients[j] != 0.) {
2192 TaylorExpansion inter = new TaylorExpansion(rhsFactory.constant(coefficients[j]));
2193 final int[] orders = lhs.getFactory().getCompiler().getPartialDerivativeOrders(j);
2194 for (int i = 0; i < orders.length; i++) {
2195 if (orders[i] != 0) {
2196 if (powers[i][orders[i] - 1] == null) {
2197
2198 final DerivativeStructure ds = new DerivativeStructure(rhsFactory, rhs[i].getAllDerivatives());
2199 ds.setDerivativeComponent(0, 0.);
2200 TaylorExpansion inter2 = new TaylorExpansion(ds);
2201 for (int k = 1; k < orders[i]; k++) {
2202 inter2 = inter2.multiply(rhsAsExpansions[i]);
2203 }
2204 powers[i][orders[i] - 1] = inter2;
2205 }
2206 inter = inter.multiply(powers[i][orders[i] - 1]);
2207 }
2208 }
2209 te = te.add(inter);
2210 }
2211 }
2212
2213
2214 return te.buildDsEquivalent();
2215 }
2216
2217
2218 private static class TaylorExpansion {
2219
2220
2221 final double[] coefficients;
2222
2223 final double[] factorials;
2224 final DSFactory dsFactory;
2225
2226
2227 TaylorExpansion(final DerivativeStructure ds) {
2228 final double[] data = ds.getAllDerivatives();
2229 this.dsFactory = ds.getFactory();
2230 this.coefficients = new double[data.length];
2231
2232
2233
2234 this.factorials = new double[ds.getOrder() + 1];
2235 Arrays.fill(this.factorials, 1.);
2236 for (int i = 2; i < this.factorials.length; i++) {
2237 this.factorials[i] = this.factorials[i - 1] * (double) (i);
2238 }
2239
2240
2241 for (int j = 0; j < data.length; j++) {
2242 this.coefficients[j] = data[j];
2243 if (this.coefficients[j] != 0.) {
2244 int[] orders = ds.getFactory().getCompiler().getPartialDerivativeOrders(j);
2245 for (int order : orders) {
2246 this.coefficients[j] /= this.factorials[order];
2247 }
2248 }
2249 }
2250 }
2251
2252
2253 public DerivativeStructure buildDsEquivalent() throws MathIllegalArgumentException {
2254 final DSCompiler dsc = this.dsFactory.getCompiler();
2255 final double[] data = new double[this.coefficients.length];
2256 for (int j = 0; j < data.length; j++) {
2257 data[j] = this.coefficients[j];
2258 if (data[j] != 0.) {
2259 int[] orders = dsc.getPartialDerivativeOrders(j);
2260 for (int order : orders) {
2261 data[j] *= this.factorials[order];
2262 }
2263 }
2264 }
2265 return new DerivativeStructure(this.dsFactory, data);
2266 }
2267
2268 TaylorExpansion add(final TaylorExpansion te) {
2269 return new TaylorExpansion(this.buildDsEquivalent().add(te.buildDsEquivalent()));
2270 }
2271
2272 TaylorExpansion multiply(final TaylorExpansion te) {
2273 return new TaylorExpansion(this.buildDsEquivalent().multiply(te.buildDsEquivalent()));
2274 }
2275
2276 }
2277
2278 private DerivativeStructure[] createBaseVariables(final DSFactory factory, double... q) {
2279 final DerivativeStructure[] qDS = new DerivativeStructure[q.length];
2280 for (int i = 0; i < q.length; ++i) {
2281 qDS[i] = factory.variable(i, q[i]);
2282 }
2283 return qDS;
2284 }
2285
2286 private DerivativeStructure[] creatIntermediateVariables(final DSFactory factory, DerivativeStructure... pBase) {
2287 final DerivativeStructure[] pIntermediate = new DerivativeStructure[pBase.length];
2288 for (int i = 0; i < pBase.length; ++i) {
2289 pIntermediate[i] = factory.variable(i, pBase[i].getValue());
2290 }
2291 return pIntermediate;
2292 }
2293
2294 private void compareDivisionToVersionViaPower(final DerivativeStructure lhs, final DerivativeStructure rhs,
2295 final double tolerance) {
2296 DSCompiler compiler = lhs.getFactory().getCompiler();
2297 final double[] result = new double[compiler.getSize()];
2298 compiler.multiply(lhs.getAllDerivatives(), 0, rhs.reciprocal().getAllDerivatives(), 0, result, 0);
2299 final double[] result2 = result.clone();
2300 compiler.divide(lhs.getAllDerivatives(), 0, rhs.getAllDerivatives(), 0, result2, 0);
2301 assertArrayEquals(result, result2, tolerance);
2302 }
2303
2304 private void compareReciprocalToVersionViaPower(final DerivativeStructure operand, final double tolerance) {
2305 DSCompiler compiler = operand.getFactory().getCompiler();
2306 final double[] result = new double[compiler.getSize()];
2307 compiler.pow(operand.getAllDerivatives(), 0, -1, result, 0);
2308 final double[] result2 = result.clone();
2309 compiler.reciprocal(operand.getAllDerivatives(), 0, result2, 0);
2310 assertArrayEquals(result, result2, tolerance);
2311 }
2312
2313 }