17 #ifndef dealii_aligned_vector_h
18 #define dealii_aligned_vector_h
20 #include <deal.II/base/config.h>
22 #include <deal.II/base/exceptions.h>
23 #include <deal.II/base/memory_consumption.h>
24 #include <deal.II/base/parallel.h>
25 #include <deal.II/base/utilities.h>
29 #include <boost/version.hpp>
30 #if BOOST_VERSION >= 106400
31 # include <boost/serialization/array_wrapper.hpp>
33 # include <boost/serialization/array.hpp>
35 #include <boost/serialization/split_member.hpp>
38 #include <type_traits>
42 DEAL_II_NAMESPACE_OPEN
75 using size_type = std::size_t;
146 resize(
const size_type size_in);
164 resize(
const size_type size_in,
const T &init);
175 reserve(
const size_type size_alloc);
208 template <
typename ForwardIterator>
233 fill(
const T &element);
268 const_reference
operator[](
const size_type index)
const;
318 template <
class Archive>
320 save(Archive &ar,
const unsigned int version)
const;
326 template <
class Archive>
328 load(Archive &ar,
const unsigned int version);
330 BOOST_SERIALIZATION_SPLIT_MEMBER()
374 template <
typename T>
377 static const std::size_t minimum_parallel_grain_size =
378 160000 /
sizeof(T) + 1;
391 const T *
const source_end,
392 T *
const destination)
393 : source_(source_begin)
394 , destination_(destination)
397 Assert(source_end == source_begin || destination !=
nullptr,
399 const std::size_t
size = source_end - source_begin;
400 if (
size < minimum_parallel_grain_size)
401 AlignedVectorCopy::apply_to_subrange(0,
size);
403 apply_parallel(0,
size, minimum_parallel_grain_size);
412 const std::size_t
end)
const override
421 if (std::is_trivial<T>::value ==
true)
422 std::memcpy(static_cast<void *>(destination_ +
begin),
423 static_cast<const void *>(source_ +
begin),
426 for (std::size_t i =
begin; i <
end; ++i)
427 new (&destination_[i]) T(source_[i]);
431 const T *
const source_;
432 T *
const destination_;
441 template <
typename T>
444 static const std::size_t minimum_parallel_grain_size =
445 160000 /
sizeof(T) + 1;
459 T *
const destination)
460 : source_(source_begin)
461 , destination_(destination)
464 Assert(source_end == source_begin || destination !=
nullptr,
466 const std::size_t
size = source_end - source_begin;
467 if (
size < minimum_parallel_grain_size)
468 apply_to_subrange(0,
size);
470 apply_parallel(0,
size, minimum_parallel_grain_size);
479 const std::size_t
end)
const override
488 if (std::is_trivial<T>::value ==
true)
489 std::memcpy(static_cast<void *>(destination_ +
begin),
490 static_cast<void *>(source_ +
begin),
493 for (std::size_t i =
begin; i <
end; ++i)
497 new (&destination_[i]) T(std::move(source_[i]));
504 T *
const destination_;
519 template <
typename T,
bool initialize_memory>
522 static const std::size_t minimum_parallel_grain_size =
523 160000 /
sizeof(T) + 1;
532 T *
const destination)
534 , destination_(destination)
535 , trivial_element(false)
544 if (std::is_trivial<T>::value ==
true &&
545 std::is_same<T, long double>::value ==
false)
547 const unsigned char zero[
sizeof(T)] = {};
551 if (std::memcmp(zero,
552 static_cast<const void *>(&element),
554 trivial_element =
true;
556 if (
size < minimum_parallel_grain_size)
557 apply_to_subrange(0,
size);
559 apply_parallel(0,
size, minimum_parallel_grain_size);
567 const std::size_t
end)
const override
573 if (std::is_trivial<T>::value ==
true && trivial_element)
574 std::memset(static_cast<void *>(destination_ +
begin),
578 copy_construct_or_assign(
579 begin,
end, std::integral_constant<bool, initialize_memory>());
584 mutable T *destination_;
585 bool trivial_element;
589 copy_construct_or_assign(
const std::size_t
begin,
590 const std::size_t
end,
591 std::integral_constant<bool, false>)
const
593 for (std::size_t i =
begin; i <
end; ++i)
594 destination_[i] = element_;
599 copy_construct_or_assign(
const std::size_t
begin,
600 const std::size_t
end,
601 std::integral_constant<bool, true>)
const
603 for (std::size_t i =
begin; i <
end; ++i)
604 new (&destination_[i]) T(element_);
621 template <
typename T,
bool initialize_memory>
624 static const std::size_t minimum_parallel_grain_size =
625 160000 /
sizeof(T) + 1;
633 : destination_(destination)
639 if (
size < minimum_parallel_grain_size)
640 apply_to_subrange(0,
size);
642 apply_parallel(0,
size, minimum_parallel_grain_size);
650 const std::size_t
end)
const override
656 if (std::is_trivial<T>::value ==
true)
657 std::memset(static_cast<void *>(destination_ +
begin),
661 default_construct_or_assign(
662 begin,
end, std::integral_constant<bool, initialize_memory>());
666 mutable T *destination_;
670 default_construct_or_assign(
const std::size_t
begin,
671 const std::size_t
end,
672 std::integral_constant<bool, false>)
const
674 for (std::size_t i =
begin; i <
end; ++i)
675 destination_[i] = std::move(T());
680 default_construct_or_assign(
const std::size_t
begin,
681 const std::size_t
end,
682 std::integral_constant<bool, true>)
const
684 for (std::size_t i =
begin; i <
end; ++i)
685 new (&destination_[i]) T;
706 : data_begin(nullptr)
708 , allocated_end(nullptr)
726 : data_begin(nullptr)
728 , allocated_end(nullptr)
732 data_end = allocated_end;
740 : data_begin(vec.data_begin)
741 , data_end(vec.data_end)
742 , allocated_end(vec.allocated_end)
745 vec.data_end =
nullptr;
746 vec.allocated_end =
nullptr;
769 data_begin = vec.data_begin;
770 data_end = vec.data_end;
771 allocated_end = vec.allocated_end;
773 vec.data_begin =
nullptr;
774 vec.data_end =
nullptr;
775 vec.allocated_end =
nullptr;
787 if (std::is_trivial<T>::value ==
false && size_in < old_size)
792 while (data_end != data_begin + size_in)
796 data_end = data_begin + size_in;
800 if (std::is_trivial<T>::value ==
false && size_in > old_size)
802 size_in - old_size, data_begin + old_size);
812 if (std::is_trivial<T>::value ==
false && size_in < old_size)
817 while (data_end != data_begin + size_in)
821 data_end = data_begin + size_in;
824 if (size_in > old_size)
826 size_in - old_size, data_begin + old_size);
836 if (std::is_trivial<T>::value ==
false && size_in < old_size)
841 while (data_end != data_begin + size_in)
845 data_end = data_begin + size_in;
848 if (size_in > old_size)
851 data_begin + old_size);
860 const size_type old_size = data_end - data_begin;
861 const size_type allocated_size = allocated_end - data_begin;
862 if (size_alloc > allocated_size)
868 if (size_alloc < (2 * allocated_size))
869 new_size = 2 * allocated_size;
871 const size_type size_actual_allocate = new_size *
sizeof(T);
878 size_actual_allocate);
883 data_end = data_begin + old_size;
884 allocated_end = data_begin + new_size;
885 if (data_end != data_begin)
895 else if (size_alloc == 0)
905 if (data_begin !=
nullptr)
907 if (std::is_trivial<T>::value ==
false)
908 while (data_end != data_begin)
913 data_begin =
nullptr;
915 allocated_end =
nullptr;
925 if (data_end == allocated_end)
926 reserve(std::max(2 * capacity(), static_cast<size_type>(16)));
927 if (std::is_trivial<T>::value ==
false)
928 new (data_end++) T(in_data);
930 *data_end++ = in_data;
936 inline typename AlignedVector<T>::reference
940 T *field = data_end - 1;
947 inline typename AlignedVector<T>::const_reference
951 const T *field = data_end - 1;
958 template <
typename ForwardIterator>
962 const unsigned int old_size = size();
963 reserve(old_size + (end - begin));
964 for (; begin != end; ++begin, ++data_end)
966 if (std::is_trivial<T>::value ==
false)
1008 return data_end == data_begin;
1014 inline typename AlignedVector<T>::size_type
1017 return data_end - data_begin;
1023 inline typename AlignedVector<T>::size_type
1026 return allocated_end - data_begin;
1036 return data_begin[index];
1046 return data_begin[index];
1051 template <
typename T>
1052 inline typename AlignedVector<T>::pointer
1060 template <
typename T>
1061 inline typename AlignedVector<T>::const_pointer
1070 inline typename AlignedVector<T>::iterator
1079 inline typename AlignedVector<T>::iterator
1088 inline typename AlignedVector<T>::const_iterator
1097 inline typename AlignedVector<T>::const_iterator
1106 template <
class Archive>
1113 ar &boost::serialization::make_array(data_begin, vec_size);
1119 template <
class Archive>
1129 ar &boost::serialization::make_array(data_begin, vec_size);
1130 data_end = data_begin + vec_size;
1137 inline typename AlignedVector<T>::size_type
1141 for (
const T *t = data_begin; t != data_end; ++t)
1143 memory +=
sizeof(T) * (allocated_end - data_end);
1148 #endif // ifndef DOXYGEN
1162 for (
typename AlignedVector<T>::const_iterator lit = lhs.
begin(),
1186 DEAL_II_NAMESPACE_CLOSE