ITK 6.0.0
Insight Toolkit
 
Loading...
Searching...
No Matches
itkVariableLengthVector.h
Go to the documentation of this file.
1/*=========================================================================
2 *
3 * Copyright NumFOCUS
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * https://www.apache.org/licenses/LICENSE-2.0.txt
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 *=========================================================================*/
18#ifndef itkVariableLengthVector_h
19#define itkVariableLengthVector_h
20
21#include <cassert>
22#include <algorithm>
23#include <iterator>
24#include <type_traits>
25#include "itkNumericTraits.h"
27#include "itkPromoteType.h"
29
30namespace itk
31{
32
33template <typename TExpr1, typename TExpr2, typename TBinaryOp>
34struct VariableLengthVectorExpression;
35
90template <typename TValue>
91class ITK_TEMPLATE_EXPORT VariableLengthVector
92{
93public:
98
110 struct AllocateRootPolicy
111 {};
112
126 struct AlwaysReallocate : AllocateRootPolicy
127 {
128 bool
129 operator()(unsigned int itkNotUsed(newSize), unsigned int itkNotUsed(oldSize)) const
130 {
131 return true;
132 }
133 };
134
152 struct NeverReallocate : AllocateRootPolicy
153 {
154 bool
155 operator()([[maybe_unused]] unsigned int newSize, [[maybe_unused]] unsigned int oldSize) const
156 {
157 itkAssertInDebugAndIgnoreInReleaseMacro(newSize == oldSize &&
158 "SetSize is expected to never change the VariableLengthVector size...");
159 return true;
160 }
161 };
162
180 struct ShrinkToFit : AllocateRootPolicy
181 {
182 bool
183 operator()(unsigned int newSize, unsigned int oldSize) const
184 {
185 return newSize != oldSize;
186 }
187 };
188
215 struct DontShrinkToFit : AllocateRootPolicy
216 {
217 bool
218 operator()(unsigned int newSize, unsigned int oldSize) const
219 {
220 return newSize > oldSize;
221 }
222 };
223
242 struct KeepValuesRootPolicy
243 {};
244
266 struct KeepOldValues : KeepValuesRootPolicy
267 {
268 template <typename TValue2>
269 void
270 operator()(unsigned int newSize, unsigned int oldSize, TValue2 * oldBuffer, TValue2 * newBuffer) const
271 {
272 const size_t nb = std::min(newSize, oldSize);
273 if (nb > 0)
274 {
275 itkAssertInDebugAndIgnoreInReleaseMacro(newBuffer);
276 itkAssertInDebugAndIgnoreInReleaseMacro(oldBuffer);
277 std::copy_n(oldBuffer, nb, newBuffer);
278 }
279 }
280 };
281
298 struct DumpOldValues : KeepValuesRootPolicy
299 {
300 template <typename TValue2>
301 void
302 operator()(unsigned int itkNotUsed(newSize),
303 unsigned int itkNotUsed(oldSize),
304 TValue2 * itkNotUsed(oldBuffer),
305 TValue2 * itkNotUsed(newBuffer)) const
306 {}
307 };
309
310
312 using ValueType = TValue;
313 using ComponentType = TValue;
314 using RealValueType = typename NumericTraits<ValueType>::RealType;
315 using Self = VariableLengthVector;
316
318 using ElementIdentifier = unsigned int;
319
320 // Nested types from C++ Standard section "Container requirements" [container.reqmts], and from `std::vector`:
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>;
330
337 VariableLengthVector() = default;
338
347 explicit VariableLengthVector(unsigned int length);
348
350 explicit VariableLengthVector(unsigned int length, const TValue & value);
351
365 VariableLengthVector(ValueType * datain, unsigned int sz, bool LetArrayManageMemory = false);
366
386 VariableLengthVector(const ValueType * datain, unsigned int sz, bool LetArrayManageMemory = false);
387
407 template <typename T>
408 VariableLengthVector(const VariableLengthVector<T> & v)
409 : VariableLengthVector(v.Size())
410 {
411 if (m_NumElements != 0)
412 {
413 itkAssertInDebugAndIgnoreInReleaseMacro(m_Data != nullptr);
414 for (ElementIdentifier i = 0; i < m_NumElements; ++i)
415 {
416 this->m_Data[i] = static_cast<ValueType>(v[i]);
417 }
418 }
419 else
420 {
421 m_Data = nullptr;
422 }
423 }
424
433 VariableLengthVector(const VariableLengthVector<TValue> & v);
434
443 void
444 Swap(Self & v) noexcept
445 {
446 itkAssertInDebugAndIgnoreInReleaseMacro(m_LetArrayManageMemory == v.m_LetArrayManageMemory);
447 using std::swap;
448 swap(v.m_Data, m_Data);
449 swap(v.m_NumElements, m_NumElements);
450 }
451
459 VariableLengthVector(Self && v) noexcept;
460
469 Self &
470 operator=(Self && v) noexcept;
471
488 template <typename TExpr1, typename TExpr2, typename TBinaryOp>
489 VariableLengthVector(const VariableLengthVectorExpression<TExpr1, TExpr2, TBinaryOp> & rhs);
490
510 template <typename TExpr1, typename TExpr2, typename TBinaryOp>
511 Self &
512 operator=(const VariableLengthVectorExpression<TExpr1, TExpr2, TBinaryOp> & rhs);
513
517 void
518 Fill(const TValue & v);
519
532 template <typename T>
533 Self &
534 operator=(const VariableLengthVector<T> & v)
535 {
536 // No self assignment test is done. Indeed:
537 // - the operator already resists self assignment through a strong exception
538 // guarantee
539 // - the test becomes a pessimization as we never write
540 // VLV<const TValue> vcref(v.GetDataPointer(), v.GetSize());
541 // ...;
542 // v = vcref;
543 const ElementIdentifier N = v.Size();
544 this->SetSize(N, DontShrinkToFit(), DumpOldValues());
545 for (ElementIdentifier i = 0; i < N; ++i)
546 {
547 this->m_Data[i] = static_cast<ValueType>(v[i]);
548 }
549 return *this;
550 }
551
567 Self &
568 operator=(const Self & v);
569
578 Self &
579 FastAssign(const Self & v);
580
588 Self &
589 operator=(const TValue & v);
590
593 [[nodiscard]] unsigned int
594 Size() const
595 {
596 return m_NumElements;
597 }
598 [[nodiscard]] unsigned int
599 GetSize() const
600 {
601 return m_NumElements;
602 }
603 [[nodiscard]] unsigned int
604 GetNumberOfElements() const
605 {
606 return m_NumElements;
607 }
610 TValue &
611 operator[](unsigned int i)
612 {
613 return this->m_Data[i];
614 }
615
617 const TValue &
618 operator[](unsigned int i) const
619 {
620 return this->m_Data[i];
621 }
622
624 [[nodiscard]] const TValue &
625 GetElement(unsigned int i) const
626 {
627 return m_Data[i];
628 }
629
631 void
632 SetElement(unsigned int i, const TValue & value)
633 {
634 m_Data[i] = value;
635 }
636
670 template <typename TReallocatePolicy, typename TKeepValuesPolicy>
671 void
672 SetSize(unsigned int sz, TReallocatePolicy reallocatePolicy, TKeepValuesPolicy keepValues);
673
684 void
685 SetSize(unsigned int sz, bool destroyExistingData = true)
686 {
687 // Stays compatible with previous code version
688 // And works around the fact C++03 template functions can't have default
689 // arguments on template types.
690 if (destroyExistingData)
691 {
692 SetSize(sz, AlwaysReallocate(), KeepOldValues());
693 }
694 else
695 {
696 SetSize(sz, ShrinkToFit(), KeepOldValues());
697 }
698 }
699
702 void
703 DestroyExistingData();
704
717 void
718 SetData(TValue * datain, bool LetArrayManageMemory = false);
719
734 void
735 SetData(TValue * datain, unsigned int sz, bool LetArrayManageMemory = false);
736
747 ~VariableLengthVector();
748
763 void
764 Reserve(ElementIdentifier size);
765
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;
775#endif
776
777 [[nodiscard]] const TValue *
778 GetDataPointer() const
779 {
780 return m_Data;
781 }
782
785 Self &
786 operator--()
787 {
788 for (ElementIdentifier i = 0; i < m_NumElements; ++i)
789 {
790 this->m_Data[i] -= static_cast<ValueType>(1.0);
791 }
792 return *this;
793 }
794
796 Self &
797 operator++() // prefix operator ++v;
798 {
799 for (ElementIdentifier i = 0; i < m_NumElements; ++i)
800 {
801 this->m_Data[i] += static_cast<ValueType>(1.0);
802 }
803 return *this;
804 }
805
808 Self
809 operator--(int) // postfix operator v--;
810 {
811 Self tmp(*this);
812
813 --tmp;
814 return tmp;
815 }
816
818 Self
819 operator++(int) // postfix operator v++;
820 {
821 Self tmp(*this);
822
823 ++tmp;
824 return tmp;
825 }
826
835 template <typename T>
836 Self &
837 operator-=(const VariableLengthVector<T> & v)
838 {
839 itkAssertInDebugAndIgnoreInReleaseMacro(m_NumElements == v.GetSize());
840 for (ElementIdentifier i = 0; i < m_NumElements; ++i)
841 {
842 m_Data[i] -= static_cast<ValueType>(v[i]);
843 }
844 return *this;
845 }
846
848 Self &
849 operator-=(TValue s)
850 {
851 for (ElementIdentifier i = 0; i < m_NumElements; ++i)
852 {
853 m_Data[i] -= s;
854 }
855 return *this;
856 }
857
866 template <typename T>
867 Self &
868 operator+=(const VariableLengthVector<T> & v)
869 {
870 itkAssertInDebugAndIgnoreInReleaseMacro(m_NumElements == v.GetSize());
871 for (ElementIdentifier i = 0; i < m_NumElements; ++i)
872 {
873 m_Data[i] += static_cast<ValueType>(v[i]);
874 }
875 return *this;
876 }
877
879 Self &
880 operator+=(TValue s)
881 {
882 for (ElementIdentifier i = 0; i < m_NumElements; ++i)
883 {
884 m_Data[i] += s;
885 }
886 return *this;
887 }
888
898 template <typename TExpr1, typename TExpr2, typename TBinaryOp>
899 Self &
900 operator+=(const VariableLengthVectorExpression<TExpr1, TExpr2, TBinaryOp> & rhs)
901 {
902 itkAssertInDebugAndIgnoreInReleaseMacro(rhs.Size() == Size());
903 for (ElementIdentifier i = 0; i < m_NumElements; ++i)
904 {
905 m_Data[i] += static_cast<ValueType>(rhs[i]);
906 }
907 return *this;
908 }
909
919 template <typename TExpr1, typename TExpr2, typename TBinaryOp>
920 Self &
921 operator-=(const VariableLengthVectorExpression<TExpr1, TExpr2, TBinaryOp> & rhs)
922 {
923 itkAssertInDebugAndIgnoreInReleaseMacro(rhs.Size() == Size());
924 for (ElementIdentifier i = 0; i < m_NumElements; ++i)
925 {
926 m_Data[i] -= static_cast<ValueType>(rhs[i]);
927 }
928 return *this;
929 }
930
936 template <typename T>
937 Self &
938 operator*=(T s)
939 {
940 const ValueType & sc = static_cast<ValueType>(s);
941 for (ElementIdentifier i = 0; i < m_NumElements; ++i)
942 {
943 m_Data[i] *= sc;
944 }
945 return *this;
946 }
947
951 Self &
952 operator*=(TValue s)
953 {
954 for (ElementIdentifier i = 0; i < m_NumElements; ++i)
955 {
956 m_Data[i] *= s;
957 }
958 return *this;
959 }
960
967 template <typename T>
968 Self &
969 operator/=(T s)
970 {
971 const RealValueType sc = s;
972 for (ElementIdentifier i = 0; i < m_NumElements; ++i)
973 {
974 m_Data[i] = static_cast<ValueType>(static_cast<RealValueType>(m_Data[i]) / sc);
975 }
976 return *this;
977 }
978
983 Self &
984 operator-(); // negation operator
985
986 bool
987 operator==(const Self & v) const;
988
989 ITK_UNEQUAL_OPERATOR_MEMBER_FUNCTION(Self);
990
992 [[nodiscard]] RealValueType
993 GetNorm() const;
994
996 [[nodiscard]] RealValueType
997 GetSquaredNorm() const;
998
1000 [[nodiscard]] bool
1001 IsAProxy() const
1002 {
1003 return !m_LetArrayManageMemory;
1004 }
1005
1006 [[nodiscard]] bool
1007 empty() const noexcept
1008 {
1009 return m_NumElements == 0;
1010 }
1011
1012 [[nodiscard]] size_type
1013 size() const noexcept
1014 {
1015 return m_NumElements;
1016 }
1017
1018 [[nodiscard]] reference
1019 at(size_type pos)
1020 {
1021 ExceptionThrowingBoundsCheck(pos);
1022 return m_Data[pos];
1023 }
1024
1025 [[nodiscard]] const_reference
1026 at(size_type pos) const
1027 {
1028 ExceptionThrowingBoundsCheck(pos);
1029 return m_Data[pos];
1030 }
1031
1032 [[nodiscard]] reference
1033 front()
1034 {
1035 return m_Data[0];
1036 }
1037
1038 [[nodiscard]] const_reference
1039 front() const
1040 {
1041 return m_Data[0];
1042 }
1043
1044 [[nodiscard]] reference
1045 back()
1046 {
1047 return m_Data[m_NumElements - 1];
1048 }
1049
1050 [[nodiscard]] const_reference
1051 back() const
1052 {
1053 return m_Data[m_NumElements - 1];
1054 }
1055
1056 [[nodiscard]] TValue *
1057 data() noexcept
1058 {
1059 return m_Data;
1060 }
1061
1062 [[nodiscard]] const TValue *
1063 data() const noexcept
1064 {
1065 return m_Data;
1066 }
1067
1068 [[nodiscard]] const_iterator
1069 cbegin() const noexcept
1070 {
1071 return m_Data;
1072 }
1073
1074 [[nodiscard]] iterator
1075 begin() noexcept
1076 {
1077 return m_Data;
1078 }
1079
1080 [[nodiscard]] const_iterator
1081 begin() const noexcept
1082 {
1083 return cbegin();
1084 }
1085
1086 [[nodiscard]] const_iterator
1087 cend() const noexcept
1088 {
1089 return m_Data + m_NumElements;
1090 }
1091
1092 [[nodiscard]] iterator
1093 end() noexcept
1094 {
1095 return m_Data + m_NumElements;
1096 }
1097
1098 [[nodiscard]] const_iterator
1099 end() const noexcept
1100 {
1101 return cend();
1102 }
1103
1104 [[nodiscard]] reverse_iterator
1105 rbegin()
1106 {
1107 return reverse_iterator{ end() };
1108 }
1109
1110 [[nodiscard]] const_reverse_iterator
1111 crbegin() const
1112 {
1113 return const_reverse_iterator{ cend() };
1114 }
1115
1116 [[nodiscard]] const_reverse_iterator
1117 rbegin() const
1118 {
1119 return crbegin();
1120 }
1121
1122 [[nodiscard]] reverse_iterator
1123 rend()
1124 {
1125 return reverse_iterator{ begin() };
1126 }
1127
1128 [[nodiscard]] const_reverse_iterator
1129 crend() const
1130 {
1131 return const_reverse_iterator{ cbegin() };
1132 }
1133
1134 [[nodiscard]] const_reverse_iterator
1135 rend() const
1136 {
1137 return crend();
1138 }
1139
1140private:
1141 bool m_LetArrayManageMemory{ true }; // if true, the array is responsible
1142 // for memory of data
1143 TValue * m_Data{}; // Array to hold data
1144 ElementIdentifier m_NumElements{ 0 };
1145
1146 void
1147 ExceptionThrowingBoundsCheck(size_type pos) const
1148 {
1149 if (pos >= m_NumElements)
1150 {
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) + ")!");
1154 }
1155 }
1156};
1157
1159namespace mpl
1160{
1170template <typename T>
1171struct IsArray : FalseType
1172{};
1173
1175template <typename T>
1176struct IsArray<itk::VariableLengthVector<T>> : TrueType
1177{};
1178
1179template <typename TExpr1, typename TExpr2, typename TBinaryOp>
1180struct IsArray<VariableLengthVectorExpression<TExpr1, TExpr2, TBinaryOp>> : TrueType
1181{};
1183} // namespace mpl
1185
1186namespace Details
1187{
1189
1201template <typename TExpr>
1202struct GetType
1203{
1204 using Type = TExpr;
1205
1209 static Type
1210 Load(const Type & v, unsigned int itkNotUsed(idx))
1211 {
1212 return v;
1213 }
1214};
1215
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)
1229{
1230 itkAssertInDebugAndIgnoreInReleaseMacro(lhs.Size() == rhs.Size());
1231 return lhs.Size();
1232}
1233
1235
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))
1247{
1248 return lhs.Size();
1249}
1250
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)
1263{
1264 return rhs.Size();
1265}
1266
1267template <typename T>
1268struct GetType<VariableLengthVector<T>>
1269{
1270 using Type = T;
1271 static Type
1272 Load(const VariableLengthVector<T> & v, unsigned int idx)
1273 {
1274 return v[idx];
1275 }
1276};
1277template <typename TExpr1, typename TExpr2, typename TBinaryOp>
1278struct GetType<VariableLengthVectorExpression<TExpr1, TExpr2, TBinaryOp>>
1279{
1280 using Type = typename VariableLengthVectorExpression<TExpr1, TExpr2, TBinaryOp>::ResType;
1281 static Type
1282 Load(const VariableLengthVectorExpression<TExpr1, TExpr2, TBinaryOp> & v, unsigned int idx)
1283 {
1284 return v[idx];
1285 }
1286};
1288
1289namespace op
1290{
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>>
1308{};
1309
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>>
1325{};
1326
1338template <typename TExpr1, typename TExpr2>
1339struct CanBeDivided : mpl::AndC<mpl::IsArray<TExpr1>::Value, std::is_arithmetic_v<TExpr2>>
1340{};
1341
1342} // namespace op
1343} // namespace Details
1345
1370template <typename TExpr1, typename TExpr2, typename TBinaryOp>
1371struct VariableLengthVectorExpression
1372{
1373 VariableLengthVectorExpression(const TExpr1 & lhs, const TExpr2 & rhs)
1374 : m_lhs(lhs)
1375 , m_rhs(rhs)
1376 {
1377 // Not necessary actually as end-user/developer is not expected to
1378 // provide new BinaryOperations
1379 static_assert(std::is_base_of_v<Details::op::BinaryOperationConcept, TBinaryOp>,
1380 "The Binary Operation shall inherit from BinaryOperationConcept");
1381 }
1382
1384 [[nodiscard]] unsigned int
1385 Size() const
1386 {
1387 return Details::GetSize(m_lhs, m_rhs);
1388 }
1389
1391 using ResType =
1392 typename mpl::PromoteType<typename Details::GetType<TExpr1>::Type, typename Details::GetType<TExpr2>::Type>::Type;
1394 using RealValueType = typename NumericTraits<ResType>::RealType;
1395
1406 ResType
1407 operator[](unsigned int idx) const
1408 {
1409 itkAssertInDebugAndIgnoreInReleaseMacro(idx < Size());
1410 return TBinaryOp::Apply(Details::GetType<TExpr1>::Load(m_lhs, idx), Details::GetType<TExpr2>::Load(m_rhs, idx));
1411 }
1412
1414 [[nodiscard]] RealValueType
1415 GetNorm() const;
1416
1418 [[nodiscard]] RealValueType
1419 GetSquaredNorm() const;
1420
1421private:
1422 const TExpr1 & m_lhs;
1423 const TExpr2 & m_rhs;
1424};
1425
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)
1439{
1440 return VariableLengthVectorExpression<TExpr1, TExpr2, Details::op::Plus>(lhs, rhs);
1441}
1442
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)
1456{
1457 return VariableLengthVectorExpression<TExpr1, TExpr2, Details::op::Sub>(lhs, rhs);
1458}
1459
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)
1472{
1473 return VariableLengthVectorExpression<TExpr1, TExpr2, Details::op::Mult>(lhs, rhs);
1474}
1475
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)
1487{
1488 return VariableLengthVectorExpression<TExpr1, TExpr2, Details::op::Div>(lhs, rhs);
1489}
1490
1494template <typename TExpr1, typename TExpr2, typename TBinaryOp>
1495std::ostream &
1496operator<<(std::ostream & os, const VariableLengthVectorExpression<TExpr1, TExpr2, TBinaryOp> & v)
1497{
1498 os << '[';
1499 if (v.Size() != 0)
1500 {
1501 os << v[0];
1502 for (unsigned int i = 1, N = v.Size(); i != N; ++i)
1503 {
1504 os << ", " << v[i];
1505 }
1506 }
1507 return os << ']';
1508}
1509
1515template <typename TExpr>
1516inline std::enable_if_t<mpl::IsArray<TExpr>::Value, typename TExpr::RealValueType>
1517GetNorm(const TExpr & v)
1518{
1519 return static_cast<typename TExpr::RealValueType>(std::sqrt(static_cast<double>(GetSquaredNorm(v))));
1520}
1521
1527template <typename TExpr>
1528inline std::enable_if_t<mpl::IsArray<TExpr>::Value, typename TExpr::RealValueType>
1529GetSquaredNorm(const TExpr & v)
1530{
1531 using RealValueType = typename TExpr::RealValueType;
1532 RealValueType sum = 0.0;
1533 for (unsigned int i = 0, N = v.Size(); i < N; ++i)
1534 {
1535 const RealValueType value = v[i];
1536 sum += value * value;
1537 }
1538 return sum;
1539}
1540
1542
1546template <typename TValue>
1547std::ostream &
1548operator<<(std::ostream & os, const VariableLengthVector<TValue> & arr)
1549{
1550 const unsigned int length = arr.Size();
1551 const int last = static_cast<unsigned int>(length) - 1;
1552
1553 os << '[';
1554 for (int i = 0; i < last; ++i)
1555 {
1556 os << arr[i] << ", ";
1557 }
1558 if (length >= 1)
1559 {
1560 os << arr[last];
1561 }
1562 os << ']';
1563 return os;
1564}
1565
1567
1585template <typename T>
1586inline void
1588{
1589 l_.Swap(r_);
1590}
1591
1592} // namespace itk
1593
1595
1596#ifndef ITK_MANUAL_INSTANTIATION
1597# include "itkVariableLengthVector.hxx"
1598#endif
1599
1600#endif
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
Definition itkArray.h:244
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)