ALIROOT-5600 - skip non-participating detector modules
[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   kAliHLTFullyCacheLineAligned = -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 AliHLTStaticAssertFailure;
64   template<> class AliHLTStaticAssertFailure<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::AliHLTStaticAssertFailure<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 AliHLTCacheLineSizeHelperData { T fData; };
82   template<typename T> struct AliHLTCacheLineSizeHelperEnums {
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 AliCacheLineSizeHelper : private AliHLTCacheLineSizeHelperData<T>, private Padding<AliHLTCacheLineSizeHelperEnums<T>::PaddingSize>
91   {
92     public:
93       operator T &() { return AliHLTCacheLineSizeHelperData<T>::fData; }
94       operator const T &() const { return AliHLTCacheLineSizeHelperData<T>::fData; }
95       //const T &operator=( const T &rhs ) { AliHLTCacheLineSizeHelperData<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, kAliHLTFullyCacheLineAligned> { typedef AliCacheLineSizeHelper<T> Type; };
101
102   // XXX
103   // The AliArrayBoundsCheck and AliAllocator 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 AliArrayBoundsCheck
112   {
113     protected:
114       virtual inline ~AliArrayBoundsCheck() {}
115       inline bool IsInBounds( int ) const { return true; }
116       inline void SetBounds( int, int ) const {}
117       inline void MoveBounds( int ) const {}
118       inline void ReinterpretCast( const AliArrayBoundsCheck &, int, int ) const {}
119   };
120 #define BOUNDS_CHECK(x, y)
121 #else
122   /**
123    * implementation for bounds-checking.
124    */
125   class AliArrayBoundsCheck
126   {
127     protected:
128       virtual inline ~AliArrayBoundsCheck() {}
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 AliArrayBoundsCheck &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::AliArrayBoundsCheck::IsInBounds(x)) {} else return y
152 #endif
153   template<typename T, int alignment> class AliAllocator
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 ) p[i].~T();        
160         _mm_free( p );
161       }
162 #else
163       static inline T *Alloc( int s ) { T *p; posix_memalign( &p, alignment, s * sizeof( T ) ); return new( p ) T[s]; }
164       static inline void Free( T *const p, int size ) {
165         for ( int i = 0; i < size; ++i ) p[i].~T();        
166         std::free( p );
167       }
168 #endif
169   };
170   template<typename T> class AliAllocator<T, kAliHLTFullyCacheLineAligned>
171   {
172     public:
173       typedef AliCacheLineSizeHelper<T> T2;
174 #ifdef USE_MM_MALLOC
175       static inline T2 *Alloc( int s ) { T2 *p = reinterpret_cast<T2 *>( _mm_malloc( s * sizeof( T2 ), 128 ) ); return new( p ) T2[s]; }
176       static inline void Free( T2 *const p, int size ) {
177         for ( int i = 0; i < size; ++i ) p[i].~T2();        
178         _mm_free( p );
179       }
180 #else
181       static inline T2 *Alloc( int s ) { T2 *p; posix_memalign( &p, 128, s * sizeof( T2 ) ); return new( p ) T2[s]; }
182       static inline void Free( T2 *const p, int size ) {
183         for ( int i = 0; i < size; ++i ) p[i].~T2();
184         std::free( p );
185       }
186 #endif
187   };
188   template<typename T> class AliAllocator<T, 0>
189   {
190     public:
191       static inline T *Alloc( int s ) { return new T[s]; }
192       static inline void Free( const T *const p, int ) { delete[] p; }
193   };
194
195   template<typename T> struct ReturnTypeHelper { typedef T Type; };
196   template<typename T> struct ReturnTypeHelper<AliCacheLineSizeHelper<T> > { typedef T Type; };
197   /**
198    * Array base class for dimension dependent behavior
199    */
200   template<typename T, int Dim> class AliHLTArrayBase;
201
202   /**
203    * 1-dim arrays only have operator[]
204    */
205   template<typename T>
206   class AliHLTArrayBase<T, 1> : public AliArrayBoundsCheck
207   {
208     friend class AliHLTArrayBase<T, 2>; // declare friend 
209     public:
210       AliHLTArrayBase() : fData( 0 ), fSize( 0 ) {} // XXX really shouldn't be done. But -Weffc++ wants it so
211       AliHLTArrayBase( const AliHLTArrayBase &rhs ) : AliArrayBoundsCheck( rhs ), fData( rhs.fData ), fSize( rhs.fSize ) {} // XXX
212       AliHLTArrayBase &operator=( const AliHLTArrayBase &rhs ) { AliArrayBoundsCheck::operator=( rhs ); fData = rhs.fData; return *this; } // XXX
213       typedef typename ReturnTypeHelper<T>::Type R;
214       /**
215        * return a reference to the value at the given index
216        */
217       inline R &operator[]( int x ) { BOUNDS_CHECK( x, fData[0] ); return fData[x]; }
218       /**
219        * return a const reference to the value at the given index
220        */
221       inline const R &operator[]( int x ) const { BOUNDS_CHECK( x, fData[0] ); return fData[x]; }
222
223     protected:
224       T *fData;  // actual data
225       int fSize; // data size
226       inline void SetSize( int x, int, int ) { fSize = x; }
227   };
228
229   /**
230    * 2-dim arrays should use operator(int, int)
231    * operator[] can be used to return a 1-dim array
232    */
233   template<typename T>
234   class AliHLTArrayBase<T, 2> : public AliArrayBoundsCheck
235   {
236     friend class AliHLTArrayBase<T, 3>; // declare friend
237     public:
238       AliHLTArrayBase() : fData( 0 ), fSize( 0 ), fStride( 0 ) {} // XXX really shouldn't be done. But -Weffc++ wants it so
239       AliHLTArrayBase( const AliHLTArrayBase &rhs ) : AliArrayBoundsCheck( rhs ), fData( rhs.fData ), fSize( rhs.fSize ), fStride( rhs.fStride ) {} // XXX
240       AliHLTArrayBase &operator=( const AliHLTArrayBase &rhs ) { AliArrayBoundsCheck::operator=( rhs ); fData = rhs.fData; fSize = rhs.fSize; fStride = rhs.fStride; return *this; } // XXX
241       typedef typename ReturnTypeHelper<T>::Type R;
242       /**
243        * return a reference to the value at the given indexes
244        */
245       inline R &operator()( int x, int y ) { BOUNDS_CHECK( x * fStride + y, fData[0] ); return fData[x * fStride + y]; }
246       /**
247        * return a const reference to the value at the given indexes
248        */
249       inline const R &operator()( int x, int y ) const { BOUNDS_CHECK( x * fStride + y, fData[0] ); return fData[x * fStride + y]; }
250       /**
251        * return a 1-dim array at the given index. This makes it behave like a 2-dim C-Array.
252        */
253       inline AliHLTArray<T, 1> operator[]( int x );
254       /**
255        * return a const 1-dim array at the given index. This makes it behave like a 2-dim C-Array.
256        */
257       inline const AliHLTArray<T, 1> operator[]( int x ) const;
258
259     protected:
260       T *fData;    // actual data
261       int fSize;   // data size
262       int fStride; // stride
263       inline void SetSize( int x, int y, int ) { fStride = y; fSize = x * y; }
264   };
265
266   /**
267    * 3-dim arrays should use operator(int, int, int)
268    * operator[] can be used to return a 2-dim array
269    */
270   template<typename T>
271   class AliHLTArrayBase<T, 3> : public AliArrayBoundsCheck
272   {
273     public:
274       AliHLTArrayBase() : fData( 0 ), fSize( 0 ), fStrideX( 0 ), fStrideY( 0 ) {} // XXX really shouldn't be done. But -Weffc++ wants it so
275       AliHLTArrayBase( const AliHLTArrayBase &rhs ) : AliArrayBoundsCheck( rhs ), fData( rhs.fData ), fSize( rhs.fSize ), fStrideX( rhs.fStrideX ), fStrideY( rhs.fStrideY ) {} // XXX
276       AliHLTArrayBase &operator=( const AliHLTArrayBase &rhs ) { AliArrayBoundsCheck::operator=( rhs ); fData = rhs.fData; fSize = rhs.fSize; fStrideX = rhs.fStrideX; fStrideY = rhs.fStrideY; return *this; } // XXX
277       // Stopped working on GCC 4.5.0
278       //typedef typename ReturnTypeHelper<T>::Type R;
279       /**
280        * return a reference to the value at the given indexes
281        */
282       inline typename ReturnTypeHelper<T>::Type &operator()( int x, int y, int z );
283       /**
284        * return a const reference to the value at the given indexes
285        */
286       inline const typename ReturnTypeHelper<T>::Type &operator()( int x, int y, int z ) const;
287       /**
288        * return a 2-dim array at the given index. This makes it behave like a 3-dim C-Array.
289        */
290       inline AliHLTArray<T, 2> operator[]( int x );
291       /**
292        * return a const 2-dim array at the given index. This makes it behave like a 3-dim C-Array.
293        */
294       inline const AliHLTArray<T, 2> operator[]( int x ) const;
295
296     protected:
297       T *fData;     // actual data
298       int fSize;    // data size
299       int fStrideX; // stride X
300       int fStrideY; // stride Y
301       inline void SetSize( int x, int y, int z ) { fStrideX = y * z; fStrideY = z; fSize = fStrideX * x; }
302   };
303
304   template<typename T, unsigned int Size, int _alignment> class AlignedData
305   {
306     public:
307       T *ConstructAlignedData() {
308         const int offset = reinterpret_cast<unsigned long>( &fUnalignedArray[0] ) & ( Alignment - 1 );
309         void *mem = &fUnalignedArray[0] + ( Alignment - offset );
310         return new( mem ) T[Size];
311       }
312       ~AlignedData() {
313         const int offset = reinterpret_cast<unsigned long>( &fUnalignedArray[0] ) & ( Alignment - 1 );
314         T *mem = reinterpret_cast<T *>( &fUnalignedArray[0] + ( Alignment - offset ) );
315         for ( unsigned int i = 0; i < Size; ++i ) mem[i].~T();        
316       }
317     private:
318       enum {
319         Alignment = _alignment == kAliHLTFullyCacheLineAligned ? 128 : _alignment,
320         PaddedSize = Size * sizeof( T ) + Alignment
321       };
322       ALIHLTARRAY_STATIC_ASSERT_NC( ( Alignment & ( Alignment - 1 ) ) == 0, alignment_needs_to_be_a_multiple_of_2 );
323
324       char fUnalignedArray[PaddedSize]; // data array
325   };
326   template<typename T, unsigned int Size> class AlignedData<T, Size, 0>
327   {
328     public:
329       T *ConstructAlignedData() { return &fArray[0]; }
330     private:
331       T fArray[Size]; // data array
332   };
333 } // namespace AliHLTInternal
334
335 /**
336  * C-Array like class with the dimension dependent behavior defined in the AliHLTArrayBase class
337  */
338 template < typename T, int Dim = 1 >
339 class AliHLTArray : public AliHLTInternal::AliHLTArrayBase<T, Dim>
340 {
341   public:
342     typedef AliHLTInternal::AliHLTArrayBase<T, Dim> Parent;
343
344     /**
345      * Returns the number of elements in the array. If it is a multi-dimensional array the size is
346      * the multiplication of the dimensions ( e.g. a 10 x 20 array returns 200 as its size ).
347      */
348     inline int Size() const { return Parent::fSize; }
349
350     /**
351      * allows you to check for validity of the array by casting to bool
352      */
353     inline operator bool() const { return Parent::fData != 0; }
354     /**
355      * allows you to check for validity of the array
356      */
357     inline bool IsValid() const { return Parent::fData != 0; }
358
359     /**
360      * returns a reference to the data at index 0
361      */
362     inline T &operator*() { BOUNDS_CHECK( 0, Parent::fData[0] ); return *Parent::fData; }
363     /**
364      * returns a const reference to the data at index 0
365      */
366     inline const T &operator*() const { BOUNDS_CHECK( 0, Parent::fData[0] ); return *Parent::fData; }
367
368     /**
369      * returns a pointer to the data
370      * This circumvents bounds checking so it should not be used.
371      */
372     inline T *Data() { return Parent::fData; }
373     /**
374      * returns a const pointer to the data
375      * This circumvents bounds checking so it should not be used.
376      */
377     inline const T *Data() const { return Parent::fData; }
378
379     /**
380      * moves the array base pointer so that the data that was once at index 0 will then be at index -x
381      */
382     inline AliHLTArray operator+( int x ) const;
383     /**
384      * moves the array base pointer so that the data that was once at index 0 will then be at index x
385      */
386     inline AliHLTArray operator-( int x ) const;
387
388 #ifndef HLTCA_GPUCODE
389     template<typename Other> inline AliHLTArray<Other, Dim> ReinterpretCast() const {
390       AliHLTArray<Other, Dim> r;
391       r.fData = reinterpret_cast<Other *>( Parent::fData );
392       r.ReinterpretCast( *this, sizeof( T ), sizeof( Other ) );
393     }
394 #endif
395 };
396
397 /**
398  * Owns the data. When it goes out of scope the data is freed.
399  *
400  * The memory is allocated on the heap.
401  *
402  * Instantiate this class on the stack. Allocation on the heap is disallowed.
403  *
404  * \param T type of the entries in the array.
405  * \param Dim selects the operator[]/operator() behavior it should have. I.e. makes it behave like a
406  * 1-, 2- or 3-dim array. (defaults to 1)
407  * \param alignment Defaults to 0 (default alignment). Other valid values are any multiples of 2.
408  *                  This is especially useful for aligning data for SIMD vectors.
409  *
410  * \warning when using alignment the type T may not have a destructor (well it may, but it won't be
411  * called)
412  *
413  * Example:
414  * \code
415  * void init( AliHLTArray<int> a, int size )
416  * {
417  *   for ( int i = 0; i < size; ++i ) {
418  *     a[i] = i;
419  *   }
420  * }
421  *
422  * int size = ...;
423  * AliHLTResizableArray<int> foo( size ); // notice that size doesn't have to be a constant like it
424  *                                        // has to be for C-Arrays in ISO C++
425  * init( foo, size );
426  * // now foo[i] == i
427  *
428  * \endcode
429  */
430 template < typename T, int Dim = 1, int alignment = 0 >
431 class AliHLTResizableArray : public AliHLTArray<typename AliHLTInternal::TypeForAlignmentHelper<T, alignment>::Type, Dim>
432 {
433   public:
434     typedef typename AliHLTInternal::TypeForAlignmentHelper<T, alignment>::Type T2;
435     typedef AliHLTInternal::AliHLTArrayBase<T2, Dim> Parent;
436     /**
437      * does not allocate any memory
438      */
439     inline AliHLTResizableArray();
440     /**
441      * use for 1-dim arrays: allocates x * sizeof(T) bytes for the array
442      */
443     inline AliHLTResizableArray( int x );
444     /**
445      * use for 2-dim arrays: allocates x * y * sizeof(T) bytes for the array
446      */
447     inline AliHLTResizableArray( int x, int y );
448     /**
449      * use for 3-dim arrays: allocates x * y * z * sizeof(T) bytes for the array
450      */
451     inline AliHLTResizableArray( int x, int y, int z );
452
453     /**
454      * frees the data
455      */
456     inline ~AliHLTResizableArray() { AliHLTInternal::AliAllocator<T, alignment>::Free( Parent::fData, Parent::fSize ); }
457
458     /**
459      * use for 1-dim arrays: resizes the memory for the array to x * sizeof(T) bytes.
460      *
461      * \warning this does not keep your previous data. If you were looking for this you probably
462      * want to use std::vector instead.
463      */
464     inline void Resize( int x );
465     /**
466      * use for 2-dim arrays: resizes the memory for the array to x * y * sizeof(T) bytes.
467      *
468      * \warning this does not keep your previous data. If you were looking for this you probably
469      * want to use std::vector instead.
470      */
471     inline void Resize( int x, int y );
472     /**
473      * use for 3-dim arrays: resizes the memory for the array to x * y * z * sizeof(T) bytes.
474      *
475      * \warning this does not keep your previous data. If you were looking for this you probably
476      * want to use std::vector instead.
477      */
478     inline void Resize( int x, int y, int z );
479
480   private:
481     // disable allocation on the heap
482     void *operator new( size_t );
483
484     // disable copy
485     AliHLTResizableArray( const AliHLTResizableArray & );
486     AliHLTResizableArray &operator=( const AliHLTResizableArray & );
487 };
488
489 template < unsigned int x, unsigned int y = 0, unsigned int z = 0 > class AliHLTArraySize
490 {
491   public:
492     enum {
493       Size = y == 0 ? x : ( z == 0 ? x * y : x * y * z ),
494       Dim = y == 0 ? 1 : ( z == 0 ? 2 : 3 ),
495       X = x, Y = y, Z = z
496     };
497 };
498
499 /**
500  * Owns the data. When it goes out of scope the data is freed.
501  *
502  * The memory is allocated on the stack.
503  *
504  * Instantiate this class on the stack.
505  *
506  * \param T type of the entries in the array.
507  * \param Size number of entries in the array.
508  * \param Dim selects the operator[]/operator() behavior it should have. I.e. makes it behave like a
509  * 1-, 2- or 3-dim array. (defaults to 1)
510  */
511 template < typename T, typename Size, int alignment = 0 >
512 class AliHLTFixedArray : public AliHLTArray<typename AliHLTInternal::TypeForAlignmentHelper<T, alignment>::Type, Size::Dim>
513 {
514   public:
515     typedef typename AliHLTInternal::TypeForAlignmentHelper<T, alignment>::Type T2;
516     typedef AliHLTInternal::AliHLTArrayBase<T2, Size::Dim> Parent;
517     inline AliHLTFixedArray() {
518       Parent::fData = fFixedArray.ConstructAlignedData();
519       Parent::SetBounds( 0, Size::Size - 1 );
520       SetSize( Size::X, Size::Y, Size::Z );
521     }
522
523   private:
524     AliHLTInternal::AlignedData<typename AliHLTInternal::TypeForAlignmentHelper<T, alignment>::Type, Size::Size, alignment> fFixedArray; // data array
525
526     // disable allocation on the heap
527     void *operator new( size_t );
528
529     // disable copy
530 #ifdef HLTCA_GPUCODE
531 #else
532     AliHLTFixedArray( const AliHLTFixedArray & );
533     AliHLTFixedArray &operator=( const AliHLTFixedArray & );
534 #endif
535 };
536
537
538
539
540 ////////////////////////
541 //// implementation ////
542 ////////////////////////
543
544
545
546
547 namespace AliHLTInternal
548 {
549 #ifdef ENABLE_ARRAY_BOUNDS_CHECKING
550   inline bool AliArrayBoundsCheck::IsInBounds( int x ) const
551   {
552     assert( x >= fStart );
553     assert( x <= fEnd );
554     return ( x >= fStart && x <= fEnd );
555   }
556 #endif
557
558   template<typename T>
559   inline AliHLTArray<T, 1> AliHLTArrayBase<T, 2>::operator[]( int x )
560   {
561     x *= fStride;
562     typedef AliHLTArray<T, 1> AT1;
563     BOUNDS_CHECK( x, AT1() );
564     AliHLTArray<T, 1> a;
565     a.fData = &fData[x];
566     a.AliArrayBoundsCheck::operator=( *this );
567     a.MoveBounds( -x );
568     return a;
569   }
570
571   template<typename T>
572   inline const AliHLTArray<T, 1> AliHLTArrayBase<T, 2>::operator[]( int x ) const
573   {
574     x *= fStride;
575     typedef AliHLTArray<T, 1> AT1;
576     BOUNDS_CHECK( x, AT1() );
577     AliHLTArray<T, 1> a;
578     a.fData = &fData[x];
579     a.AliArrayBoundsCheck::operator=( *this );
580     a.MoveBounds( -x );
581     return a;
582   }
583
584   template<typename T>
585   inline typename AliHLTInternal::ReturnTypeHelper<T>::Type &AliHLTArrayBase<T, 3>::operator()( int x, int y, int z )
586   {
587     BOUNDS_CHECK( x * fStrideX + y + fStrideY + z, fData[0] );
588     return fData[x * fStrideX + y + fStrideY + z];
589   }
590   template<typename T>
591   inline const typename AliHLTInternal::ReturnTypeHelper<T>::Type &AliHLTArrayBase<T, 3>::operator()( int x, int y, int z ) const
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 AliHLTArray<T, 2> AliHLTArrayBase<T, 3>::operator[]( int x )
598   {
599     x *= fStrideX;
600     typedef AliHLTArray<T, 2> AT2;
601     BOUNDS_CHECK( x, AT2() );
602     AliHLTArray<T, 2> a;
603     a.fData = &fData[x];
604     a.fStride = fStrideY;
605     a.AliArrayBoundsCheck::operator=( *this );
606     a.MoveBounds( -x );
607     return a;
608   }
609   template<typename T>
610   inline const AliHLTArray<T, 2> AliHLTArrayBase<T, 3>::operator[]( int x ) const
611   {
612     x *= fStrideX;
613     typedef AliHLTArray<T, 2> AT2;
614     BOUNDS_CHECK( x, AT2() );
615     AliHLTArray<T, 2> a;
616     a.fData = &fData[x];
617     a.fStride = fStrideY;
618     a.AliArrayBoundsCheck::operator=( *this );
619     a.MoveBounds( -x );
620     return a;
621   }
622 } // namespace AliHLTInternal
623
624
625 template<typename T, int Dim>
626 inline AliHLTArray<T, Dim> AliHLTArray<T, Dim>::operator+( int x ) const
627 {
628   AliHLTArray<T, Dim> r( *this );
629   r.fData += x;
630   r.MoveBounds( -x );
631   return r;
632 }
633 template<typename T, int Dim>
634 inline AliHLTArray<T, Dim> AliHLTArray<T, Dim>::operator-( int x ) const
635 {
636   AliHLTArray<T, Dim> r( *this );
637   r.fData -= x;
638   r.MoveBounds( x );
639   return r;
640 }
641
642 template<typename T, int Dim, int alignment>
643 inline AliHLTResizableArray<T, Dim, alignment>::AliHLTResizableArray()
644 {
645   Parent::fData = 0;
646   Parent::SetSize( 0, 0, 0 );
647   Parent::SetBounds( 0, -1 );
648 }
649 template<typename T, int Dim, int alignment>
650 inline AliHLTResizableArray<T, Dim, alignment>::AliHLTResizableArray( int x )
651 {
652   ALIHLTARRAY_STATIC_ASSERT( Dim == 1, AliHLTResizableArray1_used_with_incorrect_dimension );
653   Parent::fData = AliHLTInternal::AliAllocator<T, alignment>::Alloc( x );
654   Parent::SetSize( x, 0, 0 );
655   Parent::SetBounds( 0, x - 1 );
656 }
657 template<typename T, int Dim, int alignment>
658 inline AliHLTResizableArray<T, Dim, alignment>::AliHLTResizableArray( int x, int y )
659 {
660   ALIHLTARRAY_STATIC_ASSERT( Dim == 2, AliHLTResizableArray2_used_with_incorrect_dimension );
661   Parent::fData = AliHLTInternal::AliAllocator<T, alignment>::Alloc( x * y );
662   Parent::SetSize( x, y, 0 );
663   Parent::SetBounds( 0, x * y - 1 );
664 }
665 template<typename T, int Dim, int alignment>
666 inline AliHLTResizableArray<T, Dim, alignment>::AliHLTResizableArray( int x, int y, int z )
667 {
668   ALIHLTARRAY_STATIC_ASSERT( Dim == 3, AliHLTResizableArray3_used_with_incorrect_dimension );
669   Parent::fData = AliHLTInternal::AliAllocator<T, alignment>::Alloc( x * y * z );
670   Parent::SetSize( x, y, z );
671   Parent::SetBounds( 0, x * y * z - 1 );
672 }
673 template<typename T, int Dim, int alignment>
674 inline void AliHLTResizableArray<T, Dim, alignment>::Resize( int x )
675 {
676   ALIHLTARRAY_STATIC_ASSERT( Dim == 1, AliHLTResizableArray1_resize_used_with_incorrect_dimension );
677   AliHLTInternal::AliAllocator<T, alignment>::Free( Parent::fData, Parent::fSize );
678   Parent::fData = ( x == 0 ) ? 0 : AliHLTInternal::AliAllocator<T, alignment>::Alloc( x );
679   Parent::SetSize( x, 0, 0 );
680   Parent::SetBounds( 0, x - 1 );
681 }
682 template<typename T, int Dim, int alignment>
683 inline void AliHLTResizableArray<T, Dim, alignment>::Resize( int x, int y )
684 {
685   ALIHLTARRAY_STATIC_ASSERT( Dim == 2, AliHLTResizableArray2_resize_used_with_incorrect_dimension );
686   AliHLTInternal::AliAllocator<T, alignment>::Free( Parent::fData, Parent::fSize );
687   Parent::fData = ( x == 0 ) ? 0 : AliHLTInternal::AliAllocator<T, alignment>::Alloc( x * y );
688   Parent::SetSize( x, y, 0 );
689   Parent::SetBounds( 0, x * y - 1 );
690 }
691 template<typename T, int Dim, int alignment>
692 inline void AliHLTResizableArray<T, Dim, alignment>::Resize( int x, int y, int z )
693 {
694   ALIHLTARRAY_STATIC_ASSERT( Dim == 3, AliHLTResizableArray3_resize_used_with_incorrect_dimension );
695   AliHLTInternal::AliAllocator<T, alignment>::Free( Parent::fData, Parent::fSize );
696   Parent::fData = ( x == 0 ) ? 0 : AliHLTInternal::AliAllocator<T, alignment>::Alloc( x * y * z );
697   Parent::SetSize( x, y, z );
698   Parent::SetBounds( 0, x * y * z - 1 );
699 }
700
701 #undef BOUNDS_CHECK
702
703 #endif // ALIHLTARRAY_H