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 itkArray_h
19 #define itkArray_h
20 
21 #include "itkMacro.h"
22 
23 #include "vxl_version.h"
24 #include "vnl/vnl_vector.h"
25 
26 namespace itk
27 {
28 /** \class Array
29  *  \brief Array class with size defined at construction time.
30  *
31  * This class derives from the vnl_vector<> class.
32  * Its size is assigned at construction time (run time) and can
33  * not be changed afterwards except by using assignment to another
34  * Array.
35  *
36  * The class is templated over the type of the elements.
37  *
38  * Template parameters for class Array:
39  *
40  * - TValue = Element type stored at each location in the array.
41  *
42  * \ingroup DataRepresentation
43  * \ingroup ITKCommon
44  */
45 template< typename TValue >
46 class ITK_TEMPLATE_EXPORT Array : public vnl_vector< TValue >
47 {
48 public:
49 
50   /** The element type stored at each location in the Array. */
51   using ValueType = TValue;
52   using Self = Array;
53   using VnlVectorType = vnl_vector< TValue >;
54   using SizeValueType = typename vnl_vector< TValue>::size_type;
55 
56 public:
57 
58   /** Default constructor. It is created with an empty array
59    *  it has to be allocated later by assignment              */
60   Array();
61 
62   /** Copy constructor.  Uses VNL copy construtor with correct
63    *  setting for memory management.                          */
64   Array(const Array&);
65 
66   /** Constructor with size. Size can only be changed by assignment */
67   explicit Array(SizeValueType dimension);
68 
69   /** Constructor that initializes array with contents from a user supplied
70    * buffer. The pointer to the buffer and the length is specified. By default,
71    * the array does not manage the memory of the buffer. It merely points to
72    * that location and it is the user's responsibility to delete it.
73    * If "LetArrayManageMemory" is true, then this class will free the
74    * memory when this object is destroyed. */
75   Array(ValueType *data, SizeValueType sz, bool LetArrayManageMemory = false);
76 
77 #if defined ( ITK_LEGACY_REMOVE )
78   /** Constructor that initializes array with contents from a user supplied
79    * const buffer. The pointer to the buffer and the length is specified. By default,
80    * the array does a deep copy of the const pointer data, so the array class also
81    * manages memory. */
82   Array(const ValueType *datain, SizeValueType sz);
83 
84 #else // defined ( ITK_LEGACY_REMOVE )
85   /** Constructor that initializes array with contents from a user supplied
86    * buffer. The pointer to the buffer and the length is specified. By default,
87    * the array does not manage the memory of the buffer. It merely points to
88    * that location and it is the user's responsibility to delete it.
89    * If "LetArrayManageMemory" is true, then this class will free the
90    * memory when this object is destroyed. */
91   Array(const ValueType *data, SizeValueType sz,
92         bool LetArrayManageMemory = false);
93 #endif
94 
95   /** Constructor to initialize an array from another of any data type */
96   template< typename TArrayValue >
Array(const Array<TArrayValue> & r)97   Array(const Array< TArrayValue > & r)
98   {
99     this->m_LetArrayManageMemory = true;
100     this->SetSize( r.GetSize() );
101     for( SizeValueType i=0; i<r.GetSize(); i++ )
102       {
103       this->operator[](i) = static_cast< TValue >( r[i] );
104       }
105   }
106 
107   /** Set the all the elements of the array to the specified value */
Fill(TValue const & v)108   void Fill(TValue const & v)
109     {
110     this->fill(v);
111     }
112 
113   /** Copy opertor */
114   const Self & operator=(const Self & rhs);
115 
116   const Self & operator=(const VnlVectorType & rhs);
117 
118   /** Return the number of elements in the Array  */
Size()119   SizeValueType Size() const
120   { return static_cast<SizeValueType >( this->size() ); }
GetNumberOfElements()121   unsigned int GetNumberOfElements() const
122   { return static_cast<SizeValueType >( this->size() ); }
123 
124   /** Get one element */
GetElement(SizeValueType i)125   const TValue & GetElement(SizeValueType i) const
126   { return this->operator[](i); }
127 
128   /** Set one element */
SetElement(SizeValueType i,const TValue & value)129   void SetElement(SizeValueType i, const TValue & value)
130   { this->operator[](i) = value; }
131 
132   /** Destructively set the size to that given.  Will lose data.  */
133   void SetSize(SizeValueType sz);
134 
GetSize()135   SizeValueType GetSize() const
136   { return static_cast< SizeValueType >( this->size() ); }
137 
138   /** Set the pointer from which the data is imported.
139    * If "LetArrayManageMemory" is false, then the application retains
140    * the responsibility of freeing the memory for this data.  If
141    * "LetArrayManageMemory" is true, then this class will free the
142    * memory when this object is destroyed.
143    * NOTE: This signature requires that internal array is being
144    *       replaced by data array of exactly the same size
145     */
146   void SetDataSameSize(TValue *data, bool LetArrayManageMemory = false);
147 
148   /** Similar to the previous method. In the above method, the size must be
149    * separately set prior to using user-supplied data. This introduces an
150    * unnecessary allocation step to be performed. This method avoids it
151    * and should be used to import data wherever possible to avoid this.
152    * Set the pointer from which the data is imported.
153    * If "LetArrayManageMemory" is false, then the application retains
154    * the responsibility of freeing the memory for this data.  If
155    * "LetArrayManageMemory" is true, then this class will free the
156    * memory when this object is destroyed. */
157   void SetData(TValue *data, SizeValueType sz, bool LetArrayManageMemory = false);
158 
159 #ifdef __INTEL_COMPILER
160 #pragma warning disable 444 //destructor for base class "itk::Array<>" is not virtual
161 #endif
162   /** This destructor is not virtual for performance reasons. However, this
163    * means that subclasses cannot allocate memory. */
164   ~Array();
165 
166 #if ! defined ( ITK_LEGACY_REMOVE )
swap(Array & other)167   void swap(Array &other)
168     {
169       this->Swap(other);
170     }
171 #endif
172 
Swap(Array & other)173   void Swap(Array &other)
174     {
175       using std::swap;
176       this->VnlVectorType::swap(other);
177       swap(this->m_LetArrayManageMemory, other.m_LetArrayManageMemory);
178     }
179 
180 private:
181 
182   bool m_LetArrayManageMemory;
183 };
184 
185 template< typename TValue >
186 std::ostream & operator<<(std::ostream & os, const Array< TValue > & arr)
187 {
188   os << "[";
189   const unsigned int length = arr.size();
190   if ( length >= 1 )
191     {
192     const unsigned int   last   = length - 1;
193     for ( unsigned int i = 0; i < last; ++i )
194       {
195       os << arr[i] << ", ";
196       }
197       os << arr[last];
198     }
199   os << "]";
200   return os;
201 }
202 
203 // declaration of specialization
204 template<> ITKCommon_EXPORT std::ostream & operator<< <double> (std::ostream & os, const Array< double > & arr);
205 template<> ITKCommon_EXPORT std::ostream & operator<< <float> (std::ostream & os, const Array< float > & arr);
206 
207 
208 template<typename T>
swap(Array<T> & a,Array<T> & b)209 inline void swap( Array<T> &a, Array<T> &b )
210 {
211   a.Swap(b);
212 }
213 
214 } // namespace itk
215 
216 #ifndef ITK_MANUAL_INSTANTIATION
217 #include "itkArray.hxx"
218 #endif
219 
220 #endif
221