]> git.uio.no Git - u/mrichter/AliRoot.git/blob - HLT/BASE/AliHLTArray.h
coding conventions
[u/mrichter/AliRoot.git] / HLT / BASE / AliHLTArray.h
1 //-*- Mode: C++ -*-
2 // $Id$
3
4 // ****************************************************************************
5 // * This file is property of and copyright by the ALICE HLT Project          *
6 // * ALICE Experiment at CERN, All rights reserved.                           *
7 // *                                                                          *
8 // * Copyright (C) 2009 Matthias Kretz <kretz@kde.org>                        *
9 // *               for The ALICE HLT Project.                                 *
10 // *                                                                          *
11 // * Permission to use, copy, modify and distribute this software and its     *
12 // * documentation strictly for non-commercial purposes is hereby granted     *
13 // * without fee, provided that the above copyright notice appears in all     *
14 // * copies and that both the copyright notice and this permission notice     *
15 // * appear in the supporting documentation. The authors make no claims       *
16 // * about the suitability of this software for any purpose. It is            *
17 // * provided "as is" without express or implied warranty.                    *
18 // ****************************************************************************
19
20 /**
21  * \file AliHLTArray.h
22  * \author Matthias Kretz <kretz@kde.org>
23  *
24  * This file contains the classes AliHLTResizableArray and AliHLTFixedArray with AliHLTArray as base
25  * class. It's a drop-in replacement for C-Arrays. It makes it easy to use variable sized arrays on
26  * the stack and pass arrays as arguments to other functions with an optional bounds-checking
27  * enabled for the whole time.
28  */
29
30 #ifndef ALIHLTARRAY_H
31 #define ALIHLTARRAY_H
32
33 #ifndef assert
34 #include <assert.h>
35 #endif
36
37 #if (defined(__MMX__) || defined(__SSE__))
38 #if defined(__GNUC__)
39 #if __GNUC__ > 3
40 #define USE_MM_MALLOC
41 #endif
42 #else // not gcc, assume it can use _mm_malloc since it supports MMX/SSE
43 #define USE_MM_MALLOC
44 #endif
45 #endif
46
47 #ifdef USE_MM_MALLOC
48 #include <mm_malloc.h>
49 #else
50 #include <cstdlib>
51 #endif
52
53 enum {
54   AliHLTFullyCacheLineAligned = -1
55 };
56
57 #if defined(__CUDACC__) & 0
58 #define ALIHLTARRAY_STATIC_ASSERT(a, b)
59 #define ALIHLTARRAY_STATIC_ASSERT_NC(a, b)
60 #else
61 namespace AliHLTArrayInternal
62 {
63   template<bool> class STATIC_ASSERT_FAILURE;
64   template<> class STATIC_ASSERT_FAILURE<true> {};
65 }
66
67 #define ALIHLTARRAY_STATIC_ASSERT_CONCAT_HELPER(a, b) a##b
68 #define ALIHLTARRAY_STATIC_ASSERT_CONCAT(a, b) ALIHLTARRAY_STATIC_ASSERT_CONCAT_HELPER(a, b)
69 #define ALIHLTARRAY_STATIC_ASSERT_NC(cond, msg) \
70   typedef AliHLTArrayInternal::STATIC_ASSERT_FAILURE<cond> ALIHLTARRAY_STATIC_ASSERT_CONCAT(_STATIC_ASSERTION_FAILED_##msg, __LINE__); \
71   ALIHLTARRAY_STATIC_ASSERT_CONCAT(_STATIC_ASSERTION_FAILED_##msg, __LINE__) Error_##msg
72 #define ALIHLTARRAY_STATIC_ASSERT(cond, msg) ALIHLTARRAY_STATIC_ASSERT_NC(cond, msg); (void) Error_##msg
73 #endif
74
75 template<typename T, int Dim> class AliHLTArray;
76
77 namespace AliHLTInternal
78 {
79   template<unsigned int Size> struct Padding { char fPadding[Size]; };
80   template<> struct Padding<0> {};
81   template<typename T> struct CacheLineSizeHelperData { T fData; };
82   template<typename T> struct CacheLineSizeHelperEnums {
83     enum {
84       CacheLineSize = 64,
85       MaskedSize = sizeof( T ) & ( CacheLineSize - 1 ),
86       RequiredSize = MaskedSize == 0 ? sizeof( T ) : sizeof( T ) + CacheLineSize - MaskedSize,
87       PaddingSize = RequiredSize - sizeof( T )
88     };
89   };
90   template<typename T> class CacheLineSizeHelper : private CacheLineSizeHelperData<T>, private Padding<CacheLineSizeHelperEnums<T>::PaddingSize>
91   {
92     public:
93       operator T &() { return CacheLineSizeHelperData<T>::fData; }
94       operator const T &() const { return CacheLineSizeHelperData<T>::fData; }
95       //const T &operator=( const T &rhs ) { CacheLineSizeHelperData<T>::fData = rhs; }
96
97     private:
98   };
99   template<typename T, int alignment> struct TypeForAlignmentHelper { typedef T Type; };
100   template<typename T> struct TypeForAlignmentHelper<T, AliHLTFullyCacheLineAligned> { typedef CacheLineSizeHelper<T> Type; };
101
102   // XXX
103   // The ArrayBoundsCheck and Allocator classes implement a virtual destructor only in order to
104   // silence the -Weffc++ warning. It really is not required for these classes to have a virtual
105   // dtor since polymorphism is not used (AliHLTResizableArray and AliHLTFixedArray are allocated on
106   // the stack only). The virtual dtor only adds an unnecessary vtable to the code.
107 #ifndef ENABLE_ARRAY_BOUNDS_CHECKING
108   /**
109    * no-op implementation that for no-bounds-checking
110    */
111   class ArrayBoundsCheck
112   {
113     protected:
114       virtual inline ~ArrayBoundsCheck() {}
115       inline bool IsInBounds( int ) const { return true; }
116       inline void SetBounds( int, int ) {}
117       inline void MoveBounds( int ) {}
118       inline void ReinterpretCast( const ArrayBoundsCheck &, int, int ) {}
119   };
120 #define BOUNDS_CHECK(x, y)
121 #else
122   /**
123    * implementation for bounds-checking.
124    */
125   class ArrayBoundsCheck
126   {
127     protected:
128       virtual inline ~ArrayBoundsCheck() {}
129       /**
130        * checks whether the given offset is valid
131        */
132       inline bool IsInBounds( int x ) const;
133       /**
134        * set the start and end offsets that are still valid
135        */
136       inline void SetBounds( int start, int end ) { fStart = start; fEnd = end; }
137       /**
138        * move the start and end offsets by the same amount
139        */
140       inline void MoveBounds( int d ) { fStart += d; fEnd += d; }
141
142       inline void ReinterpretCast( const ArrayBoundsCheck &other, int sizeofOld, int sizeofNew ) {
143         fStart = other.fStart * sizeofNew / sizeofOld;
144         fEnd = other.fEnd * sizeofNew / sizeofOld;
145       }
146
147     private:
148       int fStart; // start
149       int fEnd;   // end
150   };
151 #define BOUNDS_CHECK(x, y) if (AliHLTInternal::ArrayBoundsCheck::IsInBounds(x)) {} else return y
152 #endif
153   template<typename T, int alignment> class Allocator
154   {
155     public:
156 #ifdef USE_MM_MALLOC
157       static inline T *Alloc( int s ) { T *p = reinterpret_cast<T *>( _mm_malloc( s * sizeof( T ), alignment ) ); return new( p ) T[s]; }
158       static inline void Free( T *const p, int size ) {
159         for ( int i = 0; i < size; ++i ) {
160           p[i].~T();
161         }
162         _mm_free( p );
163       }
164 #else
165       static inline T *Alloc( int s ) { T *p; posix_memalign( &p, alignment, s * sizeof( T ) ); return new( p ) T[s]; }
166       static inline void Free( T *const p, int size ) {
167         for ( int i = 0; i < size; ++i ) {
168           p[i].~T();
169         }
170         std::free( p );
171       }
172 #endif
173   };
174   template<typename T> class Allocator<T, AliHLTFullyCacheLineAligned>
175   {
176     public:
177       typedef CacheLineSizeHelper<T> T2;
178 #ifdef USE_MM_MALLOC
179       static inline T2 *Alloc( int s ) { T2 *p = reinterpret_cast<T2 *>( _mm_malloc( s * sizeof( T2 ), 128 ) ); return new( p ) T2[s]; }
180       static inline void Free( T2 *const p, int size ) {
181         for ( int i = 0; i < size; ++i ) {
182                         p[i].~T2();
183         }
184         _mm_free( p );
185       }
186 #else
187       static inline T2 *Alloc( int s ) { T2 *p; posix_memalign( &p, 128, s * sizeof( T2 ) ); return new( p ) T2[s]; }
188       static inline void Free( T2 *const p, int size ) {
189         for ( int i = 0; i < size; ++i ) {
190                         p[i].~T2();
191         }
192         std::free( p );
193       }
194 #endif
195   };
196   template<typename T> class Allocator<T, 0>
197   {
198     public:
199       static inline T *Alloc( int s ) { return new T[s]; }
200       static inline void Free( const T *const p, int ) { delete[] p; }
201   };
202
203   template<typename T> struct ReturnTypeHelper { typedef T Type; };
204   template<typename T> struct ReturnTypeHelper<CacheLineSizeHelper<T> > { typedef T Type; };
205   /**
206    * Array base class for dimension dependent behavior
207    */
208   template<typename T, int Dim> class ArrayBase;
209
210   /**
211    * 1-dim arrays only have operator[]
212    */
213   template<typename T>
214   class ArrayBase<T, 1> : public ArrayBoundsCheck
215   {
216       friend class ArrayBase<T, 2>;
217     public:
218       ArrayBase() : fData( 0 ), fSize( 0 ) {} // XXX really shouldn't be done. But -Weffc++ wants it so
219       ArrayBase( const ArrayBase &rhs ) : ArrayBoundsCheck( rhs ), fData( rhs.fData ), fSize( rhs.fSize ) {} // XXX
220       ArrayBase &operator=( const ArrayBase &rhs ) { ArrayBoundsCheck::operator=( rhs ); fData = rhs.fData; return *this; } // XXX
221       typedef typename ReturnTypeHelper<T>::Type R;
222       /**
223        * return a reference to the value at the given index
224        */
225       inline R &operator[]( int x ) { BOUNDS_CHECK( x, fData[0] ); return fData[x]; }
226       /**
227        * return a const reference to the value at the given index
228        */
229       inline const R &operator[]( int x ) const { BOUNDS_CHECK( x, fData[0] ); return fData[x]; }
230
231     protected:
232       T *fData;  // actual data
233       int fSize; // data size
234       inline void SetSize( int x, int, int ) { fSize = x; }
235   };
236
237   /**
238    * 2-dim arrays should use operator(int, int)
239    * operator[] can be used to return a 1-dim array
240    */
241   template<typename T>
242   class ArrayBase<T, 2> : public ArrayBoundsCheck
243   {
244       friend class ArrayBase<T, 3>;
245     public:
246       ArrayBase() : fData( 0 ), fSize( 0 ), fStride( 0 ) {} // XXX really shouldn't be done. But -Weffc++ wants it so
247       ArrayBase( const ArrayBase &rhs ) : ArrayBoundsCheck( rhs ), fData( rhs.fData ), fSize( rhs.fSize ), fStride( rhs.fStride ) {} // XXX
248       ArrayBase &operator=( const ArrayBase &rhs ) { ArrayBoundsCheck::operator=( rhs ); fData = rhs.fData; fSize = rhs.fSize; fStride = rhs.fStride; return *this; } // XXX
249       typedef typename ReturnTypeHelper<T>::Type R;
250       /**
251        * return a reference to the value at the given indexes
252        */
253       inline R &operator()( int x, int y ) { BOUNDS_CHECK( x * fStride + y, fData[0] ); return fData[x * fStride + y]; }
254       /**
255        * return a const reference to the value at the given indexes
256        */
257       inline const R &operator()( int x, int y ) const { BOUNDS_CHECK( x * fStride + y, fData[0] ); return fData[x * fStride + y]; }
258       /**
259        * return a 1-dim array at the given index. This makes it behave like a 2-dim C-Array.
260        */
261       inline AliHLTArray<T, 1> operator[]( int x );
262       /**
263        * return a const 1-dim array at the given index. This makes it behave like a 2-dim C-Array.
264        */
265       inline const AliHLTArray<T, 1> operator[]( int x ) const;
266
267     protected:
268       T *fData;    // actual data
269       int fSize;   // data size
270       int fStride; // 
271       inline void SetSize( int x, int y, int ) { fStride = y; fSize = x * y; }
272   };
273
274   /**
275    * 3-dim arrays should use operator(int, int, int)
276    * operator[] can be used to return a 2-dim array
277    */
278   template<typename T>
279   class ArrayBase<T, 3> : public ArrayBoundsCheck
280   {
281     public:
282       ArrayBase() : fData( 0 ), fSize( 0 ), fStrideX( 0 ), fStrideY( 0 ) {} // XXX really shouldn't be done. But -Weffc++ wants it so
283       ArrayBase( const ArrayBase &rhs ) : ArrayBoundsCheck( rhs ), fData( rhs.fData ), fSize( rhs.fSize ), fStrideX( rhs.fStrideX ), fStrideY( rhs.fStrideY ) {} // XXX
284       ArrayBase &operator=( const ArrayBase &rhs ) { ArrayBoundsCheck::operator=( rhs ); fData = rhs.fData; fSize = rhs.fSize; fStrideX = rhs.fStrideX; fStrideY = rhs.fStrideY; return *this; } // XXX
285       typedef typename ReturnTypeHelper<T>::Type R;
286       /**
287        * return a reference to the value at the given indexes
288        */
289       inline R &operator()( int x, int y, int z );
290       /**
291        * return a const reference to the value at the given indexes
292        */
293       inline const R &operator()( int x, int y, int z ) const;
294       /**
295        * return a 2-dim array at the given index. This makes it behave like a 3-dim C-Array.
296        */
297       inline AliHLTArray<T, 2> operator[]( int x );
298       /**
299        * return a const 2-dim array at the given index. This makes it behave like a 3-dim C-Array.
300        */
301       inline const AliHLTArray<T, 2> operator[]( int x ) const;
302
303     protected:
304       T *fData;     // actual data
305       int fSize;    // data size
306       int fStrideX; //
307       int fStrideY; //
308       inline void SetSize( int x, int y, int z ) { fStrideX = y * z; fStrideY = z; fSize = fStrideX * x; }
309   };
310
311   template<typename T, unsigned int Size, int _alignment> class AlignedData
312   {
313     public:
314       T *ConstructAlignedData() {
315         const int offset = reinterpret_cast<unsigned long>( &fUnalignedArray[0] ) & ( Alignment - 1 );
316         void *mem = &fUnalignedArray[0] + ( Alignment - offset );
317         return new( mem ) T[Size];
318       }
319       ~AlignedData() {
320         const int offset = reinterpret_cast<unsigned long>( &fUnalignedArray[0] ) & ( Alignment - 1 );
321         T *mem = reinterpret_cast<T *>( &fUnalignedArray[0] + ( Alignment - offset ) );
322         for ( unsigned int i = 0; i < Size; ++i ) {
323           mem[i].~T();
324         }
325       }
326     private:
327       enum {
328         Alignment = _alignment == AliHLTFullyCacheLineAligned ? 128 : _alignment,
329         PaddedSize = Size * sizeof( T ) + Alignment
330       };
331       ALIHLTARRAY_STATIC_ASSERT_NC( ( Alignment & ( Alignment - 1 ) ) == 0, alignment_needs_to_be_a_multiple_of_2 );
332
333       char fUnalignedArray[PaddedSize]; //
334   };
335   template<typename T, unsigned int Size> class AlignedData<T, Size, 0>
336   {
337     public:
338       T *ConstructAlignedData() { return &fArray[0]; }
339     private:
340       T fArray[Size]; //
341   };
342 } // namespace AliHLTInternal
343
344 /**
345  * C-Array like class with the dimension dependent behavior defined in the ArrayBase class
346  */
347 template < typename T, int Dim = 1 >
348 class AliHLTArray : public AliHLTInternal::ArrayBase<T, Dim>
349 {
350   public:
351     typedef AliHLTInternal::ArrayBase<T, Dim> Parent;
352
353     /**
354      * Returns the number of elements in the array. If it is a multi-dimensional array the size is
355      * the multiplication of the dimensions ( e.g. a 10 x 20 array returns 200 as its size ).
356      */
357     inline int Size() const { return Parent::fSize; }
358
359     /**
360      * allows you to check for validity of the array by casting to bool
361      */
362     inline operator bool() const { return Parent::fData != 0; }
363     /**
364      * allows you to check for validity of the array
365      */
366     inline bool IsValid() const { return Parent::fData != 0; }
367
368     /**
369      * returns a reference to the data at index 0
370      */
371     inline T &operator*() { BOUNDS_CHECK( 0, Parent::fData[0] ); return *Parent::fData; }
372     /**
373      * returns a const reference to the data at index 0
374      */
375     inline const T &operator*() const { BOUNDS_CHECK( 0, Parent::fData[0] ); return *Parent::fData; }
376
377     /**
378      * returns a pointer to the data
379      * This circumvents bounds checking so it should not be used.
380      */
381     inline T *Data() { return Parent::fData; }
382     /**
383      * returns a const pointer to the data
384      * This circumvents bounds checking so it should not be used.
385      */
386     inline const T *Data() const { return Parent::fData; }
387
388     /**
389      * moves the array base pointer so that the data that was once at index 0 will then be at index -x
390      */
391     inline AliHLTArray operator+( int x ) const;
392     /**
393      * moves the array base pointer so that the data that was once at index 0 will then be at index x
394      */
395     inline AliHLTArray operator-( int x ) const;
396
397 #ifndef HLTCA_GPUCODE
398     template<typename Other> inline AliHLTArray<Other, Dim> ReinterpretCast() const {
399       AliHLTArray<Other, Dim> r;
400       r.fData = reinterpret_cast<Other *>( Parent::fData );
401       r.ReinterpretCast( *this, sizeof( T ), sizeof( Other ) );
402     }
403 #endif
404 };
405
406 /**
407  * Owns the data. When it goes out of scope the data is freed.
408  *
409  * The memory is allocated on the heap.
410  *
411  * Instantiate this class on the stack. Allocation on the heap is disallowed.
412  *
413  * \param T type of the entries in the array.
414  * \param Dim selects the operator[]/operator() behavior it should have. I.e. makes it behave like a
415  * 1-, 2- or 3-dim array. (defaults to 1)
416  * \param alignment Defaults to 0 (default alignment). Other valid values are any multiples of 2.
417  *                  This is especially useful for aligning data for SIMD vectors.
418  *
419  * \warning when using alignment the type T may not have a destructor (well it may, but it won't be
420  * called)
421  *
422  * Example:
423  * \code
424  * void init( AliHLTArray<int> a, int size )
425  * {
426  *   for ( int i = 0; i < size; ++i ) {
427  *     a[i] = i;
428  *   }
429  * }
430  *
431  * int size = ...;
432  * AliHLTResizableArray<int> foo( size ); // notice that size doesn't have to be a constant like it
433  *                                        // has to be for C-Arrays in ISO C++
434  * init( foo, size );
435  * // now foo[i] == i
436  *
437  * \endcode
438  */
439 template < typename T, int Dim = 1, int alignment = 0 >
440 class AliHLTResizableArray : public AliHLTArray<typename AliHLTInternal::TypeForAlignmentHelper<T, alignment>::Type, Dim>
441 {
442   public:
443     typedef typename AliHLTInternal::TypeForAlignmentHelper<T, alignment>::Type T2;
444     typedef AliHLTInternal::ArrayBase<T2, Dim> Parent;
445     /**
446      * does not allocate any memory
447      */
448     inline AliHLTResizableArray();
449     /**
450      * use for 1-dim arrays: allocates x * sizeof(T) bytes for the array
451      */
452     inline AliHLTResizableArray( int x );
453     /**
454      * use for 2-dim arrays: allocates x * y * sizeof(T) bytes for the array
455      */
456     inline AliHLTResizableArray( int x, int y );
457     /**
458      * use for 3-dim arrays: allocates x * y * z * sizeof(T) bytes for the array
459      */
460     inline AliHLTResizableArray( int x, int y, int z );
461
462     /**
463      * frees the data
464      */
465     inline ~AliHLTResizableArray() { AliHLTInternal::Allocator<T, alignment>::Free( Parent::fData, Parent::fSize ); }
466
467     /**
468      * use for 1-dim arrays: resizes the memory for the array to x * sizeof(T) bytes.
469      *
470      * \warning this does not keep your previous data. If you were looking for this you probably
471      * want to use std::vector instead.
472      */
473     inline void Resize( int x );
474     /**
475      * use for 2-dim arrays: resizes the memory for the array to x * y * sizeof(T) bytes.
476      *
477      * \warning this does not keep your previous data. If you were looking for this you probably
478      * want to use std::vector instead.
479      */
480     inline void Resize( int x, int y );
481     /**
482      * use for 3-dim arrays: resizes the memory for the array to x * y * z * sizeof(T) bytes.
483      *
484      * \warning this does not keep your previous data. If you were looking for this you probably
485      * want to use std::vector instead.
486      */
487     inline void Resize( int x, int y, int z );
488
489   private:
490     // disable allocation on the heap
491     void *operator new( size_t );
492
493     // disable copy
494     AliHLTResizableArray( const AliHLTResizableArray & );
495     AliHLTResizableArray &operator=( const AliHLTResizableArray & );
496 };
497
498 template < unsigned int x, unsigned int y = 0, unsigned int z = 0 > class AliHLTArraySize
499 {
500   public:
501     enum {
502       Size = y == 0 ? x : ( z == 0 ? x * y : x * y * z ),
503       Dim = y == 0 ? 1 : ( z == 0 ? 2 : 3 ),
504       X = x, Y = y, Z = z
505     };
506 };
507
508 /**
509  * Owns the data. When it goes out of scope the data is freed.
510  *
511  * The memory is allocated on the stack.
512  *
513  * Instantiate this class on the stack.
514  *
515  * \param T type of the entries in the array.
516  * \param Size number of entries in the array.
517  * \param Dim selects the operator[]/operator() behavior it should have. I.e. makes it behave like a
518  * 1-, 2- or 3-dim array. (defaults to 1)
519  */
520 template < typename T, typename Size, int alignment = 0 >
521 class AliHLTFixedArray : public AliHLTArray<typename AliHLTInternal::TypeForAlignmentHelper<T, alignment>::Type, Size::Dim>
522 {
523   public:
524     typedef typename AliHLTInternal::TypeForAlignmentHelper<T, alignment>::Type T2;
525     typedef AliHLTInternal::ArrayBase<T2, Size::Dim> Parent;
526     inline AliHLTFixedArray() {
527       Parent::fData = fFixedArray.ConstructAlignedData();
528       Parent::SetBounds( 0, Size::Size - 1 );
529       SetSize( Size::X, Size::Y, Size::Z );
530     }
531
532   private:
533     AliHLTInternal::AlignedData<typename AliHLTInternal::TypeForAlignmentHelper<T, alignment>::Type, Size::Size, alignment> fFixedArray; //
534
535     // disable allocation on the heap
536     void *operator new( size_t );
537
538     // disable copy
539 #ifdef HLTCA_GPUCODE
540 #else
541     AliHLTFixedArray( const AliHLTFixedArray & );
542     AliHLTFixedArray &operator=( const AliHLTFixedArray & );
543 #endif
544 };
545
546
547
548
549 ////////////////////////
550 //// implementation ////
551 ////////////////////////
552
553
554
555
556 namespace AliHLTInternal
557 {
558 #ifdef ENABLE_ARRAY_BOUNDS_CHECKING
559   inline bool ArrayBoundsCheck::IsInBounds( int x ) const
560   {
561     assert( x >= fStart );
562     assert( x <= fEnd );
563     return ( x >= fStart && x <= fEnd );
564   }
565 #endif
566
567   template<typename T>
568   inline AliHLTArray<T, 1> ArrayBase<T, 2>::operator[]( int x )
569   {
570     x *= fStride;
571     typedef AliHLTArray<T, 1> AT1;
572     BOUNDS_CHECK( x, AT1() );
573     AliHLTArray<T, 1> a;
574     a.fData = &fData[x];
575     a.ArrayBoundsCheck::operator=( *this );
576     a.MoveBounds( -x );
577     return a;
578   }
579
580   template<typename T>
581   inline const AliHLTArray<T, 1> ArrayBase<T, 2>::operator[]( int x ) const
582   {
583     x *= fStride;
584     typedef AliHLTArray<T, 1> AT1;
585     BOUNDS_CHECK( x, AT1() );
586     AliHLTArray<T, 1> a;
587     a.fData = &fData[x];
588     a.ArrayBoundsCheck::operator=( *this );
589     a.MoveBounds( -x );
590     return a;
591   }
592
593   template<typename T>
594   inline typename AliHLTInternal::ReturnTypeHelper<T>::Type &ArrayBase<T, 3>::operator()( int x, int y, int z )
595   {
596     BOUNDS_CHECK( x * fStrideX + y + fStrideY + z, fData[0] );
597     return fData[x * fStrideX + y + fStrideY + z];
598   }
599   template<typename T>
600   inline const typename AliHLTInternal::ReturnTypeHelper<T>::Type &ArrayBase<T, 3>::operator()( int x, int y, int z ) const
601   {
602     BOUNDS_CHECK( x * fStrideX + y + fStrideY + z, fData[0] );
603     return fData[x * fStrideX + y + fStrideY + z];
604   }
605   template<typename T>
606   inline AliHLTArray<T, 2> ArrayBase<T, 3>::operator[]( int x )
607   {
608     x *= fStrideX;
609     typedef AliHLTArray<T, 2> AT2;
610     BOUNDS_CHECK( x, AT2() );
611     AliHLTArray<T, 2> a;
612     a.fData = &fData[x];
613     a.fStride = fStrideY;
614     a.ArrayBoundsCheck::operator=( *this );
615     a.MoveBounds( -x );
616     return a;
617   }
618   template<typename T>
619   inline const AliHLTArray<T, 2> ArrayBase<T, 3>::operator[]( int x ) const
620   {
621     x *= fStrideX;
622     typedef AliHLTArray<T, 2> AT2;
623     BOUNDS_CHECK( x, AT2() );
624     AliHLTArray<T, 2> a;
625     a.fData = &fData[x];
626     a.fStride = fStrideY;
627     a.ArrayBoundsCheck::operator=( *this );
628     a.MoveBounds( -x );
629     return a;
630   }
631 } // namespace AliHLTInternal
632
633
634 template<typename T, int Dim>
635 inline AliHLTArray<T, Dim> AliHLTArray<T, Dim>::operator+( int x ) const
636 {
637   AliHLTArray<T, Dim> r( *this );
638   r.fData += x;
639   r.MoveBounds( -x );
640   return r;
641 }
642 template<typename T, int Dim>
643 inline AliHLTArray<T, Dim> AliHLTArray<T, Dim>::operator-( int x ) const
644 {
645   AliHLTArray<T, Dim> r( *this );
646   r.fData -= x;
647   r.MoveBounds( x );
648   return r;
649 }
650
651 template<typename T, int Dim, int alignment>
652 inline AliHLTResizableArray<T, Dim, alignment>::AliHLTResizableArray()
653 {
654   Parent::fData = 0;
655   Parent::SetSize( 0, 0, 0 );
656   Parent::SetBounds( 0, -1 );
657 }
658 template<typename T, int Dim, int alignment>
659 inline AliHLTResizableArray<T, Dim, alignment>::AliHLTResizableArray( int x )
660 {
661   ALIHLTARRAY_STATIC_ASSERT( Dim == 1, AliHLTResizableArray1_used_with_incorrect_dimension );
662   Parent::fData = AliHLTInternal::Allocator<T, alignment>::Alloc( x );
663   Parent::SetSize( x, 0, 0 );
664   Parent::SetBounds( 0, x - 1 );
665 }
666 template<typename T, int Dim, int alignment>
667 inline AliHLTResizableArray<T, Dim, alignment>::AliHLTResizableArray( int x, int y )
668 {
669   ALIHLTARRAY_STATIC_ASSERT( Dim == 2, AliHLTResizableArray2_used_with_incorrect_dimension );
670   Parent::fData = AliHLTInternal::Allocator<T, alignment>::Alloc( x * y );
671   Parent::SetSize( x, y, 0 );
672   Parent::SetBounds( 0, x * y - 1 );
673 }
674 template<typename T, int Dim, int alignment>
675 inline AliHLTResizableArray<T, Dim, alignment>::AliHLTResizableArray( int x, int y, int z )
676 {
677   ALIHLTARRAY_STATIC_ASSERT( Dim == 3, AliHLTResizableArray3_used_with_incorrect_dimension );
678   Parent::fData = AliHLTInternal::Allocator<T, alignment>::Alloc( x * y * z );
679   Parent::SetSize( x, y, z );
680   Parent::SetBounds( 0, x * y * z - 1 );
681 }
682 template<typename T, int Dim, int alignment>
683 inline void AliHLTResizableArray<T, Dim, alignment>::Resize( int x )
684 {
685   ALIHLTARRAY_STATIC_ASSERT( Dim == 1, AliHLTResizableArray1_resize_used_with_incorrect_dimension );
686   AliHLTInternal::Allocator<T, alignment>::Free( Parent::fData, Parent::fSize );
687   Parent::fData = ( x == 0 ) ? 0 : AliHLTInternal::Allocator<T, alignment>::Alloc( x );
688   Parent::SetSize( x, 0, 0 );
689   Parent::SetBounds( 0, x - 1 );
690 }
691 template<typename T, int Dim, int alignment>
692 inline void AliHLTResizableArray<T, Dim, alignment>::Resize( int x, int y )
693 {
694   ALIHLTARRAY_STATIC_ASSERT( Dim == 2, AliHLTResizableArray2_resize_used_with_incorrect_dimension );
695   AliHLTInternal::Allocator<T, alignment>::Free( Parent::fData, Parent::fSize );
696   Parent::fData = ( x == 0 ) ? 0 : AliHLTInternal::Allocator<T, alignment>::Alloc( x * y );
697   Parent::SetSize( x, y, 0 );
698   Parent::SetBounds( 0, x * y - 1 );
699 }
700 template<typename T, int Dim, int alignment>
701 inline void AliHLTResizableArray<T, Dim, alignment>::Resize( int x, int y, int z )
702 {
703   ALIHLTARRAY_STATIC_ASSERT( Dim == 3, AliHLTResizableArray3_resize_used_with_incorrect_dimension );
704   AliHLTInternal::Allocator<T, alignment>::Free( Parent::fData, Parent::fSize );
705   Parent::fData = ( x == 0 ) ? 0 : AliHLTInternal::Allocator<T, alignment>::Alloc( x * y * z );
706   Parent::SetSize( x, y, z );
707   Parent::SetBounds( 0, x * y * z - 1 );
708 }
709
710 #undef BOUNDS_CHECK
711
712 #endif // ALIHLTARRAY_H