1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.hipparchus.analysis.differentiation;
18
19 import java.util.Arrays;
20
21 import org.hipparchus.CalculusFieldElement;
22 import org.hipparchus.Field;
23 import org.hipparchus.exception.LocalizedCoreFormats;
24 import org.hipparchus.exception.MathIllegalArgumentException;
25 import org.hipparchus.util.FastMath;
26 import org.hipparchus.util.FieldSinCos;
27 import org.hipparchus.util.FieldSinhCosh;
28 import org.hipparchus.util.MathArrays;
29 import org.hipparchus.util.MathUtils;
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56 public class FieldGradient<T extends CalculusFieldElement<T>> implements FieldDerivative<T, FieldGradient<T>> {
57
58
59 private final T value;
60
61
62 private final T[] grad;
63
64
65
66
67
68 private FieldGradient(final T value, int freeParameters) {
69 this.value = value;
70 this.grad = MathArrays.buildArray(value.getField(), freeParameters);
71 }
72
73
74
75
76
77 @SafeVarargs
78 public FieldGradient(final T value, final T... gradient) {
79 this(value, gradient.length);
80 System.arraycopy(gradient, 0, grad, 0, grad.length);
81 }
82
83
84
85
86
87
88 public FieldGradient(final FieldDerivativeStructure<T> ds) throws MathIllegalArgumentException {
89 this(ds.getValue(), ds.getFreeParameters());
90 MathUtils.checkDimension(ds.getOrder(), 1);
91 System.arraycopy(ds.getAllDerivatives(), 1, grad, 0, grad.length);
92 }
93
94
95
96
97
98
99
100 public static <T extends CalculusFieldElement<T>> FieldGradient<T> constant(final int freeParameters, final T value) {
101 final FieldGradient<T> g = new FieldGradient<>(value, freeParameters);
102 Arrays.fill(g.grad, value.getField().getZero());
103 return g;
104 }
105
106
107
108
109
110
111
112
113
114
115
116
117
118 public static <T extends CalculusFieldElement<T>> FieldGradient<T> variable(final int freeParameters,
119 final int index, final T value) {
120 final FieldGradient<T> g = new FieldGradient<>(value, freeParameters);
121 final Field<T> field = value.getField();
122 Arrays.fill(g.grad, field.getZero());
123 g.grad[index] = field.getOne();
124 return g;
125 }
126
127
128
129
130 public Field<T> getValueField() {
131 return value.getField();
132 }
133
134
135 @Override
136 public FieldGradient<T> newInstance(final double c) {
137 return newInstance(getValueField().getZero().newInstance(c));
138 }
139
140
141
142
143
144
145
146
147
148
149
150
151
152 public FieldGradient<T> newInstance(final T c) {
153 return new FieldGradient<>(c, MathArrays.buildArray(value.getField(), grad.length));
154 }
155
156
157 @Override
158 public double getReal() {
159 return getValue().getReal();
160 }
161
162
163
164
165 @Override
166 public T getValue() {
167 return value;
168 }
169
170
171
172
173 public T[] getGradient() {
174 return grad.clone();
175 }
176
177
178
179
180 @Override
181 public int getFreeParameters() {
182 return grad.length;
183 }
184
185
186 @Override
187 public int getOrder() {
188 return 1;
189 }
190
191
192 @Override
193 public T getPartialDerivative(final int ... orders)
194 throws MathIllegalArgumentException {
195
196
197 if (orders.length != grad.length) {
198 throw new MathIllegalArgumentException(LocalizedCoreFormats.DIMENSIONS_MISMATCH,
199 orders.length, grad.length);
200 }
201
202
203
204 int selected = -1;
205 for (int i = 0; i < orders.length; ++i) {
206 if (orders[i] != 0) {
207 if (selected >= 0 || orders[i] != 1) {
208 throw new MathIllegalArgumentException(LocalizedCoreFormats.DERIVATION_ORDER_NOT_ALLOWED,
209 orders[i]);
210 }
211
212 selected = i;
213 }
214 }
215
216 return (selected < 0) ? value : grad[selected];
217
218 }
219
220
221
222
223
224
225
226 public T getPartialDerivative(final int n) throws MathIllegalArgumentException {
227 if (n < 0 || n >= grad.length) {
228 throw new MathIllegalArgumentException(LocalizedCoreFormats.OUT_OF_RANGE_SIMPLE, n, 0, grad.length - 1);
229 }
230 return grad[n];
231 }
232
233
234
235
236 public FieldDerivativeStructure<T> toDerivativeStructure() {
237 final T[] derivatives = MathArrays.buildArray(getValueField(), 1 + grad.length);
238 derivatives[0] = value;
239 System.arraycopy(grad, 0, derivatives, 1, grad.length);
240 return getField().getConversionFactory().build(derivatives);
241 }
242
243
244
245
246
247 public FieldGradient<T> add(final T a) {
248 return new FieldGradient<>(value.add(a), grad);
249 }
250
251
252 @Override
253 public FieldGradient<T> add(final double a) {
254 return new FieldGradient<>(value.add(a), grad);
255 }
256
257
258 @Override
259 public FieldGradient<T> add(final FieldGradient<T> a) {
260 final FieldGradient<T> result = newInstance(value.add(a.value));
261 for (int i = 0; i < grad.length; ++i) {
262 result.grad[i] = grad[i].add(a.grad[i]);
263 }
264 return result;
265 }
266
267
268
269
270
271 public FieldGradient<T> subtract(final T a) {
272 return new FieldGradient<>(value.subtract(a), grad);
273 }
274
275
276 @Override
277 public FieldGradient<T> subtract(final double a) {
278 return new FieldGradient<>(value.subtract(a), grad);
279 }
280
281
282 @Override
283 public FieldGradient<T> subtract(final FieldGradient<T> a) {
284 final FieldGradient<T> result = newInstance(value.subtract(a.value));
285 for (int i = 0; i < grad.length; ++i) {
286 result.grad[i] = grad[i].subtract(a.grad[i]);
287 }
288 return result;
289 }
290
291
292
293
294
295 public FieldGradient<T> multiply(final T n) {
296 final FieldGradient<T> result = newInstance(value.multiply(n));
297 for (int i = 0; i < grad.length; ++i) {
298 result.grad[i] = grad[i].multiply(n);
299 }
300 return result;
301 }
302
303
304 @Override
305 public FieldGradient<T> multiply(final int n) {
306 final FieldGradient<T> result = newInstance(value.multiply(n));
307 for (int i = 0; i < grad.length; ++i) {
308 result.grad[i] = grad[i].multiply(n);
309 }
310 return result;
311 }
312
313
314 @Override
315 public FieldGradient<T> multiply(final double a) {
316 final FieldGradient<T> result = newInstance(value.multiply(a));
317 for (int i = 0; i < grad.length; ++i) {
318 result.grad[i] = grad[i].multiply(a);
319 }
320 return result;
321 }
322
323
324 @Override
325 public FieldGradient<T> multiply(final FieldGradient<T> a) {
326 final FieldGradient<T> result = newInstance(value.multiply(a.value));
327 for (int i = 0; i < grad.length; ++i) {
328 result.grad[i] = grad[i].multiply(a.value).add(value.multiply(a.grad[i]));
329 }
330 return result;
331 }
332
333
334
335
336
337 public FieldGradient<T> divide(final T a) {
338 final FieldGradient<T> result = newInstance(value.divide(a));
339 for (int i = 0; i < grad.length; ++i) {
340 result.grad[i] = grad[i].divide(a);
341 }
342 return result;
343 }
344
345
346 @Override
347 public FieldGradient<T> divide(final double a) {
348 final FieldGradient<T> result = newInstance(value.divide(a));
349 for (int i = 0; i < grad.length; ++i) {
350 result.grad[i] = grad[i].divide(a);
351 }
352 return result;
353 }
354
355
356 @Override
357 public FieldGradient<T> divide(final FieldGradient<T> a) {
358 final T inv1 = a.value.reciprocal();
359 final T inv2 = inv1.multiply(inv1);
360 final FieldGradient<T> result = newInstance(value.multiply(inv1));
361 for (int i = 0; i < grad.length; ++i) {
362 result.grad[i] = grad[i].multiply(a.value).subtract(value.multiply(a.grad[i])).multiply(inv2);
363 }
364 return result;
365 }
366
367
368
369
370
371
372 public FieldGradient<T> remainder(final T a) {
373 return new FieldGradient<>(FastMath.IEEEremainder(value, a), grad);
374 }
375
376
377 @Override
378 public FieldGradient<T> remainder(final double a) {
379 return new FieldGradient<>(FastMath.IEEEremainder(value, a), grad);
380 }
381
382
383 @Override
384 public FieldGradient<T> remainder(final FieldGradient<T> a) {
385
386
387 final T rem = FastMath.IEEEremainder(value, a.value);
388 final T k = FastMath.rint(value.subtract(rem).divide(a.value));
389
390 final FieldGradient<T> result = newInstance(rem);
391 for (int i = 0; i < grad.length; ++i) {
392 result.grad[i] = grad[i].subtract(k.multiply(a.grad[i]));
393 }
394 return result;
395
396 }
397
398
399 @Override
400 public FieldGradient<T> negate() {
401 final FieldGradient<T> result = newInstance(value.negate());
402 for (int i = 0; i < grad.length; ++i) {
403 result.grad[i] = grad[i].negate();
404 }
405 return result;
406 }
407
408
409 @Override
410 public FieldGradient<T> abs() {
411 if (Double.doubleToLongBits(value.getReal()) < 0) {
412
413 return negate();
414 } else {
415 return this;
416 }
417 }
418
419
420 @Override
421 public FieldGradient<T> ceil() {
422 return newInstance(FastMath.ceil(value));
423 }
424
425
426 @Override
427 public FieldGradient<T> floor() {
428 return newInstance(FastMath.floor(value));
429 }
430
431
432 @Override
433 public FieldGradient<T> rint() {
434 return newInstance(FastMath.rint(value));
435 }
436
437
438 @Override
439 public FieldGradient<T> sign() {
440 return newInstance(FastMath.sign(value));
441 }
442
443
444
445
446
447
448
449
450 public FieldGradient<T> copySign(final T sign) {
451 long m = Double.doubleToLongBits(value.getReal());
452 long s = Double.doubleToLongBits(sign.getReal());
453 if ((m >= 0 && s >= 0) || (m < 0 && s < 0)) {
454 return this;
455 }
456 return negate();
457 }
458
459
460 @Override
461 public FieldGradient<T> copySign(final FieldGradient<T> sign) {
462 long m = Double.doubleToLongBits(value.getReal());
463 long s = Double.doubleToLongBits(sign.value.getReal());
464 if ((m >= 0 && s >= 0) || (m < 0 && s < 0)) {
465 return this;
466 }
467 return negate();
468 }
469
470
471 @Override
472 public FieldGradient<T> copySign(final double sign) {
473 long m = Double.doubleToLongBits(value.getReal());
474 long s = Double.doubleToLongBits(sign);
475 if ((m >= 0 && s >= 0) || (m < 0 && s < 0)) {
476 return this;
477 }
478 return negate();
479 }
480
481
482 @Override
483 public int getExponent() {
484 return FastMath.getExponent(value.getReal());
485 }
486
487
488 @Override
489 public FieldGradient<T> scalb(final int n) {
490 final FieldGradient<T> result = newInstance(FastMath.scalb(value, n));
491 for (int i = 0; i < grad.length; ++i) {
492 result.grad[i] = FastMath.scalb(grad[i], n);
493 }
494 return result;
495 }
496
497
498
499
500
501
502
503 @Override
504 public FieldGradient<T> ulp() {
505 return newInstance(FastMath.ulp(value));
506 }
507
508
509 @Override
510 public FieldGradient<T> hypot(final FieldGradient<T> y) {
511
512 if (Double.isInfinite(value.getReal()) || Double.isInfinite(y.value.getReal())) {
513 return newInstance(Double.POSITIVE_INFINITY);
514 } else if (Double.isNaN(value.getReal()) || Double.isNaN(y.value.getReal())) {
515 return newInstance(Double.NaN);
516 } else {
517
518 final int expX = getExponent();
519 final int expY = y.getExponent();
520 if (expX > expY + 27) {
521
522 return abs();
523 } else if (expY > expX + 27) {
524
525 return y.abs();
526 } else {
527
528
529 final int middleExp = (expX + expY) / 2;
530
531
532 final FieldGradient<T> scaledX = scalb(-middleExp);
533 final FieldGradient<T> scaledY = y.scalb(-middleExp);
534
535
536 final FieldGradient<T> scaledH =
537 scaledX.multiply(scaledX).add(scaledY.multiply(scaledY)).sqrt();
538
539
540 return scaledH.scalb(middleExp);
541
542 }
543
544 }
545 }
546
547
548 @Override
549 public FieldGradient<T> reciprocal() {
550 final T inv1 = value.reciprocal();
551 final T mInv2 = inv1.multiply(inv1).negate();
552 final FieldGradient<T> result = newInstance(inv1);
553 for (int i = 0; i < grad.length; ++i) {
554 result.grad[i] = grad[i].multiply(mInv2);
555 }
556 return result;
557 }
558
559
560
561
562
563
564 public FieldGradient<T> compose(final T g0, final T g1) {
565 final FieldGradient<T> result = newInstance(g0);
566 for (int i = 0; i < grad.length; ++i) {
567 result.grad[i] = g1.multiply(grad[i]);
568 }
569 return result;
570 }
571
572
573 @Override
574 public FieldGradient<T> sqrt() {
575 final T s = FastMath.sqrt(value);
576 return compose(s, s.add(s).reciprocal());
577 }
578
579
580 @Override
581 public FieldGradient<T> cbrt() {
582 final T c = FastMath.cbrt(value);
583 return compose(c, c.multiply(c).multiply(3).reciprocal());
584 }
585
586
587 @Override
588 public FieldGradient<T> rootN(final int n) {
589 if (n == 2) {
590 return sqrt();
591 } else if (n == 3) {
592 return cbrt();
593 } else {
594 final T r = FastMath.pow(value, 1.0 / n);
595 return compose(r, FastMath.pow(r, n - 1).multiply(n).reciprocal());
596 }
597 }
598
599
600 @Override
601 public FieldGradientField<T> getField() {
602 return FieldGradientField.getField(getValueField(), getFreeParameters());
603 }
604
605
606
607
608
609
610
611 public static <T extends CalculusFieldElement<T>> FieldGradient<T> pow(final double a, final FieldGradient<T> x) {
612 if (a == 0) {
613 return x.getField().getZero();
614 } else {
615 final T aX = FastMath.pow(x.value.newInstance(a), x.value);
616 final T aXlnA = aX.multiply(FastMath.log(a));
617 final FieldGradient<T> result = x.newInstance(aX);
618 for (int i = 0; i < x.grad.length; ++i) {
619 result.grad[i] = aXlnA.multiply(x.grad[i]);
620 }
621 return result;
622 }
623 }
624
625
626 @Override
627 public FieldGradient<T> pow(final double p) {
628 if (p == 0) {
629 return getField().getOne();
630 } else {
631 final T f0Pm1 = FastMath.pow(value, p - 1);
632 return compose(f0Pm1.multiply(value), f0Pm1.multiply(p));
633 }
634 }
635
636
637 @Override
638 public FieldGradient<T> pow(final int n) {
639 if (n == 0) {
640 return getField().getOne();
641 } else {
642 final T f0Nm1 = FastMath.pow(value, n - 1);
643 return compose(f0Nm1.multiply(value), f0Nm1.multiply(n));
644 }
645 }
646
647
648 @Override
649 public FieldGradient<T> pow(final FieldGradient<T> e) {
650 return log().multiply(e).exp();
651 }
652
653
654 @Override
655 public FieldGradient<T> exp() {
656 final T exp = FastMath.exp(value);
657 return compose(exp, exp);
658 }
659
660
661 @Override
662 public FieldGradient<T> expm1() {
663 final T exp = FastMath.exp(value);
664 final T expM1 = FastMath.expm1(value);
665 return compose(expM1, exp);
666 }
667
668
669 @Override
670 public FieldGradient<T> log() {
671 return compose(FastMath.log(value), value.reciprocal());
672 }
673
674
675 @Override
676 public FieldGradient<T> log1p() {
677 return compose(FastMath.log1p(value), value.add(1).reciprocal());
678 }
679
680
681 @Override
682 public FieldGradient<T> log10() {
683 return compose(FastMath.log10(value), value.multiply(FastMath.log(10.0)).reciprocal());
684 }
685
686
687 @Override
688 public FieldGradient<T> cos() {
689 final FieldSinCos<T> sinCos = FastMath.sinCos(value);
690 return compose(sinCos.cos(), sinCos.sin().negate());
691 }
692
693
694 @Override
695 public FieldGradient<T> sin() {
696 final FieldSinCos<T> sinCos = FastMath.sinCos(value);
697 return compose(sinCos.sin(), sinCos.cos());
698 }
699
700
701 @Override
702 public FieldSinCos<FieldGradient<T>> sinCos() {
703 final FieldSinCos<T> sinCos = FastMath.sinCos(value);
704 final FieldGradient<T> sin = newInstance(sinCos.sin());
705 final FieldGradient<T> cos = newInstance(sinCos.cos());
706 final T mSin = sinCos.sin().negate();
707 for (int i = 0; i < grad.length; ++i) {
708 sin.grad[i] = grad[i].multiply(sinCos.cos());
709 cos.grad[i] = grad[i].multiply(mSin);
710 }
711 return new FieldSinCos<>(sin, cos);
712 }
713
714
715 @Override
716 public FieldGradient<T> tan() {
717 final T tan = FastMath.tan(value);
718 return compose(tan, tan.multiply(tan).add(1));
719 }
720
721
722 @Override
723 public FieldGradient<T> acos() {
724 return compose(FastMath.acos(value), value.multiply(value).negate().add(1).sqrt().reciprocal().negate());
725 }
726
727
728 @Override
729 public FieldGradient<T> asin() {
730 return compose(FastMath.asin(value), value.multiply(value).negate().add(1).sqrt().reciprocal());
731 }
732
733
734 @Override
735 public FieldGradient<T> atan() {
736 return compose(FastMath.atan(value), value.multiply(value).add(1).reciprocal());
737 }
738
739
740 @Override
741 public FieldGradient<T> atan2(final FieldGradient<T> x) {
742 final T inv = value.multiply(value).add(x.value.multiply(x.value)).reciprocal();
743 final FieldGradient<T> result = newInstance(FastMath.atan2(value, x.value));
744 final T xValueInv = x.value.multiply(inv);
745 final T mValueInv = value.negate().multiply(inv);
746 for (int i = 0; i < grad.length; ++i) {
747 result.grad[i] = xValueInv.multiply(grad[i]).add(x.grad[i].multiply(mValueInv));
748 }
749 return result;
750 }
751
752
753 @Override
754 public FieldGradient<T> cosh() {
755 return compose(FastMath.cosh(value), FastMath.sinh(value));
756 }
757
758
759 @Override
760 public FieldGradient<T> sinh() {
761 return compose(FastMath.sinh(value), FastMath.cosh(value));
762 }
763
764
765 @Override
766 public FieldSinhCosh<FieldGradient<T>> sinhCosh() {
767 final FieldSinhCosh<T> sinhCosh = FastMath.sinhCosh(value);
768 final FieldGradient<T> sinh = newInstance(sinhCosh.sinh());
769 final FieldGradient<T> cosh = newInstance(sinhCosh.cosh());
770 for (int i = 0; i < grad.length; ++i) {
771 sinh.grad[i] = grad[i].multiply(sinhCosh.cosh());
772 cosh.grad[i] = grad[i].multiply(sinhCosh.sinh());
773 }
774 return new FieldSinhCosh<>(sinh, cosh);
775 }
776
777
778 @Override
779 public FieldGradient<T> tanh() {
780 final T tanh = FastMath.tanh(value);
781 return compose(tanh, tanh.multiply(tanh).negate().add(1));
782 }
783
784
785 @Override
786 public FieldGradient<T> acosh() {
787 return compose(FastMath.acosh(value), value.multiply(value).subtract(1).sqrt().reciprocal());
788 }
789
790
791 @Override
792 public FieldGradient<T> asinh() {
793 return compose(FastMath.asinh(value), value.multiply(value).add(1).sqrt().reciprocal());
794 }
795
796
797 @Override
798 public FieldGradient<T> atanh() {
799 return compose(FastMath.atanh(value), value.multiply(value).negate().add(1).reciprocal());
800 }
801
802
803 @Override
804 public FieldGradient<T> toDegrees() {
805 final FieldGradient<T> result = newInstance(FastMath.toDegrees(value));
806 for (int i = 0; i < grad.length; ++i) {
807 result.grad[i] = FastMath.toDegrees(grad[i]);
808 }
809 return result;
810 }
811
812
813 @Override
814 public FieldGradient<T> toRadians() {
815 final FieldGradient<T> result = newInstance(FastMath.toRadians(value));
816 for (int i = 0; i < grad.length; ++i) {
817 result.grad[i] = FastMath.toRadians(grad[i]);
818 }
819 return result;
820 }
821
822
823
824
825
826 public T taylor(final double... delta) {
827 T result = value;
828 for (int i = 0; i < grad.length; ++i) {
829 result = result.add(grad[i].multiply(delta[i]));
830 }
831 return result;
832 }
833
834
835
836
837
838 public T taylor(@SuppressWarnings("unchecked") final T... delta) {
839 T result = value;
840 for (int i = 0; i < grad.length; ++i) {
841 result = result.add(grad[i].multiply(delta[i]));
842 }
843 return result;
844 }
845
846
847 @Override
848 public FieldGradient<T> linearCombination(final FieldGradient<T>[] a, final FieldGradient<T>[] b) {
849
850
851 final Field<T> field = a[0].value.getField();
852 final int n = a.length;
853 final T[] a0 = MathArrays.buildArray(field, n);
854 final T[] b0 = MathArrays.buildArray(field, n);
855 final T[] a1 = MathArrays.buildArray(field, 2 * n);
856 final T[] b1 = MathArrays.buildArray(field, 2 * n);
857 for (int i = 0; i < n; ++i) {
858 final FieldGradient<T> ai = a[i];
859 final FieldGradient<T> bi = b[i];
860 a0[i] = ai.value;
861 b0[i] = bi.value;
862 a1[2 * i] = ai.value;
863 b1[2 * i + 1] = bi.value;
864 }
865
866 final FieldGradient<T> result = newInstance(a[0].value.linearCombination(a0, b0));
867 for (int k = 0; k < grad.length; ++k) {
868 for (int i = 0; i < n; ++i) {
869 a1[2 * i + 1] = a[i].grad[k];
870 b1[2 * i] = b[i].grad[k];
871 }
872 result.grad[k] = a[0].value.linearCombination(a1, b1);
873 }
874 return result;
875
876 }
877
878
879
880
881
882
883
884
885 public FieldGradient<T> linearCombination(final T[] a, final FieldGradient<T>[] b) {
886
887
888 final Field<T> field = b[0].value.getField();
889 final int n = b.length;
890 final T[] b0 = MathArrays.buildArray(field, n);
891 final T[] b1 = MathArrays.buildArray(field, n);
892 for (int i = 0; i < n; ++i) {
893 b0[i] = b[i].value;
894 }
895
896 final FieldGradient<T> result = newInstance(b[0].value.linearCombination(a, b0));
897 for (int k = 0; k < grad.length; ++k) {
898 for (int i = 0; i < n; ++i) {
899 b1[i] = b[i].grad[k];
900 }
901 result.grad[k] = b[0].value.linearCombination(a, b1);
902 }
903 return result;
904
905 }
906
907
908 @Override
909 public FieldGradient<T> linearCombination(final double[] a, final FieldGradient<T>[] b) {
910
911
912 final Field<T> field = b[0].value.getField();
913 final int n = b.length;
914 final T[] b0 = MathArrays.buildArray(field, n);
915 final T[] b1 = MathArrays.buildArray(field, n);
916 for (int i = 0; i < n; ++i) {
917 b0[i] = b[i].value;
918 }
919
920 final FieldGradient<T> result = newInstance(b[0].value.linearCombination(a, b0));
921 for (int k = 0; k < grad.length; ++k) {
922 for (int i = 0; i < n; ++i) {
923 b1[i] = b[i].grad[k];
924 }
925 result.grad[k] = b[0].value.linearCombination(a, b1);
926 }
927 return result;
928
929 }
930
931
932 @Override
933 public FieldGradient<T> linearCombination(final FieldGradient<T> a1, final FieldGradient<T> b1,
934 final FieldGradient<T> a2, final FieldGradient<T> b2) {
935 final FieldGradient<T> result = newInstance(a1.value.linearCombination(a1.value, b1.value,
936 a2.value, b2.value));
937 for (int i = 0; i < b1.grad.length; ++i) {
938 result.grad[i] = a1.value.linearCombination(a1.value, b1.grad[i],
939 a1.grad[i], b1.value,
940 a2.value, b2.grad[i],
941 a2.grad[i], b2.value);
942 }
943 return result;
944 }
945
946
947 @Override
948 public FieldGradient<T> linearCombination(final double a1, final FieldGradient<T> b1,
949 final double a2, final FieldGradient<T> b2) {
950 final FieldGradient<T> result = newInstance(b1.value.linearCombination(a1, b1.value,
951 a2, b2.value));
952 for (int i = 0; i < b1.grad.length; ++i) {
953 result.grad[i] = b1.value.linearCombination(a1, b1.grad[i],
954 a2, b2.grad[i]);
955 }
956 return result;
957 }
958
959
960 @Override
961 public FieldGradient<T> linearCombination(final FieldGradient<T> a1, final FieldGradient<T> b1,
962 final FieldGradient<T> a2, final FieldGradient<T> b2,
963 final FieldGradient<T> a3, final FieldGradient<T> b3) {
964 final Field<T> field = a1.value.getField();
965 final T[] a = MathArrays.buildArray(field, 6);
966 final T[] b = MathArrays.buildArray(field, 6);
967 a[0] = a1.value;
968 a[2] = a2.value;
969 a[4] = a3.value;
970 b[1] = b1.value;
971 b[3] = b2.value;
972 b[5] = b3.value;
973 final FieldGradient<T> result = newInstance(a1.value.linearCombination(a1.value, b1.value,
974 a2.value, b2.value,
975 a3.value, b3.value));
976 for (int i = 0; i < b1.grad.length; ++i) {
977 a[1] = a1.grad[i];
978 a[3] = a2.grad[i];
979 a[5] = a3.grad[i];
980 b[0] = b1.grad[i];
981 b[2] = b2.grad[i];
982 b[4] = b3.grad[i];
983 result.grad[i] = a1.value.linearCombination(a, b);
984 }
985 return result;
986 }
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002 public FieldGradient<T> linearCombination(final T a1, final FieldGradient<T> b1,
1003 final T a2, final FieldGradient<T> b2,
1004 final T a3, final FieldGradient<T> b3) {
1005 final FieldGradient<T> result = newInstance(b1.value.linearCombination(a1, b1.value,
1006 a2, b2.value,
1007 a3, b3.value));
1008 for (int i = 0; i < b1.grad.length; ++i) {
1009 result.grad[i] = b1.value.linearCombination(a1, b1.grad[i],
1010 a2, b2.grad[i],
1011 a3, b3.grad[i]);
1012 }
1013 return result;
1014 }
1015
1016
1017 @Override
1018 public FieldGradient<T> linearCombination(final double a1, final FieldGradient<T> b1,
1019 final double a2, final FieldGradient<T> b2,
1020 final double a3, final FieldGradient<T> b3) {
1021 final FieldGradient<T> result = newInstance(b1.value.linearCombination(a1, b1.value,
1022 a2, b2.value,
1023 a3, b3.value));
1024 for (int i = 0; i < b1.grad.length; ++i) {
1025 result.grad[i] = b1.value.linearCombination(a1, b1.grad[i],
1026 a2, b2.grad[i],
1027 a3, b3.grad[i]);
1028 }
1029 return result;
1030 }
1031
1032
1033 @Override
1034 public FieldGradient<T> linearCombination(final FieldGradient<T> a1, final FieldGradient<T> b1,
1035 final FieldGradient<T> a2, final FieldGradient<T> b2,
1036 final FieldGradient<T> a3, final FieldGradient<T> b3,
1037 final FieldGradient<T> a4, final FieldGradient<T> b4) {
1038 final Field<T> field = a1.value.getField();
1039 final T[] a = MathArrays.buildArray(field, 8);
1040 final T[] b = MathArrays.buildArray(field, 8);
1041 a[0] = a1.value;
1042 a[2] = a2.value;
1043 a[4] = a3.value;
1044 a[6] = a4.value;
1045 b[1] = b1.value;
1046 b[3] = b2.value;
1047 b[5] = b3.value;
1048 b[7] = b4.value;
1049 final FieldGradient<T> result = newInstance(a1.value.linearCombination(a1.value, b1.value,
1050 a2.value, b2.value,
1051 a3.value, b3.value,
1052 a4.value, b4.value));
1053 for (int i = 0; i < b1.grad.length; ++i) {
1054 a[1] = a1.grad[i];
1055 a[3] = a2.grad[i];
1056 a[5] = a3.grad[i];
1057 a[7] = a4.grad[i];
1058 b[0] = b1.grad[i];
1059 b[2] = b2.grad[i];
1060 b[4] = b3.grad[i];
1061 b[6] = b4.grad[i];
1062 result.grad[i] = a1.value.linearCombination(a, b);
1063 }
1064 return result;
1065 }
1066
1067
1068 @Override
1069 public FieldGradient<T> linearCombination(final double a1, final FieldGradient<T> b1,
1070 final double a2, final FieldGradient<T> b2,
1071 final double a3, final FieldGradient<T> b3,
1072 final double a4, final FieldGradient<T> b4) {
1073 final FieldGradient<T> result = newInstance(b1.value.linearCombination(a1, b1.value,
1074 a2, b2.value,
1075 a3, b3.value,
1076 a4, b4.value));
1077 for (int i = 0; i < b1.grad.length; ++i) {
1078 result.grad[i] = b1.value.linearCombination(a1, b1.grad[i],
1079 a2, b2.grad[i],
1080 a3, b3.grad[i],
1081 a4, b4.grad[i]);
1082 }
1083 return result;
1084 }
1085
1086
1087 @Override
1088 public FieldGradient<T> getPi() {
1089 return new FieldGradient<>(getValueField().getZero().getPi(), getFreeParameters());
1090 }
1091
1092
1093
1094
1095
1096
1097
1098
1099 @Override
1100 public boolean equals(Object other) {
1101
1102 if (this == other) {
1103 return true;
1104 }
1105
1106 if (other instanceof FieldGradient) {
1107 @SuppressWarnings("unchecked")
1108 final FieldGradient<T> rhs = (FieldGradient<T>) other;
1109 if (!value.equals(rhs.value) || grad.length != rhs.grad.length) {
1110 return false;
1111 }
1112 for (int i = 0; i < grad.length; ++i) {
1113 if (!grad[i].equals(rhs.grad[i])) {
1114 return false;
1115 }
1116 }
1117 return true;
1118 }
1119
1120 return false;
1121
1122 }
1123
1124
1125
1126
1127 @Override
1128 public int hashCode() {
1129 return 129 + 7 *value.hashCode() - 15 * Arrays.hashCode(grad);
1130 }
1131
1132 }