SmallArray.h
Go to the documentation of this file.
1 //=================================================================================================
33 //=================================================================================================
34 
35 #ifndef _BLAZE_UTIL_SMALLARRAY_H_
36 #define _BLAZE_UTIL_SMALLARRAY_H_
37 
38 
39 //*************************************************************************************************
40 // Includes
41 //*************************************************************************************************
42 
43 #include <algorithm>
44 #include <iterator>
45 #include <memory>
51 #include <blaze/util/Assert.h>
54 #include <blaze/util/Exception.h>
57 #include <blaze/util/Types.h>
60 
61 
62 namespace blaze {
63 
64 //=================================================================================================
65 //
66 // CLASS DEFINITION
67 //
68 //=================================================================================================
69 
70 //*************************************************************************************************
78 template< typename T // Data type of the elements
79  , size_t N // Number of preallocated elements
80  , typename A = std::allocator<T> > // Type of the allocator
82  : private SmallArrayData<T,N>
83  , private A
84 {
85  public:
86  //**Type definitions****************************************************************************
87  using ElementType = T;
88  using Pointer = T*;
89  using ConstPointer = const T*;
90  using Reference = T&;
91  using ConstReference = const T&;
92  using Iterator = T*;
93  using ConstIterator = const T*;
94  //**********************************************************************************************
95 
96  //**Constructors********************************************************************************
99  explicit inline SmallArray( const A& alloc = A() );
100  explicit inline SmallArray( size_t n, const A& alloc = A() );
101  explicit inline SmallArray( size_t n, const T& init, const A& alloc = A() );
102 
103  template< typename InputIt >
104  explicit inline SmallArray( InputIt first, InputIt last, const A& alloc = A() );
105 
106  template< typename U >
107  explicit inline SmallArray( initializer_list<U> list, const A& alloc = A() );
108 
109  inline SmallArray( const SmallArray& sa );
110  inline SmallArray( SmallArray&& sa );
112  //**********************************************************************************************
113 
114  //**Destructor**********************************************************************************
117  inline ~SmallArray();
119  //**********************************************************************************************
120 
121  //**Data access functions***********************************************************************
124  inline Reference operator[]( size_t index ) noexcept;
125  inline ConstReference operator[]( size_t index ) const noexcept;
126  inline Reference at( size_t index );
127  inline ConstReference at( size_t index ) const;
128  inline Pointer data() noexcept;
129  inline ConstPointer data() const noexcept;
130  inline Iterator begin () noexcept;
131  inline ConstIterator begin () const noexcept;
132  inline ConstIterator cbegin() const noexcept;
133  inline Iterator end () noexcept;
134  inline ConstIterator end () const noexcept;
135  inline ConstIterator cend () const noexcept;
137  //**********************************************************************************************
138 
139  //**Assignment operators************************************************************************
142  template< typename U >
143  inline SmallArray& operator=( initializer_list<U> list );
144 
145  inline SmallArray& operator=( const SmallArray& rhs );
146  inline SmallArray& operator=( SmallArray&& rhs );
148  //**********************************************************************************************
149 
150  //**Utility functions***************************************************************************
153  inline bool empty() const noexcept;
154  inline size_t size() const noexcept;
155  inline size_t capacity() const noexcept;
156 
157  inline void clear();
158  void resize( size_t n );
159  void resize( size_t n, const T& value );
160  void reserve( size_t n );
161  void shrinkToFit();
162  void pushBack( const T& value );
163  void pushBack( T&& value );
164  Iterator insert( Iterator pos, const T& value );
165  Iterator insert( Iterator pos, T&& value );
166  Iterator erase( Iterator pos );
167  Iterator erase( Iterator first, Iterator last );
168  void swap( SmallArray& sa ) noexcept( IsNothrowMoveConstructible_v<T> );
170  //**********************************************************************************************
171 
172  private:
173  //**Uninitialized struct definition*************************************************************
176  struct Uninitialized {};
177  //**********************************************************************************************
178 
179  //**Constructors********************************************************************************
182  explicit inline SmallArray( size_t n, const A& alloc, Uninitialized );
184  //**********************************************************************************************
185 
186  //**Utility functions***************************************************************************
189  using A::allocate;
190  using A::deallocate;
191 
192  inline bool isDynamic() const noexcept;
194  //**********************************************************************************************
195 
196  //**Member variables****************************************************************************
199  T* begin_;
200  T* end_;
201  T* final_;
202 
203  //**********************************************************************************************
204 
205  //**Compile time checks*************************************************************************
210  //**********************************************************************************************
211 };
212 //*************************************************************************************************
213 
214 
215 
216 
217 //=================================================================================================
218 //
219 // CONSTRUCTORS
220 //
221 //=================================================================================================
222 
223 //*************************************************************************************************
228 template< typename T // Data type of the elements
229  , size_t N // Number of preallocated elements
230  , typename A > // Type of the allocator
231 inline SmallArray<T,N,A>::SmallArray( const A& alloc )
232  : SmallArray( 0UL, alloc, Uninitialized() )
233 {}
234 //*************************************************************************************************
235 
236 
237 //*************************************************************************************************
243 template< typename T // Data type of the elements
244  , size_t N // Number of preallocated elements
245  , typename A > // Type of the allocator
246 inline SmallArray<T,N,A>::SmallArray( size_t n, const A& alloc )
247  : SmallArray( n, alloc, Uninitialized() )
248 {
249  std::uninitialized_fill( begin_, end_, T() );
250 }
251 //*************************************************************************************************
252 
253 
254 //*************************************************************************************************
263 template< typename T // Data type of the elements
264  , size_t N // Number of preallocated elements
265  , typename A > // Type of the allocator
266 inline SmallArray<T,N,A>::SmallArray( size_t n, const T& init, const A& alloc )
267  : SmallArray( n, alloc, Uninitialized() )
268 {
269  std::uninitialized_fill( begin_, end_, init );
270 }
271 //*************************************************************************************************
272 
273 
274 //*************************************************************************************************
281 template< typename T // Data type of the elements
282  , size_t N // Number of preallocated elements
283  , typename A > // Type of the allocator
284 template< typename InputIt > // Type of the iterators
285 inline SmallArray<T,N,A>::SmallArray( InputIt first, InputIt last, const A& alloc )
286  : SmallArray( std::distance( first, last ), alloc, Uninitialized() )
287 {
288  std::uninitialized_copy( first, last, begin_ );
289 }
290 //*************************************************************************************************
291 
292 
293 //*************************************************************************************************
309 template< typename T // Data type of the elements
310  , size_t N // Number of preallocated elements
311  , typename A > // Type of the allocator
312 template< typename U > // Type of the initializer list elements
314  : SmallArray( list.size(), alloc, Uninitialized() )
315 {
316  std::uninitialized_copy( list.begin(), list.end(), begin_ );
317 }
318 //*************************************************************************************************
319 
320 
321 //*************************************************************************************************
326 template< typename T // Data type of the elements
327  , size_t N // Number of preallocated elements
328  , typename A > // Type of the allocator
330  : SmallArray( sa.size(), A(), Uninitialized() )
331 {
332  std::uninitialized_copy( sa.begin(), sa.end(), begin_ );
333 }
334 //*************************************************************************************************
335 
336 
337 //*************************************************************************************************
342 template< typename T // Data type of the elements
343  , size_t N // Number of preallocated elements
344  , typename A > // Type of the allocator
346  // Base class initialization is intentionally omitted
347  : begin_( sa.begin_ ) // Pointer to the beginning of the currently used storage
348  , end_ ( sa.end_ ) // Pointer to the end of the currently used storage
349  , final_( sa.final_ ) // Pointer to the very end of the currently used storage
350 {
351  if( !sa.isDynamic() ) {
352  begin_ = this->array();
353  end_ = begin_ + sa.size();
354  final_ = begin_ + N;
355  blaze::uninitialized_move( sa.begin_, sa.end_, begin_ );
356  blaze::destroy( sa.begin_, sa.end_ );
357  }
358 
359  sa.begin_ = sa.array();
360  sa.end_ = sa.begin_;
361  sa.final_ = sa.begin_ + N;
362 }
363 //*************************************************************************************************
364 
365 
366 //*************************************************************************************************
372 template< typename T // Data type of the elements
373  , size_t N // Number of preallocated elements
374  , typename A > // Type of the allocator
375 inline SmallArray<T,N,A>::SmallArray( size_t n, const A& alloc, Uninitialized )
376  // SmallArrayData is initialization
377  // begin_ is intentionally not initialized
378  // end_ is intentionally not initialized
379  // final_ is intentionally not initialized
380  : A( alloc ) // Base class initialization
381 {
382  if( n <= N ) {
383  begin_ = this->array();
384  end_ = begin_ + n;
385  final_ = begin_ + N;
386  }
387  else {
388  begin_ = allocate( n );
389  end_ = begin_ + n;
390  final_ = begin_ + n;
391  }
392 }
393 //*************************************************************************************************
394 
395 
396 
397 
398 //=================================================================================================
399 //
400 // DESTRUCTOR
401 //
402 //=================================================================================================
403 
404 //*************************************************************************************************
407 template< typename T // Data type of the elements
408  , size_t N // Number of preallocated elements
409  , typename A > // Type of the allocator
411 {
413 
414  if( isDynamic() ) {
415  deallocate( begin_, capacity() );
416  }
417 }
418 //*************************************************************************************************
419 
420 
421 
422 
423 
424 //=================================================================================================
425 //
426 // DATA ACCESS FUNCTIONS
427 //
428 //=================================================================================================
429 
430 //*************************************************************************************************
439 template< typename T // Data type of the elements
440  , size_t N // Number of preallocated elements
441  , typename A > // Type of the allocator
442 inline typename SmallArray<T,N,A>::Reference
443  SmallArray<T,N,A>::operator[]( size_t index ) noexcept
444 {
445  BLAZE_USER_ASSERT( index < size(), "Invalid small array access index" );
446  return begin_[index];
447 }
448 //*************************************************************************************************
449 
450 
451 //*************************************************************************************************
460 template< typename T // Data type of the elements
461  , size_t N // Number of preallocated elements
462  , typename A > // Type of the allocator
463 inline typename SmallArray<T,N,A>::ConstReference
464  SmallArray<T,N,A>::operator[]( size_t index ) const noexcept
465 {
466  BLAZE_USER_ASSERT( index < size(), "Invalid small array access index" );
467  return begin_[index];
468 }
469 //*************************************************************************************************
470 
471 
472 //*************************************************************************************************
482 template< typename T // Data type of the elements
483  , size_t N // Number of preallocated elements
484  , typename A > // Type of the allocator
485 inline typename SmallArray<T,N,A>::Reference
486  SmallArray<T,N,A>::at( size_t index )
487 {
488  if( index >= size() ) {
489  BLAZE_THROW_OUT_OF_RANGE( "Invalid small array access index" );
490  }
491  return begin_[index];
492 }
493 //*************************************************************************************************
494 
495 
496 //*************************************************************************************************
506 template< typename T // Data type of the elements
507  , size_t N // Number of preallocated elements
508  , typename A > // Type of the allocator
509 inline typename SmallArray<T,N,A>::ConstReference
510  SmallArray<T,N,A>::at( size_t index ) const
511 {
512  if( index >= size() ) {
513  BLAZE_THROW_OUT_OF_RANGE( "Invalid small array access index" );
514  }
515  return begin_[index];
516 }
517 //*************************************************************************************************
518 
519 
520 //*************************************************************************************************
527 template< typename T // Data type of the elements
528  , size_t N // Number of preallocated elements
529  , typename A > // Type of the allocator
530 inline typename SmallArray<T,N,A>::Pointer
532 {
533  return begin_;
534 }
535 //*************************************************************************************************
536 
537 
538 //*************************************************************************************************
545 template< typename T // Data type of the elements
546  , size_t N // Number of preallocated elements
547  , typename A > // Type of the allocator
548 inline typename SmallArray<T,N,A>::ConstPointer
549  SmallArray<T,N,A>::data() const noexcept
550 {
551  return begin_;
552 }
553 //*************************************************************************************************
554 
555 
556 //*************************************************************************************************
561 template< typename T // Data type of the elements
562  , size_t N // Number of preallocated elements
563  , typename A > // Type of the allocator
564 inline typename SmallArray<T,N,A>::Iterator
566 {
567  return begin_;
568 }
569 //*************************************************************************************************
570 
571 
572 //*************************************************************************************************
577 template< typename T // Data type of the elements
578  , size_t N // Number of preallocated elements
579  , typename A > // Type of the allocator
580 inline typename SmallArray<T,N,A>::ConstIterator
581  SmallArray<T,N,A>::begin() const noexcept
582 {
583  return begin_;
584 }
585 //*************************************************************************************************
586 
587 
588 //*************************************************************************************************
593 template< typename T // Data type of the elements
594  , size_t N // Number of preallocated elements
595  , typename A > // Type of the allocator
596 inline typename SmallArray<T,N,A>::ConstIterator
597  SmallArray<T,N,A>::cbegin() const noexcept
598 {
599  return begin_;
600 }
601 //*************************************************************************************************
602 
603 
604 //*************************************************************************************************
609 template< typename T // Data type of the elements
610  , size_t N // Number of preallocated elements
611  , typename A > // Type of the allocator
612 inline typename SmallArray<T,N,A>::Iterator
614 {
615  return end_;
616 }
617 //*************************************************************************************************
618 
619 
620 //*************************************************************************************************
625 template< typename T // Data type of the elements
626  , size_t N // Number of preallocated elements
627  , typename A > // Type of the allocator
628 inline typename SmallArray<T,N,A>::ConstIterator
629  SmallArray<T,N,A>::end() const noexcept
630 {
631  return end_;
632 }
633 //*************************************************************************************************
634 
635 
636 //*************************************************************************************************
641 template< typename T // Data type of the elements
642  , size_t N // Number of preallocated elements
643  , typename A > // Type of the allocator
644 inline typename SmallArray<T,N,A>::ConstIterator
645  SmallArray<T,N,A>::cend() const noexcept
646 {
647  return end_;
648 }
649 //*************************************************************************************************
650 
651 
652 
653 
654 //=================================================================================================
655 //
656 // ASSIGNMENT OPERATORS
657 //
658 //=================================================================================================
659 
660 //*************************************************************************************************
676 template< typename T // Data type of the elements
677  , size_t N // Number of preallocated elements
678  , typename A > // Type of the allocator
679 template< typename U > // Type of the initializer list elements
681 {
682  resize( list.size() );
683  std::copy( list.begin(), list.end(), begin_ );
684 
685  return *this;
686 }
687 //*************************************************************************************************
688 
689 
690 //*************************************************************************************************
699 template< typename T // Data type of the elements
700  , size_t N // Number of preallocated elements
701  , typename A > // Type of the allocator
703 {
704  resize( rhs.size() );
705  std::copy( rhs.begin(), rhs.end(), begin_ );
706 
707  return *this;
708 }
709 //*************************************************************************************************
710 
711 
712 //*************************************************************************************************
718 template< typename T // Data type of the elements
719  , size_t N // Number of preallocated elements
720  , typename A > // Type of the allocator
722 {
723  resize( rhs.size() );
724  std::move( rhs.begin_, rhs.end_, begin_ );
725  blaze::destroy( rhs.begin_, rhs.end_ );
726 
727  rhs.begin_ = rhs.array();
728  rhs.end_ = rhs.begin_;
729  rhs.final_ = rhs.begin_ + N;
730 
731  return *this;
732 }
733 //*************************************************************************************************
734 
735 
736 
737 
738 //=================================================================================================
739 //
740 // UTILITY FUNCTIONS
741 //
742 //=================================================================================================
743 
744 //*************************************************************************************************
749 template< typename T // Data type of the elements
750  , size_t N // Number of preallocated elements
751  , typename A > // Type of the allocator
752 inline bool SmallArray<T,N,A>::empty() const noexcept
753 {
754  return begin_ == end_;
755 }
756 //*************************************************************************************************
757 
758 
759 //*************************************************************************************************
764 template< typename T // Data type of the elements
765  , size_t N // Number of preallocated elements
766  , typename A > // Type of the allocator
767 inline size_t SmallArray<T,N,A>::size() const noexcept
768 {
769  return end_ - begin_;
770 }
771 //*************************************************************************************************
772 
773 
774 //*************************************************************************************************
779 template< typename T // Data type of the elements
780  , size_t N // Number of preallocated elements
781  , typename A > // Type of the allocator
782 inline size_t SmallArray<T,N,A>::capacity() const noexcept
783 {
784  return final_ - begin_;
785 }
786 //*************************************************************************************************
787 
788 
789 //*************************************************************************************************
796 template< typename T // Data type of the elements
797  , size_t N // Number of preallocated elements
798  , typename A > // Type of the allocator
800 {
802 
803  if( isDynamic() ) {
804  deallocate( begin_, capacity() );
805  }
806 
807  begin_ = this->array();
808  end_ = begin_;
809  final_ = begin_ + N;
810 }
811 //*************************************************************************************************
812 
813 
814 //*************************************************************************************************
824 template< typename T // Data type of the elements
825  , size_t N // Number of preallocated elements
826  , typename A > // Type of the allocator
828 {
829  if( n > size() )
830  {
831  reserve( n );
833  end_ = begin_ + n;
834  }
835  else if( n < size() )
836  {
837  blaze::destroy( begin_+n, end_ );
838  end_ = begin_ + n;
839  }
840 }
841 //*************************************************************************************************
842 
843 
844 //*************************************************************************************************
855 template< typename T // Data type of the elements
856  , size_t N // Number of preallocated elements
857  , typename A > // Type of the allocator
858 void SmallArray<T,N,A>::resize( size_t n, const T& value )
859 {
860  if( n > size() )
861  {
862  reserve( n );
863  std::uninitialized_fill( begin_+size(), begin_+n, value );
864  end_ = begin_ + n;
865  }
866  else if( n < size() )
867  {
868  blaze::destroy( begin_+n, end_ );
869  end_ = begin_ + n;
870  }
871 }
872 //*************************************************************************************************
873 
874 
875 //*************************************************************************************************
884 template< typename T // Data type of the elements
885  , size_t N // Number of preallocated elements
886  , typename A > // Type of the allocator
888 {
889  const size_t oldCapacity( capacity() );
890 
891  if( n > oldCapacity )
892  {
893  const size_t oldSize( size() );
894  T* tmp( allocate( n ) );
895 
896  if( IsNothrowMoveConstructible_v<T> ) {
898  }
899  else {
900  std::uninitialized_copy( begin_, end_, tmp );
901  }
902 
904 
905  if( isDynamic() ) {
906  deallocate( begin_, oldCapacity );
907  }
908 
909  final_ = tmp + n;
910  end_ = tmp + oldSize;
911  begin_ = tmp;
912  }
913 }
914 //*************************************************************************************************
915 
916 
917 //*************************************************************************************************
926 template< typename T // Data type of the elements
927  , size_t N // Number of preallocated elements
928  , typename A > // Type of the allocator
930 {
931  const size_t oldCapacity( capacity() );
932  const size_t oldSize ( size() );
933 
934  if( isDynamic() && oldCapacity > oldSize )
935  {
936  T* tmp( allocate( oldSize ) );
937 
938  if( IsNothrowMoveConstructible_v<T> ) {
940  }
941  else {
942  std::uninitialized_copy( begin_, end_, tmp );
943  }
944 
946  deallocate( begin_, oldCapacity );
947 
948  final_ = tmp + oldSize;
949  end_ = final_;
950  begin_ = tmp;
951  }
952 }
953 //*************************************************************************************************
954 
955 
956 //*************************************************************************************************
962 template< typename T // Data type of the elements
963  , size_t N // Number of preallocated elements
964  , typename A > // Type of the allocator
965 void SmallArray<T,N,A>::pushBack( const T& value )
966 {
967  using blaze::max;
968 
969  const size_t oldCapacity( capacity() );
970 
971  if( size() == oldCapacity ) {
972  reserve( max( 2UL*oldCapacity, 7UL ) );
973  }
974 
975  ::new ( end_ ) T( value );
976  ++end_;
977 }
978 //*************************************************************************************************
979 
980 
981 //*************************************************************************************************
987 template< typename T // Data type of the elements
988  , size_t N // Number of preallocated elements
989  , typename A > // Type of the allocator
991 {
992  using blaze::max;
993 
994  const size_t oldCapacity( capacity() );
995 
996  if( size() == oldCapacity ) {
997  reserve( max( 2UL*oldCapacity, 7UL ) );
998  }
999 
1000  ::new ( end_ ) T( std::move( value ) );
1001  ++end_;
1002 }
1003 //*************************************************************************************************
1004 
1005 
1006 //*************************************************************************************************
1013 template< typename T // Data type of the elements
1014  , size_t N // Number of preallocated elements
1015  , typename A > // Type of the allocator
1017  SmallArray<T,N,A>::insert( Iterator pos, const T& value )
1018 {
1019  const size_t oldCapacity( capacity() );
1020  const size_t oldSize ( size() );
1021 
1022  if( oldSize == oldCapacity )
1023  {
1024  const size_t newCapacity( max( 1UL, 2UL*oldCapacity ) );
1025  const size_t index( pos - begin_ );
1026 
1027  T* tmp ( allocate( newCapacity ) );
1028  T* newpos( tmp + index );
1029 
1030  blaze::uninitialized_move( begin_, pos, tmp );
1031  ::new ( newpos ) T( value );
1032  blaze::uninitialized_move( pos, end_, tmp+index+1UL );
1034 
1035  if( isDynamic() ) {
1036  deallocate( begin_, capacity() );
1037  }
1038 
1039  final_ = tmp + newCapacity;
1040  end_ = tmp + oldSize + 1UL;
1041  begin_ = tmp;
1042 
1043  return newpos;
1044  }
1045  else if( pos == end_ )
1046  {
1047  ::new( pos ) T( value );
1048  ++end_;
1049  return pos;
1050  }
1051  else
1052  {
1053  const auto tmp( end_ - 1UL );
1054  ::new ( end_ ) T( std::move( *tmp ) );
1055 
1056  try {
1057  std::move_backward( pos, tmp, end_ );
1058  blaze::destroy_at( pos );
1059  ::new ( pos ) T( value );
1060  ++end_;
1061  }
1062  catch( ... ) {
1064  throw;
1065  }
1066 
1067  return pos;
1068  }
1069 }
1070 //*************************************************************************************************
1071 
1072 
1073 //*************************************************************************************************
1080 template< typename T // Data type of the elements
1081  , size_t N // Number of preallocated elements
1082  , typename A > // Type of the allocator
1085 {
1086  const size_t oldCapacity( capacity() );
1087  const size_t oldSize ( size() );
1088 
1089  if( oldSize == oldCapacity )
1090  {
1091  const size_t newCapacity( max( 1UL, 2UL*oldCapacity ) );
1092  const size_t index( pos - begin_ );
1093 
1094  T* tmp ( allocate( newCapacity ) );
1095  T* newpos( tmp + index );
1096 
1097  blaze::uninitialized_move( begin_, pos, tmp );
1098  ::new ( newpos ) T( std::move( value ) );
1099  blaze::uninitialized_move( pos, end_, tmp+index+1UL );
1101 
1102  if( isDynamic() ) {
1103  deallocate( begin_, capacity() );
1104  }
1105 
1106  final_ = tmp + newCapacity;
1107  end_ = tmp + oldSize + 1UL;
1108  begin_ = tmp;
1109 
1110  return newpos;
1111  }
1112  else if( pos == end_ )
1113  {
1114  ::new( pos ) T( std::move( value ) );
1115  ++end_;
1116  return pos;
1117  }
1118  else
1119  {
1120  const auto tmp( end_ - 1UL );
1121  ::new ( end_ ) T( std::move( *tmp ) );
1122 
1123  try {
1124  std::move_backward( pos, tmp, end_ );
1125  blaze::destroy_at( pos );
1126  ::new ( pos ) T( std::move( value ) );
1127  ++end_;
1128  }
1129  catch( ... ) {
1131  throw;
1132  }
1133 
1134  return pos;
1135  }
1136 }
1137 //*************************************************************************************************
1138 
1139 
1140 //*************************************************************************************************
1148 template< typename T // Data type of the elements
1149  , size_t N // Number of preallocated elements
1150  , typename A > // Type of the allocator
1153 {
1154  std::move( pos+1UL, end_, pos );
1155  --end_;
1157 
1158  return pos;
1159 }
1160 //*************************************************************************************************
1161 
1162 
1163 //*************************************************************************************************
1172 template< typename T // Data type of the elements
1173  , size_t N // Number of preallocated elements
1174  , typename A > // Type of the allocator
1177 {
1178  BLAZE_USER_ASSERT( first <= last, "Invalid range detected" );
1179 
1180  const size_t n( last - first );
1181 
1182  std::move( last, end_, first );
1183  end_ -= n;
1184  blaze::destroy( end_, end_+n );
1185 
1186  return first;
1187 }
1188 //*************************************************************************************************
1189 
1190 
1191 //*************************************************************************************************
1201 template< typename T // Data type of the elements
1202  , size_t N // Number of preallocated elements
1203  , typename A > // Type of the allocator
1204 void SmallArray<T,N,A>::swap( SmallArray& sa ) noexcept( IsNothrowMoveConstructible_v<T> )
1205 {
1206  using std::swap;
1207 
1208  if( isDynamic() && sa.isDynamic() )
1209  {
1210  swap( begin_, sa.begin_ );
1211  swap( end_ , sa.end_ );
1212  swap( final_, sa.final_ );
1213  }
1214  else if( isDynamic() )
1215  {
1216  const size_t n( sa.size() );
1217 
1218  blaze::uninitialized_move( sa.begin_, sa.end_, this->array() );
1219  blaze::destroy( sa.begin_, sa.end_ );
1220 
1221  sa.begin_ = begin_;
1222  sa.end_ = end_;
1223  sa.final_ = final_;
1224 
1225  begin_ = this->array();
1226  end_ = begin_ + n;
1227  final_ = begin_ + N;
1228  }
1229  else if( sa.isDynamic() )
1230  {
1231  const size_t n( size() );
1232 
1233  blaze::uninitialized_move( begin_, end_, sa.array() );
1235 
1236  begin_ = sa.begin_;
1237  end_ = sa.end_;
1238  final_ = sa.final_;
1239 
1240  sa.begin_ = sa.array();
1241  sa.end_ = sa.begin_ + n;
1242  sa.final_ = sa.begin_ + N;
1243  }
1244  else if( size() > sa.size() )
1245  {
1246  const size_t n( size() - sa.size() );
1247  const auto pos = std::swap_ranges( sa.begin_, sa.end_, begin_ );
1248 
1249  blaze::uninitialized_move( pos, end_, sa.end_ );
1250  blaze::destroy( pos, end_ );
1251  end_ -= n;
1252  sa.end_ += n;
1253  }
1254  else
1255  {
1256  const size_t n( sa.size() - size() );
1257  const auto pos = std::swap_ranges( begin_, end_, sa.begin_ );
1258 
1259  blaze::uninitialized_move( pos, sa.end_, end_ );
1260  blaze::destroy( pos, sa.end_ );
1261  end_ += n;
1262  sa.end_ -= n;
1263  }
1264 }
1265 //*************************************************************************************************
1266 
1267 
1268 //*************************************************************************************************
1273 template< typename T // Data type of the elements
1274  , size_t N // Number of preallocated elements
1275  , typename A > // Type of the allocator
1276 inline bool SmallArray<T,N,A>::isDynamic() const noexcept
1277 {
1278  return ( N == 0UL || begin_ != this->array() );
1279 }
1280 //*************************************************************************************************
1281 
1282 
1283 
1284 
1285 //=================================================================================================
1286 //
1287 // SMALLARRAY OPERATORS
1288 //
1289 //=================================================================================================
1290 
1291 //*************************************************************************************************
1294 template< typename T1, size_t N1, typename A1, typename T2, size_t N2, typename A2 >
1295 inline bool operator==( const SmallArray<T1,N1,A1>& lhs, const SmallArray<T2,N2,A2>& rhs );
1296 
1297 template< typename T1, size_t N1, typename A1, typename T2, size_t N2, typename A2 >
1298 inline bool operator!=( const SmallArray<T1,N1,A1>& lhs, const SmallArray<T2,N2,A2>& rhs );
1299 
1300 template< typename T, size_t N, typename A >
1301 inline typename SmallArray<T,N,A>::Iterator begin( SmallArray<T,N,A>& sa );
1302 
1303 template< typename T, size_t N, typename A >
1304 inline typename SmallArray<T,N,A>::ConstIterator begin( const SmallArray<T,N,A>& sa );
1305 
1306 template< typename T, size_t N, typename A >
1307 inline typename SmallArray<T,N,A>::ConstIterator cbegin( const SmallArray<T,N,A>& sa );
1308 
1309 template< typename T, size_t N, typename A >
1310 inline typename SmallArray<T,N,A>::Iterator end( SmallArray<T,N,A>& sa );
1311 
1312 template< typename T, size_t N, typename A >
1313 inline typename SmallArray<T,N,A>::ConstIterator end( const SmallArray<T,N,A>& sa );
1314 
1315 template< typename T, size_t N, typename A >
1316 inline typename SmallArray<T,N,A>::ConstIterator cend( const SmallArray<T,N,A>& sa );
1317 
1318 template< typename T, size_t N, typename A >
1319 inline void clear( SmallArray<T,N,A>& sa );
1320 
1321 template< typename T, size_t N, typename A >
1322 inline void swap( SmallArray<T,N,A>& a, SmallArray<T,N,A>& b )
1323  noexcept( IsNothrowMoveConstructible_v<T> );
1325 //*************************************************************************************************
1326 
1327 
1328 //*************************************************************************************************
1336 template< typename T1 // Data type of the elements of the left-hand side array
1337  , size_t N1 // Number of elements of the left-hand side array
1338  , typename A1 // Type of the allocator of the left-hand side array
1339  , typename T2 // Data type of the elements of the right-hand side array
1340  , size_t N2 // Number of elements of the right-hand side array
1341  , typename A2 > // Type of the allocator of the right-hand side array
1342 inline bool operator==( const SmallArray<T1,N1,A1>& lhs, const SmallArray<T2,N2,A2>& rhs )
1343 {
1344  if( lhs.size() != rhs.size() ) return false;
1345 
1346  return std::equal( lhs.begin(), lhs.end(), rhs.begin() );
1347 }
1348 //*************************************************************************************************
1349 
1350 
1351 //*************************************************************************************************
1359 template< typename T1 // Data type of the elements of the left-hand side array
1360  , size_t N1 // Number of elements of the left-hand side array
1361  , typename A1 // Type of the allocator of the left-hand side array
1362  , typename T2 // Data type of the elements of the right-hand side array
1363  , size_t N2 // Number of elements of the right-hand side array
1364  , typename A2 > // Type of the allocator of the right-hand side array
1365 inline bool operator!=( const SmallArray<T1,N1,A1>& lhs, const SmallArray<T2,N2,A2>& rhs )
1366 {
1367  return !( lhs == rhs );
1368 }
1369 //*************************************************************************************************
1370 
1371 
1372 //*************************************************************************************************
1379 template< typename T, size_t N, typename A >
1381 {
1382  return sa.begin();
1383 }
1384 //*************************************************************************************************
1385 
1386 
1387 //*************************************************************************************************
1394 template< typename T, size_t N, typename A >
1396 {
1397  return sa.begin();
1398 }
1399 //*************************************************************************************************
1400 
1401 
1402 //*************************************************************************************************
1409 template< typename T, size_t N, typename A >
1411 {
1412  return sa.begin();
1413 }
1414 //*************************************************************************************************
1415 
1416 
1417 //*************************************************************************************************
1424 template< typename T, size_t N, typename A >
1426 {
1427  return sa.end();
1428 }
1429 //*************************************************************************************************
1430 
1431 
1432 //*************************************************************************************************
1439 template< typename T, size_t N, typename A >
1441 {
1442  return sa.end();
1443 }
1444 //*************************************************************************************************
1445 
1446 
1447 //*************************************************************************************************
1454 template< typename T, size_t N, typename A >
1456 {
1457  return sa.end();
1458 }
1459 //*************************************************************************************************
1460 
1461 
1462 //*************************************************************************************************
1469 template< typename T // Data type of the elements
1470  , size_t N // Number of preallocated elements
1471  , typename A > // Type of the allocator
1472 inline void clear( SmallArray<T,N,A>& sa )
1473 {
1474  sa.clear();
1475 }
1476 //*************************************************************************************************
1477 
1478 
1479 //*************************************************************************************************
1491 template< typename T // Data type of the elements
1492  , size_t N // Number of preallocated elements
1493  , typename A > // Type of the allocator
1495  noexcept( IsNothrowMoveConstructible_v<T> )
1496 {
1497  a.swap( b );
1498 }
1499 //*************************************************************************************************
1500 
1501 } // namespace blaze
1502 
1503 #endif
#define BLAZE_CONSTRAINT_MUST_NOT_BE_CONST(T)
Constraint on the data type.In case the given data type is a const-qualified type, a compilation error is created.
Definition: Const.h:79
Headerfile for the generic destroy algorithm.
Definition of the nested auxiliary struct Uninitialized.
Definition: SmallArray.h:176
const T * ConstIterator
Iterator over constant elements.
Definition: SmallArray.h:93
#define BLAZE_USER_ASSERT(expr, msg)
Run time assertion macro for user checks.In case of an invalid run time expression, the program execution is terminated. The BLAZE_USER_ASSERT macro can be disabled by setting the BLAZE_USER_ASSERT flag to zero or by defining NDEBUG during the compilation.
Definition: Assert.h:117
size_t capacity(const Matrix< MT, SO > &matrix) noexcept
Returns the maximum capacity of the matrix.
Definition: Matrix.h:546
Header file for basic type definitions.
Reference operator[](size_t index) noexcept
Subscript operator for the direct access to the array elements.
Definition: SmallArray.h:443
MT::Iterator begin(Matrix< MT, SO > &matrix, size_t i)
Returns an iterator to the first element of row/column i.
Definition: Matrix.h:372
Header file for exception macros.
Iterator insert(Iterator pos, const T &value)
Inserting an element at the specified position into the small array.
Definition: SmallArray.h:1017
T ElementType
Type of the array elements.
Definition: SmallArray.h:87
#define BLAZE_CONSTRAINT_MUST_NOT_BE_VOLATILE(T)
Constraint on the data type.In case the given data type is a volatile-qualified type, a compilation error is created.
Definition: Volatile.h:79
~SmallArray()
The destructor for SmallArray.
Definition: SmallArray.h:410
STL namespace.
bool isDynamic() const noexcept
Returns whether the small array uses its dynamic storage.
Definition: SmallArray.h:1276
const T & ConstReference
Reference to a constant array element.
Definition: SmallArray.h:91
void clear()
Clearing the array.
Definition: SmallArray.h:799
MT::ConstIterator cend(const Matrix< MT, SO > &matrix, size_t i)
Returns an iterator just past the last element of row/column i.
Definition: Matrix.h:482
MT::ConstIterator cbegin(const Matrix< MT, SO > &matrix, size_t i)
Returns an iterator to the first element of row/column i.
Definition: Matrix.h:416
void swap(SmallArray &sa) noexcept(IsNothrowMoveConstructible_v< T >)
Swapping the contents of two small arrays.
Definition: SmallArray.h:1204
bool empty() const noexcept
Returns whether the array is empty.
Definition: SmallArray.h:752
Header file for the initializer_list template.
constexpr bool IsNothrowMoveConstructible_v
Auxiliary variable template for the IsNothrowMoveConstructible type trait.The IsNothrowMoveConstructi...
Definition: IsConstructible.h:427
Headerfile for the generic max algorithm.
Headerfile for the generic uninitialized_default_construct algorithm.
Namespace of the Blaze C++ math library.
Definition: Blaze.h:58
void swap(CompressedMatrix< Type, SO > &a, CompressedMatrix< Type, SO > &b) noexcept
Swapping the contents of two compressed matrices.
Definition: CompressedMatrix.h:5907
Headerfile for the generic destroy_at algorithm.
Reference at(size_t index)
Checked access to the array elements.
Definition: SmallArray.h:486
T * begin_
Pointer to the beginning of the currently used storage.
Definition: SmallArray.h:199
Headerfile for the generic uninitialized_move algorithm.
Implementation of a dynamic array with small array optimization.The SmallArray class template is a hy...
Definition: SmallArray.h:81
Pointer data() noexcept
Low-level data access to the array elements.
Definition: SmallArray.h:531
ForwardIt uninitialized_move(InputIt first, InputIt last, ForwardIt dest)
Move the elements from the given source range to the uninitialized destination range.
Definition: UninitializedMove.h:70
Iterator * end_
Pointers one past the last non-zero element of each column.
Definition: CompressedMatrix.h:3293
#define BLAZE_THROW_OUT_OF_RANGE(MESSAGE)
Macro for the emission of a std::out_of_range exception.This macro encapsulates the default way of Bl...
Definition: Exception.h:331
constexpr bool operator==(const NegativeAccuracy< A > &lhs, const T &rhs)
Equality comparison between a NegativeAccuracy object and a floating point value. ...
Definition: Accuracy.h:253
Constraint on the data type.
Header file for the IsConstructible type trait.
void reserve(size_t n)
Setting the minimum capacity of the array.
Definition: SmallArray.h:887
Iterator erase(Iterator pos)
Erasing an element from the small array.
Definition: SmallArray.h:1152
decltype(auto) max(const DenseMatrix< MT1, SO1 > &lhs, const DenseMatrix< MT2, SO2 > &rhs)
Computes the componentwise maximum of the dense matrices lhs and rhs.
Definition: DMatDMatMapExpr.h:1179
void resize(Matrix< MT, SO > &matrix, size_t rows, size_t columns, bool preserve=true)
Changing the size of the matrix.
Definition: Matrix.h:738
MT::Iterator end(Matrix< MT, SO > &matrix, size_t i)
Returns an iterator just past the last element of row/column i.
Definition: Matrix.h:438
constexpr bool operator!=(const NegativeAccuracy< A > &lhs, const T &rhs)
Inequality comparison between a NegativeAccuracy object and a floating point value.
Definition: Accuracy.h:293
ConstIterator cbegin() const noexcept
Returns an iterator to the first element of the small array.
Definition: SmallArray.h:597
void clear(const DiagonalProxy< MT > &proxy)
Clearing the represented element.
Definition: DiagonalProxy.h:611
void destroy(ForwardIt first, ForwardIt last)
Destroys the given range of objects .
Definition: Destroy.h:66
void resize(size_t n)
Changing the size of the array.
Definition: SmallArray.h:827
T * end_
Pointer to the end of the currently used storage.
Definition: SmallArray.h:200
void pushBack(const T &value)
Adding an element to the end of the small array.
Definition: SmallArray.h:965
size_t size() const noexcept
Returns the current size/dimension of the small array.
Definition: SmallArray.h:767
Header file for run time assertion macros.
Iterator begin() noexcept
Returns an iterator to the first element of the small array.
Definition: SmallArray.h:565
void shrinkToFit()
Requesting the removal of unused capacity.
Definition: SmallArray.h:929
Constraint on the data type.
size_t capacity() const noexcept
Returns the maximum capacity of the small array.
Definition: SmallArray.h:782
void swap(DiagonalMatrix< MT, SO, DF > &a, DiagonalMatrix< MT, SO, DF > &b) noexcept
Swapping the contents of two matrices.
Definition: DiagonalMatrix.h:281
constexpr size_t size(const Matrix< MT, SO > &matrix) noexcept
Returns the total number of elements of the matrix.
Definition: Matrix.h:530
SmallArray(const A &alloc=A())
The (default) constructor for SmallArray.
Definition: SmallArray.h:231
Header file for the IsAssignable type trait.
Iterator * begin_
Pointers to the first non-zero element of each column.
Definition: CompressedMatrix.h:3292
T & Reference
Reference to a non-constant array element.
Definition: SmallArray.h:90
void uninitialized_default_construct(ForwardIt first, ForwardIt last)
Default constructs elements in the given range.
Definition: UninitializedDefaultConstruct.h:67
T * Iterator
Iterator over non-constant elements.
Definition: SmallArray.h:92
EnableIf_t< IsBuiltin_v< T > > deallocate(T *address) noexcept
Deallocation of memory for built-in data types.
Definition: Memory.h:224
T * Pointer
Pointer to a non-constant array element.
Definition: SmallArray.h:88
Iterator end() noexcept
Returns an iterator just past the last element of the small array.
Definition: SmallArray.h:613
Initializer list type of the Blaze library.
Header file for the SmallArrayData class template.
void destroy_at(T *p) noexcept
Destroys the object at the given address.
Definition: DestroyAt.h:57
ConstIterator cend() const noexcept
Returns an iterator just past the last element of the small array.
Definition: SmallArray.h:645
EnableIf_t< IsBuiltin_v< T >, T *> allocate(size_t size)
Aligned array allocation for built-in data types.
Definition: Memory.h:156
T * final_
Pointer to the very end of the currently used storage.
Definition: SmallArray.h:201
bool equal(const SharedValue< T1 > &lhs, const SharedValue< T2 > &rhs)
Equality check for a two shared values.
Definition: SharedValue.h:342
const T * ConstPointer
Pointer to a constant array element.
Definition: SmallArray.h:89