1 /* ***** BEGIN LICENSE BLOCK *****
2 *
3 * $Id: arrays.h,v 1.21 2008/03/14 08:17:36 asuraparaju Exp $ $Name: Dirac_1_0_2 $
4 *
5 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
6 *
7 * The contents of this file are subject to the Mozilla Public License
8 * Version 1.1 (the "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 * http://www.mozilla.org/MPL/
11 *
12 * Software distributed under the License is distributed on an "AS IS" basis,
13 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
14 * the specific language governing rights and limitations under the License.
15 *
16 * The Original Code is BBC Research and Development code.
17 *
18 * The Initial Developer of the Original Code is the British Broadcasting
19 * Corporation.
20 * Portions created by the Initial Developer are Copyright (C) 2004.
21 * All Rights Reserved.
22 *
23 * Contributor(s): Thomas Davies (Original Author),
24 *                 Peter Meerwald (pmeerw@users.sourceforge.net)
25 *                 Mike Ferenduros (mike_ferenzduros@users.sourceforge.net)
26 *                 Anuradha Suraparaju
27 *
28 * Alternatively, the contents of this file may be used under the terms of
29 * the GNU General Public License Version 2 (the "GPL"), or the GNU Lesser
30 * Public License Version 2.1 (the "LGPL"), in which case the provisions of
31 * the GPL or the LGPL are applicable instead of those above. If you wish to
32 * allow use of your version of this file only under the terms of the either
33 * the GPL or LGPL and not to allow others to use your version of this file
34 * under the MPL, indicate your decision by deleting the provisions above
35 * and replace them with the notice and other provisions required by the GPL
36 * or LGPL. If you do not delete the provisions above, a recipient may use
37 * your version of this file under the terms of any one of the MPL, the GPL
38 * or the LGPL.
39 * ***** END LICENSE BLOCK ***** */
40 
41 #ifndef _ARRAYS_H_
42 #define _ARRAYS_H_
43 
44 //basic array types used for pictures etc
45 
46 #include <memory>
47 #include <cstddef>
48 #include <stdexcept>
49 #include <iostream>
50 #include <algorithm>
51 #include <cstring>
52 
53 namespace dirac
54 {
55     //! Range type.
56     /*!
57         Range type encapsulating a closed range of values [first,last].
58         Used to initialies OneDArrays.
59      */
60     class Range
61     {
62     public:
63         //! Constructor
64         /*!
65             Constructor taking a start and an end point for the range.
66          */
Range(int s,int e)67         Range(int s, int e): m_fst(s), m_lst(e){}
68 
69         //! Returns the start of the range.
First()70         int First() const {return m_fst;}
71 
72         //! Returns the end point of the range.
Last()73         int Last() const {return m_lst;}
74 
75     private:
76         int m_fst ,m_lst;
77     };
78 
79     //////////////////////////////
80     //One-Dimensional Array type//
81     //////////////////////////////
82 
83     //! A template class for one-dimensional arrays.
84     /*!
85         A template class for one-D arrays. Can be used wherever built-in
86         arrays are used, and eliminates the need for explicit memory
87         (de-)allocation. Also supports arrays not based at zero.
88      */
89     template <class T> class OneDArray
90     {
91     public:
92         //! Default constructor.
93         /*!
94             Default constructor produces an empty array.
95          */
96         OneDArray();
97 
98         //! 'Length' constructor.
99         /*!
100             Length constructor produces a zero-based array.
101          */
102         OneDArray(const int len);
103 
104        //! Range constructor
105         /*!
106             Range constructor produces an array with values indexed within the
107             range parameters.
108             \param    r    a range of indexing values.
109          */
110         OneDArray(const Range& r);
111 
112         //! Destructor.
113         /*!
114             Destructor frees the data allocated in the constructors.
115          */
~OneDArray()116         ~OneDArray()
117         {
118             FreePtr();
119         }
120 
121         //! Copy constructor.
122         /*!
123             Copy constructor copies both data and metadata.
124          */
125         OneDArray(const OneDArray<T>& cpy);
126 
127         //! Assignment=
128         /*!
129             Assignment= assigns both data and metadata.
130          */
131         OneDArray<T>& operator=(const OneDArray<T>& rhs);
132 
133         //! Resize the array, throwing away the current data.
134         void Resize(int l);
135 
136         //! Element access.
137         T& operator[](const int pos){return m_ptr[pos-m_first];}
138 
139         //! Element access.
140         const T& operator[](const int pos) const {return m_ptr[pos-m_first];}
141 
142         //! Returns the length of the array.
Length()143         int Length() const {return m_length;}
144 
145         //! Returns the index of the first element.
First()146         int First() const {return m_first;}
147 
148         //! Returns the index of the last element.
Last()149         int Last() const {return m_last;}
150 
151     private:
152         void Init(const int len);
153 
154         void Init(const Range& r);
155 
156         void FreePtr();
157 
158         int m_first, m_last;
159         int m_length;
160         T* m_ptr;
161     };
162 
163     //public member functions//
164     ///////////////////////////
165 
166     template <class T>
OneDArray()167     OneDArray<T>::OneDArray()
168     {
169         Init(0);
170     }
171 
172     template <class T>
OneDArray(const int len)173     OneDArray<T>::OneDArray(const int len)
174     {
175         Init(len);
176     }
177 
178     template <class T>
OneDArray(const Range & r)179     OneDArray<T>::OneDArray(const Range& r)
180     {
181         Init(r);
182     }
183 
184     template <class T>
OneDArray(const OneDArray<T> & cpy)185     OneDArray<T>::OneDArray(const OneDArray<T>& cpy)
186     {
187         m_first = cpy.m_first;
188         m_last = cpy.m_last;
189         m_length = m_last - m_first + 1;
190 
191         if (m_first==0)
192             Init(m_length);
193         else
194             Init(Range(m_first , m_last));
195 
196         memcpy( m_ptr , cpy.m_ptr , m_length * sizeof( T ) );
197     }
198 
199     template <class T>
200     OneDArray<T>& OneDArray<T>::operator=(const OneDArray<T>& rhs)
201     {
202         if (&rhs != this)
203         {
204             FreePtr();
205             m_first = rhs.m_first;
206             m_last = rhs.m_last;
207             m_length = rhs.m_length;
208 
209             if (m_first == 0)
210                 Init(m_length);
211             else
212                 Init(Range(m_first , m_last));
213 
214             memcpy( m_ptr , rhs.m_ptr , m_length * sizeof( T ) );
215 
216         }
217         return *this;
218     }
219 
220     template <class T>
Resize(int l)221     void OneDArray<T>::Resize(int l)
222     {
223         if (l != m_length)
224         {
225             FreePtr();
226             Init(l);
227         }
228     }
229 
230     //private member functions//
231     ////////////////////////////
232 
233     template <class T>
Init(const int len)234     void OneDArray<T>::Init(const int len)
235     {
236         Range r(0 , len-1);
237 
238         Init(r);
239 
240     }
241 
242     template <class T>
Init(const Range & r)243     void OneDArray<T>::Init(const Range& r)
244     {
245 
246         m_first = r.First();
247         m_last = r.Last();
248         m_length = m_last - m_first + 1;
249 
250         if ( m_length>0 )
251         {
252             m_ptr = new T[ m_length ];
253         }
254         else
255         {
256             m_length = 0;
257             m_first = 0;
258             m_last = -1;
259             m_ptr = NULL;
260         }
261     }
262 
263     template <class T>
FreePtr()264     void OneDArray<T>::FreePtr()
265     {
266         if ( m_length>0 )
267             delete[] m_ptr;
268     }
269 
270 
271     //////////////////////////////
272     //Two-Dimensional Array type//
273     //////////////////////////////
274 
275     //! A template class for two-dimensional arrays.
276     /*!
277         A template class to do two-d arrays, so that explicit memory
278         (de-)allocation is not required. Only zero-based arrays are
279         currently supported so that access is fast. Accessing elements along
280         a row is therefore much faster than accessing them along a column.
281         Rows are contiguous in memory, so array[y][x] is equivalent to
282         array[0][x+y*LengthX()].
283      */
284     template <class T> class TwoDArray
285     {
286         typedef T* element_type;
287 
288     public:
289 
290         //! Default constructor.
291         /*!
292             Default constructor creates an empty array.
293          */
TwoDArray()294         TwoDArray(){ Init(0,0); }
295 
296         //! Constructor.
297         /*!
298             The constructor creates an array of given width height.
299          */
TwoDArray(const int height,const int width)300         TwoDArray( const int height , const int width ){Init(height , width);}
301 
302         //! Constructor.
303         /*!
304             The constructor creates an array of given width and length height
305             and initialises it to a value
306          */
307         TwoDArray( const int height , const int width , T val);
308 
309         //! Destructor
310         /*!
311             Destructor frees the data allocated in the constructor.
312          */
~TwoDArray()313         virtual ~TwoDArray(){
314             FreeData();
315         }
316 
317         //! Copy constructor.
318         /*!
319             Copy constructor copies data and metadata.
320          */
321         TwoDArray(const TwoDArray<T>& Cpy);
322 
323         //! Assignment =
324         /*!
325             Assignement = assigns both data and metadata.
326          */
327         TwoDArray<T>& operator=(const TwoDArray<T>& rhs);
328 
329         //! Copy Contents
330         /*!
331             Copy contents of array into output array retaining the dimensions
332             of the output array. If output array is larger that array then
333             pad with last true value.
334             Return true is copy was successful
335          */
336         bool CopyContents(TwoDArray<T>& out) const;
337 
338         //! Fill contents
339         /*!
340             Initialise the array with the val provided.
341          */
342         void Fill(T val);
343 
344         //! Resizes the array, deleting the current data.
345         void Resize(const int height, const int width);
346 
347         //! Element access.
348         /*!
349             Accesses the rows of the arrays, which are returned in the form
350             of pointers to the row data NOT OneDArray objects.
351          */
352         inline element_type& operator[](const int pos){return m_array_of_rows[pos];}
353 
354         //! Element access.
355         /*!
356             Accesses the rows of the arrays, which are returned in the form of
357             pointers to the row data NOT OneDArray objects.
358          */
359         inline const element_type& operator[](const int pos) const {return m_array_of_rows[pos];}
360 
361         //! Returns the width
LengthX()362         int LengthX() const { return m_length_x; }
363 
364         //! Returns the height
LengthY()365         int LengthY() const { return m_length_y; }
366 
367         //! Returns the index of the first element of a row
FirstX()368         int FirstX() const { return m_first_x; }
369 
370         //! Returns the index of the first element of a column
FirstY()371         int FirstY() const { return m_first_y; }
372 
373         //! Returns the index of the last element of a row
LastX()374         int LastX() const { return m_last_x; }
375 
376         //! Returns the index of the first element of a column
LastY()377         int LastY() const { return m_last_y; }
378 
379     private:
380         //! Initialise the array
381         void Init(const int height,const int width);
382 
383         //! Free all the allocated data
384         void FreeData();
385 
386         int m_first_x;
387         int m_first_y;
388 
389         int m_last_x;
390         int m_last_y;
391 
392         int m_length_x;
393         int m_length_y;
394 
395         element_type* m_array_of_rows;
396     };
397 
398     //public member functions//
399     ///////////////////////////
400 
401     template <class T>
TwoDArray(const int height,const int width,const T val)402     TwoDArray<T>::TwoDArray( const int height , const int width , const T val)
403     {
404         Init( height , width );
405         std::fill_n( m_array_of_rows[0], m_length_x*m_length_y, val);
406     }
407 
408     template <class T>
TwoDArray(const TwoDArray<T> & Cpy)409     TwoDArray<T>::TwoDArray(const TwoDArray<T>& Cpy)
410     {
411         m_first_x = Cpy.m_first_x;
412         m_first_y = Cpy.m_first_y;
413         m_last_x = Cpy.m_last_x;
414         m_last_y = Cpy.m_last_y;
415 
416         m_length_x = m_last_x - m_first_x + 1;
417         m_length_y = m_last_y - m_first_y + 1;
418 
419         if (m_first_x == 0 && m_first_y == 0)
420             Init(m_length_y , m_length_x);
421         else{
422                 //based 2D arrays not yet supported
423         }
424 
425         memcpy( m_array_of_rows[0] , (Cpy.m_array_of_rows)[0] , m_length_x * m_length_y * sizeof( T ) );
426 
427     }
428 
429     template <class T>
430     TwoDArray<T>& TwoDArray<T>::operator=(const TwoDArray<T>& rhs)
431     {
432         if (&rhs != this)
433         {
434             FreeData();
435 
436             m_first_x = rhs.m_first_x;
437             m_first_y = rhs.m_first_y;
438 
439             m_last_x = rhs.m_last_x;
440             m_last_y = rhs.m_last_y;
441 
442             m_length_x = m_last_x - m_first_x + 1;
443             m_length_y = m_last_y - m_first_y + 1;
444 
445             if (m_first_x == 0 && m_first_y == 0)
446                 Init(m_length_y , m_length_x);
447             else
448             {
449                     //based 2D arrays not yet supported
450             }
451 
452             memcpy( m_array_of_rows[0], (rhs.m_array_of_rows)[0], m_length_x * m_length_y * sizeof( T ) );
453 
454         }
455 
456         return *this;
457 
458     }
459 
460     template <class T>
CopyContents(TwoDArray<T> & out)461     bool TwoDArray<T>::CopyContents(TwoDArray<T>& out) const
462     {
463         if (&out != this)
464         {
465             int rows = std::min (m_length_y, out.m_length_y);
466             int cols = std::min (m_length_x, out.m_length_x);
467             for (int j = 0; j < rows; ++j)
468             {
469                 memcpy( out.m_array_of_rows[j], m_array_of_rows[j], cols * sizeof( T )) ;
470                 for (int i = cols; i <out.m_length_x; ++i)
471                     out.m_array_of_rows[j][i] = out.m_array_of_rows[j][cols-1];
472             }
473             for (int j = rows; j < out.m_length_y; ++j)
474             {
475                 memcpy( out.m_array_of_rows[j], out.m_array_of_rows[rows-1], out.m_length_x * sizeof( T )) ;
476             }
477         }
478         return true;
479     }
480 
481     template <class T>
Fill(T val)482     void TwoDArray<T>::Fill( T val)
483     {
484         if (m_length_x && m_length_y)
485             std::fill_n( m_array_of_rows[0], m_length_x*m_length_y, val);
486     }
487 
488     template <class T>
Resize(const int height,const int width)489     void TwoDArray<T>::Resize(const int height, const int width)
490     {
491         if (height != m_length_y || width != m_length_x)
492         {
493             FreeData();
494             Init(height , width);
495         }
496     }
497 
498     //private member functions//
499     ////////////////////////////
500 
501     template <class T>
Init(const int height,const int width)502     void TwoDArray<T>::Init(const int height , const int width)
503     {
504         m_length_x = width;
505         m_length_y = height;
506         m_first_x = 0;
507         m_first_y = 0;
508 
509         m_last_x = m_length_x-1;
510         m_last_y = m_length_y-1;
511 
512         if (m_length_y>0)
513         {
514             // allocate the array containing ptrs to all the rows
515             m_array_of_rows = new element_type[ m_length_y ];
516 
517             if ( m_length_x>0 )
518             {
519                 // Allocate the whole thing as a single big block
520                 m_array_of_rows[0] = new T[ m_length_x * m_length_y ];
521 
522                 // Point the pointers
523                 for (int j=1 ; j<m_length_y ; ++j)
524                     m_array_of_rows[j] = m_array_of_rows[0] + j * m_length_x;
525             }
526             else
527             {
528                 m_length_x = 0;
529                 m_first_x = 0;
530                 m_last_x = -1;
531             }
532         }
533         else
534         {
535             m_length_x = 0;
536             m_length_y = 0;
537             m_first_x = 0;
538             m_first_y = 0;
539             m_last_x = -1;
540             m_last_y = -1;
541             m_array_of_rows = NULL;
542         }
543     }
544 
545     template <class T>
FreeData()546     void TwoDArray<T>::FreeData()
547     {
548         if (m_length_y>0)
549         {
550             if (m_length_x>0)
551             {
552                 delete[] m_array_of_rows[0];
553             }
554 
555             m_length_y = m_length_x = 0;
556             // deallocate the array of rows
557             delete[] m_array_of_rows;
558         }
559     }
560 
561     // Related functions
562 
563     //! A function for extracting array data
564     template <class T >
565     std::ostream & operator<< (std::ostream & stream, TwoDArray<T> & array)
566     {
567         for (int j=0 ; j<array.LengthY() ; ++j)
568         {
569             for (int i=0 ; i<array.LengthX() ; ++i)
570             {
571                 stream << array[j][i] << " ";
572             }// i
573             stream << std::endl;
574         }// j
575 
576         return stream;
577     }
578 
579     //! A function for inserting array data
580     template <class T >
581     std::istream & operator>> (std::istream & stream, TwoDArray<T> & array)
582     {
583         for (int j=0 ; j<array.LengthY() ; ++j)
584         {
585             for (int i=0 ; i<array.LengthX() ; ++i)
586             {
587                 stream >> array[j][i];
588             }// i
589         }// j
590 
591         return stream;
592     }
593 
594 } //namespace dirac
595 #endif
596