ITK  4.13.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 != ITK_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  typedef TValue ValueType;
310  typedef TValue ComponentType;
313 
315  typedef unsigned int ElementIdentifier;
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 != ITK_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 = ITK_NULLPTR;
409  }
410  }
412 
422 
431  void Swap(Self & v) ITK_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 
440 #if defined(ITK_HAS_CXX11_RVREF)
441 
448  VariableLengthVector(Self && v) ITK_NOEXCEPT;
449 
458  Self & operator=(Self && v) ITK_NOEXCEPT;
459 #endif
460 
477  template <typename TExpr1, typename TExpr2, typename TBinaryOp>
479 
499  template <typename TExpr1, typename TExpr2, typename TBinaryOp>
501 
505  void Fill(TValue const & v);
506 
519  template< typename T >
521  {
522  // No self assignment test is done. Indeed:
523  // - the operator already resists self assignment through a strong exception
524  // guarantee
525  // - the test becomes a pessimization as we never write
526  // VLV<const TValue> vcref(v.GetDataPointer(), v.GetSize());
527  // ...;
528  // v = vcref;
529  ElementIdentifier const N = v.Size();
530  this->SetSize( N, DontShrinkToFit(), DumpOldValues() );
531  for ( ElementIdentifier i = 0; i < N; ++i )
532  {
533  this->m_Data[i] = static_cast< ValueType >( v[i] );
534  }
535  return *this;
536  }
538 
554  Self & operator=(const Self & v);
555 
564  Self & FastAssign(const Self & v);
565 
573  Self & operator=(TValue const & v);
574 
576  unsigned int Size(void) const { return m_NumElements; }
577  unsigned int GetSize(void) const { return m_NumElements; }
578  unsigned int GetNumberOfElements(void) const { return m_NumElements; }
580 
582  TValue & operator[](unsigned int i) { return this->m_Data[i]; }
583 
585  TValue const & operator[](unsigned int i) const { return this->m_Data[i]; }
586 
588  const TValue & GetElement(unsigned int i) const { return m_Data[i]; }
589 
591  void SetElement(unsigned int i, const TValue & value) { m_Data[i] = value; }
592 
626  template <typename TReallocatePolicy, typename TKeepValuesPolicy>
627  void SetSize(unsigned int sz,
628  TReallocatePolicy reallocatePolicy,
629  TKeepValuesPolicy keepValues);
630 
641  void SetSize(unsigned int sz, bool destroyExistingData = true)
642  {
643  // Stays compatible with previous code version
644  // And works around the fact C++03 template functions can't have default
645  // arguments on template types.
646  if (destroyExistingData)
647  {
648  SetSize(sz, AlwaysReallocate(), KeepOldValues());
649  }
650  else
651  {
652  SetSize(sz, ShrinkToFit(), KeepOldValues());
653  }
654  }
656 
659  void DestroyExistingData();
660 
673  void SetData(TValue *data, bool LetArrayManageMemory = false);
674 
689  void SetData(TValue *data, unsigned int sz, bool LetArrayManageMemory = false);
690 
702 
717  void Reserve(ElementIdentifier size);
719 
724  TValue * AllocateElements(ElementIdentifier size) const;
725 
726  const TValue * GetDataPointer() const { return m_Data; }
727 
731  {
732  for ( ElementIdentifier i = 0; i < m_NumElements; i++ )
733  {
734  this->m_Data[i] -= static_cast< ValueType >( 1.0 );
735  }
736  return *this;
737  }
739 
741  Self & operator++() // prefix operator ++v;
742  {
743  for ( ElementIdentifier i = 0; i < m_NumElements; i++ )
744  {
745  this->m_Data[i] += static_cast< ValueType >( 1.0 );
746  }
747  return *this;
748  }
750 
753  Self operator--(int) // postfix operator v--;
754  {
755  Self tmp(*this);
757 
758  --tmp;
759  return tmp;
760  }
761 
763  Self operator++(int) // postfix operator v++;
764  {
765  Self tmp(*this);
767 
768  ++tmp;
769  return tmp;
770  }
771 
780  template< typename T >
781  Self & operator-=
783  {
784  itkAssertInDebugAndIgnoreInReleaseMacro( m_NumElements == v.GetSize() );
785  for ( ElementIdentifier i = 0; i < m_NumElements; i++ )
786  {
787  m_Data[i] -= static_cast< ValueType >( v[i] );
788  }
789  return *this;
790  }
792 
794  Self & operator-=(TValue s)
795  {
796  for ( ElementIdentifier i = 0; i < m_NumElements; i++ )
797  {
798  m_Data[i] -= s;
799  }
800  return *this;
801  }
803 
812  template< typename T >
813  Self & operator+=
815  {
816  itkAssertInDebugAndIgnoreInReleaseMacro( m_NumElements == v.GetSize() );
817  for ( ElementIdentifier i = 0; i < m_NumElements; i++ )
818  {
819  m_Data[i] += static_cast< ValueType >( v[i] );
820  }
821  return *this;
822  }
824 
826  Self & operator+=(TValue s)
827  {
828  for ( ElementIdentifier i = 0; i < m_NumElements; i++ )
829  {
830  m_Data[i] += s;
831  }
832  return *this;
833  }
835 
845  template <typename TExpr1, typename TExpr2, typename TBinaryOp>
847  {
848  itkAssertInDebugAndIgnoreInReleaseMacro(rhs.Size() == Size());
849  for ( ElementIdentifier i = 0; i < m_NumElements; ++i )
850  {
851  m_Data[i] += static_cast<ValueType>(rhs[i]);
852  }
853  return *this;
854  }
856 
866  template <typename TExpr1, typename TExpr2, typename TBinaryOp>
868  {
869  itkAssertInDebugAndIgnoreInReleaseMacro(rhs.Size() == Size());
870  for ( ElementIdentifier i = 0; i < m_NumElements; ++i )
871  {
872  m_Data[i] -= static_cast<ValueType>(rhs[i]);
873  }
874  return *this;
875  }
877 
883  template< typename T >
885  {
886  const ValueType & sc = static_cast<ValueType>(s);
887  for ( ElementIdentifier i = 0; i < m_NumElements; i++ )
888  {
889  m_Data[i] *= sc;
890  }
891  return *this;
892  }
894 
898  Self & operator*=(TValue s)
899  {
900  for ( ElementIdentifier i = 0; i < m_NumElements; i++ )
901  {
902  m_Data[i] *= s;
903  }
904  return *this;
905  }
907 
914  template< typename T >
916  {
917  const RealValueType sc = s;
918  for ( ElementIdentifier i = 0; i < m_NumElements; i++ )
919  {
920  m_Data[i] = static_cast< ValueType >(
921  static_cast< RealValueType >( m_Data[i] )
922  / sc );
923  }
924  return *this;
925  }
927 
932  Self & operator-(); // negation operator
933 
934  bool operator==(const Self & v) const;
935 
936  bool operator!=(const Self & v) const;
937 
939  RealValueType GetNorm() const;
940 
942  RealValueType GetSquaredNorm() const;
943 
945  bool IsAProxy() const { return ! m_LetArrayManageMemory;}
946 
947 private:
948  bool m_LetArrayManageMemory; // if true, the array is responsible
949  // for memory of data
950  TValue * m_Data; // Array to hold data
952 };
953 
955 namespace mpl {
965 template <typename T>
966 struct IsArray : FalseType {};
967 
969 template <typename T>
970 struct IsArray<itk::VariableLengthVector<T> > : TrueType {};
971 
972 template <typename TExpr1, typename TExpr2, typename TBinaryOp>
973 struct IsArray<VariableLengthVectorExpression<TExpr1, TExpr2,TBinaryOp> > : TrueType {};
975 } // namespace mpl
977 
978 namespace Details
979 {
981 
993 template <typename TExpr> struct GetType
994  {
995  typedef TExpr Type;
996 
1000  static Type Load(Type const& v, unsigned int idx)
1001  { (void)idx; return v; }
1002  };
1004 
1015 template <typename TExpr1, typename TExpr2>
1016 inline
1017 typename mpl::EnableIf<mpl::And<mpl::IsArray<TExpr1>, mpl::IsArray<TExpr2> >, unsigned int>::Type
1018 GetSize(TExpr1 const& lhs, TExpr2 const& rhs)
1019  {
1020  (void)rhs;
1021  itkAssertInDebugAndIgnoreInReleaseMacro(lhs.Size() == rhs.Size());
1022  return lhs.Size();
1023  }
1025 
1027 
1036 template <typename TExpr1, typename TExpr2>
1037 inline
1038 typename mpl::EnableIf<mpl::And<mpl::IsArray<TExpr1>, mpl::Not<mpl::IsArray<TExpr2> > >, unsigned int>::Type
1039 GetSize(TExpr1 const& lhs, TExpr2 const& itkNotUsed(rhs))
1040  {
1041  return lhs.Size();
1042  }
1043 
1053 template <typename TExpr1, typename TExpr2>
1054 inline
1055 typename mpl::EnableIf<mpl::And<mpl::IsArray<TExpr2>, mpl::Not<mpl::IsArray<TExpr1> > >, unsigned int>::Type
1056 GetSize(TExpr1 const& itkNotUsed(lhs), TExpr2 const& rhs)
1057  {
1058  return rhs.Size();
1059  }
1060 
1061 template <typename T>
1062 struct GetType<VariableLengthVector<T> >
1063  {
1064  typedef T Type;
1065  static Type Load(VariableLengthVector<T> const& v, unsigned int idx)
1066  { return v[idx]; }
1067  };
1068 template <typename TExpr1, typename TExpr2, typename TBinaryOp>
1069 struct GetType<VariableLengthVectorExpression<TExpr1, TExpr2, TBinaryOp> >
1070  {
1072  static Type Load(VariableLengthVectorExpression<TExpr1, TExpr2, TBinaryOp> const& v, unsigned int idx)
1073  { return v[idx]; }
1074  };
1076 
1077 namespace op
1078 {
1091 template <typename TExpr1, typename TExpr2>
1093 : mpl::Or< mpl::And<mpl::IsArray<TExpr1>, mpl::IsArray<TExpr2> >,
1094  mpl::And<mpl::IsArray<TExpr1>, mpl::IsNumber<TExpr2> >,
1095  mpl::And<mpl::IsNumber<TExpr1>, mpl::IsArray<TExpr2> >
1096  >
1097 {};
1098 
1110 template <typename TExpr1, typename TExpr2>
1112 : mpl::Or< mpl::And<mpl::IsArray<TExpr1>, mpl::IsNumber<TExpr2> >,
1113  mpl::And<mpl::IsNumber<TExpr1>, mpl::IsArray<TExpr2> >
1114  >
1115 {};
1116 
1128 template <typename TExpr1, typename TExpr2>
1130 : mpl::And<mpl::IsArray<TExpr1>, mpl::IsNumber<TExpr2> >
1131 {};
1132 
1133 } // op namespace
1134 } // Details namespace
1136 
1161 template <typename TExpr1, typename TExpr2, typename TBinaryOp>
1163 {
1164  VariableLengthVectorExpression(TExpr1 const& lhs, TExpr2 const& rhs)
1165  : m_lhs(lhs), m_rhs(rhs)
1166  {
1167  // Not neccessary actually as end-user/developper is not expected to
1168  // provide new BinaryOperations
1170  (itk::mpl::IsBaseOf<Details::op::BinaryOperationConcept, TBinaryOp>::Value),
1171  "The Binary Operation shall inherit from BinaryOperationConcept");
1172  }
1173 
1175  unsigned int Size() const{ return Details::GetSize(m_lhs, m_rhs); }
1176 
1178  typedef typename mpl::PromoteType<
1179  typename Details::GetType<TExpr1>::Type,
1180  typename Details::GetType<TExpr2>::Type>::Type ResType;
1182  typedef typename NumericTraits< ResType > ::RealType RealValueType;
1183 
1194  ResType operator[](unsigned int idx) const
1195  {
1196  itkAssertInDebugAndIgnoreInReleaseMacro(idx < Size());
1197  return TBinaryOp::Apply(
1198  Details::GetType<TExpr1>::Load(m_lhs, idx),
1199  Details::GetType<TExpr2>::Load(m_rhs, idx));
1200  }
1202 
1204  RealValueType GetNorm() const;
1205 
1207  RealValueType GetSquaredNorm() const;
1208 
1209 private:
1210  TExpr1 const& m_lhs;
1211  TExpr2 const& m_rhs;
1212 };
1213 
1223 template <typename TExpr1, typename TExpr2>
1224 inline
1225 typename mpl::EnableIf<Details::op::CanBeAddedOrSubstracted<TExpr1,TExpr2>, VariableLengthVectorExpression<TExpr1, TExpr2, Details::op::Plus> >::Type
1226 operator+(TExpr1 const& lhs, TExpr2 const& rhs)
1228 
1238 template <typename TExpr1, typename TExpr2>
1239 inline
1240 typename mpl::EnableIf<Details::op::CanBeAddedOrSubstracted<TExpr1,TExpr2>, VariableLengthVectorExpression<TExpr1, TExpr2, Details::op::Sub> >::Type
1241 operator-(TExpr1 const& lhs, TExpr2 const& rhs)
1243 
1252 template <typename TExpr1, typename TExpr2>
1253 inline
1254 typename mpl::EnableIf<Details::op::CanBeMultiplied<TExpr1,TExpr2>, VariableLengthVectorExpression<TExpr1, TExpr2, Details::op::Mult> >::Type
1255 operator*(TExpr1 const& lhs, TExpr2 const& rhs)
1257 
1265 template <typename TExpr1, typename TExpr2>
1266 inline
1267 typename mpl::EnableIf<Details::op::CanBeDivided<TExpr1,TExpr2>, VariableLengthVectorExpression<TExpr1, TExpr2, Details::op::Div> >::Type
1268 operator/(TExpr1 const& lhs, TExpr2 const& rhs)
1270 
1274 template <typename TExpr1, typename TExpr2, typename TBinaryOp>
1275 std::ostream & operator<<(std::ostream &os, VariableLengthVectorExpression<TExpr1, TExpr2, TBinaryOp> const& v)
1276 {
1277  os << "[";
1278  if (v.Size() != 0)
1279  {
1280  os << v[0];
1281  for (unsigned int i = 1, N = v.Size(); i != N; ++i)
1282  {
1283  os << ", " << v[i];
1284  }
1285  }
1286  return os << "]";
1287 }
1289 
1295 template <typename TExpr>
1296 inline
1297 typename mpl::EnableIf<mpl::IsArray<TExpr>, typename TExpr::RealValueType>::Type
1298 GetNorm(TExpr const& v)
1299 {
1300  return static_cast<typename TExpr::RealValueType>(
1301  std::sqrt(static_cast<double>(GetSquaredNorm(v))));
1302 }
1303 
1309 template <typename TExpr>
1310 inline
1311 typename mpl::EnableIf<mpl::IsArray<TExpr>, typename TExpr::RealValueType>::Type
1312 GetSquaredNorm(TExpr const& v)
1313 {
1314  typedef typename TExpr::RealValueType RealValueType;
1315  RealValueType sum = 0.0;
1316  for ( unsigned int i = 0, N=v.Size(); i < N; ++i )
1317  {
1318  const RealValueType value = v[i];
1319  sum += value * value;
1320  }
1321  return sum;
1322 }
1324 
1327 
1331 template< typename TValue >
1332 std::ostream & operator<<(std::ostream & os, const VariableLengthVector< TValue > & arr)
1333 {
1334  const unsigned int length = arr.Size();
1335  const signed int last = (unsigned int)length - 1;
1337 
1338  os << "[";
1339  for ( signed int i = 0; i < last; ++i )
1340  {
1341  os << arr[i] << ", ";
1342  }
1343  if ( length >= 1 )
1344  {
1345  os << arr[last];
1346  }
1347  os << "]";
1348  return os;
1349 }
1351 
1354 
1372 template <typename T>
1373 inline
1375 {
1376  l_.Swap(r_);
1377 }
1379 
1380 
1381 } // namespace itk
1382 
1384 
1385 #ifndef ITK_MANUAL_INSTANTIATION
1386 #include "itkVariableLengthVector.hxx"
1387 #endif
1388 
1389 #endif
bool operator!=(const ImageRegionCopier< D1, D2 > &c1, const ImageRegionCopier< D1, D2 > &c2)
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.
TValue & operator[](unsigned int i)
ConstNeighborhoodIterator< TImage > operator-(const ConstNeighborhoodIterator< TImage > &it, const typename ConstNeighborhoodIterator< TImage >::OffsetType &ind)
unsigned int Size(void) const
Represent the size (bounds) of a n-dimensional image.
Definition: itkSize.h:52
VariableLengthVector(const VariableLengthVector< T > &v)
unsigned int GetNumberOfElements(void) const
bool operator()(unsigned int newSize, unsigned int oldSize) const
mpl::EnableIf< Details::op::CanBeAddedOrSubstracted< TExpr1, TExpr2 >, VariableLengthVectorExpression< TExpr1, TExpr2, Details::op::Plus > >::Type operator+(TExpr1 const &lhs, TExpr2 const &rhs)
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
unsigned int GetSize(void) const
void swap(Array< T > &a, Array< T > &b)
Definition: itkArray.h:215
bool operator()(unsigned int newSize, unsigned int oldSize) const
Represents an array whose length can be defined at run-time.
mpl::EnableIf< Details::op::CanBeAddedOrSubstracted< TExpr1, TExpr2 >, VariableLengthVectorExpression< TExpr1, TExpr2, Details::op::Sub > >::Type operator-(TExpr1 const &lhs, TExpr2 const &rhs)
Self & operator=(const VariableLengthVector< T > &v)
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)
void operator()(unsigned int, unsigned int, TValue2 *, TValue2 *) const
void SetSize(unsigned int sz, bool destroyExistingData=true)
NumericTraits< ValueType >::RealType RealValueType
#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)
mpl::PromoteType< typename Details::GetType< TExpr1 >::Type, typename Details::GetType< TExpr2 >::Type >::Type ResType
Vector type of the Result Expression.
bool ITKIOXML_EXPORT operator==(itk::FancyString &s, const std::string &)
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