1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package com.irurueta.algebra;
17
18 import java.util.Arrays;
19
20
21
22
23 @SuppressWarnings("DuplicatedCode")
24 public class ArrayUtils {
25
26
27
28
29 private ArrayUtils() {
30 }
31
32
33
34
35
36
37
38
39
40
41 private static void internalMultiplyByScalar(
42 final double[] inputArray, final double scalar, final double[] result) {
43 for (var i = 0; i < inputArray.length; ++i) {
44 result[i] = scalar * inputArray[i];
45 }
46 }
47
48
49
50
51
52
53
54
55
56
57
58 public static void multiplyByScalar(final double[] inputArray, final double scalar, final double[] result) {
59 if (inputArray.length != result.length) {
60 throw new IllegalArgumentException();
61 }
62 internalMultiplyByScalar(inputArray, scalar, result);
63 }
64
65
66
67
68
69
70
71
72
73
74 public static double[] multiplyByScalarAndReturnNew(final double[] inputArray, final double scalar) {
75 final var result = new double[inputArray.length];
76 internalMultiplyByScalar(inputArray, scalar, result);
77 return result;
78 }
79
80
81
82
83
84
85
86
87
88
89
90
91
92 private static void internalSum(final double[] firstOperand, final double[] secondOperand, final double[] result) {
93 for (var i = 0; i < firstOperand.length; i++) {
94 result[i] = firstOperand[i] + secondOperand[i];
95 }
96 }
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111 public static void sum(final double[] firstOperand, final double[] secondOperand, final double[] result) {
112 if (firstOperand.length != secondOperand.length || firstOperand.length != result.length) {
113 throw new IllegalArgumentException();
114 }
115 internalSum(firstOperand, secondOperand, result);
116 }
117
118
119
120
121
122
123
124
125
126
127
128 public static double[] sumAndReturnNew(final double[] firstOperand, final double[] secondOperand) {
129 if (firstOperand.length != secondOperand.length) {
130 throw new IllegalArgumentException();
131 }
132
133 final var result = new double[firstOperand.length];
134 internalSum(firstOperand, secondOperand, result);
135 return result;
136 }
137
138
139
140
141
142
143
144
145
146
147
148
149
150 private static void internalSubtract(
151 final double[] firstOperand, final double[] secondOperand, final double[] result) {
152 for (var i = 0; i < firstOperand.length; i++) {
153 result[i] = firstOperand[i] - secondOperand[i];
154 }
155 }
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170 public static void subtract(final double[] firstOperand, final double[] secondOperand, final double[] result) {
171 if (firstOperand.length != secondOperand.length || firstOperand.length != result.length) {
172 throw new IllegalArgumentException();
173 }
174 internalSubtract(firstOperand, secondOperand, result);
175 }
176
177
178
179
180
181
182
183
184
185
186
187
188 public static double[] subtractAndReturnNew(final double[] firstOperand, final double[] secondOperand) {
189 if (firstOperand.length != secondOperand.length) {
190 throw new IllegalArgumentException();
191 }
192
193 final var result = new double[firstOperand.length];
194 internalSubtract(firstOperand, secondOperand, result);
195 return result;
196 }
197
198
199
200
201
202
203
204
205
206
207
208 public static double dotProduct(final double[] firstOperand, final double[] secondOperand) {
209 if (firstOperand.length != secondOperand.length) {
210 throw new IllegalArgumentException("both operands must have same length");
211 }
212
213 var result = 0.0;
214 for (var i = 0; i < firstOperand.length; i++) {
215 result += firstOperand[i] * secondOperand[i];
216 }
217 return result;
218 }
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237 public static double dotProduct(final double[] firstOperand, final double[] secondOperand,
238 final Matrix jacobianFirst, final Matrix jacobianSecond) {
239 if (jacobianFirst != null
240 && (jacobianFirst.getRows() != 1 || jacobianFirst.getColumns() != firstOperand.length)) {
241 throw new IllegalArgumentException("jacobian first must be a row vector having the same number of "
242 + "columns as first operand length");
243 }
244 if (jacobianSecond != null
245 && (jacobianSecond.getRows() != 1 || jacobianSecond.getColumns() != secondOperand.length)) {
246 throw new IllegalArgumentException("jacobian second must be a row vector having the same number of "
247 + "columns as second operand length");
248 }
249
250 if (jacobianFirst != null) {
251 jacobianFirst.setSubmatrix(0, 0, 0,
252 firstOperand.length - 1, firstOperand);
253 }
254 if (jacobianSecond != null) {
255 jacobianSecond.setSubmatrix(0, 0, 0,
256 secondOperand.length - 1, secondOperand);
257 }
258
259 return dotProduct(firstOperand, secondOperand);
260 }
261
262
263
264
265
266
267
268
269
270
271
272 public static double angle(final double[] firstOperand, final double[] secondOperand) {
273 final var norm1 = Utils.normF(firstOperand);
274 final var norm2 = Utils.normF(secondOperand);
275 return Math.acos(Math.min(dotProduct(firstOperand, secondOperand) / norm1 / norm2, 1.0));
276 }
277
278
279
280
281
282
283
284
285
286
287
288
289 private static void internalMultiplyByScalar(final Complex[] inputArray, final double scalar,
290 final Complex[] result) {
291 for (var i = 0; i < inputArray.length; ++i) {
292 result[i].setReal(inputArray[i].getReal() * scalar);
293 result[i].setImaginary(inputArray[i].getImaginary() * scalar);
294 }
295 }
296
297
298
299
300
301
302
303
304
305
306
307 public static void multiplyByScalar(final Complex[] inputArray, final double scalar, final Complex[] result) {
308 if (inputArray.length != result.length) {
309 throw new IllegalArgumentException();
310 }
311 internalMultiplyByScalar(inputArray, scalar, result);
312 }
313
314
315
316
317
318
319
320
321
322
323 public static Complex[] multiplyByScalarAndReturnNew(final Complex[] inputArray, final double scalar) {
324 final var result = new Complex[inputArray.length];
325
326
327 for (var i = 0; i < inputArray.length; i++) {
328 result[i] = new Complex(inputArray[i].getReal() * scalar,
329 inputArray[i].getImaginary() * scalar);
330 }
331 return result;
332 }
333
334
335
336
337
338
339
340
341
342
343
344
345
346 private static void internalSum(final Complex[] firstOperand, final Complex[] secondOperand,
347 final Complex[] result) {
348 for (var i = 0; i < firstOperand.length; i++) {
349 result[i].setReal(firstOperand[i].getReal() + secondOperand[i].getReal());
350 result[i].setImaginary(firstOperand[i].getImaginary() + secondOperand[i].getImaginary());
351 }
352 }
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367 public static void sum(
368 final Complex[] firstOperand, final Complex[] secondOperand, final Complex[] result) {
369 if (firstOperand.length != secondOperand.length || firstOperand.length != result.length) {
370 throw new IllegalArgumentException();
371 }
372 internalSum(firstOperand, secondOperand, result);
373 }
374
375
376
377
378
379
380
381
382
383
384
385 public static Complex[] sumAndReturnNew(final Complex[] firstOperand, final Complex[] secondOperand) {
386 if (firstOperand.length != secondOperand.length) {
387 throw new IllegalArgumentException();
388 }
389
390 final var result = new Complex[firstOperand.length];
391
392 for (var i = 0; i < firstOperand.length; i++)
393 result[i] = firstOperand[i].addAndReturnNew(secondOperand[i]);
394 return result;
395 }
396
397
398
399
400
401
402
403
404
405
406
407
408
409 private static void internalSubtract(
410 final Complex[] firstOperand, final Complex[] secondOperand, final Complex[] result) {
411 for (var i = 0; i < firstOperand.length; i++) {
412 result[i].setReal(firstOperand[i].getReal() - secondOperand[i].getReal());
413 result[i].setImaginary(firstOperand[i].getImaginary() - secondOperand[i].getImaginary());
414 }
415 }
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430 public static void subtract(final Complex[] firstOperand, final Complex[] secondOperand, final Complex[] result) {
431 if (firstOperand.length != secondOperand.length || firstOperand.length != result.length) {
432 throw new IllegalArgumentException();
433 }
434 internalSubtract(firstOperand, secondOperand, result);
435 }
436
437
438
439
440
441
442
443
444
445
446
447
448 public static Complex[] subtractAndReturnNew(final Complex[] firstOperand, final Complex[] secondOperand) {
449 if (firstOperand.length != secondOperand.length) {
450 throw new IllegalArgumentException();
451 }
452
453 final var result = new Complex[firstOperand.length];
454
455 for (int i = 0; i < firstOperand.length; i++) {
456 result[i] = firstOperand[i].subtractAndReturnNew(secondOperand[i]);
457 }
458 return result;
459 }
460
461
462
463
464
465
466
467
468
469
470
471 public static Complex dotProduct(final Complex[] firstOperand, final Complex[] secondOperand) {
472 if (firstOperand.length != secondOperand.length) {
473 throw new IllegalArgumentException();
474 }
475
476 final var result = new Complex(0.0);
477 for (var i = 0; i < firstOperand.length; i++) {
478 result.add(firstOperand[i].multiplyAndReturnNew(secondOperand[i]));
479 }
480 return result;
481 }
482
483
484
485
486
487
488
489
490
491
492 public static void normalize(final double[] v, final double[] result, final Matrix jacobian) {
493 final var s = v.length;
494
495 if (s != result.length) {
496 throw new IllegalArgumentException("both arrays must have the same length");
497 }
498
499 if (jacobian != null && (jacobian.getRows() != s || jacobian.getColumns() != s)) {
500 throw new IllegalArgumentException("provided jacobian is not NxN where N is length of v");
501 }
502
503 final var n2 = dotProduct(v, v);
504 final var n = Math.sqrt(n2);
505
506 if (jacobian != null) {
507 try {
508 final var n3 = n * n2;
509
510
511 Matrix.identity(jacobian);
512 jacobian.multiplyByScalar(n2);
513 jacobian.subtract(Matrix.newFromArray(v, true)
514 .multiplyAndReturnNew(Matrix.newFromArray(v, false)));
515 if (n3 != 0.0) {
516 jacobian.multiplyByScalar(1.0 / n3);
517 } else {
518 jacobian.initialize(Double.MAX_VALUE);
519 }
520 } catch (final WrongSizeException ignore) {
521
522 }
523 }
524
525 if (n != 0.0) {
526 internalMultiplyByScalar(v, 1.0 / n, result);
527 } else {
528 Arrays.fill(result, Double.MAX_VALUE);
529 }
530 }
531
532
533
534
535
536
537
538
539
540
541 public static double[] normalizeAndReturnNew(final double[] v, final Matrix jacobian) {
542 final var result = new double[v.length];
543 normalize(v, result, jacobian);
544 return result;
545 }
546
547
548
549
550
551
552
553
554
555
556 public static void normalize(final double[] v, final Matrix jacobian) {
557 normalize(v, v, jacobian);
558 }
559
560
561
562
563
564
565
566
567
568 public static void normalize(final double[] v, final double[] result) {
569 normalize(v, result, null);
570 }
571
572
573
574
575
576
577
578 public static double[] normalizeAndReturnNew(final double[] v) {
579 return normalizeAndReturnNew(v, null);
580 }
581
582
583
584
585
586
587 public static void normalize(final double[] v) {
588 normalize(v, (Matrix) null);
589 }
590
591
592
593
594
595
596
597
598
599 public static void reverse(final double[] v, final double[] result) {
600
601 final var length = v.length;
602
603 if (result.length != length) {
604 throw new IllegalArgumentException();
605 }
606
607 final var halfLength = length / 2;
608 double tmp;
609 for (int i = 0, j = length - 1; i < halfLength; i++, j--) {
610 tmp = v[i];
611 result[i] = v[j];
612 result[j] = tmp;
613 }
614
615 if (length % 2 != 0) {
616
617 result[halfLength] = v[halfLength];
618 }
619 }
620
621
622
623
624
625
626
627 public static void reverse(final double[] v) {
628 reverse(v, v);
629 }
630
631
632
633
634
635
636
637
638 public static double[] reverseAndReturnNew(final double[] v) {
639 final var result = new double[v.length];
640 reverse(v, result);
641 return result;
642 }
643
644
645
646
647
648
649
650
651
652 public static void reverse(final Complex[] v, final Complex[] result) {
653
654 final var length = v.length;
655
656 if (result.length != length) {
657 throw new IllegalArgumentException();
658 }
659
660 final var halfLength = length / 2;
661 Complex tmp;
662 if (v != result) {
663
664 for (int i = 0, j = length - 1; i < halfLength; i++, j--) {
665 tmp = new Complex(v[i]);
666 result[i] = new Complex(v[j]);
667 result[j] = tmp;
668 }
669
670 if (length % 2 != 0) {
671
672 result[halfLength] = new Complex(v[halfLength]);
673 }
674 } else {
675
676 for (int i = 0, j = length - 1; i < halfLength; i++, j--) {
677 tmp = v[i];
678 result[i] = v[j];
679 result[j] = tmp;
680 }
681
682 if (length % 2 != 0) {
683
684 result[halfLength] = v[halfLength];
685 }
686 }
687 }
688
689
690
691
692
693
694
695 public static void reverse(final Complex[] v) {
696 reverse(v, v);
697 }
698
699
700
701
702
703
704
705
706 public static Complex[] reverseAndReturnNew(final Complex[] v) {
707 final var result = new Complex[v.length];
708 reverse(v, result);
709 return result;
710 }
711
712
713
714
715
716
717
718
719
720
721 public static void sqrt(final double[] v, final double[] result) {
722 final var length = v.length;
723
724 if (result.length != length) {
725 throw new IllegalArgumentException();
726 }
727
728 for (int i = 0; i < length; i++) {
729 result[i] = Math.sqrt(v[i]);
730 }
731 }
732
733
734
735
736
737
738
739
740
741 public static double[] sqrtAndReturnNew(final double[] v) {
742 final var result = new double[v.length];
743 sqrt(v, result);
744 return result;
745 }
746
747
748
749
750
751
752 public static void sqrt(final double[] v) {
753 sqrt(v, v);
754 }
755
756
757
758
759
760
761
762
763
764 public static double min(final double[] v, final int[] pos) {
765 final var length = v.length;
766 var min = Double.MAX_VALUE;
767 var foundPos = -1;
768 for (int i = 0; i < length; i++) {
769 if (v[i] < min) {
770 min = v[i];
771 foundPos = i;
772 }
773 }
774
775 if (pos != null && pos.length > 0) {
776 pos[0] = foundPos;
777 }
778
779 return min;
780 }
781
782
783
784
785
786
787
788 public static double min(final double[] v) {
789 return min(v, null);
790 }
791
792
793
794
795
796
797
798
799
800 public static double max(final double[] v, final int[] pos) {
801 final var length = v.length;
802 var max = -Double.MAX_VALUE;
803 var foundPos = -1;
804 for (int i = 0; i < length; i++) {
805 if (v[i] > max) {
806 max = v[i];
807 foundPos = i;
808 }
809 }
810
811 if (pos != null && pos.length > 0) {
812 pos[0] = foundPos;
813 }
814
815 return max;
816 }
817
818
819
820
821
822
823
824 public static double max(final double[] v) {
825 return max(v, null);
826 }
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841 public static void minMax(final double[] v, final double[] result, final int[] pos) {
842 if (result.length != 2) {
843 throw new IllegalArgumentException("result must have length 2");
844 }
845 if (pos != null && pos.length != 2) {
846 throw new IllegalArgumentException("pos must have length 2");
847 }
848
849 final var length = v.length;
850 var min = Double.MAX_VALUE;
851 var max = -Double.MAX_VALUE;
852 var minPos = -1;
853 var maxPos = -1;
854 for (int i = 0; i < length; i++) {
855 if (v[i] < min) {
856 min = v[i];
857 minPos = i;
858 }
859 if (v[i] > max) {
860 max = v[i];
861 maxPos = i;
862 }
863 }
864
865 result[0] = min;
866 result[1] = max;
867 if (pos != null) {
868 pos[0] = minPos;
869 pos[1] = maxPos;
870 }
871 }
872 }