Line data Source code
1 : //-*- Mode: C++ -*-
2 : // $Id$
3 :
4 : // ****************************************************************************
5 : // * This file is property of and copyright by the ALICE HLT Project *
6 : // * ALICE Experiment at CERN, All rights reserved. *
7 : // * *
8 : // * Copyright (C) 2009 Matthias Kretz <kretz@kde.org> *
9 : // * for The ALICE HLT Project. *
10 : // * *
11 : // * Permission to use, copy, modify and distribute this software and its *
12 : // * documentation strictly for non-commercial purposes is hereby granted *
13 : // * without fee, provided that the above copyright notice appears in all *
14 : // * copies and that both the copyright notice and this permission notice *
15 : // * appear in the supporting documentation. The authors make no claims *
16 : // * about the suitability of this software for any purpose. It is *
17 : // * provided "as is" without express or implied warranty. *
18 : // ****************************************************************************
19 :
20 : /**
21 : * \file AliHLTArray.h
22 : * \author Matthias Kretz <kretz@kde.org>
23 : *
24 : * This file contains the classes AliHLTResizableArray and AliHLTFixedArray with AliHLTArray as base
25 : * class. It's a drop-in replacement for C-Arrays. It makes it easy to use variable sized arrays on
26 : * the stack and pass arrays as arguments to other functions with an optional bounds-checking
27 : * enabled for the whole time.
28 : */
29 :
30 : #ifndef ALIHLTARRAY_H
31 : #define ALIHLTARRAY_H
32 :
33 : #ifndef assert
34 : #include <assert.h>
35 : #endif
36 :
37 : #if (defined(__MMX__) || defined(__SSE__))
38 : #if defined(__GNUC__)
39 : #if __GNUC__ > 3
40 : #define USE_MM_MALLOC
41 : #endif
42 : #else // not gcc, assume it can use _mm_malloc since it supports MMX/SSE
43 : #define USE_MM_MALLOC
44 : #endif
45 : #endif
46 :
47 : #ifdef USE_MM_MALLOC
48 : #include <mm_malloc.h>
49 : #else
50 : #include <cstdlib>
51 : #endif
52 :
53 : enum {
54 : kAliHLTFullyCacheLineAligned = -1
55 : };
56 :
57 : #if defined(__CUDACC__) & 0
58 : #define ALIHLTARRAY_STATIC_ASSERT(a, b)
59 : #define ALIHLTARRAY_STATIC_ASSERT_NC(a, b)
60 : #else
61 : namespace AliHLTArrayInternal
62 : {
63 : template<bool> class AliHLTStaticAssertFailure;
64 : template<> class AliHLTStaticAssertFailure<true> {};
65 : }
66 :
67 : #define ALIHLTARRAY_STATIC_ASSERT_CONCAT_HELPER(a, b) a##b
68 : #define ALIHLTARRAY_STATIC_ASSERT_CONCAT(a, b) ALIHLTARRAY_STATIC_ASSERT_CONCAT_HELPER(a, b)
69 : #define ALIHLTARRAY_STATIC_ASSERT_NC(cond, msg) \
70 : typedef AliHLTArrayInternal::AliHLTStaticAssertFailure<cond> ALIHLTARRAY_STATIC_ASSERT_CONCAT(_STATIC_ASSERTION_FAILED_##msg, __LINE__); \
71 : ALIHLTARRAY_STATIC_ASSERT_CONCAT(_STATIC_ASSERTION_FAILED_##msg, __LINE__) Error_##msg
72 : #define ALIHLTARRAY_STATIC_ASSERT(cond, msg) ALIHLTARRAY_STATIC_ASSERT_NC(cond, msg); (void) Error_##msg
73 : #endif
74 :
75 : template<typename T, int Dim> class AliHLTArray;
76 :
77 : namespace AliHLTInternal
78 : {
79 : template<unsigned int Size> struct Padding { char fPadding[Size]; };
80 : template<> struct Padding<0> {};
81 : template<typename T> struct AliHLTCacheLineSizeHelperData { T fData; };
82 : template<typename T> struct AliHLTCacheLineSizeHelperEnums {
83 : enum {
84 : CacheLineSize = 64,
85 : MaskedSize = sizeof( T ) & ( CacheLineSize - 1 ),
86 : RequiredSize = MaskedSize == 0 ? sizeof( T ) : sizeof( T ) + CacheLineSize - MaskedSize,
87 : PaddingSize = RequiredSize - sizeof( T )
88 : };
89 : };
90 : template<typename T> class AliCacheLineSizeHelper : private AliHLTCacheLineSizeHelperData<T>, private Padding<AliHLTCacheLineSizeHelperEnums<T>::PaddingSize>
91 : {
92 : public:
93 : operator T &() { return AliHLTCacheLineSizeHelperData<T>::fData; }
94 : operator const T &() const { return AliHLTCacheLineSizeHelperData<T>::fData; }
95 : //const T &operator=( const T &rhs ) { AliHLTCacheLineSizeHelperData<T>::fData = rhs; }
96 :
97 : private:
98 : };
99 : template<typename T, int alignment> struct TypeForAlignmentHelper { typedef T Type; };
100 : template<typename T> struct TypeForAlignmentHelper<T, kAliHLTFullyCacheLineAligned> { typedef AliCacheLineSizeHelper<T> Type; };
101 :
102 : // XXX
103 : // The AliArrayBoundsCheck and AliAllocator classes implement a virtual destructor only in order to
104 : // silence the -Weffc++ warning. It really is not required for these classes to have a virtual
105 : // dtor since polymorphism is not used (AliHLTResizableArray and AliHLTFixedArray are allocated on
106 : // the stack only). The virtual dtor only adds an unnecessary vtable to the code.
107 : #ifndef ENABLE_ARRAY_BOUNDS_CHECKING
108 : /**
109 : * no-op implementation that for no-bounds-checking
110 : */
111 0 : class AliArrayBoundsCheck
112 : {
113 : protected:
114 0 : virtual inline ~AliArrayBoundsCheck() {}
115 : inline bool IsInBounds( int ) const { return true; }
116 0 : inline void SetBounds( int, int ) const {}
117 0 : inline void MoveBounds( int ) const {}
118 : inline void ReinterpretCast( const AliArrayBoundsCheck &, int, int ) const {}
119 : };
120 : #define BOUNDS_CHECK(x, y)
121 : #else
122 : /**
123 : * implementation for bounds-checking.
124 : */
125 : class AliArrayBoundsCheck
126 : {
127 : protected:
128 : virtual inline ~AliArrayBoundsCheck() {}
129 : /**
130 : * checks whether the given offset is valid
131 : */
132 : inline bool IsInBounds( int x ) const;
133 : /**
134 : * set the start and end offsets that are still valid
135 : */
136 : inline void SetBounds( int start, int end ) { fStart = start; fEnd = end; }
137 : /**
138 : * move the start and end offsets by the same amount
139 : */
140 : inline void MoveBounds( int d ) { fStart += d; fEnd += d; }
141 :
142 : inline void ReinterpretCast( const AliArrayBoundsCheck &other, int sizeofOld, int sizeofNew ) {
143 : fStart = other.fStart * sizeofNew / sizeofOld;
144 : fEnd = other.fEnd * sizeofNew / sizeofOld;
145 : }
146 :
147 : private:
148 : int fStart; // start
149 : int fEnd; // end
150 : };
151 : #define BOUNDS_CHECK(x, y) if (AliHLTInternal::AliArrayBoundsCheck::IsInBounds(x)) {} else return y
152 : #endif
153 : template<typename T, int alignment> class AliAllocator
154 : {
155 : public:
156 : #ifdef USE_MM_MALLOC
157 : static inline T *Alloc( int s ) { T *p = reinterpret_cast<T *>( _mm_malloc( s * sizeof( T ), alignment ) ); return new( p ) T[s]; }
158 : static inline void Free( T *const p, int size ) {
159 : for ( int i = 0; i < size; ++i ) p[i].~T();
160 : _mm_free( p );
161 : }
162 : #else
163 : static inline T *Alloc( int s ) { T *p; posix_memalign( &p, alignment, s * sizeof( T ) ); return new( p ) T[s]; }
164 : static inline void Free( T *const p, int size ) {
165 : for ( int i = 0; i < size; ++i ) p[i].~T();
166 : std::free( p );
167 : }
168 : #endif
169 : };
170 : template<typename T> class AliAllocator<T, kAliHLTFullyCacheLineAligned>
171 : {
172 : public:
173 : typedef AliCacheLineSizeHelper<T> T2;
174 : #ifdef USE_MM_MALLOC
175 : static inline T2 *Alloc( int s ) { T2 *p = reinterpret_cast<T2 *>( _mm_malloc( s * sizeof( T2 ), 128 ) ); return new( p ) T2[s]; }
176 : static inline void Free( T2 *const p, int size ) {
177 : for ( int i = 0; i < size; ++i ) p[i].~T2();
178 : _mm_free( p );
179 : }
180 : #else
181 : static inline T2 *Alloc( int s ) { T2 *p; posix_memalign( &p, 128, s * sizeof( T2 ) ); return new( p ) T2[s]; }
182 : static inline void Free( T2 *const p, int size ) {
183 : for ( int i = 0; i < size; ++i ) p[i].~T2();
184 : std::free( p );
185 : }
186 : #endif
187 : };
188 : template<typename T> class AliAllocator<T, 0>
189 : {
190 : public:
191 0 : static inline T *Alloc( int s ) { return new T[s]; }
192 0 : static inline void Free( const T *const p, int ) { delete[] p; }
193 : };
194 :
195 : template<typename T> struct ReturnTypeHelper { typedef T Type; };
196 : template<typename T> struct ReturnTypeHelper<AliCacheLineSizeHelper<T> > { typedef T Type; };
197 : /**
198 : * Array base class for dimension dependent behavior
199 : */
200 0 : template<typename T, int Dim> class AliHLTArrayBase;
201 :
202 : /**
203 : * 1-dim arrays only have operator[]
204 : */
205 : template<typename T>
206 : class AliHLTArrayBase<T, 1> : public AliArrayBoundsCheck
207 : {
208 : friend class AliHLTArrayBase<T, 2>; // declare friend
209 : public:
210 0 : AliHLTArrayBase() : fData( 0 ), fSize( 0 ) {} // XXX really shouldn't be done. But -Weffc++ wants it so
211 0 : AliHLTArrayBase( const AliHLTArrayBase &rhs ) : AliArrayBoundsCheck( rhs ), fData( rhs.fData ), fSize( rhs.fSize ) {} // XXX
212 : AliHLTArrayBase &operator=( const AliHLTArrayBase &rhs ) { AliArrayBoundsCheck::operator=( rhs ); fData = rhs.fData; return *this; } // XXX
213 : typedef typename ReturnTypeHelper<T>::Type R;
214 : /**
215 : * return a reference to the value at the given index
216 : */
217 0 : 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 0 : inline const R &operator[]( int x ) const { BOUNDS_CHECK( x, fData[0] ); return fData[x]; }
222 :
223 : protected:
224 : T *fData; // actual data
225 : int fSize; // data size
226 0 : inline void SetSize( int x, int, int ) { fSize = x; }
227 : };
228 :
229 : /**
230 : * 2-dim arrays should use operator(int, int)
231 : * operator[] can be used to return a 1-dim array
232 : */
233 : template<typename T>
234 : class AliHLTArrayBase<T, 2> : public AliArrayBoundsCheck
235 : {
236 : friend class AliHLTArrayBase<T, 3>; // declare friend
237 : public:
238 : AliHLTArrayBase() : fData( 0 ), fSize( 0 ), fStride( 0 ) {} // XXX really shouldn't be done. But -Weffc++ wants it so
239 : AliHLTArrayBase( const AliHLTArrayBase &rhs ) : AliArrayBoundsCheck( rhs ), fData( rhs.fData ), fSize( rhs.fSize ), fStride( rhs.fStride ) {} // XXX
240 : AliHLTArrayBase &operator=( const AliHLTArrayBase &rhs ) { AliArrayBoundsCheck::operator=( rhs ); fData = rhs.fData; fSize = rhs.fSize; fStride = rhs.fStride; return *this; } // XXX
241 : typedef typename ReturnTypeHelper<T>::Type R;
242 : /**
243 : * return a reference to the value at the given indexes
244 : */
245 : inline R &operator()( int x, int y ) { BOUNDS_CHECK( x * fStride + y, fData[0] ); return fData[x * fStride + y]; }
246 : /**
247 : * return a const reference to the value at the given indexes
248 : */
249 : inline const R &operator()( int x, int y ) const { BOUNDS_CHECK( x * fStride + y, fData[0] ); return fData[x * fStride + y]; }
250 : /**
251 : * return a 1-dim array at the given index. This makes it behave like a 2-dim C-Array.
252 : */
253 : inline AliHLTArray<T, 1> operator[]( int x );
254 : /**
255 : * return a const 1-dim array at the given index. This makes it behave like a 2-dim C-Array.
256 : */
257 : inline const AliHLTArray<T, 1> operator[]( int x ) const;
258 :
259 : protected:
260 : T *fData; // actual data
261 : int fSize; // data size
262 : int fStride; // stride
263 : inline void SetSize( int x, int y, int ) { fStride = y; fSize = x * y; }
264 : };
265 :
266 : /**
267 : * 3-dim arrays should use operator(int, int, int)
268 : * operator[] can be used to return a 2-dim array
269 : */
270 : template<typename T>
271 : class AliHLTArrayBase<T, 3> : public AliArrayBoundsCheck
272 : {
273 : public:
274 : AliHLTArrayBase() : fData( 0 ), fSize( 0 ), fStrideX( 0 ), fStrideY( 0 ) {} // XXX really shouldn't be done. But -Weffc++ wants it so
275 : AliHLTArrayBase( const AliHLTArrayBase &rhs ) : AliArrayBoundsCheck( rhs ), fData( rhs.fData ), fSize( rhs.fSize ), fStrideX( rhs.fStrideX ), fStrideY( rhs.fStrideY ) {} // XXX
276 : AliHLTArrayBase &operator=( const AliHLTArrayBase &rhs ) { AliArrayBoundsCheck::operator=( rhs ); fData = rhs.fData; fSize = rhs.fSize; fStrideX = rhs.fStrideX; fStrideY = rhs.fStrideY; return *this; } // XXX
277 : // Stopped working on GCC 4.5.0
278 : //typedef typename ReturnTypeHelper<T>::Type R;
279 : /**
280 : * return a reference to the value at the given indexes
281 : */
282 : inline typename ReturnTypeHelper<T>::Type &operator()( int x, int y, int z );
283 : /**
284 : * return a const reference to the value at the given indexes
285 : */
286 : inline const typename ReturnTypeHelper<T>::Type &operator()( int x, int y, int z ) const;
287 : /**
288 : * return a 2-dim array at the given index. This makes it behave like a 3-dim C-Array.
289 : */
290 : inline AliHLTArray<T, 2> operator[]( int x );
291 : /**
292 : * return a const 2-dim array at the given index. This makes it behave like a 3-dim C-Array.
293 : */
294 : inline const AliHLTArray<T, 2> operator[]( int x ) const;
295 :
296 : protected:
297 : T *fData; // actual data
298 : int fSize; // data size
299 : int fStrideX; // stride X
300 : int fStrideY; // stride Y
301 : inline void SetSize( int x, int y, int z ) { fStrideX = y * z; fStrideY = z; fSize = fStrideX * x; }
302 : };
303 :
304 : template<typename T, unsigned int Size, int _alignment> class AlignedData
305 : {
306 : public:
307 : T *ConstructAlignedData() {
308 : const int offset = reinterpret_cast<unsigned long>( &fUnalignedArray[0] ) & ( Alignment - 1 );
309 : void *mem = &fUnalignedArray[0] + ( Alignment - offset );
310 : return new( mem ) T[Size];
311 : }
312 : ~AlignedData() {
313 : const int offset = reinterpret_cast<unsigned long>( &fUnalignedArray[0] ) & ( Alignment - 1 );
314 : T *mem = reinterpret_cast<T *>( &fUnalignedArray[0] + ( Alignment - offset ) );
315 : for ( unsigned int i = 0; i < Size; ++i ) mem[i].~T();
316 : }
317 : private:
318 : enum {
319 : Alignment = _alignment == kAliHLTFullyCacheLineAligned ? 128 : _alignment,
320 : PaddedSize = Size * sizeof( T ) + Alignment
321 : };
322 : ALIHLTARRAY_STATIC_ASSERT_NC( ( Alignment & ( Alignment - 1 ) ) == 0, alignment_needs_to_be_a_multiple_of_2 );
323 :
324 : char fUnalignedArray[PaddedSize]; // data array
325 : };
326 : template<typename T, unsigned int Size> class AlignedData<T, Size, 0>
327 : {
328 : public:
329 : T *ConstructAlignedData() { return &fArray[0]; }
330 : private:
331 : T fArray[Size]; // data array
332 : };
333 : } // namespace AliHLTInternal
334 :
335 : /**
336 : * C-Array like class with the dimension dependent behavior defined in the AliHLTArrayBase class
337 : */
338 : template < typename T, int Dim = 1 >
339 0 : class AliHLTArray : public AliHLTInternal::AliHLTArrayBase<T, Dim>
340 : {
341 : public:
342 : typedef AliHLTInternal::AliHLTArrayBase<T, Dim> Parent;
343 :
344 : /**
345 : * Returns the number of elements in the array. If it is a multi-dimensional array the size is
346 : * the multiplication of the dimensions ( e.g. a 10 x 20 array returns 200 as its size ).
347 : */
348 : inline int Size() const { return Parent::fSize; }
349 :
350 : /**
351 : * allows you to check for validity of the array by casting to bool
352 : */
353 : inline operator bool() const { return Parent::fData != 0; }
354 : /**
355 : * allows you to check for validity of the array
356 : */
357 : inline bool IsValid() const { return Parent::fData != 0; }
358 :
359 : /**
360 : * returns a reference to the data at index 0
361 : */
362 : inline T &operator*() { BOUNDS_CHECK( 0, Parent::fData[0] ); return *Parent::fData; }
363 : /**
364 : * returns a const reference to the data at index 0
365 : */
366 : inline const T &operator*() const { BOUNDS_CHECK( 0, Parent::fData[0] ); return *Parent::fData; }
367 :
368 : /**
369 : * returns a pointer to the data
370 : * This circumvents bounds checking so it should not be used.
371 : */
372 0 : inline T *Data() { return Parent::fData; }
373 : /**
374 : * returns a const pointer to the data
375 : * This circumvents bounds checking so it should not be used.
376 : */
377 : inline const T *Data() const { return Parent::fData; }
378 :
379 : /**
380 : * moves the array base pointer so that the data that was once at index 0 will then be at index -x
381 : */
382 : inline AliHLTArray operator+( int x ) const;
383 : /**
384 : * moves the array base pointer so that the data that was once at index 0 will then be at index x
385 : */
386 : inline AliHLTArray operator-( int x ) const;
387 :
388 : #ifndef HLTCA_GPUCODE
389 : template<typename Other> inline AliHLTArray<Other, Dim> ReinterpretCast() const {
390 : AliHLTArray<Other, Dim> r;
391 : r.fData = reinterpret_cast<Other *>( Parent::fData );
392 : r.ReinterpretCast( *this, sizeof( T ), sizeof( Other ) );
393 : }
394 : #endif
395 : };
396 :
397 : /**
398 : * Owns the data. When it goes out of scope the data is freed.
399 : *
400 : * The memory is allocated on the heap.
401 : *
402 : * Instantiate this class on the stack. Allocation on the heap is disallowed.
403 : *
404 : * \param T type of the entries in the array.
405 : * \param Dim selects the operator[]/operator() behavior it should have. I.e. makes it behave like a
406 : * 1-, 2- or 3-dim array. (defaults to 1)
407 : * \param alignment Defaults to 0 (default alignment). Other valid values are any multiples of 2.
408 : * This is especially useful for aligning data for SIMD vectors.
409 : *
410 : * \warning when using alignment the type T may not have a destructor (well it may, but it won't be
411 : * called)
412 : *
413 : * Example:
414 : * \code
415 : * void init( AliHLTArray<int> a, int size )
416 : * {
417 : * for ( int i = 0; i < size; ++i ) {
418 : * a[i] = i;
419 : * }
420 : * }
421 : *
422 : * int size = ...;
423 : * AliHLTResizableArray<int> foo( size ); // notice that size doesn't have to be a constant like it
424 : * // has to be for C-Arrays in ISO C++
425 : * init( foo, size );
426 : * // now foo[i] == i
427 : *
428 : * \endcode
429 : */
430 : template < typename T, int Dim = 1, int alignment = 0 >
431 : class AliHLTResizableArray : public AliHLTArray<typename AliHLTInternal::TypeForAlignmentHelper<T, alignment>::Type, Dim>
432 : {
433 : public:
434 : typedef typename AliHLTInternal::TypeForAlignmentHelper<T, alignment>::Type T2;
435 : typedef AliHLTInternal::AliHLTArrayBase<T2, Dim> Parent;
436 : /**
437 : * does not allocate any memory
438 : */
439 : inline AliHLTResizableArray();
440 : /**
441 : * use for 1-dim arrays: allocates x * sizeof(T) bytes for the array
442 : */
443 0 : inline AliHLTResizableArray( int x );
444 : /**
445 : * use for 2-dim arrays: allocates x * y * sizeof(T) bytes for the array
446 : */
447 : inline AliHLTResizableArray( int x, int y );
448 : /**
449 : * use for 3-dim arrays: allocates x * y * z * sizeof(T) bytes for the array
450 : */
451 : inline AliHLTResizableArray( int x, int y, int z );
452 :
453 : /**
454 : * frees the data
455 : */
456 0 : inline ~AliHLTResizableArray() { AliHLTInternal::AliAllocator<T, alignment>::Free( Parent::fData, Parent::fSize ); }
457 :
458 : /**
459 : * use for 1-dim arrays: resizes the memory for the array to x * sizeof(T) bytes.
460 : *
461 : * \warning this does not keep your previous data. If you were looking for this you probably
462 : * want to use std::vector instead.
463 : */
464 : inline void Resize( int x );
465 : /**
466 : * use for 2-dim arrays: resizes the memory for the array to x * y * sizeof(T) bytes.
467 : *
468 : * \warning this does not keep your previous data. If you were looking for this you probably
469 : * want to use std::vector instead.
470 : */
471 : inline void Resize( int x, int y );
472 : /**
473 : * use for 3-dim arrays: resizes the memory for the array to x * y * z * sizeof(T) bytes.
474 : *
475 : * \warning this does not keep your previous data. If you were looking for this you probably
476 : * want to use std::vector instead.
477 : */
478 : inline void Resize( int x, int y, int z );
479 :
480 : private:
481 : // disable allocation on the heap
482 : void *operator new( size_t );
483 :
484 : // disable copy
485 : AliHLTResizableArray( const AliHLTResizableArray & );
486 : AliHLTResizableArray &operator=( const AliHLTResizableArray & );
487 : };
488 :
489 : template < unsigned int x, unsigned int y = 0, unsigned int z = 0 > class AliHLTArraySize
490 : {
491 : public:
492 : enum {
493 : Size = y == 0 ? x : ( z == 0 ? x * y : x * y * z ),
494 : Dim = y == 0 ? 1 : ( z == 0 ? 2 : 3 ),
495 : X = x, Y = y, Z = z
496 : };
497 : };
498 :
499 : /**
500 : * Owns the data. When it goes out of scope the data is freed.
501 : *
502 : * The memory is allocated on the stack.
503 : *
504 : * Instantiate this class on the stack.
505 : *
506 : * \param T type of the entries in the array.
507 : * \param Size number of entries in the array.
508 : * \param Dim selects the operator[]/operator() behavior it should have. I.e. makes it behave like a
509 : * 1-, 2- or 3-dim array. (defaults to 1)
510 : */
511 : template < typename T, typename Size, int alignment = 0 >
512 : class AliHLTFixedArray : public AliHLTArray<typename AliHLTInternal::TypeForAlignmentHelper<T, alignment>::Type, Size::Dim>
513 : {
514 : public:
515 : typedef typename AliHLTInternal::TypeForAlignmentHelper<T, alignment>::Type T2;
516 : typedef AliHLTInternal::AliHLTArrayBase<T2, Size::Dim> Parent;
517 : inline AliHLTFixedArray() {
518 : Parent::fData = fFixedArray.ConstructAlignedData();
519 : Parent::SetBounds( 0, Size::Size - 1 );
520 : SetSize( Size::X, Size::Y, Size::Z );
521 : }
522 :
523 : private:
524 : AliHLTInternal::AlignedData<typename AliHLTInternal::TypeForAlignmentHelper<T, alignment>::Type, Size::Size, alignment> fFixedArray; // data array
525 :
526 : // disable allocation on the heap
527 : void *operator new( size_t );
528 :
529 : // disable copy
530 : #ifdef HLTCA_GPUCODE
531 : #else
532 : AliHLTFixedArray( const AliHLTFixedArray & );
533 : AliHLTFixedArray &operator=( const AliHLTFixedArray & );
534 : #endif
535 : };
536 :
537 :
538 :
539 :
540 : ////////////////////////
541 : //// implementation ////
542 : ////////////////////////
543 :
544 :
545 :
546 :
547 : namespace AliHLTInternal
548 : {
549 : #ifdef ENABLE_ARRAY_BOUNDS_CHECKING
550 : inline bool AliArrayBoundsCheck::IsInBounds( int x ) const
551 : {
552 : assert( x >= fStart );
553 : assert( x <= fEnd );
554 : return ( x >= fStart && x <= fEnd );
555 : }
556 : #endif
557 :
558 : template<typename T>
559 : inline AliHLTArray<T, 1> AliHLTArrayBase<T, 2>::operator[]( int x )
560 : {
561 : x *= fStride;
562 : typedef AliHLTArray<T, 1> AT1;
563 : BOUNDS_CHECK( x, AT1() );
564 : AliHLTArray<T, 1> a;
565 : a.fData = &fData[x];
566 : a.AliArrayBoundsCheck::operator=( *this );
567 : a.MoveBounds( -x );
568 : return a;
569 : }
570 :
571 : template<typename T>
572 : inline const AliHLTArray<T, 1> AliHLTArrayBase<T, 2>::operator[]( int x ) const
573 : {
574 : x *= fStride;
575 : typedef AliHLTArray<T, 1> AT1;
576 : BOUNDS_CHECK( x, AT1() );
577 : AliHLTArray<T, 1> a;
578 : a.fData = &fData[x];
579 : a.AliArrayBoundsCheck::operator=( *this );
580 : a.MoveBounds( -x );
581 : return a;
582 : }
583 :
584 : template<typename T>
585 : inline typename AliHLTInternal::ReturnTypeHelper<T>::Type &AliHLTArrayBase<T, 3>::operator()( int x, int y, int z )
586 : {
587 : BOUNDS_CHECK( x * fStrideX + y + fStrideY + z, fData[0] );
588 : return fData[x * fStrideX + y + fStrideY + z];
589 : }
590 : template<typename T>
591 : inline const typename AliHLTInternal::ReturnTypeHelper<T>::Type &AliHLTArrayBase<T, 3>::operator()( int x, int y, int z ) const
592 : {
593 : BOUNDS_CHECK( x * fStrideX + y + fStrideY + z, fData[0] );
594 : return fData[x * fStrideX + y + fStrideY + z];
595 : }
596 : template<typename T>
597 : inline AliHLTArray<T, 2> AliHLTArrayBase<T, 3>::operator[]( int x )
598 : {
599 : x *= fStrideX;
600 : typedef AliHLTArray<T, 2> AT2;
601 : BOUNDS_CHECK( x, AT2() );
602 : AliHLTArray<T, 2> a;
603 : a.fData = &fData[x];
604 : a.fStride = fStrideY;
605 : a.AliArrayBoundsCheck::operator=( *this );
606 : a.MoveBounds( -x );
607 : return a;
608 : }
609 : template<typename T>
610 : inline const AliHLTArray<T, 2> AliHLTArrayBase<T, 3>::operator[]( int x ) const
611 : {
612 : x *= fStrideX;
613 : typedef AliHLTArray<T, 2> AT2;
614 : BOUNDS_CHECK( x, AT2() );
615 : AliHLTArray<T, 2> a;
616 : a.fData = &fData[x];
617 : a.fStride = fStrideY;
618 : a.AliArrayBoundsCheck::operator=( *this );
619 : a.MoveBounds( -x );
620 : return a;
621 : }
622 : } // namespace AliHLTInternal
623 :
624 :
625 : template<typename T, int Dim>
626 : inline AliHLTArray<T, Dim> AliHLTArray<T, Dim>::operator+( int x ) const
627 : {
628 0 : AliHLTArray<T, Dim> r( *this );
629 0 : r.fData += x;
630 0 : r.MoveBounds( -x );
631 : return r;
632 0 : }
633 : template<typename T, int Dim>
634 : inline AliHLTArray<T, Dim> AliHLTArray<T, Dim>::operator-( int x ) const
635 : {
636 : AliHLTArray<T, Dim> r( *this );
637 : r.fData -= x;
638 : r.MoveBounds( x );
639 : return r;
640 : }
641 :
642 : template<typename T, int Dim, int alignment>
643 : inline AliHLTResizableArray<T, Dim, alignment>::AliHLTResizableArray()
644 : {
645 : Parent::fData = 0;
646 : Parent::SetSize( 0, 0, 0 );
647 : Parent::SetBounds( 0, -1 );
648 : }
649 : template<typename T, int Dim, int alignment>
650 : inline AliHLTResizableArray<T, Dim, alignment>::AliHLTResizableArray( int x )
651 0 : {
652 : ALIHLTARRAY_STATIC_ASSERT( Dim == 1, AliHLTResizableArray1_used_with_incorrect_dimension );
653 0 : Parent::fData = AliHLTInternal::AliAllocator<T, alignment>::Alloc( x );
654 0 : Parent::SetSize( x, 0, 0 );
655 0 : Parent::SetBounds( 0, x - 1 );
656 0 : }
657 : template<typename T, int Dim, int alignment>
658 : inline AliHLTResizableArray<T, Dim, alignment>::AliHLTResizableArray( int x, int y )
659 : {
660 : ALIHLTARRAY_STATIC_ASSERT( Dim == 2, AliHLTResizableArray2_used_with_incorrect_dimension );
661 : Parent::fData = AliHLTInternal::AliAllocator<T, alignment>::Alloc( x * y );
662 : Parent::SetSize( x, y, 0 );
663 : Parent::SetBounds( 0, x * y - 1 );
664 : }
665 : template<typename T, int Dim, int alignment>
666 : inline AliHLTResizableArray<T, Dim, alignment>::AliHLTResizableArray( int x, int y, int z )
667 : {
668 : ALIHLTARRAY_STATIC_ASSERT( Dim == 3, AliHLTResizableArray3_used_with_incorrect_dimension );
669 : Parent::fData = AliHLTInternal::AliAllocator<T, alignment>::Alloc( x * y * z );
670 : Parent::SetSize( x, y, z );
671 : Parent::SetBounds( 0, x * y * z - 1 );
672 : }
673 : template<typename T, int Dim, int alignment>
674 : inline void AliHLTResizableArray<T, Dim, alignment>::Resize( int x )
675 : {
676 : ALIHLTARRAY_STATIC_ASSERT( Dim == 1, AliHLTResizableArray1_resize_used_with_incorrect_dimension );
677 0 : AliHLTInternal::AliAllocator<T, alignment>::Free( Parent::fData, Parent::fSize );
678 0 : Parent::fData = ( x == 0 ) ? 0 : AliHLTInternal::AliAllocator<T, alignment>::Alloc( x );
679 0 : Parent::SetSize( x, 0, 0 );
680 0 : Parent::SetBounds( 0, x - 1 );
681 0 : }
682 : template<typename T, int Dim, int alignment>
683 : inline void AliHLTResizableArray<T, Dim, alignment>::Resize( int x, int y )
684 : {
685 : ALIHLTARRAY_STATIC_ASSERT( Dim == 2, AliHLTResizableArray2_resize_used_with_incorrect_dimension );
686 : AliHLTInternal::AliAllocator<T, alignment>::Free( Parent::fData, Parent::fSize );
687 : Parent::fData = ( x == 0 ) ? 0 : AliHLTInternal::AliAllocator<T, alignment>::Alloc( x * y );
688 : Parent::SetSize( x, y, 0 );
689 : Parent::SetBounds( 0, x * y - 1 );
690 : }
691 : template<typename T, int Dim, int alignment>
692 : inline void AliHLTResizableArray<T, Dim, alignment>::Resize( int x, int y, int z )
693 : {
694 : ALIHLTARRAY_STATIC_ASSERT( Dim == 3, AliHLTResizableArray3_resize_used_with_incorrect_dimension );
695 : AliHLTInternal::AliAllocator<T, alignment>::Free( Parent::fData, Parent::fSize );
696 : Parent::fData = ( x == 0 ) ? 0 : AliHLTInternal::AliAllocator<T, alignment>::Alloc( x * y * z );
697 : Parent::SetSize( x, y, z );
698 : Parent::SetBounds( 0, x * y * z - 1 );
699 : }
700 :
701 : #undef BOUNDS_CHECK
702 :
703 : #endif // ALIHLTARRAY_H
|