1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.math4.legacy.linear;
18
19 import java.io.Serializable;
20
21 import org.apache.commons.math4.legacy.core.Field;
22 import org.apache.commons.math4.legacy.core.FieldElement;
23 import org.apache.commons.math4.legacy.exception.DimensionMismatchException;
24 import org.apache.commons.math4.legacy.exception.MathArithmeticException;
25 import org.apache.commons.math4.legacy.exception.NotPositiveException;
26 import org.apache.commons.math4.legacy.exception.NullArgumentException;
27 import org.apache.commons.math4.legacy.exception.NumberIsTooSmallException;
28 import org.apache.commons.math4.legacy.exception.OutOfRangeException;
29 import org.apache.commons.math4.legacy.exception.util.LocalizedFormats;
30 import org.apache.commons.math4.legacy.core.MathArrays;
31
32
33
34
35
36
37
38
39
40
41
42
43
44 public class SparseFieldVector<T extends FieldElement<T>> implements FieldVector<T>, Serializable {
45
46 private static final long serialVersionUID = 7841233292190413362L;
47
48 private final Field<T> field;
49
50 private final OpenIntToFieldHashMap<T> entries;
51
52 private final int virtualSize;
53
54
55
56
57
58
59
60
61
62
63
64 public SparseFieldVector(Field<T> field) {
65 this(field, 0);
66 }
67
68
69
70
71
72
73
74
75 public SparseFieldVector(Field<T> field, int dimension) {
76 this.field = field;
77 virtualSize = dimension;
78 entries = new OpenIntToFieldHashMap<>(field);
79 }
80
81
82
83
84
85
86
87 protected SparseFieldVector(SparseFieldVector<T> v, int resize) {
88 field = v.field;
89 virtualSize = v.getDimension() + resize;
90 entries = new OpenIntToFieldHashMap<>(v.entries);
91 }
92
93
94
95
96
97
98
99
100
101 public SparseFieldVector(Field<T> field, int dimension, int expectedSize) {
102 this.field = field;
103 virtualSize = dimension;
104 entries = new OpenIntToFieldHashMap<>(field,expectedSize);
105 }
106
107
108
109
110
111
112
113
114
115 public SparseFieldVector(Field<T> field, T[] values) throws NullArgumentException {
116 NullArgumentException.check(values);
117 this.field = field;
118 virtualSize = values.length;
119 entries = new OpenIntToFieldHashMap<>(field);
120 for (int key = 0; key < values.length; key++) {
121 T value = values[key];
122 entries.put(key, value);
123 }
124 }
125
126
127
128
129
130
131 public SparseFieldVector(SparseFieldVector<T> v) {
132 field = v.field;
133 virtualSize = v.getDimension();
134 entries = new OpenIntToFieldHashMap<>(v.getEntries());
135 }
136
137
138
139
140
141
142 private OpenIntToFieldHashMap<T> getEntries() {
143 return entries;
144 }
145
146
147
148
149
150
151
152
153
154 public FieldVector<T> add(SparseFieldVector<T> v)
155 throws DimensionMismatchException {
156 checkVectorDimensions(v.getDimension());
157 SparseFieldVector<T> res = (SparseFieldVector<T>)copy();
158 OpenIntToFieldHashMap<T>.Iterator iter = v.getEntries().iterator();
159 while (iter.hasNext()) {
160 iter.advance();
161 int key = iter.key();
162 T value = iter.value();
163 if (entries.containsKey(key)) {
164 res.setEntry(key, entries.get(key).add(value));
165 } else {
166 res.setEntry(key, value);
167 }
168 }
169 return res;
170 }
171
172
173
174
175
176
177
178 public FieldVector<T> append(SparseFieldVector<T> v) {
179 SparseFieldVector<T> res = new SparseFieldVector<>(this, v.getDimension());
180 OpenIntToFieldHashMap<T>.Iterator iter = v.entries.iterator();
181 while (iter.hasNext()) {
182 iter.advance();
183 res.setEntry(iter.key() + virtualSize, iter.value());
184 }
185 return res;
186 }
187
188
189 @Override
190 public FieldVector<T> append(FieldVector<T> v) {
191 if (v instanceof SparseFieldVector<?>) {
192 return append((SparseFieldVector<T>) v);
193 } else {
194 final int n = v.getDimension();
195 FieldVector<T> res = new SparseFieldVector<>(this, n);
196 for (int i = 0; i < n; i++) {
197 res.setEntry(i + virtualSize, v.getEntry(i));
198 }
199 return res;
200 }
201 }
202
203
204
205
206 @Override
207 public FieldVector<T> append(T d) throws NullArgumentException {
208 NullArgumentException.check(d);
209 FieldVector<T> res = new SparseFieldVector<>(this, 1);
210 res.setEntry(virtualSize, d);
211 return res;
212 }
213
214
215 @Override
216 public FieldVector<T> copy() {
217 return new SparseFieldVector<>(this);
218 }
219
220
221 @Override
222 public T dotProduct(FieldVector<T> v) throws DimensionMismatchException {
223 checkVectorDimensions(v.getDimension());
224 T res = field.getZero();
225 OpenIntToFieldHashMap<T>.Iterator iter = entries.iterator();
226 while (iter.hasNext()) {
227 iter.advance();
228 res = res.add(v.getEntry(iter.key()).multiply(iter.value()));
229 }
230 return res;
231 }
232
233
234 @Override
235 public FieldVector<T> ebeDivide(FieldVector<T> v)
236 throws DimensionMismatchException, MathArithmeticException {
237 checkVectorDimensions(v.getDimension());
238 SparseFieldVector<T> res = new SparseFieldVector<>(this);
239 OpenIntToFieldHashMap<T>.Iterator iter = res.entries.iterator();
240 while (iter.hasNext()) {
241 iter.advance();
242 res.setEntry(iter.key(), iter.value().divide(v.getEntry(iter.key())));
243 }
244 return res;
245 }
246
247
248 @Override
249 public FieldVector<T> ebeMultiply(FieldVector<T> v)
250 throws DimensionMismatchException {
251 checkVectorDimensions(v.getDimension());
252 SparseFieldVector<T> res = new SparseFieldVector<>(this);
253 OpenIntToFieldHashMap<T>.Iterator iter = res.entries.iterator();
254 while (iter.hasNext()) {
255 iter.advance();
256 res.setEntry(iter.key(), iter.value().multiply(v.getEntry(iter.key())));
257 }
258 return res;
259 }
260
261
262 @Override
263 public int getDimension() {
264 return virtualSize;
265 }
266
267
268 @Override
269 public T getEntry(int index) throws OutOfRangeException {
270 checkIndex(index);
271 return entries.get(index);
272 }
273
274
275 @Override
276 public Field<T> getField() {
277 return field;
278 }
279
280
281 @Override
282 public FieldVector<T> getSubVector(int index, int n)
283 throws OutOfRangeException, NotPositiveException {
284 if (n < 0) {
285 throw new NotPositiveException(LocalizedFormats.NUMBER_OF_ELEMENTS_SHOULD_BE_POSITIVE, n);
286 }
287 checkIndex(index);
288 checkIndex(index + n - 1);
289 SparseFieldVector<T> res = new SparseFieldVector<>(field,n);
290 int end = index + n;
291 OpenIntToFieldHashMap<T>.Iterator iter = entries.iterator();
292 while (iter.hasNext()) {
293 iter.advance();
294 int key = iter.key();
295 if (key >= index && key < end) {
296 res.setEntry(key - index, iter.value());
297 }
298 }
299 return res;
300 }
301
302
303 @Override
304 public FieldVector<T> mapAdd(T d) throws NullArgumentException {
305 return copy().mapAddToSelf(d);
306 }
307
308
309 @Override
310 public FieldVector<T> mapAddToSelf(T d) throws NullArgumentException {
311 for (int i = 0; i < virtualSize; i++) {
312 setEntry(i, getEntry(i).add(d));
313 }
314 return this;
315 }
316
317
318 @Override
319 public FieldVector<T> mapDivide(T d)
320 throws NullArgumentException, MathArithmeticException {
321 return copy().mapDivideToSelf(d);
322 }
323
324
325 @Override
326 public FieldVector<T> mapDivideToSelf(T d)
327 throws NullArgumentException, MathArithmeticException {
328 OpenIntToFieldHashMap<T>.Iterator iter = entries.iterator();
329 while (iter.hasNext()) {
330 iter.advance();
331 entries.put(iter.key(), iter.value().divide(d));
332 }
333 return this;
334 }
335
336
337 @Override
338 public FieldVector<T> mapInv() throws MathArithmeticException {
339 return copy().mapInvToSelf();
340 }
341
342
343 @Override
344 public FieldVector<T> mapInvToSelf() throws MathArithmeticException {
345 for (int i = 0; i < virtualSize; i++) {
346 setEntry(i, field.getOne().divide(getEntry(i)));
347 }
348 return this;
349 }
350
351
352 @Override
353 public FieldVector<T> mapMultiply(T d) throws NullArgumentException {
354 return copy().mapMultiplyToSelf(d);
355 }
356
357
358 @Override
359 public FieldVector<T> mapMultiplyToSelf(T d) throws NullArgumentException {
360 OpenIntToFieldHashMap<T>.Iterator iter = entries.iterator();
361 while (iter.hasNext()) {
362 iter.advance();
363 entries.put(iter.key(), iter.value().multiply(d));
364 }
365 return this;
366 }
367
368
369 @Override
370 public FieldVector<T> mapSubtract(T d) throws NullArgumentException {
371 return copy().mapSubtractToSelf(d);
372 }
373
374
375 @Override
376 public FieldVector<T> mapSubtractToSelf(T d) throws NullArgumentException {
377 return mapAddToSelf(field.getZero().subtract(d));
378 }
379
380
381
382
383
384
385 public FieldMatrix<T> outerProduct(SparseFieldVector<T> v) {
386 final int n = v.getDimension();
387 SparseFieldMatrix<T> res = new SparseFieldMatrix<>(field, virtualSize, n);
388 OpenIntToFieldHashMap<T>.Iterator iter = entries.iterator();
389 while (iter.hasNext()) {
390 iter.advance();
391 OpenIntToFieldHashMap<T>.Iterator iter2 = v.entries.iterator();
392 while (iter2.hasNext()) {
393 iter2.advance();
394 res.setEntry(iter.key(), iter2.key(), iter.value().multiply(iter2.value()));
395 }
396 }
397 return res;
398 }
399
400
401 @Override
402 public FieldMatrix<T> outerProduct(FieldVector<T> v) {
403 if (v instanceof SparseFieldVector<?>) {
404 return outerProduct((SparseFieldVector<T>)v);
405 } else {
406 final int n = v.getDimension();
407 FieldMatrix<T> res = new SparseFieldMatrix<>(field, virtualSize, n);
408 OpenIntToFieldHashMap<T>.Iterator iter = entries.iterator();
409 while (iter.hasNext()) {
410 iter.advance();
411 int row = iter.key();
412 FieldElement<T> value = iter.value();
413 for (int col = 0; col < n; col++) {
414 res.setEntry(row, col, value.multiply(v.getEntry(col)));
415 }
416 }
417 return res;
418 }
419 }
420
421
422 @Override
423 public FieldVector<T> projection(FieldVector<T> v)
424 throws DimensionMismatchException, MathArithmeticException {
425 checkVectorDimensions(v.getDimension());
426 return v.mapMultiply(dotProduct(v).divide(v.dotProduct(v)));
427 }
428
429
430
431
432 @Override
433 public void set(T value) {
434 NullArgumentException.check(value);
435 for (int i = 0; i < virtualSize; i++) {
436 setEntry(i, value);
437 }
438 }
439
440
441
442
443 @Override
444 public void setEntry(int index, T value) throws NullArgumentException, OutOfRangeException {
445 NullArgumentException.check(value);
446 checkIndex(index);
447 entries.put(index, value);
448 }
449
450
451 @Override
452 public void setSubVector(int index, FieldVector<T> v)
453 throws OutOfRangeException {
454 checkIndex(index);
455 checkIndex(index + v.getDimension() - 1);
456 final int n = v.getDimension();
457 for (int i = 0; i < n; i++) {
458 setEntry(i + index, v.getEntry(i));
459 }
460 }
461
462
463
464
465
466
467
468
469 public SparseFieldVector<T> subtract(SparseFieldVector<T> v)
470 throws DimensionMismatchException {
471 checkVectorDimensions(v.getDimension());
472 SparseFieldVector<T> res = (SparseFieldVector<T>)copy();
473 OpenIntToFieldHashMap<T>.Iterator iter = v.getEntries().iterator();
474 while (iter.hasNext()) {
475 iter.advance();
476 int key = iter.key();
477 if (entries.containsKey(key)) {
478 res.setEntry(key, entries.get(key).subtract(iter.value()));
479 } else {
480 res.setEntry(key, field.getZero().subtract(iter.value()));
481 }
482 }
483 return res;
484 }
485
486
487 @Override
488 public FieldVector<T> subtract(FieldVector<T> v)
489 throws DimensionMismatchException {
490 if (v instanceof SparseFieldVector<?>) {
491 return subtract((SparseFieldVector<T>)v);
492 } else {
493 final int n = v.getDimension();
494 checkVectorDimensions(n);
495 SparseFieldVector<T> res = new SparseFieldVector<>(this);
496 for (int i = 0; i < n; i++) {
497 if (entries.containsKey(i)) {
498 res.setEntry(i, entries.get(i).subtract(v.getEntry(i)));
499 } else {
500 res.setEntry(i, field.getZero().subtract(v.getEntry(i)));
501 }
502 }
503 return res;
504 }
505 }
506
507
508 @Override
509 public T[] toArray() {
510 T[] res = MathArrays.buildArray(field, virtualSize);
511 OpenIntToFieldHashMap<T>.Iterator iter = entries.iterator();
512 while (iter.hasNext()) {
513 iter.advance();
514 res[iter.key()] = iter.value();
515 }
516 return res;
517 }
518
519
520
521
522
523
524
525 private void checkIndex(final int index) throws OutOfRangeException {
526 if (index < 0 || index >= getDimension()) {
527 throw new OutOfRangeException(index, 0, getDimension() - 1);
528 }
529 }
530
531
532
533
534
535
536
537
538
539
540 private void checkIndices(final int start, final int end)
541 throws NumberIsTooSmallException, OutOfRangeException {
542 final int dim = getDimension();
543 if (start < 0 || start >= dim) {
544 throw new OutOfRangeException(LocalizedFormats.INDEX, start, 0,
545 dim - 1);
546 }
547 if (end < 0 || end >= dim) {
548 throw new OutOfRangeException(LocalizedFormats.INDEX, end, 0,
549 dim - 1);
550 }
551 if (end < start) {
552 throw new NumberIsTooSmallException(LocalizedFormats.INITIAL_ROW_AFTER_FINAL_ROW,
553 end, start, false);
554 }
555 }
556
557
558
559
560
561
562
563 protected void checkVectorDimensions(int n)
564 throws DimensionMismatchException {
565 if (getDimension() != n) {
566 throw new DimensionMismatchException(getDimension(), n);
567 }
568 }
569
570
571 @Override
572 public FieldVector<T> add(FieldVector<T> v) throws DimensionMismatchException {
573 if (v instanceof SparseFieldVector<?>) {
574 return add((SparseFieldVector<T>) v);
575 } else {
576 final int n = v.getDimension();
577 checkVectorDimensions(n);
578 SparseFieldVector<T> res = new SparseFieldVector<>(field,
579 getDimension());
580 for (int i = 0; i < n; i++) {
581 res.setEntry(i, v.getEntry(i).add(getEntry(i)));
582 }
583 return res;
584 }
585 }
586
587
588
589
590
591
592
593
594
595
596
597 public T walkInDefaultOrder(final FieldVectorPreservingVisitor<T> visitor) {
598 final int dim = getDimension();
599 visitor.start(dim, 0, dim - 1);
600 for (int i = 0; i < dim; i++) {
601 visitor.visit(i, getEntry(i));
602 }
603 return visitor.end();
604 }
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619 public T walkInDefaultOrder(final FieldVectorPreservingVisitor<T> visitor,
620 final int start, final int end)
621 throws NumberIsTooSmallException, OutOfRangeException {
622 checkIndices(start, end);
623 visitor.start(getDimension(), start, end);
624 for (int i = start; i <= end; i++) {
625 visitor.visit(i, getEntry(i));
626 }
627 return visitor.end();
628 }
629
630
631
632
633
634
635
636
637
638
639
640
641
642 public T walkInOptimizedOrder(final FieldVectorPreservingVisitor<T> visitor) {
643 return walkInDefaultOrder(visitor);
644 }
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661 public T walkInOptimizedOrder(final FieldVectorPreservingVisitor<T> visitor,
662 final int start, final int end)
663 throws NumberIsTooSmallException, OutOfRangeException {
664 return walkInDefaultOrder(visitor, start, end);
665 }
666
667
668
669
670
671
672
673
674
675
676
677 public T walkInDefaultOrder(final FieldVectorChangingVisitor<T> visitor) {
678 final int dim = getDimension();
679 visitor.start(dim, 0, dim - 1);
680 for (int i = 0; i < dim; i++) {
681 setEntry(i, visitor.visit(i, getEntry(i)));
682 }
683 return visitor.end();
684 }
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699 public T walkInDefaultOrder(final FieldVectorChangingVisitor<T> visitor,
700 final int start, final int end)
701 throws NumberIsTooSmallException, OutOfRangeException {
702 checkIndices(start, end);
703 visitor.start(getDimension(), start, end);
704 for (int i = start; i <= end; i++) {
705 setEntry(i, visitor.visit(i, getEntry(i)));
706 }
707 return visitor.end();
708 }
709
710
711
712
713
714
715
716
717
718
719
720
721
722 public T walkInOptimizedOrder(final FieldVectorChangingVisitor<T> visitor) {
723 return walkInDefaultOrder(visitor);
724 }
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741 public T walkInOptimizedOrder(final FieldVectorChangingVisitor<T> visitor,
742 final int start, final int end)
743 throws NumberIsTooSmallException, OutOfRangeException {
744 return walkInDefaultOrder(visitor, start, end);
745 }
746
747
748 @Override
749 public int hashCode() {
750 final int prime = 31;
751 int result = 1;
752 result = prime * result + ((field == null) ? 0 : field.hashCode());
753 result = prime * result + virtualSize;
754 OpenIntToFieldHashMap<T>.Iterator iter = entries.iterator();
755 while (iter.hasNext()) {
756 iter.advance();
757 int temp = iter.value().hashCode();
758 result = prime * result + temp;
759 }
760 return result;
761 }
762
763
764
765 @Override
766 public boolean equals(Object obj) {
767
768 if (this == obj) {
769 return true;
770 }
771
772 if (!(obj instanceof SparseFieldVector<?>)) {
773 return false;
774 }
775
776 @SuppressWarnings("unchecked")
777
778 SparseFieldVector<T> other = (SparseFieldVector<T>) obj;
779 if (field == null) {
780 if (other.field != null) {
781 return false;
782 }
783 } else if (!field.equals(other.field)) {
784 return false;
785 }
786 if (virtualSize != other.virtualSize) {
787 return false;
788 }
789
790 OpenIntToFieldHashMap<T>.Iterator iter = entries.iterator();
791 while (iter.hasNext()) {
792 iter.advance();
793 T test = other.getEntry(iter.key());
794 if (!test.equals(iter.value())) {
795 return false;
796 }
797 }
798 iter = other.getEntries().iterator();
799 while (iter.hasNext()) {
800 iter.advance();
801 T test = iter.value();
802 if (!test.equals(getEntry(iter.key()))) {
803 return false;
804 }
805 }
806 return true;
807 }
808 }