1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.hipparchus.util;
18
19 import java.util.Arrays;
20
21 import org.hipparchus.CalculusFieldElement;
22 import org.hipparchus.Field;
23 import org.hipparchus.exception.MathIllegalArgumentException;
24
25
26
27
28
29 public class Tuple implements CalculusFieldElement<Tuple> {
30
31
32 private final double[] values;
33
34
35 private final transient TupleField field;
36
37
38
39
40 public Tuple(final double... x) {
41 this(new TupleField(x.length), x.clone());
42 }
43
44
45
46
47
48 private Tuple(final TupleField field, final double[] x) {
49 this.values = x;
50 this.field = field;
51 }
52
53
54 @Override
55 public Tuple newInstance(final double value) {
56 final Tuple t = new Tuple(field, new double[values.length]);
57 Arrays.fill(t.values, value);
58 return t;
59 }
60
61
62
63
64 public int getDimension() {
65 return values.length;
66 }
67
68
69
70
71
72 public double getComponent(final int index) {
73 return values[index];
74 }
75
76
77
78
79 public double[] getComponents() {
80 return values.clone();
81 }
82
83
84 @Override
85 public Field<Tuple> getField() {
86 return field;
87 }
88
89
90 @Override
91 public Tuple add(final Tuple a) {
92 final Tuple result = new Tuple(field, new double[values.length]);
93 for (int i = 0; i < values.length; ++i) {
94 result.values[i] = values[i] + a.values[i];
95 }
96 return result;
97 }
98
99
100 @Override
101 public Tuple subtract(final Tuple a) {
102 final Tuple result = new Tuple(field, new double[values.length]);
103 for (int i = 0; i < values.length; ++i) {
104 result.values[i] = values[i] - a.values[i];
105 }
106 return result;
107 }
108
109
110 @Override
111 public Tuple negate() {
112 final Tuple result = new Tuple(field, new double[values.length]);
113 for (int i = 0; i < values.length; ++i) {
114 result.values[i] = -values[i];
115 }
116 return result;
117 }
118
119
120 @Override
121 public Tuple multiply(final Tuple a) {
122 final Tuple result = new Tuple(field, new double[values.length]);
123 for (int i = 0; i < values.length; ++i) {
124 result.values[i] = values[i] * a.values[i];
125 }
126 return result;
127 }
128
129
130 @Override
131 public Tuple multiply(final int n) {
132 final Tuple result = new Tuple(field, new double[values.length]);
133 for (int i = 0; i < values.length; ++i) {
134 result.values[i] = values[i] * n;
135 }
136 return result;
137 }
138
139
140 @Override
141 public Tuple square() {
142 return multiply(this);
143 }
144
145
146 @Override
147 public Tuple divide(final Tuple a) {
148 final Tuple result = new Tuple(field, new double[values.length]);
149 for (int i = 0; i < values.length; ++i) {
150 result.values[i] = values[i] / a.values[i];
151 }
152 return result;
153 }
154
155
156 @Override
157 public Tuple reciprocal() {
158 final Tuple result = new Tuple(field, new double[values.length]);
159 for (int i = 0; i < values.length; ++i) {
160 result.values[i] = 1.0 / values[i];
161 }
162 return result;
163 }
164
165
166 @Override
167 public boolean equals(final Object obj) {
168 if (obj instanceof Tuple) {
169 final Tuple that = (Tuple) obj;
170 if (getDimension() == that.getDimension()) {
171 boolean equals = true;
172 for (int i = 0; i < values.length; ++i) {
173 equals &= Double.doubleToRawLongBits(values[i]) == Double.doubleToRawLongBits(that.values[i]);
174 }
175 return equals;
176 }
177 }
178 return false;
179 }
180
181
182 @Override
183 public int hashCode() {
184 return 0x34b1a444 + Arrays.hashCode(values);
185 }
186
187
188 @Override
189 public double getReal() {
190 return values[0];
191 }
192
193
194 @Override
195 public Tuple getAddendum() {
196 final double[] addendum = values.clone();
197 addendum[0] = 0;
198 for (int i = 1; i < addendum.length; ++i) {
199 addendum[i] -= values[0];
200 }
201 return new Tuple(field, addendum);
202 }
203
204
205 @Override
206 public Tuple add(final double a) {
207 final Tuple result = new Tuple(field, new double[values.length]);
208 for (int i = 0; i < values.length; ++i) {
209 result.values[i] = values[i] + a;
210 }
211 return result;
212 }
213
214
215 @Override
216 public Tuple subtract(final double a) {
217 final Tuple result = new Tuple(field, new double[values.length]);
218 for (int i = 0; i < values.length; ++i) {
219 result.values[i] = values[i] - a;
220 }
221 return result;
222 }
223
224
225 @Override
226 public Tuple multiply(final double a) {
227 final Tuple result = new Tuple(field, new double[values.length]);
228 for (int i = 0; i < values.length; ++i) {
229 result.values[i] = values[i] * a;
230 }
231 return result;
232 }
233
234
235 @Override
236 public Tuple divide(final double a) {
237 final Tuple result = new Tuple(field, new double[values.length]);
238 for (int i = 0; i < values.length; ++i) {
239 result.values[i] = values[i] / a;
240 }
241 return result;
242 }
243
244
245 @Override
246 public Tuple remainder(final double a) {
247 final Tuple result = new Tuple(field, new double[values.length]);
248 for (int i = 0; i < values.length; ++i) {
249 result.values[i] = FastMath.IEEEremainder(values[i], a);
250 }
251 return result;
252 }
253
254
255 @Override
256 public Tuple remainder(final Tuple a) {
257 final Tuple result = new Tuple(field, new double[values.length]);
258 for (int i = 0; i < values.length; ++i) {
259 result.values[i] = FastMath.IEEEremainder(values[i], a.values[i]);
260 }
261 return result;
262 }
263
264
265 @Override
266 public Tuple abs() {
267 final Tuple result = new Tuple(field, new double[values.length]);
268 for (int i = 0; i < values.length; ++i) {
269 result.values[i] = FastMath.abs(values[i]);
270 }
271 return result;
272 }
273
274
275 @Override
276 public Tuple ceil() {
277 final Tuple result = new Tuple(field, new double[values.length]);
278 for (int i = 0; i < values.length; ++i) {
279 result.values[i] = FastMath.ceil(values[i]);
280 }
281 return result;
282 }
283
284
285 @Override
286 public Tuple floor() {
287 final Tuple result = new Tuple(field, new double[values.length]);
288 for (int i = 0; i < values.length; ++i) {
289 result.values[i] = FastMath.floor(values[i]);
290 }
291 return result;
292 }
293
294
295 @Override
296 public Tuple rint() {
297 final Tuple result = new Tuple(field, new double[values.length]);
298 for (int i = 0; i < values.length; ++i) {
299 result.values[i] = FastMath.rint(values[i]);
300 }
301 return result;
302 }
303
304
305 @Override
306 public Tuple sign() {
307 final Tuple result = new Tuple(field, new double[values.length]);
308 for (int i = 0; i < values.length; ++i) {
309 result.values[i] = FastMath.signum(values[i]);
310 }
311 return result;
312 }
313
314
315 @Override
316 public Tuple copySign(final Tuple sign) {
317 final Tuple result = new Tuple(field, new double[values.length]);
318 for (int i = 0; i < values.length; ++i) {
319 result.values[i] = FastMath.copySign(values[i], sign.values[i]);
320 }
321 return result;
322 }
323
324
325 @Override
326 public Tuple copySign(final double sign) {
327 final Tuple result = new Tuple(field, new double[values.length]);
328 for (int i = 0; i < values.length; ++i) {
329 result.values[i] = FastMath.copySign(values[i], sign);
330 }
331 return result;
332 }
333
334
335 @Override
336 public Tuple scalb(final int n) {
337 final Tuple result = new Tuple(field, new double[values.length]);
338 for (int i = 0; i < values.length; ++i) {
339 result.values[i] = FastMath.scalb(values[i], n);
340 }
341 return result;
342 }
343
344
345 @Override
346 public Tuple ulp() {
347 final Tuple result = new Tuple(field, new double[values.length]);
348 for (int i = 0; i < values.length; ++i) {
349 result.values[i] = FastMath.ulp(values[i]);
350 }
351 return result;
352 }
353
354
355 @Override
356 public Tuple hypot(final Tuple y) {
357 final Tuple result = new Tuple(field, new double[values.length]);
358 for (int i = 0; i < values.length; ++i) {
359 result.values[i] = FastMath.hypot(values[i], y.values[i]);
360 }
361 return result;
362 }
363
364
365 @Override
366 public Tuple sqrt() {
367 final Tuple result = new Tuple(field, new double[values.length]);
368 for (int i = 0; i < values.length; ++i) {
369 result.values[i] = FastMath.sqrt(values[i]);
370 }
371 return result;
372 }
373
374
375 @Override
376 public Tuple cbrt() {
377 final Tuple result = new Tuple(field, new double[values.length]);
378 for (int i = 0; i < values.length; ++i) {
379 result.values[i] = FastMath.cbrt(values[i]);
380 }
381 return result;
382 }
383
384
385 @Override
386 public Tuple rootN(final int n) {
387 final Tuple result = new Tuple(field, new double[values.length]);
388 for (int i = 0; i < values.length; ++i) {
389 if (values[i] < 0) {
390 result.values[i] = -FastMath.pow(-values[i], 1.0 / n);
391 } else {
392 result.values[i] = FastMath.pow(values[i], 1.0 / n);
393 }
394 }
395 return result;
396 }
397
398
399 @Override
400 public Tuple pow(final double p) {
401 final Tuple result = new Tuple(field, new double[values.length]);
402 for (int i = 0; i < values.length; ++i) {
403 result.values[i] = FastMath.pow(values[i], p);
404 }
405 return result;
406 }
407
408
409 @Override
410 public Tuple pow(final int n) {
411 final Tuple result = new Tuple(field, new double[values.length]);
412 for (int i = 0; i < values.length; ++i) {
413 result.values[i] = FastMath.pow(values[i], n);
414 }
415 return result;
416 }
417
418
419 @Override
420 public Tuple pow(final Tuple e) {
421 final Tuple result = new Tuple(field, new double[values.length]);
422 for (int i = 0; i < values.length; ++i) {
423 result.values[i] = FastMath.pow(values[i], e.values[i]);
424 }
425 return result;
426 }
427
428
429 @Override
430 public Tuple exp() {
431 final Tuple result = new Tuple(field, new double[values.length]);
432 for (int i = 0; i < values.length; ++i) {
433 result.values[i] = FastMath.exp(values[i]);
434 }
435 return result;
436 }
437
438
439 @Override
440 public Tuple expm1() {
441 final Tuple result = new Tuple(field, new double[values.length]);
442 for (int i = 0; i < values.length; ++i) {
443 result.values[i] = FastMath.expm1(values[i]);
444 }
445 return result;
446 }
447
448
449 @Override
450 public Tuple log() {
451 final Tuple result = new Tuple(field, new double[values.length]);
452 for (int i = 0; i < values.length; ++i) {
453 result.values[i] = FastMath.log(values[i]);
454 }
455 return result;
456 }
457
458
459 @Override
460 public Tuple log1p() {
461 final Tuple result = new Tuple(field, new double[values.length]);
462 for (int i = 0; i < values.length; ++i) {
463 result.values[i] = FastMath.log1p(values[i]);
464 }
465 return result;
466 }
467
468
469 @Override
470 public Tuple log10() {
471 final Tuple result = new Tuple(field, new double[values.length]);
472 for (int i = 0; i < values.length; ++i) {
473 result.values[i] = FastMath.log10(values[i]);
474 }
475 return result;
476 }
477
478
479 @Override
480 public Tuple cos() {
481 final Tuple result = new Tuple(field, new double[values.length]);
482 for (int i = 0; i < values.length; ++i) {
483 result.values[i] = FastMath.cos(values[i]);
484 }
485 return result;
486 }
487
488
489 @Override
490 public Tuple sin() {
491 final Tuple result = new Tuple(field, new double[values.length]);
492 for (int i = 0; i < values.length; ++i) {
493 result.values[i] = FastMath.sin(values[i]);
494 }
495 return result;
496 }
497
498
499 @Override
500 public FieldSinCos<Tuple> sinCos() {
501 final Tuple sin = new Tuple(field, new double[values.length]);
502 final Tuple cos = new Tuple(field, new double[values.length]);
503 for (int i = 0; i < values.length; ++i) {
504 final SinCos sc = FastMath.sinCos(values[i]);
505 sin.values[i] = sc.sin();
506 cos.values[i] = sc.cos();
507 }
508 return new FieldSinCos<>(sin, cos);
509 }
510
511
512 @Override
513 public Tuple tan() {
514 final Tuple result = new Tuple(field, new double[values.length]);
515 for (int i = 0; i < values.length; ++i) {
516 result.values[i] = FastMath.tan(values[i]);
517 }
518 return result;
519 }
520
521
522 @Override
523 public Tuple acos() {
524 final Tuple result = new Tuple(field, new double[values.length]);
525 for (int i = 0; i < values.length; ++i) {
526 result.values[i] = FastMath.acos(values[i]);
527 }
528 return result;
529 }
530
531
532 @Override
533 public Tuple asin() {
534 final Tuple result = new Tuple(field, new double[values.length]);
535 for (int i = 0; i < values.length; ++i) {
536 result.values[i] = FastMath.asin(values[i]);
537 }
538 return result;
539 }
540
541
542 @Override
543 public Tuple atan() {
544 final Tuple result = new Tuple(field, new double[values.length]);
545 for (int i = 0; i < values.length; ++i) {
546 result.values[i] = FastMath.atan(values[i]);
547 }
548 return result;
549 }
550
551
552 @Override
553 public Tuple atan2(final Tuple x) {
554 final Tuple result = new Tuple(field, new double[values.length]);
555 for (int i = 0; i < values.length; ++i) {
556 result.values[i] = FastMath.atan2(values[i], x.values[i]);
557 }
558 return result;
559 }
560
561
562 @Override
563 public Tuple cosh() {
564 final Tuple result = new Tuple(field, new double[values.length]);
565 for (int i = 0; i < values.length; ++i) {
566 result.values[i] = FastMath.cosh(values[i]);
567 }
568 return result;
569 }
570
571
572 @Override
573 public Tuple sinh() {
574 final Tuple result = new Tuple(field, new double[values.length]);
575 for (int i = 0; i < values.length; ++i) {
576 result.values[i] = FastMath.sinh(values[i]);
577 }
578 return result;
579 }
580
581
582 @Override
583 public FieldSinhCosh<Tuple> sinhCosh() {
584 final Tuple sinh = new Tuple(field, new double[values.length]);
585 final Tuple cosh = new Tuple(field, new double[values.length]);
586 for (int i = 0; i < values.length; ++i) {
587 final SinhCosh sch = FastMath.sinhCosh(values[i]);
588 sinh.values[i] = sch.sinh();
589 cosh.values[i] = sch.cosh();
590 }
591 return new FieldSinhCosh<>(sinh, cosh);
592 }
593
594
595 @Override
596 public Tuple tanh() {
597 final Tuple result = new Tuple(field, new double[values.length]);
598 for (int i = 0; i < values.length; ++i) {
599 result.values[i] = FastMath.tanh(values[i]);
600 }
601 return result;
602 }
603
604
605 @Override
606 public Tuple acosh() {
607 final Tuple result = new Tuple(field, new double[values.length]);
608 for (int i = 0; i < values.length; ++i) {
609 result.values[i] = FastMath.acosh(values[i]);
610 }
611 return result;
612 }
613
614
615 @Override
616 public Tuple asinh() {
617 final Tuple result = new Tuple(field, new double[values.length]);
618 for (int i = 0; i < values.length; ++i) {
619 result.values[i] = FastMath.asinh(values[i]);
620 }
621 return result;
622 }
623
624
625 @Override
626 public Tuple atanh() {
627 final Tuple result = new Tuple(field, new double[values.length]);
628 for (int i = 0; i < values.length; ++i) {
629 result.values[i] = FastMath.atanh(values[i]);
630 }
631 return result;
632 }
633
634
635 @Override
636 public Tuple toDegrees() {
637 final Tuple result = new Tuple(field, new double[values.length]);
638 for (int i = 0; i < values.length; ++i) {
639 result.values[i] = FastMath.toDegrees(values[i]);
640 }
641 return result;
642 }
643
644
645 @Override
646 public Tuple toRadians() {
647 final Tuple result = new Tuple(field, new double[values.length]);
648 for (int i = 0; i < values.length; ++i) {
649 result.values[i] = FastMath.toRadians(values[i]);
650 }
651 return result;
652 }
653
654
655 @Override
656 public Tuple linearCombination(final Tuple[] a, final Tuple[] b)
657 throws MathIllegalArgumentException {
658 final Tuple result = new Tuple(field, new double[values.length]);
659 MathUtils.checkDimension(a.length, b.length);
660 final double[] aDouble = new double[a.length];
661 final double[] bDouble = new double[b.length];
662 for (int i = 0; i < values.length; ++i) {
663 for (int j = 0; j < a.length; ++j) {
664 aDouble[j] = a[j].values[i];
665 bDouble[j] = b[j].values[i];
666 }
667 result.values[i] = MathArrays.linearCombination(aDouble, bDouble);
668 }
669 return result;
670 }
671
672
673 @Override
674 public Tuple linearCombination(final double[] a, final Tuple[] b)
675 throws MathIllegalArgumentException {
676 final Tuple result = new Tuple(field, new double[values.length]);
677 MathUtils.checkDimension(a.length, b.length);
678 final double[] bDouble = new double[b.length];
679 for (int i = 0; i < values.length; ++i) {
680 for (int j = 0; j < a.length; ++j) {
681 bDouble[j] = b[j].values[i];
682 }
683 result.values[i] = MathArrays.linearCombination(a, bDouble);
684 }
685 return result;
686 }
687
688
689 @Override
690 public Tuple linearCombination(final Tuple a1, final Tuple b1,
691 final Tuple a2, final Tuple b2) {
692 final Tuple result = new Tuple(field, new double[values.length]);
693 for (int i = 0; i < values.length; ++i) {
694 result.values[i] = MathArrays.linearCombination(a1.values[i], b1.values[i],
695 a2.values[i], b2.values[i]);
696 }
697 return result;
698 }
699
700
701 @Override
702 public Tuple linearCombination(final double a1, final Tuple b1,
703 final double a2, final Tuple b2) {
704 final Tuple result = new Tuple(field, new double[values.length]);
705 for (int i = 0; i < values.length; ++i) {
706 result.values[i] = MathArrays.linearCombination(a1, b1.values[i],
707 a2, b2.values[i]);
708 }
709 return result;
710 }
711
712
713 @Override
714 public Tuple linearCombination(final Tuple a1, final Tuple b1,
715 final Tuple a2, final Tuple b2,
716 final Tuple a3, final Tuple b3) {
717 final Tuple result = new Tuple(field, new double[values.length]);
718 for (int i = 0; i < values.length; ++i) {
719 result.values[i] = MathArrays.linearCombination(a1.values[i], b1.values[i],
720 a2.values[i], b2.values[i],
721 a3.values[i], b3.values[i]);
722 }
723 return result;
724 }
725
726
727 @Override
728 public Tuple linearCombination(final double a1, final Tuple b1,
729 final double a2, final Tuple b2,
730 final double a3, final Tuple b3) {
731 final Tuple result = new Tuple(field, new double[values.length]);
732 for (int i = 0; i < values.length; ++i) {
733 result.values[i] = MathArrays.linearCombination(a1, b1.values[i],
734 a2, b2.values[i],
735 a3, b3.values[i]);
736 }
737 return result;
738 }
739
740
741 @Override
742 public Tuple linearCombination(final Tuple a1, final Tuple b1,
743 final Tuple a2, final Tuple b2,
744 final Tuple a3, final Tuple b3,
745 final Tuple a4, final Tuple b4) {
746 final Tuple result = new Tuple(field, new double[values.length]);
747 for (int i = 0; i < values.length; ++i) {
748 result.values[i] = MathArrays.linearCombination(a1.values[i], b1.values[i],
749 a2.values[i], b2.values[i],
750 a3.values[i], b3.values[i],
751 a4.values[i], b4.values[i]);
752 }
753 return result;
754 }
755
756
757 @Override
758 public Tuple linearCombination(final double a1, final Tuple b1,
759 final double a2, final Tuple b2,
760 final double a3, final Tuple b3,
761 final double a4, final Tuple b4) {
762 final Tuple result = new Tuple(field, new double[values.length]);
763 for (int i = 0; i < values.length; ++i) {
764 result.values[i] = MathArrays.linearCombination(a1, b1.values[i],
765 a2, b2.values[i],
766 a3, b3.values[i],
767 a4, b4.values[i]);
768 }
769 return result;
770 }
771
772
773 @Override
774 public Tuple getPi() {
775 final Tuple result = new Tuple(field, new double[values.length]);
776 Arrays.fill(result.values, FastMath.PI);
777 return result;
778 }
779
780
781
782 private static class TupleField implements Field<Tuple> {
783
784
785 private final Tuple zero;
786
787
788 private final Tuple one;
789
790
791
792
793 TupleField(final int dimension) {
794 final double[] zeroData = new double[dimension];
795 final double[] oneData = new double[dimension];
796 Arrays.fill(oneData, 1.0);
797 this.zero = new Tuple(this, zeroData);
798 this.one = new Tuple(this, oneData);
799 }
800
801
802 @Override
803 public Tuple getZero() {
804 return zero;
805 }
806
807
808 @Override
809 public Tuple getOne() {
810 return one;
811 }
812
813
814 @Override
815 public Class<Tuple> getRuntimeClass() {
816 return Tuple.class;
817 }
818
819
820 @Override
821 public boolean equals(final Object other) {
822 if (other instanceof TupleField) {
823 return zero.getDimension() == ((TupleField) other).zero.getDimension();
824 } else {
825 return false;
826 }
827 }
828
829
830 @Override
831 public int hashCode() {
832 return 0x6672493d ^ zero.getDimension();
833 }
834
835 }
836
837 }