]> git.uio.no Git - u/mrichter/AliRoot.git/blame - HLT/BASE/AliHLTArray.h
minor coverity defect: added protection for self-assignment
[u/mrichter/AliRoot.git] / HLT / BASE / AliHLTArray.h
CommitLineData
cf9d96e4 1//-*- Mode: C++ -*-
2// $Id$
3
e18739d0 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// ****************************************************************************
30122bae 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
84e050b7 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
30122bae 48#include <mm_malloc.h>
49#else
50#include <cstdlib>
51#endif
52
e18739d0 53enum {
dd5579d1 54 kAliHLTFullyCacheLineAligned = -1
e18739d0 55};
56
9e2dadc1 57#if defined(__CUDACC__) & 0
58#define ALIHLTARRAY_STATIC_ASSERT(a, b)
59#define ALIHLTARRAY_STATIC_ASSERT_NC(a, b)
60#else
30122bae 61namespace AliHLTArrayInternal
62{
5e1afc14 63 template<bool> class AliHLTStaticAssertFailure;
64 template<> class AliHLTStaticAssertFailure<true> {};
30122bae 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)
e18739d0 69#define ALIHLTARRAY_STATIC_ASSERT_NC(cond, msg) \
5e1afc14 70 typedef AliHLTArrayInternal::AliHLTStaticAssertFailure<cond> ALIHLTARRAY_STATIC_ASSERT_CONCAT(_STATIC_ASSERTION_FAILED_##msg, __LINE__); \
e18739d0 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
9e2dadc1 73#endif
30122bae 74
75template<typename T, int Dim> class AliHLTArray;
76
77namespace AliHLTInternal
78{
e18739d0 79 template<unsigned int Size> struct Padding { char fPadding[Size]; };
80 template<> struct Padding<0> {};
5e1afc14 81 template<typename T> struct AliHLTCacheLineSizeHelperData { T fData; };
82 template<typename T> struct AliHLTCacheLineSizeHelperEnums {
e18739d0 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 };
5e1afc14 90 template<typename T> class AliCacheLineSizeHelper : private AliHLTCacheLineSizeHelperData<T>, private Padding<AliHLTCacheLineSizeHelperEnums<T>::PaddingSize>
e18739d0 91 {
92 public:
5e1afc14 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; }
e18739d0 96
97 private:
98 };
99 template<typename T, int alignment> struct TypeForAlignmentHelper { typedef T Type; };
dd5579d1 100 template<typename T> struct TypeForAlignmentHelper<T, kAliHLTFullyCacheLineAligned> { typedef AliCacheLineSizeHelper<T> Type; };
e18739d0 101
30122bae 102 // XXX
dd5579d1 103 // The AliArrayBoundsCheck and AliAllocator classes implement a virtual destructor only in order to
e18739d0 104 // silence the -Weffc++ warning. It really is not required for these classes to have a virtual
30122bae 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 */
dd5579d1 111 class AliArrayBoundsCheck
30122bae 112 {
113 protected:
dd5579d1 114 virtual inline ~AliArrayBoundsCheck() {}
30122bae 115 inline bool IsInBounds( int ) const { return true; }
5e1afc14 116 inline void SetBounds( int, int ) const {}
117 inline void MoveBounds( int ) const {}
118 inline void ReinterpretCast( const AliArrayBoundsCheck &, int, int ) const {}
30122bae 119 };
120#define BOUNDS_CHECK(x, y)
121#else
122 /**
123 * implementation for bounds-checking.
124 */
dd5579d1 125 class AliArrayBoundsCheck
30122bae 126 {
127 protected:
dd5579d1 128 virtual inline ~AliArrayBoundsCheck() {}
30122bae 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
dd5579d1 142 inline void ReinterpretCast( const AliArrayBoundsCheck &other, int sizeofOld, int sizeofNew ) {
e18739d0 143 fStart = other.fStart * sizeofNew / sizeofOld;
144 fEnd = other.fEnd * sizeofNew / sizeofOld;
145 }
146
30122bae 147 private:
cf9d96e4 148 int fStart; // start
149 int fEnd; // end
30122bae 150 };
dd5579d1 151#define BOUNDS_CHECK(x, y) if (AliHLTInternal::AliArrayBoundsCheck::IsInBounds(x)) {} else return y
30122bae 152#endif
dd5579d1 153 template<typename T, int alignment> class AliAllocator
30122bae 154 {
e18739d0 155 public:
84e050b7 156#ifdef USE_MM_MALLOC
30122bae 157 static inline T *Alloc( int s ) { T *p = reinterpret_cast<T *>( _mm_malloc( s * sizeof( T ), alignment ) ); return new( p ) T[s]; }
e18739d0 158 static inline void Free( T *const p, int size ) {
5e1afc14 159 for ( int i = 0; i < size; ++i ) p[i].~T();
e18739d0 160 _mm_free( p );
161 }
30122bae 162#else
163 static inline T *Alloc( int s ) { T *p; posix_memalign( &p, alignment, s * sizeof( T ) ); return new( p ) T[s]; }
e18739d0 164 static inline void Free( T *const p, int size ) {
5e1afc14 165 for ( int i = 0; i < size; ++i ) p[i].~T();
e18739d0 166 std::free( p );
167 }
168#endif
169 };
dd5579d1 170 template<typename T> class AliAllocator<T, kAliHLTFullyCacheLineAligned>
e18739d0 171 {
172 public:
dd5579d1 173 typedef AliCacheLineSizeHelper<T> T2;
e18739d0 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 ) {
5e1afc14 177 for ( int i = 0; i < size; ++i ) p[i].~T2();
e18739d0 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 ) {
5e1afc14 183 for ( int i = 0; i < size; ++i ) p[i].~T2();
e18739d0 184 std::free( p );
185 }
30122bae 186#endif
187 };
dd5579d1 188 template<typename T> class AliAllocator<T, 0>
30122bae 189 {
e18739d0 190 public:
30122bae 191 static inline T *Alloc( int s ) { return new T[s]; }
e18739d0 192 static inline void Free( const T *const p, int ) { delete[] p; }
30122bae 193 };
e18739d0 194
195 template<typename T> struct ReturnTypeHelper { typedef T Type; };
dd5579d1 196 template<typename T> struct ReturnTypeHelper<AliCacheLineSizeHelper<T> > { typedef T Type; };
30122bae 197 /**
198 * Array base class for dimension dependent behavior
199 */
5e1afc14 200 template<typename T, int Dim> class AliHLTArrayBase;
30122bae 201
202 /**
203 * 1-dim arrays only have operator[]
204 */
205 template<typename T>
5e1afc14 206 class AliHLTArrayBase<T, 1> : public AliArrayBoundsCheck
30122bae 207 {
5e1afc14 208 friend class AliHLTArrayBase<T, 2>; // declare friend
30122bae 209 public:
5e1afc14 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
e18739d0 213 typedef typename ReturnTypeHelper<T>::Type R;
30122bae 214 /**
215 * return a reference to the value at the given index
216 */
e18739d0 217 inline R &operator[]( int x ) { BOUNDS_CHECK( x, fData[0] ); return fData[x]; }
30122bae 218 /**
219 * return a const reference to the value at the given index
220 */
e18739d0 221 inline const R &operator[]( int x ) const { BOUNDS_CHECK( x, fData[0] ); return fData[x]; }
30122bae 222
223 protected:
cf9d96e4 224 T *fData; // actual data
225 int fSize; // data size
e18739d0 226 inline void SetSize( int x, int, int ) { fSize = x; }
30122bae 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>
5e1afc14 234 class AliHLTArrayBase<T, 2> : public AliArrayBoundsCheck
30122bae 235 {
5e1afc14 236 friend class AliHLTArrayBase<T, 3>; // declare friend
30122bae 237 public:
5e1afc14 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
e18739d0 241 typedef typename ReturnTypeHelper<T>::Type R;
30122bae 242 /**
243 * return a reference to the value at the given indexes
244 */
e18739d0 245 inline R &operator()( int x, int y ) { BOUNDS_CHECK( x * fStride + y, fData[0] ); return fData[x * fStride + y]; }
30122bae 246 /**
247 * return a const reference to the value at the given indexes
248 */
e18739d0 249 inline const R &operator()( int x, int y ) const { BOUNDS_CHECK( x * fStride + y, fData[0] ); return fData[x * fStride + y]; }
30122bae 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:
cf9d96e4 260 T *fData; // actual data
261 int fSize; // data size
dd5579d1 262 int fStride; // stride
e18739d0 263 inline void SetSize( int x, int y, int ) { fStride = y; fSize = x * y; }
30122bae 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>
5e1afc14 271 class AliHLTArrayBase<T, 3> : public AliArrayBoundsCheck
30122bae 272 {
273 public:
5e1afc14 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
e2b8fd2d 277 // Stopped working on GCC 4.5.0
278 //typedef typename ReturnTypeHelper<T>::Type R;
30122bae 279 /**
280 * return a reference to the value at the given indexes
281 */
e2b8fd2d 282 inline typename ReturnTypeHelper<T>::Type &operator()( int x, int y, int z );
30122bae 283 /**
284 * return a const reference to the value at the given indexes
285 */
e2b8fd2d 286 inline const typename ReturnTypeHelper<T>::Type &operator()( int x, int y, int z ) const;
30122bae 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:
cf9d96e4 297 T *fData; // actual data
298 int fSize; // data size
dd5579d1 299 int fStrideX; // stride X
300 int fStrideY; // stride Y
e18739d0 301 inline void SetSize( int x, int y, int z ) { fStrideX = y * z; fStrideY = z; fSize = fStrideX * x; }
30122bae 302 };
303
e18739d0 304 template<typename T, unsigned int Size, int _alignment> class AlignedData
30122bae 305 {
e18739d0 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 ) );
5e1afc14 315 for ( unsigned int i = 0; i < Size; ++i ) mem[i].~T();
e18739d0 316 }
317 private:
318 enum {
dd5579d1 319 Alignment = _alignment == kAliHLTFullyCacheLineAligned ? 128 : _alignment,
e18739d0 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
dd5579d1 324 char fUnalignedArray[PaddedSize]; // data array
30122bae 325 };
e18739d0 326 template<typename T, unsigned int Size> class AlignedData<T, Size, 0>
30122bae 327 {
e18739d0 328 public:
329 T *ConstructAlignedData() { return &fArray[0]; }
330 private:
dd5579d1 331 T fArray[Size]; // data array
30122bae 332 };
30122bae 333} // namespace AliHLTInternal
334
335/**
5e1afc14 336 * C-Array like class with the dimension dependent behavior defined in the AliHLTArrayBase class
30122bae 337 */
338template < typename T, int Dim = 1 >
5e1afc14 339class AliHLTArray : public AliHLTInternal::AliHLTArrayBase<T, Dim>
30122bae 340{
341 public:
5e1afc14 342 typedef AliHLTInternal::AliHLTArrayBase<T, Dim> Parent;
e18739d0 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
30122bae 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;
e18739d0 387
9e2dadc1 388#ifndef HLTCA_GPUCODE
e18739d0 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 }
9e2dadc1 394#endif
30122bae 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 */
430template < typename T, int Dim = 1, int alignment = 0 >
e18739d0 431class AliHLTResizableArray : public AliHLTArray<typename AliHLTInternal::TypeForAlignmentHelper<T, alignment>::Type, Dim>
30122bae 432{
433 public:
e18739d0 434 typedef typename AliHLTInternal::TypeForAlignmentHelper<T, alignment>::Type T2;
5e1afc14 435 typedef AliHLTInternal::AliHLTArrayBase<T2, Dim> Parent;
30122bae 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 */
dd5579d1 456 inline ~AliHLTResizableArray() { AliHLTInternal::AliAllocator<T, alignment>::Free( Parent::fData, Parent::fSize ); }
30122bae 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
e18739d0 489template < 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
30122bae 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 */
e18739d0 511template < typename T, typename Size, int alignment = 0 >
512class AliHLTFixedArray : public AliHLTArray<typename AliHLTInternal::TypeForAlignmentHelper<T, alignment>::Type, Size::Dim>
30122bae 513{
514 public:
e18739d0 515 typedef typename AliHLTInternal::TypeForAlignmentHelper<T, alignment>::Type T2;
5e1afc14 516 typedef AliHLTInternal::AliHLTArrayBase<T2, Size::Dim> Parent;
e18739d0 517 inline AliHLTFixedArray() {
518 Parent::fData = fFixedArray.ConstructAlignedData();
519 Parent::SetBounds( 0, Size::Size - 1 );
520 SetSize( Size::X, Size::Y, Size::Z );
521 }
30122bae 522
523 private:
dd5579d1 524 AliHLTInternal::AlignedData<typename AliHLTInternal::TypeForAlignmentHelper<T, alignment>::Type, Size::Size, alignment> fFixedArray; // data array
e18739d0 525
30122bae 526 // disable allocation on the heap
527 void *operator new( size_t );
528
30122bae 529 // disable copy
9e2dadc1 530#ifdef HLTCA_GPUCODE
531#else
30122bae 532 AliHLTFixedArray( const AliHLTFixedArray & );
533 AliHLTFixedArray &operator=( const AliHLTFixedArray & );
9e2dadc1 534#endif
30122bae 535};
536
537
538
539
30122bae 540////////////////////////
541//// implementation ////
542////////////////////////
543
544
545
546
547namespace AliHLTInternal
548{
549#ifdef ENABLE_ARRAY_BOUNDS_CHECKING
dd5579d1 550 inline bool AliArrayBoundsCheck::IsInBounds( int x ) const
30122bae 551 {
552 assert( x >= fStart );
553 assert( x <= fEnd );
554 return ( x >= fStart && x <= fEnd );
555 }
556#endif
557
558 template<typename T>
5e1afc14 559 inline AliHLTArray<T, 1> AliHLTArrayBase<T, 2>::operator[]( int x )
30122bae 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];
dd5579d1 566 a.AliArrayBoundsCheck::operator=( *this );
30122bae 567 a.MoveBounds( -x );
568 return a;
569 }
570
571 template<typename T>
5e1afc14 572 inline const AliHLTArray<T, 1> AliHLTArrayBase<T, 2>::operator[]( int x ) const
30122bae 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];
dd5579d1 579 a.AliArrayBoundsCheck::operator=( *this );
30122bae 580 a.MoveBounds( -x );
581 return a;
582 }
583
584 template<typename T>
5e1afc14 585 inline typename AliHLTInternal::ReturnTypeHelper<T>::Type &AliHLTArrayBase<T, 3>::operator()( int x, int y, int z )
30122bae 586 {
587 BOUNDS_CHECK( x * fStrideX + y + fStrideY + z, fData[0] );
588 return fData[x * fStrideX + y + fStrideY + z];
589 }
590 template<typename T>
5e1afc14 591 inline const typename AliHLTInternal::ReturnTypeHelper<T>::Type &AliHLTArrayBase<T, 3>::operator()( int x, int y, int z ) const
30122bae 592 {
593 BOUNDS_CHECK( x * fStrideX + y + fStrideY + z, fData[0] );
594 return fData[x * fStrideX + y + fStrideY + z];
595 }
596 template<typename T>
5e1afc14 597 inline AliHLTArray<T, 2> AliHLTArrayBase<T, 3>::operator[]( int x )
30122bae 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;
dd5579d1 605 a.AliArrayBoundsCheck::operator=( *this );
30122bae 606 a.MoveBounds( -x );
607 return a;
608 }
609 template<typename T>
5e1afc14 610 inline const AliHLTArray<T, 2> AliHLTArrayBase<T, 3>::operator[]( int x ) const
30122bae 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;
dd5579d1 618 a.AliArrayBoundsCheck::operator=( *this );
30122bae 619 a.MoveBounds( -x );
620 return a;
621 }
622} // namespace AliHLTInternal
623
624
625template<typename T, int Dim>
626inline 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}
633template<typename T, int Dim>
634inline 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
642template<typename T, int Dim, int alignment>
643inline AliHLTResizableArray<T, Dim, alignment>::AliHLTResizableArray()
644{
645 Parent::fData = 0;
e18739d0 646 Parent::SetSize( 0, 0, 0 );
30122bae 647 Parent::SetBounds( 0, -1 );
648}
649template<typename T, int Dim, int alignment>
650inline AliHLTResizableArray<T, Dim, alignment>::AliHLTResizableArray( int x )
651{
652 ALIHLTARRAY_STATIC_ASSERT( Dim == 1, AliHLTResizableArray1_used_with_incorrect_dimension );
dd5579d1 653 Parent::fData = AliHLTInternal::AliAllocator<T, alignment>::Alloc( x );
e18739d0 654 Parent::SetSize( x, 0, 0 );
30122bae 655 Parent::SetBounds( 0, x - 1 );
656}
657template<typename T, int Dim, int alignment>
658inline AliHLTResizableArray<T, Dim, alignment>::AliHLTResizableArray( int x, int y )
659{
660 ALIHLTARRAY_STATIC_ASSERT( Dim == 2, AliHLTResizableArray2_used_with_incorrect_dimension );
dd5579d1 661 Parent::fData = AliHLTInternal::AliAllocator<T, alignment>::Alloc( x * y );
30122bae 662 Parent::SetSize( x, y, 0 );
663 Parent::SetBounds( 0, x * y - 1 );
664}
665template<typename T, int Dim, int alignment>
666inline AliHLTResizableArray<T, Dim, alignment>::AliHLTResizableArray( int x, int y, int z )
667{
668 ALIHLTARRAY_STATIC_ASSERT( Dim == 3, AliHLTResizableArray3_used_with_incorrect_dimension );
dd5579d1 669 Parent::fData = AliHLTInternal::AliAllocator<T, alignment>::Alloc( x * y * z );
30122bae 670 Parent::SetSize( x, y, z );
671 Parent::SetBounds( 0, x * y * z - 1 );
672}
673template<typename T, int Dim, int alignment>
674inline void AliHLTResizableArray<T, Dim, alignment>::Resize( int x )
675{
676 ALIHLTARRAY_STATIC_ASSERT( Dim == 1, AliHLTResizableArray1_resize_used_with_incorrect_dimension );
dd5579d1 677 AliHLTInternal::AliAllocator<T, alignment>::Free( Parent::fData, Parent::fSize );
678 Parent::fData = ( x == 0 ) ? 0 : AliHLTInternal::AliAllocator<T, alignment>::Alloc( x );
e18739d0 679 Parent::SetSize( x, 0, 0 );
30122bae 680 Parent::SetBounds( 0, x - 1 );
681}
682template<typename T, int Dim, int alignment>
683inline void AliHLTResizableArray<T, Dim, alignment>::Resize( int x, int y )
684{
685 ALIHLTARRAY_STATIC_ASSERT( Dim == 2, AliHLTResizableArray2_resize_used_with_incorrect_dimension );
dd5579d1 686 AliHLTInternal::AliAllocator<T, alignment>::Free( Parent::fData, Parent::fSize );
687 Parent::fData = ( x == 0 ) ? 0 : AliHLTInternal::AliAllocator<T, alignment>::Alloc( x * y );
30122bae 688 Parent::SetSize( x, y, 0 );
689 Parent::SetBounds( 0, x * y - 1 );
690}
691template<typename T, int Dim, int alignment>
692inline 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 );
dd5579d1 695 AliHLTInternal::AliAllocator<T, alignment>::Free( Parent::fData, Parent::fSize );
696 Parent::fData = ( x == 0 ) ? 0 : AliHLTInternal::AliAllocator<T, alignment>::Alloc( x * y * z );
30122bae 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