AbstractLinAlgPack: C++ Interfaces For Vectors, Matrices And Related Linear Algebra Objects  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
AbstractLinAlgPack_SparseVectorClassDecl.hpp
1 // @HEADER
2 // ***********************************************************************
3 //
4 // Moocho: Multi-functional Object-Oriented arCHitecture for Optimization
5 // Copyright (2003) Sandia Corporation
6 //
7 // Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive
8 // license for use of this work by or on behalf of the U.S. Government.
9 //
10 // Redistribution and use in source and binary forms, with or without
11 // modification, are permitted provided that the following conditions are
12 // met:
13 //
14 // 1. Redistributions of source code must retain the above copyright
15 // notice, this list of conditions and the following disclaimer.
16 //
17 // 2. Redistributions in binary form must reproduce the above copyright
18 // notice, this list of conditions and the following disclaimer in the
19 // documentation and/or other materials provided with the distribution.
20 //
21 // 3. Neither the name of the Corporation nor the names of the
22 // contributors may be used to endorse or promote products derived from
23 // this software without specific prior written permission.
24 //
25 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
26 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
29 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
30 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
31 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
32 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
33 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
34 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
35 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 //
37 // Questions? Contact Roscoe A. Bartlett (rabartl@sandia.gov)
38 //
39 // ***********************************************************************
40 // @HEADER
41 
42 #ifndef SPARSE_VECTOR_CLASS_DECL_H
43 #define SPARSE_VECTOR_CLASS_DECL_H
44 
45 #include <assert.h>
46 
47 #include <vector>
48 #include <sstream>
49 
50 #include "AbstractLinAlgPack_SpVecIndexLookupClass.hpp"
51 
52 namespace AbstractLinAlgPack {
53 
54 namespace SparseVectorUtilityPack {
55 
56 void assert_is_sorted(bool is_sorted);
57 
59 class DoesNotExistException : public std::logic_error
60 {public: DoesNotExistException(const std::string& what_arg) : std::logic_error(what_arg) {}};
62 class NotSortedException : public std::logic_error
63 {public: NotSortedException(const std::string& what_arg) : std::logic_error(what_arg) {}};
65 class DuplicateIndexesException : public std::logic_error
66 {public: DuplicateIndexesException(const std::string& what_arg) : std::logic_error(what_arg) {}};
68 class OutOfRoomException : public std::logic_error
69 {public: OutOfRoomException(const std::string& what_arg) : std::logic_error(what_arg) {}};
71 class UnsizedException : public std::logic_error
72 {public: UnsizedException(const std::string& what_arg) : std::logic_error(what_arg) {}};
74 class NoNonZeroElementsException : public std::logic_error
75 {public: NoNonZeroElementsException(const std::string& what_arg) : std::logic_error(what_arg) {}};
76 
77 } // end namespace SparseVectorUtilityPack
78 
79 // /////////////////////////////////////////////////////////////////////////////////////
82 
94 template<class T_Element>
95 SparseVectorSlice<T_Element> create_slice(
97  , size_type size, Range1D rng);
98 
100 
101 template <class T_Element>
103 
104 // ///////////////////////////////////////////////////////////////////////
126 template <class T_Element, class T_Alloc = std::allocator<T_Element> >
128 public:
131 
133  typedef T_Alloc allocator_type;
135  typedef T_Element element_type;
137  typedef AbstractLinAlgPack::size_type size_type;
139  typedef ptrdiff_t difference_type;
143  typedef const element_type* const_iterator;
144 
145 #if 0 /* defined(_WINDOWS) || defined(_INTEL_CXX) */
146 
147  typedef std::reverse_iterator<iterator, element_type
149 
150  typedef std::reverse_iterator<const_iterator
151  , element_type, const element_type&
153 
154 #else
155 
157  typedef std::reverse_iterator<iterator> reverse_iterator;
159  typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
160 
161 #endif
162 
175 
177 
180 
184  SparseVector(const allocator_type& alloc = allocator_type());
185 
188 
191  , bool assume_sorted = false, const allocator_type& alloc = allocator_type());
192 
199 
202  , const allocator_type& alloc = allocator_type());
203 
205  ~SparseVector();
206 
208 
215 
222 
224 
233  EOverLap overlap(const SparseVectorSlice<T_Element>& sv) const;
234 
237 
239  size_type dim() const;
240 
242  size_type nz() const;
243 
247  difference_type offset() const;
248 
255  bool is_sorted() const;
256 
264 
270  iterator begin();
271 
273  const_iterator begin() const;
274 
276  iterator end();
277 
279  const_iterator end() const;
280 
287 
290 
292  reverse_iterator rend();
293 
295  const_reverse_iterator rend() const;
296 
297  // end Iterator access to elements
299 
300  // end SparseVectorTemplateInterface
302 
305 
312  void resize(size_type size, size_type max_nz, difference_type offset = 0);
313 
322 
324  size_type max_nz() const;
325 
335  void add_element(element_type ele);
336 
346  void insert_element(element_type ele);
347 
352  void assume_sorted(bool assume_is_sorted);
353 
355  void sort();
356 
368  void assert_valid_and_sorted() const;
369 
371 
386 
390  const element_type* lookup_element(size_type i) const;
391 
393 
402 
407  operator SparseVectorSlice<T_Element>();
408 
410  operator const SparseVectorSlice<T_Element>() const;
411 
419 
422 
424 
441 
443  const SparseVectorSlice<T_Element> operator()(const Range1D& rng) const;
444 
446 
463 
465  const SparseVectorSlice<T_Element> operator()(size_type lbound, size_type ubound) const;
466 
468 
469 private:
470 
471  // /////////////////////////////////////////////////////////////////////////
472  // Private types
473 
476 
477  // /////////////////////////////////////////////////////////////////////////
478  // Private data members
479 
480  allocator_type alloc_; // allocator used to allocate memory
481  size_type size_; // the number of elements in the full vector
482  size_type max_nz_; // the amount of storage that has been allocated
483 // commented out because of problems with MS Visual C++ 5.0
484 // std::vector<element_type, allocator_type> ele_;
485  SpVecIndexLookup index_lookup_; // Acts as storage for elements and caching of searches.
486  bool assume_sorted_; // true if the client said that you can assume sorted.
487  bool know_is_sorted_; // true if it has been varified that is sorted.
488 
489  // //////////////////////////
490  // Private member functions
491 
492  // Throw a NotSortedException of is_sorted() == false
493  void assert_is_sorted() const {
494  SparseVectorUtilityPack::assert_is_sorted(is_sorted());
495  }
496 
498  void assert_space(size_type n) const {
499 #ifdef LINALGPACK_CHECK_SLICE_SETUP
500  if(index_lookup_.nz() + n > max_nz_)
501  throw OutOfRoomException("SparseVector<T_Element,T_Alloc>::assert_space(): There is not storage for this many elements");
502 #endif
503  }
504 
506  void assert_sized_with_mem_set() const {
507  if(!dim())
508  throw UnsizedException("SparseVector<...>::assert_sized_with_mem_set() : "
509  "Error: The sparse vector is unsized");
510  if(!index_lookup_.ele()) {
511  throw NoNonZeroElementsException("SparseVector<...>::assert_sized_with_mem_set() : "
512  "Error: There is no memory set.");
513  }
514  }
515 
517  SparseVectorSlice<T_Element> get_whole_sp_vec() {
518  return SparseVectorSlice<T_Element>(index_lookup_.ele(), index_lookup_.nz()
519  , index_lookup_.offset(), size_, is_sorted());
520  }
521 
523  const SparseVectorSlice<T_Element> get_whole_sp_vec() const {
524  return SparseVectorSlice<T_Element>(index_lookup_.ele(), index_lookup_.nz()
525  , index_lookup_.offset(), size_, is_sorted());
526  }
527 
529  SparseVectorSlice<T_Element> get_slice(const Range1D& rng) const {
530  assert_is_sorted();
531  return create_slice(index_lookup_, size_, rng);
532  }
533 
534 }; // end class SparseVector
535 
536 // ///////////////////////////////////////////////////////////////////////
554 template <class T_Element>
555 class SparseVectorSlice {
556 public:
559 
561  typedef T_Element element_type;
563  typedef AbstractLinAlgPack::size_type size_type;
565  typedef ptrdiff_t difference_type;
569  typedef const element_type* const_iterator;
570 
571 #if 0 /* defined(_WINDOWS) || defined(_INTEL_CXX) */
572 
573  typedef std::reverse_iterator<iterator, element_type
575 
576  typedef std::reverse_iterator<const_iterator
577  , element_type, const element_type&
579 
580 #else
581 
583  typedef std::reverse_iterator<iterator> reverse_iterator;
585  typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
586 
587 #endif
588 
593 
595 
601 
623  , bool assume_sorted = false);
624 
626 
629  void bind(SparseVectorSlice svs);
630 
632 
641  EOverLap overlap(const SparseVectorSlice<T_Element>& sv) const;
642 
645 
647  size_type dim() const;
648 
650  size_type nz() const;
651 
655  difference_type offset() const;
656 
659  bool is_sorted() const;
660 
662  iterator begin();
663 
665  const_iterator begin() const;
666 
668  iterator end();
669 
671  const_iterator end() const;
672 
675 
678 
680  reverse_iterator rend();
681 
683  const_reverse_iterator rend() const;
684 
686 
701 
705  const element_type* lookup_element(size_type i) const;
706 
708 
711 
713 
718 
721 
724  { return this; }
725 
726  const SparseVectorSlice* operator&() const
727  { return this; }
728 
730 
746  SparseVectorSlice<T_Element> operator()(const Range1D& rng);
747 
749  const SparseVectorSlice<T_Element> operator()(const Range1D& rng) const;
750 
752 
768  SparseVectorSlice<T_Element> operator()(size_type lbound, size_type ubound);
769 
771  const SparseVectorSlice<T_Element> operator()(size_type lbound, size_type ubound) const;
772 
774 
775 private:
776  // /////////////////////////////////////////////////////////////////////////
777  // Private types
778 
780  typedef SparseVectorUtilityPack::SpVecIndexLookup<element_type> index_lookup_type;
781 
782  // /////////////////////////////////////////////////////////////////////////
783  // Private data members
784 
785  index_lookup_type index_lookup_; // Acts as storage and cacheing
786  size_type size_; // size of the full vector
787  bool assume_sorted_; // true if the client said that you can assume sorted.
788 
789 
790  // /////////////////////////////////////////////////////////////////////////
791  // Private member functions
792 
793  // Throw a NotSortedException of is_sorted() == false
794  void assert_is_sorted() const {
795  SparseVectorUtilityPack::assert_is_sorted(is_sorted());
796  }
797 
799  SparseVectorSlice<T_Element> get_slice(const Range1D& rng) const {
800  assert_is_sorted();
801  return create_slice(index_lookup_, size_, rng);
802  }
803 
807  SparseVectorSlice<element_type>& operator=(const SparseVectorSlice<element_type>&);
808 
809 }; // end class SparseVectorSlice
810 
811 // ////////////////////////////////////////////////
812 // Non-member non-public utility functions
813 
814 namespace SparseVectorUtilityPack {
815 
820 template< class T_Element >
821 inline const T_Element* lookup_element( const SpVecIndexLookup<T_Element>& index_lookup
822  , typename SpVecIndexLookup<T_Element>::index_type index, bool is_sorted )
823 {
824  size_type poss;
825  return ( ( poss = index_lookup.find_element(index,is_sorted) ) < index_lookup.nz() )
826  ? index_lookup.ele() + poss
827  : NULL;
828 }
829 
830 } // end namespace SparseVectorUtilityPack
831 
832 // /////////////////////////////////////////////////////////////////////////////////////
833 // Inline members for SparseVector<>
834 
835 // constructors
836 
837 template <class T_Element, class T_Alloc>
839  : alloc_(alloc), size_(0), max_nz_(0), assume_sorted_(false), know_is_sorted_(false)
840 {}
841 
842 template <class T_Element, class T_Alloc>
843 inline SparseVector<T_Element,T_Alloc>::SparseVector(bool assume_sorted,const allocator_type& alloc)
844  : alloc_(alloc), size_(0), max_nz_(0), assume_sorted_(assume_sorted), know_is_sorted_(false)
845 {}
846 
847 template <class T_Element, class T_Alloc>
849  , difference_type offset, bool assume_sorted, const allocator_type& alloc)
850  : alloc_(alloc), size_(0), max_nz_(0), assume_sorted_(assume_sorted), know_is_sorted_(false)
851 {
852  resize(size,max_nz,offset);
853 }
854 
855 template <class T_Element, class T_Alloc>
857  resize(0,0);
858 }
859 
860 // SparseVectorTemplateInterface for linear algebra operations
861 
862 template <class T_Element, class T_Alloc>
864  return size_;
865 }
866 
867 template <class T_Element, class T_Alloc>
869  return index_lookup_.nz();
870 }
871 
872 template <class T_Element, class T_Alloc>
874  return index_lookup_.offset();
875 }
876 
877 template <class T_Element, class T_Alloc>
879  return nz() <= 1 || assume_sorted_ || know_is_sorted_;
880 }
881 
882 template <class T_Element, class T_Alloc>
884  return index_lookup_.nz() ? index_lookup_.ele() : NULL;
885 }
886 
887 template <class T_Element, class T_Alloc>
889  return index_lookup_.nz() ? index_lookup_.ele() : NULL;
890 }
891 
892 template <class T_Element, class T_Alloc>
894  return index_lookup_.nz() ? index_lookup_.ele() + index_lookup_.nz() : NULL;
895 }
896 
897 template <class T_Element, class T_Alloc>
899  return index_lookup_.nz() ? index_lookup_.ele() + index_lookup_.nz() : NULL;
900 }
901 
902 template <class T_Element, class T_Alloc>
904  return reverse_iterator(end());
905 }
906 
907 template <class T_Element, class T_Alloc>
909  return const_reverse_iterator(end());
910 }
911 
912 template <class T_Element, class T_Alloc>
914  return reverse_iterator(begin());
915 }
916 
917 template <class T_Element, class T_Alloc>
919  return const_reverse_iterator(begin());
920 }
921 
922 // Element setup and modification
923 
924 template <class T_Element, class T_Alloc>
926  return max_nz_;
927 }
928 
929 template <class T_Element, class T_Alloc>
931  assert_space(1);
932  assume_sorted_ = know_is_sorted_ = false;
933 #ifdef _PG_CXX
934  new (index_lookup_.ele() + index_lookup_.nz()) element_type;
935 #else
936  alloc_.construct(index_lookup_.ele() + index_lookup_.nz(), ele);
937 #endif
938  index_lookup_.incr_nz();
939 }
940 
941 template <class T_Element, class T_Alloc>
942 inline void SparseVector<T_Element,T_Alloc>::assume_sorted(bool assume_is_sorted) {
943  assume_sorted_ = assume_is_sorted;
944 }
945 
946 // Lookup an element
947 
948 template <class T_Element, class T_Alloc>
949 inline
952 {
953  return const_cast<element_type*>(SparseVectorUtilityPack::lookup_element(index_lookup_,i,assume_sorted_));
954 }
955 
956 template <class T_Element, class T_Alloc>
957 inline
960 {
961  return SparseVectorUtilityPack::lookup_element(index_lookup_,i,assume_sorted_);
962 }
963 
964 // Creating a slice (subregion) of the sparse vector
965 
966 template <class T_Element, class T_Alloc>
968  return get_whole_sp_vec();
969 }
970 
971 template <class T_Element, class T_Alloc>
973  return get_whole_sp_vec();
974 }
975 
976 template <class T_Element, class T_Alloc>
978  return get_whole_sp_vec();
979 }
980 
981 template <class T_Element, class T_Alloc>
983  return get_whole_sp_vec();
984 }
985 
986 template <class T_Element, class T_Alloc>
988  return get_slice(rng);
989 }
990 
991 template <class T_Element, class T_Alloc>
993  return get_slice(rng);
994 }
995 
996 template <class T_Element, class T_Alloc>
998  return get_slice(Range1D(lbound,ubound));
999 }
1000 
1001 template <class T_Element, class T_Alloc>
1003  return get_slice(Range1D(lbound,ubound));
1004 }
1005 
1006 // /////////////////////////////////////////////////////////////////////////////////////
1007 // Inline members for SparseVectorSlice<>
1008 
1009 // Constuctors
1010 
1011 template <class T_Element>
1013  , difference_type offset, size_type size, bool assume_sorted)
1014  : index_lookup_(ele,nz,offset), size_(size), assume_sorted_(assume_sorted)
1015 {}
1016 
1017 template <class T_Element>
1019 {
1020  index_lookup_ = svs.index_lookup_;
1021  size_ = svs.size_;
1022  assume_sorted_ = svs.assume_sorted_;
1023 }
1024 
1025 // Sparse Vector Templated interface for linear algebra operations
1026 
1027 template <class T_Element>
1029  return size_;
1030 }
1031 
1032 template <class T_Element>
1034  return index_lookup_.nz();
1035 }
1036 
1037 template <class T_Element>
1039  return index_lookup_.offset();
1040 }
1041 
1042 template <class T_Element>
1044  return nz() <= 1 || assume_sorted_;
1045 }
1046 
1047 template <class T_Element>
1049  return index_lookup_.ele();
1050 }
1051 
1052 template <class T_Element>
1054  return index_lookup_.ele();
1055 }
1056 
1057 template <class T_Element>
1059  return index_lookup_.ele() + index_lookup_.nz();
1060 }
1061 
1062 template <class T_Element>
1064  return index_lookup_.ele() + index_lookup_.nz();
1065 }
1066 
1067 template <class T_Element>
1069  return reverse_iterator(end());
1070 }
1071 
1072 template <class T_Element>
1074  return const_reverse_iterator(end());
1075 }
1076 
1077 template <class T_Element>
1079  return reverse_iterator(begin());
1080 }
1081 
1082 template <class T_Element>
1084  return const_reverse_iterator(begin());
1085 }
1086 
1087 // Lookup an element
1088 
1089 template <class T_Element>
1090 inline
1093 {
1094  return const_cast<element_type*>(SparseVectorUtilityPack::lookup_element(index_lookup_,i,assume_sorted_));
1095 }
1096 
1097 template <class T_Element>
1098 inline
1101 {
1102  return SparseVectorUtilityPack::lookup_element(index_lookup_,i,assume_sorted_);
1103 }
1104 
1105 // Creating a slice (subregion) of the sparse vector
1106 
1107 template <class T_Element>
1109  return *this;
1110 }
1111 
1112 template <class T_Element>
1114  return *this;
1115 }
1116 
1117 template <class T_Element>
1119  return get_slice(rng);
1120 }
1121 
1122 template <class T_Element>
1124  return get_slice(rng);
1125 }
1126 
1127 template <class T_Element>
1129  return get_slice(Range1D(lbound,ubound));
1130 }
1131 
1132 template <class T_Element>
1134  return get_slice(Range1D(lbound,ubound));
1135 }
1136 
1137 } // end namespace AbstractLinAlgPack
1138 
1139 #endif // SPARSE_VECTOR_CLASS_DECL_H
SparseVector< T_Element, T_Alloc > & operator=(const SparseVector< T_Element, T_Alloc > &sp_vec)
Assignment operator.
difference_type offset() const
Return the offset for the indexes (ith real index = begin()[i-1]->index() + offset()# ...
void resize(size_type size, size_type max_nz, difference_type offset=0)
Resize to #size# with a maximum of max_nz# non-zero elements.
size_type dim() const
Return the number of elements in the full vector.
~SparseVector()
Destructor (frees storage for elements).
bool is_sorted() const
Return true if the sequence is sorted.
SparseVectorUtilityPack::OutOfRoomException OutOfRoomException
std::reverse_iterator< const_iterator > const_reverse_iterator
std::reverse_iterator< const_iterator > const_reverse_iterator
void add_element(element_type ele)
Add an unsorted element.
SparseVectorUtilityPack::DoesNotExistException DoesNotExistException
bool is_sorted() const
Return true if the sequence is assumed sorted.
void bind(SparseVectorSlice svs)
Constructs a sparse vector slice view from another sparse vector slice.
void assert_valid_and_sorted() const
Assert that sparse vector is sorted.
SparseVectorUtilityPack::UnsizedException UnsizedException
SparseVectorUtilityPack::DoesNotExistException DoesNotExistException
SparseVectorUtilityPack::DuplicateIndexesException DuplicateIndexesException
size_type dim() const
Return the number of elements in the full vector.
SparseVectorUtilityPack::NoNonZeroElementsException NoNonZeroElementsException
size_type nz() const
Return the number of non-zero elements.
size_t size_type
void assume_sorted(bool assume_is_sorted)
Called by the client to inform this sparse vector object that the elements be assumed to be in sequen...
SparseVectorSlice * operator&()
Allow address to be taken of an rvalue of this object.
void uninitialized_resize(size_type size, size_type nz, size_type max_nz, difference_type offset=0)
Resize to #size# with a max_nz# uninitialized non-zero elements.
EOverLap overlap(const SparseVectorSlice< T_Element > &sv) const
difference_type offset() const
Return the offset for the indexes (ith real index = begin()[i-1]->index() + offset()# ...
void sort()
Sort the elements into assending order by index.
SparseVectorSlice(element_type ele[], size_type nz, difference_type offset, size_type size, bool assume_sorted=false)
Constructs a sparse vector slice from an array of elements.
SparseVectorUtilityPack::NotSortedException NotSortedException
SparseVector(const allocator_type &alloc=allocator_type())
Constructs a sparse vector with no elements (nz() == dim() == 0#) and assumes the elements are not so...
EOverLap overlap(const SparseVectorSlice< T_Element > &sv) const
SparseVectorUtilityPack::NotSortedException NotSortedException
SparseVectorSlice< T_Element > operator()()
Returns a SparseVectorSlice representing the entire sparse vector.
size_type max_nz() const
Return the max number of elements that can be held without resizing.
iterator begin()
Returns iterator that iterates forward through the nonzero elements.
size_type nz() const
Return the number of non-zero elements.
void insert_element(element_type ele)
Add an element into a sorted sequence.
reverse_iterator rbegin()
Returns iterator that iterates backward through the nonzero elements.