1 // ****************************************************************************
2 // * This file is property of and copyright by the ALICE HLT Project *
3 // * ALICE Experiment at CERN, All rights reserved. *
5 // * Copyright (C) 2009 Matthias Kretz <kretz@kde.org> *
6 // * for The ALICE HLT Project. *
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 // ****************************************************************************
19 * \author Matthias Kretz <kretz@kde.org>
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.
34 #if (defined(__MMX__) || defined(__SSE__))
39 #else // not gcc, assume it can use _mm_malloc since it supports MMX/SSE
45 #include <mm_malloc.h>
51 AliHLTFullyCacheLineAligned = -1
54 #if defined(__CUDACC__) & 0
55 #define ALIHLTARRAY_STATIC_ASSERT(a, b)
56 #define ALIHLTARRAY_STATIC_ASSERT_NC(a, b)
58 namespace AliHLTArrayInternal
60 template<bool> class STATIC_ASSERT_FAILURE;
61 template<> class STATIC_ASSERT_FAILURE<true> {};
64 #define ALIHLTARRAY_STATIC_ASSERT_CONCAT_HELPER(a, b) a##b
65 #define ALIHLTARRAY_STATIC_ASSERT_CONCAT(a, b) ALIHLTARRAY_STATIC_ASSERT_CONCAT_HELPER(a, b)
66 #define ALIHLTARRAY_STATIC_ASSERT_NC(cond, msg) \
67 typedef AliHLTArrayInternal::STATIC_ASSERT_FAILURE<cond> ALIHLTARRAY_STATIC_ASSERT_CONCAT(_STATIC_ASSERTION_FAILED_##msg, __LINE__); \
68 ALIHLTARRAY_STATIC_ASSERT_CONCAT(_STATIC_ASSERTION_FAILED_##msg, __LINE__) Error_##msg
69 #define ALIHLTARRAY_STATIC_ASSERT(cond, msg) ALIHLTARRAY_STATIC_ASSERT_NC(cond, msg); (void) Error_##msg
72 template<typename T, int Dim> class AliHLTArray;
74 namespace AliHLTInternal
76 template<unsigned int Size> struct Padding { char fPadding[Size]; };
77 template<> struct Padding<0> {};
78 template<typename T> struct CacheLineSizeHelperData { T fData; };
79 template<typename T> struct CacheLineSizeHelperEnums {
82 MaskedSize = sizeof( T ) & ( CacheLineSize - 1 ),
83 RequiredSize = MaskedSize == 0 ? sizeof( T ) : sizeof( T ) + CacheLineSize - MaskedSize,
84 PaddingSize = RequiredSize - sizeof( T )
87 template<typename T> class CacheLineSizeHelper : private CacheLineSizeHelperData<T>, private Padding<CacheLineSizeHelperEnums<T>::PaddingSize>
90 operator T &() { return CacheLineSizeHelperData<T>::fData; }
91 operator const T &() const { return CacheLineSizeHelperData<T>::fData; }
92 //const T &operator=( const T &rhs ) { CacheLineSizeHelperData<T>::fData = rhs; }
96 template<typename T, int alignment> struct TypeForAlignmentHelper { typedef T Type; };
97 template<typename T> struct TypeForAlignmentHelper<T, AliHLTFullyCacheLineAligned> { typedef CacheLineSizeHelper<T> Type; };
100 // The ArrayBoundsCheck and Allocator classes implement a virtual destructor only in order to
101 // silence the -Weffc++ warning. It really is not required for these classes to have a virtual
102 // dtor since polymorphism is not used (AliHLTResizableArray and AliHLTFixedArray are allocated on
103 // the stack only). The virtual dtor only adds an unnecessary vtable to the code.
104 #ifndef ENABLE_ARRAY_BOUNDS_CHECKING
106 * no-op implementation that for no-bounds-checking
108 class ArrayBoundsCheck
111 virtual inline ~ArrayBoundsCheck() {}
112 inline bool IsInBounds( int ) const { return true; }
113 inline void SetBounds( int, int ) {}
114 inline void MoveBounds( int ) {}
115 inline void ReinterpretCast( const ArrayBoundsCheck &, int, int ) {}
117 #define BOUNDS_CHECK(x, y)
120 * implementation for bounds-checking.
122 class ArrayBoundsCheck
125 virtual inline ~ArrayBoundsCheck() {}
127 * checks whether the given offset is valid
129 inline bool IsInBounds( int x ) const;
131 * set the start and end offsets that are still valid
133 inline void SetBounds( int start, int end ) { fStart = start; fEnd = end; }
135 * move the start and end offsets by the same amount
137 inline void MoveBounds( int d ) { fStart += d; fEnd += d; }
139 inline void ReinterpretCast( const ArrayBoundsCheck &other, int sizeofOld, int sizeofNew ) {
140 fStart = other.fStart * sizeofNew / sizeofOld;
141 fEnd = other.fEnd * sizeofNew / sizeofOld;
148 #define BOUNDS_CHECK(x, y) if (AliHLTInternal::ArrayBoundsCheck::IsInBounds(x)) {} else return y
150 template<typename T, int alignment> class Allocator
154 static inline T *Alloc( int s ) { T *p = reinterpret_cast<T *>( _mm_malloc( s * sizeof( T ), alignment ) ); return new( p ) T[s]; }
155 static inline void Free( T *const p, int size ) {
156 for ( int i = 0; i < size; ++i ) {
162 static inline T *Alloc( int s ) { T *p; posix_memalign( &p, alignment, s * sizeof( T ) ); return new( p ) T[s]; }
163 static inline void Free( T *const p, int size ) {
164 for ( int i = 0; i < size; ++i ) {
171 template<typename T> class Allocator<T, AliHLTFullyCacheLineAligned>
174 typedef CacheLineSizeHelper<T> T2;
176 static inline T2 *Alloc( int s ) { T2 *p = reinterpret_cast<T2 *>( _mm_malloc( s * sizeof( T2 ), 128 ) ); return new( p ) T2[s]; }
177 static inline void Free( T2 *const p, int size ) {
178 for ( int i = 0; i < size; ++i ) {
184 static inline T2 *Alloc( int s ) { T2 *p; posix_memalign( &p, 128, s * sizeof( T2 ) ); return new( p ) T2[s]; }
185 static inline void Free( T2 *const p, int size ) {
186 for ( int i = 0; i < size; ++i ) {
193 template<typename T> class Allocator<T, 0>
196 static inline T *Alloc( int s ) { return new T[s]; }
197 static inline void Free( const T *const p, int ) { delete[] p; }
200 template<typename T> struct ReturnTypeHelper { typedef T Type; };
201 template<typename T> struct ReturnTypeHelper<CacheLineSizeHelper<T> > { typedef T Type; };
203 * Array base class for dimension dependent behavior
205 template<typename T, int Dim> class ArrayBase;
208 * 1-dim arrays only have operator[]
211 class ArrayBase<T, 1> : public ArrayBoundsCheck
213 friend class ArrayBase<T, 2>;
215 ArrayBase() : fData( 0 ), fSize( 0 ) {} // XXX really shouldn't be done. But -Weffc++ wants it so
216 ArrayBase( const ArrayBase &rhs ) : ArrayBoundsCheck( rhs ), fData( rhs.fData ), fSize( rhs.fSize ) {} // XXX
217 ArrayBase &operator=( const ArrayBase &rhs ) { ArrayBoundsCheck::operator=( rhs ); fData = rhs.fData; return *this; } // XXX
218 typedef typename ReturnTypeHelper<T>::Type R;
220 * return a reference to the value at the given index
222 inline R &operator[]( int x ) { BOUNDS_CHECK( x, fData[0] ); return fData[x]; }
224 * return a const reference to the value at the given index
226 inline const R &operator[]( int x ) const { BOUNDS_CHECK( x, fData[0] ); return fData[x]; }
231 inline void SetSize( int x, int, int ) { fSize = x; }
235 * 2-dim arrays should use operator(int, int)
236 * operator[] can be used to return a 1-dim array
239 class ArrayBase<T, 2> : public ArrayBoundsCheck
241 friend class ArrayBase<T, 3>;
243 ArrayBase() : fData( 0 ), fSize( 0 ), fStride( 0 ) {} // XXX really shouldn't be done. But -Weffc++ wants it so
244 ArrayBase( const ArrayBase &rhs ) : ArrayBoundsCheck( rhs ), fData( rhs.fData ), fSize( rhs.fSize ), fStride( rhs.fStride ) {} // XXX
245 ArrayBase &operator=( const ArrayBase &rhs ) { ArrayBoundsCheck::operator=( rhs ); fData = rhs.fData; fSize = rhs.fSize; fStride = rhs.fStride; return *this; } // XXX
246 typedef typename ReturnTypeHelper<T>::Type R;
248 * return a reference to the value at the given indexes
250 inline R &operator()( int x, int y ) { BOUNDS_CHECK( x * fStride + y, fData[0] ); return fData[x * fStride + y]; }
252 * return a const reference to the value at the given indexes
254 inline const R &operator()( int x, int y ) const { BOUNDS_CHECK( x * fStride + y, fData[0] ); return fData[x * fStride + y]; }
256 * return a 1-dim array at the given index. This makes it behave like a 2-dim C-Array.
258 inline AliHLTArray<T, 1> operator[]( int x );
260 * return a const 1-dim array at the given index. This makes it behave like a 2-dim C-Array.
262 inline const AliHLTArray<T, 1> operator[]( int x ) const;
268 inline void SetSize( int x, int y, int ) { fStride = y; fSize = x * y; }
272 * 3-dim arrays should use operator(int, int, int)
273 * operator[] can be used to return a 2-dim array
276 class ArrayBase<T, 3> : public ArrayBoundsCheck
279 ArrayBase() : fData( 0 ), fSize( 0 ), fStrideX( 0 ), fStrideY( 0 ) {} // XXX really shouldn't be done. But -Weffc++ wants it so
280 ArrayBase( const ArrayBase &rhs ) : ArrayBoundsCheck( rhs ), fData( rhs.fData ), fSize( rhs.fSize ), fStrideX( rhs.fStrideX ), fStrideY( rhs.fStrideY ) {} // XXX
281 ArrayBase &operator=( const ArrayBase &rhs ) { ArrayBoundsCheck::operator=( rhs ); fData = rhs.fData; fSize = rhs.fSize; fStrideX = rhs.fStrideX; fStrideY = rhs.fStrideY; return *this; } // XXX
282 typedef typename ReturnTypeHelper<T>::Type R;
284 * return a reference to the value at the given indexes
286 inline R &operator()( int x, int y, int z );
288 * return a const reference to the value at the given indexes
290 inline const R &operator()( int x, int y, int z ) const;
292 * return a 2-dim array at the given index. This makes it behave like a 3-dim C-Array.
294 inline AliHLTArray<T, 2> operator[]( int x );
296 * return a const 2-dim array at the given index. This makes it behave like a 3-dim C-Array.
298 inline const AliHLTArray<T, 2> operator[]( int x ) const;
305 inline void SetSize( int x, int y, int z ) { fStrideX = y * z; fStrideY = z; fSize = fStrideX * x; }
308 template<typename T, unsigned int Size, int _alignment> class AlignedData
311 T *ConstructAlignedData() {
312 const int offset = reinterpret_cast<unsigned long>( &fUnalignedArray[0] ) & ( Alignment - 1 );
313 void *mem = &fUnalignedArray[0] + ( Alignment - offset );
314 return new( mem ) T[Size];
317 const int offset = reinterpret_cast<unsigned long>( &fUnalignedArray[0] ) & ( Alignment - 1 );
318 T *mem = reinterpret_cast<T *>( &fUnalignedArray[0] + ( Alignment - offset ) );
319 for ( unsigned int i = 0; i < Size; ++i ) {
325 Alignment = _alignment == AliHLTFullyCacheLineAligned ? 128 : _alignment,
326 PaddedSize = Size * sizeof( T ) + Alignment
328 ALIHLTARRAY_STATIC_ASSERT_NC( ( Alignment & ( Alignment - 1 ) ) == 0, alignment_needs_to_be_a_multiple_of_2 );
330 char fUnalignedArray[PaddedSize];
332 template<typename T, unsigned int Size> class AlignedData<T, Size, 0>
335 T *ConstructAlignedData() { return &fArray[0]; }
339 } // namespace AliHLTInternal
342 * C-Array like class with the dimension dependent behavior defined in the ArrayBase class
344 template < typename T, int Dim = 1 >
345 class AliHLTArray : public AliHLTInternal::ArrayBase<T, Dim>
348 typedef AliHLTInternal::ArrayBase<T, Dim> Parent;
351 * Returns the number of elements in the array. If it is a multi-dimensional array the size is
352 * the multiplication of the dimensions ( e.g. a 10 x 20 array returns 200 as its size ).
354 inline int Size() const { return Parent::fSize; }
357 * allows you to check for validity of the array by casting to bool
359 inline operator bool() const { return Parent::fData != 0; }
361 * allows you to check for validity of the array
363 inline bool IsValid() const { return Parent::fData != 0; }
366 * returns a reference to the data at index 0
368 inline T &operator*() { BOUNDS_CHECK( 0, Parent::fData[0] ); return *Parent::fData; }
370 * returns a const reference to the data at index 0
372 inline const T &operator*() const { BOUNDS_CHECK( 0, Parent::fData[0] ); return *Parent::fData; }
375 * returns a pointer to the data
376 * This circumvents bounds checking so it should not be used.
378 inline T *Data() { return Parent::fData; }
380 * returns a const pointer to the data
381 * This circumvents bounds checking so it should not be used.
383 inline const T *Data() const { return Parent::fData; }
386 * moves the array base pointer so that the data that was once at index 0 will then be at index -x
388 inline AliHLTArray operator+( int x ) const;
390 * moves the array base pointer so that the data that was once at index 0 will then be at index x
392 inline AliHLTArray operator-( int x ) const;
394 #ifndef HLTCA_GPUCODE
395 template<typename Other> inline AliHLTArray<Other, Dim> ReinterpretCast() const {
396 AliHLTArray<Other, Dim> r;
397 r.fData = reinterpret_cast<Other *>( Parent::fData );
398 r.ReinterpretCast( *this, sizeof( T ), sizeof( Other ) );
404 * Owns the data. When it goes out of scope the data is freed.
406 * The memory is allocated on the heap.
408 * Instantiate this class on the stack. Allocation on the heap is disallowed.
410 * \param T type of the entries in the array.
411 * \param Dim selects the operator[]/operator() behavior it should have. I.e. makes it behave like a
412 * 1-, 2- or 3-dim array. (defaults to 1)
413 * \param alignment Defaults to 0 (default alignment). Other valid values are any multiples of 2.
414 * This is especially useful for aligning data for SIMD vectors.
416 * \warning when using alignment the type T may not have a destructor (well it may, but it won't be
421 * void init( AliHLTArray<int> a, int size )
423 * for ( int i = 0; i < size; ++i ) {
429 * AliHLTResizableArray<int> foo( size ); // notice that size doesn't have to be a constant like it
430 * // has to be for C-Arrays in ISO C++
436 template < typename T, int Dim = 1, int alignment = 0 >
437 class AliHLTResizableArray : public AliHLTArray<typename AliHLTInternal::TypeForAlignmentHelper<T, alignment>::Type, Dim>
440 typedef typename AliHLTInternal::TypeForAlignmentHelper<T, alignment>::Type T2;
441 typedef AliHLTInternal::ArrayBase<T2, Dim> Parent;
443 * does not allocate any memory
445 inline AliHLTResizableArray();
447 * use for 1-dim arrays: allocates x * sizeof(T) bytes for the array
449 inline AliHLTResizableArray( int x );
451 * use for 2-dim arrays: allocates x * y * sizeof(T) bytes for the array
453 inline AliHLTResizableArray( int x, int y );
455 * use for 3-dim arrays: allocates x * y * z * sizeof(T) bytes for the array
457 inline AliHLTResizableArray( int x, int y, int z );
462 inline ~AliHLTResizableArray() { AliHLTInternal::Allocator<T, alignment>::Free( Parent::fData, Parent::fSize ); }
465 * use for 1-dim arrays: resizes the memory for the array to x * sizeof(T) bytes.
467 * \warning this does not keep your previous data. If you were looking for this you probably
468 * want to use std::vector instead.
470 inline void Resize( int x );
472 * use for 2-dim arrays: resizes the memory for the array to x * y * sizeof(T) bytes.
474 * \warning this does not keep your previous data. If you were looking for this you probably
475 * want to use std::vector instead.
477 inline void Resize( int x, int y );
479 * use for 3-dim arrays: resizes the memory for the array to x * y * z * sizeof(T) bytes.
481 * \warning this does not keep your previous data. If you were looking for this you probably
482 * want to use std::vector instead.
484 inline void Resize( int x, int y, int z );
487 // disable allocation on the heap
488 void *operator new( size_t );
491 AliHLTResizableArray( const AliHLTResizableArray & );
492 AliHLTResizableArray &operator=( const AliHLTResizableArray & );
495 template < unsigned int x, unsigned int y = 0, unsigned int z = 0 > class AliHLTArraySize
499 Size = y == 0 ? x : ( z == 0 ? x * y : x * y * z ),
500 Dim = y == 0 ? 1 : ( z == 0 ? 2 : 3 ),
506 * Owns the data. When it goes out of scope the data is freed.
508 * The memory is allocated on the stack.
510 * Instantiate this class on the stack.
512 * \param T type of the entries in the array.
513 * \param Size number of entries in the array.
514 * \param Dim selects the operator[]/operator() behavior it should have. I.e. makes it behave like a
515 * 1-, 2- or 3-dim array. (defaults to 1)
517 template < typename T, typename Size, int alignment = 0 >
518 class AliHLTFixedArray : public AliHLTArray<typename AliHLTInternal::TypeForAlignmentHelper<T, alignment>::Type, Size::Dim>
521 typedef typename AliHLTInternal::TypeForAlignmentHelper<T, alignment>::Type T2;
522 typedef AliHLTInternal::ArrayBase<T2, Size::Dim> Parent;
523 inline AliHLTFixedArray() {
524 Parent::fData = fFixedArray.ConstructAlignedData();
525 Parent::SetBounds( 0, Size::Size - 1 );
526 SetSize( Size::X, Size::Y, Size::Z );
530 AliHLTInternal::AlignedData<typename AliHLTInternal::TypeForAlignmentHelper<T, alignment>::Type, Size::Size, alignment> fFixedArray;
532 // disable allocation on the heap
533 void *operator new( size_t );
538 AliHLTFixedArray( const AliHLTFixedArray & );
539 AliHLTFixedArray &operator=( const AliHLTFixedArray & );
546 ////////////////////////
547 //// implementation ////
548 ////////////////////////
553 namespace AliHLTInternal
555 #ifdef ENABLE_ARRAY_BOUNDS_CHECKING
556 inline bool ArrayBoundsCheck::IsInBounds( int x ) const
558 assert( x >= fStart );
560 return ( x >= fStart && x <= fEnd );
565 inline AliHLTArray<T, 1> ArrayBase<T, 2>::operator[]( int x )
568 typedef AliHLTArray<T, 1> AT1;
569 BOUNDS_CHECK( x, AT1() );
572 a.ArrayBoundsCheck::operator=( *this );
578 inline const AliHLTArray<T, 1> ArrayBase<T, 2>::operator[]( int x ) const
581 typedef AliHLTArray<T, 1> AT1;
582 BOUNDS_CHECK( x, AT1() );
585 a.ArrayBoundsCheck::operator=( *this );
591 inline typename AliHLTInternal::ReturnTypeHelper<T>::Type &ArrayBase<T, 3>::operator()( int x, int y, int z )
593 BOUNDS_CHECK( x * fStrideX + y + fStrideY + z, fData[0] );
594 return fData[x * fStrideX + y + fStrideY + z];
597 inline const typename AliHLTInternal::ReturnTypeHelper<T>::Type &ArrayBase<T, 3>::operator()( int x, int y, int z ) const
599 BOUNDS_CHECK( x * fStrideX + y + fStrideY + z, fData[0] );
600 return fData[x * fStrideX + y + fStrideY + z];
603 inline AliHLTArray<T, 2> ArrayBase<T, 3>::operator[]( int x )
606 typedef AliHLTArray<T, 2> AT2;
607 BOUNDS_CHECK( x, AT2() );
610 a.fStride = fStrideY;
611 a.ArrayBoundsCheck::operator=( *this );
616 inline const AliHLTArray<T, 2> ArrayBase<T, 3>::operator[]( int x ) const
619 typedef AliHLTArray<T, 2> AT2;
620 BOUNDS_CHECK( x, AT2() );
623 a.fStride = fStrideY;
624 a.ArrayBoundsCheck::operator=( *this );
628 } // namespace AliHLTInternal
631 template<typename T, int Dim>
632 inline AliHLTArray<T, Dim> AliHLTArray<T, Dim>::operator+( int x ) const
634 AliHLTArray<T, Dim> r( *this );
639 template<typename T, int Dim>
640 inline AliHLTArray<T, Dim> AliHLTArray<T, Dim>::operator-( int x ) const
642 AliHLTArray<T, Dim> r( *this );
648 template<typename T, int Dim, int alignment>
649 inline AliHLTResizableArray<T, Dim, alignment>::AliHLTResizableArray()
652 Parent::SetSize( 0, 0, 0 );
653 Parent::SetBounds( 0, -1 );
655 template<typename T, int Dim, int alignment>
656 inline AliHLTResizableArray<T, Dim, alignment>::AliHLTResizableArray( int x )
658 ALIHLTARRAY_STATIC_ASSERT( Dim == 1, AliHLTResizableArray1_used_with_incorrect_dimension );
659 Parent::fData = AliHLTInternal::Allocator<T, alignment>::Alloc( x );
660 Parent::SetSize( x, 0, 0 );
661 Parent::SetBounds( 0, x - 1 );
663 template<typename T, int Dim, int alignment>
664 inline AliHLTResizableArray<T, Dim, alignment>::AliHLTResizableArray( int x, int y )
666 ALIHLTARRAY_STATIC_ASSERT( Dim == 2, AliHLTResizableArray2_used_with_incorrect_dimension );
667 Parent::fData = AliHLTInternal::Allocator<T, alignment>::Alloc( x * y );
668 Parent::SetSize( x, y, 0 );
669 Parent::SetBounds( 0, x * y - 1 );
671 template<typename T, int Dim, int alignment>
672 inline AliHLTResizableArray<T, Dim, alignment>::AliHLTResizableArray( int x, int y, int z )
674 ALIHLTARRAY_STATIC_ASSERT( Dim == 3, AliHLTResizableArray3_used_with_incorrect_dimension );
675 Parent::fData = AliHLTInternal::Allocator<T, alignment>::Alloc( x * y * z );
676 Parent::SetSize( x, y, z );
677 Parent::SetBounds( 0, x * y * z - 1 );
679 template<typename T, int Dim, int alignment>
680 inline void AliHLTResizableArray<T, Dim, alignment>::Resize( int x )
682 ALIHLTARRAY_STATIC_ASSERT( Dim == 1, AliHLTResizableArray1_resize_used_with_incorrect_dimension );
683 AliHLTInternal::Allocator<T, alignment>::Free( Parent::fData, Parent::fSize );
684 Parent::fData = ( x == 0 ) ? 0 : AliHLTInternal::Allocator<T, alignment>::Alloc( x );
685 Parent::SetSize( x, 0, 0 );
686 Parent::SetBounds( 0, x - 1 );
688 template<typename T, int Dim, int alignment>
689 inline void AliHLTResizableArray<T, Dim, alignment>::Resize( int x, int y )
691 ALIHLTARRAY_STATIC_ASSERT( Dim == 2, AliHLTResizableArray2_resize_used_with_incorrect_dimension );
692 AliHLTInternal::Allocator<T, alignment>::Free( Parent::fData, Parent::fSize );
693 Parent::fData = ( x == 0 ) ? 0 : AliHLTInternal::Allocator<T, alignment>::Alloc( x * y );
694 Parent::SetSize( x, y, 0 );
695 Parent::SetBounds( 0, x * y - 1 );
697 template<typename T, int Dim, int alignment>
698 inline void AliHLTResizableArray<T, Dim, alignment>::Resize( int x, int y, int z )
700 ALIHLTARRAY_STATIC_ASSERT( Dim == 3, AliHLTResizableArray3_resize_used_with_incorrect_dimension );
701 AliHLTInternal::Allocator<T, alignment>::Free( Parent::fData, Parent::fSize );
702 Parent::fData = ( x == 0 ) ? 0 : AliHLTInternal::Allocator<T, alignment>::Alloc( x * y * z );
703 Parent::SetSize( x, y, z );
704 Parent::SetBounds( 0, x * y * z - 1 );
709 #endif // ALIHLTARRAY_H