1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.hipparchus.complex;
18
19 import java.util.ArrayList;
20 import java.util.List;
21
22 import org.hipparchus.CalculusFieldElement;
23 import org.hipparchus.Field;
24 import org.hipparchus.exception.LocalizedCoreFormats;
25 import org.hipparchus.exception.MathIllegalArgumentException;
26 import org.hipparchus.exception.NullArgumentException;
27 import org.hipparchus.util.FastMath;
28 import org.hipparchus.util.FieldSinCos;
29 import org.hipparchus.util.FieldSinhCosh;
30 import org.hipparchus.util.MathArrays;
31 import org.hipparchus.util.MathUtils;
32 import org.hipparchus.util.Precision;
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59 public class FieldComplex<T extends CalculusFieldElement<T>> implements CalculusFieldElement<FieldComplex<T>> {
60
61
62 private static final double LOG10 = 2.302585092994045684;
63
64
65 private final T imaginary;
66
67
68 private final T real;
69
70
71 private final transient boolean isNaN;
72
73
74 private final transient boolean isInfinite;
75
76
77
78
79
80
81 public FieldComplex(T real) {
82 this(real, real.getField().getZero());
83 }
84
85
86
87
88
89
90
91 public FieldComplex(T real, T imaginary) {
92 this.real = real;
93 this.imaginary = imaginary;
94
95 isNaN = real.isNaN() || imaginary.isNaN();
96 isInfinite = !isNaN &&
97 (real.isInfinite() || imaginary.isInfinite());
98 }
99
100
101
102
103
104
105 public static <T extends CalculusFieldElement<T>> FieldComplex<T> getI(final Field<T> field) {
106 return new FieldComplex<>(field.getZero(), field.getOne());
107 }
108
109
110
111
112
113
114 public static <T extends CalculusFieldElement<T>> FieldComplex<T> getMinusI(final Field<T> field) {
115 return new FieldComplex<>(field.getZero(), field.getOne().negate());
116 }
117
118
119
120
121
122
123 public static <T extends CalculusFieldElement<T>> FieldComplex<T> getNaN(final Field<T> field) {
124 return new FieldComplex<>(field.getZero().add(Double.NaN), field.getZero().add(Double.NaN));
125 }
126
127
128
129
130
131
132 public static <T extends CalculusFieldElement<T>> FieldComplex<T> getInf(final Field<T> field) {
133 return new FieldComplex<>(field.getZero().add(Double.POSITIVE_INFINITY), field.getZero().add(Double.POSITIVE_INFINITY));
134 }
135
136
137
138
139
140
141 public static <T extends CalculusFieldElement<T>> FieldComplex<T> getOne(final Field<T> field) {
142 return new FieldComplex<>(field.getOne(), field.getZero());
143 }
144
145
146
147
148
149
150 public static <T extends CalculusFieldElement<T>> FieldComplex<T> getMinusOne(final Field<T> field) {
151 return new FieldComplex<>(field.getOne().negate(), field.getZero());
152 }
153
154
155
156
157
158
159 public static <T extends CalculusFieldElement<T>> FieldComplex<T> getZero(final Field<T> field) {
160 return new FieldComplex<>(field.getZero(), field.getZero());
161 }
162
163
164
165
166
167
168 public static <T extends CalculusFieldElement<T>> FieldComplex<T> getPi(final Field<T> field) {
169 return new FieldComplex<>(field.getZero().getPi(), field.getZero());
170 }
171
172
173
174
175
176
177
178
179
180 @Override
181 public FieldComplex<T> abs() {
182
183 return isNaN ? getNaN(getPartsField()) : createComplex(FastMath.hypot(real, imaginary), getPartsField().getZero());
184 }
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202 @Override
203 public FieldComplex<T> add(FieldComplex<T> addend) throws NullArgumentException {
204 MathUtils.checkNotNull(addend);
205 if (isNaN || addend.isNaN) {
206 return getNaN(getPartsField());
207 }
208
209 return createComplex(real.add(addend.getRealPart()),
210 imaginary.add(addend.getImaginaryPart()));
211 }
212
213
214
215
216
217
218
219
220
221 public FieldComplex<T> add(T addend) {
222 if (isNaN || addend.isNaN()) {
223 return getNaN(getPartsField());
224 }
225
226 return createComplex(real.add(addend), imaginary);
227 }
228
229
230
231
232
233
234
235
236
237 @Override
238 public FieldComplex<T> add(double addend) {
239 if (isNaN || Double.isNaN(addend)) {
240 return getNaN(getPartsField());
241 }
242
243 return createComplex(real.add(addend), imaginary);
244 }
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260 public FieldComplex<T> conjugate() {
261 if (isNaN) {
262 return getNaN(getPartsField());
263 }
264
265 return createComplex(real, imaginary.negate());
266 }
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310 @Override
311 public FieldComplex<T> divide(FieldComplex<T> divisor)
312 throws NullArgumentException {
313 MathUtils.checkNotNull(divisor);
314 if (isNaN || divisor.isNaN) {
315 return getNaN(getPartsField());
316 }
317
318 final T c = divisor.getRealPart();
319 final T d = divisor.getImaginaryPart();
320 if (c.isZero() && d.isZero()) {
321 return getNaN(getPartsField());
322 }
323
324 if (divisor.isInfinite() && !isInfinite()) {
325 return getZero(getPartsField());
326 }
327
328 if (FastMath.abs(c).getReal() < FastMath.abs(d).getReal()) {
329 T q = c.divide(d);
330 T invDen = c.multiply(q).add(d).reciprocal();
331 return createComplex(real.multiply(q).add(imaginary).multiply(invDen),
332 imaginary.multiply(q).subtract(real).multiply(invDen));
333 } else {
334 T q = d.divide(c);
335 T invDen = d.multiply(q).add(c).reciprocal();
336 return createComplex(imaginary.multiply(q).add(real).multiply(invDen),
337 imaginary.subtract(real.multiply(q)).multiply(invDen));
338 }
339 }
340
341
342
343
344
345
346
347
348
349 public FieldComplex<T> divide(T divisor) {
350 if (isNaN || divisor.isNaN()) {
351 return getNaN(getPartsField());
352 }
353 if (divisor.isZero()) {
354 return getNaN(getPartsField());
355 }
356 if (divisor.isInfinite()) {
357 return !isInfinite() ? getZero(getPartsField()) : getNaN(getPartsField());
358 }
359 return createComplex(real.divide(divisor), imaginary.divide(divisor));
360 }
361
362
363
364
365
366
367
368
369
370 @Override
371 public FieldComplex<T> divide(double divisor) {
372 if (isNaN || Double.isNaN(divisor)) {
373 return getNaN(getPartsField());
374 }
375 if (divisor == 0.0) {
376 return getNaN(getPartsField());
377 }
378 if (Double.isInfinite(divisor)) {
379 return !isInfinite() ? getZero(getPartsField()) : getNaN(getPartsField());
380 }
381 return createComplex(real.divide(divisor), imaginary.divide(divisor));
382 }
383
384
385 @Override
386 public FieldComplex<T> reciprocal() {
387 if (isNaN) {
388 return getNaN(getPartsField());
389 }
390
391 if (real.isZero() && imaginary.isZero()) {
392 return getInf(getPartsField());
393 }
394
395 if (isInfinite) {
396 return getZero(getPartsField());
397 }
398
399 if (FastMath.abs(real).getReal() < FastMath.abs(imaginary).getReal()) {
400 T q = real.divide(imaginary);
401 T scale = real.multiply(q).add(imaginary).reciprocal();
402 return createComplex(scale.multiply(q), scale.negate());
403 } else {
404 T q = imaginary.divide(real);
405 T scale = imaginary.multiply(q).add(real).reciprocal();
406 return createComplex(scale, scale.negate().multiply(q));
407 }
408 }
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434 @Override
435 public boolean equals(Object other) {
436 if (this == other) {
437 return true;
438 }
439 if (other instanceof FieldComplex){
440 @SuppressWarnings("unchecked")
441 FieldComplex<T> c = (FieldComplex<T>) other;
442 if (c.isNaN) {
443 return isNaN;
444 } else {
445 return real.equals(c.real) && imaginary.equals(c.imaginary);
446 }
447 }
448 return false;
449 }
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468 public static <T extends CalculusFieldElement<T>>boolean equals(FieldComplex<T> x, FieldComplex<T> y, int maxUlps) {
469 return Precision.equals(x.real.getReal(), y.real.getReal(), maxUlps) &&
470 Precision.equals(x.imaginary.getReal(), y.imaginary.getReal(), maxUlps);
471 }
472
473
474
475
476
477
478
479
480
481
482 public static <T extends CalculusFieldElement<T>>boolean equals(FieldComplex<T> x, FieldComplex<T> y) {
483 return equals(x, y, 1);
484 }
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501 public static <T extends CalculusFieldElement<T>>boolean equals(FieldComplex<T> x, FieldComplex<T> y,
502 double eps) {
503 return Precision.equals(x.real.getReal(), y.real.getReal(), eps) &&
504 Precision.equals(x.imaginary.getReal(), y.imaginary.getReal(), eps);
505 }
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522 public static <T extends CalculusFieldElement<T>>boolean equalsWithRelativeTolerance(FieldComplex<T> x,
523 FieldComplex<T> y,
524 double eps) {
525 return Precision.equalsWithRelativeTolerance(x.real.getReal(), y.real.getReal(), eps) &&
526 Precision.equalsWithRelativeTolerance(x.imaginary.getReal(), y.imaginary.getReal(), eps);
527 }
528
529
530
531
532
533
534
535
536 @Override
537 public int hashCode() {
538 if (isNaN) {
539 return 7;
540 }
541 return 37 * (17 * imaginary.hashCode() + real.hashCode());
542 }
543
544
545
546
547
548
549
550 @Override
551 public boolean isZero() {
552 return real.isZero() && imaginary.isZero();
553 }
554
555
556
557
558
559
560 public T getImaginary() {
561 return imaginary;
562 }
563
564
565
566
567
568
569 public T getImaginaryPart() {
570 return imaginary;
571 }
572
573
574
575
576
577
578 @Override
579 public double getReal() {
580 return real.getReal();
581 }
582
583
584
585
586
587
588 public T getRealPart() {
589 return real;
590 }
591
592
593
594
595
596
597
598
599 @Override
600 public boolean isNaN() {
601 return isNaN;
602 }
603
604
605
606
607 public boolean isReal() {
608 return imaginary.isZero();
609 }
610
611
612
613
614 public boolean isMathematicalInteger() {
615 return isReal() && Precision.isMathematicalInteger(real.getReal());
616 }
617
618
619
620
621
622
623
624
625
626
627 @Override
628 public boolean isInfinite() {
629 return isInfinite;
630 }
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654 @Override
655 public FieldComplex<T> multiply(FieldComplex<T> factor)
656 throws NullArgumentException {
657 MathUtils.checkNotNull(factor);
658 if (isNaN || factor.isNaN) {
659 return getNaN(getPartsField());
660 }
661 if (real.isInfinite() ||
662 imaginary.isInfinite() ||
663 factor.real.isInfinite() ||
664 factor.imaginary.isInfinite()) {
665
666 return getInf(getPartsField());
667 }
668 return createComplex(real.linearCombination(real, factor.real, imaginary.negate(), factor.imaginary),
669 real.linearCombination(real, factor.imaginary, imaginary, factor.real));
670 }
671
672
673
674
675
676
677
678
679
680 @Override
681 public FieldComplex<T> multiply(final int factor) {
682 if (isNaN) {
683 return getNaN(getPartsField());
684 }
685 if (real.isInfinite() || imaginary.isInfinite()) {
686 return getInf(getPartsField());
687 }
688 return createComplex(real.multiply(factor), imaginary.multiply(factor));
689 }
690
691
692
693
694
695
696
697
698
699 @Override
700 public FieldComplex<T> multiply(double factor) {
701 if (isNaN || Double.isNaN(factor)) {
702 return getNaN(getPartsField());
703 }
704 if (real.isInfinite() ||
705 imaginary.isInfinite() ||
706 Double.isInfinite(factor)) {
707
708 return getInf(getPartsField());
709 }
710 return createComplex(real.multiply(factor), imaginary.multiply(factor));
711 }
712
713
714
715
716
717
718
719
720
721 public FieldComplex<T> multiply(T factor) {
722 if (isNaN || factor.isNaN()) {
723 return getNaN(getPartsField());
724 }
725 if (real.isInfinite() ||
726 imaginary.isInfinite() ||
727 factor.isInfinite()) {
728
729 return getInf(getPartsField());
730 }
731 return createComplex(real.multiply(factor), imaginary.multiply(factor));
732 }
733
734
735
736
737
738 public FieldComplex<T> multiplyPlusI() {
739 return createComplex(imaginary.negate(), real);
740 }
741
742
743
744
745
746 public FieldComplex<T> multiplyMinusI() {
747 return createComplex(imaginary, real.negate());
748 }
749
750 @Override
751 public FieldComplex<T> square() {
752 return multiply(this);
753 }
754
755
756
757
758
759
760
761
762 @Override
763 public FieldComplex<T> negate() {
764 if (isNaN) {
765 return getNaN(getPartsField());
766 }
767
768 return createComplex(real.negate(), imaginary.negate());
769 }
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787 @Override
788 public FieldComplex<T> subtract(FieldComplex<T> subtrahend)
789 throws NullArgumentException {
790 MathUtils.checkNotNull(subtrahend);
791 if (isNaN || subtrahend.isNaN) {
792 return getNaN(getPartsField());
793 }
794
795 return createComplex(real.subtract(subtrahend.getRealPart()),
796 imaginary.subtract(subtrahend.getImaginaryPart()));
797 }
798
799
800
801
802
803
804
805
806
807 @Override
808 public FieldComplex<T> subtract(double subtrahend) {
809 if (isNaN || Double.isNaN(subtrahend)) {
810 return getNaN(getPartsField());
811 }
812 return createComplex(real.subtract(subtrahend), imaginary);
813 }
814
815
816
817
818
819
820
821
822
823 public FieldComplex<T> subtract(T subtrahend) {
824 if (isNaN || subtrahend.isNaN()) {
825 return getNaN(getPartsField());
826 }
827 return createComplex(real.subtract(subtrahend), imaginary);
828 }
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843 @Override
844 public FieldComplex<T> acos() {
845 if (isNaN) {
846 return getNaN(getPartsField());
847 }
848
849 return this.add(this.sqrt1z().multiplyPlusI()).log().multiplyMinusI();
850 }
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865 @Override
866 public FieldComplex<T> asin() {
867 if (isNaN) {
868 return getNaN(getPartsField());
869 }
870
871 return sqrt1z().add(this.multiplyPlusI()).log().multiplyMinusI();
872 }
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887 @Override
888 public FieldComplex<T> atan() {
889 if (isNaN) {
890 return getNaN(getPartsField());
891 }
892
893 final T one = getPartsField().getOne();
894 if (real.isZero()) {
895
896
897 if (imaginary.multiply(imaginary).subtract(one).isZero()) {
898 return getNaN(getPartsField());
899 }
900
901
902 final T zero = getPartsField().getZero();
903 final FieldComplex<T> tmp = createComplex(one.add(imaginary).divide(one.subtract(imaginary)), zero).
904 log().multiplyPlusI().multiply(0.5);
905 return createComplex(FastMath.copySign(tmp.real, real), tmp.imaginary);
906
907 } else {
908
909 final FieldComplex<T> n = createComplex(one.add(imaginary), real.negate());
910 final FieldComplex<T> d = createComplex(one.subtract(imaginary), real);
911 return n.divide(d).log().multiplyPlusI().multiply(0.5);
912 }
913
914 }
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944 @Override
945 public FieldComplex<T> cos() {
946 if (isNaN) {
947 return getNaN(getPartsField());
948 }
949
950 final FieldSinCos<T> scr = FastMath.sinCos(real);
951 final FieldSinhCosh<T> schi = FastMath.sinhCosh(imaginary);
952 return createComplex(scr.cos().multiply(schi.cosh()), scr.sin().negate().multiply(schi.sinh()));
953 }
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985 @Override
986 public FieldComplex<T> cosh() {
987 if (isNaN) {
988 return getNaN(getPartsField());
989 }
990
991 final FieldSinhCosh<T> schr = FastMath.sinhCosh(real);
992 final FieldSinCos<T> sci = FastMath.sinCos(imaginary);
993 return createComplex(schr.cosh().multiply(sci.cos()), schr.sinh().multiply(sci.sin()));
994 }
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027 @Override
1028 public FieldComplex<T> exp() {
1029 if (isNaN) {
1030 return getNaN(getPartsField());
1031 }
1032
1033 final T expReal = FastMath.exp(real);
1034 final FieldSinCos<T> sc = FastMath.sinCos(imaginary);
1035 return createComplex(expReal.multiply(sc.cos()), expReal.multiply(sc.sin()));
1036 }
1037
1038
1039 @Override
1040 public FieldComplex<T> expm1() {
1041 if (isNaN) {
1042 return getNaN(getPartsField());
1043 }
1044
1045 final T expm1Real = FastMath.expm1(real);
1046 final FieldSinCos<T> sc = FastMath.sinCos(imaginary);
1047 return createComplex(expm1Real.multiply(sc.cos()), expm1Real.multiply(sc.sin()));
1048 }
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084 @Override
1085 public FieldComplex<T> log() {
1086 if (isNaN) {
1087 return getNaN(getPartsField());
1088 }
1089
1090 return createComplex(FastMath.log(FastMath.hypot(real, imaginary)),
1091 FastMath.atan2(imaginary, real));
1092 }
1093
1094
1095 @Override
1096 public FieldComplex<T> log1p() {
1097 return add(1.0).log();
1098 }
1099
1100
1101 @Override
1102 public FieldComplex<T> log10() {
1103 return log().divide(LOG10);
1104 }
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121 @Override
1122 public FieldComplex<T> pow(FieldComplex<T> x)
1123 throws NullArgumentException {
1124
1125 MathUtils.checkNotNull(x);
1126
1127 if (x.imaginary.isZero()) {
1128 final int nx = (int) FastMath.rint(x.real.getReal());
1129 if (x.real.getReal() == nx) {
1130
1131 return pow(nx);
1132 } else if (this.imaginary.isZero()) {
1133
1134 final T realPow = FastMath.pow(this.real, x.real);
1135 if (realPow.isFinite()) {
1136 return createComplex(realPow, getPartsField().getZero());
1137 }
1138 }
1139 }
1140
1141
1142 return this.log().multiply(x).exp();
1143
1144 }
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161 public FieldComplex<T> pow(T x) {
1162
1163 final int nx = (int) FastMath.rint(x.getReal());
1164 if (x.getReal() == nx) {
1165
1166 return pow(nx);
1167 } else if (this.imaginary.isZero()) {
1168
1169 final T realPow = FastMath.pow(this.real, x);
1170 if (realPow.isFinite()) {
1171 return createComplex(realPow, getPartsField().getZero());
1172 }
1173 }
1174
1175
1176 return this.log().multiply(x).exp();
1177
1178 }
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194 @Override
1195 public FieldComplex<T> pow(double x) {
1196
1197 final int nx = (int) FastMath.rint(x);
1198 if (x == nx) {
1199
1200 return pow(nx);
1201 } else if (this.imaginary.isZero()) {
1202
1203 final T realPow = FastMath.pow(this.real, x);
1204 if (realPow.isFinite()) {
1205 return createComplex(realPow, getPartsField().getZero());
1206 }
1207 }
1208
1209
1210 return this.log().multiply(x).exp();
1211
1212 }
1213
1214
1215 @Override
1216 public FieldComplex<T> pow(final int n) {
1217
1218 FieldComplex<T> result = getField().getOne();
1219 final boolean invert;
1220 int p = n;
1221 if (p < 0) {
1222 invert = true;
1223 p = -p;
1224 } else {
1225 invert = false;
1226 }
1227
1228
1229 FieldComplex<T> square = this;
1230 while (p > 0) {
1231 if ((p & 0x1) > 0) {
1232 result = result.multiply(square);
1233 }
1234 square = square.multiply(square);
1235 p = p >> 1;
1236 }
1237
1238 return invert ? result.reciprocal() : result;
1239
1240 }
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273 @Override
1274 public FieldComplex<T> sin() {
1275 if (isNaN) {
1276 return getNaN(getPartsField());
1277 }
1278
1279 final FieldSinCos<T> scr = FastMath.sinCos(real);
1280 final FieldSinhCosh<T> schi = FastMath.sinhCosh(imaginary);
1281 return createComplex(scr.sin().multiply(schi.cosh()), scr.cos().multiply(schi.sinh()));
1282
1283 }
1284
1285
1286
1287 @Override
1288 public FieldSinCos<FieldComplex<T>> sinCos() {
1289 if (isNaN) {
1290 return new FieldSinCos<>(getNaN(getPartsField()), getNaN(getPartsField()));
1291 }
1292
1293 final FieldSinCos<T> scr = FastMath.sinCos(real);
1294 final FieldSinhCosh<T> schi = FastMath.sinhCosh(imaginary);
1295 return new FieldSinCos<>(createComplex(scr.sin().multiply(schi.cosh()), scr.cos().multiply(schi.sinh())),
1296 createComplex(scr.cos().multiply(schi.cosh()), scr.sin().negate().multiply(schi.sinh())));
1297 }
1298
1299
1300 @Override
1301 public FieldComplex<T> atan2(FieldComplex<T> x) {
1302
1303
1304 final FieldComplex<T> r = x.square().add(multiply(this)).sqrt();
1305
1306 if (x.real.getReal() >= 0) {
1307
1308 return divide(r.add(x)).atan().multiply(2);
1309 } else {
1310
1311 return divide(r.subtract(x)).atan().multiply(-2).add(x.real.getPi());
1312 }
1313 }
1314
1315
1316
1317
1318
1319
1320 @Override
1321 public FieldComplex<T> acosh() {
1322 final FieldComplex<T> sqrtPlus = add(1).sqrt();
1323 final FieldComplex<T> sqrtMinus = subtract(1).sqrt();
1324 return add(sqrtPlus.multiply(sqrtMinus)).log();
1325 }
1326
1327
1328
1329
1330
1331
1332 @Override
1333 public FieldComplex<T> asinh() {
1334 return add(multiply(this).add(1.0).sqrt()).log();
1335 }
1336
1337
1338
1339
1340
1341
1342 @Override
1343 public FieldComplex<T> atanh() {
1344 final FieldComplex<T> logPlus = add(1).log();
1345 final FieldComplex<T> logMinus = createComplex(getPartsField().getOne().subtract(real), imaginary.negate()).log();
1346 return logPlus.subtract(logMinus).multiply(0.5);
1347 }
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379 @Override
1380 public FieldComplex<T> sinh() {
1381 if (isNaN) {
1382 return getNaN(getPartsField());
1383 }
1384
1385 final FieldSinhCosh<T> schr = FastMath.sinhCosh(real);
1386 final FieldSinCos<T> sci = FastMath.sinCos(imaginary);
1387 return createComplex(schr.sinh().multiply(sci.cos()), schr.cosh().multiply(sci.sin()));
1388 }
1389
1390
1391
1392 @Override
1393 public FieldSinhCosh<FieldComplex<T>> sinhCosh() {
1394 if (isNaN) {
1395 return new FieldSinhCosh<>(getNaN(getPartsField()), getNaN(getPartsField()));
1396 }
1397
1398 final FieldSinhCosh<T> schr = FastMath.sinhCosh(real);
1399 final FieldSinCos<T> sci = FastMath.sinCos(imaginary);
1400 return new FieldSinhCosh<>(createComplex(schr.sinh().multiply(sci.cos()), schr.cosh().multiply(sci.sin())),
1401 createComplex(schr.cosh().multiply(sci.cos()), schr.sinh().multiply(sci.sin())));
1402 }
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440 @Override
1441 public FieldComplex<T> sqrt() {
1442 if (isNaN) {
1443 return getNaN(getPartsField());
1444 }
1445
1446 if (isZero()) {
1447 return getZero(getPartsField());
1448 }
1449
1450 T t = FastMath.sqrt((FastMath.abs(real).add(FastMath.hypot(real, imaginary))).multiply(0.5));
1451 if (real.getReal() >= 0.0) {
1452 return createComplex(t, imaginary.divide(t.multiply(2)));
1453 } else {
1454 return createComplex(FastMath.abs(imaginary).divide(t.multiply(2)),
1455 FastMath.copySign(t, imaginary));
1456 }
1457 }
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475 public FieldComplex<T> sqrt1z() {
1476 final FieldComplex<T> t2 = this.square();
1477 return createComplex(getPartsField().getOne().subtract(t2.real), t2.imaginary.negate()).sqrt();
1478 }
1479
1480
1481
1482
1483
1484
1485 @Override
1486 public FieldComplex<T> cbrt() {
1487 final T magnitude = FastMath.cbrt(abs().getRealPart());
1488 final FieldSinCos<T> sc = FastMath.sinCos(getArgument().divide(3));
1489 return createComplex(magnitude.multiply(sc.cos()), magnitude.multiply(sc.sin()));
1490 }
1491
1492
1493
1494
1495
1496
1497 @Override
1498 public FieldComplex<T> rootN(int n) {
1499 final T magnitude = FastMath.pow(abs().getRealPart(), 1.0 / n);
1500 final FieldSinCos<T> sc = FastMath.sinCos(getArgument().divide(n));
1501 return createComplex(magnitude.multiply(sc.cos()), magnitude.multiply(sc.sin()));
1502 }
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535 @Override
1536 public FieldComplex<T> tan() {
1537 if (isNaN || real.isInfinite()) {
1538 return getNaN(getPartsField());
1539 }
1540 if (imaginary.getReal() > 20.0) {
1541 return getI(getPartsField());
1542 }
1543 if (imaginary.getReal() < -20.0) {
1544 return getMinusI(getPartsField());
1545 }
1546
1547 final FieldSinCos<T> sc2r = FastMath.sinCos(real.multiply(2));
1548 T imaginary2 = imaginary.multiply(2);
1549 T d = sc2r.cos().add(FastMath.cosh(imaginary2));
1550
1551 return createComplex(sc2r.sin().divide(d), FastMath.sinh(imaginary2).divide(d));
1552
1553 }
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586 @Override
1587 public FieldComplex<T> tanh() {
1588 if (isNaN || imaginary.isInfinite()) {
1589 return getNaN(getPartsField());
1590 }
1591 if (real.getReal() > 20.0) {
1592 return getOne(getPartsField());
1593 }
1594 if (real.getReal() < -20.0) {
1595 return getMinusOne(getPartsField());
1596 }
1597 T real2 = real.multiply(2);
1598 final FieldSinCos<T> sc2i = FastMath.sinCos(imaginary.multiply(2));
1599 T d = FastMath.cosh(real2).add(sc2i.cos());
1600
1601 return createComplex(FastMath.sinh(real2).divide(d), sc2i.sin().divide(d));
1602 }
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623 public T getArgument() {
1624 return FastMath.atan2(getImaginaryPart(), getRealPart());
1625 }
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648 public List<FieldComplex<T>> nthRoot(int n) throws MathIllegalArgumentException {
1649
1650 if (n <= 0) {
1651 throw new MathIllegalArgumentException(LocalizedCoreFormats.CANNOT_COMPUTE_NTH_ROOT_FOR_NEGATIVE_N,
1652 n);
1653 }
1654
1655 final List<FieldComplex<T>> result = new ArrayList<>();
1656
1657 if (isNaN) {
1658 result.add(getNaN(getPartsField()));
1659 return result;
1660 }
1661 if (isInfinite()) {
1662 result.add(getInf(getPartsField()));
1663 return result;
1664 }
1665
1666
1667 final T nthRootOfAbs = FastMath.pow(FastMath.hypot(real, imaginary), 1.0 / n);
1668
1669
1670 final T nthPhi = getArgument().divide(n);
1671 final double slice = 2 * FastMath.PI / n;
1672 T innerPart = nthPhi;
1673 for (int k = 0; k < n ; k++) {
1674
1675 final FieldSinCos<T> scInner = FastMath.sinCos(innerPart);
1676 final T realPart = nthRootOfAbs.multiply(scInner.cos());
1677 final T imaginaryPart = nthRootOfAbs.multiply(scInner.sin());
1678 result.add(createComplex(realPart, imaginaryPart));
1679 innerPart = innerPart.add(slice);
1680 }
1681
1682 return result;
1683 }
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694 protected FieldComplex<T> createComplex(final T realPart, final T imaginaryPart) {
1695 return new FieldComplex<>(realPart, imaginaryPart);
1696 }
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706 public static <T extends CalculusFieldElement<T>> FieldComplex<T>
1707 valueOf(T realPart, T imaginaryPart) {
1708 if (realPart.isNaN() || imaginaryPart.isNaN()) {
1709 return getNaN(realPart.getField());
1710 }
1711 return new FieldComplex<>(realPart, imaginaryPart);
1712 }
1713
1714
1715
1716
1717
1718
1719
1720
1721 public static <T extends CalculusFieldElement<T>> FieldComplex<T>
1722 valueOf(T realPart) {
1723 if (realPart.isNaN()) {
1724 return getNaN(realPart.getField());
1725 }
1726 return new FieldComplex<>(realPart);
1727 }
1728
1729
1730 @Override
1731 public FieldComplex<T> newInstance(double realPart) {
1732 return valueOf(getPartsField().getZero().newInstance(realPart));
1733 }
1734
1735
1736 @Override
1737 public FieldComplexField<T> getField() {
1738 return FieldComplexField.getField(getPartsField());
1739 }
1740
1741
1742
1743
1744 public Field<T> getPartsField() {
1745 return real.getField();
1746 }
1747
1748
1749 @Override
1750 public String toString() {
1751 return "(" + real + ", " + imaginary + ")";
1752 }
1753
1754
1755 @Override
1756 public FieldComplex<T> scalb(int n) {
1757 return createComplex(FastMath.scalb(real, n), FastMath.scalb(imaginary, n));
1758 }
1759
1760
1761 @Override
1762 public FieldComplex<T> ulp() {
1763 return createComplex(FastMath.ulp(real), FastMath.ulp(imaginary));
1764 }
1765
1766
1767 @Override
1768 public FieldComplex<T> hypot(FieldComplex<T> y) {
1769 if (isInfinite() || y.isInfinite()) {
1770 return getInf(getPartsField());
1771 } else if (isNaN() || y.isNaN()) {
1772 return getNaN(getPartsField());
1773 } else {
1774 return square().add(y.square()).sqrt();
1775 }
1776 }
1777
1778
1779 @Override
1780 public FieldComplex<T> linearCombination(final FieldComplex<T>[] a, final FieldComplex<T>[] b)
1781 throws MathIllegalArgumentException {
1782 final int n = 2 * a.length;
1783 final T[] realA = MathArrays.buildArray(getPartsField(), n);
1784 final T[] realB = MathArrays.buildArray(getPartsField(), n);
1785 final T[] imaginaryA = MathArrays.buildArray(getPartsField(), n);
1786 final T[] imaginaryB = MathArrays.buildArray(getPartsField(), n);
1787 for (int i = 0; i < a.length; ++i) {
1788 final FieldComplex<T> ai = a[i];
1789 final FieldComplex<T> bi = b[i];
1790 realA[2 * i ] = ai.real;
1791 realA[2 * i + 1] = ai.imaginary.negate();
1792 realB[2 * i ] = bi.real;
1793 realB[2 * i + 1] = bi.imaginary;
1794 imaginaryA[2 * i ] = ai.real;
1795 imaginaryA[2 * i + 1] = ai.imaginary;
1796 imaginaryB[2 * i ] = bi.imaginary;
1797 imaginaryB[2 * i + 1] = bi.real;
1798 }
1799 return createComplex(real.linearCombination(realA, realB),
1800 real.linearCombination(imaginaryA, imaginaryB));
1801 }
1802
1803
1804 @Override
1805 public FieldComplex<T> linearCombination(final double[] a, final FieldComplex<T>[] b)
1806 throws MathIllegalArgumentException {
1807 final int n = a.length;
1808 final T[] realB = MathArrays.buildArray(getPartsField(), n);
1809 final T[] imaginaryB = MathArrays.buildArray(getPartsField(), n);
1810 for (int i = 0; i < a.length; ++i) {
1811 final FieldComplex<T> bi = b[i];
1812 realB[i] = bi.real;
1813 imaginaryB[i] = bi.imaginary;
1814 }
1815 return createComplex(real.linearCombination(a, realB),
1816 real.linearCombination(a, imaginaryB));
1817 }
1818
1819
1820 @Override
1821 public FieldComplex<T> linearCombination(final FieldComplex<T> a1, final FieldComplex<T> b1, final FieldComplex<T> a2, final FieldComplex<T> b2) {
1822 return createComplex(real.linearCombination(a1.real, b1.real,
1823 a1.imaginary.negate(), b1.imaginary,
1824 a2.real, b2.real,
1825 a2.imaginary.negate(), b2.imaginary),
1826 real.linearCombination(a1.real, b1.imaginary,
1827 a1.imaginary, b1.real,
1828 a2.real, b2.imaginary,
1829 a2.imaginary, b2.real));
1830 }
1831
1832
1833 @Override
1834 public FieldComplex<T> linearCombination(final double a1, final FieldComplex<T> b1, final double a2, final FieldComplex<T> b2) {
1835 return createComplex(real.linearCombination(a1, b1.real,
1836 a2, b2.real),
1837 real.linearCombination(a1, b1.imaginary,
1838 a2, b2.imaginary));
1839 }
1840
1841
1842 @Override
1843 public FieldComplex<T> linearCombination(final FieldComplex<T> a1, final FieldComplex<T> b1,
1844 final FieldComplex<T> a2, final FieldComplex<T> b2,
1845 final FieldComplex<T> a3, final FieldComplex<T> b3) {
1846 FieldComplex<T>[] a = MathArrays.buildArray(getField(), 3);
1847 a[0] = a1;
1848 a[1] = a2;
1849 a[2] = a3;
1850 FieldComplex<T>[] b = MathArrays.buildArray(getField(), 3);
1851 b[0] = b1;
1852 b[1] = b2;
1853 b[2] = b3;
1854 return linearCombination(a, b);
1855 }
1856
1857
1858 @Override
1859 public FieldComplex<T> linearCombination(final double a1, final FieldComplex<T> b1,
1860 final double a2, final FieldComplex<T> b2,
1861 final double a3, final FieldComplex<T> b3) {
1862 FieldComplex<T>[] b = MathArrays.buildArray(getField(), 3);
1863 b[0] = b1;
1864 b[1] = b2;
1865 b[2] = b3;
1866 return linearCombination(new double[] { a1, a2, a3 }, b);
1867 }
1868
1869
1870 @Override
1871 public FieldComplex<T> linearCombination(final FieldComplex<T> a1, final FieldComplex<T> b1,
1872 final FieldComplex<T> a2, final FieldComplex<T> b2,
1873 final FieldComplex<T> a3, final FieldComplex<T> b3,
1874 final FieldComplex<T> a4, final FieldComplex<T> b4) {
1875 FieldComplex<T>[] a = MathArrays.buildArray(getField(), 4);
1876 a[0] = a1;
1877 a[1] = a2;
1878 a[2] = a3;
1879 a[3] = a4;
1880 FieldComplex<T>[] b = MathArrays.buildArray(getField(), 4);
1881 b[0] = b1;
1882 b[1] = b2;
1883 b[2] = b3;
1884 b[3] = b4;
1885 return linearCombination(a, b);
1886 }
1887
1888
1889 @Override
1890 public FieldComplex<T> linearCombination(final double a1, final FieldComplex<T> b1,
1891 final double a2, final FieldComplex<T> b2,
1892 final double a3, final FieldComplex<T> b3,
1893 final double a4, final FieldComplex<T> b4) {
1894 FieldComplex<T>[] b = MathArrays.buildArray(getField(), 4);
1895 b[0] = b1;
1896 b[1] = b2;
1897 b[2] = b3;
1898 b[3] = b4;
1899 return linearCombination(new double[] { a1, a2, a3, a4 }, b);
1900 }
1901
1902
1903 @Override
1904 public FieldComplex<T> ceil() {
1905 return createComplex(FastMath.ceil(getRealPart()), FastMath.ceil(getImaginaryPart()));
1906 }
1907
1908
1909 @Override
1910 public FieldComplex<T> floor() {
1911 return createComplex(FastMath.floor(getRealPart()), FastMath.floor(getImaginaryPart()));
1912 }
1913
1914
1915 @Override
1916 public FieldComplex<T> rint() {
1917 return createComplex(FastMath.rint(getRealPart()), FastMath.rint(getImaginaryPart()));
1918 }
1919
1920
1921
1922
1923
1924
1925
1926 @Override
1927 public FieldComplex<T> remainder(final double a) {
1928 return createComplex(FastMath.IEEEremainder(getRealPart(), a), FastMath.IEEEremainder(getImaginaryPart(), a));
1929 }
1930
1931
1932
1933
1934
1935
1936
1937 @Override
1938 public FieldComplex<T> remainder(final FieldComplex<T> a) {
1939 final FieldComplex<T> complexQuotient = divide(a);
1940 final T qRInt = FastMath.rint(complexQuotient.real);
1941 final T qIInt = FastMath.rint(complexQuotient.imaginary);
1942 return createComplex(real.subtract(qRInt.multiply(a.real)).add(qIInt.multiply(a.imaginary)),
1943 imaginary.subtract(qRInt.multiply(a.imaginary)).subtract(qIInt.multiply(a.real)));
1944 }
1945
1946
1947 @Override
1948 public FieldComplex<T> sign() {
1949 if (isNaN() || isZero()) {
1950 return this;
1951 } else {
1952 return this.divide(FastMath.hypot(real, imaginary));
1953 }
1954 }
1955
1956
1957
1958
1959
1960
1961 @Override
1962 public FieldComplex<T> copySign(final FieldComplex<T> z) {
1963 return createComplex(FastMath.copySign(getRealPart(), z.getRealPart()),
1964 FastMath.copySign(getImaginaryPart(), z.getImaginaryPart()));
1965 }
1966
1967
1968 @Override
1969 public FieldComplex<T> copySign(double r) {
1970 return createComplex(FastMath.copySign(getRealPart(), r), FastMath.copySign(getImaginaryPart(), r));
1971 }
1972
1973
1974 @Override
1975 public FieldComplex<T> toDegrees() {
1976 return createComplex(FastMath.toDegrees(getRealPart()), FastMath.toDegrees(getImaginaryPart()));
1977 }
1978
1979
1980 @Override
1981 public FieldComplex<T> toRadians() {
1982 return createComplex(FastMath.toRadians(getRealPart()), FastMath.toRadians(getImaginaryPart()));
1983 }
1984
1985
1986 @Override
1987 public FieldComplex<T> getPi() {
1988 return getPi(getPartsField());
1989 }
1990
1991 }