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 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);
277 }
278 };
279
296 struct DumpOldValues : KeepValuesRootPolicy
297 {
298 template <typename TValue2>
299 void
300 operator()(unsigned int itkNotUsed(newSize),
301 unsigned int itkNotUsed(oldSize),
302 TValue2 * itkNotUsed(oldBuffer),
303 TValue2 * itkNotUsed(newBuffer)) const
304 {}
305 };
307
308
310 using ValueType = TValue;
311 using ComponentType = TValue;
312 using RealValueType = typename NumericTraits<ValueType>::RealType;
313 using Self = VariableLengthVector;
314
316 using ElementIdentifier = unsigned int;
317
318 // Nested types from C++ Standard section "Container requirements" [container.reqmts], and from `std::vector`:
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>;
328
335 VariableLengthVector() = default;
336
345 explicit VariableLengthVector(unsigned int length);
346
348 explicit VariableLengthVector(unsigned int length, const TValue & value);
349
363 VariableLengthVector(ValueType * datain, unsigned int sz, bool LetArrayManageMemory = false);
364
384 VariableLengthVector(const ValueType * datain, unsigned int sz, bool LetArrayManageMemory = false);
385
405 template <typename T>
406 VariableLengthVector(const VariableLengthVector<T> & v)
407 : VariableLengthVector(v.Size())
408 {
409 if (m_NumElements != 0)
410 {
411 itkAssertInDebugAndIgnoreInReleaseMacro(m_Data != nullptr);
412 for (ElementIdentifier i = 0; i < m_NumElements; ++i)
413 {
414 this->m_Data[i] = static_cast<ValueType>(v[i]);
415 }
416 }
417 else
418 {
419 m_Data = nullptr;
420 }
421 }
422
431 VariableLengthVector(const VariableLengthVector<TValue> & v);
432
441 void
442 Swap(Self & v) noexcept
443 {
444 itkAssertInDebugAndIgnoreInReleaseMacro(m_LetArrayManageMemory == v.m_LetArrayManageMemory);
445 using std::swap;
446 swap(v.m_Data, m_Data);
447 swap(v.m_NumElements, m_NumElements);
448 }
449
457 VariableLengthVector(Self && v) noexcept;
458
467 Self &
468 operator=(Self && v) noexcept;
469
486 template <typename TExpr1, typename TExpr2, typename TBinaryOp>
487 VariableLengthVector(const VariableLengthVectorExpression<TExpr1, TExpr2, TBinaryOp> & rhs);
488
508 template <typename TExpr1, typename TExpr2, typename TBinaryOp>
509 Self &
510 operator=(const VariableLengthVectorExpression<TExpr1, TExpr2, TBinaryOp> & rhs);
511
515 void
516 Fill(const TValue & v);
517
530 template <typename T>
531 Self &
532 operator=(const VariableLengthVector<T> & v)
533 {
534 // No self assignment test is done. Indeed:
535 // - the operator already resists self assignment through a strong exception
536 // guarantee
537 // - the test becomes a pessimization as we never write
538 // VLV<const TValue> vcref(v.GetDataPointer(), v.GetSize());
539 // ...;
540 // v = vcref;
541 const ElementIdentifier N = v.Size();
542 this->SetSize(N, DontShrinkToFit(), DumpOldValues());
543 for (ElementIdentifier i = 0; i < N; ++i)
544 {
545 this->m_Data[i] = static_cast<ValueType>(v[i]);
546 }
547 return *this;
548 }
549
565 Self &
566 operator=(const Self & v);
567
576 Self &
577 FastAssign(const Self & v);
578
586 Self &
587 operator=(const TValue & v);
588
591 [[nodiscard]] unsigned int
592 Size() const
593 {
594 return m_NumElements;
595 }
596 [[nodiscard]] unsigned int
597 GetSize() const
598 {
599 return m_NumElements;
600 }
601 [[nodiscard]] unsigned int
602 GetNumberOfElements() const
603 {
604 return m_NumElements;
605 }
608 TValue &
609 operator[](unsigned int i)
610 {
611 return this->m_Data[i];
612 }
613
615 const TValue &
616 operator[](unsigned int i) const
617 {
618 return this->m_Data[i];
619 }
620
622 [[nodiscard]] const TValue &
623 GetElement(unsigned int i) const
624 {
625 return m_Data[i];
626 }
627
629 void
630 SetElement(unsigned int i, const TValue & value)
631 {
632 m_Data[i] = value;
633 }
634
668 template <typename TReallocatePolicy, typename TKeepValuesPolicy>
669 void
670 SetSize(unsigned int sz, TReallocatePolicy reallocatePolicy, TKeepValuesPolicy keepValues);
671
682 void
683 SetSize(unsigned int sz, bool destroyExistingData = true)
684 {
685 // Stays compatible with previous code version
686 // And works around the fact C++03 template functions can't have default
687 // arguments on template types.
688 if (destroyExistingData)
689 {
690 SetSize(sz, AlwaysReallocate(), KeepOldValues());
691 }
692 else
693 {
694 SetSize(sz, ShrinkToFit(), KeepOldValues());
695 }
696 }
697
700 void
701 DestroyExistingData();
702
715 void
716 SetData(TValue * datain, bool LetArrayManageMemory = false);
717
732 void
733 SetData(TValue * datain, unsigned int sz, bool LetArrayManageMemory = false);
734
745 ~VariableLengthVector();
746
761 void
762 Reserve(ElementIdentifier size);
763
764#ifndef ITK_FUTURE_LEGACY_REMOVE
770 [[deprecated("Please consider calling `std::make_unique<TValue[]>(size)` instead.")]] [[nodiscard]] TValue *
771 AllocateElements(ElementIdentifier size) const;
772#endif
773
774 [[nodiscard]] const TValue *
775 GetDataPointer() const
776 {
777 return m_Data;
778 }
779
782 Self &
783 operator--()
784 {
785 for (ElementIdentifier i = 0; i < m_NumElements; ++i)
786 {
787 this->m_Data[i] -= static_cast<ValueType>(1.0);
788 }
789 return *this;
790 }
791
793 Self &
794 operator++() // prefix operator ++v;
795 {
796 for (ElementIdentifier i = 0; i < m_NumElements; ++i)
797 {
798 this->m_Data[i] += static_cast<ValueType>(1.0);
799 }
800 return *this;
801 }
802
805 Self
806 operator--(int) // postfix operator v--;
807 {
808 Self tmp(*this);
809
810 --tmp;
811 return tmp;
812 }
813
815 Self
816 operator++(int) // postfix operator v++;
817 {
818 Self tmp(*this);
819
820 ++tmp;
821 return tmp;
822 }
823
832 template <typename T>
833 Self &
834 operator-=(const VariableLengthVector<T> & v)
835 {
836 itkAssertInDebugAndIgnoreInReleaseMacro(m_NumElements == v.GetSize());
837 for (ElementIdentifier i = 0; i < m_NumElements; ++i)
838 {
839 m_Data[i] -= static_cast<ValueType>(v[i]);
840 }
841 return *this;
842 }
843
845 Self &
846 operator-=(TValue s)
847 {
848 for (ElementIdentifier i = 0; i < m_NumElements; ++i)
849 {
850 m_Data[i] -= s;
851 }
852 return *this;
853 }
854
863 template <typename T>
864 Self &
865 operator+=(const VariableLengthVector<T> & v)
866 {
867 itkAssertInDebugAndIgnoreInReleaseMacro(m_NumElements == v.GetSize());
868 for (ElementIdentifier i = 0; i < m_NumElements; ++i)
869 {
870 m_Data[i] += static_cast<ValueType>(v[i]);
871 }
872 return *this;
873 }
874
876 Self &
877 operator+=(TValue s)
878 {
879 for (ElementIdentifier i = 0; i < m_NumElements; ++i)
880 {
881 m_Data[i] += s;
882 }
883 return *this;
884 }
885
895 template <typename TExpr1, typename TExpr2, typename TBinaryOp>
896 Self &
897 operator+=(const VariableLengthVectorExpression<TExpr1, TExpr2, TBinaryOp> & rhs)
898 {
899 itkAssertInDebugAndIgnoreInReleaseMacro(rhs.Size() == Size());
900 for (ElementIdentifier i = 0; i < m_NumElements; ++i)
901 {
902 m_Data[i] += static_cast<ValueType>(rhs[i]);
903 }
904 return *this;
905 }
906
916 template <typename TExpr1, typename TExpr2, typename TBinaryOp>
917 Self &
918 operator-=(const VariableLengthVectorExpression<TExpr1, TExpr2, TBinaryOp> & rhs)
919 {
920 itkAssertInDebugAndIgnoreInReleaseMacro(rhs.Size() == Size());
921 for (ElementIdentifier i = 0; i < m_NumElements; ++i)
922 {
923 m_Data[i] -= static_cast<ValueType>(rhs[i]);
924 }
925 return *this;
926 }
927
933 template <typename T>
934 Self &
935 operator*=(T s)
936 {
937 const ValueType & sc = static_cast<ValueType>(s);
938 for (ElementIdentifier i = 0; i < m_NumElements; ++i)
939 {
940 m_Data[i] *= sc;
941 }
942 return *this;
943 }
944
948 Self &
949 operator*=(TValue s)
950 {
951 for (ElementIdentifier i = 0; i < m_NumElements; ++i)
952 {
953 m_Data[i] *= s;
954 }
955 return *this;
956 }
957
964 template <typename T>
965 Self &
966 operator/=(T s)
967 {
968 const RealValueType sc = s;
969 for (ElementIdentifier i = 0; i < m_NumElements; ++i)
970 {
971 m_Data[i] = static_cast<ValueType>(static_cast<RealValueType>(m_Data[i]) / sc);
972 }
973 return *this;
974 }
975
980 Self &
981 operator-(); // negation operator
982
983 bool
984 operator==(const Self & v) const;
985
986 ITK_UNEQUAL_OPERATOR_MEMBER_FUNCTION(Self);
987
989 [[nodiscard]] RealValueType
990 GetNorm() const;
991
993 [[nodiscard]] RealValueType
994 GetSquaredNorm() const;
995
997 [[nodiscard]] bool
998 IsAProxy() const
999 {
1000 return !m_LetArrayManageMemory;
1001 }
1002
1003 [[nodiscard]] bool
1004 empty() const noexcept
1005 {
1006 return m_NumElements == 0;
1007 }
1008
1009 [[nodiscard]] size_type
1010 size() const noexcept
1011 {
1012 return m_NumElements;
1013 }
1014
1015 [[nodiscard]] reference
1016 at(size_type pos)
1017 {
1018 ExceptionThrowingBoundsCheck(pos);
1019 return m_Data[pos];
1020 }
1021
1022 [[nodiscard]] const_reference
1023 at(size_type pos) const
1024 {
1025 ExceptionThrowingBoundsCheck(pos);
1026 return m_Data[pos];
1027 }
1028
1029 [[nodiscard]] reference
1030 front()
1031 {
1032 return m_Data[0];
1033 }
1034
1035 [[nodiscard]] const_reference
1036 front() const
1037 {
1038 return m_Data[0];
1039 }
1040
1041 [[nodiscard]] reference
1042 back()
1043 {
1044 return m_Data[m_NumElements - 1];
1045 }
1046
1047 [[nodiscard]] const_reference
1048 back() const
1049 {
1050 return m_Data[m_NumElements - 1];
1051 }
1052
1053 [[nodiscard]] TValue *
1054 data() noexcept
1055 {
1056 return m_Data;
1057 }
1058
1059 [[nodiscard]] const TValue *
1060 data() const noexcept
1061 {
1062 return m_Data;
1063 }
1064
1065 [[nodiscard]] const_iterator
1066 cbegin() const noexcept
1067 {
1068 return m_Data;
1069 }
1070
1071 [[nodiscard]] iterator
1072 begin() noexcept
1073 {
1074 return m_Data;
1075 }
1076
1077 [[nodiscard]] const_iterator
1078 begin() const noexcept
1079 {
1080 return cbegin();
1081 }
1082
1083 [[nodiscard]] const_iterator
1084 cend() const noexcept
1085 {
1086 return m_Data + m_NumElements;
1087 }
1088
1089 [[nodiscard]] iterator
1090 end() noexcept
1091 {
1092 return m_Data + m_NumElements;
1093 }
1094
1095 [[nodiscard]] const_iterator
1096 end() const noexcept
1097 {
1098 return cend();
1099 }
1100
1101 [[nodiscard]] reverse_iterator
1102 rbegin()
1103 {
1104 return reverse_iterator{ end() };
1105 }
1106
1107 [[nodiscard]] const_reverse_iterator
1108 crbegin() const
1109 {
1110 return const_reverse_iterator{ cend() };
1111 }
1112
1113 [[nodiscard]] const_reverse_iterator
1114 rbegin() const
1115 {
1116 return crbegin();
1117 }
1118
1119 [[nodiscard]] reverse_iterator
1120 rend()
1121 {
1122 return reverse_iterator{ begin() };
1123 }
1124
1125 [[nodiscard]] const_reverse_iterator
1126 crend() const
1127 {
1128 return const_reverse_iterator{ cbegin() };
1129 }
1130
1131 [[nodiscard]] const_reverse_iterator
1132 rend() const
1133 {
1134 return crend();
1135 }
1136
1137private:
1138 bool m_LetArrayManageMemory{ true }; // if true, the array is responsible
1139 // for memory of data
1140 TValue * m_Data{}; // Array to hold data
1141 ElementIdentifier m_NumElements{ 0 };
1142
1143 void
1144 ExceptionThrowingBoundsCheck(size_type pos) const
1145 {
1146 if (pos >= m_NumElements)
1147 {
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) + ")!");
1151 }
1152 }
1153};
1154
1156namespace mpl
1157{
1167template <typename T>
1168struct IsArray : FalseType
1169{};
1170
1172template <typename T>
1173struct IsArray<itk::VariableLengthVector<T>> : TrueType
1174{};
1175
1176template <typename TExpr1, typename TExpr2, typename TBinaryOp>
1177struct IsArray<VariableLengthVectorExpression<TExpr1, TExpr2, TBinaryOp>> : TrueType
1178{};
1180} // namespace mpl
1182
1183namespace Details
1184{
1186
1198template <typename TExpr>
1199struct GetType
1200{
1201 using Type = TExpr;
1202
1206 static Type
1207 Load(const Type & v, unsigned int itkNotUsed(idx))
1208 {
1209 return v;
1210 }
1211};
1212
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)
1226{
1227 itkAssertInDebugAndIgnoreInReleaseMacro(lhs.Size() == rhs.Size());
1228 return lhs.Size();
1229}
1230
1232
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))
1244{
1245 return lhs.Size();
1246}
1247
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)
1260{
1261 return rhs.Size();
1262}
1263
1264template <typename T>
1265struct GetType<VariableLengthVector<T>>
1266{
1267 using Type = T;
1268 static Type
1269 Load(const VariableLengthVector<T> & v, unsigned int idx)
1270 {
1271 return v[idx];
1272 }
1273};
1274template <typename TExpr1, typename TExpr2, typename TBinaryOp>
1275struct GetType<VariableLengthVectorExpression<TExpr1, TExpr2, TBinaryOp>>
1276{
1277 using Type = typename VariableLengthVectorExpression<TExpr1, TExpr2, TBinaryOp>::ResType;
1278 static Type
1279 Load(const VariableLengthVectorExpression<TExpr1, TExpr2, TBinaryOp> & v, unsigned int idx)
1280 {
1281 return v[idx];
1282 }
1283};
1285
1286namespace op
1287{
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>>>
1305{};
1306
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>>>
1322{};
1323
1335template <typename TExpr1, typename TExpr2>
1336struct CanBeDivided : mpl::And<mpl::IsArray<TExpr1>, mpl::IsNumber<TExpr2>>
1337{};
1338
1339} // namespace op
1340} // namespace Details
1342
1367template <typename TExpr1, typename TExpr2, typename TBinaryOp>
1368struct VariableLengthVectorExpression
1369{
1370 VariableLengthVectorExpression(const TExpr1 & lhs, const TExpr2 & rhs)
1371 : m_lhs(lhs)
1372 , m_rhs(rhs)
1373 {
1374 // Not necessary actually as end-user/developer is not expected to
1375 // provide new BinaryOperations
1376 static_assert(std::is_base_of_v<Details::op::BinaryOperationConcept, TBinaryOp>,
1377 "The Binary Operation shall inherit from BinaryOperationConcept");
1378 }
1379
1381 [[nodiscard]] unsigned int
1382 Size() const
1383 {
1384 return Details::GetSize(m_lhs, m_rhs);
1385 }
1386
1388 using ResType =
1389 typename mpl::PromoteType<typename Details::GetType<TExpr1>::Type, typename Details::GetType<TExpr2>::Type>::Type;
1391 using RealValueType = typename NumericTraits<ResType>::RealType;
1392
1403 ResType
1404 operator[](unsigned int idx) const
1405 {
1406 itkAssertInDebugAndIgnoreInReleaseMacro(idx < Size());
1407 return TBinaryOp::Apply(Details::GetType<TExpr1>::Load(m_lhs, idx), Details::GetType<TExpr2>::Load(m_rhs, idx));
1408 }
1409
1411 [[nodiscard]] RealValueType
1412 GetNorm() const;
1413
1415 [[nodiscard]] RealValueType
1416 GetSquaredNorm() const;
1417
1418private:
1419 const TExpr1 & m_lhs;
1420 const TExpr2 & m_rhs;
1421};
1422
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)
1436{
1437 return VariableLengthVectorExpression<TExpr1, TExpr2, Details::op::Plus>(lhs, rhs);
1438}
1439
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)
1453{
1454 return VariableLengthVectorExpression<TExpr1, TExpr2, Details::op::Sub>(lhs, rhs);
1455}
1456
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)
1469{
1470 return VariableLengthVectorExpression<TExpr1, TExpr2, Details::op::Mult>(lhs, rhs);
1471}
1472
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)
1484{
1485 return VariableLengthVectorExpression<TExpr1, TExpr2, Details::op::Div>(lhs, rhs);
1486}
1487
1491template <typename TExpr1, typename TExpr2, typename TBinaryOp>
1492std::ostream &
1493operator<<(std::ostream & os, const VariableLengthVectorExpression<TExpr1, TExpr2, TBinaryOp> & v)
1494{
1495 os << '[';
1496 if (v.Size() != 0)
1497 {
1498 os << v[0];
1499 for (unsigned int i = 1, N = v.Size(); i != N; ++i)
1500 {
1501 os << ", " << v[i];
1502 }
1503 }
1504 return os << ']';
1505}
1506
1512template <typename TExpr>
1513inline std::enable_if_t<mpl::IsArray<TExpr>::Value, typename TExpr::RealValueType>
1514GetNorm(const TExpr & v)
1515{
1516 return static_cast<typename TExpr::RealValueType>(std::sqrt(static_cast<double>(GetSquaredNorm(v))));
1517}
1518
1524template <typename TExpr>
1525inline std::enable_if_t<mpl::IsArray<TExpr>::Value, typename TExpr::RealValueType>
1526GetSquaredNorm(const TExpr & v)
1527{
1528 using RealValueType = typename TExpr::RealValueType;
1529 RealValueType sum = 0.0;
1530 for (unsigned int i = 0, N = v.Size(); i < N; ++i)
1531 {
1532 const RealValueType value = v[i];
1533 sum += value * value;
1534 }
1535 return sum;
1536}
1537
1539
1543template <typename TValue>
1544std::ostream &
1545operator<<(std::ostream & os, const VariableLengthVector<TValue> & arr)
1546{
1547 const unsigned int length = arr.Size();
1548 const int last = static_cast<unsigned int>(length) - 1;
1549
1550 os << '[';
1551 for (int i = 0; i < last; ++i)
1552 {
1553 os << arr[i] << ", ";
1554 }
1555 if (length >= 1)
1556 {
1557 os << arr[last];
1558 }
1559 os << ']';
1560 return os;
1561}
1562
1564
1582template <typename T>
1583inline void
1585{
1586 l_.Swap(r_);
1587}
1588
1589} // namespace itk
1590
1592
1593#ifndef ITK_MANUAL_INSTANTIATION
1594# include "itkVariableLengthVector.hxx"
1595#endif
1596
1597#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
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)