1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 package org.hipparchus.analysis.differentiation;
23
24 import org.hipparchus.CalculusFieldElementAbstractTest;
25 import org.hipparchus.Field;
26 import org.hipparchus.UnitTestUtils;
27 import org.hipparchus.analysis.polynomials.PolynomialFunction;
28 import org.hipparchus.random.Well1024a;
29 import org.hipparchus.util.FastMath;
30 import org.hipparchus.util.FieldSinCos;
31 import org.junit.jupiter.api.Test;
32
33 import java.util.ArrayList;
34 import java.util.Arrays;
35 import java.util.HashMap;
36 import java.util.List;
37 import java.util.Map;
38
39 import static org.junit.jupiter.api.Assertions.assertEquals;
40 import static org.junit.jupiter.api.Assertions.assertNotEquals;
41 import static org.junit.jupiter.api.Assertions.assertTrue;
42
43 class SparseGradientTest extends CalculusFieldElementAbstractTest<SparseGradient> {
44
45 @Override
46 protected SparseGradient build(final double x) {
47 return SparseGradient.createVariable(0, x);
48 }
49
50 @Test
51 void testConstant() {
52 double c = 1.0;
53 SparseGradient grad = SparseGradient.createConstant(c);
54 assertEquals(c, grad.getValue(), 1.0e-15);
55 assertEquals(0, grad.getFreeParameters(), 1.0e-15);
56 }
57
58 @Test
59 void testVariable() {
60 double v = 1.0;
61 int id = 0;
62 SparseGradient grad = SparseGradient.createVariable(id, v);
63 assertEquals(v, grad.getValue(), 1.0e-15);
64 assertEquals(1, grad.getFreeParameters(), 1.0e-15);
65 assertEquals(1.0, grad.getDerivative(id), 1.0e-15);
66 }
67
68 @Test
69 void testVarAddition() {
70 final double v1 = 1.0;
71 final double v2 = 2.0;
72 final int id1 = -1;
73 final int id2 = 3;
74 final SparseGradient var1 = SparseGradient.createVariable(id1, v1);
75 final SparseGradient var2 = SparseGradient.createVariable(id2, v2);
76 final SparseGradient sum = var1.add(var2);
77
78 assertEquals(v1 + v2, sum.getValue(), 1.0e-15);
79 assertEquals(2, sum.getFreeParameters());
80 assertEquals(1.0, sum.getDerivative(id1), 1.0e-15);
81 assertEquals(1.0, sum.getDerivative(id2), 1.0e-15);
82 }
83
84 @Test
85 void testSubtraction() {
86 final double v1 = 1.0;
87 final double v2 = 2.0;
88 final int id1 = -1;
89 final int id2 = 3;
90 final SparseGradient var1 = SparseGradient.createVariable(id1, v1);
91 final SparseGradient var2 = SparseGradient.createVariable(id2, v2);
92 final SparseGradient sum = var1.subtract(var2);
93
94 assertEquals(v1 - v2, sum.getValue(), 1.0e-15);
95 assertEquals(2, sum.getFreeParameters());
96 assertEquals(1.0, sum.getDerivative(id1), 1.0e-15);
97 assertEquals(-1.0, sum.getDerivative(id2), 1.0e-15);
98 }
99
100 @Test
101 void testDivision() {
102 final double v1 = 1.0;
103 final double v2 = 2.0;
104 final int id1 = -1;
105 final int id2 = 3;
106 final SparseGradient var1 = SparseGradient.createVariable(id1, v1);
107 final SparseGradient var2 = SparseGradient.createVariable(id2, v2);
108 final SparseGradient out = var1.divide(var2);
109 assertEquals(v1 / v2, out.getValue(), 1.0e-15);
110 assertEquals(2, out.getFreeParameters());
111 assertEquals(1 / v2, out.getDerivative(id1), 1.0e-15);
112 assertEquals(-1 / (v2 * v2), out.getDerivative(id2), 1.0e-15);
113 }
114
115 @Test
116 void testMult() {
117 final double v1 = 1.0;
118 final double c1 = 0.5;
119 final double v2 = 2.0;
120 final int id1 = -1;
121 final int id2 = 3;
122 final SparseGradient var1 = SparseGradient.createVariable(id1, v1);
123 final SparseGradient unit1 = var1.multiply(c1);
124 final SparseGradient unit2 = SparseGradient.createVariable(id2, v2).multiply(var1);
125 final SparseGradient sum = unit1.add(unit2);
126 assertEquals(v1 * c1 + v2 * v1, sum.getValue(), 1.0e-15);
127 assertEquals(2, sum.getFreeParameters());
128 assertEquals(c1 + v2, sum.getDerivative(id1), 1.0e-15);
129 assertEquals(v1, sum.getDerivative(id2), 1.0e-15);
130 }
131
132 @Test
133 void testVarMultInPlace() {
134 final double v1 = 1.0;
135 final double c1 = 0.5;
136 final double v2 = 2.0;
137 final int id1 = -1;
138 final int id2 = 3;
139 final SparseGradient var1 = SparseGradient.createVariable(id1, v1);
140 final SparseGradient sum = var1.multiply(c1);
141 final SparseGradient mult = SparseGradient.createVariable(id2, v2);
142 mult.multiplyInPlace(var1);
143 sum.addInPlace(mult);
144 assertEquals(v1 * c1 + v2 * v1, sum.getValue(), 1.0e-15);
145 assertEquals(2, sum.getFreeParameters());
146 assertEquals(c1 + v2, sum.getDerivative(id1), 1.0e-15);
147 assertEquals(v1, sum.getDerivative(id2), 1.0e-15);
148 }
149
150 @Test
151 void testPrimitiveAdd() {
152 checkF0F1(SparseGradient.createVariable(0, 1.0).add(5), 6.0, 1.0, 0.0, 0.0);
153 checkF0F1(SparseGradient.createVariable(1, 2.0).add(5), 7.0, 0.0, 1.0, 0.0);
154 checkF0F1(SparseGradient.createVariable(2, 3.0).add(5), 8.0, 0.0, 0.0, 1.0);
155 }
156
157 @Test
158 void testAdd() {
159 SparseGradient x = SparseGradient.createVariable(0, 1.0);
160 SparseGradient y = SparseGradient.createVariable(1, 2.0);
161 SparseGradient z = SparseGradient.createVariable(2, 3.0);
162 SparseGradient xyz = x.add(y.add(z));
163 checkF0F1(xyz, x.getValue() + y.getValue() + z.getValue(), 1.0, 1.0, 1.0);
164 }
165
166 @Test
167 void testPrimitiveSubtract() {
168 checkF0F1(SparseGradient.createVariable(0, 1.0).subtract(5), -4.0, 1.0, 0.0, 0.0);
169 checkF0F1(SparseGradient.createVariable(1, 2.0).subtract(5), -3.0, 0.0, 1.0, 0.0);
170 checkF0F1(SparseGradient.createVariable(2, 3.0).subtract(5), -2.0, 0.0, 0.0, 1.0);
171 }
172
173 @Test
174 void testSubtract() {
175 SparseGradient x = SparseGradient.createVariable(0, 1.0);
176 SparseGradient y = SparseGradient.createVariable(1, 2.0);
177 SparseGradient z = SparseGradient.createVariable(2, 3.0);
178 SparseGradient xyz = x.subtract(y.subtract(z));
179 checkF0F1(xyz, x.getValue() - (y.getValue() - z.getValue()), 1.0, -1.0, 1.0);
180 }
181
182 @Test
183 void testPrimitiveMultiply() {
184 checkF0F1(SparseGradient.createVariable(0, 1.0).multiply(5), 5.0, 5.0, 0.0, 0.0);
185 checkF0F1(SparseGradient.createVariable(1, 2.0).multiply(5), 10.0, 0.0, 5.0, 0.0);
186 checkF0F1(SparseGradient.createVariable(2, 3.0).multiply(5), 15.0, 0.0, 0.0, 5.0);
187 }
188
189 @Test
190 void testMultiply() {
191 SparseGradient x = SparseGradient.createVariable(0, 1.0);
192 SparseGradient y = SparseGradient.createVariable(1, 2.0);
193 SparseGradient z = SparseGradient.createVariable(2, 3.0);
194 SparseGradient xyz = x.multiply(y.multiply(z));
195 checkF0F1(xyz, 6.0, 6.0, 3.0, 2.0);
196 }
197
198 @Test
199 void testNegate() {
200 checkF0F1(SparseGradient.createVariable(0, 1.0).negate(), -1.0, -1.0, 0.0, 0.0);
201 checkF0F1(SparseGradient.createVariable(1, 2.0).negate(), -2.0, 0.0, -1.0, 0.0);
202 checkF0F1(SparseGradient.createVariable(2, 3.0).negate(), -3.0, 0.0, 0.0, -1.0);
203 }
204
205 @Test
206 void testReciprocal() {
207 for (double x = 0.1; x < 1.2; x += 0.1) {
208 SparseGradient r = SparseGradient.createVariable(0, x).reciprocal();
209 assertEquals(1 / x, r.getValue(), 1.0e-15);
210 final double expected = -1 / (x * x);
211 assertEquals(expected, r.getDerivative(0), 1.0e-15 * FastMath.abs(expected));
212 }
213 }
214
215 @Test
216 void testPow() {
217 for (int n = 0; n < 10; ++n) {
218
219 SparseGradient x = SparseGradient.createVariable(0, 1.0);
220 SparseGradient y = SparseGradient.createVariable(1, 2.0);
221 SparseGradient z = SparseGradient.createVariable(2, 3.0);
222 List<SparseGradient> list = Arrays.asList(x, y, z,
223 x.add(y).add(z),
224 x.multiply(y).multiply(z));
225
226 if (n == 0) {
227 for (SparseGradient sg : list) {
228 assertEquals(sg.getField().getOne(), sg.pow(n));
229 }
230 } else if (n == 1) {
231 for (SparseGradient sg : list) {
232 assertEquals(sg, sg.pow(n));
233 }
234 } else {
235 for (SparseGradient sg : list) {
236 SparseGradient p = sg.getField().getOne();
237 for (int i = 0; i < n; ++i) {
238 p = p.multiply(sg);
239 }
240 assertEquals(p, sg.pow(n));
241 }
242 }
243 }
244 }
245
246 @Test
247 void testPowDoubleDS() {
248 for (int maxOrder = 1; maxOrder < 5; ++maxOrder) {
249
250 SparseGradient x = SparseGradient.createVariable(0, 0.1);
251 SparseGradient y = SparseGradient.createVariable(1, 0.2);
252 SparseGradient z = SparseGradient.createVariable(2, 0.3);
253 List<SparseGradient> list = Arrays.asList(x, y, z,
254 x.add(y).add(z),
255 x.multiply(y).multiply(z));
256
257 for (SparseGradient sg : list) {
258
259 for (double a : new double[] { 0.0, 0.1, 1.0, 2.0, 5.0 }) {
260 SparseGradient reference = (a == 0) ?
261 x.getField().getZero() :
262 SparseGradient.createConstant(a).pow(sg);
263 SparseGradient result = SparseGradient.pow(a, sg);
264 assertEquals(reference, result);
265 }
266
267 }
268
269
270 SparseGradient negEvenInteger = SparseGradient.pow(-2.0, SparseGradient.createVariable(0, 2.0));
271 assertEquals(4.0, negEvenInteger.getValue(), 1.0e-15);
272 assertTrue(Double.isNaN(negEvenInteger.getDerivative(0)));
273 SparseGradient negOddInteger = SparseGradient.pow(-2.0, SparseGradient.createVariable(0, 3.0));
274 assertEquals(-8.0, negOddInteger.getValue(), 1.0e-15);
275 assertTrue(Double.isNaN(negOddInteger.getDerivative(0)));
276 SparseGradient negNonInteger = SparseGradient.pow(-2.0, SparseGradient.createVariable(0, 2.001));
277 assertTrue(Double.isNaN(negNonInteger.getValue()));
278 assertTrue(Double.isNaN(negNonInteger.getDerivative(0)));
279
280 SparseGradient zeroNeg = SparseGradient.pow(0.0, SparseGradient.createVariable(0, -1.0));
281 assertTrue(Double.isNaN(zeroNeg.getValue()));
282 assertTrue(Double.isNaN(zeroNeg.getDerivative(0)));
283 SparseGradient posNeg = SparseGradient.pow(2.0, SparseGradient.createVariable(0, -2.0));
284 assertEquals(1.0 / 4.0, posNeg.getValue(), 1.0e-15);
285 assertEquals(FastMath.log(2.0) / 4.0, posNeg.getDerivative(0), 1.0e-15);
286
287
288 SparseGradient zeroZero = SparseGradient.pow(0.0, SparseGradient.createVariable(0, 0.0));
289
290
291 assertEquals(1.0, zeroZero.getValue(), 1.0e-15);
292 assertEquals(Double.NEGATIVE_INFINITY, zeroZero.getDerivative(0), 1.0e-15);
293 assertEquals(0.0, zeroZero.getDerivative(1), 1.0e-15);
294 assertEquals(0.0, zeroZero.getDerivative(2), 1.0e-15);
295
296 }
297
298 }
299
300 @Test
301 void testExpression() {
302 double epsilon = 2.5e-13;
303 for (double x = 0; x < 2; x += 0.2) {
304 SparseGradient sgX = SparseGradient.createVariable(0, x);
305 for (double y = 0; y < 2; y += 0.2) {
306 SparseGradient sgY = SparseGradient.createVariable(1, y);
307 for (double z = 0; z >- 2; z -= 0.2) {
308 SparseGradient sgZ = SparseGradient.createVariable(2, z);
309
310
311 SparseGradient sg =
312 sgZ.linearCombination(1, sgX,
313 5, sgX.multiply(sgY),
314 -2, sgZ,
315 1, sgZ.linearCombination(8, sgZ.multiply(sgX), -1, sgY).pow(3));
316 double f = x + 5 * x * y - 2 * z + FastMath.pow(8 * z * x - y, 3);
317 assertEquals(f, sg.getValue(), FastMath.abs(epsilon * f));
318
319
320 double dfdx = 1 + 5 * y + 24 * z * FastMath.pow(8 * z * x - y, 2);
321 assertEquals(dfdx, sg.getDerivative(0), FastMath.abs(epsilon * dfdx));
322
323 }
324
325 }
326 }
327 }
328
329 @Test
330 void testCompositionOneVariableX() {
331 double epsilon = 1.0e-13;
332 for (double x = 0.1; x < 1.2; x += 0.1) {
333 SparseGradient sgX = SparseGradient.createVariable(0, x);
334 for (double y = 0.1; y < 1.2; y += 0.1) {
335 SparseGradient sgY = SparseGradient.createConstant(y);
336 SparseGradient f = sgX.divide(sgY).sqrt();
337 double f0 = FastMath.sqrt(x / y);
338 assertEquals(f0, f.getValue(), FastMath.abs(epsilon * f0));
339 double f1 = 1 / (2 * FastMath.sqrt(x * y));
340 assertEquals(f1, f.getDerivative(0), FastMath.abs(epsilon * f1));
341 }
342 }
343 }
344
345 @Test
346 void testTrigo() {
347 double epsilon = 2.0e-12;
348 for (double x = 0.1; x < 1.2; x += 0.1) {
349 SparseGradient sgX = SparseGradient.createVariable(0, x);
350 for (double y = 0.1; y < 1.2; y += 0.1) {
351 SparseGradient sgY = SparseGradient.createVariable(1, y);
352 for (double z = 0.1; z < 1.2; z += 0.1) {
353 SparseGradient sgZ = SparseGradient.createVariable(2, z);
354 SparseGradient f = sgX.divide(sgY.cos().add(sgZ.tan())).sin();
355 double a = FastMath.cos(y) + FastMath.tan(z);
356 double f0 = FastMath.sin(x / a);
357 assertEquals(f0, f.getValue(), FastMath.abs(epsilon * f0));
358 double dfdx = FastMath.cos(x / a) / a;
359 assertEquals(dfdx, f.getDerivative(0), FastMath.abs(epsilon * dfdx));
360 double dfdy = x * FastMath.sin(y) * dfdx / a;
361 assertEquals(dfdy, f.getDerivative(1), FastMath.abs(epsilon * dfdy));
362 double cz = FastMath.cos(z);
363 double cz2 = cz * cz;
364 double dfdz = -x * dfdx / (a * cz2);
365 assertEquals(dfdz, f.getDerivative(2), FastMath.abs(epsilon * dfdz));
366 }
367 }
368 }
369 }
370
371 @Test
372 void testSqrtDefinition() {
373 for (double x = 0.1; x < 1.2; x += 0.001) {
374 SparseGradient sgX = SparseGradient.createVariable(0, x);
375 SparseGradient sqrt1 = sgX.pow(0.5);
376 SparseGradient sqrt2 = sgX.sqrt();
377 SparseGradient zero = sqrt1.subtract(sqrt2);
378 checkF0F1(zero, 0.0, 0.0);
379 }
380 }
381
382 @Test
383 void testRootNSingularity() {
384 for (int n = 2; n < 10; ++n) {
385 SparseGradient sgZero = SparseGradient.createVariable(0, 0.0);
386 SparseGradient rootN = sgZero.rootN(n);
387 assertEquals(0.0, rootN.getValue(), 1.0e-5);
388 assertTrue(Double.isInfinite(rootN.getDerivative(0)));
389 assertTrue(rootN.getDerivative(0) > 0);
390 }
391
392 }
393
394 @Test
395 void testSqrtPow2() {
396 for (double x = 0.1; x < 1.2; x += 0.001) {
397 SparseGradient sgX = SparseGradient.createVariable(0, x);
398 SparseGradient rebuiltX = sgX.multiply(sgX).sqrt();
399 SparseGradient zero = rebuiltX.subtract(sgX);
400 checkF0F1(zero, 0.0, 0.0);
401 }
402 }
403
404 @Test
405 void testCbrtDefinition() {
406 for (double x = 0.1; x < 1.2; x += 0.001) {
407 SparseGradient sgX = SparseGradient.createVariable(0, x);
408 SparseGradient cbrt1 = sgX.pow(1.0 / 3.0);
409 SparseGradient cbrt2 = sgX.cbrt();
410 SparseGradient zero = cbrt1.subtract(cbrt2);
411 checkF0F1(zero, 0.0, 0.0);
412 }
413 }
414
415 @Test
416 void testCbrtPow3() {
417 for (double x = 0.1; x < 1.2; x += 0.001) {
418 SparseGradient sgX = SparseGradient.createVariable(0, x);
419 SparseGradient rebuiltX = sgX.multiply(sgX.multiply(sgX)).cbrt();
420 SparseGradient zero = rebuiltX.subtract(sgX);
421 checkF0F1(zero, 0.0, 0.0);
422 }
423 }
424
425 @Test
426 void testPowReciprocalPow() {
427 for (double x = 0.1; x < 1.2; x += 0.01) {
428 SparseGradient sgX = SparseGradient.createVariable(0, x);
429 for (double y = 0.1; y < 1.2; y += 0.01) {
430 SparseGradient sgY = SparseGradient.createVariable(1, y);
431 SparseGradient rebuiltX = sgX.pow(sgY).pow(sgY.reciprocal());
432 SparseGradient zero = rebuiltX.subtract(sgX);
433 checkF0F1(zero, 0.0, 0.0, 0.0);
434 }
435 }
436 }
437
438 @Test
439 void testHypotDefinition() {
440 for (double x = -1.7; x < 2; x += 0.2) {
441 SparseGradient sgX = SparseGradient.createVariable(0, x);
442 for (double y = -1.7; y < 2; y += 0.2) {
443 SparseGradient sgY = SparseGradient.createVariable(1, y);
444 SparseGradient hypot = SparseGradient.hypot(sgY, sgX);
445 SparseGradient ref = sgX.multiply(sgX).add(sgY.multiply(sgY)).sqrt();
446 SparseGradient zero = hypot.subtract(ref);
447 checkF0F1(zero, 0.0, 0.0, 0.0);
448
449 }
450 }
451 }
452
453 @Test
454 void testHypotNoOverflow() {
455
456 SparseGradient sgX = SparseGradient.createVariable(0, +3.0e250);
457 SparseGradient sgY = SparseGradient.createVariable(1, -4.0e250);
458 SparseGradient hypot = SparseGradient.hypot(sgX, sgY);
459 assertEquals(5.0e250, hypot.getValue(), 1.0e235);
460 assertEquals(sgX.getValue() / hypot.getValue(), hypot.getDerivative(0), 1.0e-10);
461 assertEquals(sgY.getValue() / hypot.getValue(), hypot.getDerivative(1), 1.0e-10);
462
463 SparseGradient sqrt = sgX.multiply(sgX).add(sgY.multiply(sgY)).sqrt();
464 assertTrue(Double.isInfinite(sqrt.getValue()));
465
466 }
467
468 @Test
469 void testHypotNeglectible() {
470
471 SparseGradient sgSmall = SparseGradient.createVariable(0, +3.0e-10);
472 SparseGradient sgLarge = SparseGradient.createVariable(1, -4.0e25);
473
474 assertEquals(sgLarge.abs().getValue(),
475 SparseGradient.hypot(sgSmall, sgLarge).getValue(),
476 1.0e-10);
477 assertEquals(0,
478 SparseGradient.hypot(sgSmall, sgLarge).getDerivative(0),
479 1.0e-10);
480 assertEquals(-1,
481 SparseGradient.hypot(sgSmall, sgLarge).getDerivative(1),
482 1.0e-10);
483
484 assertEquals(sgLarge.abs().getValue(),
485 SparseGradient.hypot(sgLarge, sgSmall).getValue(),
486 1.0e-10);
487 assertEquals(0,
488 SparseGradient.hypot(sgLarge, sgSmall).getDerivative(0),
489 1.0e-10);
490 assertEquals(-1,
491 SparseGradient.hypot(sgLarge, sgSmall).getDerivative(1),
492 1.0e-10);
493
494 }
495
496 @Test
497 void testHypotSpecial() {
498 assertTrue(Double.isNaN(SparseGradient.hypot(SparseGradient.createVariable(0, Double.NaN),
499 SparseGradient.createVariable(0, +3.0e250)).getValue()));
500 assertTrue(Double.isNaN(SparseGradient.hypot(SparseGradient.createVariable(0, +3.0e250),
501 SparseGradient.createVariable(0, Double.NaN)).getValue()));
502 assertTrue(Double.isInfinite(SparseGradient.hypot(SparseGradient.createVariable(0, Double.POSITIVE_INFINITY),
503 SparseGradient.createVariable(0, +3.0e250)).getValue()));
504 assertTrue(Double.isInfinite(SparseGradient.hypot(SparseGradient.createVariable(0, +3.0e250),
505 SparseGradient.createVariable(0, Double.POSITIVE_INFINITY)).getValue()));
506 }
507
508 @Test
509 void testPrimitiveRemainder() {
510 for (double x = -1.7; x < 2; x += 0.2) {
511 SparseGradient sgX = SparseGradient.createVariable(0, x);
512 for (double y = -1.7; y < 2; y += 0.2) {
513 SparseGradient remainder = sgX.remainder(y);
514 SparseGradient ref = sgX.subtract(x - FastMath.IEEEremainder(x, y));
515 SparseGradient zero = remainder.subtract(ref);
516 checkF0F1(zero, 0.0, 0.0, 0.0);
517 }
518 }
519 }
520
521 @Test
522 void testRemainder() {
523 for (double x = -1.7; x < 2; x += 0.2) {
524 SparseGradient sgX = SparseGradient.createVariable(0, x);
525 for (double y = -1.7; y < 2; y += 0.2) {
526 SparseGradient sgY = SparseGradient.createVariable(1, y);
527 SparseGradient remainder = sgX.remainder(sgY);
528 SparseGradient ref = sgX.subtract(sgY.multiply((x - FastMath.IEEEremainder(x, y)) / y));
529 SparseGradient zero = remainder.subtract(ref);
530 checkF0F1(zero, 0.0, 0.0, 0.0);
531 }
532 }
533 }
534
535 @Override
536 @Test
537 public void testExp() {
538 for (double x = 0.1; x < 1.2; x += 0.001) {
539 double refExp = FastMath.exp(x);
540 checkF0F1(SparseGradient.createVariable(0, x).exp(), refExp, refExp);
541 }
542 }
543
544 @Test
545 void testExpm1Definition() {
546 for (double x = 0.1; x < 1.2; x += 0.001) {
547 SparseGradient sgX = SparseGradient.createVariable(0, x);
548 SparseGradient expm11 = sgX.expm1();
549 SparseGradient expm12 = sgX.exp().subtract(sgX.getField().getOne());
550 SparseGradient zero = expm11.subtract(expm12);
551 checkF0F1(zero, 0.0, 0.0);
552 }
553 }
554
555 @Override
556 @Test
557 public void testLog() {
558 for (double x = 0.1; x < 1.2; x += 0.001) {
559 checkF0F1(SparseGradient.createVariable(0, x).log(), FastMath.log(x), 1.0 / x);
560 }
561 }
562
563 @Test
564 void testLog1pDefinition() {
565 for (double x = 0.1; x < 1.2; x += 0.001) {
566 SparseGradient sgX = SparseGradient.createVariable(0, x);
567 SparseGradient log1p1 = sgX.log1p();
568 SparseGradient log1p2 = sgX.add(sgX.getField().getOne()).log();
569 SparseGradient zero = log1p1.subtract(log1p2);
570 checkF0F1(zero, 0.0, 0.0);
571 }
572 }
573
574 @Test
575 void testLog10Definition() {
576 for (double x = 0.1; x < 1.2; x += 0.001) {
577 SparseGradient sgX = SparseGradient.createVariable(0, x);
578 SparseGradient log101 = sgX.log10();
579 SparseGradient log102 = sgX.log().divide(FastMath.log(10.0));
580 SparseGradient zero = log101.subtract(log102);
581 checkF0F1(zero, 0.0, 0.0);
582 }
583 }
584
585 @Test
586 void testLogExp() {
587 for (double x = 0.1; x < 1.2; x += 0.001) {
588 SparseGradient sgX = SparseGradient.createVariable(0, x);
589 SparseGradient rebuiltX = sgX.exp().log();
590 SparseGradient zero = rebuiltX.subtract(sgX);
591 checkF0F1(zero, 0.0, 0.0);
592 }
593 }
594
595 @Test
596 void testLog1pExpm1() {
597 for (double x = 0.1; x < 1.2; x += 0.001) {
598 SparseGradient sgX = SparseGradient.createVariable(0, x);
599 SparseGradient rebuiltX = sgX.expm1().log1p();
600 SparseGradient zero = rebuiltX.subtract(sgX);
601 checkF0F1(zero, 0.0, 0.0);
602 }
603 }
604
605 @Test
606 void testLog10Power() {
607 for (double x = 0.1; x < 1.2; x += 0.001) {
608 SparseGradient sgX = SparseGradient.createVariable(0, x);
609 SparseGradient rebuiltX = SparseGradient.pow(10.0, sgX).log10();
610 SparseGradient zero = rebuiltX.subtract(sgX);
611 checkF0F1(zero, 0.0, 0.0);
612 }
613 }
614
615 @Test
616 public void testSinCos() {
617 for (double x = 0.1; x < 1.2; x += 0.001) {
618 SparseGradient sgX = SparseGradient.createVariable(0, x);
619 SparseGradient sin = sgX.sin();
620 SparseGradient cos = sgX.cos();
621 FieldSinCos<SparseGradient> sinCos = sgX.sinCos();
622 double s = FastMath.sin(x);
623 double c = FastMath.cos(x);
624 checkF0F1(sin, s, c);
625 checkF0F1(cos, c, -s);
626 checkF0F1(sinCos.sin(), s, c);
627 checkF0F1(sinCos.cos(), c, -s);
628 }
629 }
630
631 @Test
632 void testSinAsin() {
633 for (double x = 0.1; x < 1.2; x += 0.001) {
634 SparseGradient sgX = SparseGradient.createVariable(0, x);
635 SparseGradient rebuiltX = sgX.sin().asin();
636 SparseGradient zero = rebuiltX.subtract(sgX);
637 checkF0F1(zero, 0.0, 0.0);
638 }
639 }
640
641 @Test
642 void testCosAcos() {
643 for (double x = 0.1; x < 1.2; x += 0.001) {
644 SparseGradient sgX = SparseGradient.createVariable(0, x);
645 SparseGradient rebuiltX = sgX.cos().acos();
646 SparseGradient zero = rebuiltX.subtract(sgX);
647 checkF0F1(zero, 0.0, 0.0);
648 }
649 }
650
651 @Test
652 void testTanAtan() {
653 for (double x = 0.1; x < 1.2; x += 0.001) {
654 SparseGradient sgX = SparseGradient.createVariable(0, x);
655 SparseGradient rebuiltX = sgX.tan().atan();
656 SparseGradient zero = rebuiltX.subtract(sgX);
657 checkF0F1(zero, 0.0, 0.0);
658 }
659 }
660
661 @Test
662 void testTangentDefinition() {
663 for (double x = 0.1; x < 1.2; x += 0.001) {
664 SparseGradient sgX = SparseGradient.createVariable(0, x);
665 SparseGradient tan1 = sgX.sin().divide(sgX.cos());
666 SparseGradient tan2 = sgX.tan();
667 SparseGradient zero = tan1.subtract(tan2);
668 checkF0F1(zero, 0.0, 0.0);
669 }
670 }
671
672 @Override
673 @Test
674 public void testAtan2() {
675 for (double x = -1.7; x < 2; x += 0.2) {
676 SparseGradient sgX = SparseGradient.createVariable(0, x);
677 for (double y = -1.7; y < 2; y += 0.2) {
678 SparseGradient sgY = SparseGradient.createVariable(1, y);
679 SparseGradient atan2 = SparseGradient.atan2(sgY, sgX);
680 SparseGradient ref = sgY.divide(sgX).atan();
681 if (x < 0) {
682 ref = (y < 0) ? ref.subtract(FastMath.PI) : ref.add(FastMath.PI);
683 }
684 SparseGradient zero = atan2.subtract(ref);
685 checkF0F1(zero, 0.0, 0.0);
686 }
687 }
688 }
689
690 @Test
691 void testAtan2SpecialCasesSparseGradient() {
692
693 SparseGradient pp =
694 SparseGradient.atan2(SparseGradient.createVariable(1, +0.0),
695 SparseGradient.createVariable(1, +0.0));
696 assertEquals(0, pp.getValue(), 1.0e-15);
697 assertEquals(+1, FastMath.copySign(1, pp.getValue()), 1.0e-15);
698
699 SparseGradient pn =
700 SparseGradient.atan2(SparseGradient.createVariable(1, +0.0),
701 SparseGradient.createVariable(1, -0.0));
702 assertEquals(FastMath.PI, pn.getValue(), 1.0e-15);
703
704 SparseGradient np =
705 SparseGradient.atan2(SparseGradient.createVariable(1, -0.0),
706 SparseGradient.createVariable(1, +0.0));
707 assertEquals(0, np.getValue(), 1.0e-15);
708 assertEquals(-1, FastMath.copySign(1, np.getValue()), 1.0e-15);
709
710 SparseGradient nn =
711 SparseGradient.atan2(SparseGradient.createVariable(1, -0.0),
712 SparseGradient.createVariable(1, -0.0));
713 assertEquals(-FastMath.PI, nn.getValue(), 1.0e-15);
714
715 }
716
717 @Test
718 void testSinhDefinition() {
719 for (double x = 0.1; x < 1.2; x += 0.001) {
720 SparseGradient sgX = SparseGradient.createVariable(0, x);
721 SparseGradient sinh1 = sgX.exp().subtract(sgX.exp().reciprocal()).multiply(0.5);
722 SparseGradient sinh2 = sgX.sinh();
723 SparseGradient zero = sinh1.subtract(sinh2);
724 checkF0F1(zero, 0.0, 0.0);
725 }
726 }
727
728 @Test
729 void testCoshDefinition() {
730 for (double x = 0.1; x < 1.2; x += 0.001) {
731 SparseGradient sgX = SparseGradient.createVariable(0, x);
732 SparseGradient cosh1 = sgX.exp().add(sgX.exp().reciprocal()).multiply(0.5);
733 SparseGradient cosh2 = sgX.cosh();
734 SparseGradient zero = cosh1.subtract(cosh2);
735 checkF0F1(zero, 0.0, 0.0);
736 }
737 }
738
739 @Test
740 void testTanhDefinition() {
741 for (double x = 0.1; x < 1.2; x += 0.001) {
742 SparseGradient sgX = SparseGradient.createVariable(0, x);
743 SparseGradient tanh1 = sgX.exp().subtract(sgX.exp().reciprocal()).divide(sgX.exp().add(sgX.exp().reciprocal()));
744 SparseGradient tanh2 = sgX.tanh();
745 SparseGradient zero = tanh1.subtract(tanh2);
746 checkF0F1(zero, 0.0, 0.0);
747 }
748 }
749
750 @Test
751 void testSinhAsinh() {
752 for (double x = 0.1; x < 1.2; x += 0.001) {
753 SparseGradient sgX = SparseGradient.createVariable(0, x);
754 SparseGradient rebuiltX = sgX.sinh().asinh();
755 SparseGradient zero = rebuiltX.subtract(sgX);
756 checkF0F1(zero, 0.0, 0.0);
757 }
758 }
759
760 @Test
761 void testCoshAcosh() {
762 for (double x = 0.1; x < 1.2; x += 0.001) {
763 SparseGradient sgX = SparseGradient.createVariable(0, x);
764 SparseGradient rebuiltX = sgX.cosh().acosh();
765 SparseGradient zero = rebuiltX.subtract(sgX);
766 checkF0F1(zero, 0.0, 0.0);
767 }
768 }
769
770 @Test
771 void testTanhAtanh() {
772 for (double x = 0.1; x < 1.2; x += 0.001) {
773 SparseGradient sgX = SparseGradient.createVariable(0, x);
774 SparseGradient rebuiltX = sgX.tanh().atanh();
775 SparseGradient zero = rebuiltX.subtract(sgX);
776 checkF0F1(zero, 0.0, 0.0);
777 }
778 }
779
780 @Test
781 void testCompositionOneVariableY() {
782 for (double x = 0.1; x < 1.2; x += 0.1) {
783 SparseGradient sgX = SparseGradient.createConstant(x);
784 for (double y = 0.1; y < 1.2; y += 0.1) {
785 SparseGradient sgY = SparseGradient.createVariable(0, y);
786 SparseGradient f = sgX.divide(sgY).sqrt();
787 double f0 = FastMath.sqrt(x / y);
788 double f1 = -x / (2 * y * y * f0);
789 checkF0F1(f, f0, f1);
790 }
791 }
792 }
793
794 @Test
795 void testTaylorPolynomial() {
796 for (double x = 0; x < 1.2; x += 0.1) {
797 SparseGradient sgX = SparseGradient.createVariable(0, x);
798 for (double y = 0; y < 1.2; y += 0.2) {
799 SparseGradient sgY = SparseGradient.createVariable(1, y);
800 for (double z = 0; z < 1.2; z += 0.2) {
801 SparseGradient sgZ = SparseGradient.createVariable(2, z);
802 SparseGradient f = sgX.multiply(3).add(sgZ.multiply(-2)).add(sgY.multiply(5));
803 for (double dx = -0.2; dx < 0.2; dx += 0.2) {
804 for (double dy = -0.2; dy < 0.2; dy += 0.1) {
805 for (double dz = -0.2; dz < 0.2; dz += 0.1) {
806 double ref = 3 * (x + dx) + 5 * (y + dy) -2 * (z + dz);
807 assertEquals(ref, f.taylor(dx, dy, dz), 3.0e-15);
808 }
809 }
810 }
811 }
812 }
813 }
814 }
815
816 @Test
817 void testTaylorAtan2() {
818 double x0 = 0.1;
819 double y0 = -0.3;
820 SparseGradient sgX = SparseGradient.createVariable(0, x0);
821 SparseGradient sgY = SparseGradient.createVariable(1, y0);
822 SparseGradient atan2 = SparseGradient.atan2(sgY, sgX);
823 double maxError = 0;
824 for (double dx = -0.05; dx < 0.05; dx += 0.001) {
825 for (double dy = -0.05; dy < 0.05; dy += 0.001) {
826 double ref = FastMath.atan2(y0 + dy, x0 + dx);
827 maxError = FastMath.max(maxError, FastMath.abs(ref - atan2.taylor(dx, dy)));
828 }
829 }
830 double expectedError = 0.0241;
831 assertEquals(expectedError, maxError, 0.01 * expectedError);
832 }
833
834 @Test
835 public void testAbs() {
836
837 SparseGradient minusOne = SparseGradient.createVariable(0, -1.0);
838 assertEquals(+1.0, minusOne.abs().getValue(), 1.0e-15);
839 assertEquals(-1.0, minusOne.abs().getDerivative(0), 1.0e-15);
840
841 SparseGradient plusOne = SparseGradient.createVariable(0, +1.0);
842 assertEquals(+1.0, plusOne.abs().getValue(), 1.0e-15);
843 assertEquals(+1.0, plusOne.abs().getDerivative(0), 1.0e-15);
844
845 SparseGradient minusZero = SparseGradient.createVariable(0, -0.0);
846 assertEquals(+0.0, minusZero.abs().getValue(), 1.0e-15);
847 assertEquals(-1.0, minusZero.abs().getDerivative(0), 1.0e-15);
848
849 SparseGradient plusZero = SparseGradient.createVariable(0, +0.0);
850 assertEquals(+0.0, plusZero.abs().getValue(), 1.0e-15);
851 assertEquals(+1.0, plusZero.abs().getDerivative(0), 1.0e-15);
852
853 }
854
855 @Override
856 @Test
857 public void testSign() {
858
859 SparseGradient minusOne = SparseGradient.createVariable(0, -1.0);
860 assertEquals(-1.0, minusOne.sign().getValue(), 1.0e-15);
861 assertEquals( 0.0, minusOne.sign().getDerivative(0), 1.0e-15);
862
863 SparseGradient plusOne = SparseGradient.createVariable(0, +1.0);
864 assertEquals(+1.0, plusOne.sign().getValue(), 1.0e-15);
865 assertEquals( 0.0, plusOne.sign().getDerivative(0), 1.0e-15);
866
867 SparseGradient minusZero = SparseGradient.createVariable(0, -0.0);
868 assertEquals(-0.0, minusZero.sign().getValue(), 1.0e-15);
869 assertTrue(Double.doubleToLongBits(minusZero.sign().getValue()) < 0);
870 assertEquals( 0.0, minusZero.sign().getDerivative(0), 1.0e-15);
871
872 SparseGradient plusZero = SparseGradient.createVariable(0, +0.0);
873 assertEquals(+0.0, plusZero.sign().getValue(), 1.0e-15);
874 assertEquals(0, Double.doubleToLongBits(plusZero.sign().getValue()));
875 assertEquals( 0.0, plusZero.sign().getDerivative(0), 1.0e-15);
876
877 }
878
879 @Test
880 void testCeilFloorRintLong() {
881
882 SparseGradient x = SparseGradient.createVariable(0, -1.5);
883 assertEquals(-1.5, x.getValue(), 1.0e-15);
884 assertEquals(+1.0, x.getDerivative(0), 1.0e-15);
885 assertEquals(-1.0, x.ceil().getValue(), 1.0e-15);
886 assertEquals(+0.0, x.ceil().getDerivative(0), 1.0e-15);
887 assertEquals(-2.0, x.floor().getValue(), 1.0e-15);
888 assertEquals(+0.0, x.floor().getDerivative(0), 1.0e-15);
889 assertEquals(-2.0, x.rint().getValue(), 1.0e-15);
890 assertEquals(+0.0, x.rint().getDerivative(0), 1.0e-15);
891 assertEquals(-2.0, x.subtract(x.getField().getOne()).rint().getValue(), 1.0e-15);
892
893 }
894
895 @Test
896 void testCopySign() {
897
898 SparseGradient minusOne = SparseGradient.createVariable(0, -1.0);
899 assertEquals(+1.0, minusOne.copySign(+1.0).getValue(), 1.0e-15);
900 assertEquals(-1.0, minusOne.copySign(+1.0).getDerivative(0), 1.0e-15);
901 assertEquals(-1.0, minusOne.copySign(-1.0).getValue(), 1.0e-15);
902 assertEquals(+1.0, minusOne.copySign(-1.0).getDerivative(0), 1.0e-15);
903 assertEquals(+1.0, minusOne.copySign(+0.0).getValue(), 1.0e-15);
904 assertEquals(-1.0, minusOne.copySign(+0.0).getDerivative(0), 1.0e-15);
905 assertEquals(-1.0, minusOne.copySign(-0.0).getValue(), 1.0e-15);
906 assertEquals(+1.0, minusOne.copySign(-0.0).getDerivative(0), 1.0e-15);
907 assertEquals(+1.0, minusOne.copySign(Double.NaN).getValue(), 1.0e-15);
908 assertEquals(-1.0, minusOne.copySign(Double.NaN).getDerivative(0), 1.0e-15);
909
910 SparseGradient plusOne = SparseGradient.createVariable(0, +1.0);
911 assertEquals(+1.0, plusOne.copySign(+1.0).getValue(), 1.0e-15);
912 assertEquals(+1.0, plusOne.copySign(+1.0).getDerivative(0), 1.0e-15);
913 assertEquals(-1.0, plusOne.copySign(-1.0).getValue(), 1.0e-15);
914 assertEquals(-1.0, plusOne.copySign(-1.0).getDerivative(0), 1.0e-15);
915 assertEquals(+1.0, plusOne.copySign(+0.0).getValue(), 1.0e-15);
916 assertEquals(+1.0, plusOne.copySign(+0.0).getDerivative(0), 1.0e-15);
917 assertEquals(-1.0, plusOne.copySign(-0.0).getValue(), 1.0e-15);
918 assertEquals(-1.0, plusOne.copySign(-0.0).getDerivative(0), 1.0e-15);
919 assertEquals(+1.0, plusOne.copySign(Double.NaN).getValue(), 1.0e-15);
920 assertEquals(+1.0, plusOne.copySign(Double.NaN).getDerivative(0), 1.0e-15);
921
922 }
923
924 @Test
925 void testToDegreesDefinition() {
926 double epsilon = 3.0e-16;
927 for (int maxOrder = 0; maxOrder < 6; ++maxOrder) {
928 for (double x = 0.1; x < 1.2; x += 0.001) {
929 SparseGradient sgX = SparseGradient.createVariable(0, x);
930 assertEquals(FastMath.toDegrees(x), sgX.toDegrees().getValue(), epsilon);
931 assertEquals(180 / FastMath.PI, sgX.toDegrees().getDerivative(0), epsilon);
932 }
933 }
934 }
935
936 @Test
937 void testToRadiansDefinition() {
938 double epsilon = 3.0e-16;
939 for (int maxOrder = 0; maxOrder < 6; ++maxOrder) {
940 for (double x = 0.1; x < 1.2; x += 0.001) {
941 SparseGradient sgX = SparseGradient.createVariable(0, x);
942 assertEquals(FastMath.toRadians(x), sgX.toRadians().getValue(), epsilon);
943 assertEquals(FastMath.PI / 180, sgX.toRadians().getDerivative(0), epsilon);
944 }
945 }
946 }
947
948 @Test
949 void testDegRad() {
950 for (double x = 0.1; x < 1.2; x += 0.001) {
951 SparseGradient sgX = SparseGradient.createVariable(0, x);
952 SparseGradient rebuiltX = sgX.toDegrees().toRadians();
953 SparseGradient zero = rebuiltX.subtract(sgX);
954 checkF0F1(zero, 0, 0);
955 }
956 }
957
958 @Test
959 void testCompose() {
960 PolynomialFunction poly =
961 new PolynomialFunction(new double[] { 1.0, 2.0, 3.0, 4.0, 5.0, 6.0 });
962 for (double x = 0.1; x < 1.2; x += 0.001) {
963 SparseGradient sgX = SparseGradient.createVariable(0, x);
964 SparseGradient sgY1 = sgX.getField().getZero();
965 for (int i = poly.degree(); i >= 0; --i) {
966 sgY1 = sgY1.multiply(sgX).add(poly.getCoefficients()[i]);
967 }
968 SparseGradient sgY2 = sgX.compose(poly.value(x), poly.polynomialDerivative().value(x));
969 SparseGradient zero = sgY1.subtract(sgY2);
970 checkF0F1(zero, 0.0, 0.0);
971 }
972 }
973
974 @Test
975 void testField() {
976 SparseGradient x = SparseGradient.createVariable(0, 1.0);
977 checkF0F1(x.getField().getZero(), 0.0, 0.0, 0.0, 0.0);
978 checkF0F1(x.getField().getOne(), 1.0, 0.0, 0.0, 0.0);
979 assertEquals(SparseGradient.class, x.getField().getRuntimeClass());
980 }
981
982 @Test
983 void testLinearCombination1DSDS() {
984 final SparseGradient[] a = new SparseGradient[] {
985 SparseGradient.createVariable(0, -1321008684645961.0 / 268435456.0),
986 SparseGradient.createVariable(1, -5774608829631843.0 / 268435456.0),
987 SparseGradient.createVariable(2, -7645843051051357.0 / 8589934592.0)
988 };
989 final SparseGradient[] b = new SparseGradient[] {
990 SparseGradient.createVariable(3, -5712344449280879.0 / 2097152.0),
991 SparseGradient.createVariable(4, -4550117129121957.0 / 2097152.0),
992 SparseGradient.createVariable(5, 8846951984510141.0 / 131072.0)
993 };
994
995 final SparseGradient abSumInline = a[0].linearCombination(a[0], b[0], a[1], b[1], a[2], b[2]);
996 final SparseGradient abSumArray = a[0].linearCombination(a, b);
997
998 assertEquals(abSumInline.getValue(), abSumArray.getValue(), 1.0e-15);
999 assertEquals(-1.8551294182586248737720779899, abSumInline.getValue(), 1.0e-15);
1000 assertEquals(b[0].getValue(), abSumInline.getDerivative(0), 1.0e-15);
1001 assertEquals(b[1].getValue(), abSumInline.getDerivative(1), 1.0e-15);
1002 assertEquals(b[2].getValue(), abSumInline.getDerivative(2), 1.0e-15);
1003 assertEquals(a[0].getValue(), abSumInline.getDerivative(3), 1.0e-15);
1004 assertEquals(a[1].getValue(), abSumInline.getDerivative(4), 1.0e-15);
1005 assertEquals(a[2].getValue(), abSumInline.getDerivative(5), 1.0e-15);
1006
1007 }
1008
1009 @Test
1010 void testLinearCombination1DoubleDS() {
1011 final double[] a = new double[] {
1012 -1321008684645961.0 / 268435456.0,
1013 -5774608829631843.0 / 268435456.0,
1014 -7645843051051357.0 / 8589934592.0
1015 };
1016 final SparseGradient[] b = new SparseGradient[] {
1017 SparseGradient.createVariable(0, -5712344449280879.0 / 2097152.0),
1018 SparseGradient.createVariable(1, -4550117129121957.0 / 2097152.0),
1019 SparseGradient.createVariable(2, 8846951984510141.0 / 131072.0)
1020 };
1021
1022 final SparseGradient abSumInline = b[0].linearCombination(a[0], b[0],
1023 a[1], b[1],
1024 a[2], b[2]);
1025 final SparseGradient abSumArray = b[0].linearCombination(a, b);
1026
1027 assertEquals(abSumInline.getValue(), abSumArray.getValue(), 1.0e-15);
1028 assertEquals(-1.8551294182586248737720779899, abSumInline.getValue(), 1.0e-15);
1029 assertEquals(a[0], abSumInline.getDerivative(0), 1.0e-15);
1030 assertEquals(a[1], abSumInline.getDerivative(1), 1.0e-15);
1031 assertEquals(a[2], abSumInline.getDerivative(2), 1.0e-15);
1032
1033 }
1034
1035 @Test
1036 void testLinearCombination2DSDS() {
1037
1038
1039 Well1024a random = new Well1024a(0xc6af886975069f11l);
1040
1041 for (int i = 0; i < 10000; ++i) {
1042 final SparseGradient[] u = new SparseGradient[4];
1043 final SparseGradient[] v = new SparseGradient[4];
1044 for (int j = 0; j < u.length; ++j) {
1045 u[j] = SparseGradient.createVariable(j, 1e17 * random.nextDouble());
1046 v[j] = SparseGradient.createConstant(1e17 * random.nextDouble());
1047 }
1048
1049 SparseGradient lin = u[0].linearCombination(u[0], v[0], u[1], v[1]);
1050 double ref = u[0].getValue() * v[0].getValue() +
1051 u[1].getValue() * v[1].getValue();
1052 assertEquals(ref, lin.getValue(), 1.0e-15 * FastMath.abs(ref));
1053 assertEquals(v[0].getValue(), lin.getDerivative(0), 1.0e-15 * FastMath.abs(v[0].getValue()));
1054 assertEquals(v[1].getValue(), lin.getDerivative(1), 1.0e-15 * FastMath.abs(v[1].getValue()));
1055
1056 lin = u[0].linearCombination(u[0], v[0], u[1], v[1], u[2], v[2]);
1057 ref = u[0].getValue() * v[0].getValue() +
1058 u[1].getValue() * v[1].getValue() +
1059 u[2].getValue() * v[2].getValue();
1060 assertEquals(ref, lin.getValue(), 1.0e-15 * FastMath.abs(ref));
1061 assertEquals(v[0].getValue(), lin.getDerivative(0), 1.0e-15 * FastMath.abs(v[0].getValue()));
1062 assertEquals(v[1].getValue(), lin.getDerivative(1), 1.0e-15 * FastMath.abs(v[1].getValue()));
1063 assertEquals(v[2].getValue(), lin.getDerivative(2), 1.0e-15 * FastMath.abs(v[2].getValue()));
1064
1065 lin = u[0].linearCombination(u[0], v[0], u[1], v[1], u[2], v[2], u[3], v[3]);
1066 ref = u[0].getValue() * v[0].getValue() +
1067 u[1].getValue() * v[1].getValue() +
1068 u[2].getValue() * v[2].getValue() +
1069 u[3].getValue() * v[3].getValue();
1070 assertEquals(ref, lin.getValue(), 1.0e-15 * FastMath.abs(ref));
1071 assertEquals(v[0].getValue(), lin.getDerivative(0), 1.0e-15 * FastMath.abs(v[0].getValue()));
1072 assertEquals(v[1].getValue(), lin.getDerivative(1), 1.0e-15 * FastMath.abs(v[1].getValue()));
1073 assertEquals(v[2].getValue(), lin.getDerivative(2), 1.0e-15 * FastMath.abs(v[2].getValue()));
1074 assertEquals(v[3].getValue(), lin.getDerivative(3), 1.0e-15 * FastMath.abs(v[3].getValue()));
1075
1076 }
1077 }
1078
1079 @Test
1080 void testLinearCombination2DoubleDS() {
1081
1082
1083 Well1024a random = new Well1024a(0xc6af886975069f11l);
1084
1085 for (int i = 0; i < 10000; ++i) {
1086 final double[] u = new double[4];
1087 final SparseGradient[] v = new SparseGradient[4];
1088 for (int j = 0; j < u.length; ++j) {
1089 u[j] = 1e17 * random.nextDouble();
1090 v[j] = SparseGradient.createVariable(j, 1e17 * random.nextDouble());
1091 }
1092
1093 SparseGradient lin = v[0].linearCombination(u[0], v[0], u[1], v[1]);
1094 double ref = u[0] * v[0].getValue() +
1095 u[1] * v[1].getValue();
1096 assertEquals(ref, lin.getValue(), 1.0e-15 * FastMath.abs(ref));
1097 assertEquals(u[0], lin.getDerivative(0), 1.0e-15 * FastMath.abs(v[0].getValue()));
1098 assertEquals(u[1], lin.getDerivative(1), 1.0e-15 * FastMath.abs(v[1].getValue()));
1099
1100 lin = v[0].linearCombination(u[0], v[0], u[1], v[1], u[2], v[2]);
1101 ref = u[0] * v[0].getValue() +
1102 u[1] * v[1].getValue() +
1103 u[2] * v[2].getValue();
1104 assertEquals(ref, lin.getValue(), 1.0e-15 * FastMath.abs(ref));
1105 assertEquals(u[0], lin.getDerivative(0), 1.0e-15 * FastMath.abs(v[0].getValue()));
1106 assertEquals(u[1], lin.getDerivative(1), 1.0e-15 * FastMath.abs(v[1].getValue()));
1107 assertEquals(u[2], lin.getDerivative(2), 1.0e-15 * FastMath.abs(v[2].getValue()));
1108
1109 lin = v[0].linearCombination(u[0], v[0], u[1], v[1], u[2], v[2], u[3], v[3]);
1110 ref = u[0] * v[0].getValue() +
1111 u[1] * v[1].getValue() +
1112 u[2] * v[2].getValue() +
1113 u[3] * v[3].getValue();
1114 assertEquals(ref, lin.getValue(), 1.0e-15 * FastMath.abs(ref));
1115 assertEquals(u[0], lin.getDerivative(0), 1.0e-15 * FastMath.abs(v[0].getValue()));
1116 assertEquals(u[1], lin.getDerivative(1), 1.0e-15 * FastMath.abs(v[1].getValue()));
1117 assertEquals(u[2], lin.getDerivative(2), 1.0e-15 * FastMath.abs(v[2].getValue()));
1118 assertEquals(u[3], lin.getDerivative(3), 1.0e-15 * FastMath.abs(v[3].getValue()));
1119
1120 }
1121 }
1122
1123 @Test
1124 void testSerialization() {
1125 SparseGradient a = SparseGradient.createVariable(0, 1.3);
1126 SparseGradient b = (SparseGradient) UnitTestUtils.serializeAndRecover(a);
1127 assertEquals(a, b);
1128 }
1129
1130 @Test
1131 void testZero() {
1132 SparseGradient zero = SparseGradient.createVariable(0, 17.0).getField().getZero();
1133 assertEquals(0, zero.getFreeParameters());
1134 assertEquals(0.0, zero.getValue(), 1.0e-15);
1135 assertEquals(0.0, zero.getDerivative(0), 1.0e-15);
1136 }
1137
1138 @Test
1139 void testOne() {
1140 SparseGradient one = SparseGradient.createVariable(0, 17.0).getField().getOne();
1141 assertEquals(0, one.getFreeParameters());
1142 assertEquals(1.0, one.getValue(), 1.0e-15);
1143 assertEquals(0.0, one.getDerivative(0), 1.0e-15);
1144 }
1145
1146 @Test
1147 void testMap() {
1148 List<int[]> pairs = new ArrayList<>();
1149 for (int parameters = 1; parameters < 5; ++parameters) {
1150 for (int order = 0; order < 3; ++order) {
1151 pairs.add(new int[] { parameters, order });
1152 }
1153 }
1154 Map<Field<?>, Integer> map = new HashMap<>();
1155 for (int i = 0; i < 1000; ++i) {
1156 map.put(SparseGradient.createVariable(i, 17.0).getField(), 0);
1157 }
1158
1159 assertEquals(1, map.size());
1160 @SuppressWarnings("unchecked")
1161 Field<SparseGradient> first = (Field<SparseGradient>) map.entrySet().iterator().next().getKey();
1162 assertEquals(first, first);
1163 assertNotEquals(first, new DSFactory(1, 1).constant(0.0).getField());
1164
1165 }
1166
1167 @Test
1168 void testRunTimeClass() {
1169 Field<SparseGradient> field = SparseGradient.createVariable(5, 17.0).getField();
1170 assertEquals(SparseGradient.class, field.getRuntimeClass());
1171 }
1172
1173 private void checkF0F1(SparseGradient sg, double value, double...derivatives) {
1174
1175
1176 assertEquals(value, sg.getValue(), 1.0e-13);
1177
1178
1179 for (int i = 0; i < derivatives.length; ++i) {
1180 assertEquals(derivatives[i], sg.getDerivative(i), 1.0e-13);
1181 }
1182
1183 }
1184
1185 }