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 itkAssertInDebugAndIgnoreInReleaseMacro(newBuffer);
274 const size_t nb = std::min(newSize, oldSize);
275 itkAssertInDebugAndIgnoreInReleaseMacro(nb == 0 || (nb > 0 && oldBuffer !=
nullptr));
276 std::copy_n(oldBuffer, nb, newBuffer);
296 struct DumpOldValues : KeepValuesRootPolicy
298 template <
typename TValue2>
300 operator()(
unsigned int itkNotUsed(newSize),
301 unsigned int itkNotUsed(oldSize),
302 TValue2 * itkNotUsed(oldBuffer),
303 TValue2 * itkNotUsed(newBuffer))
const
310 using ValueType = TValue;
311 using ComponentType = TValue;
312 using RealValueType =
typename NumericTraits<ValueType>::RealType;
313 using Self = VariableLengthVector;
316 using ElementIdentifier =
unsigned int;
319 using value_type = TValue;
320 using reference = TValue &;
321 using const_reference =
const TValue &;
322 using iterator = TValue *;
323 using const_iterator =
const TValue *;
324 using difference_type = ptrdiff_t;
325 using size_type = size_t;
326 using reverse_iterator = std::reverse_iterator<iterator>;
327 using const_reverse_iterator = std::reverse_iterator<const_iterator>;
335 VariableLengthVector() =
default;
345 explicit VariableLengthVector(
unsigned int length);
348 explicit VariableLengthVector(
unsigned int length,
const TValue & value);
363 VariableLengthVector(ValueType * datain,
unsigned int sz,
bool LetArrayManageMemory =
false);
384 VariableLengthVector(
const ValueType * datain,
unsigned int sz,
bool LetArrayManageMemory =
false);
405 template <
typename T>
406 VariableLengthVector(
const VariableLengthVector<T> & v)
407 : VariableLengthVector(v.Size())
409 if (m_NumElements != 0)
411 itkAssertInDebugAndIgnoreInReleaseMacro(m_Data !=
nullptr);
412 for (ElementIdentifier i = 0; i < m_NumElements; ++i)
414 this->m_Data[i] =
static_cast<ValueType
>(v[i]);
431 VariableLengthVector(
const VariableLengthVector<TValue> & v);
442 Swap(Self & v)
noexcept
444 itkAssertInDebugAndIgnoreInReleaseMacro(m_LetArrayManageMemory == v.m_LetArrayManageMemory);
446 swap(v.m_Data, m_Data);
447 swap(v.m_NumElements, m_NumElements);
457 VariableLengthVector(Self && v)
noexcept;
468 operator=(Self && v)
noexcept;
486 template <
typename TExpr1,
typename TExpr2,
typename TBinaryOp>
487 VariableLengthVector(
const VariableLengthVectorExpression<TExpr1, TExpr2, TBinaryOp> & rhs);
508 template <
typename TExpr1,
typename TExpr2,
typename TBinaryOp>
510 operator=(
const VariableLengthVectorExpression<TExpr1, TExpr2, TBinaryOp> & rhs);
516 Fill(
const TValue & v);
530 template <
typename T>
532 operator=(
const VariableLengthVector<T> & v)
541 const ElementIdentifier N = v.Size();
542 this->SetSize(N, DontShrinkToFit(), DumpOldValues());
543 for (ElementIdentifier i = 0; i < N; ++i)
545 this->m_Data[i] =
static_cast<ValueType
>(v[i]);
566 operator=(
const Self & v);
577 FastAssign(
const Self & v);
587 operator=(
const TValue & v);
591 [[nodiscard]]
unsigned int
594 return m_NumElements;
596 [[nodiscard]]
unsigned int
599 return m_NumElements;
601 [[nodiscard]]
unsigned int
602 GetNumberOfElements()
const
604 return m_NumElements;
609 operator[](
unsigned int i)
611 return this->m_Data[i];
616 operator[](
unsigned int i)
const
618 return this->m_Data[i];
622 [[nodiscard]]
const TValue &
623 GetElement(
unsigned int i)
const
630 SetElement(
unsigned int i,
const TValue & value)
668 template <
typename TReallocatePolicy,
typename TKeepValuesPolicy>
670 SetSize(
unsigned int sz, TReallocatePolicy reallocatePolicy, TKeepValuesPolicy keepValues);
683 SetSize(
unsigned int sz,
bool destroyExistingData =
true)
688 if (destroyExistingData)
690 SetSize(sz, AlwaysReallocate(), KeepOldValues());
694 SetSize(sz, ShrinkToFit(), KeepOldValues());
701 DestroyExistingData();
716 SetData(TValue * datain,
bool LetArrayManageMemory =
false);
733 SetData(TValue * datain,
unsigned int sz,
bool LetArrayManageMemory =
false);
745 ~VariableLengthVector();
762 Reserve(ElementIdentifier size);
764#ifndef ITK_FUTURE_LEGACY_REMOVE
770 [[deprecated(
"Please consider calling `std::make_unique<TValue[]>(size)` instead.")]] [[nodiscard]] TValue *
771 AllocateElements(ElementIdentifier size)
const;
774 [[nodiscard]]
const TValue *
775 GetDataPointer()
const
785 for (ElementIdentifier i = 0; i < m_NumElements; ++i)
787 this->m_Data[i] -=
static_cast<ValueType
>(1.0);
796 for (ElementIdentifier i = 0; i < m_NumElements; ++i)
798 this->m_Data[i] +=
static_cast<ValueType
>(1.0);
832 template <
typename T>
834 operator-=(
const VariableLengthVector<T> & v)
836 itkAssertInDebugAndIgnoreInReleaseMacro(m_NumElements == v.GetSize());
837 for (ElementIdentifier i = 0; i < m_NumElements; ++i)
839 m_Data[i] -=
static_cast<ValueType
>(v[i]);
848 for (ElementIdentifier i = 0; i < m_NumElements; ++i)
863 template <
typename T>
865 operator+=(
const VariableLengthVector<T> & v)
867 itkAssertInDebugAndIgnoreInReleaseMacro(m_NumElements == v.GetSize());
868 for (ElementIdentifier i = 0; i < m_NumElements; ++i)
870 m_Data[i] +=
static_cast<ValueType
>(v[i]);
879 for (ElementIdentifier i = 0; i < m_NumElements; ++i)
895 template <
typename TExpr1,
typename TExpr2,
typename TBinaryOp>
897 operator+=(
const VariableLengthVectorExpression<TExpr1, TExpr2, TBinaryOp> & rhs)
899 itkAssertInDebugAndIgnoreInReleaseMacro(rhs.Size() == Size());
900 for (ElementIdentifier i = 0; i < m_NumElements; ++i)
902 m_Data[i] +=
static_cast<ValueType
>(rhs[i]);
916 template <
typename TExpr1,
typename TExpr2,
typename TBinaryOp>
918 operator-=(
const VariableLengthVectorExpression<TExpr1, TExpr2, TBinaryOp> & rhs)
920 itkAssertInDebugAndIgnoreInReleaseMacro(rhs.Size() == Size());
921 for (ElementIdentifier i = 0; i < m_NumElements; ++i)
923 m_Data[i] -=
static_cast<ValueType
>(rhs[i]);
933 template <
typename T>
937 const ValueType & sc =
static_cast<ValueType
>(s);
938 for (ElementIdentifier i = 0; i < m_NumElements; ++i)
951 for (ElementIdentifier i = 0; i < m_NumElements; ++i)
964 template <
typename T>
968 const RealValueType sc = s;
969 for (ElementIdentifier i = 0; i < m_NumElements; ++i)
971 m_Data[i] =
static_cast<ValueType
>(
static_cast<RealValueType
>(m_Data[i]) / sc);
986 ITK_UNEQUAL_OPERATOR_MEMBER_FUNCTION(Self);
989 [[nodiscard]] RealValueType
993 [[nodiscard]] RealValueType
994 GetSquaredNorm()
const;
1000 return !m_LetArrayManageMemory;
1004 empty() const noexcept
1006 return m_NumElements == 0;
1009 [[nodiscard]] size_type
1010 size() const noexcept
1012 return m_NumElements;
1015 [[nodiscard]] reference
1018 ExceptionThrowingBoundsCheck(pos);
1022 [[nodiscard]] const_reference
1023 at(size_type pos)
const
1025 ExceptionThrowingBoundsCheck(pos);
1029 [[nodiscard]] reference
1035 [[nodiscard]] const_reference
1041 [[nodiscard]] reference
1044 return m_Data[m_NumElements - 1];
1047 [[nodiscard]] const_reference
1050 return m_Data[m_NumElements - 1];
1053 [[nodiscard]] TValue *
1059 [[nodiscard]]
const TValue *
1060 data() const noexcept
1065 [[nodiscard]] const_iterator
1066 cbegin() const noexcept
1071 [[nodiscard]] iterator
1077 [[nodiscard]] const_iterator
1078 begin() const noexcept
1083 [[nodiscard]] const_iterator
1084 cend() const noexcept
1086 return m_Data + m_NumElements;
1089 [[nodiscard]] iterator
1092 return m_Data + m_NumElements;
1095 [[nodiscard]] const_iterator
1096 end() const noexcept
1101 [[nodiscard]] reverse_iterator
1104 return reverse_iterator{ end() };
1107 [[nodiscard]] const_reverse_iterator
1110 return const_reverse_iterator{ cend() };
1113 [[nodiscard]] const_reverse_iterator
1119 [[nodiscard]] reverse_iterator
1122 return reverse_iterator{ begin() };
1125 [[nodiscard]] const_reverse_iterator
1128 return const_reverse_iterator{ cbegin() };
1131 [[nodiscard]] const_reverse_iterator
1138 bool m_LetArrayManageMemory{
true };
1141 ElementIdentifier m_NumElements{ 0 };
1144 ExceptionThrowingBoundsCheck(size_type pos)
const
1146 if (pos >= m_NumElements)
1148 throw std::out_of_range(
"Out of range: `itk::VariableLengthVector::at` argument `pos` (which is " +
1149 std::to_string(pos) +
") should be less than `m_NumElements` (which is " +
1150 std::to_string(m_NumElements) +
")!");
1167template <
typename T>
1168struct IsArray : FalseType
1172template <
typename T>
1173struct IsArray<itk::VariableLengthVector<T>> : TrueType
1176template <
typename TExpr1,
typename TExpr2,
typename TBinaryOp>
1177struct IsArray<VariableLengthVectorExpression<TExpr1, TExpr2, TBinaryOp>> : TrueType
1198template <
typename TExpr>
1207 Load(
const Type & v,
unsigned int itkNotUsed(idx))
1223template <
typename TExpr1,
typename TExpr2>
1224inline std::enable_if_t<mpl::And<mpl::IsArray<TExpr1>, mpl::IsArray<TExpr2>>::Value,
unsigned int>
1225GetSize(
const TExpr1 & lhs, [[maybe_unused]]
const TExpr2 & rhs)
1227 itkAssertInDebugAndIgnoreInReleaseMacro(lhs.Size() == rhs.Size());
1241template <
typename TExpr1,
typename TExpr2>
1242inline std::enable_if_t<mpl::And<mpl::IsArray<TExpr1>, mpl::Not<mpl::IsArray<TExpr2>>>::Value,
unsigned int>
1243GetSize(
const TExpr1 & lhs,
const TExpr2 & itkNotUsed(rhs))
1257template <
typename TExpr1,
typename TExpr2>
1258inline std::enable_if_t<mpl::And<mpl::IsArray<TExpr2>, mpl::Not<mpl::IsArray<TExpr1>>>::Value,
unsigned int>
1259GetSize(
const TExpr1 & itkNotUsed(lhs),
const TExpr2 & rhs)
1264template <
typename T>
1265struct GetType<VariableLengthVector<T>>
1269 Load(
const VariableLengthVector<T> & v,
unsigned int idx)
1274template <
typename TExpr1,
typename TExpr2,
typename TBinaryOp>
1275struct GetType<VariableLengthVectorExpression<TExpr1, TExpr2, TBinaryOp>>
1277 using Type =
typename VariableLengthVectorExpression<TExpr1, TExpr2, TBinaryOp>::ResType;
1279 Load(
const VariableLengthVectorExpression<TExpr1, TExpr2, TBinaryOp> & v,
unsigned int idx)
1300template <
typename TExpr1,
typename TExpr2>
1301struct CanBeAddedOrSubtracted
1302 : mpl::Or<mpl::And<mpl::IsArray<TExpr1>, mpl::IsArray<TExpr2>>,
1303 mpl::And<mpl::IsArray<TExpr1>, mpl::IsNumber<TExpr2>>,
1304 mpl::And<mpl::IsNumber<TExpr1>, mpl::IsArray<TExpr2>>>
1318template <
typename TExpr1,
typename TExpr2>
1319struct CanBeMultiplied
1320 : mpl::Or<mpl::And<mpl::IsArray<TExpr1>, mpl::IsNumber<TExpr2>>,
1321 mpl::And<mpl::IsNumber<TExpr1>, mpl::IsArray<TExpr2>>>
1335template <
typename TExpr1,
typename TExpr2>
1336struct CanBeDivided : mpl::And<mpl::IsArray<TExpr1>, mpl::IsNumber<TExpr2>>
1367template <
typename TExpr1,
typename TExpr2,
typename TBinaryOp>
1368struct VariableLengthVectorExpression
1370 VariableLengthVectorExpression(
const TExpr1 & lhs,
const TExpr2 & rhs)
1376 static_assert(std::is_base_of_v<Details::op::BinaryOperationConcept, TBinaryOp>,
1377 "The Binary Operation shall inherit from BinaryOperationConcept");
1381 [[nodiscard]]
unsigned int
1384 return Details::GetSize(m_lhs, m_rhs);
1389 typename mpl::PromoteType<typename Details::GetType<TExpr1>::Type,
typename Details::GetType<TExpr2>::Type>::Type;
1391 using RealValueType =
typename NumericTraits<ResType>::RealType;
1404 operator[](
unsigned int idx)
const
1406 itkAssertInDebugAndIgnoreInReleaseMacro(idx < Size());
1407 return TBinaryOp::Apply(Details::GetType<TExpr1>::Load(m_lhs, idx), Details::GetType<TExpr2>::Load(m_rhs, idx));
1411 [[nodiscard]] RealValueType
1415 [[nodiscard]] RealValueType
1416 GetSquaredNorm()
const;
1419 const TExpr1 & m_lhs;
1420 const TExpr2 & m_rhs;
1432template <
typename TExpr1,
typename TExpr2>
1433inline std::enable_if_t<Details::op::CanBeAddedOrSubtracted<TExpr1, TExpr2>::Value,
1434 VariableLengthVectorExpression<TExpr1, TExpr2, Details::op::Plus>>
1435operator+(
const TExpr1 & lhs,
const TExpr2 & rhs)
1437 return VariableLengthVectorExpression<TExpr1, TExpr2, Details::op::Plus>(lhs, rhs);
1449template <
typename TExpr1,
typename TExpr2>
1450inline std::enable_if_t<Details::op::CanBeAddedOrSubtracted<TExpr1, TExpr2>::Value,
1451 VariableLengthVectorExpression<TExpr1, TExpr2, Details::op::Sub>>
1452operator-(
const TExpr1 & lhs,
const TExpr2 & rhs)
1454 return VariableLengthVectorExpression<TExpr1, TExpr2, Details::op::Sub>(lhs, rhs);
1465template <
typename TExpr1,
typename TExpr2>
1466inline std::enable_if_t<Details::op::CanBeMultiplied<TExpr1, TExpr2>::Value,
1467 VariableLengthVectorExpression<TExpr1, TExpr2, Details::op::Mult>>
1468operator*(
const TExpr1 & lhs,
const TExpr2 & rhs)
1470 return VariableLengthVectorExpression<TExpr1, TExpr2, Details::op::Mult>(lhs, rhs);
1480template <
typename TExpr1,
typename TExpr2>
1481inline std::enable_if_t<Details::op::CanBeDivided<TExpr1, TExpr2>::Value,
1482 VariableLengthVectorExpression<TExpr1, TExpr2, Details::op::Div>>
1483operator/(
const TExpr1 & lhs,
const TExpr2 & rhs)
1485 return VariableLengthVectorExpression<TExpr1, TExpr2, Details::op::Div>(lhs, rhs);
1491template <
typename TExpr1,
typename TExpr2,
typename TBinaryOp>
1493operator<<(std::ostream & os,
const VariableLengthVectorExpression<TExpr1, TExpr2, TBinaryOp> & v)
1499 for (
unsigned int i = 1, N = v.Size(); i != N; ++i)
1512template <
typename TExpr>
1513inline std::enable_if_t<mpl::IsArray<TExpr>::Value,
typename TExpr::RealValueType>
1514GetNorm(
const TExpr & v)
1516 return static_cast<typename TExpr::RealValueType
>(std::sqrt(
static_cast<double>(GetSquaredNorm(v))));
1524template <
typename TExpr>
1525inline std::enable_if_t<mpl::IsArray<TExpr>::Value,
typename TExpr::RealValueType>
1526GetSquaredNorm(
const TExpr & v)
1528 using RealValueType =
typename TExpr::RealValueType;
1529 RealValueType sum = 0.0;
1530 for (
unsigned int i = 0, N = v.Size(); i < N; ++i)
1532 const RealValueType value = v[i];
1533 sum += value * value;
1543template <
typename TValue>
1547 const unsigned int length = arr.Size();
1548 const int last =
static_cast<unsigned int>(length) - 1;
1551 for (
int i = 0; i < last; ++i)
1553 os << arr[i] <<
", ";
1582template <
typename T>
1593#ifndef ITK_MANUAL_INSTANTIATION
1594# 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
ITKCommon_EXPORT std::ostream & operator<<(std::ostream &out, typename AnatomicalOrientation::CoordinateEnum value)
CovariantVector< T, VVectorDimension > operator*(const T &scalar, const CovariantVector< T, VVectorDimension > &v)
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)