18#ifndef itkVariableLengthVector_h
19#define itkVariableLengthVector_h
34template <
typename TExpr1,
typename TExpr2,
typename TBinaryOp>
35struct VariableLengthVectorExpression;
91template <
typename TValue>
111 struct AllocateRootPolicy
127 struct AlwaysReallocate : AllocateRootPolicy
130 operator()(
unsigned int itkNotUsed(newSize),
unsigned int itkNotUsed(oldSize))
const
153 struct NeverReallocate : AllocateRootPolicy
156 operator()([[maybe_unused]]
unsigned int newSize, [[maybe_unused]]
unsigned int oldSize)
const
158 itkAssertInDebugAndIgnoreInReleaseMacro(newSize == oldSize &&
159 "SetSize is expected to never change the VariableLengthVector size...");
181 struct ShrinkToFit : AllocateRootPolicy
184 operator()(
unsigned int newSize,
unsigned int oldSize)
const
186 return newSize != oldSize;
216 struct DontShrinkToFit : AllocateRootPolicy
219 operator()(
unsigned int newSize,
unsigned int oldSize)
const
221 return newSize > oldSize;
243 struct KeepValuesRootPolicy
267 struct KeepOldValues : KeepValuesRootPolicy
269 template <
typename TValue2>
271 operator()(
unsigned int newSize,
unsigned int oldSize, TValue2 * oldBuffer, TValue2 * newBuffer)
const
273 const size_t nb = std::min(newSize, oldSize);
276 itkAssertInDebugAndIgnoreInReleaseMacro(newBuffer);
277 itkAssertInDebugAndIgnoreInReleaseMacro(oldBuffer);
278 std::copy_n(oldBuffer, nb, newBuffer);
299 struct DumpOldValues : KeepValuesRootPolicy
301 template <
typename TValue2>
303 operator()(
unsigned int itkNotUsed(newSize),
304 unsigned int itkNotUsed(oldSize),
305 TValue2 * itkNotUsed(oldBuffer),
306 TValue2 * itkNotUsed(newBuffer))
const
313 using ValueType = TValue;
314 using ComponentType = TValue;
315 using RealValueType =
typename NumericTraits<ValueType>::RealType;
316 using Self = VariableLengthVector;
319 using ElementIdentifier =
unsigned int;
322 using value_type = TValue;
323 using reference = TValue &;
324 using const_reference =
const TValue &;
325 using iterator = TValue *;
326 using const_iterator =
const TValue *;
327 using difference_type = ptrdiff_t;
328 using size_type = size_t;
329 using reverse_iterator = std::reverse_iterator<iterator>;
330 using const_reverse_iterator = std::reverse_iterator<const_iterator>;
338 VariableLengthVector() =
default;
348 explicit VariableLengthVector(
unsigned int length);
351 explicit VariableLengthVector(
unsigned int length,
const TValue & value);
366 VariableLengthVector(ValueType * datain,
unsigned int sz,
bool LetArrayManageMemory =
false);
387 VariableLengthVector(
const ValueType * datain,
unsigned int sz,
bool LetArrayManageMemory =
false);
408 template <
typename T>
409 VariableLengthVector(
const VariableLengthVector<T> & v)
410 : VariableLengthVector(v.Size())
412 if (m_NumElements != 0)
414 itkAssertInDebugAndIgnoreInReleaseMacro(m_Data !=
nullptr);
415 for (ElementIdentifier i = 0; i < m_NumElements; ++i)
417 this->m_Data[i] =
static_cast<ValueType
>(v[i]);
434 VariableLengthVector(
const VariableLengthVector<TValue> & v);
445 Swap(Self & v)
noexcept
447 itkAssertInDebugAndIgnoreInReleaseMacro(m_LetArrayManageMemory == v.m_LetArrayManageMemory);
449 swap(v.m_Data, m_Data);
450 swap(v.m_NumElements, m_NumElements);
460 VariableLengthVector(Self && v)
noexcept;
471 operator=(Self && v)
noexcept;
489 template <
typename TExpr1,
typename TExpr2,
typename TBinaryOp>
490 VariableLengthVector(
const VariableLengthVectorExpression<TExpr1, TExpr2, TBinaryOp> & rhs);
511 template <
typename TExpr1,
typename TExpr2,
typename TBinaryOp>
513 operator=(
const VariableLengthVectorExpression<TExpr1, TExpr2, TBinaryOp> & rhs);
519 Fill(
const TValue & v);
533 template <
typename T>
535 operator=(
const VariableLengthVector<T> & v)
544 const ElementIdentifier N = v.Size();
545 this->SetSize(N, DontShrinkToFit(), DumpOldValues());
546 for (ElementIdentifier i = 0; i < N; ++i)
548 this->m_Data[i] =
static_cast<ValueType
>(v[i]);
569 operator=(
const Self & v);
580 FastAssign(
const Self & v);
590 operator=(
const TValue & v);
594 [[nodiscard]]
unsigned int
597 return m_NumElements;
599 [[nodiscard]]
unsigned int
602 return m_NumElements;
604 [[nodiscard]]
unsigned int
605 GetNumberOfElements()
const
607 return m_NumElements;
612 operator[](
unsigned int i)
614 return this->m_Data[i];
619 operator[](
unsigned int i)
const
621 return this->m_Data[i];
625 [[nodiscard]]
const TValue &
626 GetElement(
unsigned int i)
const
633 SetElement(
unsigned int i,
const TValue & value)
671 template <
typename TReallocatePolicy,
typename TKeepValuesPolicy>
673 SetSize(
unsigned int sz, TReallocatePolicy reallocatePolicy, TKeepValuesPolicy keepValues);
686 SetSize(
unsigned int sz,
bool destroyExistingData =
true)
691 if (destroyExistingData)
693 SetSize(sz, AlwaysReallocate(), KeepOldValues());
697 SetSize(sz, ShrinkToFit(), KeepOldValues());
704 DestroyExistingData();
719 SetData(TValue * datain,
bool LetArrayManageMemory =
false);
736 SetData(TValue * datain,
unsigned int sz,
bool LetArrayManageMemory =
false);
748 ~VariableLengthVector();
765 Reserve(ElementIdentifier size);
767#ifndef ITK_FUTURE_LEGACY_REMOVE
773 ITK_FUTURE_DEPRECATED(
"Please consider calling `std::make_unique<TValue[]>(size)` instead.")
774 [[nodiscard]] TValue *
775 AllocateElements(ElementIdentifier size)
const;
778 [[nodiscard]]
const TValue *
779 GetDataPointer()
const
789 for (ElementIdentifier i = 0; i < m_NumElements; ++i)
791 this->m_Data[i] -=
static_cast<ValueType
>(1.0);
800 for (ElementIdentifier i = 0; i < m_NumElements; ++i)
802 this->m_Data[i] +=
static_cast<ValueType
>(1.0);
836 template <
typename T>
838 operator-=(
const VariableLengthVector<T> & v)
840 itkAssertInDebugAndIgnoreInReleaseMacro(m_NumElements == v.GetSize());
841 for (ElementIdentifier i = 0; i < m_NumElements; ++i)
843 m_Data[i] -=
static_cast<ValueType
>(v[i]);
852 for (ElementIdentifier i = 0; i < m_NumElements; ++i)
867 template <
typename T>
869 operator+=(
const VariableLengthVector<T> & v)
871 itkAssertInDebugAndIgnoreInReleaseMacro(m_NumElements == v.GetSize());
872 for (ElementIdentifier i = 0; i < m_NumElements; ++i)
874 m_Data[i] +=
static_cast<ValueType
>(v[i]);
883 for (ElementIdentifier i = 0; i < m_NumElements; ++i)
899 template <
typename TExpr1,
typename TExpr2,
typename TBinaryOp>
901 operator+=(
const VariableLengthVectorExpression<TExpr1, TExpr2, TBinaryOp> & rhs)
903 itkAssertInDebugAndIgnoreInReleaseMacro(rhs.Size() == Size());
904 for (ElementIdentifier i = 0; i < m_NumElements; ++i)
906 m_Data[i] +=
static_cast<ValueType
>(rhs[i]);
920 template <
typename TExpr1,
typename TExpr2,
typename TBinaryOp>
922 operator-=(
const VariableLengthVectorExpression<TExpr1, TExpr2, TBinaryOp> & rhs)
924 itkAssertInDebugAndIgnoreInReleaseMacro(rhs.Size() == Size());
925 for (ElementIdentifier i = 0; i < m_NumElements; ++i)
927 m_Data[i] -=
static_cast<ValueType
>(rhs[i]);
937 template <
typename T>
941 const ValueType & sc =
static_cast<ValueType
>(s);
942 for (ElementIdentifier i = 0; i < m_NumElements; ++i)
955 for (ElementIdentifier i = 0; i < m_NumElements; ++i)
968 template <
typename T>
972 const RealValueType sc = s;
973 for (ElementIdentifier i = 0; i < m_NumElements; ++i)
975 m_Data[i] =
static_cast<ValueType
>(
static_cast<RealValueType
>(m_Data[i]) / sc);
990 ITK_UNEQUAL_OPERATOR_MEMBER_FUNCTION(Self);
993 [[nodiscard]] RealValueType
997 [[nodiscard]] RealValueType
998 GetSquaredNorm()
const;
1004 return !m_LetArrayManageMemory;
1008 empty() const noexcept
1010 return m_NumElements == 0;
1013 [[nodiscard]] size_type
1014 size() const noexcept
1016 return m_NumElements;
1019 [[nodiscard]] reference
1022 ExceptionThrowingBoundsCheck(pos);
1026 [[nodiscard]] const_reference
1027 at(size_type pos)
const
1029 ExceptionThrowingBoundsCheck(pos);
1033 [[nodiscard]] reference
1039 [[nodiscard]] const_reference
1045 [[nodiscard]] reference
1048 return m_Data[m_NumElements - 1];
1051 [[nodiscard]] const_reference
1054 return m_Data[m_NumElements - 1];
1057 [[nodiscard]] TValue *
1063 [[nodiscard]]
const TValue *
1064 data() const noexcept
1069 [[nodiscard]] const_iterator
1070 cbegin() const noexcept
1075 [[nodiscard]] iterator
1081 [[nodiscard]] const_iterator
1082 begin() const noexcept
1087 [[nodiscard]] const_iterator
1088 cend() const noexcept
1090 return m_Data + m_NumElements;
1093 [[nodiscard]] iterator
1096 return m_Data + m_NumElements;
1099 [[nodiscard]] const_iterator
1100 end() const noexcept
1105 [[nodiscard]] reverse_iterator
1108 return reverse_iterator{ end() };
1111 [[nodiscard]] const_reverse_iterator
1114 return const_reverse_iterator{ cend() };
1117 [[nodiscard]] const_reverse_iterator
1123 [[nodiscard]] reverse_iterator
1126 return reverse_iterator{ begin() };
1129 [[nodiscard]] const_reverse_iterator
1132 return const_reverse_iterator{ cbegin() };
1135 [[nodiscard]] const_reverse_iterator
1142 bool m_LetArrayManageMemory{
true };
1145 ElementIdentifier m_NumElements{ 0 };
1148 ExceptionThrowingBoundsCheck(size_type pos)
const
1150 if (pos >= m_NumElements)
1152 throw std::out_of_range(
"Out of range: `itk::VariableLengthVector::at` argument `pos` (which is " +
1153 std::to_string(pos) +
") should be less than `m_NumElements` (which is " +
1154 std::to_string(m_NumElements) +
")!");
1171template <
typename T>
1172struct IsArray : FalseType
1176template <
typename T>
1177struct IsArray<itk::VariableLengthVector<T>> : TrueType
1180template <
typename TExpr1,
typename TExpr2,
typename TBinaryOp>
1181struct IsArray<VariableLengthVectorExpression<TExpr1, TExpr2, TBinaryOp>> : TrueType
1202template <
typename TExpr>
1211 Load(
const Type & v,
unsigned int itkNotUsed(idx))
1227template <
typename TExpr1,
typename TExpr2>
1228inline std::enable_if_t<mpl::And<mpl::IsArray<TExpr1>, mpl::IsArray<TExpr2>>::Value,
unsigned int>
1229GetSize(
const TExpr1 & lhs, [[maybe_unused]]
const TExpr2 & rhs)
1231 itkAssertInDebugAndIgnoreInReleaseMacro(lhs.Size() == rhs.Size());
1245template <
typename TExpr1,
typename TExpr2>
1246inline std::enable_if_t<mpl::And<mpl::IsArray<TExpr1>, mpl::Not<mpl::IsArray<TExpr2>>>::Value,
unsigned int>
1247GetSize(
const TExpr1 & lhs,
const TExpr2 & itkNotUsed(rhs))
1261template <
typename TExpr1,
typename TExpr2>
1262inline std::enable_if_t<mpl::And<mpl::IsArray<TExpr2>, mpl::Not<mpl::IsArray<TExpr1>>>::Value,
unsigned int>
1263GetSize(
const TExpr1 & itkNotUsed(lhs),
const TExpr2 & rhs)
1268template <
typename T>
1269struct GetType<VariableLengthVector<T>>
1273 Load(
const VariableLengthVector<T> & v,
unsigned int idx)
1278template <
typename TExpr1,
typename TExpr2,
typename TBinaryOp>
1279struct GetType<VariableLengthVectorExpression<TExpr1, TExpr2, TBinaryOp>>
1281 using Type =
typename VariableLengthVectorExpression<TExpr1, TExpr2, TBinaryOp>::ResType;
1283 Load(
const VariableLengthVectorExpression<TExpr1, TExpr2, TBinaryOp> & v,
unsigned int idx)
1304template <
typename TExpr1,
typename TExpr2>
1305struct CanBeAddedOrSubtracted
1306 : mpl::Or<mpl::And<mpl::IsArray<TExpr1>, mpl::IsArray<TExpr2>>,
1307 mpl::And<mpl::IsArray<TExpr1>, mpl::IsNumber<TExpr2>>,
1308 mpl::And<mpl::IsNumber<TExpr1>, mpl::IsArray<TExpr2>>>
1322template <
typename TExpr1,
typename TExpr2>
1323struct CanBeMultiplied
1324 : mpl::Or<mpl::And<mpl::IsArray<TExpr1>, mpl::IsNumber<TExpr2>>,
1325 mpl::And<mpl::IsNumber<TExpr1>, mpl::IsArray<TExpr2>>>
1339template <
typename TExpr1,
typename TExpr2>
1340struct CanBeDivided : mpl::And<mpl::IsArray<TExpr1>, mpl::IsNumber<TExpr2>>
1371template <
typename TExpr1,
typename TExpr2,
typename TBinaryOp>
1372struct VariableLengthVectorExpression
1374 VariableLengthVectorExpression(
const TExpr1 & lhs,
const TExpr2 & rhs)
1380 static_assert(std::is_base_of_v<Details::op::BinaryOperationConcept, TBinaryOp>,
1381 "The Binary Operation shall inherit from BinaryOperationConcept");
1385 [[nodiscard]]
unsigned int
1388 return Details::GetSize(m_lhs, m_rhs);
1393 typename mpl::PromoteType<typename Details::GetType<TExpr1>::Type,
typename Details::GetType<TExpr2>::Type>::Type;
1395 using RealValueType =
typename NumericTraits<ResType>::RealType;
1408 operator[](
unsigned int idx)
const
1410 itkAssertInDebugAndIgnoreInReleaseMacro(idx < Size());
1411 return TBinaryOp::Apply(Details::GetType<TExpr1>::Load(m_lhs, idx), Details::GetType<TExpr2>::Load(m_rhs, idx));
1415 [[nodiscard]] RealValueType
1419 [[nodiscard]] RealValueType
1420 GetSquaredNorm()
const;
1423 const TExpr1 & m_lhs;
1424 const TExpr2 & m_rhs;
1436template <
typename TExpr1,
typename TExpr2>
1437inline std::enable_if_t<Details::op::CanBeAddedOrSubtracted<TExpr1, TExpr2>::Value,
1438 VariableLengthVectorExpression<TExpr1, TExpr2, Details::op::Plus>>
1439operator+(
const TExpr1 & lhs,
const TExpr2 & rhs)
1441 return VariableLengthVectorExpression<TExpr1, TExpr2, Details::op::Plus>(lhs, rhs);
1453template <
typename TExpr1,
typename TExpr2>
1454inline std::enable_if_t<Details::op::CanBeAddedOrSubtracted<TExpr1, TExpr2>::Value,
1455 VariableLengthVectorExpression<TExpr1, TExpr2, Details::op::Sub>>
1456operator-(
const TExpr1 & lhs,
const TExpr2 & rhs)
1458 return VariableLengthVectorExpression<TExpr1, TExpr2, Details::op::Sub>(lhs, rhs);
1469template <
typename TExpr1,
typename TExpr2>
1470inline std::enable_if_t<Details::op::CanBeMultiplied<TExpr1, TExpr2>::Value,
1471 VariableLengthVectorExpression<TExpr1, TExpr2, Details::op::Mult>>
1472operator*(
const TExpr1 & lhs,
const TExpr2 & rhs)
1474 return VariableLengthVectorExpression<TExpr1, TExpr2, Details::op::Mult>(lhs, rhs);
1484template <
typename TExpr1,
typename TExpr2>
1485inline std::enable_if_t<Details::op::CanBeDivided<TExpr1, TExpr2>::Value,
1486 VariableLengthVectorExpression<TExpr1, TExpr2, Details::op::Div>>
1487operator/(
const TExpr1 & lhs,
const TExpr2 & rhs)
1489 return VariableLengthVectorExpression<TExpr1, TExpr2, Details::op::Div>(lhs, rhs);
1495template <
typename TExpr1,
typename TExpr2,
typename TBinaryOp>
1497operator<<(std::ostream & os,
const VariableLengthVectorExpression<TExpr1, TExpr2, TBinaryOp> & v)
1503 for (
unsigned int i = 1, N = v.Size(); i != N; ++i)
1516template <
typename TExpr>
1517inline std::enable_if_t<mpl::IsArray<TExpr>::Value,
typename TExpr::RealValueType>
1518GetNorm(
const TExpr & v)
1520 return static_cast<typename TExpr::RealValueType
>(std::sqrt(
static_cast<double>(GetSquaredNorm(v))));
1528template <
typename TExpr>
1529inline std::enable_if_t<mpl::IsArray<TExpr>::Value,
typename TExpr::RealValueType>
1530GetSquaredNorm(
const TExpr & v)
1532 using RealValueType =
typename TExpr::RealValueType;
1533 RealValueType sum = 0.0;
1534 for (
unsigned int i = 0, N = v.Size(); i < N; ++i)
1536 const RealValueType value = v[i];
1537 sum += value * value;
1547template <
typename TValue>
1551 const unsigned int length = arr.Size();
1552 const int last =
static_cast<unsigned int>(length) - 1;
1555 for (
int i = 0; i < last; ++i)
1557 os << arr[i] <<
", ";
1586template <
typename T>
1597#ifndef ITK_MANUAL_INSTANTIATION
1598# 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)