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