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 }