ITK  5.0.0
Insight Segmentation and Registration Toolkit
itkVariableLengthVector.h
Go to the documentation of this file.
1 /*=========================================================================
2  *
3  * Copyright Insight Software Consortium
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  * http://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 "itkNumericTraits.h"
24 #include "itkStaticAssert.h"
26 #include "itkEnableIf.h"
27 #include "itkIsBaseOf.h"
28 #include "itkIsNumber.h"
29 #include "itkPromoteType.h"
31 
32 namespace itk
33 {
34 
35 template <typename TExpr1, typename TExpr2, typename TBinaryOp>
37 
92 template< typename TValue >
93 class ITK_TEMPLATE_EXPORT VariableLengthVector
94 {
95 public:
100 
113 
128  {
129  bool operator()(unsigned int itkNotUsed(newSize), unsigned int itkNotUsed(oldSize)) const
130  {
131  return true;
132  }
133  };
135 
155  {
156  bool operator()(unsigned int newSize, unsigned int oldSize) const
157  {
158  (void) newSize;
159  (void) oldSize;
160  itkAssertInDebugAndIgnoreInReleaseMacro(newSize == oldSize && "SetSize is expected to never change the VariableLengthVector size...");
161  return true;
162  }
163  };
165 
184  {
185  bool operator()(unsigned int newSize, unsigned int oldSize) const
186  { return newSize != oldSize; }
187  };
189 
217  {
218  bool operator()(unsigned int newSize, unsigned int oldSize) const
219  { return newSize > oldSize; }
220  };
222 
242 
265  {
266  template <typename TValue2>
268  unsigned int newSize, unsigned int oldSize,
269  TValue2 * oldBuffer, TValue2 * newBuffer) const
270  {
271  itkAssertInDebugAndIgnoreInReleaseMacro(newBuffer);
272  const std::size_t nb = std::min(newSize, oldSize);
273  itkAssertInDebugAndIgnoreInReleaseMacro(nb == 0 || (nb > 0 && oldBuffer != nullptr));
274  std::copy(oldBuffer, oldBuffer+nb, newBuffer);
275  }
276  };
278 
296  {
297  template <typename TValue2>
299  unsigned int itkNotUsed(newSize), unsigned int itkNotUsed(oldSize),
300  TValue2 * itkNotUsed(oldBuffer), TValue2 * itkNotUsed(newBuffer)) const
301  {
302  }
303  };
305 
306 
307 
309  using ValueType = TValue;
310  using ComponentType = TValue;
313 
315  using ElementIdentifier = unsigned int;
316 
324 
333  explicit VariableLengthVector(unsigned int dimension);
334 
348  VariableLengthVector(ValueType *data, unsigned int sz,
349  bool LetArrayManageMemory = false);
350 
370  VariableLengthVector(const ValueType *data, unsigned int sz,
371  bool LetArrayManageMemory = false);
372 
392  template< typename T >
394  {
395  m_NumElements = v.Size();
396  m_LetArrayManageMemory = true;
397  if (m_NumElements != 0)
398  {
399  m_Data = this->AllocateElements(m_NumElements);
400  itkAssertInDebugAndIgnoreInReleaseMacro(m_Data != nullptr);
401  for ( ElementIdentifier i = 0; i < m_NumElements; ++i )
402  {
403  this->m_Data[i] = static_cast< ValueType >( v[i] );
404  }
405  }
406  else
407  {
408  m_Data = nullptr;
409  }
410  }
412 
422 
431  void Swap(Self & v) noexcept
432  {
433  itkAssertInDebugAndIgnoreInReleaseMacro(m_LetArrayManageMemory == v.m_LetArrayManageMemory);
434  using std::swap;
435  swap(v.m_Data , m_Data);
436  swap(v.m_NumElements, m_NumElements);
437  }
439 
447  VariableLengthVector(Self && v) noexcept;
448 
457  Self & operator=(Self && v) noexcept;
458 
475  template <typename TExpr1, typename TExpr2, typename TBinaryOp>
476  VariableLengthVector(VariableLengthVectorExpression<TExpr1, TExpr2, TBinaryOp> const& rhs);
477 
497  template <typename TExpr1, typename TExpr2, typename TBinaryOp>
498  Self & operator=(VariableLengthVectorExpression<TExpr1, TExpr2, TBinaryOp> const& rhs);
499 
503  void Fill(TValue const & v);
504 
517  template< typename T >
518  Self & operator=(const VariableLengthVector< T > & v)
519  {
520  // No self assignment test is done. Indeed:
521  // - the operator already resists self assignment through a strong exception
522  // guarantee
523  // - the test becomes a pessimization as we never write
524  // VLV<const TValue> vcref(v.GetDataPointer(), v.GetSize());
525  // ...;
526  // v = vcref;
527  ElementIdentifier const N = v.Size();
528  this->SetSize( N, DontShrinkToFit(), DumpOldValues() );
529  for ( ElementIdentifier i = 0; i < N; ++i )
530  {
531  this->m_Data[i] = static_cast< ValueType >( v[i] );
532  }
533  return *this;
534  }
536 
552  Self & operator=(const Self & v);
553 
562  Self & FastAssign(const Self & v);
563 
571  Self & operator=(TValue const & v);
572 
574  unsigned int Size() const { return m_NumElements; }
575  unsigned int GetSize() const { return m_NumElements; }
576  unsigned int GetNumberOfElements() const { return m_NumElements; }
578 
580  TValue & operator[](unsigned int i) { return this->m_Data[i]; }
581 
583  TValue const & operator[](unsigned int i) const { return this->m_Data[i]; }
584 
586  const TValue & GetElement(unsigned int i) const { return m_Data[i]; }
587 
589  void SetElement(unsigned int i, const TValue & value) { m_Data[i] = value; }
590 
624  template <typename TReallocatePolicy, typename TKeepValuesPolicy>
625  void SetSize(unsigned int sz,
626  TReallocatePolicy reallocatePolicy,
627  TKeepValuesPolicy keepValues);
628 
639  void SetSize(unsigned int sz, bool destroyExistingData = true)
640  {
641  // Stays compatible with previous code version
642  // And works around the fact C++03 template functions can't have default
643  // arguments on template types.
644  if (destroyExistingData)
645  {
646  SetSize(sz, AlwaysReallocate(), KeepOldValues());
647  }
648  else
649  {
650  SetSize(sz, ShrinkToFit(), KeepOldValues());
651  }
652  }
654 
657  void DestroyExistingData();
658 
671  void SetData(TValue *data, bool LetArrayManageMemory = false);
672 
687  void SetData(TValue *data, unsigned int sz, bool LetArrayManageMemory = false);
688 
700 
715  void Reserve(ElementIdentifier size);
717 
722  TValue * AllocateElements(ElementIdentifier size) const;
723 
724  const TValue * GetDataPointer() const { return m_Data; }
725 
729  {
730  for ( ElementIdentifier i = 0; i < m_NumElements; i++ )
731  {
732  this->m_Data[i] -= static_cast< ValueType >( 1.0 );
733  }
734  return *this;
735  }
737 
739  Self & operator++() // prefix operator ++v;
740  {
741  for ( ElementIdentifier i = 0; i < m_NumElements; i++ )
742  {
743  this->m_Data[i] += static_cast< ValueType >( 1.0 );
744  }
745  return *this;
746  }
748 
751  Self operator--(int) // postfix operator v--;
752  {
753  Self tmp(*this);
755 
756  --tmp;
757  return tmp;
758  }
759 
761  Self operator++(int) // postfix operator v++;
762  {
763  Self tmp(*this);
765 
766  ++tmp;
767  return tmp;
768  }
769 
778  template< typename T >
779  Self & operator-=
781  {
782  itkAssertInDebugAndIgnoreInReleaseMacro( m_NumElements == v.GetSize() );
783  for ( ElementIdentifier i = 0; i < m_NumElements; i++ )
784  {
785  m_Data[i] -= static_cast< ValueType >( v[i] );
786  }
787  return *this;
788  }
790 
792  Self & operator-=(TValue s)
793  {
794  for ( ElementIdentifier i = 0; i < m_NumElements; i++ )
795  {
796  m_Data[i] -= s;
797  }
798  return *this;
799  }
801 
810  template< typename T >
811  Self & operator+=
813  {
814  itkAssertInDebugAndIgnoreInReleaseMacro( m_NumElements == v.GetSize() );
815  for ( ElementIdentifier i = 0; i < m_NumElements; i++ )
816  {
817  m_Data[i] += static_cast< ValueType >( v[i] );
818  }
819  return *this;
820  }
822 
824  Self & operator+=(TValue s)
825  {
826  for ( ElementIdentifier i = 0; i < m_NumElements; i++ )
827  {
828  m_Data[i] += s;
829  }
830  return *this;
831  }
833 
843  template <typename TExpr1, typename TExpr2, typename TBinaryOp>
845  {
846  itkAssertInDebugAndIgnoreInReleaseMacro(rhs.Size() == Size());
847  for ( ElementIdentifier i = 0; i < m_NumElements; ++i )
848  {
849  m_Data[i] += static_cast<ValueType>(rhs[i]);
850  }
851  return *this;
852  }
854 
864  template <typename TExpr1, typename TExpr2, typename TBinaryOp>
866  {
867  itkAssertInDebugAndIgnoreInReleaseMacro(rhs.Size() == Size());
868  for ( ElementIdentifier i = 0; i < m_NumElements; ++i )
869  {
870  m_Data[i] -= static_cast<ValueType>(rhs[i]);
871  }
872  return *this;
873  }
875 
881  template< typename T >
883  {
884  const ValueType & sc = static_cast<ValueType>(s);
885  for ( ElementIdentifier i = 0; i < m_NumElements; i++ )
886  {
887  m_Data[i] *= sc;
888  }
889  return *this;
890  }
892 
896  Self & operator*=(TValue s)
897  {
898  for ( ElementIdentifier i = 0; i < m_NumElements; i++ )
899  {
900  m_Data[i] *= s;
901  }
902  return *this;
903  }
905 
912  template< typename T >
914  {
915  const RealValueType sc = s;
916  for ( ElementIdentifier i = 0; i < m_NumElements; i++ )
917  {
918  m_Data[i] = static_cast< ValueType >(
919  static_cast< RealValueType >( m_Data[i] )
920  / sc );
921  }
922  return *this;
923  }
925 
930  Self & operator-(); // negation operator
931 
932  bool operator==(const Self & v) const;
933 
934  bool operator!=(const Self & v) const;
935 
937  RealValueType GetNorm() const;
938 
940  RealValueType GetSquaredNorm() const;
941 
943  bool IsAProxy() const { return ! m_LetArrayManageMemory;}
944 
945 private:
946  bool m_LetArrayManageMemory{true}; // if true, the array is responsible
947  // for memory of data
948  TValue * m_Data; // Array to hold data
949  ElementIdentifier m_NumElements{0};
950 };
951 
953 namespace mpl {
963 template <typename T>
964 struct IsArray : FalseType {};
965 
967 template <typename T>
968 struct IsArray<itk::VariableLengthVector<T> > : TrueType {};
969 
970 template <typename TExpr1, typename TExpr2, typename TBinaryOp>
971 struct IsArray<VariableLengthVectorExpression<TExpr1, TExpr2,TBinaryOp> > : TrueType {};
973 } // namespace mpl
975 
976 namespace Details
977 {
979 
991 template <typename TExpr> struct GetType
992  {
993  using Type = TExpr;
994 
998  static Type Load(Type const& v, unsigned int idx)
999  { (void)idx; return v; }
1000  };
1002 
1013 template <typename TExpr1, typename TExpr2>
1014 inline
1015 typename mpl::EnableIf<mpl::And<mpl::IsArray<TExpr1>, mpl::IsArray<TExpr2> >, unsigned int>::Type
1016 GetSize(TExpr1 const& lhs, TExpr2 const& rhs)
1017  {
1018  (void)rhs;
1019  itkAssertInDebugAndIgnoreInReleaseMacro(lhs.Size() == rhs.Size());
1020  return lhs.Size();
1021  }
1023 
1025 
1034 template <typename TExpr1, typename TExpr2>
1035 inline
1036 typename mpl::EnableIf<mpl::And<mpl::IsArray<TExpr1>, mpl::Not<mpl::IsArray<TExpr2> > >, unsigned int>::Type
1037 GetSize(TExpr1 const& lhs, TExpr2 const& itkNotUsed(rhs))
1038  {
1039  return lhs.Size();
1040  }
1041 
1051 template <typename TExpr1, typename TExpr2>
1052 inline
1053 typename mpl::EnableIf<mpl::And<mpl::IsArray<TExpr2>, mpl::Not<mpl::IsArray<TExpr1> > >, unsigned int>::Type
1054 GetSize(TExpr1 const& itkNotUsed(lhs), TExpr2 const& rhs)
1055  {
1056  return rhs.Size();
1057  }
1058 
1059 template <typename T>
1060 struct GetType<VariableLengthVector<T> >
1061  {
1062  using Type = T;
1063  static Type Load(VariableLengthVector<T> const& v, unsigned int idx)
1064  { return v[idx]; }
1065  };
1066 template <typename TExpr1, typename TExpr2, typename TBinaryOp>
1067 struct GetType<VariableLengthVectorExpression<TExpr1, TExpr2, TBinaryOp> >
1068  {
1070  static Type Load(VariableLengthVectorExpression<TExpr1, TExpr2, TBinaryOp> const& v, unsigned int idx)
1071  { return v[idx]; }
1072  };
1074 
1075 namespace op
1076 {
1089 template <typename TExpr1, typename TExpr2>
1091 : mpl::Or< mpl::And<mpl::IsArray<TExpr1>, mpl::IsArray<TExpr2> >,
1092  mpl::And<mpl::IsArray<TExpr1>, mpl::IsNumber<TExpr2> >,
1093  mpl::And<mpl::IsNumber<TExpr1>, mpl::IsArray<TExpr2> >
1094  >
1095 {};
1096 
1108 template <typename TExpr1, typename TExpr2>
1110 : mpl::Or< mpl::And<mpl::IsArray<TExpr1>, mpl::IsNumber<TExpr2> >,
1111  mpl::And<mpl::IsNumber<TExpr1>, mpl::IsArray<TExpr2> >
1112  >
1113 {};
1114 
1126 template <typename TExpr1, typename TExpr2>
1128 : mpl::And<mpl::IsArray<TExpr1>, mpl::IsNumber<TExpr2> >
1129 {};
1130 
1131 } // op namespace
1132 } // Details namespace
1134 
1159 template <typename TExpr1, typename TExpr2, typename TBinaryOp>
1161 {
1162  VariableLengthVectorExpression(TExpr1 const& lhs, TExpr2 const& rhs)
1163  : m_lhs(lhs), m_rhs(rhs)
1164  {
1165  // Not neccessary actually as end-user/developper is not expected to
1166  // provide new BinaryOperations
1168  (itk::mpl::IsBaseOf<Details::op::BinaryOperationConcept, TBinaryOp>::Value),
1169  "The Binary Operation shall inherit from BinaryOperationConcept");
1170  }
1171 
1173  unsigned int Size() const{ return Details::GetSize(m_lhs, m_rhs); }
1174 
1176  using ResType = typename mpl::PromoteType<
1177  typename Details::GetType<TExpr1>::Type,
1178  typename Details::GetType<TExpr2>::Type>::Type;
1180  using RealValueType = typename NumericTraits< ResType > ::RealType;
1181 
1192  ResType operator[](unsigned int idx) const
1193  {
1194  itkAssertInDebugAndIgnoreInReleaseMacro(idx < Size());
1195  return TBinaryOp::Apply(
1196  Details::GetType<TExpr1>::Load(m_lhs, idx),
1197  Details::GetType<TExpr2>::Load(m_rhs, idx));
1198  }
1200 
1202  RealValueType GetNorm() const;
1203 
1205  RealValueType GetSquaredNorm() const;
1206 
1207 private:
1208  TExpr1 const& m_lhs;
1209  TExpr2 const& m_rhs;
1210 };
1211 
1221 template <typename TExpr1, typename TExpr2>
1222 inline
1223 typename mpl::EnableIf<Details::op::CanBeAddedOrSubtracted<TExpr1,TExpr2>, VariableLengthVectorExpression<TExpr1, TExpr2, Details::op::Plus> >::Type
1224 operator+(TExpr1 const& lhs, TExpr2 const& rhs)
1226 
1236 template <typename TExpr1, typename TExpr2>
1237 inline
1238 typename mpl::EnableIf<Details::op::CanBeAddedOrSubtracted<TExpr1,TExpr2>, VariableLengthVectorExpression<TExpr1, TExpr2, Details::op::Sub> >::Type
1239 operator-(TExpr1 const& lhs, TExpr2 const& rhs)
1241 
1250 template <typename TExpr1, typename TExpr2>
1251 inline
1252 typename mpl::EnableIf<Details::op::CanBeMultiplied<TExpr1,TExpr2>, VariableLengthVectorExpression<TExpr1, TExpr2, Details::op::Mult> >::Type
1253 operator*(TExpr1 const& lhs, TExpr2 const& rhs)
1255 
1263 template <typename TExpr1, typename TExpr2>
1264 inline
1265 typename mpl::EnableIf<Details::op::CanBeDivided<TExpr1,TExpr2>, VariableLengthVectorExpression<TExpr1, TExpr2, Details::op::Div> >::Type
1266 operator/(TExpr1 const& lhs, TExpr2 const& rhs)
1268 
1272 template <typename TExpr1, typename TExpr2, typename TBinaryOp>
1273 std::ostream & operator<<(std::ostream &os, VariableLengthVectorExpression<TExpr1, TExpr2, TBinaryOp> const& v)
1274 {
1275  os << "[";
1276  if (v.Size() != 0)
1277  {
1278  os << v[0];
1279  for (unsigned int i = 1, N = v.Size(); i != N; ++i)
1280  {
1281  os << ", " << v[i];
1282  }
1283  }
1284  return os << "]";
1285 }
1287 
1293 template <typename TExpr>
1294 inline
1295 typename mpl::EnableIf<mpl::IsArray<TExpr>, typename TExpr::RealValueType>::Type
1296 GetNorm(TExpr const& v)
1297 {
1298  return static_cast<typename TExpr::RealValueType>(
1299  std::sqrt(static_cast<double>(GetSquaredNorm(v))));
1300 }
1301 
1307 template <typename TExpr>
1308 inline
1309 typename mpl::EnableIf<mpl::IsArray<TExpr>, typename TExpr::RealValueType>::Type
1310 GetSquaredNorm(TExpr const& v)
1311 {
1312  using RealValueType = typename TExpr::RealValueType;
1313  RealValueType sum = 0.0;
1314  for ( unsigned int i = 0, N=v.Size(); i < N; ++i )
1315  {
1316  const RealValueType value = v[i];
1317  sum += value * value;
1318  }
1319  return sum;
1320 }
1322 
1325 
1329 template< typename TValue >
1330 std::ostream & operator<<(std::ostream & os, const VariableLengthVector< TValue > & arr)
1331 {
1332  const unsigned int length = arr.Size();
1333  const signed int last = (unsigned int)length - 1;
1335 
1336  os << "[";
1337  for ( signed int i = 0; i < last; ++i )
1338  {
1339  os << arr[i] << ", ";
1340  }
1341  if ( length >= 1 )
1342  {
1343  os << arr[last];
1344  }
1345  os << "]";
1346  return os;
1347 }
1349 
1352 
1370 template <typename T>
1371 inline
1373 {
1374  l_.Swap(r_);
1375 }
1377 
1378 
1379 } // namespace itk
1380 
1382 
1383 #ifndef ITK_MANUAL_INSTANTIATION
1384 #include "itkVariableLengthVector.hxx"
1385 #endif
1386 
1387 #endif
void operator()(unsigned int newSize, unsigned int oldSize, TValue2 *oldBuffer, TValue2 *newBuffer) const
void swap(VariableLengthVector< T > &l_, VariableLengthVector< T > &r_) noexcept
unsigned int Size() const
Returns the size of the vector expression.
bool operator==(const Index< VDimension > &one, const Index< VDimension > &two)
Definition: itkIndex.h:485
TValue & operator[](unsigned int i)
ConstNeighborhoodIterator< TImage > operator-(const ConstNeighborhoodIterator< TImage > &it, const typename ConstNeighborhoodIterator< TImage >::OffsetType &ind)
Define numeric traits for std::vector.
VariableLengthVector(const VariableLengthVector< T > &v)
bool operator()(unsigned int newSize, unsigned int oldSize) const
void SetElement(unsigned int i, const TValue &value)
bool operator()(unsigned int, unsigned int) const
mpl::EnableIf< mpl::IsArray< TExpr >, typename TExpr::RealValueType >::Type GetNorm(TExpr const &v)
Self & operator+=(VariableLengthVectorExpression< TExpr1, TExpr2, TBinaryOp > const &rhs)
const TValue & GetElement(unsigned int i) const
const TValue * GetDataPointer() const
void swap(Array< T > &a, Array< T > &b)
Definition: itkArray.h:211
bool operator()(unsigned int newSize, unsigned int oldSize) const
Represents an array whose length can be defined at run-time.
bool operator!=(const Index< VDimension > &one, const Index< VDimension > &two)
Definition: itkIndex.h:492
mpl::EnableIf< Details::op::CanBeAddedOrSubtracted< TExpr1, TExpr2 >, VariableLengthVectorExpression< TExpr1, TExpr2, Details::op::Sub > >::Type operator-(TExpr1 const &lhs, TExpr2 const &rhs)
Represent a n-dimensional size (bounds) of a n-dimensional image.
Definition: itkSize.h:68
mpl::EnableIf< Details::op::CanBeAddedOrSubtracted< TExpr1, TExpr2 >, VariableLengthVectorExpression< TExpr1, TExpr2, Details::op::Plus > >::Type operator+(TExpr1 const &lhs, TExpr2 const &rhs)
typename NumericTraits< ResType >::RealType RealValueType
Real type of the elements.
mpl::EnableIf< Details::op::CanBeDivided< TExpr1, TExpr2 >, VariableLengthVectorExpression< TExpr1, TExpr2, Details::op::Div > >::Type operator/(TExpr1 const &lhs, TExpr2 const &rhs)
Self & operator-=(VariableLengthVectorExpression< TExpr1, TExpr2, TBinaryOp > const &rhs)
typename NumericTraits< ValueType >::RealType RealValueType
void operator()(unsigned int, unsigned int, TValue2 *, TValue2 *) const
typename mpl::PromoteType< typename Details::GetType< TExpr1 >::Type, typename Details::GetType< TExpr2 >::Type >::Type ResType
Vector type of the Result Expression.
void SetSize(unsigned int sz, bool destroyExistingData=true)
unsigned int GetNumberOfElements() const
#define itkStaticAssert(expr, str)
bool operator()(unsigned int newSize, unsigned int oldSize) const
mpl::EnableIf< Details::op::CanBeMultiplied< TExpr1, TExpr2 >, VariableLengthVectorExpression< TExpr1, TExpr2, Details::op::Mult > >::Type operator*(TExpr1 const &lhs, TExpr2 const &rhs)
VariableLengthVectorExpression(TExpr1 const &lhs, TExpr2 const &rhs)
mpl::EnableIf< mpl::IsArray< TExpr >, typename TExpr::RealValueType >::Type GetSquaredNorm(TExpr const &v)
ResType operator[](unsigned int idx) const
TValue const & operator[](unsigned int i) const