18#ifndef itkVariableLengthVector_h
19#define itkVariableLengthVector_h
33template <
typename TExpr1,
typename TExpr2,
typename TBinaryOp>
34struct VariableLengthVectorExpression;
90template <
typename TValue>
110 struct AllocateRootPolicy
126 struct AlwaysReallocate : AllocateRootPolicy
129 operator()(
unsigned int itkNotUsed(newSize),
unsigned int itkNotUsed(oldSize))
const
152 struct NeverReallocate : AllocateRootPolicy
155 operator()([[maybe_unused]]
unsigned int newSize, [[maybe_unused]]
unsigned int oldSize)
const
157 itkAssertInDebugAndIgnoreInReleaseMacro(newSize == oldSize &&
158 "SetSize is expected to never change the VariableLengthVector size...");
180 struct ShrinkToFit : AllocateRootPolicy
183 operator()(
unsigned int newSize,
unsigned int oldSize)
const
185 return newSize != oldSize;
215 struct DontShrinkToFit : AllocateRootPolicy
218 operator()(
unsigned int newSize,
unsigned int oldSize)
const
220 return newSize > oldSize;
242 struct KeepValuesRootPolicy
266 struct KeepOldValues : KeepValuesRootPolicy
268 template <
typename TValue2>
270 operator()(
unsigned int newSize,
unsigned int oldSize, TValue2 * oldBuffer, TValue2 * newBuffer)
const
272 const size_t nb = std::min(newSize, oldSize);
275 itkAssertInDebugAndIgnoreInReleaseMacro(newBuffer);
276 itkAssertInDebugAndIgnoreInReleaseMacro(oldBuffer);
277 std::copy_n(oldBuffer, nb, newBuffer);
298 struct DumpOldValues : KeepValuesRootPolicy
300 template <
typename TValue2>
302 operator()(
unsigned int itkNotUsed(newSize),
303 unsigned int itkNotUsed(oldSize),
304 TValue2 * itkNotUsed(oldBuffer),
305 TValue2 * itkNotUsed(newBuffer))
const
312 using ValueType = TValue;
313 using ComponentType = TValue;
314 using RealValueType =
typename NumericTraits<ValueType>::RealType;
315 using Self = VariableLengthVector;
318 using ElementIdentifier =
unsigned int;
321 using value_type = TValue;
322 using reference = TValue &;
323 using const_reference =
const TValue &;
324 using iterator = TValue *;
325 using const_iterator =
const TValue *;
326 using difference_type = ptrdiff_t;
327 using size_type = size_t;
328 using reverse_iterator = std::reverse_iterator<iterator>;
329 using const_reverse_iterator = std::reverse_iterator<const_iterator>;
337 VariableLengthVector() =
default;
347 explicit VariableLengthVector(
unsigned int length);
350 explicit VariableLengthVector(
unsigned int length,
const TValue & value);
365 VariableLengthVector(ValueType * datain,
unsigned int sz,
bool LetArrayManageMemory =
false);
386 VariableLengthVector(
const ValueType * datain,
unsigned int sz,
bool LetArrayManageMemory =
false);
407 template <
typename T>
408 VariableLengthVector(
const VariableLengthVector<T> & v)
409 : VariableLengthVector(v.Size())
411 if (m_NumElements != 0)
413 itkAssertInDebugAndIgnoreInReleaseMacro(m_Data !=
nullptr);
414 for (ElementIdentifier i = 0; i < m_NumElements; ++i)
416 this->m_Data[i] =
static_cast<ValueType
>(v[i]);
433 VariableLengthVector(
const VariableLengthVector<TValue> & v);
444 Swap(Self & v)
noexcept
446 itkAssertInDebugAndIgnoreInReleaseMacro(m_LetArrayManageMemory == v.m_LetArrayManageMemory);
448 swap(v.m_Data, m_Data);
449 swap(v.m_NumElements, m_NumElements);
459 VariableLengthVector(Self && v)
noexcept;
470 operator=(Self && v)
noexcept;
488 template <
typename TExpr1,
typename TExpr2,
typename TBinaryOp>
489 VariableLengthVector(
const VariableLengthVectorExpression<TExpr1, TExpr2, TBinaryOp> & rhs);
510 template <
typename TExpr1,
typename TExpr2,
typename TBinaryOp>
512 operator=(
const VariableLengthVectorExpression<TExpr1, TExpr2, TBinaryOp> & rhs);
518 Fill(
const TValue & v);
532 template <
typename T>
534 operator=(
const VariableLengthVector<T> & v)
543 const ElementIdentifier N = v.Size();
544 this->SetSize(N, DontShrinkToFit(), DumpOldValues());
545 for (ElementIdentifier i = 0; i < N; ++i)
547 this->m_Data[i] =
static_cast<ValueType
>(v[i]);
568 operator=(
const Self & v);
579 FastAssign(
const Self & v);
589 operator=(
const TValue & v);
593 [[nodiscard]]
unsigned int
596 return m_NumElements;
598 [[nodiscard]]
unsigned int
601 return m_NumElements;
603 [[nodiscard]]
unsigned int
604 GetNumberOfElements()
const
606 return m_NumElements;
611 operator[](
unsigned int i)
613 return this->m_Data[i];
618 operator[](
unsigned int i)
const
620 return this->m_Data[i];
624 [[nodiscard]]
const TValue &
625 GetElement(
unsigned int i)
const
632 SetElement(
unsigned int i,
const TValue & value)
670 template <
typename TReallocatePolicy,
typename TKeepValuesPolicy>
672 SetSize(
unsigned int sz, TReallocatePolicy reallocatePolicy, TKeepValuesPolicy keepValues);
685 SetSize(
unsigned int sz,
bool destroyExistingData =
true)
690 if (destroyExistingData)
692 SetSize(sz, AlwaysReallocate(), KeepOldValues());
696 SetSize(sz, ShrinkToFit(), KeepOldValues());
703 DestroyExistingData();
718 SetData(TValue * datain,
bool LetArrayManageMemory =
false);
735 SetData(TValue * datain,
unsigned int sz,
bool LetArrayManageMemory =
false);
747 ~VariableLengthVector();
764 Reserve(ElementIdentifier size);
766#ifndef ITK_FUTURE_LEGACY_REMOVE
772 ITK_FUTURE_DEPRECATED(
"Please consider calling `std::make_unique<TValue[]>(size)` instead.")
773 [[nodiscard]] TValue *
774 AllocateElements(ElementIdentifier size)
const;
777 [[nodiscard]]
const TValue *
778 GetDataPointer()
const
788 for (ElementIdentifier i = 0; i < m_NumElements; ++i)
790 this->m_Data[i] -=
static_cast<ValueType
>(1.0);
799 for (ElementIdentifier i = 0; i < m_NumElements; ++i)
801 this->m_Data[i] +=
static_cast<ValueType
>(1.0);
835 template <
typename T>
837 operator-=(
const VariableLengthVector<T> & v)
839 itkAssertInDebugAndIgnoreInReleaseMacro(m_NumElements == v.GetSize());
840 for (ElementIdentifier i = 0; i < m_NumElements; ++i)
842 m_Data[i] -=
static_cast<ValueType
>(v[i]);
851 for (ElementIdentifier i = 0; i < m_NumElements; ++i)
866 template <
typename T>
868 operator+=(
const VariableLengthVector<T> & v)
870 itkAssertInDebugAndIgnoreInReleaseMacro(m_NumElements == v.GetSize());
871 for (ElementIdentifier i = 0; i < m_NumElements; ++i)
873 m_Data[i] +=
static_cast<ValueType
>(v[i]);
882 for (ElementIdentifier i = 0; i < m_NumElements; ++i)
898 template <
typename TExpr1,
typename TExpr2,
typename TBinaryOp>
900 operator+=(
const VariableLengthVectorExpression<TExpr1, TExpr2, TBinaryOp> & rhs)
902 itkAssertInDebugAndIgnoreInReleaseMacro(rhs.Size() == Size());
903 for (ElementIdentifier i = 0; i < m_NumElements; ++i)
905 m_Data[i] +=
static_cast<ValueType
>(rhs[i]);
919 template <
typename TExpr1,
typename TExpr2,
typename TBinaryOp>
921 operator-=(
const VariableLengthVectorExpression<TExpr1, TExpr2, TBinaryOp> & rhs)
923 itkAssertInDebugAndIgnoreInReleaseMacro(rhs.Size() == Size());
924 for (ElementIdentifier i = 0; i < m_NumElements; ++i)
926 m_Data[i] -=
static_cast<ValueType
>(rhs[i]);
936 template <
typename T>
940 const ValueType & sc =
static_cast<ValueType
>(s);
941 for (ElementIdentifier i = 0; i < m_NumElements; ++i)
954 for (ElementIdentifier i = 0; i < m_NumElements; ++i)
967 template <
typename T>
971 const RealValueType sc = s;
972 for (ElementIdentifier i = 0; i < m_NumElements; ++i)
974 m_Data[i] =
static_cast<ValueType
>(
static_cast<RealValueType
>(m_Data[i]) / sc);
989 ITK_UNEQUAL_OPERATOR_MEMBER_FUNCTION(Self);
992 [[nodiscard]] RealValueType
996 [[nodiscard]] RealValueType
997 GetSquaredNorm()
const;
1003 return !m_LetArrayManageMemory;
1007 empty() const noexcept
1009 return m_NumElements == 0;
1012 [[nodiscard]] size_type
1013 size() const noexcept
1015 return m_NumElements;
1018 [[nodiscard]] reference
1021 ExceptionThrowingBoundsCheck(pos);
1025 [[nodiscard]] const_reference
1026 at(size_type pos)
const
1028 ExceptionThrowingBoundsCheck(pos);
1032 [[nodiscard]] reference
1038 [[nodiscard]] const_reference
1044 [[nodiscard]] reference
1047 return m_Data[m_NumElements - 1];
1050 [[nodiscard]] const_reference
1053 return m_Data[m_NumElements - 1];
1056 [[nodiscard]] TValue *
1062 [[nodiscard]]
const TValue *
1063 data() const noexcept
1068 [[nodiscard]] const_iterator
1069 cbegin() const noexcept
1074 [[nodiscard]] iterator
1080 [[nodiscard]] const_iterator
1081 begin() const noexcept
1086 [[nodiscard]] const_iterator
1087 cend() const noexcept
1089 return m_Data + m_NumElements;
1092 [[nodiscard]] iterator
1095 return m_Data + m_NumElements;
1098 [[nodiscard]] const_iterator
1099 end() const noexcept
1104 [[nodiscard]] reverse_iterator
1107 return reverse_iterator{ end() };
1110 [[nodiscard]] const_reverse_iterator
1113 return const_reverse_iterator{ cend() };
1116 [[nodiscard]] const_reverse_iterator
1122 [[nodiscard]] reverse_iterator
1125 return reverse_iterator{ begin() };
1128 [[nodiscard]] const_reverse_iterator
1131 return const_reverse_iterator{ cbegin() };
1134 [[nodiscard]] const_reverse_iterator
1141 bool m_LetArrayManageMemory{
true };
1144 ElementIdentifier m_NumElements{ 0 };
1147 ExceptionThrowingBoundsCheck(size_type pos)
const
1149 if (pos >= m_NumElements)
1151 throw std::out_of_range(
"Out of range: `itk::VariableLengthVector::at` argument `pos` (which is " +
1152 std::to_string(pos) +
") should be less than `m_NumElements` (which is " +
1153 std::to_string(m_NumElements) +
")!");
1170template <
typename T>
1171struct IsArray : FalseType
1175template <
typename T>
1176struct IsArray<itk::VariableLengthVector<T>> : TrueType
1179template <
typename TExpr1,
typename TExpr2,
typename TBinaryOp>
1180struct IsArray<VariableLengthVectorExpression<TExpr1, TExpr2, TBinaryOp>> : TrueType
1201template <
typename TExpr>
1210 Load(
const Type & v,
unsigned int itkNotUsed(idx))
1226template <
typename TExpr1,
typename TExpr2>
1227inline std::enable_if_t<mpl::And<mpl::IsArray<TExpr1>, mpl::IsArray<TExpr2>>::Value,
unsigned int>
1228GetSize(
const TExpr1 & lhs, [[maybe_unused]]
const TExpr2 & rhs)
1230 itkAssertInDebugAndIgnoreInReleaseMacro(lhs.Size() == rhs.Size());
1244template <
typename TExpr1,
typename TExpr2>
1245inline std::enable_if_t<mpl::And<mpl::IsArray<TExpr1>, mpl::Not<mpl::IsArray<TExpr2>>>::Value,
unsigned int>
1246GetSize(
const TExpr1 & lhs,
const TExpr2 & itkNotUsed(rhs))
1260template <
typename TExpr1,
typename TExpr2>
1261inline std::enable_if_t<mpl::And<mpl::IsArray<TExpr2>, mpl::Not<mpl::IsArray<TExpr1>>>::Value,
unsigned int>
1262GetSize(
const TExpr1 & itkNotUsed(lhs),
const TExpr2 & rhs)
1267template <
typename T>
1268struct GetType<VariableLengthVector<T>>
1272 Load(
const VariableLengthVector<T> & v,
unsigned int idx)
1277template <
typename TExpr1,
typename TExpr2,
typename TBinaryOp>
1278struct GetType<VariableLengthVectorExpression<TExpr1, TExpr2, TBinaryOp>>
1280 using Type =
typename VariableLengthVectorExpression<TExpr1, TExpr2, TBinaryOp>::ResType;
1282 Load(
const VariableLengthVectorExpression<TExpr1, TExpr2, TBinaryOp> & v,
unsigned int idx)
1303template <
typename TExpr1,
typename TExpr2>
1304struct CanBeAddedOrSubtracted
1305 : mpl::Or<mpl::And<mpl::IsArray<TExpr1>, mpl::IsArray<TExpr2>>,
1306 mpl::AndC<mpl::IsArray<TExpr1>::Value, std::is_arithmetic_v<TExpr2>>,
1307 mpl::AndC<std::is_arithmetic_v<TExpr1>, mpl::IsArray<TExpr2>::Value>>
1321template <
typename TExpr1,
typename TExpr2>
1322struct CanBeMultiplied
1323 : mpl::Or<mpl::AndC<mpl::IsArray<TExpr1>::Value, std::is_arithmetic_v<TExpr2>>,
1324 mpl::AndC<std::is_arithmetic_v<TExpr1>, mpl::IsArray<TExpr2>::Value>>
1338template <
typename TExpr1,
typename TExpr2>
1339struct CanBeDivided : mpl::AndC<mpl::IsArray<TExpr1>::Value, std::is_arithmetic_v<TExpr2>>
1370template <
typename TExpr1,
typename TExpr2,
typename TBinaryOp>
1371struct VariableLengthVectorExpression
1373 VariableLengthVectorExpression(
const TExpr1 & lhs,
const TExpr2 & rhs)
1379 static_assert(std::is_base_of_v<Details::op::BinaryOperationConcept, TBinaryOp>,
1380 "The Binary Operation shall inherit from BinaryOperationConcept");
1384 [[nodiscard]]
unsigned int
1387 return Details::GetSize(m_lhs, m_rhs);
1392 typename mpl::PromoteType<typename Details::GetType<TExpr1>::Type,
typename Details::GetType<TExpr2>::Type>::Type;
1394 using RealValueType =
typename NumericTraits<ResType>::RealType;
1407 operator[](
unsigned int idx)
const
1409 itkAssertInDebugAndIgnoreInReleaseMacro(idx < Size());
1410 return TBinaryOp::Apply(Details::GetType<TExpr1>::Load(m_lhs, idx), Details::GetType<TExpr2>::Load(m_rhs, idx));
1414 [[nodiscard]] RealValueType
1418 [[nodiscard]] RealValueType
1419 GetSquaredNorm()
const;
1422 const TExpr1 & m_lhs;
1423 const TExpr2 & m_rhs;
1435template <
typename TExpr1,
typename TExpr2>
1436inline std::enable_if_t<Details::op::CanBeAddedOrSubtracted<TExpr1, TExpr2>::Value,
1437 VariableLengthVectorExpression<TExpr1, TExpr2, Details::op::Plus>>
1438operator+(
const TExpr1 & lhs,
const TExpr2 & rhs)
1440 return VariableLengthVectorExpression<TExpr1, TExpr2, Details::op::Plus>(lhs, rhs);
1452template <
typename TExpr1,
typename TExpr2>
1453inline std::enable_if_t<Details::op::CanBeAddedOrSubtracted<TExpr1, TExpr2>::Value,
1454 VariableLengthVectorExpression<TExpr1, TExpr2, Details::op::Sub>>
1455operator-(
const TExpr1 & lhs,
const TExpr2 & rhs)
1457 return VariableLengthVectorExpression<TExpr1, TExpr2, Details::op::Sub>(lhs, rhs);
1468template <
typename TExpr1,
typename TExpr2>
1469inline std::enable_if_t<Details::op::CanBeMultiplied<TExpr1, TExpr2>::Value,
1470 VariableLengthVectorExpression<TExpr1, TExpr2, Details::op::Mult>>
1471operator*(
const TExpr1 & lhs,
const TExpr2 & rhs)
1473 return VariableLengthVectorExpression<TExpr1, TExpr2, Details::op::Mult>(lhs, rhs);
1483template <
typename TExpr1,
typename TExpr2>
1484inline std::enable_if_t<Details::op::CanBeDivided<TExpr1, TExpr2>::Value,
1485 VariableLengthVectorExpression<TExpr1, TExpr2, Details::op::Div>>
1486operator/(
const TExpr1 & lhs,
const TExpr2 & rhs)
1488 return VariableLengthVectorExpression<TExpr1, TExpr2, Details::op::Div>(lhs, rhs);
1494template <
typename TExpr1,
typename TExpr2,
typename TBinaryOp>
1496operator<<(std::ostream & os,
const VariableLengthVectorExpression<TExpr1, TExpr2, TBinaryOp> & v)
1502 for (
unsigned int i = 1, N = v.Size(); i != N; ++i)
1515template <
typename TExpr>
1516inline std::enable_if_t<mpl::IsArray<TExpr>::Value,
typename TExpr::RealValueType>
1517GetNorm(
const TExpr & v)
1519 return static_cast<typename TExpr::RealValueType
>(std::sqrt(
static_cast<double>(GetSquaredNorm(v))));
1527template <
typename TExpr>
1528inline std::enable_if_t<mpl::IsArray<TExpr>::Value,
typename TExpr::RealValueType>
1529GetSquaredNorm(
const TExpr & v)
1531 using RealValueType =
typename TExpr::RealValueType;
1532 RealValueType sum = 0.0;
1533 for (
unsigned int i = 0, N = v.Size(); i < N; ++i)
1535 const RealValueType value = v[i];
1536 sum += value * value;
1546template <
typename TValue>
1550 const unsigned int length = arr.Size();
1551 const int last =
static_cast<unsigned int>(length) - 1;
1554 for (
int i = 0; i < last; ++i)
1556 os << arr[i] <<
", ";
1585template <
typename T>
1596#ifndef ITK_MANUAL_INSTANTIATION
1597# include "itkVariableLengthVector.hxx"
bool ITKIOXML_EXPORT operator==(itk::FancyString &s, const std::string &)
The "itk" namespace contains all Insight Segmentation and Registration Toolkit (ITK) classes....
void swap(Array< T > &a, Array< T > &b) noexcept
CovariantVector< T, VVectorDimension > operator*(const T &scalar, const CovariantVector< T, VVectorDimension > &v)
ITKCommon_EXPORT std::ostream & operator<<(std::ostream &out, AnatomicalOrientation::CoordinateEnum value)
ConstNeighborhoodIterator< TImage > operator-(const ConstNeighborhoodIterator< TImage > &it, const typename ConstNeighborhoodIterator< TImage >::OffsetType &ind)
ConstNeighborhoodIterator< TImage > operator+(const ConstNeighborhoodIterator< TImage > &it, const typename ConstNeighborhoodIterator< TImage >::OffsetType &ind)