00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 #ifndef SPARSE_VECTOR_CLASS_DEF_H
00030 #define SPARSE_VECTOR_CLASS_DEF_H
00031
00032 #include <algorithm>
00033
00034 #include "AbstractLinAlgPack_SparseVectorClassDecl.hpp"
00035 #include "AbstractLinAlgPack_compare_element_indexes.hpp"
00036 #include "Teuchos_TestForException.hpp"
00037
00038 namespace AbstractLinAlgPack {
00039
00040
00041
00042
00043
00044
00045 template<class T_Element>
00046 SparseVectorSlice<T_Element>
00047 create_slice(const SparseVectorUtilityPack::SpVecIndexLookup<T_Element>& index_lookup
00048 , size_type size, Range1D rng)
00049 {
00050
00051 if(rng.full_range()) {
00052 rng = Range1D(1,size);
00053 }
00054 else {
00055 #ifdef TEUCHOS_DEBUG
00056 TEST_FOR_EXCEPT( !( rng.ubound() <= size ) );
00057 #endif
00058 }
00059
00060
00061 if(!index_lookup.nz())
00062 return SparseVectorSlice<T_Element>(0, 0, 0, rng.ubound() - rng.lbound() + 1, true);
00063
00064
00065 typedef SparseVectorUtilityPack::SpVecIndexLookup<T_Element> SpVecIndexLookup;
00066 index_lookup.validate_state();
00067 typename SpVecIndexLookup::poss_type
00068 lower_poss = index_lookup.find_poss(rng.lbound(), SpVecIndexLookup::LOWER_ELE),
00069 upper_poss = index_lookup.find_poss(rng.ubound(), SpVecIndexLookup::UPPER_ELE);
00070 if( lower_poss.poss == upper_poss.poss
00071 && ( lower_poss.rel == SpVecIndexLookup::AFTER_ELE
00072 || upper_poss.rel == SpVecIndexLookup::BEFORE_ELE )
00073 )
00074 {
00075
00076 return SparseVectorSlice<T_Element>(0, 0, 0, rng.ubound() - rng.lbound() + 1, true);
00077 }
00078 else {
00079
00080 return SparseVectorSlice<T_Element>(index_lookup.ele() + lower_poss.poss
00081 , upper_poss.poss - lower_poss.poss + 1, index_lookup.offset() - rng.lbound() + 1
00082 , rng.ubound() - rng.lbound() + 1, true);
00083 }
00084 }
00085
00086
00087
00088
00089 template <class T_Element, class T_Alloc>
00090 SparseVector<T_Element,T_Alloc>::SparseVector(
00091 const SparseVector<T_Element,T_Alloc>& sp_vec )
00092 :
00093 alloc_(sp_vec.alloc_), size_(sp_vec.size_), max_nz_(sp_vec.max_nz_)
00094 , assume_sorted_(sp_vec.assume_sorted_)
00095 , know_is_sorted_(sp_vec.know_is_sorted_)
00096 {
00097
00098 index_lookup_.set_sp_vec(
00099 #ifdef _PG_CXX
00100 new element_type[max_nz_]
00101 #else
00102 alloc_.allocate(max_nz_,NULL)
00103 #endif
00104 ,sp_vec.nz(),sp_vec.offset());
00105
00106 iterator ele_to_itr = index_lookup_.ele();
00107 const_iterator ele_from_itr = sp_vec.begin();
00108 while(ele_from_itr != sp_vec.end()) {
00109 #ifdef _PG_CXX
00110 new (ele_to_itr++) element_type(*ele_from_itr++);
00111 #else
00112 alloc_.construct(ele_to_itr++,*ele_from_itr++);
00113 #endif
00114 }
00115 }
00116
00117 template <class T_Element, class T_Alloc>
00118 SparseVector<T_Element,T_Alloc>::SparseVector(
00119 SparseVectorSlice<T_Element> sp_vec_slc
00120 , const allocator_type& alloc )
00121 :
00122 alloc_(alloc), size_(sp_vec_slc.dim()), max_nz_(sp_vec_slc.nz())
00123 , assume_sorted_(sp_vec_slc.is_sorted())
00124 , know_is_sorted_(false)
00125 {
00126
00127 index_lookup_.set_sp_vec(
00128 #ifdef _PG_CXX
00129 new element_type[max_nz_]
00130 #else
00131 alloc_.allocate(max_nz_,NULL)
00132 #endif
00133 , sp_vec_slc.nz()
00134 ,sp_vec_slc.offset() );
00135
00136 iterator ele_to_itr = index_lookup_.ele();
00137 const_iterator ele_from_itr = sp_vec_slc.begin();
00138 while(ele_from_itr != sp_vec_slc.end()) {
00139 #ifdef _PG_CXX
00140 new (ele_to_itr++) element_type(*ele_from_itr++);
00141 #else
00142 alloc_.construct(ele_to_itr++,*ele_from_itr++);
00143 #endif
00144 }
00145 }
00146
00147 template <class T_Element, class T_Alloc>
00148 SparseVector<T_Element,T_Alloc>&
00149 SparseVector<T_Element,T_Alloc>::operator=(
00150 const SparseVector<T_Element,T_Alloc>& sp_vec)
00151 {
00152 if(this == &sp_vec) return *this;
00153
00154 know_is_sorted_ = sp_vec.know_is_sorted_;
00155 assume_sorted_ = sp_vec.assume_sorted_;
00156
00157 if( max_nz() < sp_vec.nz() ) {
00158
00159 resize(0,0);
00160 resize(sp_vec.dim(),sp_vec.nz(),sp_vec.offset());
00161 }
00162 else if( nz() ) {
00163
00164
00165 for(iterator ele_itr = begin(); ele_itr != end();) {
00166 #ifdef _PG_CXX
00167 (ele_itr++)->~element_type();
00168 #else
00169 alloc_.destroy(ele_itr++);
00170 #endif
00171 }
00172
00173 size_ = sp_vec.size_;
00174 }
00175
00176
00177 index_lookup_.set_sp_vec(index_lookup_.ele(),sp_vec.nz(),sp_vec.offset());
00178
00179 if( sp_vec.nz() ) {
00180
00181 iterator ele_to_itr = index_lookup_.ele();
00182 const_iterator ele_from_itr = sp_vec.begin();
00183 while(ele_from_itr != sp_vec.end()) {
00184 #ifdef _PG_CXX
00185 new (ele_to_itr++) element_type(*ele_from_itr++);
00186 #else
00187 alloc_.construct(ele_to_itr++,*ele_from_itr++);
00188 #endif
00189 }
00190 }
00191
00192 return *this;
00193 }
00194
00195 template <class T_Element, class T_Alloc>
00196 SparseVector<T_Element,T_Alloc>&
00197 SparseVector<T_Element,T_Alloc>::operator=(
00198 const SparseVectorSlice<T_Element>& sp_vec_slc )
00199 {
00200 know_is_sorted_ = false;
00201 assume_sorted_ = sp_vec_slc.is_sorted();
00202
00203 if(max_nz() < sp_vec_slc.nz()) {
00204
00205 resize(0,0);
00206 resize(sp_vec_slc.dim(),sp_vec_slc.nz(),sp_vec_slc.offset());
00207 }
00208 else if( nz() ) {
00209
00210
00211 for(iterator ele_itr = begin(); ele_itr != end();) {
00212 #ifdef _PG_CXX
00213 (ele_itr++)->~element_type();
00214 #else
00215 alloc_.destroy(ele_itr++);
00216 #endif
00217 }
00218
00219 size_ = sp_vec_slc.dim();
00220 }
00221
00222
00223 index_lookup_.set_sp_vec(index_lookup_.ele(),sp_vec_slc.nz()
00224 ,sp_vec_slc.offset());
00225
00226 if( sp_vec_slc.nz() ) {
00227
00228 iterator ele_to_itr = index_lookup_.ele();
00229 const_iterator ele_from_itr = sp_vec_slc.begin();
00230 while(ele_from_itr != sp_vec_slc.end()) {
00231 #ifdef _PG_CXX
00232 new (ele_to_itr++) element_type(*ele_from_itr++);
00233 #else
00234 alloc_.construct(ele_to_itr++,*ele_from_itr++);
00235 #endif
00236 }
00237 }
00238
00239 return *this;
00240 }
00241
00242 template <class T_Element, class T_Alloc>
00243 EOverLap SparseVector<T_Element,T_Alloc>::overlap(const SparseVectorSlice<T_Element>& sv) const
00244 {
00245 if(!sv.dim()) return DenseLinAlgPack::NO_OVERLAP;
00246
00247 const_iterator this_begin = begin();
00248 typename SparseVectorSlice<T_Element>::const_iterator sv_begin = sv.begin();
00249
00250 if( this_begin == sv_begin && end() == sv.end() )
00251 {
00252 return DenseLinAlgPack::SAME_MEM;
00253 }
00254
00255 if( ( this_begin < sv_begin && end() < sv_begin )
00256 || ( sv_begin < this_begin && sv.end() < this_begin ) )
00257 {
00258 return DenseLinAlgPack::NO_OVERLAP;
00259 }
00260
00261 return DenseLinAlgPack::SOME_OVERLAP;
00262 }
00263
00264 template <class T_Element, class T_Alloc>
00265 void SparseVector<T_Element,T_Alloc>::resize(size_type size, size_type max_nz
00266 , difference_type offset)
00267 {
00268
00269 if(index_lookup_.ele()) {
00270 for(element_type* p = index_lookup_.ele(); p < index_lookup_.ele() + index_lookup_.nz(); ++p) {
00271 #ifdef _PG_CXX
00272 p->~element_type();
00273 #else
00274 alloc_.destroy(p);
00275 #endif
00276 }
00277 #ifdef _PG_CXX
00278 delete [] index_lookup_.ele();
00279 #else
00280 alloc_.deallocate(index_lookup_.ele(), max_nz_);
00281 #endif
00282 }
00283
00284
00285 max_nz_ = 0;
00286 know_is_sorted_ = false;
00287
00288 if(max_nz) {
00289
00290 #ifdef _PG_CXX
00291 index_lookup_.set_sp_vec( new element_type[max_nz_ = max_nz], 0, offset );
00292 #else
00293 index_lookup_.set_sp_vec( alloc_.allocate( max_nz_ = max_nz, 0 ), 0, offset );
00294 #endif
00295 size_ = size;
00296 }
00297 else {
00298
00299 index_lookup_.set_sp_vec( 0, 0, offset );
00300 size_ = size;
00301 }
00302 }
00303
00304 template <class T_Element, class T_Alloc>
00305 void SparseVector<T_Element,T_Alloc>::uninitialized_resize(size_type size, size_type nz, size_type max_nz
00306 , difference_type offset)
00307 {
00308 #ifdef TEUCHOS_DEBUG
00309 TEST_FOR_EXCEPTION(
00310 nz > max_nz, std::length_error
00311 ,"SparseVector<...>::uninitialized_resize(...) : nz can not be greater"
00312 " than max_nz" );
00313 #endif
00314 resize(size,max_nz,offset);
00315 index_lookup_.set_sp_vec(index_lookup_.ele(), nz, index_lookup_.offset());
00316 }
00317
00318 template <class T_Element, class T_Alloc>
00319 void SparseVector<T_Element,T_Alloc>::insert_element(element_type ele)
00320 {
00321 assert_space(1);
00322 assert_is_sorted();
00323
00324 if( nz() ) {
00325 typedef SparseVectorUtilityPack::SpVecIndexLookup<T_Element> SpVecIndexLookup;
00326 typedef typename SpVecIndexLookup::poss_type poss_type;
00327 index_lookup_.validate_state();
00328 poss_type poss
00329 = ( nz()
00330 ? index_lookup_.find_poss(ele.index(), SpVecIndexLookup::LOWER_ELE)
00331 : poss_type(0,SpVecIndexLookup::BEFORE_ELE)
00332 );
00333
00334 #ifdef TEUCHOS_DEBUG
00335 TEST_FOR_EXCEPTION(
00336 nz() && poss.rel == SpVecIndexLookup::EQUAL_TO_ELE, std::length_error
00337 ,"SparseVector<...>::insert_element(...) : Error, this index"
00338 " all ready exists!" );
00339 #endif
00340 const size_type
00341 insert_poss = (poss.rel == SpVecIndexLookup::BEFORE_ELE ? poss.poss : poss.poss+1);
00342
00343 std::copy_backward(
00344 index_lookup_.ele() + insert_poss, index_lookup_.ele() + index_lookup_.nz()
00345 , index_lookup_.ele() + index_lookup_.nz() + 1 );
00346 index_lookup_.ele()[insert_poss] = ele;
00347 index_lookup_.incr_nz();
00348 }
00349 else {
00350 index_lookup_.ele()[0] = ele;
00351 index_lookup_.incr_nz();
00352 }
00353 }
00354
00355 template <class T_Element, class T_Alloc>
00356 void SparseVector<T_Element,T_Alloc>::sort() {
00357 if( index_lookup_.nz() > 0 )
00358 std::stable_sort(begin(),end(),compare_element_indexes_less<element_type>());
00359 know_is_sorted_ = true;
00360 }
00361
00362 template <class T_Element, class T_Alloc>
00363 void SparseVector<T_Element,T_Alloc>::assert_valid_and_sorted() const
00364 {
00365
00366 if(!index_lookup_.nz()) return;
00367
00368
00369
00370
00371 typename T_Element::index_type last_index;
00372 for(T_Element* p = index_lookup_.ele();
00373 p < index_lookup_.ele() + index_lookup_.nz(); ++p)
00374 {
00375 typename T_Element::index_type curr_index = p->index() + offset();
00376 #ifdef TEUCHOS_DEBUG
00377 TEST_FOR_EXCEPTION(
00378 (1 > curr_index) || (curr_index > dim()), std::out_of_range
00379 ,"SparseVector<...>::assert_valid_and_sorted():"
00380 << " Error, not in range: element (0-based) " << p - index_lookup_.ele() - 1
00381 << " with index + offset = " << curr_index
00382 << " is not in range" );
00383 #endif
00384 if(p == index_lookup_.ele()) {
00385 last_index = curr_index;
00386 continue;
00387 }
00388 #ifdef TEUCHOS_DEBUG
00389 TEST_FOR_EXCEPTION(
00390 curr_index < last_index, NotSortedException
00391 ,"SparseVector<...>::assert_valid_and_sorted():"
00392 << " Error, not sorted: element (0-based) " << p - index_lookup_.ele() - 1
00393 << " and " << p - index_lookup_.ele() << " are not in assending order" );
00394 TEST_FOR_EXCEPTION(
00395 curr_index == last_index, DuplicateIndexesException
00396 ,"SparseVector<...>::assert_valid_and_sorted():"
00397 << " Error, duplicate indexes: element (0-based) " << p - index_lookup_.ele() - 1
00398 << " and " << p - index_lookup_.ele() << " have duplicate indexes" );
00399 #endif
00400 last_index = curr_index;
00401 }
00402 }
00403
00404
00405
00406
00407
00408 template <class T_Element>
00409 EOverLap SparseVectorSlice<T_Element>::overlap(const SparseVectorSlice<T_Element>& sv) const
00410 {
00411 if(!sv.dim()) return DenseLinAlgPack::NO_OVERLAP;
00412
00413 const_iterator this_begin = begin(),
00414 sv_begin = sv.begin();
00415
00416 if( this_begin == sv_begin && end() == sv.end() )
00417 {
00418 return DenseLinAlgPack::SAME_MEM;
00419 }
00420
00421 if( ( this_begin < sv_begin && end() < sv_begin )
00422 || ( sv_begin < this_begin && sv.end() < this_begin ) )
00423 {
00424 return DenseLinAlgPack::NO_OVERLAP;
00425 }
00426
00427 return DenseLinAlgPack::SOME_OVERLAP;
00428 }
00429
00430 }
00431
00432 #endif // SPARSE_VECTOR_CLASS_DEF_H