1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 package org.nuiton.util;
23
24 import org.apache.commons.lang3.ObjectUtils;
25 import org.apache.commons.lang3.StringUtils;
26 import org.apache.commons.logging.Log;
27 import org.apache.commons.logging.LogFactory;
28
29 import java.io.Serializable;
30 import java.util.*;
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52 public interface MatrixMap<E> extends Iterable<E> {
53
54
55
56
57 class Factory {
58 public static <T> MatrixMap<T> create(List... semantics) {
59 MatrixMap<T> result = new MatrixMapFixed<T>(semantics);
60 return result;
61 }
62
63 public static <T> MatrixMap<T> create(String name, List... semantics) {
64 MatrixMap<T> result = new MatrixMapFixed<T>(name, semantics);
65 return result;
66 }
67
68 public static <T> MatrixMap<T> create(String name, String[] dimNames, List... semantics) {
69 MatrixMap<T> result = new MatrixMapFixed<T>(name, dimNames, semantics);
70 return result;
71 }
72
73 public static <T> MatrixMap<T> create(MatrixMap<T> matrix) {
74 MatrixMap<T> result = new MatrixMapFixed<T>(matrix);
75 return result;
76 }
77
78 public static <T> MatrixMap<T> createElastic(List... semantics) {
79 MatrixMap<T> result = create(semantics);
80 result = createElastic(result);
81 return result;
82 }
83
84 public static <T> MatrixMap<T> createElastic(String name, List... semantics) {
85 MatrixMap<T> result = create(name, semantics);
86 result = createElastic(result);
87 return result;
88 }
89
90 public static <T> MatrixMap<T> createElastic(String name, String[] dimNames, List... semantics) {
91 MatrixMap<T> result = create(name, dimNames, semantics);
92 result = createElastic(result);
93 return result;
94 }
95
96 public static <T> MatrixMap<T> createElastic(MatrixMap<T> matrix) {
97 MatrixMap<T> result = new MatrixMapElastic<T>(matrix);
98 return result;
99 }
100 }
101
102 @Override
103 MatrixMapIterator<E> iterator();
104
105
106
107
108
109
110
111 MatrixMap<E> copy();
112
113 SemanticList[] getSemantics();
114
115 SemanticList getSemantic(int dim);
116
117 void setSemantic(int dim, List sem);
118
119 void setName(String name);
120
121 String getName();
122
123 String[] getDimensionNames();
124
125 void setDimensionNames(String[] names);
126
127 void setDimensionName(int dim, String name);
128
129 String getDimensionName(int dim);
130
131 int getDimCount();
132
133 int[] getDim();
134
135 int getDim(int d);
136
137
138
139
140
141
142
143
144 MatrixMap<E> map(MapFunction<E> f);
145
146
147
148
149
150
151
152
153 E getValueIndex(int... coordinates);
154
155
156
157
158
159
160
161
162 void setValueIndex(E value, int... coordinates);
163
164
165
166
167
168
169
170 E getValue(Object... coordinates);
171
172
173
174
175
176
177
178 void setValue(E value, Object... coordinates);
179
180
181
182
183
184
185
186
187 boolean equals(MatrixMap mat);
188
189
190
191
192
193
194
195
196 boolean equalsValues(MatrixMap<E> mat);
197
198
199
200
201
202
203 String toStringGeneric();
204
205
206
207
208
209
210
211
212 boolean isValidCoordinates(Object[] semantics);
213
214
215
216
217
218
219
220
221
222 MatrixMap paste(MatrixMap<E> mat);
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239 MatrixMap<E> getSubMatrix(int dim, Object start, int nb);
240
241
242
243
244
245
246
247
248
249
250 MatrixMap<E> getSubMatrix(int dim, Object... elem);
251
252
253
254
255
256
257
258
259
260
261 MatrixMap<E> getSubMatrix(Object[]... elems);
262
263
264
265
266
267
268
269
270
271 MatrixMap<E> reduce();
272
273
274
275
276
277
278
279
280
281 MatrixMap<E> reduceDims(int... dims);
282
283
284
285
286
287
288
289
290
291
292
293 MatrixMap<E> reduce(int minNbDim);
294
295
296
297
298
299
300
301
302
303 MatrixMap<E> extend(Object... sems);
304
305
306
307
308
309
310
311
312
313
314
315 class MatrixHelper {
316
317
318
319
320
321
322
323
324
325
326
327
328 public static String format(Object o, int length, String valueIfNull) {
329 if (o == null) {
330 o = valueIfNull;
331 }
332 int absLength = Math.abs(length);
333
334 String result = String.valueOf(o);
335 if (absLength > 3) {
336 result = StringUtils.abbreviate(result, absLength);
337 }
338 if (length < 0) {
339 result = StringUtils.leftPad(result, absLength);
340 } else if (length > 0) {
341 result = StringUtils.rightPad(result, absLength);
342 }
343
344 return result;
345 }
346
347
348
349
350
351
352
353
354
355
356
357 public static Object[] dimensionToSemantics(List[] semantics,
358 int[] coordinates) {
359 Object[] result = new Object[coordinates.length];
360 for (int i = 0; i < result.length; i++) {
361 result[i] = semantics[i].get(coordinates[i]);
362 }
363 return result;
364 }
365
366
367
368
369
370
371
372
373
374
375 public static int[] semanticsToDimension(List[] semantics,
376 Object[] coordinates) {
377 int[] result = new int[coordinates.length];
378 for (int i = 0; i < coordinates.length; i++) {
379 result[i] = indexOf(semantics, i, coordinates[i]);
380 }
381 return result;
382 }
383
384
385
386
387
388
389
390
391
392
393 public static int indexOf(List[] semantics, int dim, Object o)
394 throws NoSuchElementException {
395 int result = -1;
396 if ((0 <= dim) && (dim < semantics.length)) {
397 result = semantics[dim].indexOf(o);
398 }
399 if (result == -1) {
400 throw new NoSuchElementException(
401 "L'objet passé en argument n'a pas été retrouvé ou la dimension donnée ne convient pas:"
402 + o + " in " + semantics[dim]);
403 }
404 return result;
405 }
406
407
408
409
410
411
412
413
414 public static boolean sameDimension(int[] dim1, int[] dim2) {
415 return Arrays.equals(dim1, dim2);
416 }
417
418 }
419
420
421
422
423
424
425 interface MatrixMapIterator<E> extends Iterator<E> {
426 int[] getCoordinates();
427
428 E getValue();
429
430 void setValue(E value);
431
432 Object[] getSemanticsCoordinates();
433 }
434
435 class MatrixMapIteratorImpl<E> implements MatrixMapIterator<E> {
436
437 protected MatrixIterator<E> iterator = null;
438
439 protected List[] semantics = null;
440
441 protected int pos = 0;
442
443
444
445
446
447
448 public MatrixMapIteratorImpl(MatrixIterator<E> iterator, List[] semantics) {
449 this.iterator = iterator;
450 this.semantics = semantics;
451 pos = 0;
452 }
453
454 @Override
455 public boolean hasNext() {
456 return iterator.hasNext();
457 }
458
459 @Override
460 public E next() {
461 return iterator.next();
462 }
463
464 @Override
465 public void remove() {
466 iterator.remove();
467 }
468
469 public int[] getCoordinates() {
470 return iterator.getCoordinates();
471 }
472
473 public E getValue() {
474 return iterator.getValue();
475 }
476
477 public void setValue(E value) {
478 iterator.setValue(value);
479 }
480
481 public Object[] getSemanticsCoordinates() {
482 Object[] result = null;
483 if (semantics != null) {
484 int[] coordinates = getCoordinates();
485 result = MatrixHelper.dimensionToSemantics(semantics,
486 coordinates);
487 }
488 return result;
489 }
490
491 }
492
493
494
495
496
497
498
499
500
501 class SemanticList<T> extends AbstractList<T> implements RandomAccess {
502
503 protected ArrayList<T> datas = null;
504
505 protected Map<T, Integer> index = new HashMap<T, Integer>();
506
507 public SemanticList() {
508 this(new ArrayList<T>());
509 }
510
511 public SemanticList(Collection<T> c) {
512 datas = new ArrayList<T>(c);
513 }
514
515
516
517
518 @Override
519 public T get(int index) {
520 T result = datas.get(index);
521 return result;
522 }
523
524 @Override
525 public void add(int index, T element) {
526 datas.add(index, element);
527 this.index.clear();
528 }
529
530 @Override
531 public T set(int index, T element) {
532 T result = datas.set(index, element);
533 this.index.clear();
534 return result;
535 }
536
537 @Override
538 public T remove(int index) {
539 T result = super.remove(index);
540 this.index.clear();
541 return result;
542 }
543
544
545
546
547
548 @Override
549 public int size() {
550 int result = datas.size();
551 return result;
552 }
553
554
555
556
557 @Override
558 public int indexOf(Object o) {
559 Map<T, Integer> index = getIndex();
560 Integer result = index.get(o);
561 int resultIndex = -1;
562 if (result != null) {
563 resultIndex = result.intValue();
564 }
565 return resultIndex;
566 }
567
568 protected Map<T, Integer> getIndex() {
569 if (index.isEmpty()) {
570 for (int i = 0; i < datas.size(); i++) {
571 index.put(datas.get(i), Integer.valueOf(i));
572 }
573 }
574 return index;
575 }
576 }
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598 class MatrixMapElastic<E> implements MatrixMap<E> {
599
600 protected MatrixMap<E> internalMatrixMap;
601
602 public MatrixMapElastic() {
603 internalMatrixMap = Factory.create();
604 }
605
606 public MatrixMapElastic(MatrixMap<E> m) {
607 setInternalMatrixMap(m);
608 }
609
610 public MatrixMap<E> getInternalMatrixMap() {
611 return internalMatrixMap;
612 }
613
614 public void setInternalMatrixMap(MatrixMap<E> internalMatrixMap) {
615 this.internalMatrixMap = internalMatrixMap;
616 }
617
618 public MatrixMapIterator<E> iterator() {
619 return getInternalMatrixMap().iterator();
620 }
621
622 public MatrixMap<E> copy() {
623 return getInternalMatrixMap().copy();
624 }
625
626 public SemanticList[] getSemantics() {
627 return getInternalMatrixMap().getSemantics();
628 }
629
630 public SemanticList getSemantic(int dim) {
631 return getInternalMatrixMap().getSemantic(dim);
632 }
633
634 public void setSemantic(int dim, List sem) {
635 getInternalMatrixMap().setSemantic(dim, sem);
636 }
637
638 public void setName(String name) {
639 getInternalMatrixMap().setName(name);
640 }
641
642 public String getName() {
643 return getInternalMatrixMap().getName();
644 }
645
646 public String[] getDimensionNames() {
647 return getInternalMatrixMap().getDimensionNames();
648 }
649
650 public void setDimensionNames(String[] names) {
651 getInternalMatrixMap().setDimensionNames(names);
652 }
653
654 public void setDimensionName(int dim, String name) {
655 getInternalMatrixMap().setDimensionName(dim, name);
656 }
657
658 public String getDimensionName(int dim) {
659 return getInternalMatrixMap().getDimensionName(dim);
660 }
661
662 public int getDimCount() {
663 return getInternalMatrixMap().getDimCount();
664 }
665
666 public int[] getDim() {
667 return getInternalMatrixMap().getDim();
668 }
669
670 public int getDim(int d) {
671 return getInternalMatrixMap().getDim(d);
672 }
673
674 public MatrixMap<E> map(MapFunction<E> f) {
675 return getInternalMatrixMap().map(f);
676 }
677
678 public E getValueIndex(int... coordinates) {
679 return getInternalMatrixMap().getValueIndex(coordinates);
680 }
681
682 public void setValueIndex(E value, int... coordinates) {
683
684 getInternalMatrixMap().setValueIndex(value, coordinates);
685 }
686
687 public E getValue(Object... coordinates) {
688 return getInternalMatrixMap().getValue(coordinates);
689 }
690
691 public void setValue(E value, Object... coordinates) {
692
693
694
695 if (!isValidCoordinates(coordinates)) {
696 MatrixMap<E> newMatrixMap = getInternalMatrixMap().extend(coordinates);
697 setInternalMatrixMap(newMatrixMap);
698 }
699 getInternalMatrixMap().setValue(value, coordinates);
700 }
701
702 @Override
703 public boolean equals(Object obj) {
704 return getInternalMatrixMap().equals(obj);
705 }
706
707 public boolean equals(MatrixMap mat) {
708 return getInternalMatrixMap().equals(mat);
709 }
710
711 public boolean equalsValues(MatrixMap<E> mat) {
712 return getInternalMatrixMap().equalsValues(mat);
713 }
714
715 @Override
716 public String toString() {
717 return getInternalMatrixMap().toString();
718 }
719
720 public String toStringGeneric() {
721 return getInternalMatrixMap().toStringGeneric();
722 }
723
724 public boolean isValidCoordinates(Object[] semantics) {
725 return getInternalMatrixMap().isValidCoordinates(semantics);
726 }
727
728 public MatrixMap paste(MatrixMap<E> mat) {
729 return getInternalMatrixMap().paste(mat);
730 }
731
732 public MatrixMap<E> getSubMatrix(int dim, Object start, int nb) {
733 return getInternalMatrixMap().getSubMatrix(dim, start, nb);
734 }
735
736 public MatrixMap<E> getSubMatrix(int dim, Object... elem) {
737 return getInternalMatrixMap().getSubMatrix(dim, elem);
738 }
739
740 public MatrixMap<E> getSubMatrix(Object[]... elems) {
741 return getInternalMatrixMap().getSubMatrix(elems);
742 }
743
744 public MatrixMap<E> reduce() {
745 return getInternalMatrixMap().reduce();
746 }
747
748 public MatrixMap<E> reduceDims(int... dims) {
749 return getInternalMatrixMap().reduceDims(dims);
750 }
751
752 public MatrixMap<E> reduce(int minNbDim) {
753 return getInternalMatrixMap().reduce(minNbDim);
754 }
755
756 public MatrixMap<E> extend(Object... sems) {
757 return getInternalMatrixMap().extend(sems);
758 }
759
760 }
761
762
763
764
765
766
767
768 class MatrixMapFixed<E> extends AbstractMatrixMap<E> {
769
770
771
772 private static final Log log = LogFactory.getLog(MatrixMapFixed.class);
773
774 protected Matrix<E> matrix = null;
775
776 public MatrixMapFixed(List... semantics) {
777 super(semantics);
778 }
779
780 public MatrixMapFixed(String name, List... semantics) {
781 this(semantics);
782 setName(name);
783 }
784
785 public MatrixMapFixed(String name, String[] dimNames, List... semantics) {
786 this(name, semantics);
787 for (int i = 0; dimNames != null && i < dimNames.length; i++) {
788 setDimensionName(i, dimNames[i]);
789 }
790 }
791
792 public MatrixMapFixed(MatrixMap<E> matrix) {
793 this(matrix.getName(), matrix.getDimensionNames(), matrix.getSemantics());
794 this.pasteIndex(matrix);
795 }
796
797 protected Matrix<E> getMatrix() {
798 if (matrix == null) {
799 matrix = new Matrix<E>(getDim());
800 }
801 return matrix;
802 }
803
804 @Override
805 public MatrixMapIterator<E> iterator() {
806 return new MatrixMapIteratorImpl<E>(getMatrix().iterator(), getSemantics());
807 }
808
809 @Override
810 public MatrixMap<E> map(MapFunction<E> f) {
811 getMatrix().data.map(f);
812 return this;
813 }
814
815 @Override
816 public E getValueIndex(int... coordinates) {
817 if (coordinates.length == 0) {
818 throw new IllegalArgumentException("Coordinates must not be empty");
819 }
820 return getMatrix().getValue(coordinates);
821 }
822
823
824
825
826
827
828
829
830
831
832
833 @Override
834 public void setValueIndex(E value, int... coordinates) {
835 if (coordinates.length == 0) {
836 throw new IllegalArgumentException("Coordinates must not be empty");
837 }
838 getMatrix().setValue(coordinates, value);
839 }
840
841
842
843
844
845
846
847
848
849
850 public MatrixMap<E> paste(int[] origin, MatrixMap<E> mat) {
851 if (mat != null) {
852
853
854
855
856
857 boolean origin0 = true;
858 for (int i = 0; i < origin.length && origin0; i++) {
859 origin0 = origin0 && origin[i] == 0;
860 }
861 if (origin0
862 && mat instanceof MatrixMapFixed
863 && Arrays.equals(mat.getDim(), this.getDim())) {
864 getMatrix().data.paste(((MatrixMapFixed<E>) mat).getMatrix().data);
865 } else {
866 super.paste(origin, mat);
867 }
868 }
869 return this;
870 }
871
872 }
873
874
875
876
877
878
879
880 abstract class AbstractMatrixMap<E> implements MatrixMap<E> {
881
882
883
884
885 private static final Log log = LogFactory.getLog(AbstractMatrixMap.class);
886
887 protected String name = null;
888
889 protected String[] dimNames = null;
890
891 protected int[] dim = null;
892
893 protected SemanticList[] semantics = null;
894
895 protected void init(int[] dim) {
896 this.dim = new int[dim.length];
897 System.arraycopy(dim, 0, this.dim, 0, dim.length);
898 semantics = new SemanticList[dim.length];
899 dimNames = new String[dim.length];
900 }
901
902 protected AbstractMatrixMap(int[] dim) {
903 init(dim);
904 for (int i = 0; i < getDimCount(); i++) {
905
906
907 setSemantic(i, Collections.nCopies(dim[i], null));
908 }
909 }
910
911 public AbstractMatrixMap(List... semantics) {
912 int[] dim = new int[semantics.length];
913 for (int i = 0; i < dim.length; i++) {
914 if (semantics[i] == null) {
915 dim[i] = 0;
916 } else {
917 dim[i] = semantics[i].size();
918 }
919 }
920 init(dim);
921 for (int i = 0; i < getDimCount(); i++) {
922 setSemantic(i, semantics[i]);
923 }
924 }
925
926 protected AbstractMatrixMap(String name, int[] dim) {
927 this(dim);
928 setName(name);
929 }
930
931 protected AbstractMatrixMap(String name, int[] dim, String[] dimNames) {
932 this(dim);
933 setName(name);
934 for (int i = 0; dimNames != null && i < dimNames.length; i++) {
935 setDimensionName(i, dimNames[i]);
936 }
937 }
938
939 public AbstractMatrixMap(String name, List... semantics) {
940 this(semantics);
941 setName(name);
942 }
943
944 public AbstractMatrixMap(String name, String[] dimNames, List... semantics) {
945 this(name, semantics);
946 for (int i = 0; dimNames != null && i < dimNames.length; i++) {
947 setDimensionName(i, dimNames[i]);
948 }
949 }
950
951 public AbstractMatrixMap(MatrixMap<E> matrix) {
952 this(matrix.getName(), matrix.getDimensionNames(), matrix.getSemantics());
953 this.pasteIndex(matrix);
954 }
955
956
957
958
959
960
961
962 public MatrixMap<E> copy() {
963 MatrixMap<E> result = new MatrixMapFixed<E>(this);
964 return result;
965 }
966
967 @Override
968 public MatrixMap clone() {
969 return copy();
970 }
971
972 public SemanticList[] getSemantics() {
973 return semantics;
974 }
975
976 public SemanticList getSemantic(int dim) {
977 return semantics[dim];
978 }
979
980 public void setSemantic(int dim, List sem) {
981
982 SemanticList l = new SemanticList(sem);
983 semantics[dim] = l;
984 }
985
986 public void setName(String name) {
987 this.name = name;
988 }
989
990 public String getName() {
991 return name;
992 }
993
994 public String[] getDimensionNames() {
995 return dimNames;
996 }
997
998 public void setDimensionNames(String[] names) {
999 for (int i = 0; names != null && i < names.length; i++) {
1000 setDimensionName(i, names[i]);
1001 }
1002 }
1003
1004 public void setDimensionName(int dim, String name) {
1005 dimNames[dim] = name;
1006 }
1007
1008 public String getDimensionName(int dim) {
1009 return dimNames[dim];
1010 }
1011
1012 public int getDimCount() {
1013 return dim.length;
1014 }
1015
1016 public int[] getDim() {
1017 return dim;
1018 }
1019
1020 public int getDim(int d) {
1021 return dim[d];
1022 }
1023
1024
1025
1026
1027
1028 @Override
1029 public MatrixMap<E> map(MapFunction<E> f) {
1030 for (MatrixMapIterator<E> i = iterator(); i.hasNext(); ) {
1031 i.setValue(f.apply(i.next()));
1032 }
1033 return this;
1034 }
1035
1036 public E getValue(Object... coordinates) {
1037 if (coordinates.length == 0) {
1038 throw new IllegalArgumentException("Coordinates must not be empty");
1039 }
1040 int[] intCoordinates =
1041 MatrixHelper.semanticsToDimension(getSemantics(), coordinates);
1042 E result = getValueIndex(intCoordinates);
1043 return result;
1044 }
1045
1046 public void setValue(E value, Object... coordinates) {
1047 if (coordinates.length == 0) {
1048 throw new IllegalArgumentException("Coordinates must not be empty");
1049 }
1050 int[] intCoordinates =
1051 MatrixHelper.semanticsToDimension(getSemantics(), coordinates);
1052 setValueIndex(value, intCoordinates);
1053 }
1054
1055
1056
1057 @Override
1058 public boolean equals(Object o) {
1059 return o instanceof MatrixMap && equals((MatrixMap) o);
1060 }
1061
1062 public boolean equals(MatrixMap mat) {
1063 boolean result = true;
1064
1065 result = result && getName().equals(mat.getName());
1066
1067 result = result && equalsValues(mat);
1068
1069
1070 for (int i = 0; result && i < getDimCount(); i++) {
1071 String dimName1 = getDimensionName(i);
1072 String dimName2 = mat.getDimensionName(i);
1073 result = Objects.equals(dimName1, dimName2);
1074 if (log.isTraceEnabled()) {
1075 log.trace("dimName1(" + dimName1 + ")==dimName2(" + dimName2
1076 + ")=" + result);
1077 }
1078
1079
1080
1081 List sem1 = getSemantic(i);
1082 List sem2 = mat.getSemantic(i);
1083 result = result && Objects.equals(sem1, sem2);
1084 if (log.isTraceEnabled()) {
1085 log.trace("sem1(" + sem1 + ")==sem2(" + sem2 + ")=" + result);
1086 }
1087
1088 }
1089
1090 if (log.isTraceEnabled()) {
1091 log.trace("result=" + result);
1092 }
1093
1094 return result;
1095 }
1096
1097
1098
1099
1100
1101
1102
1103
1104 public boolean equalsValues(MatrixMap mat) {
1105 boolean result = true;
1106
1107 result = result && MatrixHelper.sameDimension(getDim(), mat.getDim());
1108
1109
1110 for (MatrixMapIterator<E> i = mat.iterator(); result && i.hasNext(); ) {
1111 E v1 = i.next();
1112 E v2 = getValueIndex(i.getCoordinates());
1113 result = v1 == v2;
1114 if (log.isTraceEnabled()) {
1115 log.trace("v1(" + v1 + ")==v2(" + v2 + ")=" + result);
1116 }
1117 }
1118
1119 return result;
1120 }
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147 @Override
1148 public String toString() {
1149 int LENGTH = 10;
1150 StringBuilder result = new StringBuilder();
1151 if (getDimCount() == 1) {
1152 result.append(MatrixHelper.format(getName(), -LENGTH, "#NoNameMat"));
1153 result.append("(matrix1D)[\n");
1154 String dimName = getDimensionName(0);
1155 result.append(MatrixHelper.format(dimName, LENGTH, "#NoNameDim"));
1156 for (Object sem : getSemantic(0)) {
1157 result.append(",");
1158 result.append(MatrixHelper.format(sem, -LENGTH, null));
1159 }
1160 result.append(StringUtils.repeat(" ", LENGTH + 1));
1161 for (int i = 0; i < getDim(0); i++) {
1162 Object v = getValueIndex(i);
1163 result.append(MatrixHelper.format(v, -LENGTH, null) + ",");
1164 }
1165 result.append("\n]");
1166 } else if (getDimCount() == 2) {
1167 int[] pos = new int[2];
1168 result.append(MatrixHelper.format(getName(), -LENGTH, "#NoNameMat"));
1169 result.append("(matrix2D) [\n");
1170
1171 result.append(StringUtils.repeat(" ", LENGTH + 1));
1172 String dimNameX = getDimensionName(0);
1173 result.append(MatrixHelper.format(dimNameX, LENGTH, "#DimX"));
1174 result.append("\n");
1175 String dimNameY = getDimensionName(1);
1176 result.append(MatrixHelper.format(dimNameY, LENGTH, "#DimY"));
1177 result.append(" ");
1178 for (Object sem : getSemantic(0)) {
1179 result.append(MatrixHelper.format(sem, -LENGTH, null));
1180 result.append(",");
1181 }
1182
1183 for (int y = 0; y < getDim(1); y++) {
1184 result.append("\n");
1185 Object sem = getSemantic(1).get(y);
1186 result.append(MatrixHelper.format(sem, LENGTH, null));
1187 result.append(" ");
1188 for (int x = 0; x < getDim(0); x++) {
1189 pos[0] = x;
1190 pos[1] = y;
1191 Object v = getValueIndex(pos);
1192 result.append(MatrixHelper.format(v, -LENGTH, null) + ",");
1193 }
1194 }
1195 result.append("\n]");
1196 } else {
1197 result.append(toStringGeneric());
1198 }
1199 return result.toString();
1200 }
1201
1202
1203
1204
1205
1206
1207 public String toStringGeneric() {
1208 StringBuilder result = new StringBuilder();
1209 result.append(MatrixHelper.format(getName(), 0, "#NoNameMat"));
1210 result.append("(matrix" + getDimCount() + "D)[\n");
1211 result.append("dimensions = [");
1212 for (int i = 0; i < getDim().length; i++) {
1213 result.append(getDim()[i] + ",");
1214 }
1215 result.append("]\ndata = [");
1216 for (MatrixMapIterator i = this.iterator(); i.hasNext(); ) {
1217 result.append(i.next() + ",");
1218 }
1219 result.append("]\n");
1220 return result.toString();
1221 }
1222
1223 public boolean isValidCoordinates(int[] dim) {
1224 boolean result = getDimCount() == dim.length;
1225 for (int i = 0; result && i < dim.length; i++) {
1226 result = 0 <= dim[i] && dim[i] < getDim(i);
1227 }
1228 return result;
1229 }
1230
1231 public boolean isValidCoordinates(Object[] semantics) {
1232 boolean result = getDimCount() == semantics.length;
1233 for (int i = 0; result && i < semantics.length; i++) {
1234 List semantic = getSemantic(i);
1235 result = semantic.contains(semantics[i]);
1236 }
1237 return result;
1238 }
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248 public MatrixMap pasteIndex(MatrixMap<E> mat) {
1249 return paste(new int[getDimCount()], mat);
1250 }
1251
1252 protected MatrixMap<E> paste(int[] origin, MatrixMap<E> mat) {
1253 if (mat != null) {
1254 for (MatrixMapIterator<E> mi = mat.iterator(); mi.hasNext(); ) {
1255 E value = mi.next();
1256 int[] coordinates = ArrayUtil.sum(origin, mi.getCoordinates());
1257 if (isValidCoordinates(coordinates)) {
1258 setValueIndex(value, coordinates);
1259 }
1260 }
1261 }
1262 return this;
1263 }
1264
1265
1266
1267
1268
1269
1270 public MatrixMap<E> paste(MatrixMap<E> mat) {
1271 if (mat != null) {
1272 for (MatrixMapIterator<E> mi = mat.iterator(); mi.hasNext(); ) {
1273 E value = mi.next();
1274 Object[] sems = mi.getSemanticsCoordinates();
1275 if (isValidCoordinates(sems)) {
1276 setValue(value, sems);
1277 }
1278 }
1279 }
1280 return this;
1281 }
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299 public MatrixMap<E> getSubMatrix(int dim, int start, int nb) {
1300 if (dim < 0) {
1301 dim = getDimCount() + dim;
1302 }
1303 if (start < 0) {
1304 start = getDim(dim) + start;
1305 }
1306 if (nb <= 0) {
1307 nb = getDim(dim) - start;
1308 }
1309 return new SubMatrix<E>(this, dim, start, nb);
1310 }
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327 public MatrixMap<E> getSubMatrix(int dim, Object start, int nb) {
1328 int begin = MatrixHelper.indexOf(getSemantics(), dim, start);
1329 return getSubMatrix(dim, begin, nb);
1330 }
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340 public MatrixMap<E> getSubMatrixOnSemantic(int dim, Object... elem) {
1341 MatrixMap<E> result = getSubMatrix(dim, elem);
1342 return result;
1343 }
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354 public MatrixMap<E> getSubMatrix(int dim, Object... elem) {
1355 int[] ielem = new int[elem.length];
1356 for (int i = 0; i < ielem.length; i++) {
1357 ielem[i] = MatrixHelper.indexOf(getSemantics(), dim, elem[i]);
1358 }
1359 return getSubMatrix(dim, ielem);
1360 }
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371 public MatrixMap<E> getSubMatrix(Object[]... elems) {
1372
1373
1374 if (elems.length != dim.length) {
1375 throw new IllegalArgumentException(String.format(
1376 "Can't get sub matrix with different dimension count "
1377 + "(expected: %d, got %d)", dim.length, elems.length));
1378 }
1379
1380 MatrixMap<E> result = this;
1381 for (int i = 0; i < elems.length; ++i) {
1382 if (elems[i] != null) {
1383 result = result.getSubMatrix(i, elems[i]);
1384 }
1385 }
1386 return result;
1387 }
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398 public MatrixMap<E> getSubMatrix(int dim, int[] elem) {
1399 return new SubMatrix<E>(this, dim, elem);
1400 }
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411 public MatrixMap<E> getSubMatrix(int[]... elems) {
1412
1413
1414 if (elems.length != dim.length) {
1415 throw new IllegalArgumentException(String.format(
1416 "Can't get sub matrix with different dimension count "
1417 + "(expected: %d, got %d)", dim.length, elems.length));
1418 }
1419
1420 MatrixMap<E> result = this;
1421 for (int i = 0; i < elems.length; ++i) {
1422 if (elems[i] != null) {
1423 result = new SubMatrix<E>(result, i, elems[i]);
1424 }
1425 }
1426 return result;
1427 }
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437 public MatrixMap<E> reduce() {
1438 return reduce(1);
1439 }
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449 public MatrixMap<E> reduceDims(int... dims) {
1450 Arrays.sort(dims);
1451
1452
1453
1454
1455
1456 int[] correspondance = new int[getDimCount()];
1457
1458 List<List> sem = new ArrayList<List>();
1459
1460 List<String> dimName = new ArrayList<String>();
1461
1462 int minNbDim = 1;
1463 for (int j = getDimCount() - 1; j >= 0; j--) {
1464
1465
1466 if (getDim(j) > 1 || Arrays.binarySearch(dims, j) < 0
1467 || j < minNbDim) {
1468
1469 correspondance[sem.size()] = j;
1470 sem.add(getSemantic(j));
1471 dimName.add(getDimensionName(j));
1472 minNbDim--;
1473 }
1474 }
1475 MatrixMap<E> result = reduce(dimName, sem, correspondance);
1476 return result;
1477 }
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489 public MatrixMap<E> reduce(int minNbDim) {
1490
1491
1492
1493
1494
1495 int[] correspondance = new int[getDimCount()];
1496
1497 List<List> sem = new ArrayList<List>();
1498
1499 List<String> dimName = new ArrayList<String>();
1500 for (int j = getDimCount() - 1; j >= 0; j--) {
1501
1502
1503 if (getDim(j) > 1 || j < minNbDim) {
1504
1505 correspondance[sem.size()] = j;
1506 sem.add(getSemantic(j));
1507 dimName.add(getDimensionName(j));
1508
1509
1510 minNbDim--;
1511 }
1512 }
1513
1514 MatrixMap<E> result = reduce(dimName, sem, correspondance);
1515 return result;
1516 }
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527 protected MatrixMap<E> reduce(List<String> dimName, List<List> sem, int[] correspondance) {
1528
1529
1530 int nbDim = sem.size();
1531 List[] newSemantics = new List[nbDim];
1532 String[] newDimNames = new String[nbDim];
1533 int[] tmpcorrespondance = new int[nbDim];
1534 for (int i = 0; i < nbDim; i++) {
1535 newSemantics[i] = sem.get(nbDim - 1 - i);
1536 newDimNames[i] = dimName.get(nbDim - 1 - i);
1537 tmpcorrespondance[i] = correspondance[nbDim - 1 - i];
1538 }
1539 correspondance = tmpcorrespondance;
1540
1541 MatrixMap<E> result = new MatrixMapFixed<E>(getName(), newDimNames, newSemantics);
1542
1543
1544 int[] newCoordinates = new int[result.getDimCount()];
1545 for (MatrixMapIterator<E> mi = iterator(); mi.hasNext(); ) {
1546 E value = mi.next();
1547 int[] oldCoordinates = mi.getCoordinates();
1548 for (int i = 0; i < newCoordinates.length; i++) {
1549 newCoordinates[i] = oldCoordinates[correspondance[i]];
1550 }
1551 result.setValueIndex(value, newCoordinates);
1552 }
1553 return result;
1554 }
1555
1556 public MatrixMap<E> extend(Object... sems) {
1557 String name = getName();
1558 String[] dimNames = getDimensionNames();
1559 SemanticList[] semantics = getSemantics();
1560
1561
1562 if (sems.length > semantics.length) {
1563 String[] newDimNames = new String[sems.length];
1564 System.arraycopy(dimNames, 0, newDimNames, 0, dimNames.length);
1565 dimNames = newDimNames;
1566
1567 SemanticList[] newSems = new SemanticList[sems.length];
1568 System.arraycopy(semantics, 0, newSems, 0, semantics.length);
1569 semantics = newSems;
1570
1571 for (int i = semantics.length; i < newSems.length; i++) {
1572 newSems[i] = new SemanticList();
1573 }
1574 }
1575
1576
1577 for (int i = 0; i < sems.length; i++) {
1578 if (semantics[i].indexOf(sems[i]) == -1) {
1579 semantics[i].add(sems[i]);
1580 }
1581 }
1582
1583 MatrixMap<E> result = MatrixMap.Factory.create(name, dimNames, semantics);
1584 result.paste(this);
1585 return result;
1586 }
1587
1588 }
1589
1590
1591
1592
1593
1594
1595
1596
1597 class SubMatrix<E> extends AbstractMatrixMap<E> {
1598
1599 protected MatrixMap<E> matrix = null;
1600
1601 protected DimensionConverter converter = null;
1602
1603 public SubMatrix(MatrixMap<E> matrix, int dim, int start, int nb) {
1604 super(matrix.getName(), matrix.getDimensionNames(), matrix.getSemantics());
1605 this.matrix = matrix;
1606
1607 converter = new ShiftConverter(dim, start, nb);
1608 setSemantic(dim, getSemantic(dim).subList(start, start + nb));
1609 getDim()[dim] = nb;
1610 }
1611
1612 public SubMatrix(MatrixMap<E> matrix, int dim, int[] elem) {
1613 super(matrix.getName(), matrix.getDimensionNames(), matrix.getSemantics());
1614 this.matrix = matrix;
1615
1616 converter = new MappingConverter(dim, elem);
1617
1618 List oldSemantic = getSemantic(dim);
1619 List newSemantic = new LinkedList();
1620 for (int i = 0; i < elem.length; i++) {
1621 newSemantic.add(oldSemantic.get(elem[i]));
1622 }
1623 setSemantic(dim, newSemantic);
1624 getDim()[dim] = elem.length;
1625 }
1626
1627 @Override
1628 public MatrixMapIterator<E> iterator() {
1629 return new SubMatrixIterator<E>(this);
1630 }
1631
1632 @Override
1633 public E getValueIndex(int... coordinates) {
1634 return matrix.getValueIndex(converter.convertCoordinates(coordinates));
1635 }
1636
1637 @Override
1638 public void setValueIndex(E value, int... coordinates) {
1639 matrix.setValueIndex(value, converter.convertCoordinates(coordinates));
1640 }
1641
1642 protected class SubMatrixIterator<E> implements MatrixMapIterator<E> {
1643
1644 protected SubMatrix<E> subMatrix = null;
1645
1646 protected int[] cpt = null;
1647
1648 protected int[] last = null;
1649
1650 public SubMatrixIterator(SubMatrix<E> subMatrix) {
1651 this.subMatrix = subMatrix;
1652 cpt = new int[subMatrix.getDimCount()];
1653 cpt[cpt.length - 1] = -1;
1654
1655 last = new int[subMatrix.getDimCount()];
1656 for (int i = 0; i < last.length; i++) {
1657 last[i] = subMatrix.getDim(i) - 1;
1658 }
1659
1660 }
1661
1662 @Override
1663 public boolean hasNext() {
1664 return !Arrays.equals(cpt, last);
1665 }
1666
1667 @Override
1668 public E next() {
1669 int ret = 1;
1670 int[] dim = getDim();
1671 for (int i = cpt.length - 1; i >= 0; i--) {
1672 cpt[i] = cpt[i] + ret;
1673 ret = cpt[i] / dim[i];
1674 cpt[i] = cpt[i] % dim[i];
1675 }
1676 E result = getValue();
1677 return result;
1678 }
1679
1680 @Override
1681 public void remove() {
1682 setValue(null);
1683 }
1684
1685 public int[] getCoordinates() {
1686 return cpt;
1687 }
1688
1689 public Object[] getSemanticsCoordinates() {
1690 int[] coordinates = getCoordinates();
1691 Object[] result = MatrixHelper.dimensionToSemantics(subMatrix.getSemantics(), coordinates);
1692 return result;
1693 }
1694
1695 public E getValue() {
1696 return subMatrix.getValueIndex(getCoordinates());
1697 }
1698
1699 public void setValue(E value) {
1700 subMatrix.setValue(value, getCoordinates());
1701 }
1702 }
1703
1704
1705
1706
1707
1708 protected interface DimensionConverter extends Serializable {
1709 int[] convertCoordinates(int[] coordinates);
1710 }
1711
1712
1713
1714
1715 protected static class ShiftConverter implements DimensionConverter {
1716
1717
1718
1719
1720 private static final long serialVersionUID = 1L;
1721
1722 protected int dim;
1723
1724 protected int start;
1725
1726 protected int nb;
1727
1728 public ShiftConverter(int dim, int start, int nb) {
1729 this.dim = dim;
1730 this.start = start;
1731 this.nb = nb;
1732 }
1733
1734 @Override
1735 public int[] convertCoordinates(int[] coordinates) {
1736 int[] result = null;
1737 if (coordinates[dim] < nb) {
1738 result = new int[coordinates.length];
1739 System.arraycopy(coordinates, 0, result, 0, result.length);
1740 result[dim] = result[dim] + start;
1741 } else {
1742 throw new NoSuchElementException(
1743 "L'indice est supérieur au nombre d'élement de la sous matrice pour cette dimension.");
1744 }
1745 return result;
1746 }
1747 }
1748
1749
1750
1751
1752 protected static class MappingConverter implements DimensionConverter {
1753
1754
1755
1756
1757 private static final long serialVersionUID = -6367416559713556559L;
1758
1759 protected int dim;
1760
1761 protected int[] elem = null;
1762
1763 public MappingConverter(int dim, int[] elem) {
1764 this.dim = dim;
1765 this.elem = new int[elem.length];
1766 System.arraycopy(elem, 0, this.elem, 0, elem.length);
1767 }
1768
1769 @Override
1770 public int[] convertCoordinates(int[] coordinates) {
1771 int[] result = null;
1772 if (coordinates[dim] < elem.length) {
1773 result = new int[coordinates.length];
1774 System.arraycopy(coordinates, 0, result, 0, result.length);
1775 result[dim] = elem[coordinates[dim]];
1776
1777 } else {
1778 throw new NoSuchElementException(
1779 "L'indice est supérieur au nombre d'élements de la sous matrice pour cette dimension.");
1780 }
1781 return result;
1782 }
1783 }
1784 }
1785
1786
1787
1788
1789
1790
1791
1792 class Matrix<E> implements Iterable<E> {
1793
1794
1795
1796
1797 protected int[] dimensions = null;
1798
1799
1800
1801
1802 protected Vector<E> data = null;
1803
1804
1805
1806
1807
1808 protected int[] linearFactor = null;
1809
1810
1811
1812
1813
1814
1815 public Matrix(int[] dimensions) {
1816 checkDim(dimensions);
1817
1818
1819
1820 this.dimensions = new int[dimensions.length];
1821 System.arraycopy(dimensions, 0, this.dimensions, 0, dimensions.length);
1822
1823
1824 linearFactor = new int[dimensions.length];
1825 linearFactor[linearFactor.length - 1] = 1;
1826 for (int i = linearFactor.length - 2; i >= 0; i--) {
1827 linearFactor[i] = linearFactor[i + 1] * dimensions[i + 1];
1828 }
1829
1830
1831 data = new Vector<E>(linearFactor[0] * dimensions[0]);
1832 }
1833
1834
1835
1836
1837
1838
1839 public int getNbDim() {
1840 return dimensions.length;
1841 }
1842
1843
1844
1845
1846
1847
1848
1849 public int getDim(int dim) {
1850 checkDim(dim);
1851 return dimensions[dim];
1852 }
1853
1854
1855
1856
1857
1858
1859
1860 public int[] getDim() {
1861 return dimensions;
1862 }
1863
1864
1865
1866
1867
1868
1869
1870 public E getValue(int[] pos) {
1871 int indice = coordonatesToLinear(pos);
1872 return data.getValue(indice);
1873 }
1874
1875
1876
1877
1878
1879
1880
1881 public void setValue(int[] pos, E value) {
1882 int indice = coordonatesToLinear(pos);
1883 data.setValue(indice, value);
1884 }
1885
1886
1887
1888
1889
1890
1891
1892 @Override
1893 public MatrixIterator<E> iterator() {
1894 return new MatrixIterator<E>(this);
1895 }
1896
1897
1898
1899
1900
1901
1902 public void map(MapFunction f) {
1903 data.map(f);
1904 }
1905
1906
1907
1908
1909
1910
1911
1912
1913 protected int coordonatesToLinear(int[] coordonates) {
1914 checkPos(coordonates);
1915
1916 int result = 0;
1917 for (int i = 0; i < linearFactor.length; i++) {
1918 result += coordonates[i] * linearFactor[i];
1919 }
1920 return result;
1921 }
1922
1923
1924
1925
1926
1927
1928
1929 protected int[] linearToCoordinates(int pos) {
1930 int[] result = new int[linearFactor.length];
1931
1932 for (int i = 0; i < result.length; i++) {
1933 result[i] = pos / linearFactor[i];
1934 pos -= result[i] * linearFactor[i];
1935 }
1936 return result;
1937 }
1938
1939
1940
1941
1942
1943
1944
1945
1946 protected void checkDim(int[] dim) {
1947 for (int i = 0; i < dim.length; i++) {
1948 if (dim[i] <= 0) {
1949 throw new IllegalArgumentException(String.format(
1950 "Dimension %s is invalid %s", i, dim[i]));
1951 }
1952 }
1953 }
1954
1955
1956
1957
1958
1959
1960
1961 protected void checkDim(int dim) {
1962 if (dim < 0 || dim >= getNbDim()) {
1963 throw new IndexOutOfBoundsException(String.format(
1964 "Invalid dimension %s max dimension is %s",
1965 dim, getNbDim()));
1966 }
1967 }
1968
1969
1970
1971
1972
1973
1974
1975
1976 protected void checkPos(int[] pos) {
1977 int[] dim = getDim();
1978 boolean result = dim.length == pos.length;
1979 for (int i = 0; result && i < dim.length; i++) {
1980 result = (0 <= pos[i]) && (pos[i] < dim[i]);
1981 }
1982 if (!result) {
1983 throw new NoSuchElementException(String.format(
1984 "Invalid element asked %s for real dimension %s", Arrays.toString(pos), Arrays
1985 .toString(dim)));
1986 }
1987 }
1988
1989 @Override
1990 public String toString() {
1991 StringBuffer result = new StringBuffer();
1992 if (getNbDim() == 1) {
1993 result.append("matrix1D [");
1994 for (int i = 0; i < data.size(); i++) {
1995 result.append(data.getValue(i) + ",");
1996 }
1997 result.append("]");
1998 } else if (getNbDim() == 2) {
1999 int[] pos = new int[2];
2000 result.append("matrix2D [");
2001 for (int y = 0; y < getDim(1); y++) {
2002 result.append("\n");
2003 for (int x = 0; x < getDim(0); x++) {
2004 pos[0] = x;
2005 pos[1] = y;
2006 result.append(getValue(pos) + ",");
2007 }
2008 }
2009 result.append("]");
2010 } else {
2011 result.append("dimensions = [\n");
2012 for (int i = 0; i < dimensions.length; i++) {
2013 result.append(dimensions[i] + ",");
2014 }
2015 result.append("\n]\nmatrice = [\n");
2016 for (int i = 0; i < data.size(); i++) {
2017 result.append(data.getValue(i) + ",");
2018 }
2019 result.append("\n]\nlinearFactor = [\n");
2020 for (int i = 0; i < linearFactor.length; i++) {
2021 result.append(linearFactor[i] + ",");
2022 }
2023 result.append("\n]\n");
2024 }
2025 return result.toString();
2026 }
2027
2028 @Override
2029 public boolean equals(Object o) {
2030 if (o instanceof Matrix) {
2031 Matrix other = (Matrix) o;
2032 return this == o
2033 || (Arrays.equals(this.dimensions, other.dimensions) && this.data
2034 .equals(other.data));
2035 }
2036 return false;
2037 }
2038
2039 }
2040
2041 class MatrixIterator<E> implements Iterator<E> {
2042
2043 protected Matrix<E> matrix = null;
2044
2045 protected int pos = -1;
2046
2047
2048
2049
2050 public MatrixIterator(Matrix<E> matrix) {
2051 this.matrix = matrix;
2052 pos = -1;
2053 }
2054
2055 @Override
2056 public boolean hasNext() {
2057 return pos + 1 < matrix.data.size();
2058 }
2059
2060 @Override
2061 public E next() {
2062 if (hasNext()) {
2063 pos++;
2064 } else {
2065 throw new NoSuchElementException();
2066 }
2067 E result = getValue();
2068 return result;
2069 }
2070
2071 @Override
2072 public void remove() {
2073 setValue(null);
2074 }
2075
2076 public E getValue() {
2077 return matrix.data.getValue(pos);
2078 }
2079
2080 public void setValue(E value) {
2081 matrix.data.setValue(pos, value);
2082 }
2083
2084 public int[] getCoordinates() {
2085 return matrix.linearToCoordinates(pos);
2086 }
2087
2088 }
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098 class Vector<E> {
2099
2100
2101
2102
2103 protected int capacity = 0;
2104
2105
2106
2107
2108 protected E defaultValue = null;
2109
2110
2111
2112
2113 protected int[] position;
2114
2115 protected int positionSize = 0;
2116
2117
2118
2119
2120 protected ArrayList<E> data = new ArrayList<E>();
2121
2122 public Vector(int capacity) {
2123 this.capacity = capacity;
2124 position = new int[8];
2125 Arrays.fill(position, Integer.MAX_VALUE);
2126 }
2127
2128 public Vector(int capacity, E defaultValue) {
2129 this(capacity);
2130 this.defaultValue = defaultValue;
2131 }
2132
2133 public int size() {
2134 return capacity;
2135 }
2136
2137
2138
2139 public E getMaxOccurrence() {
2140 E result = defaultValue;
2141
2142 E[] tmp = (E[]) data.toArray();
2143
2144
2145
2146 if (this.capacity < 2 * tmp.length) {
2147 Arrays.sort(tmp);
2148
2149
2150
2151 int max = 1;
2152
2153 int count = 1;
2154
2155 result = tmp[0];
2156
2157 E old = tmp[0];
2158
2159 E current = tmp[0];
2160
2161
2162 for (int i = 1; max < tmp.length - i + count && i < tmp.length; i++) {
2163 current = tmp[i];
2164
2165 if (current == old) {
2166 count++;
2167 } else {
2168 if (count > max) {
2169 max = count;
2170 result = old;
2171 }
2172 count = 1;
2173 old = current;
2174 }
2175 }
2176 if (count > max) {
2177 max = count;
2178 result = current;
2179 }
2180
2181 if (max <= capacity - tmp.length) {
2182
2183
2184 result = defaultValue;
2185 }
2186 }
2187
2188 return result;
2189 }
2190
2191 protected void checkPos(int pos) {
2192 if (pos < 0 || pos >= capacity) {
2193 throw new IllegalArgumentException("pos " + pos + " is not in [0, "
2194 + capacity + "]");
2195 }
2196 }
2197
2198 public E getValue(int pos) {
2199 checkPos(pos);
2200
2201 E result = defaultValue;
2202 int index = findIndex(pos);
2203 if (index >= 0) {
2204 result = data.get(index);
2205 }
2206 return result;
2207 }
2208
2209 public void setValue(int pos, E value) {
2210 checkPos(pos);
2211
2212 int index = findIndex(pos);
2213 if (index >= 0) {
2214 if (value == defaultValue) {
2215
2216 removeElementAt(index);
2217 data.remove(index);
2218 } else {
2219
2220 data.set(index, value);
2221 }
2222 } else {
2223
2224 if (value != defaultValue) {
2225
2226 index = -index - 1;
2227
2228 addElementAt(index, pos);
2229 data.add(index, value);
2230 }
2231 }
2232 }
2233
2234 public boolean equals(Object o) {
2235 boolean result = false;
2236 if (o instanceof Vector) {
2237 Vector other = (Vector) o;
2238 result = Arrays.equals(this.position, other.position)
2239 && data.equals(other.data);
2240 }
2241 return result;
2242 }
2243
2244
2245
2246
2247
2248
2249
2250
2251 protected int findIndex(int pos) {
2252 return Arrays.binarySearch(position, pos);
2253 }
2254
2255 protected void ensureCapacity(int mincap) {
2256 if (mincap > position.length) {
2257 int newcap = (position.length * 3) / 2 + 1;
2258 int olddata[] = position;
2259 position = new int[newcap >= mincap ? newcap : mincap];
2260 System.arraycopy(olddata, 0, position, 0, positionSize);
2261 for (int i = positionSize; i < position.length; i++) {
2262 position[i] = Integer.MAX_VALUE;
2263 }
2264 }
2265 }
2266
2267 protected void addElementAt(int index, int element) {
2268 ensureCapacity(positionSize + 1);
2269 int numtomove = positionSize - index;
2270 System.arraycopy(position, index, position, index + 1, numtomove);
2271 position[index] = element;
2272 positionSize++;
2273 }
2274
2275 protected int removeElementAt(int index) {
2276 int oldval = position[index];
2277 int numtomove = positionSize - index - 1;
2278 if (numtomove > 0) {
2279 System.arraycopy(position, index + 1, position, index, numtomove);
2280 }
2281 positionSize--;
2282 position[positionSize] = Integer.MAX_VALUE;
2283 return oldval;
2284 }
2285
2286
2287
2288
2289
2290
2291 public void paste(Vector<E> v) {
2292 this.capacity = v.capacity;
2293 this.defaultValue = v.defaultValue;
2294 this.positionSize = v.positionSize;
2295 this.position = new int[v.position.length];
2296 System.arraycopy(v.position, 0, this.position, 0,
2297 this.position.length);
2298 this.data.clear();
2299 this.data.addAll(v.data);
2300 }
2301
2302
2303
2304
2305
2306 public void map(MapFunction<E> f) {
2307
2308
2309
2310 defaultValue = f.apply(defaultValue);
2311
2312 for (int i = data.size() - 1; i >= 0; i--) {
2313 E value = f.apply(data.get(i));
2314 if (value == defaultValue) {
2315
2316 removeElementAt(i);
2317 data.remove(i);
2318 } else {
2319
2320 data.set(i, value);
2321 }
2322 }
2323 }
2324 }
2325
2326
2327
2328
2329
2330
2331
2332 interface MapFunction<E> {
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342 E apply(E value);
2343
2344 }
2345
2346 }