4 // ****************************************************************************
5 // * This file is property of and copyright by the ALICE HLT Project *
6 // * ALICE Experiment at CERN, All rights reserved. *
8 // * Copyright (C) 2009 Matthias Kretz <kretz@kde.org> *
9 // * for The ALICE HLT Project. *
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 // ****************************************************************************
22 * \author Matthias Kretz <kretz@kde.org>
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.
37 #if (defined(__MMX__) || defined(__SSE__))
42 #else // not gcc, assume it can use _mm_malloc since it supports MMX/SSE
48 #include <mm_malloc.h>
54 AliHLTFullyCacheLineAligned = -1
57 #if defined(__CUDACC__) & 0
58 #define ALIHLTARRAY_STATIC_ASSERT(a, b)
59 #define ALIHLTARRAY_STATIC_ASSERT_NC(a, b)
61 namespace AliHLTArrayInternal
63 template<bool> class STATIC_ASSERT_FAILURE;
64 template<> class STATIC_ASSERT_FAILURE<true> {};
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
75 template<typename T, int Dim> class AliHLTArray;
77 namespace AliHLTInternal
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 {
85 MaskedSize = sizeof( T ) & ( CacheLineSize - 1 ),
86 RequiredSize = MaskedSize == 0 ? sizeof( T ) : sizeof( T ) + CacheLineSize - MaskedSize,
87 PaddingSize = RequiredSize - sizeof( T )
90 template<typename T> class CacheLineSizeHelper : private CacheLineSizeHelperData<T>, private Padding<CacheLineSizeHelperEnums<T>::PaddingSize>
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; }
99 template<typename T, int alignment> struct TypeForAlignmentHelper { typedef T Type; };
100 template<typename T> struct TypeForAlignmentHelper<T, AliHLTFullyCacheLineAligned> { typedef CacheLineSizeHelper<T> Type; };
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
109 * no-op implementation that for no-bounds-checking
111 class ArrayBoundsCheck
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 ) {}
120 #define BOUNDS_CHECK(x, y)
123 * implementation for bounds-checking.
125 class ArrayBoundsCheck
128 virtual inline ~ArrayBoundsCheck() {}
130 * checks whether the given offset is valid
132 inline bool IsInBounds( int x ) const;
134 * set the start and end offsets that are still valid
136 inline void SetBounds( int start, int end ) { fStart = start; fEnd = end; }
138 * move the start and end offsets by the same amount
140 inline void MoveBounds( int d ) { fStart += d; fEnd += d; }
142 inline void ReinterpretCast( const ArrayBoundsCheck &other, int sizeofOld, int sizeofNew ) {
143 fStart = other.fStart * sizeofNew / sizeofOld;
144 fEnd = other.fEnd * sizeofNew / sizeofOld;
151 #define BOUNDS_CHECK(x, y) if (AliHLTInternal::ArrayBoundsCheck::IsInBounds(x)) {} else return y
153 template<typename T, int alignment> class Allocator
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 ) {
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 ) {
174 template<typename T> class Allocator<T, AliHLTFullyCacheLineAligned>
177 typedef CacheLineSizeHelper<T> T2;
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 ) {
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 ) {
196 template<typename T> class Allocator<T, 0>
199 static inline T *Alloc( int s ) { return new T[s]; }
200 static inline void Free( const T *const p, int ) { delete[] p; }
203 template<typename T> struct ReturnTypeHelper { typedef T Type; };
204 template<typename T> struct ReturnTypeHelper<CacheLineSizeHelper<T> > { typedef T Type; };
206 * Array base class for dimension dependent behavior
208 template<typename T, int Dim> class ArrayBase;
211 * 1-dim arrays only have operator[]
214 class ArrayBase<T, 1> : public ArrayBoundsCheck
216 friend class ArrayBase<T, 2>;
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;
223 * return a reference to the value at the given index
225 inline R &operator[]( int x ) { BOUNDS_CHECK( x, fData[0] ); return fData[x]; }
227 * return a const reference to the value at the given index
229 inline const R &operator[]( int x ) const { BOUNDS_CHECK( x, fData[0] ); return fData[x]; }
232 T *fData; // actual data
233 int fSize; // data size
234 inline void SetSize( int x, int, int ) { fSize = x; }
238 * 2-dim arrays should use operator(int, int)
239 * operator[] can be used to return a 1-dim array
242 class ArrayBase<T, 2> : public ArrayBoundsCheck
244 friend class ArrayBase<T, 3>;
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;
251 * return a reference to the value at the given indexes
253 inline R &operator()( int x, int y ) { BOUNDS_CHECK( x * fStride + y, fData[0] ); return fData[x * fStride + y]; }
255 * return a const reference to the value at the given indexes
257 inline const R &operator()( int x, int y ) const { BOUNDS_CHECK( x * fStride + y, fData[0] ); return fData[x * fStride + y]; }
259 * return a 1-dim array at the given index. This makes it behave like a 2-dim C-Array.
261 inline AliHLTArray<T, 1> operator[]( int x );
263 * return a const 1-dim array at the given index. This makes it behave like a 2-dim C-Array.
265 inline const AliHLTArray<T, 1> operator[]( int x ) const;
268 T *fData; // actual data
269 int fSize; // data size
271 inline void SetSize( int x, int y, int ) { fStride = y; fSize = x * y; }
275 * 3-dim arrays should use operator(int, int, int)
276 * operator[] can be used to return a 2-dim array
279 class ArrayBase<T, 3> : public ArrayBoundsCheck
282 ArrayBase() : fData( 0 ), fSize( 0 ), fStrideX( 0 ), fStrideY( 0 ) {} // XXX really shouldn't be done. But -Weffc++ wants it so
283 ArrayBase( const ArrayBase &rhs ) : ArrayBoundsCheck( rhs ), fData( rhs.fData ), fSize( rhs.fSize ), fStrideX( rhs.fStrideX ), fStrideY( rhs.fStrideY ) {} // XXX
284 ArrayBase &operator=( const ArrayBase &rhs ) { ArrayBoundsCheck::operator=( rhs ); fData = rhs.fData; fSize = rhs.fSize; fStrideX = rhs.fStrideX; fStrideY = rhs.fStrideY; return *this; } // XXX
285 typedef typename ReturnTypeHelper<T>::Type R;
287 * return a reference to the value at the given indexes
289 inline R &operator()( int x, int y, int z );
291 * return a const reference to the value at the given indexes
293 inline const R &operator()( int x, int y, int z ) const;
295 * return a 2-dim array at the given index. This makes it behave like a 3-dim C-Array.
297 inline AliHLTArray<T, 2> operator[]( int x );
299 * return a const 2-dim array at the given index. This makes it behave like a 3-dim C-Array.
301 inline const AliHLTArray<T, 2> operator[]( int x ) const;
304 T *fData; // actual data
305 int fSize; // data size
308 inline void SetSize( int x, int y, int z ) { fStrideX = y * z; fStrideY = z; fSize = fStrideX * x; }
311 template<typename T, unsigned int Size, int _alignment> class AlignedData
314 T *ConstructAlignedData() {
315 const int offset = reinterpret_cast<unsigned long>( &fUnalignedArray[0] ) & ( Alignment - 1 );
316 void *mem = &fUnalignedArray[0] + ( Alignment - offset );
317 return new( mem ) T[Size];
320 const int offset = reinterpret_cast<unsigned long>( &fUnalignedArray[0] ) & ( Alignment - 1 );
321 T *mem = reinterpret_cast<T *>( &fUnalignedArray[0] + ( Alignment - offset ) );
322 for ( unsigned int i = 0; i < Size; ++i ) {
328 Alignment = _alignment == AliHLTFullyCacheLineAligned ? 128 : _alignment,
329 PaddedSize = Size * sizeof( T ) + Alignment
331 ALIHLTARRAY_STATIC_ASSERT_NC( ( Alignment & ( Alignment - 1 ) ) == 0, alignment_needs_to_be_a_multiple_of_2 );
333 char fUnalignedArray[PaddedSize]; //
335 template<typename T, unsigned int Size> class AlignedData<T, Size, 0>
338 T *ConstructAlignedData() { return &fArray[0]; }
342 } // namespace AliHLTInternal
345 * C-Array like class with the dimension dependent behavior defined in the ArrayBase class
347 template < typename T, int Dim = 1 >
348 class AliHLTArray : public AliHLTInternal::ArrayBase<T, Dim>
351 typedef AliHLTInternal::ArrayBase<T, Dim> Parent;
354 * Returns the number of elements in the array. If it is a multi-dimensional array the size is
355 * the multiplication of the dimensions ( e.g. a 10 x 20 array returns 200 as its size ).
357 inline int Size() const { return Parent::fSize; }
360 * allows you to check for validity of the array by casting to bool
362 inline operator bool() const { return Parent::fData != 0; }
364 * allows you to check for validity of the array
366 inline bool IsValid() const { return Parent::fData != 0; }
369 * returns a reference to the data at index 0
371 inline T &operator*() { BOUNDS_CHECK( 0, Parent::fData[0] ); return *Parent::fData; }
373 * returns a const reference to the data at index 0
375 inline const T &operator*() const { BOUNDS_CHECK( 0, Parent::fData[0] ); return *Parent::fData; }
378 * returns a pointer to the data
379 * This circumvents bounds checking so it should not be used.
381 inline T *Data() { return Parent::fData; }
383 * returns a const pointer to the data
384 * This circumvents bounds checking so it should not be used.
386 inline const T *Data() const { return Parent::fData; }
389 * moves the array base pointer so that the data that was once at index 0 will then be at index -x
391 inline AliHLTArray operator+( int x ) const;
393 * moves the array base pointer so that the data that was once at index 0 will then be at index x
395 inline AliHLTArray operator-( int x ) const;
397 #ifndef HLTCA_GPUCODE
398 template<typename Other> inline AliHLTArray<Other, Dim> ReinterpretCast() const {
399 AliHLTArray<Other, Dim> r;
400 r.fData = reinterpret_cast<Other *>( Parent::fData );
401 r.ReinterpretCast( *this, sizeof( T ), sizeof( Other ) );
407 * Owns the data. When it goes out of scope the data is freed.
409 * The memory is allocated on the heap.
411 * Instantiate this class on the stack. Allocation on the heap is disallowed.
413 * \param T type of the entries in the array.
414 * \param Dim selects the operator[]/operator() behavior it should have. I.e. makes it behave like a
415 * 1-, 2- or 3-dim array. (defaults to 1)
416 * \param alignment Defaults to 0 (default alignment). Other valid values are any multiples of 2.
417 * This is especially useful for aligning data for SIMD vectors.
419 * \warning when using alignment the type T may not have a destructor (well it may, but it won't be
424 * void init( AliHLTArray<int> a, int size )
426 * for ( int i = 0; i < size; ++i ) {
432 * AliHLTResizableArray<int> foo( size ); // notice that size doesn't have to be a constant like it
433 * // has to be for C-Arrays in ISO C++
439 template < typename T, int Dim = 1, int alignment = 0 >
440 class AliHLTResizableArray : public AliHLTArray<typename AliHLTInternal::TypeForAlignmentHelper<T, alignment>::Type, Dim>
443 typedef typename AliHLTInternal::TypeForAlignmentHelper<T, alignment>::Type T2;
444 typedef AliHLTInternal::ArrayBase<T2, Dim> Parent;
446 * does not allocate any memory
448 inline AliHLTResizableArray();
450 * use for 1-dim arrays: allocates x * sizeof(T) bytes for the array
452 inline AliHLTResizableArray( int x );
454 * use for 2-dim arrays: allocates x * y * sizeof(T) bytes for the array
456 inline AliHLTResizableArray( int x, int y );
458 * use for 3-dim arrays: allocates x * y * z * sizeof(T) bytes for the array
460 inline AliHLTResizableArray( int x, int y, int z );
465 inline ~AliHLTResizableArray() { AliHLTInternal::Allocator<T, alignment>::Free( Parent::fData, Parent::fSize ); }
468 * use for 1-dim arrays: resizes the memory for the array to x * sizeof(T) bytes.
470 * \warning this does not keep your previous data. If you were looking for this you probably
471 * want to use std::vector instead.
473 inline void Resize( int x );
475 * use for 2-dim arrays: resizes the memory for the array to x * y * sizeof(T) bytes.
477 * \warning this does not keep your previous data. If you were looking for this you probably
478 * want to use std::vector instead.
480 inline void Resize( int x, int y );
482 * use for 3-dim arrays: resizes the memory for the array to x * y * z * sizeof(T) bytes.
484 * \warning this does not keep your previous data. If you were looking for this you probably
485 * want to use std::vector instead.
487 inline void Resize( int x, int y, int z );
490 // disable allocation on the heap
491 void *operator new( size_t );
494 AliHLTResizableArray( const AliHLTResizableArray & );
495 AliHLTResizableArray &operator=( const AliHLTResizableArray & );
498 template < unsigned int x, unsigned int y = 0, unsigned int z = 0 > class AliHLTArraySize
502 Size = y == 0 ? x : ( z == 0 ? x * y : x * y * z ),
503 Dim = y == 0 ? 1 : ( z == 0 ? 2 : 3 ),
509 * Owns the data. When it goes out of scope the data is freed.
511 * The memory is allocated on the stack.
513 * Instantiate this class on the stack.
515 * \param T type of the entries in the array.
516 * \param Size number of entries in the array.
517 * \param Dim selects the operator[]/operator() behavior it should have. I.e. makes it behave like a
518 * 1-, 2- or 3-dim array. (defaults to 1)
520 template < typename T, typename Size, int alignment = 0 >
521 class AliHLTFixedArray : public AliHLTArray<typename AliHLTInternal::TypeForAlignmentHelper<T, alignment>::Type, Size::Dim>
524 typedef typename AliHLTInternal::TypeForAlignmentHelper<T, alignment>::Type T2;
525 typedef AliHLTInternal::ArrayBase<T2, Size::Dim> Parent;
526 inline AliHLTFixedArray() {
527 Parent::fData = fFixedArray.ConstructAlignedData();
528 Parent::SetBounds( 0, Size::Size - 1 );
529 SetSize( Size::X, Size::Y, Size::Z );
533 AliHLTInternal::AlignedData<typename AliHLTInternal::TypeForAlignmentHelper<T, alignment>::Type, Size::Size, alignment> fFixedArray; //
535 // disable allocation on the heap
536 void *operator new( size_t );
541 AliHLTFixedArray( const AliHLTFixedArray & );
542 AliHLTFixedArray &operator=( const AliHLTFixedArray & );
549 ////////////////////////
550 //// implementation ////
551 ////////////////////////
556 namespace AliHLTInternal
558 #ifdef ENABLE_ARRAY_BOUNDS_CHECKING
559 inline bool ArrayBoundsCheck::IsInBounds( int x ) const
561 assert( x >= fStart );
563 return ( x >= fStart && x <= fEnd );
568 inline AliHLTArray<T, 1> ArrayBase<T, 2>::operator[]( int x )
571 typedef AliHLTArray<T, 1> AT1;
572 BOUNDS_CHECK( x, AT1() );
575 a.ArrayBoundsCheck::operator=( *this );
581 inline const AliHLTArray<T, 1> ArrayBase<T, 2>::operator[]( int x ) const
584 typedef AliHLTArray<T, 1> AT1;
585 BOUNDS_CHECK( x, AT1() );
588 a.ArrayBoundsCheck::operator=( *this );
594 inline typename AliHLTInternal::ReturnTypeHelper<T>::Type &ArrayBase<T, 3>::operator()( int x, int y, int z )
596 BOUNDS_CHECK( x * fStrideX + y + fStrideY + z, fData[0] );
597 return fData[x * fStrideX + y + fStrideY + z];
600 inline const typename AliHLTInternal::ReturnTypeHelper<T>::Type &ArrayBase<T, 3>::operator()( int x, int y, int z ) const
602 BOUNDS_CHECK( x * fStrideX + y + fStrideY + z, fData[0] );
603 return fData[x * fStrideX + y + fStrideY + z];
606 inline AliHLTArray<T, 2> ArrayBase<T, 3>::operator[]( int x )
609 typedef AliHLTArray<T, 2> AT2;
610 BOUNDS_CHECK( x, AT2() );
613 a.fStride = fStrideY;
614 a.ArrayBoundsCheck::operator=( *this );
619 inline const AliHLTArray<T, 2> ArrayBase<T, 3>::operator[]( int x ) const
622 typedef AliHLTArray<T, 2> AT2;
623 BOUNDS_CHECK( x, AT2() );
626 a.fStride = fStrideY;
627 a.ArrayBoundsCheck::operator=( *this );
631 } // namespace AliHLTInternal
634 template<typename T, int Dim>
635 inline AliHLTArray<T, Dim> AliHLTArray<T, Dim>::operator+( int x ) const
637 AliHLTArray<T, Dim> r( *this );
642 template<typename T, int Dim>
643 inline AliHLTArray<T, Dim> AliHLTArray<T, Dim>::operator-( int x ) const
645 AliHLTArray<T, Dim> r( *this );
651 template<typename T, int Dim, int alignment>
652 inline AliHLTResizableArray<T, Dim, alignment>::AliHLTResizableArray()
655 Parent::SetSize( 0, 0, 0 );
656 Parent::SetBounds( 0, -1 );
658 template<typename T, int Dim, int alignment>
659 inline AliHLTResizableArray<T, Dim, alignment>::AliHLTResizableArray( int x )
661 ALIHLTARRAY_STATIC_ASSERT( Dim == 1, AliHLTResizableArray1_used_with_incorrect_dimension );
662 Parent::fData = AliHLTInternal::Allocator<T, alignment>::Alloc( x );
663 Parent::SetSize( x, 0, 0 );
664 Parent::SetBounds( 0, x - 1 );
666 template<typename T, int Dim, int alignment>
667 inline AliHLTResizableArray<T, Dim, alignment>::AliHLTResizableArray( int x, int y )
669 ALIHLTARRAY_STATIC_ASSERT( Dim == 2, AliHLTResizableArray2_used_with_incorrect_dimension );
670 Parent::fData = AliHLTInternal::Allocator<T, alignment>::Alloc( x * y );
671 Parent::SetSize( x, y, 0 );
672 Parent::SetBounds( 0, x * y - 1 );
674 template<typename T, int Dim, int alignment>
675 inline AliHLTResizableArray<T, Dim, alignment>::AliHLTResizableArray( int x, int y, int z )
677 ALIHLTARRAY_STATIC_ASSERT( Dim == 3, AliHLTResizableArray3_used_with_incorrect_dimension );
678 Parent::fData = AliHLTInternal::Allocator<T, alignment>::Alloc( x * y * z );
679 Parent::SetSize( x, y, z );
680 Parent::SetBounds( 0, x * y * z - 1 );
682 template<typename T, int Dim, int alignment>
683 inline void AliHLTResizableArray<T, Dim, alignment>::Resize( int x )
685 ALIHLTARRAY_STATIC_ASSERT( Dim == 1, AliHLTResizableArray1_resize_used_with_incorrect_dimension );
686 AliHLTInternal::Allocator<T, alignment>::Free( Parent::fData, Parent::fSize );
687 Parent::fData = ( x == 0 ) ? 0 : AliHLTInternal::Allocator<T, alignment>::Alloc( x );
688 Parent::SetSize( x, 0, 0 );
689 Parent::SetBounds( 0, x - 1 );
691 template<typename T, int Dim, int alignment>
692 inline void AliHLTResizableArray<T, Dim, alignment>::Resize( int x, int y )
694 ALIHLTARRAY_STATIC_ASSERT( Dim == 2, AliHLTResizableArray2_resize_used_with_incorrect_dimension );
695 AliHLTInternal::Allocator<T, alignment>::Free( Parent::fData, Parent::fSize );
696 Parent::fData = ( x == 0 ) ? 0 : AliHLTInternal::Allocator<T, alignment>::Alloc( x * y );
697 Parent::SetSize( x, y, 0 );
698 Parent::SetBounds( 0, x * y - 1 );
700 template<typename T, int Dim, int alignment>
701 inline void AliHLTResizableArray<T, Dim, alignment>::Resize( int x, int y, int z )
703 ALIHLTARRAY_STATIC_ASSERT( Dim == 3, AliHLTResizableArray3_resize_used_with_incorrect_dimension );
704 AliHLTInternal::Allocator<T, alignment>::Free( Parent::fData, Parent::fSize );
705 Parent::fData = ( x == 0 ) ? 0 : AliHLTInternal::Allocator<T, alignment>::Alloc( x * y * z );
706 Parent::SetSize( x, y, z );
707 Parent::SetBounds( 0, x * y * z - 1 );
712 #endif // ALIHLTARRAY_H