]> git.uio.no Git - u/mrichter/AliRoot.git/blob - HLT/BASE/AliHLTArray.h
bugfix: inserted blank to separate reuired component libraries correctly. error
[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 namespace AliHLTArrayInternal
55 {
56   template<bool> class STATIC_ASSERT_FAILURE;
57   template<> class STATIC_ASSERT_FAILURE<true> {};
58 }
59
60 #define ALIHLTARRAY_STATIC_ASSERT_CONCAT_HELPER(a, b) a##b
61 #define ALIHLTARRAY_STATIC_ASSERT_CONCAT(a, b) ALIHLTARRAY_STATIC_ASSERT_CONCAT_HELPER(a, b)
62 #define ALIHLTARRAY_STATIC_ASSERT_NC(cond, msg) \
63   typedef AliHLTArrayInternal::STATIC_ASSERT_FAILURE<cond> ALIHLTARRAY_STATIC_ASSERT_CONCAT(_STATIC_ASSERTION_FAILED_##msg, __LINE__); \
64   ALIHLTARRAY_STATIC_ASSERT_CONCAT(_STATIC_ASSERTION_FAILED_##msg, __LINE__) Error_##msg
65 #define ALIHLTARRAY_STATIC_ASSERT(cond, msg) ALIHLTARRAY_STATIC_ASSERT_NC(cond, msg); (void) Error_##msg
66
67 template<typename T, int Dim> class AliHLTArray;
68
69 namespace AliHLTInternal
70 {
71   template<unsigned int Size> struct Padding { char fPadding[Size]; };
72   template<> struct Padding<0> {};
73   template<typename T> struct CacheLineSizeHelperData { T fData; };
74   template<typename T> struct CacheLineSizeHelperEnums {
75     enum {
76       CacheLineSize = 64,
77       MaskedSize = sizeof( T ) & ( CacheLineSize - 1 ),
78       RequiredSize = MaskedSize == 0 ? sizeof( T ) : sizeof( T ) + CacheLineSize - MaskedSize,
79       PaddingSize = RequiredSize - sizeof( T )
80     };
81   };
82   template<typename T> class CacheLineSizeHelper : private CacheLineSizeHelperData<T>, private Padding<CacheLineSizeHelperEnums<T>::PaddingSize>
83   {
84     public:
85       operator T &() { return CacheLineSizeHelperData<T>::fData; }
86       operator const T &() const { return CacheLineSizeHelperData<T>::fData; }
87       //const T &operator=( const T &rhs ) { CacheLineSizeHelperData<T>::fData = rhs; }
88
89     private:
90   };
91   template<typename T, int alignment> struct TypeForAlignmentHelper { typedef T Type; };
92   template<typename T> struct TypeForAlignmentHelper<T, AliHLTFullyCacheLineAligned> { typedef CacheLineSizeHelper<T> Type; };
93
94   // XXX
95   // The ArrayBoundsCheck and Allocator classes implement a virtual destructor only in order to
96   // silence the -Weffc++ warning. It really is not required for these classes to have a virtual
97   // dtor since polymorphism is not used (AliHLTResizableArray and AliHLTFixedArray are allocated on
98   // the stack only). The virtual dtor only adds an unnecessary vtable to the code.
99 #ifndef ENABLE_ARRAY_BOUNDS_CHECKING
100   /**
101    * no-op implementation that for no-bounds-checking
102    */
103   class ArrayBoundsCheck
104   {
105     protected:
106       virtual inline ~ArrayBoundsCheck() {}
107       inline bool IsInBounds( int ) const { return true; }
108       inline void SetBounds( int, int ) {}
109       inline void MoveBounds( int ) {}
110       inline void ReinterpretCast( const ArrayBoundsCheck &, int, int ) {}
111   };
112 #define BOUNDS_CHECK(x, y)
113 #else
114   /**
115    * implementation for bounds-checking.
116    */
117   class ArrayBoundsCheck
118   {
119     protected:
120       virtual inline ~ArrayBoundsCheck() {}
121       /**
122        * checks whether the given offset is valid
123        */
124       inline bool IsInBounds( int x ) const;
125       /**
126        * set the start and end offsets that are still valid
127        */
128       inline void SetBounds( int start, int end ) { fStart = start; fEnd = end; }
129       /**
130        * move the start and end offsets by the same amount
131        */
132       inline void MoveBounds( int d ) { fStart += d; fEnd += d; }
133
134       inline void ReinterpretCast( const ArrayBoundsCheck &other, int sizeofOld, int sizeofNew ) {
135         fStart = other.fStart * sizeofNew / sizeofOld;
136         fEnd = other.fEnd * sizeofNew / sizeofOld;
137       }
138
139     private:
140       int fStart;
141       int fEnd;
142   };
143 #define BOUNDS_CHECK(x, y) if (AliHLTInternal::ArrayBoundsCheck::IsInBounds(x)) {} else return y
144 #endif
145   template<typename T, int alignment> class Allocator
146   {
147     public:
148 #ifdef USE_MM_MALLOC
149       static inline T *Alloc( int s ) { T *p = reinterpret_cast<T *>( _mm_malloc( s * sizeof( T ), alignment ) ); return new( p ) T[s]; }
150       static inline void Free( T *const p, int size ) {
151         for ( int i = 0; i < size; ++i ) {
152           p[i].~T();
153         }
154         _mm_free( p );
155       }
156 #else
157       static inline T *Alloc( int s ) { T *p; posix_memalign( &p, alignment, s * sizeof( T ) ); 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         std::free( p );
163       }
164 #endif
165   };
166   template<typename T> class Allocator<T, AliHLTFullyCacheLineAligned>
167   {
168     public:
169       typedef CacheLineSizeHelper<T> T2;
170 #ifdef USE_MM_MALLOC
171       static inline T2 *Alloc( int s ) { T2 *p = reinterpret_cast<T2 *>( _mm_malloc( s * sizeof( T2 ), 128 ) ); return new( p ) T2[s]; }
172       static inline void Free( T2 *const p, int size ) {
173         for ( int i = 0; i < size; ++i ) {
174           p[i].~T2();
175         }
176         _mm_free( p );
177       }
178 #else
179       static inline T2 *Alloc( int s ) { T2 *p; posix_memalign( &p, 128, s * sizeof( T2 ) ); 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         std::free( p );
185       }
186 #endif
187   };
188   template<typename T> class Allocator<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<CacheLineSizeHelper<T> > { typedef T Type; };
197   /**
198    * Array base class for dimension dependent behavior
199    */
200   template<typename T, int Dim> class ArrayBase;
201
202   /**
203    * 1-dim arrays only have operator[]
204    */
205   template<typename T>
206   class ArrayBase<T, 1> : public ArrayBoundsCheck
207   {
208       friend class ArrayBase<T, 2>;
209     public:
210       ArrayBase() : fData( 0 ), fSize( 0 ) {} // XXX really shouldn't be done. But -Weffc++ wants it so
211       ArrayBase( const ArrayBase &rhs ) : ArrayBoundsCheck( rhs ), fData( rhs.fData ), fSize( rhs.fSize ) {} // XXX
212       ArrayBase &operator=( const ArrayBase &rhs ) { ArrayBoundsCheck::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;
225       int fSize;
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 ArrayBase<T, 2> : public ArrayBoundsCheck
235   {
236       friend class ArrayBase<T, 3>;
237     public:
238       ArrayBase() : fData( 0 ), fSize( 0 ), fStride( 0 ) {} // XXX really shouldn't be done. But -Weffc++ wants it so
239       ArrayBase( const ArrayBase &rhs ) : ArrayBoundsCheck( rhs ), fData( rhs.fData ), fSize( rhs.fSize ), fStride( rhs.fStride ) {} // XXX
240       ArrayBase &operator=( const ArrayBase &rhs ) { ArrayBoundsCheck::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;
261       int fSize;
262       int fStride;
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 ArrayBase<T, 3> : public ArrayBoundsCheck
272   {
273     public:
274       ArrayBase() : fData( 0 ), fSize( 0 ), fStrideX( 0 ), fStrideY( 0 ) {} // XXX really shouldn't be done. But -Weffc++ wants it so
275       ArrayBase( const ArrayBase &rhs ) : ArrayBoundsCheck( rhs ), fData( rhs.fData ), fSize( rhs.fSize ), fStrideX( rhs.fStrideX ), fStrideY( rhs.fStrideY ) {} // XXX
276       ArrayBase &operator=( const ArrayBase &rhs ) { ArrayBoundsCheck::operator=( rhs ); fData = rhs.fData; fSize = rhs.fSize; fStrideX = rhs.fStrideX; fStrideY = rhs.fStrideY; return *this; } // XXX
277       typedef typename ReturnTypeHelper<T>::Type R;
278       /**
279        * return a reference to the value at the given indexes
280        */
281       inline R &operator()( int x, int y, int z );
282       /**
283        * return a const reference to the value at the given indexes
284        */
285       inline const R &operator()( int x, int y, int z ) const;
286       /**
287        * return a 2-dim array at the given index. This makes it behave like a 3-dim C-Array.
288        */
289       inline AliHLTArray<T, 2> operator[]( int x );
290       /**
291        * return a const 2-dim array at the given index. This makes it behave like a 3-dim C-Array.
292        */
293       inline const AliHLTArray<T, 2> operator[]( int x ) const;
294
295     protected:
296       T *fData;
297       int fSize;
298       int fStrideX;
299       int fStrideY;
300       inline void SetSize( int x, int y, int z ) { fStrideX = y * z; fStrideY = z; fSize = fStrideX * x; }
301   };
302
303   template<typename T, unsigned int Size, int _alignment> class AlignedData
304   {
305     public:
306       T *ConstructAlignedData() {
307         const int offset = reinterpret_cast<unsigned long>( &fUnalignedArray[0] ) & ( Alignment - 1 );
308         void *mem = &fUnalignedArray[0] + ( Alignment - offset );
309         return new( mem ) T[Size];
310       }
311       ~AlignedData() {
312         const int offset = reinterpret_cast<unsigned long>( &fUnalignedArray[0] ) & ( Alignment - 1 );
313         T *mem = reinterpret_cast<T *>( &fUnalignedArray[0] + ( Alignment - offset ) );
314         for ( unsigned int i = 0; i < Size; ++i ) {
315           mem[i].~T();
316         }
317       }
318     private:
319       enum {
320         Alignment = _alignment == AliHLTFullyCacheLineAligned ? 128 : _alignment,
321         PaddedSize = Size * sizeof( T ) + Alignment
322       };
323       ALIHLTARRAY_STATIC_ASSERT_NC( ( Alignment & ( Alignment - 1 ) ) == 0, alignment_needs_to_be_a_multiple_of_2 );
324
325       char fUnalignedArray[PaddedSize];
326   };
327   template<typename T, unsigned int Size> class AlignedData<T, Size, 0>
328   {
329     public:
330       T *ConstructAlignedData() { return &fArray[0]; }
331     private:
332       T fArray[Size];
333   };
334 } // namespace AliHLTInternal
335
336 /**
337  * C-Array like class with the dimension dependent behavior defined in the ArrayBase class
338  */
339 template < typename T, int Dim = 1 >
340 class AliHLTArray : public AliHLTInternal::ArrayBase<T, Dim>
341 {
342   public:
343     typedef AliHLTInternal::ArrayBase<T, Dim> Parent;
344
345     /**
346      * Returns the number of elements in the array. If it is a multi-dimensional array the size is
347      * the multiplication of the dimensions ( e.g. a 10 x 20 array returns 200 as its size ).
348      */
349     inline int Size() const { return Parent::fSize; }
350
351     /**
352      * allows you to check for validity of the array by casting to bool
353      */
354     inline operator bool() const { return Parent::fData != 0; }
355     /**
356      * allows you to check for validity of the array
357      */
358     inline bool IsValid() const { return Parent::fData != 0; }
359
360     /**
361      * returns a reference to the data at index 0
362      */
363     inline T &operator*() { BOUNDS_CHECK( 0, Parent::fData[0] ); return *Parent::fData; }
364     /**
365      * returns a const reference to the data at index 0
366      */
367     inline const T &operator*() const { BOUNDS_CHECK( 0, Parent::fData[0] ); return *Parent::fData; }
368
369     /**
370      * returns a pointer to the data
371      * This circumvents bounds checking so it should not be used.
372      */
373     inline T *Data() { return Parent::fData; }
374     /**
375      * returns a const pointer to the data
376      * This circumvents bounds checking so it should not be used.
377      */
378     inline const T *Data() const { return Parent::fData; }
379
380     /**
381      * moves the array base pointer so that the data that was once at index 0 will then be at index -x
382      */
383     inline AliHLTArray operator+( int x ) const;
384     /**
385      * moves the array base pointer so that the data that was once at index 0 will then be at index x
386      */
387     inline AliHLTArray operator-( int x ) const;
388
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 };
395
396 /**
397  * Owns the data. When it goes out of scope the data is freed.
398  *
399  * The memory is allocated on the heap.
400  *
401  * Instantiate this class on the stack. Allocation on the heap is disallowed.
402  *
403  * \param T type of the entries in the array.
404  * \param Dim selects the operator[]/operator() behavior it should have. I.e. makes it behave like a
405  * 1-, 2- or 3-dim array. (defaults to 1)
406  * \param alignment Defaults to 0 (default alignment). Other valid values are any multiples of 2.
407  *                  This is especially useful for aligning data for SIMD vectors.
408  *
409  * \warning when using alignment the type T may not have a destructor (well it may, but it won't be
410  * called)
411  *
412  * Example:
413  * \code
414  * void init( AliHLTArray<int> a, int size )
415  * {
416  *   for ( int i = 0; i < size; ++i ) {
417  *     a[i] = i;
418  *   }
419  * }
420  *
421  * int size = ...;
422  * AliHLTResizableArray<int> foo( size ); // notice that size doesn't have to be a constant like it
423  *                                        // has to be for C-Arrays in ISO C++
424  * init( foo, size );
425  * // now foo[i] == i
426  *
427  * \endcode
428  */
429 template < typename T, int Dim = 1, int alignment = 0 >
430 class AliHLTResizableArray : public AliHLTArray<typename AliHLTInternal::TypeForAlignmentHelper<T, alignment>::Type, Dim>
431 {
432   public:
433     typedef typename AliHLTInternal::TypeForAlignmentHelper<T, alignment>::Type T2;
434     typedef AliHLTInternal::ArrayBase<T2, Dim> Parent;
435     /**
436      * does not allocate any memory
437      */
438     inline AliHLTResizableArray();
439     /**
440      * use for 1-dim arrays: allocates x * sizeof(T) bytes for the array
441      */
442     inline AliHLTResizableArray( int x );
443     /**
444      * use for 2-dim arrays: allocates x * y * sizeof(T) bytes for the array
445      */
446     inline AliHLTResizableArray( int x, int y );
447     /**
448      * use for 3-dim arrays: allocates x * y * z * sizeof(T) bytes for the array
449      */
450     inline AliHLTResizableArray( int x, int y, int z );
451
452     /**
453      * frees the data
454      */
455     inline ~AliHLTResizableArray() { AliHLTInternal::Allocator<T, alignment>::Free( Parent::fData, Parent::fSize ); }
456
457     /**
458      * use for 1-dim arrays: resizes the memory for the array to x * sizeof(T) bytes.
459      *
460      * \warning this does not keep your previous data. If you were looking for this you probably
461      * want to use std::vector instead.
462      */
463     inline void Resize( int x );
464     /**
465      * use for 2-dim arrays: resizes the memory for the array to x * y * 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, int y );
471     /**
472      * use for 3-dim arrays: resizes the memory for the array to x * y * z * 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, int z );
478
479   private:
480     // disable allocation on the heap
481     void *operator new( size_t );
482
483     // disable copy
484     AliHLTResizableArray( const AliHLTResizableArray & );
485     AliHLTResizableArray &operator=( const AliHLTResizableArray & );
486 };
487
488 template < unsigned int x, unsigned int y = 0, unsigned int z = 0 > class AliHLTArraySize
489 {
490   public:
491     enum {
492       Size = y == 0 ? x : ( z == 0 ? x * y : x * y * z ),
493       Dim = y == 0 ? 1 : ( z == 0 ? 2 : 3 ),
494       X = x, Y = y, Z = z
495     };
496 };
497
498 /**
499  * Owns the data. When it goes out of scope the data is freed.
500  *
501  * The memory is allocated on the stack.
502  *
503  * Instantiate this class on the stack.
504  *
505  * \param T type of the entries in the array.
506  * \param Size number of entries in the array.
507  * \param Dim selects the operator[]/operator() behavior it should have. I.e. makes it behave like a
508  * 1-, 2- or 3-dim array. (defaults to 1)
509  */
510 template < typename T, typename Size, int alignment = 0 >
511 class AliHLTFixedArray : public AliHLTArray<typename AliHLTInternal::TypeForAlignmentHelper<T, alignment>::Type, Size::Dim>
512 {
513   public:
514     typedef typename AliHLTInternal::TypeForAlignmentHelper<T, alignment>::Type T2;
515     typedef AliHLTInternal::ArrayBase<T2, Size::Dim> Parent;
516     inline AliHLTFixedArray() {
517       Parent::fData = fFixedArray.ConstructAlignedData();
518       Parent::SetBounds( 0, Size::Size - 1 );
519       SetSize( Size::X, Size::Y, Size::Z );
520     }
521
522   private:
523     AliHLTInternal::AlignedData<typename AliHLTInternal::TypeForAlignmentHelper<T, alignment>::Type, Size::Size, alignment> fFixedArray;
524
525     // disable allocation on the heap
526     void *operator new( size_t );
527
528     // disable copy
529     AliHLTFixedArray( const AliHLTFixedArray & );
530     AliHLTFixedArray &operator=( const AliHLTFixedArray & );
531 };
532
533
534
535
536 ////////////////////////
537 //// implementation ////
538 ////////////////////////
539
540
541
542
543 namespace AliHLTInternal
544 {
545 #ifdef ENABLE_ARRAY_BOUNDS_CHECKING
546   inline bool ArrayBoundsCheck::IsInBounds( int x ) const
547   {
548     assert( x >= fStart );
549     assert( x <= fEnd );
550     return ( x >= fStart && x <= fEnd );
551   }
552 #endif
553
554   template<typename T>
555   inline AliHLTArray<T, 1> ArrayBase<T, 2>::operator[]( int x )
556   {
557     x *= fStride;
558     typedef AliHLTArray<T, 1> AT1;
559     BOUNDS_CHECK( x, AT1() );
560     AliHLTArray<T, 1> a;
561     a.fData = &fData[x];
562     a.ArrayBoundsCheck::operator=( *this );
563     a.MoveBounds( -x );
564     return a;
565   }
566
567   template<typename T>
568   inline const AliHLTArray<T, 1> ArrayBase<T, 2>::operator[]( int x ) const
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 typename AliHLTInternal::ReturnTypeHelper<T>::Type &ArrayBase<T, 3>::operator()( int x, int y, int z )
582   {
583     BOUNDS_CHECK( x * fStrideX + y + fStrideY + z, fData[0] );
584     return fData[x * fStrideX + y + fStrideY + z];
585   }
586   template<typename T>
587   inline const typename AliHLTInternal::ReturnTypeHelper<T>::Type &ArrayBase<T, 3>::operator()( int x, int y, int z ) const
588   {
589     BOUNDS_CHECK( x * fStrideX + y + fStrideY + z, fData[0] );
590     return fData[x * fStrideX + y + fStrideY + z];
591   }
592   template<typename T>
593   inline AliHLTArray<T, 2> ArrayBase<T, 3>::operator[]( int x )
594   {
595     x *= fStrideX;
596     typedef AliHLTArray<T, 2> AT2;
597     BOUNDS_CHECK( x, AT2() );
598     AliHLTArray<T, 2> a;
599     a.fData = &fData[x];
600     a.fStride = fStrideY;
601     a.ArrayBoundsCheck::operator=( *this );
602     a.MoveBounds( -x );
603     return a;
604   }
605   template<typename T>
606   inline const AliHLTArray<T, 2> ArrayBase<T, 3>::operator[]( int x ) const
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 } // namespace AliHLTInternal
619
620
621 template<typename T, int Dim>
622 inline AliHLTArray<T, Dim> AliHLTArray<T, Dim>::operator+( int x ) const
623 {
624   AliHLTArray<T, Dim> r( *this );
625   r.fData += x;
626   r.MoveBounds( -x );
627   return r;
628 }
629 template<typename T, int Dim>
630 inline AliHLTArray<T, Dim> AliHLTArray<T, Dim>::operator-( int x ) const
631 {
632   AliHLTArray<T, Dim> r( *this );
633   r.fData -= x;
634   r.MoveBounds( x );
635   return r;
636 }
637
638 template<typename T, int Dim, int alignment>
639 inline AliHLTResizableArray<T, Dim, alignment>::AliHLTResizableArray()
640 {
641   Parent::fData = 0;
642   Parent::SetSize( 0, 0, 0 );
643   Parent::SetBounds( 0, -1 );
644 }
645 template<typename T, int Dim, int alignment>
646 inline AliHLTResizableArray<T, Dim, alignment>::AliHLTResizableArray( int x )
647 {
648   ALIHLTARRAY_STATIC_ASSERT( Dim == 1, AliHLTResizableArray1_used_with_incorrect_dimension );
649   Parent::fData = AliHLTInternal::Allocator<T, alignment>::Alloc( x );
650   Parent::SetSize( x, 0, 0 );
651   Parent::SetBounds( 0, x - 1 );
652 }
653 template<typename T, int Dim, int alignment>
654 inline AliHLTResizableArray<T, Dim, alignment>::AliHLTResizableArray( int x, int y )
655 {
656   ALIHLTARRAY_STATIC_ASSERT( Dim == 2, AliHLTResizableArray2_used_with_incorrect_dimension );
657   Parent::fData = AliHLTInternal::Allocator<T, alignment>::Alloc( x * y );
658   Parent::SetSize( x, y, 0 );
659   Parent::SetBounds( 0, x * y - 1 );
660 }
661 template<typename T, int Dim, int alignment>
662 inline AliHLTResizableArray<T, Dim, alignment>::AliHLTResizableArray( int x, int y, int z )
663 {
664   ALIHLTARRAY_STATIC_ASSERT( Dim == 3, AliHLTResizableArray3_used_with_incorrect_dimension );
665   Parent::fData = AliHLTInternal::Allocator<T, alignment>::Alloc( x * y * z );
666   Parent::SetSize( x, y, z );
667   Parent::SetBounds( 0, x * y * z - 1 );
668 }
669 template<typename T, int Dim, int alignment>
670 inline void AliHLTResizableArray<T, Dim, alignment>::Resize( int x )
671 {
672   ALIHLTARRAY_STATIC_ASSERT( Dim == 1, AliHLTResizableArray1_resize_used_with_incorrect_dimension );
673   AliHLTInternal::Allocator<T, alignment>::Free( Parent::fData, Parent::fSize );
674   Parent::fData = ( x == 0 ) ? 0 : AliHLTInternal::Allocator<T, alignment>::Alloc( x );
675   Parent::SetSize( x, 0, 0 );
676   Parent::SetBounds( 0, x - 1 );
677 }
678 template<typename T, int Dim, int alignment>
679 inline void AliHLTResizableArray<T, Dim, alignment>::Resize( int x, int y )
680 {
681   ALIHLTARRAY_STATIC_ASSERT( Dim == 2, AliHLTResizableArray2_resize_used_with_incorrect_dimension );
682   AliHLTInternal::Allocator<T, alignment>::Free( Parent::fData, Parent::fSize );
683   Parent::fData = ( x == 0 ) ? 0 : AliHLTInternal::Allocator<T, alignment>::Alloc( x * y );
684   Parent::SetSize( x, y, 0 );
685   Parent::SetBounds( 0, x * y - 1 );
686 }
687 template<typename T, int Dim, int alignment>
688 inline void AliHLTResizableArray<T, Dim, alignment>::Resize( int x, int y, int z )
689 {
690   ALIHLTARRAY_STATIC_ASSERT( Dim == 3, AliHLTResizableArray3_resize_used_with_incorrect_dimension );
691   AliHLTInternal::Allocator<T, alignment>::Free( Parent::fData, Parent::fSize );
692   Parent::fData = ( x == 0 ) ? 0 : AliHLTInternal::Allocator<T, alignment>::Alloc( x * y * z );
693   Parent::SetSize( x, y, z );
694   Parent::SetBounds( 0, x * y * z - 1 );
695 }
696
697 #undef BOUNDS_CHECK
698
699 #endif // ALIHLTARRAY_H