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