]> git.uio.no Git - u/mrichter/AliRoot.git/blob - HLT/BASE/AliHLTArray.h
Cosmetics. Fixed bug preventing creation of async block list
[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       // Stopped working on GCC 4.5.0
286       //typedef typename ReturnTypeHelper<T>::Type R;
287       /**
288        * return a reference to the value at the given indexes
289        */
290       inline typename ReturnTypeHelper<T>::Type &operator()( int x, int y, int z );
291       /**
292        * return a const reference to the value at the given indexes
293        */
294       inline const typename ReturnTypeHelper<T>::Type &operator()( int x, int y, int z ) const;
295       /**
296        * return a 2-dim array at the given index. This makes it behave like a 3-dim C-Array.
297        */
298       inline AliHLTArray<T, 2> operator[]( int x );
299       /**
300        * return a const 2-dim array at the given index. This makes it behave like a 3-dim C-Array.
301        */
302       inline const AliHLTArray<T, 2> operator[]( int x ) const;
303
304     protected:
305       T *fData;     // actual data
306       int fSize;    // data size
307       int fStrideX; //
308       int fStrideY; //
309       inline void SetSize( int x, int y, int z ) { fStrideX = y * z; fStrideY = z; fSize = fStrideX * x; }
310   };
311
312   template<typename T, unsigned int Size, int _alignment> class AlignedData
313   {
314     public:
315       T *ConstructAlignedData() {
316         const int offset = reinterpret_cast<unsigned long>( &fUnalignedArray[0] ) & ( Alignment - 1 );
317         void *mem = &fUnalignedArray[0] + ( Alignment - offset );
318         return new( mem ) T[Size];
319       }
320       ~AlignedData() {
321         const int offset = reinterpret_cast<unsigned long>( &fUnalignedArray[0] ) & ( Alignment - 1 );
322         T *mem = reinterpret_cast<T *>( &fUnalignedArray[0] + ( Alignment - offset ) );
323         for ( unsigned int i = 0; i < Size; ++i ) {
324           mem[i].~T();
325         }
326       }
327     private:
328       enum {
329         Alignment = _alignment == AliHLTFullyCacheLineAligned ? 128 : _alignment,
330         PaddedSize = Size * sizeof( T ) + Alignment
331       };
332       ALIHLTARRAY_STATIC_ASSERT_NC( ( Alignment & ( Alignment - 1 ) ) == 0, alignment_needs_to_be_a_multiple_of_2 );
333
334       char fUnalignedArray[PaddedSize]; //
335   };
336   template<typename T, unsigned int Size> class AlignedData<T, Size, 0>
337   {
338     public:
339       T *ConstructAlignedData() { return &fArray[0]; }
340     private:
341       T fArray[Size]; //
342   };
343 } // namespace AliHLTInternal
344
345 /**
346  * C-Array like class with the dimension dependent behavior defined in the ArrayBase class
347  */
348 template < typename T, int Dim = 1 >
349 class AliHLTArray : public AliHLTInternal::ArrayBase<T, Dim>
350 {
351   public:
352     typedef AliHLTInternal::ArrayBase<T, Dim> Parent;
353
354     /**
355      * Returns the number of elements in the array. If it is a multi-dimensional array the size is
356      * the multiplication of the dimensions ( e.g. a 10 x 20 array returns 200 as its size ).
357      */
358     inline int Size() const { return Parent::fSize; }
359
360     /**
361      * allows you to check for validity of the array by casting to bool
362      */
363     inline operator bool() const { return Parent::fData != 0; }
364     /**
365      * allows you to check for validity of the array
366      */
367     inline bool IsValid() const { return Parent::fData != 0; }
368
369     /**
370      * returns a reference to the data at index 0
371      */
372     inline T &operator*() { BOUNDS_CHECK( 0, Parent::fData[0] ); return *Parent::fData; }
373     /**
374      * returns a const reference to the data at index 0
375      */
376     inline const T &operator*() const { BOUNDS_CHECK( 0, Parent::fData[0] ); return *Parent::fData; }
377
378     /**
379      * returns a pointer to the data
380      * This circumvents bounds checking so it should not be used.
381      */
382     inline T *Data() { return Parent::fData; }
383     /**
384      * returns a const pointer to the data
385      * This circumvents bounds checking so it should not be used.
386      */
387     inline const T *Data() const { return Parent::fData; }
388
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      * moves the array base pointer so that the data that was once at index 0 will then be at index x
395      */
396     inline AliHLTArray operator-( int x ) const;
397
398 #ifndef HLTCA_GPUCODE
399     template<typename Other> inline AliHLTArray<Other, Dim> ReinterpretCast() const {
400       AliHLTArray<Other, Dim> r;
401       r.fData = reinterpret_cast<Other *>( Parent::fData );
402       r.ReinterpretCast( *this, sizeof( T ), sizeof( Other ) );
403     }
404 #endif
405 };
406
407 /**
408  * Owns the data. When it goes out of scope the data is freed.
409  *
410  * The memory is allocated on the heap.
411  *
412  * Instantiate this class on the stack. Allocation on the heap is disallowed.
413  *
414  * \param T type of the entries in the array.
415  * \param Dim selects the operator[]/operator() behavior it should have. I.e. makes it behave like a
416  * 1-, 2- or 3-dim array. (defaults to 1)
417  * \param alignment Defaults to 0 (default alignment). Other valid values are any multiples of 2.
418  *                  This is especially useful for aligning data for SIMD vectors.
419  *
420  * \warning when using alignment the type T may not have a destructor (well it may, but it won't be
421  * called)
422  *
423  * Example:
424  * \code
425  * void init( AliHLTArray<int> a, int size )
426  * {
427  *   for ( int i = 0; i < size; ++i ) {
428  *     a[i] = i;
429  *   }
430  * }
431  *
432  * int size = ...;
433  * AliHLTResizableArray<int> foo( size ); // notice that size doesn't have to be a constant like it
434  *                                        // has to be for C-Arrays in ISO C++
435  * init( foo, size );
436  * // now foo[i] == i
437  *
438  * \endcode
439  */
440 template < typename T, int Dim = 1, int alignment = 0 >
441 class AliHLTResizableArray : public AliHLTArray<typename AliHLTInternal::TypeForAlignmentHelper<T, alignment>::Type, Dim>
442 {
443   public:
444     typedef typename AliHLTInternal::TypeForAlignmentHelper<T, alignment>::Type T2;
445     typedef AliHLTInternal::ArrayBase<T2, Dim> Parent;
446     /**
447      * does not allocate any memory
448      */
449     inline AliHLTResizableArray();
450     /**
451      * use for 1-dim arrays: allocates x * sizeof(T) bytes for the array
452      */
453     inline AliHLTResizableArray( int x );
454     /**
455      * use for 2-dim arrays: allocates x * y * sizeof(T) bytes for the array
456      */
457     inline AliHLTResizableArray( int x, int y );
458     /**
459      * use for 3-dim arrays: allocates x * y * z * sizeof(T) bytes for the array
460      */
461     inline AliHLTResizableArray( int x, int y, int z );
462
463     /**
464      * frees the data
465      */
466     inline ~AliHLTResizableArray() { AliHLTInternal::Allocator<T, alignment>::Free( Parent::fData, Parent::fSize ); }
467
468     /**
469      * use for 1-dim arrays: resizes the memory for the array to x * sizeof(T) bytes.
470      *
471      * \warning this does not keep your previous data. If you were looking for this you probably
472      * want to use std::vector instead.
473      */
474     inline void Resize( int x );
475     /**
476      * use for 2-dim arrays: resizes the memory for the array to x * y * sizeof(T) bytes.
477      *
478      * \warning this does not keep your previous data. If you were looking for this you probably
479      * want to use std::vector instead.
480      */
481     inline void Resize( int x, int y );
482     /**
483      * use for 3-dim arrays: resizes the memory for the array to x * y * z * sizeof(T) bytes.
484      *
485      * \warning this does not keep your previous data. If you were looking for this you probably
486      * want to use std::vector instead.
487      */
488     inline void Resize( int x, int y, int z );
489
490   private:
491     // disable allocation on the heap
492     void *operator new( size_t );
493
494     // disable copy
495     AliHLTResizableArray( const AliHLTResizableArray & );
496     AliHLTResizableArray &operator=( const AliHLTResizableArray & );
497 };
498
499 template < unsigned int x, unsigned int y = 0, unsigned int z = 0 > class AliHLTArraySize
500 {
501   public:
502     enum {
503       Size = y == 0 ? x : ( z == 0 ? x * y : x * y * z ),
504       Dim = y == 0 ? 1 : ( z == 0 ? 2 : 3 ),
505       X = x, Y = y, Z = z
506     };
507 };
508
509 /**
510  * Owns the data. When it goes out of scope the data is freed.
511  *
512  * The memory is allocated on the stack.
513  *
514  * Instantiate this class on the stack.
515  *
516  * \param T type of the entries in the array.
517  * \param Size number of entries in the array.
518  * \param Dim selects the operator[]/operator() behavior it should have. I.e. makes it behave like a
519  * 1-, 2- or 3-dim array. (defaults to 1)
520  */
521 template < typename T, typename Size, int alignment = 0 >
522 class AliHLTFixedArray : public AliHLTArray<typename AliHLTInternal::TypeForAlignmentHelper<T, alignment>::Type, Size::Dim>
523 {
524   public:
525     typedef typename AliHLTInternal::TypeForAlignmentHelper<T, alignment>::Type T2;
526     typedef AliHLTInternal::ArrayBase<T2, Size::Dim> Parent;
527     inline AliHLTFixedArray() {
528       Parent::fData = fFixedArray.ConstructAlignedData();
529       Parent::SetBounds( 0, Size::Size - 1 );
530       SetSize( Size::X, Size::Y, Size::Z );
531     }
532
533   private:
534     AliHLTInternal::AlignedData<typename AliHLTInternal::TypeForAlignmentHelper<T, alignment>::Type, Size::Size, alignment> fFixedArray; //
535
536     // disable allocation on the heap
537     void *operator new( size_t );
538
539     // disable copy
540 #ifdef HLTCA_GPUCODE
541 #else
542     AliHLTFixedArray( const AliHLTFixedArray & );
543     AliHLTFixedArray &operator=( const AliHLTFixedArray & );
544 #endif
545 };
546
547
548
549
550 ////////////////////////
551 //// implementation ////
552 ////////////////////////
553
554
555
556
557 namespace AliHLTInternal
558 {
559 #ifdef ENABLE_ARRAY_BOUNDS_CHECKING
560   inline bool ArrayBoundsCheck::IsInBounds( int x ) const
561   {
562     assert( x >= fStart );
563     assert( x <= fEnd );
564     return ( x >= fStart && x <= fEnd );
565   }
566 #endif
567
568   template<typename T>
569   inline AliHLTArray<T, 1> ArrayBase<T, 2>::operator[]( int x )
570   {
571     x *= fStride;
572     typedef AliHLTArray<T, 1> AT1;
573     BOUNDS_CHECK( x, AT1() );
574     AliHLTArray<T, 1> a;
575     a.fData = &fData[x];
576     a.ArrayBoundsCheck::operator=( *this );
577     a.MoveBounds( -x );
578     return a;
579   }
580
581   template<typename T>
582   inline const AliHLTArray<T, 1> ArrayBase<T, 2>::operator[]( int x ) const
583   {
584     x *= fStride;
585     typedef AliHLTArray<T, 1> AT1;
586     BOUNDS_CHECK( x, AT1() );
587     AliHLTArray<T, 1> a;
588     a.fData = &fData[x];
589     a.ArrayBoundsCheck::operator=( *this );
590     a.MoveBounds( -x );
591     return a;
592   }
593
594   template<typename T>
595   inline typename AliHLTInternal::ReturnTypeHelper<T>::Type &ArrayBase<T, 3>::operator()( int x, int y, int z )
596   {
597     BOUNDS_CHECK( x * fStrideX + y + fStrideY + z, fData[0] );
598     return fData[x * fStrideX + y + fStrideY + z];
599   }
600   template<typename T>
601   inline const typename AliHLTInternal::ReturnTypeHelper<T>::Type &ArrayBase<T, 3>::operator()( int x, int y, int z ) const
602   {
603     BOUNDS_CHECK( x * fStrideX + y + fStrideY + z, fData[0] );
604     return fData[x * fStrideX + y + fStrideY + z];
605   }
606   template<typename T>
607   inline AliHLTArray<T, 2> ArrayBase<T, 3>::operator[]( int x )
608   {
609     x *= fStrideX;
610     typedef AliHLTArray<T, 2> AT2;
611     BOUNDS_CHECK( x, AT2() );
612     AliHLTArray<T, 2> a;
613     a.fData = &fData[x];
614     a.fStride = fStrideY;
615     a.ArrayBoundsCheck::operator=( *this );
616     a.MoveBounds( -x );
617     return a;
618   }
619   template<typename T>
620   inline const AliHLTArray<T, 2> ArrayBase<T, 3>::operator[]( int x ) const
621   {
622     x *= fStrideX;
623     typedef AliHLTArray<T, 2> AT2;
624     BOUNDS_CHECK( x, AT2() );
625     AliHLTArray<T, 2> a;
626     a.fData = &fData[x];
627     a.fStride = fStrideY;
628     a.ArrayBoundsCheck::operator=( *this );
629     a.MoveBounds( -x );
630     return a;
631   }
632 } // namespace AliHLTInternal
633
634
635 template<typename T, int Dim>
636 inline AliHLTArray<T, Dim> AliHLTArray<T, Dim>::operator+( int x ) const
637 {
638   AliHLTArray<T, Dim> r( *this );
639   r.fData += x;
640   r.MoveBounds( -x );
641   return r;
642 }
643 template<typename T, int Dim>
644 inline AliHLTArray<T, Dim> AliHLTArray<T, Dim>::operator-( int x ) const
645 {
646   AliHLTArray<T, Dim> r( *this );
647   r.fData -= x;
648   r.MoveBounds( x );
649   return r;
650 }
651
652 template<typename T, int Dim, int alignment>
653 inline AliHLTResizableArray<T, Dim, alignment>::AliHLTResizableArray()
654 {
655   Parent::fData = 0;
656   Parent::SetSize( 0, 0, 0 );
657   Parent::SetBounds( 0, -1 );
658 }
659 template<typename T, int Dim, int alignment>
660 inline AliHLTResizableArray<T, Dim, alignment>::AliHLTResizableArray( int x )
661 {
662   ALIHLTARRAY_STATIC_ASSERT( Dim == 1, AliHLTResizableArray1_used_with_incorrect_dimension );
663   Parent::fData = AliHLTInternal::Allocator<T, alignment>::Alloc( x );
664   Parent::SetSize( x, 0, 0 );
665   Parent::SetBounds( 0, x - 1 );
666 }
667 template<typename T, int Dim, int alignment>
668 inline AliHLTResizableArray<T, Dim, alignment>::AliHLTResizableArray( int x, int y )
669 {
670   ALIHLTARRAY_STATIC_ASSERT( Dim == 2, AliHLTResizableArray2_used_with_incorrect_dimension );
671   Parent::fData = AliHLTInternal::Allocator<T, alignment>::Alloc( x * y );
672   Parent::SetSize( x, y, 0 );
673   Parent::SetBounds( 0, x * y - 1 );
674 }
675 template<typename T, int Dim, int alignment>
676 inline AliHLTResizableArray<T, Dim, alignment>::AliHLTResizableArray( int x, int y, int z )
677 {
678   ALIHLTARRAY_STATIC_ASSERT( Dim == 3, AliHLTResizableArray3_used_with_incorrect_dimension );
679   Parent::fData = AliHLTInternal::Allocator<T, alignment>::Alloc( x * y * z );
680   Parent::SetSize( x, y, z );
681   Parent::SetBounds( 0, x * y * z - 1 );
682 }
683 template<typename T, int Dim, int alignment>
684 inline void AliHLTResizableArray<T, Dim, alignment>::Resize( int x )
685 {
686   ALIHLTARRAY_STATIC_ASSERT( Dim == 1, AliHLTResizableArray1_resize_used_with_incorrect_dimension );
687   AliHLTInternal::Allocator<T, alignment>::Free( Parent::fData, Parent::fSize );
688   Parent::fData = ( x == 0 ) ? 0 : AliHLTInternal::Allocator<T, alignment>::Alloc( x );
689   Parent::SetSize( x, 0, 0 );
690   Parent::SetBounds( 0, x - 1 );
691 }
692 template<typename T, int Dim, int alignment>
693 inline void AliHLTResizableArray<T, Dim, alignment>::Resize( int x, int y )
694 {
695   ALIHLTARRAY_STATIC_ASSERT( Dim == 2, AliHLTResizableArray2_resize_used_with_incorrect_dimension );
696   AliHLTInternal::Allocator<T, alignment>::Free( Parent::fData, Parent::fSize );
697   Parent::fData = ( x == 0 ) ? 0 : AliHLTInternal::Allocator<T, alignment>::Alloc( x * y );
698   Parent::SetSize( x, y, 0 );
699   Parent::SetBounds( 0, x * y - 1 );
700 }
701 template<typename T, int Dim, int alignment>
702 inline void AliHLTResizableArray<T, Dim, alignment>::Resize( int x, int y, int z )
703 {
704   ALIHLTARRAY_STATIC_ASSERT( Dim == 3, AliHLTResizableArray3_resize_used_with_incorrect_dimension );
705   AliHLTInternal::Allocator<T, alignment>::Free( Parent::fData, Parent::fSize );
706   Parent::fData = ( x == 0 ) ? 0 : AliHLTInternal::Allocator<T, alignment>::Alloc( x * y * z );
707   Parent::SetSize( x, y, z );
708   Parent::SetBounds( 0, x * y * z - 1 );
709 }
710
711 #undef BOUNDS_CHECK
712
713 #endif // ALIHLTARRAY_H