]> git.uio.no Git - u/mrichter/AliRoot.git/blame - HLT/BASE/AliHLTArray.h
- component for plotting the Y and Z track residuals (Timur)
[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 {
54 AliHLTFullyCacheLineAligned = -1
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{
63 template<bool> class STATIC_ASSERT_FAILURE;
64 template<> class STATIC_ASSERT_FAILURE<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)
e18739d0 69#define ALIHLTARRAY_STATIC_ASSERT_NC(cond, msg) \
30122bae 70 typedef AliHLTArrayInternal::STATIC_ASSERT_FAILURE<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> {};
81 template<typename T> struct CacheLineSizeHelperData { T fData; };
82 template<typename T> struct CacheLineSizeHelperEnums {
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 CacheLineSizeHelper : private CacheLineSizeHelperData<T>, private Padding<CacheLineSizeHelperEnums<T>::PaddingSize>
91 {
92 public:
93 operator T &() { return CacheLineSizeHelperData<T>::fData; }
94 operator const T &() const { return CacheLineSizeHelperData<T>::fData; }
95 //const T &operator=( const T &rhs ) { CacheLineSizeHelperData<T>::fData = rhs; }
96
97 private:
98 };
99 template<typename T, int alignment> struct TypeForAlignmentHelper { typedef T Type; };
100 template<typename T> struct TypeForAlignmentHelper<T, AliHLTFullyCacheLineAligned> { typedef CacheLineSizeHelper<T> Type; };
101
30122bae 102 // XXX
103 // The ArrayBoundsCheck and Allocator 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 */
111 class ArrayBoundsCheck
112 {
113 protected:
114 virtual inline ~ArrayBoundsCheck() {}
115 inline bool IsInBounds( int ) const { return true; }
116 inline void SetBounds( int, int ) {}
117 inline void MoveBounds( int ) {}
e18739d0 118 inline void ReinterpretCast( const ArrayBoundsCheck &, int, int ) {}
30122bae 119 };
120#define BOUNDS_CHECK(x, y)
121#else
122 /**
123 * implementation for bounds-checking.
124 */
125 class ArrayBoundsCheck
126 {
127 protected:
128 virtual inline ~ArrayBoundsCheck() {}
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
e18739d0 142 inline void ReinterpretCast( const ArrayBoundsCheck &other, int sizeofOld, int sizeofNew ) {
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 };
151#define BOUNDS_CHECK(x, y) if (AliHLTInternal::ArrayBoundsCheck::IsInBounds(x)) {} else return y
152#endif
153 template<typename T, int alignment> class Allocator
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 ) {
159 for ( int i = 0; i < size; ++i ) {
160 p[i].~T();
161 }
162 _mm_free( p );
163 }
30122bae 164#else
165 static inline T *Alloc( int s ) { T *p; posix_memalign( &p, alignment, s * sizeof( T ) ); return new( p ) T[s]; }
e18739d0 166 static inline void Free( T *const p, int size ) {
167 for ( int i = 0; i < size; ++i ) {
168 p[i].~T();
169 }
170 std::free( p );
171 }
172#endif
173 };
174 template<typename T> class Allocator<T, AliHLTFullyCacheLineAligned>
175 {
176 public:
177 typedef CacheLineSizeHelper<T> T2;
178#ifdef USE_MM_MALLOC
179 static inline T2 *Alloc( int s ) { T2 *p = reinterpret_cast<T2 *>( _mm_malloc( s * sizeof( T2 ), 128 ) ); return new( p ) T2[s]; }
180 static inline void Free( T2 *const p, int size ) {
181 for ( int i = 0; i < size; ++i ) {
9e2dadc1 182 p[i].~T2();
e18739d0 183 }
184 _mm_free( p );
185 }
186#else
187 static inline T2 *Alloc( int s ) { T2 *p; posix_memalign( &p, 128, s * sizeof( T2 ) ); return new( p ) T2[s]; }
188 static inline void Free( T2 *const p, int size ) {
189 for ( int i = 0; i < size; ++i ) {
9e2dadc1 190 p[i].~T2();
e18739d0 191 }
192 std::free( p );
193 }
30122bae 194#endif
195 };
196 template<typename T> class Allocator<T, 0>
197 {
e18739d0 198 public:
30122bae 199 static inline T *Alloc( int s ) { return new T[s]; }
e18739d0 200 static inline void Free( const T *const p, int ) { delete[] p; }
30122bae 201 };
e18739d0 202
203 template<typename T> struct ReturnTypeHelper { typedef T Type; };
204 template<typename T> struct ReturnTypeHelper<CacheLineSizeHelper<T> > { typedef T Type; };
30122bae 205 /**
206 * Array base class for dimension dependent behavior
207 */
208 template<typename T, int Dim> class ArrayBase;
209
210 /**
211 * 1-dim arrays only have operator[]
212 */
213 template<typename T>
214 class ArrayBase<T, 1> : public ArrayBoundsCheck
215 {
216 friend class ArrayBase<T, 2>;
217 public:
e18739d0 218 ArrayBase() : fData( 0 ), fSize( 0 ) {} // XXX really shouldn't be done. But -Weffc++ wants it so
219 ArrayBase( const ArrayBase &rhs ) : ArrayBoundsCheck( rhs ), fData( rhs.fData ), fSize( rhs.fSize ) {} // XXX
220 ArrayBase &operator=( const ArrayBase &rhs ) { ArrayBoundsCheck::operator=( rhs ); fData = rhs.fData; return *this; } // XXX
221 typedef typename ReturnTypeHelper<T>::Type R;
30122bae 222 /**
223 * return a reference to the value at the given index
224 */
e18739d0 225 inline R &operator[]( int x ) { BOUNDS_CHECK( x, fData[0] ); return fData[x]; }
30122bae 226 /**
227 * return a const reference to the value at the given index
228 */
e18739d0 229 inline const R &operator[]( int x ) const { BOUNDS_CHECK( x, fData[0] ); return fData[x]; }
30122bae 230
231 protected:
cf9d96e4 232 T *fData; // actual data
233 int fSize; // data size
e18739d0 234 inline void SetSize( int x, int, int ) { fSize = x; }
30122bae 235 };
236
237 /**
238 * 2-dim arrays should use operator(int, int)
239 * operator[] can be used to return a 1-dim array
240 */
241 template<typename T>
242 class ArrayBase<T, 2> : public ArrayBoundsCheck
243 {
244 friend class ArrayBase<T, 3>;
245 public:
e18739d0 246 ArrayBase() : fData( 0 ), fSize( 0 ), fStride( 0 ) {} // XXX really shouldn't be done. But -Weffc++ wants it so
247 ArrayBase( const ArrayBase &rhs ) : ArrayBoundsCheck( rhs ), fData( rhs.fData ), fSize( rhs.fSize ), fStride( rhs.fStride ) {} // XXX
248 ArrayBase &operator=( const ArrayBase &rhs ) { ArrayBoundsCheck::operator=( rhs ); fData = rhs.fData; fSize = rhs.fSize; fStride = rhs.fStride; return *this; } // XXX
249 typedef typename ReturnTypeHelper<T>::Type R;
30122bae 250 /**
251 * return a reference to the value at the given indexes
252 */
e18739d0 253 inline R &operator()( int x, int y ) { BOUNDS_CHECK( x * fStride + y, fData[0] ); return fData[x * fStride + y]; }
30122bae 254 /**
255 * return a const reference to the value at the given indexes
256 */
e18739d0 257 inline const R &operator()( int x, int y ) const { BOUNDS_CHECK( x * fStride + y, fData[0] ); return fData[x * fStride + y]; }
30122bae 258 /**
259 * return a 1-dim array at the given index. This makes it behave like a 2-dim C-Array.
260 */
261 inline AliHLTArray<T, 1> operator[]( int x );
262 /**
263 * return a const 1-dim array at the given index. This makes it behave like a 2-dim C-Array.
264 */
265 inline const AliHLTArray<T, 1> operator[]( int x ) const;
266
267 protected:
cf9d96e4 268 T *fData; // actual data
269 int fSize; // data size
270 int fStride; //
e18739d0 271 inline void SetSize( int x, int y, int ) { fStride = y; fSize = x * y; }
30122bae 272 };
273
274 /**
275 * 3-dim arrays should use operator(int, int, int)
276 * operator[] can be used to return a 2-dim array
277 */
278 template<typename T>
279 class ArrayBase<T, 3> : public ArrayBoundsCheck
280 {
281 public:
e18739d0 282 ArrayBase() : fData( 0 ), fSize( 0 ), fStrideX( 0 ), fStrideY( 0 ) {} // XXX really shouldn't be done. But -Weffc++ wants it so
283 ArrayBase( const ArrayBase &rhs ) : ArrayBoundsCheck( rhs ), fData( rhs.fData ), fSize( rhs.fSize ), fStrideX( rhs.fStrideX ), fStrideY( rhs.fStrideY ) {} // XXX
284 ArrayBase &operator=( const ArrayBase &rhs ) { ArrayBoundsCheck::operator=( rhs ); fData = rhs.fData; fSize = rhs.fSize; fStrideX = rhs.fStrideX; fStrideY = rhs.fStrideY; return *this; } // XXX
e2b8fd2d 285 // Stopped working on GCC 4.5.0
286 //typedef typename ReturnTypeHelper<T>::Type R;
30122bae 287 /**
288 * return a reference to the value at the given indexes
289 */
e2b8fd2d 290 inline typename ReturnTypeHelper<T>::Type &operator()( int x, int y, int z );
30122bae 291 /**
292 * return a const reference to the value at the given indexes
293 */
e2b8fd2d 294 inline const typename ReturnTypeHelper<T>::Type &operator()( int x, int y, int z ) const;
30122bae 295 /**
296 * return a 2-dim array at the given index. This makes it behave like a 3-dim C-Array.
297 */
298 inline AliHLTArray<T, 2> operator[]( int x );
299 /**
300 * return a const 2-dim array at the given index. This makes it behave like a 3-dim C-Array.
301 */
302 inline const AliHLTArray<T, 2> operator[]( int x ) const;
303
304 protected:
cf9d96e4 305 T *fData; // actual data
306 int fSize; // data size
307 int fStrideX; //
308 int fStrideY; //
e18739d0 309 inline void SetSize( int x, int y, int z ) { fStrideX = y * z; fStrideY = z; fSize = fStrideX * x; }
30122bae 310 };
311
e18739d0 312 template<typename T, unsigned int Size, int _alignment> class AlignedData
30122bae 313 {
e18739d0 314 public:
315 T *ConstructAlignedData() {
316 const int offset = reinterpret_cast<unsigned long>( &fUnalignedArray[0] ) & ( Alignment - 1 );
317 void *mem = &fUnalignedArray[0] + ( Alignment - offset );
318 return new( mem ) T[Size];
319 }
320 ~AlignedData() {
321 const int offset = reinterpret_cast<unsigned long>( &fUnalignedArray[0] ) & ( Alignment - 1 );
322 T *mem = reinterpret_cast<T *>( &fUnalignedArray[0] + ( Alignment - offset ) );
323 for ( unsigned int i = 0; i < Size; ++i ) {
324 mem[i].~T();
325 }
326 }
327 private:
328 enum {
329 Alignment = _alignment == AliHLTFullyCacheLineAligned ? 128 : _alignment,
330 PaddedSize = Size * sizeof( T ) + Alignment
331 };
332 ALIHLTARRAY_STATIC_ASSERT_NC( ( Alignment & ( Alignment - 1 ) ) == 0, alignment_needs_to_be_a_multiple_of_2 );
333
cf9d96e4 334 char fUnalignedArray[PaddedSize]; //
30122bae 335 };
e18739d0 336 template<typename T, unsigned int Size> class AlignedData<T, Size, 0>
30122bae 337 {
e18739d0 338 public:
339 T *ConstructAlignedData() { return &fArray[0]; }
340 private:
cf9d96e4 341 T fArray[Size]; //
30122bae 342 };
30122bae 343} // namespace AliHLTInternal
344
345/**
346 * C-Array like class with the dimension dependent behavior defined in the ArrayBase class
347 */
348template < typename T, int Dim = 1 >
349class AliHLTArray : public AliHLTInternal::ArrayBase<T, Dim>
350{
351 public:
352 typedef AliHLTInternal::ArrayBase<T, Dim> Parent;
e18739d0 353
354 /**
355 * Returns the number of elements in the array. If it is a multi-dimensional array the size is
356 * the multiplication of the dimensions ( e.g. a 10 x 20 array returns 200 as its size ).
357 */
358 inline int Size() const { return Parent::fSize; }
359
30122bae 360 /**
361 * allows you to check for validity of the array by casting to bool
362 */
363 inline operator bool() const { return Parent::fData != 0; }
364 /**
365 * allows you to check for validity of the array
366 */
367 inline bool IsValid() const { return Parent::fData != 0; }
368
369 /**
370 * returns a reference to the data at index 0
371 */
372 inline T &operator*() { BOUNDS_CHECK( 0, Parent::fData[0] ); return *Parent::fData; }
373 /**
374 * returns a const reference to the data at index 0
375 */
376 inline const T &operator*() const { BOUNDS_CHECK( 0, Parent::fData[0] ); return *Parent::fData; }
377
378 /**
379 * returns a pointer to the data
380 * This circumvents bounds checking so it should not be used.
381 */
382 inline T *Data() { return Parent::fData; }
383 /**
384 * returns a const pointer to the data
385 * This circumvents bounds checking so it should not be used.
386 */
387 inline const T *Data() const { return Parent::fData; }
388
389 /**
390 * moves the array base pointer so that the data that was once at index 0 will then be at index -x
391 */
392 inline AliHLTArray operator+( int x ) const;
393 /**
394 * moves the array base pointer so that the data that was once at index 0 will then be at index x
395 */
396 inline AliHLTArray operator-( int x ) const;
e18739d0 397
9e2dadc1 398#ifndef HLTCA_GPUCODE
e18739d0 399 template<typename Other> inline AliHLTArray<Other, Dim> ReinterpretCast() const {
400 AliHLTArray<Other, Dim> r;
401 r.fData = reinterpret_cast<Other *>( Parent::fData );
402 r.ReinterpretCast( *this, sizeof( T ), sizeof( Other ) );
403 }
9e2dadc1 404#endif
30122bae 405};
406
407/**
408 * Owns the data. When it goes out of scope the data is freed.
409 *
410 * The memory is allocated on the heap.
411 *
412 * Instantiate this class on the stack. Allocation on the heap is disallowed.
413 *
414 * \param T type of the entries in the array.
415 * \param Dim selects the operator[]/operator() behavior it should have. I.e. makes it behave like a
416 * 1-, 2- or 3-dim array. (defaults to 1)
417 * \param alignment Defaults to 0 (default alignment). Other valid values are any multiples of 2.
418 * This is especially useful for aligning data for SIMD vectors.
419 *
420 * \warning when using alignment the type T may not have a destructor (well it may, but it won't be
421 * called)
422 *
423 * Example:
424 * \code
425 * void init( AliHLTArray<int> a, int size )
426 * {
427 * for ( int i = 0; i < size; ++i ) {
428 * a[i] = i;
429 * }
430 * }
431 *
432 * int size = ...;
433 * AliHLTResizableArray<int> foo( size ); // notice that size doesn't have to be a constant like it
434 * // has to be for C-Arrays in ISO C++
435 * init( foo, size );
436 * // now foo[i] == i
437 *
438 * \endcode
439 */
440template < typename T, int Dim = 1, int alignment = 0 >
e18739d0 441class AliHLTResizableArray : public AliHLTArray<typename AliHLTInternal::TypeForAlignmentHelper<T, alignment>::Type, Dim>
30122bae 442{
443 public:
e18739d0 444 typedef typename AliHLTInternal::TypeForAlignmentHelper<T, alignment>::Type T2;
445 typedef AliHLTInternal::ArrayBase<T2, Dim> Parent;
30122bae 446 /**
447 * does not allocate any memory
448 */
449 inline AliHLTResizableArray();
450 /**
451 * use for 1-dim arrays: allocates x * sizeof(T) bytes for the array
452 */
453 inline AliHLTResizableArray( int x );
454 /**
455 * use for 2-dim arrays: allocates x * y * sizeof(T) bytes for the array
456 */
457 inline AliHLTResizableArray( int x, int y );
458 /**
459 * use for 3-dim arrays: allocates x * y * z * sizeof(T) bytes for the array
460 */
461 inline AliHLTResizableArray( int x, int y, int z );
462
463 /**
464 * frees the data
465 */
e18739d0 466 inline ~AliHLTResizableArray() { AliHLTInternal::Allocator<T, alignment>::Free( Parent::fData, Parent::fSize ); }
30122bae 467
468 /**
469 * use for 1-dim arrays: resizes the memory for the array to x * sizeof(T) bytes.
470 *
471 * \warning this does not keep your previous data. If you were looking for this you probably
472 * want to use std::vector instead.
473 */
474 inline void Resize( int x );
475 /**
476 * use for 2-dim arrays: resizes the memory for the array to x * y * sizeof(T) bytes.
477 *
478 * \warning this does not keep your previous data. If you were looking for this you probably
479 * want to use std::vector instead.
480 */
481 inline void Resize( int x, int y );
482 /**
483 * use for 3-dim arrays: resizes the memory for the array to x * y * z * sizeof(T) bytes.
484 *
485 * \warning this does not keep your previous data. If you were looking for this you probably
486 * want to use std::vector instead.
487 */
488 inline void Resize( int x, int y, int z );
489
490 private:
491 // disable allocation on the heap
492 void *operator new( size_t );
493
494 // disable copy
495 AliHLTResizableArray( const AliHLTResizableArray & );
496 AliHLTResizableArray &operator=( const AliHLTResizableArray & );
497};
498
e18739d0 499template < unsigned int x, unsigned int y = 0, unsigned int z = 0 > class AliHLTArraySize
500{
501 public:
502 enum {
503 Size = y == 0 ? x : ( z == 0 ? x * y : x * y * z ),
504 Dim = y == 0 ? 1 : ( z == 0 ? 2 : 3 ),
505 X = x, Y = y, Z = z
506 };
507};
508
30122bae 509/**
510 * Owns the data. When it goes out of scope the data is freed.
511 *
512 * The memory is allocated on the stack.
513 *
514 * Instantiate this class on the stack.
515 *
516 * \param T type of the entries in the array.
517 * \param Size number of entries in the array.
518 * \param Dim selects the operator[]/operator() behavior it should have. I.e. makes it behave like a
519 * 1-, 2- or 3-dim array. (defaults to 1)
520 */
e18739d0 521template < typename T, typename Size, int alignment = 0 >
522class AliHLTFixedArray : public AliHLTArray<typename AliHLTInternal::TypeForAlignmentHelper<T, alignment>::Type, Size::Dim>
30122bae 523{
524 public:
e18739d0 525 typedef typename AliHLTInternal::TypeForAlignmentHelper<T, alignment>::Type T2;
526 typedef AliHLTInternal::ArrayBase<T2, Size::Dim> Parent;
527 inline AliHLTFixedArray() {
528 Parent::fData = fFixedArray.ConstructAlignedData();
529 Parent::SetBounds( 0, Size::Size - 1 );
530 SetSize( Size::X, Size::Y, Size::Z );
531 }
30122bae 532
533 private:
cf9d96e4 534 AliHLTInternal::AlignedData<typename AliHLTInternal::TypeForAlignmentHelper<T, alignment>::Type, Size::Size, alignment> fFixedArray; //
e18739d0 535
30122bae 536 // disable allocation on the heap
537 void *operator new( size_t );
538
30122bae 539 // disable copy
9e2dadc1 540#ifdef HLTCA_GPUCODE
541#else
30122bae 542 AliHLTFixedArray( const AliHLTFixedArray & );
543 AliHLTFixedArray &operator=( const AliHLTFixedArray & );
9e2dadc1 544#endif
30122bae 545};
546
547
548
549
30122bae 550////////////////////////
551//// implementation ////
552////////////////////////
553
554
555
556
557namespace AliHLTInternal
558{
559#ifdef ENABLE_ARRAY_BOUNDS_CHECKING
560 inline bool ArrayBoundsCheck::IsInBounds( int x ) const
561 {
562 assert( x >= fStart );
563 assert( x <= fEnd );
564 return ( x >= fStart && x <= fEnd );
565 }
566#endif
567
568 template<typename T>
569 inline AliHLTArray<T, 1> ArrayBase<T, 2>::operator[]( int x )
570 {
571 x *= fStride;
572 typedef AliHLTArray<T, 1> AT1;
573 BOUNDS_CHECK( x, AT1() );
574 AliHLTArray<T, 1> a;
575 a.fData = &fData[x];
576 a.ArrayBoundsCheck::operator=( *this );
577 a.MoveBounds( -x );
578 return a;
579 }
580
581 template<typename T>
582 inline const AliHLTArray<T, 1> ArrayBase<T, 2>::operator[]( int x ) const
583 {
584 x *= fStride;
585 typedef AliHLTArray<T, 1> AT1;
586 BOUNDS_CHECK( x, AT1() );
587 AliHLTArray<T, 1> a;
588 a.fData = &fData[x];
589 a.ArrayBoundsCheck::operator=( *this );
590 a.MoveBounds( -x );
591 return a;
592 }
593
594 template<typename T>
e18739d0 595 inline typename AliHLTInternal::ReturnTypeHelper<T>::Type &ArrayBase<T, 3>::operator()( int x, int y, int z )
30122bae 596 {
597 BOUNDS_CHECK( x * fStrideX + y + fStrideY + z, fData[0] );
598 return fData[x * fStrideX + y + fStrideY + z];
599 }
600 template<typename T>
e18739d0 601 inline const typename AliHLTInternal::ReturnTypeHelper<T>::Type &ArrayBase<T, 3>::operator()( int x, int y, int z ) const
30122bae 602 {
603 BOUNDS_CHECK( x * fStrideX + y + fStrideY + z, fData[0] );
604 return fData[x * fStrideX + y + fStrideY + z];
605 }
606 template<typename T>
607 inline AliHLTArray<T, 2> ArrayBase<T, 3>::operator[]( int x )
608 {
609 x *= fStrideX;
610 typedef AliHLTArray<T, 2> AT2;
611 BOUNDS_CHECK( x, AT2() );
612 AliHLTArray<T, 2> a;
613 a.fData = &fData[x];
614 a.fStride = fStrideY;
615 a.ArrayBoundsCheck::operator=( *this );
616 a.MoveBounds( -x );
617 return a;
618 }
619 template<typename T>
620 inline const AliHLTArray<T, 2> ArrayBase<T, 3>::operator[]( int x ) const
621 {
622 x *= fStrideX;
623 typedef AliHLTArray<T, 2> AT2;
624 BOUNDS_CHECK( x, AT2() );
625 AliHLTArray<T, 2> a;
626 a.fData = &fData[x];
627 a.fStride = fStrideY;
628 a.ArrayBoundsCheck::operator=( *this );
629 a.MoveBounds( -x );
630 return a;
631 }
632} // namespace AliHLTInternal
633
634
635template<typename T, int Dim>
636inline AliHLTArray<T, Dim> AliHLTArray<T, Dim>::operator+( int x ) const
637{
638 AliHLTArray<T, Dim> r( *this );
639 r.fData += x;
640 r.MoveBounds( -x );
641 return r;
642}
643template<typename T, int Dim>
644inline AliHLTArray<T, Dim> AliHLTArray<T, Dim>::operator-( int x ) const
645{
646 AliHLTArray<T, Dim> r( *this );
647 r.fData -= x;
648 r.MoveBounds( x );
649 return r;
650}
651
652template<typename T, int Dim, int alignment>
653inline AliHLTResizableArray<T, Dim, alignment>::AliHLTResizableArray()
654{
655 Parent::fData = 0;
e18739d0 656 Parent::SetSize( 0, 0, 0 );
30122bae 657 Parent::SetBounds( 0, -1 );
658}
659template<typename T, int Dim, int alignment>
660inline AliHLTResizableArray<T, Dim, alignment>::AliHLTResizableArray( int x )
661{
662 ALIHLTARRAY_STATIC_ASSERT( Dim == 1, AliHLTResizableArray1_used_with_incorrect_dimension );
663 Parent::fData = AliHLTInternal::Allocator<T, alignment>::Alloc( x );
e18739d0 664 Parent::SetSize( x, 0, 0 );
30122bae 665 Parent::SetBounds( 0, x - 1 );
666}
667template<typename T, int Dim, int alignment>
668inline AliHLTResizableArray<T, Dim, alignment>::AliHLTResizableArray( int x, int y )
669{
670 ALIHLTARRAY_STATIC_ASSERT( Dim == 2, AliHLTResizableArray2_used_with_incorrect_dimension );
671 Parent::fData = AliHLTInternal::Allocator<T, alignment>::Alloc( x * y );
672 Parent::SetSize( x, y, 0 );
673 Parent::SetBounds( 0, x * y - 1 );
674}
675template<typename T, int Dim, int alignment>
676inline AliHLTResizableArray<T, Dim, alignment>::AliHLTResizableArray( int x, int y, int z )
677{
678 ALIHLTARRAY_STATIC_ASSERT( Dim == 3, AliHLTResizableArray3_used_with_incorrect_dimension );
679 Parent::fData = AliHLTInternal::Allocator<T, alignment>::Alloc( x * y * z );
680 Parent::SetSize( x, y, z );
681 Parent::SetBounds( 0, x * y * z - 1 );
682}
683template<typename T, int Dim, int alignment>
684inline void AliHLTResizableArray<T, Dim, alignment>::Resize( int x )
685{
686 ALIHLTARRAY_STATIC_ASSERT( Dim == 1, AliHLTResizableArray1_resize_used_with_incorrect_dimension );
e18739d0 687 AliHLTInternal::Allocator<T, alignment>::Free( Parent::fData, Parent::fSize );
30122bae 688 Parent::fData = ( x == 0 ) ? 0 : AliHLTInternal::Allocator<T, alignment>::Alloc( x );
e18739d0 689 Parent::SetSize( x, 0, 0 );
30122bae 690 Parent::SetBounds( 0, x - 1 );
691}
692template<typename T, int Dim, int alignment>
693inline void AliHLTResizableArray<T, Dim, alignment>::Resize( int x, int y )
694{
695 ALIHLTARRAY_STATIC_ASSERT( Dim == 2, AliHLTResizableArray2_resize_used_with_incorrect_dimension );
e18739d0 696 AliHLTInternal::Allocator<T, alignment>::Free( Parent::fData, Parent::fSize );
30122bae 697 Parent::fData = ( x == 0 ) ? 0 : AliHLTInternal::Allocator<T, alignment>::Alloc( x * y );
698 Parent::SetSize( x, y, 0 );
699 Parent::SetBounds( 0, x * y - 1 );
700}
701template<typename T, int Dim, int alignment>
702inline void AliHLTResizableArray<T, Dim, alignment>::Resize( int x, int y, int z )
703{
704 ALIHLTARRAY_STATIC_ASSERT( Dim == 3, AliHLTResizableArray3_resize_used_with_incorrect_dimension );
e18739d0 705 AliHLTInternal::Allocator<T, alignment>::Free( Parent::fData, Parent::fSize );
30122bae 706 Parent::fData = ( x == 0 ) ? 0 : AliHLTInternal::Allocator<T, alignment>::Alloc( x * y * z );
707 Parent::SetSize( x, y, z );
708 Parent::SetBounds( 0, x * y * z - 1 );
709}
710
711#undef BOUNDS_CHECK
712
713#endif // ALIHLTARRAY_H