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 "itkIsNumber.h"
28#include "itkPromoteType.h"
30
31namespace itk
32{
33
34template <typename TExpr1, typename TExpr2, typename TBinaryOp>
35struct VariableLengthVectorExpression;
36
91template <typename TValue>
92class ITK_TEMPLATE_EXPORT VariableLengthVector
93{
94public:
99
111 struct AllocateRootPolicy
112 {};
113
127 struct AlwaysReallocate : AllocateRootPolicy
128 {
129 bool
130 operator()(unsigned int itkNotUsed(newSize), unsigned int itkNotUsed(oldSize)) const
131 {
132 return true;
133 }
134 };
135
153 struct NeverReallocate : AllocateRootPolicy
154 {
155 bool
156 operator()([[maybe_unused]] unsigned int newSize, [[maybe_unused]] unsigned int oldSize) const
157 {
158 itkAssertInDebugAndIgnoreInReleaseMacro(newSize == oldSize &&
159 "SetSize is expected to never change the VariableLengthVector size...");
160 return true;
161 }
162 };
163
181 struct ShrinkToFit : AllocateRootPolicy
182 {
183 bool
184 operator()(unsigned int newSize, unsigned int oldSize) const
185 {
186 return newSize != oldSize;
187 }
188 };
189
216 struct DontShrinkToFit : AllocateRootPolicy
217 {
218 bool
219 operator()(unsigned int newSize, unsigned int oldSize) const
220 {
221 return newSize > oldSize;
222 }
223 };
224
243 struct KeepValuesRootPolicy
244 {};
245
267 struct KeepOldValues : KeepValuesRootPolicy
268 {
269 template <typename TValue2>
270 void
271 operator()(unsigned int newSize, unsigned int oldSize, TValue2 * oldBuffer, TValue2 * newBuffer) const
272 {
273 const size_t nb = std::min(newSize, oldSize);
274 if (nb > 0)
275 {
276 itkAssertInDebugAndIgnoreInReleaseMacro(newBuffer);
277 itkAssertInDebugAndIgnoreInReleaseMacro(oldBuffer);
278 std::copy_n(oldBuffer, nb, newBuffer);
279 }
280 }
281 };
282
299 struct DumpOldValues : KeepValuesRootPolicy
300 {
301 template <typename TValue2>
302 void
303 operator()(unsigned int itkNotUsed(newSize),
304 unsigned int itkNotUsed(oldSize),
305 TValue2 * itkNotUsed(oldBuffer),
306 TValue2 * itkNotUsed(newBuffer)) const
307 {}
308 };
310
311
313 using ValueType = TValue;
314 using ComponentType = TValue;
315 using RealValueType = typename NumericTraits<ValueType>::RealType;
316 using Self = VariableLengthVector;
317
319 using ElementIdentifier = unsigned int;
320
321 // Nested types from C++ Standard section "Container requirements" [container.reqmts], and from `std::vector`:
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>;
331
338 VariableLengthVector() = default;
339
348 explicit VariableLengthVector(unsigned int length);
349
351 explicit VariableLengthVector(unsigned int length, const TValue & value);
352
366 VariableLengthVector(ValueType * datain, unsigned int sz, bool LetArrayManageMemory = false);
367
387 VariableLengthVector(const ValueType * datain, unsigned int sz, bool LetArrayManageMemory = false);
388
408 template <typename T>
409 VariableLengthVector(const VariableLengthVector<T> & v)
410 : VariableLengthVector(v.Size())
411 {
412 if (m_NumElements != 0)
413 {
414 itkAssertInDebugAndIgnoreInReleaseMacro(m_Data != nullptr);
415 for (ElementIdentifier i = 0; i < m_NumElements; ++i)
416 {
417 this->m_Data[i] = static_cast<ValueType>(v[i]);
418 }
419 }
420 else
421 {
422 m_Data = nullptr;
423 }
424 }
425
434 VariableLengthVector(const VariableLengthVector<TValue> & v);
435
444 void
445 Swap(Self & v) noexcept
446 {
447 itkAssertInDebugAndIgnoreInReleaseMacro(m_LetArrayManageMemory == v.m_LetArrayManageMemory);
448 using std::swap;
449 swap(v.m_Data, m_Data);
450 swap(v.m_NumElements, m_NumElements);
451 }
452
460 VariableLengthVector(Self && v) noexcept;
461
470 Self &
471 operator=(Self && v) noexcept;
472
489 template <typename TExpr1, typename TExpr2, typename TBinaryOp>
490 VariableLengthVector(const VariableLengthVectorExpression<TExpr1, TExpr2, TBinaryOp> & rhs);
491
511 template <typename TExpr1, typename TExpr2, typename TBinaryOp>
512 Self &
513 operator=(const VariableLengthVectorExpression<TExpr1, TExpr2, TBinaryOp> & rhs);
514
518 void
519 Fill(const TValue & v);
520
533 template <typename T>
534 Self &
535 operator=(const VariableLengthVector<T> & v)
536 {
537 // No self assignment test is done. Indeed:
538 // - the operator already resists self assignment through a strong exception
539 // guarantee
540 // - the test becomes a pessimization as we never write
541 // VLV<const TValue> vcref(v.GetDataPointer(), v.GetSize());
542 // ...;
543 // v = vcref;
544 const ElementIdentifier N = v.Size();
545 this->SetSize(N, DontShrinkToFit(), DumpOldValues());
546 for (ElementIdentifier i = 0; i < N; ++i)
547 {
548 this->m_Data[i] = static_cast<ValueType>(v[i]);
549 }
550 return *this;
551 }
552
568 Self &
569 operator=(const Self & v);
570
579 Self &
580 FastAssign(const Self & v);
581
589 Self &
590 operator=(const TValue & v);
591
594 [[nodiscard]] unsigned int
595 Size() const
596 {
597 return m_NumElements;
598 }
599 [[nodiscard]] unsigned int
600 GetSize() const
601 {
602 return m_NumElements;
603 }
604 [[nodiscard]] unsigned int
605 GetNumberOfElements() const
606 {
607 return m_NumElements;
608 }
611 TValue &
612 operator[](unsigned int i)
613 {
614 return this->m_Data[i];
615 }
616
618 const TValue &
619 operator[](unsigned int i) const
620 {
621 return this->m_Data[i];
622 }
623
625 [[nodiscard]] const TValue &
626 GetElement(unsigned int i) const
627 {
628 return m_Data[i];
629 }
630
632 void
633 SetElement(unsigned int i, const TValue & value)
634 {
635 m_Data[i] = value;
636 }
637
671 template <typename TReallocatePolicy, typename TKeepValuesPolicy>
672 void
673 SetSize(unsigned int sz, TReallocatePolicy reallocatePolicy, TKeepValuesPolicy keepValues);
674
685 void
686 SetSize(unsigned int sz, bool destroyExistingData = true)
687 {
688 // Stays compatible with previous code version
689 // And works around the fact C++03 template functions can't have default
690 // arguments on template types.
691 if (destroyExistingData)
692 {
693 SetSize(sz, AlwaysReallocate(), KeepOldValues());
694 }
695 else
696 {
697 SetSize(sz, ShrinkToFit(), KeepOldValues());
698 }
699 }
700
703 void
704 DestroyExistingData();
705
718 void
719 SetData(TValue * datain, bool LetArrayManageMemory = false);
720
735 void
736 SetData(TValue * datain, unsigned int sz, bool LetArrayManageMemory = false);
737
748 ~VariableLengthVector();
749
764 void
765 Reserve(ElementIdentifier size);
766
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;
776#endif
777
778 [[nodiscard]] const TValue *
779 GetDataPointer() const
780 {
781 return m_Data;
782 }
783
786 Self &
787 operator--()
788 {
789 for (ElementIdentifier i = 0; i < m_NumElements; ++i)
790 {
791 this->m_Data[i] -= static_cast<ValueType>(1.0);
792 }
793 return *this;
794 }
795
797 Self &
798 operator++() // prefix operator ++v;
799 {
800 for (ElementIdentifier i = 0; i < m_NumElements; ++i)
801 {
802 this->m_Data[i] += static_cast<ValueType>(1.0);
803 }
804 return *this;
805 }
806
809 Self
810 operator--(int) // postfix operator v--;
811 {
812 Self tmp(*this);
813
814 --tmp;
815 return tmp;
816 }
817
819 Self
820 operator++(int) // postfix operator v++;
821 {
822 Self tmp(*this);
823
824 ++tmp;
825 return tmp;
826 }
827
836 template <typename T>
837 Self &
838 operator-=(const VariableLengthVector<T> & v)
839 {
840 itkAssertInDebugAndIgnoreInReleaseMacro(m_NumElements == v.GetSize());
841 for (ElementIdentifier i = 0; i < m_NumElements; ++i)
842 {
843 m_Data[i] -= static_cast<ValueType>(v[i]);
844 }
845 return *this;
846 }
847
849 Self &
850 operator-=(TValue s)
851 {
852 for (ElementIdentifier i = 0; i < m_NumElements; ++i)
853 {
854 m_Data[i] -= s;
855 }
856 return *this;
857 }
858
867 template <typename T>
868 Self &
869 operator+=(const VariableLengthVector<T> & v)
870 {
871 itkAssertInDebugAndIgnoreInReleaseMacro(m_NumElements == v.GetSize());
872 for (ElementIdentifier i = 0; i < m_NumElements; ++i)
873 {
874 m_Data[i] += static_cast<ValueType>(v[i]);
875 }
876 return *this;
877 }
878
880 Self &
881 operator+=(TValue s)
882 {
883 for (ElementIdentifier i = 0; i < m_NumElements; ++i)
884 {
885 m_Data[i] += s;
886 }
887 return *this;
888 }
889
899 template <typename TExpr1, typename TExpr2, typename TBinaryOp>
900 Self &
901 operator+=(const VariableLengthVectorExpression<TExpr1, TExpr2, TBinaryOp> & rhs)
902 {
903 itkAssertInDebugAndIgnoreInReleaseMacro(rhs.Size() == Size());
904 for (ElementIdentifier i = 0; i < m_NumElements; ++i)
905 {
906 m_Data[i] += static_cast<ValueType>(rhs[i]);
907 }
908 return *this;
909 }
910
920 template <typename TExpr1, typename TExpr2, typename TBinaryOp>
921 Self &
922 operator-=(const VariableLengthVectorExpression<TExpr1, TExpr2, TBinaryOp> & rhs)
923 {
924 itkAssertInDebugAndIgnoreInReleaseMacro(rhs.Size() == Size());
925 for (ElementIdentifier i = 0; i < m_NumElements; ++i)
926 {
927 m_Data[i] -= static_cast<ValueType>(rhs[i]);
928 }
929 return *this;
930 }
931
937 template <typename T>
938 Self &
939 operator*=(T s)
940 {
941 const ValueType & sc = static_cast<ValueType>(s);
942 for (ElementIdentifier i = 0; i < m_NumElements; ++i)
943 {
944 m_Data[i] *= sc;
945 }
946 return *this;
947 }
948
952 Self &
953 operator*=(TValue s)
954 {
955 for (ElementIdentifier i = 0; i < m_NumElements; ++i)
956 {
957 m_Data[i] *= s;
958 }
959 return *this;
960 }
961
968 template <typename T>
969 Self &
970 operator/=(T s)
971 {
972 const RealValueType sc = s;
973 for (ElementIdentifier i = 0; i < m_NumElements; ++i)
974 {
975 m_Data[i] = static_cast<ValueType>(static_cast<RealValueType>(m_Data[i]) / sc);
976 }
977 return *this;
978 }
979
984 Self &
985 operator-(); // negation operator
986
987 bool
988 operator==(const Self & v) const;
989
990 ITK_UNEQUAL_OPERATOR_MEMBER_FUNCTION(Self);
991
993 [[nodiscard]] RealValueType
994 GetNorm() const;
995
997 [[nodiscard]] RealValueType
998 GetSquaredNorm() const;
999
1001 [[nodiscard]] bool
1002 IsAProxy() const
1003 {
1004 return !m_LetArrayManageMemory;
1005 }
1006
1007 [[nodiscard]] bool
1008 empty() const noexcept
1009 {
1010 return m_NumElements == 0;
1011 }
1012
1013 [[nodiscard]] size_type
1014 size() const noexcept
1015 {
1016 return m_NumElements;
1017 }
1018
1019 [[nodiscard]] reference
1020 at(size_type pos)
1021 {
1022 ExceptionThrowingBoundsCheck(pos);
1023 return m_Data[pos];
1024 }
1025
1026 [[nodiscard]] const_reference
1027 at(size_type pos) const
1028 {
1029 ExceptionThrowingBoundsCheck(pos);
1030 return m_Data[pos];
1031 }
1032
1033 [[nodiscard]] reference
1034 front()
1035 {
1036 return m_Data[0];
1037 }
1038
1039 [[nodiscard]] const_reference
1040 front() const
1041 {
1042 return m_Data[0];
1043 }
1044
1045 [[nodiscard]] reference
1046 back()
1047 {
1048 return m_Data[m_NumElements - 1];
1049 }
1050
1051 [[nodiscard]] const_reference
1052 back() const
1053 {
1054 return m_Data[m_NumElements - 1];
1055 }
1056
1057 [[nodiscard]] TValue *
1058 data() noexcept
1059 {
1060 return m_Data;
1061 }
1062
1063 [[nodiscard]] const TValue *
1064 data() const noexcept
1065 {
1066 return m_Data;
1067 }
1068
1069 [[nodiscard]] const_iterator
1070 cbegin() const noexcept
1071 {
1072 return m_Data;
1073 }
1074
1075 [[nodiscard]] iterator
1076 begin() noexcept
1077 {
1078 return m_Data;
1079 }
1080
1081 [[nodiscard]] const_iterator
1082 begin() const noexcept
1083 {
1084 return cbegin();
1085 }
1086
1087 [[nodiscard]] const_iterator
1088 cend() const noexcept
1089 {
1090 return m_Data + m_NumElements;
1091 }
1092
1093 [[nodiscard]] iterator
1094 end() noexcept
1095 {
1096 return m_Data + m_NumElements;
1097 }
1098
1099 [[nodiscard]] const_iterator
1100 end() const noexcept
1101 {
1102 return cend();
1103 }
1104
1105 [[nodiscard]] reverse_iterator
1106 rbegin()
1107 {
1108 return reverse_iterator{ end() };
1109 }
1110
1111 [[nodiscard]] const_reverse_iterator
1112 crbegin() const
1113 {
1114 return const_reverse_iterator{ cend() };
1115 }
1116
1117 [[nodiscard]] const_reverse_iterator
1118 rbegin() const
1119 {
1120 return crbegin();
1121 }
1122
1123 [[nodiscard]] reverse_iterator
1124 rend()
1125 {
1126 return reverse_iterator{ begin() };
1127 }
1128
1129 [[nodiscard]] const_reverse_iterator
1130 crend() const
1131 {
1132 return const_reverse_iterator{ cbegin() };
1133 }
1134
1135 [[nodiscard]] const_reverse_iterator
1136 rend() const
1137 {
1138 return crend();
1139 }
1140
1141private:
1142 bool m_LetArrayManageMemory{ true }; // if true, the array is responsible
1143 // for memory of data
1144 TValue * m_Data{}; // Array to hold data
1145 ElementIdentifier m_NumElements{ 0 };
1146
1147 void
1148 ExceptionThrowingBoundsCheck(size_type pos) const
1149 {
1150 if (pos >= m_NumElements)
1151 {
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) + ")!");
1155 }
1156 }
1157};
1158
1160namespace mpl
1161{
1171template <typename T>
1172struct IsArray : FalseType
1173{};
1174
1176template <typename T>
1177struct IsArray<itk::VariableLengthVector<T>> : TrueType
1178{};
1179
1180template <typename TExpr1, typename TExpr2, typename TBinaryOp>
1181struct IsArray<VariableLengthVectorExpression<TExpr1, TExpr2, TBinaryOp>> : TrueType
1182{};
1184} // namespace mpl
1186
1187namespace Details
1188{
1190
1202template <typename TExpr>
1203struct GetType
1204{
1205 using Type = TExpr;
1206
1210 static Type
1211 Load(const Type & v, unsigned int itkNotUsed(idx))
1212 {
1213 return v;
1214 }
1215};
1216
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)
1230{
1231 itkAssertInDebugAndIgnoreInReleaseMacro(lhs.Size() == rhs.Size());
1232 return lhs.Size();
1233}
1234
1236
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))
1248{
1249 return lhs.Size();
1250}
1251
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)
1264{
1265 return rhs.Size();
1266}
1267
1268template <typename T>
1269struct GetType<VariableLengthVector<T>>
1270{
1271 using Type = T;
1272 static Type
1273 Load(const VariableLengthVector<T> & v, unsigned int idx)
1274 {
1275 return v[idx];
1276 }
1277};
1278template <typename TExpr1, typename TExpr2, typename TBinaryOp>
1279struct GetType<VariableLengthVectorExpression<TExpr1, TExpr2, TBinaryOp>>
1280{
1281 using Type = typename VariableLengthVectorExpression<TExpr1, TExpr2, TBinaryOp>::ResType;
1282 static Type
1283 Load(const VariableLengthVectorExpression<TExpr1, TExpr2, TBinaryOp> & v, unsigned int idx)
1284 {
1285 return v[idx];
1286 }
1287};
1289
1290namespace op
1291{
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>>>
1309{};
1310
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>>>
1326{};
1327
1339template <typename TExpr1, typename TExpr2>
1340struct CanBeDivided : mpl::And<mpl::IsArray<TExpr1>, mpl::IsNumber<TExpr2>>
1341{};
1342
1343} // namespace op
1344} // namespace Details
1346
1371template <typename TExpr1, typename TExpr2, typename TBinaryOp>
1372struct VariableLengthVectorExpression
1373{
1374 VariableLengthVectorExpression(const TExpr1 & lhs, const TExpr2 & rhs)
1375 : m_lhs(lhs)
1376 , m_rhs(rhs)
1377 {
1378 // Not necessary actually as end-user/developer is not expected to
1379 // provide new BinaryOperations
1380 static_assert(std::is_base_of_v<Details::op::BinaryOperationConcept, TBinaryOp>,
1381 "The Binary Operation shall inherit from BinaryOperationConcept");
1382 }
1383
1385 [[nodiscard]] unsigned int
1386 Size() const
1387 {
1388 return Details::GetSize(m_lhs, m_rhs);
1389 }
1390
1392 using ResType =
1393 typename mpl::PromoteType<typename Details::GetType<TExpr1>::Type, typename Details::GetType<TExpr2>::Type>::Type;
1395 using RealValueType = typename NumericTraits<ResType>::RealType;
1396
1407 ResType
1408 operator[](unsigned int idx) const
1409 {
1410 itkAssertInDebugAndIgnoreInReleaseMacro(idx < Size());
1411 return TBinaryOp::Apply(Details::GetType<TExpr1>::Load(m_lhs, idx), Details::GetType<TExpr2>::Load(m_rhs, idx));
1412 }
1413
1415 [[nodiscard]] RealValueType
1416 GetNorm() const;
1417
1419 [[nodiscard]] RealValueType
1420 GetSquaredNorm() const;
1421
1422private:
1423 const TExpr1 & m_lhs;
1424 const TExpr2 & m_rhs;
1425};
1426
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)
1440{
1441 return VariableLengthVectorExpression<TExpr1, TExpr2, Details::op::Plus>(lhs, rhs);
1442}
1443
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)
1457{
1458 return VariableLengthVectorExpression<TExpr1, TExpr2, Details::op::Sub>(lhs, rhs);
1459}
1460
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)
1473{
1474 return VariableLengthVectorExpression<TExpr1, TExpr2, Details::op::Mult>(lhs, rhs);
1475}
1476
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)
1488{
1489 return VariableLengthVectorExpression<TExpr1, TExpr2, Details::op::Div>(lhs, rhs);
1490}
1491
1495template <typename TExpr1, typename TExpr2, typename TBinaryOp>
1496std::ostream &
1497operator<<(std::ostream & os, const VariableLengthVectorExpression<TExpr1, TExpr2, TBinaryOp> & v)
1498{
1499 os << '[';
1500 if (v.Size() != 0)
1501 {
1502 os << v[0];
1503 for (unsigned int i = 1, N = v.Size(); i != N; ++i)
1504 {
1505 os << ", " << v[i];
1506 }
1507 }
1508 return os << ']';
1509}
1510
1516template <typename TExpr>
1517inline std::enable_if_t<mpl::IsArray<TExpr>::Value, typename TExpr::RealValueType>
1518GetNorm(const TExpr & v)
1519{
1520 return static_cast<typename TExpr::RealValueType>(std::sqrt(static_cast<double>(GetSquaredNorm(v))));
1521}
1522
1528template <typename TExpr>
1529inline std::enable_if_t<mpl::IsArray<TExpr>::Value, typename TExpr::RealValueType>
1530GetSquaredNorm(const TExpr & v)
1531{
1532 using RealValueType = typename TExpr::RealValueType;
1533 RealValueType sum = 0.0;
1534 for (unsigned int i = 0, N = v.Size(); i < N; ++i)
1535 {
1536 const RealValueType value = v[i];
1537 sum += value * value;
1538 }
1539 return sum;
1540}
1541
1543
1547template <typename TValue>
1548std::ostream &
1549operator<<(std::ostream & os, const VariableLengthVector<TValue> & arr)
1550{
1551 const unsigned int length = arr.Size();
1552 const int last = static_cast<unsigned int>(length) - 1;
1553
1554 os << '[';
1555 for (int i = 0; i < last; ++i)
1556 {
1557 os << arr[i] << ", ";
1558 }
1559 if (length >= 1)
1560 {
1561 os << arr[last];
1562 }
1563 os << ']';
1564 return os;
1565}
1566
1568
1586template <typename T>
1587inline void
1589{
1590 l_.Swap(r_);
1591}
1592
1593} // namespace itk
1594
1596
1597#ifndef ITK_MANUAL_INSTANTIATION
1598# include "itkVariableLengthVector.hxx"
1599#endif
1600
1601#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:247
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)