]> git.uio.no Git - u/mrichter/AliRoot.git/blame - HLT/BASE/AliHLTArray.h
added setters for nonflow, flow and multiplicity in kine tree reader
[u/mrichter/AliRoot.git] / HLT / BASE / AliHLTArray.h
CommitLineData
30122bae 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 ***************************************************************************/
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
34#if defined(__MMX__) || defined(__SSE__)
35#include <mm_malloc.h>
36#else
37#include <cstdlib>
38#endif
39
40namespace AliHLTArrayInternal
41{
42 template<bool> class STATIC_ASSERT_FAILURE;
43 template<> class STATIC_ASSERT_FAILURE<true> {};
44}
45
46#define ALIHLTARRAY_STATIC_ASSERT_CONCAT_HELPER(a, b) a##b
47#define ALIHLTARRAY_STATIC_ASSERT_CONCAT(a, b) ALIHLTARRAY_STATIC_ASSERT_CONCAT_HELPER(a, b)
48#define ALIHLTARRAY_STATIC_ASSERT(cond, msg) \
49 typedef AliHLTArrayInternal::STATIC_ASSERT_FAILURE<cond> ALIHLTARRAY_STATIC_ASSERT_CONCAT(_STATIC_ASSERTION_FAILED_##msg, __LINE__); \
50 ALIHLTARRAY_STATIC_ASSERT_CONCAT(_STATIC_ASSERTION_FAILED_##msg, __LINE__) Error_##msg; \
51 (void) Error_##msg
52
53template<typename T, int Dim> class AliHLTArray;
54
55namespace AliHLTInternal
56{
57 // XXX
58 // The ArrayBoundsCheck and Allocator classes implement a virtual destructor only in order to
59 // silence the -Weff-c++ warning. It really is not required for these classes to have a virtual
60 // dtor since polymorphism is not used (AliHLTResizableArray and AliHLTFixedArray are allocated on
61 // the stack only). The virtual dtor only adds an unnecessary vtable to the code.
62#ifndef ENABLE_ARRAY_BOUNDS_CHECKING
63 /**
64 * no-op implementation that for no-bounds-checking
65 */
66 class ArrayBoundsCheck
67 {
68 protected:
69 virtual inline ~ArrayBoundsCheck() {}
70 inline bool IsInBounds( int ) const { return true; }
71 inline void SetBounds( int, int ) {}
72 inline void MoveBounds( int ) {}
73 };
74#define BOUNDS_CHECK(x, y)
75#else
76 /**
77 * implementation for bounds-checking.
78 */
79 class ArrayBoundsCheck
80 {
81 protected:
82 virtual inline ~ArrayBoundsCheck() {}
83 /**
84 * checks whether the given offset is valid
85 */
86 inline bool IsInBounds( int x ) const;
87 /**
88 * set the start and end offsets that are still valid
89 */
90 inline void SetBounds( int start, int end ) { fStart = start; fEnd = end; }
91 /**
92 * move the start and end offsets by the same amount
93 */
94 inline void MoveBounds( int d ) { fStart += d; fEnd += d; }
95
96 private:
97 int fStart;
98 int fEnd;
99 };
100#define BOUNDS_CHECK(x, y) if (AliHLTInternal::ArrayBoundsCheck::IsInBounds(x)) {} else return y
101#endif
102 template<typename T, int alignment> class Allocator
103 {
104 protected:
105 virtual inline ~Allocator() {}
106#if defined(__MMX__) || defined(__SSE__)
107 static inline T *Alloc( int s ) { T *p = reinterpret_cast<T *>( _mm_malloc( s * sizeof( T ), alignment ) ); return new( p ) T[s]; }
108 static inline void Free( const T *const p ) { /** p->~T(); */ _mm_free( p ); } // XXX: doesn't call dtor because it's an array
109#else
110 static inline T *Alloc( int s ) { T *p; posix_memalign( &p, alignment, s * sizeof( T ) ); return new( p ) T[s]; }
111 static inline void Free( const T *const p ) { std::free( p ); } // XXX: doesn't call dtor because it's an array
112#endif
113 };
114 template<typename T> class Allocator<T, 0>
115 {
116 protected:
117 virtual inline ~Allocator() {}
118 static inline T *Alloc( int s ) { return new T[s]; }
119 static inline void Free( const T *const p ) { delete[] p; }
120 };
121 /**
122 * Array base class for dimension dependent behavior
123 */
124 template<typename T, int Dim> class ArrayBase;
125
126 /**
127 * 1-dim arrays only have operator[]
128 */
129 template<typename T>
130 class ArrayBase<T, 1> : public ArrayBoundsCheck
131 {
132 friend class ArrayBase<T, 2>;
133 public:
134 /**
135 * return a reference to the value at the given index
136 */
137 inline T &operator[]( int x ) { BOUNDS_CHECK( x, fData[0] ); return fData[x]; }
138 /**
139 * return a const reference to the value at the given index
140 */
141 inline const T &operator[]( int x ) const { BOUNDS_CHECK( x, fData[0] ); return fData[x]; }
142
143 protected:
144 T *fData;
145 inline void SetSize( int, int, int ) {}
146 };
147
148 /**
149 * 2-dim arrays should use operator(int, int)
150 * operator[] can be used to return a 1-dim array
151 */
152 template<typename T>
153 class ArrayBase<T, 2> : public ArrayBoundsCheck
154 {
155 friend class ArrayBase<T, 3>;
156 public:
157 /**
158 * return a reference to the value at the given indexes
159 */
160 inline T &operator()( int x, int y ) { BOUNDS_CHECK( x * fStride + y, fData[0] ); return fData[x * fStride + y]; }
161 /**
162 * return a const reference to the value at the given indexes
163 */
164 inline const T &operator()( int x, int y ) const { BOUNDS_CHECK( x * fStride + y, fData[0] ); return fData[x * fStride + y]; }
165 /**
166 * return a 1-dim array at the given index. This makes it behave like a 2-dim C-Array.
167 */
168 inline AliHLTArray<T, 1> operator[]( int x );
169 /**
170 * return a const 1-dim array at the given index. This makes it behave like a 2-dim C-Array.
171 */
172 inline const AliHLTArray<T, 1> operator[]( int x ) const;
173
174 protected:
175 T *fData;
176 int fStride;
177 inline void SetSize( int, int y, int ) { fStride = y; }
178 };
179
180 /**
181 * 3-dim arrays should use operator(int, int, int)
182 * operator[] can be used to return a 2-dim array
183 */
184 template<typename T>
185 class ArrayBase<T, 3> : public ArrayBoundsCheck
186 {
187 public:
188 /**
189 * return a reference to the value at the given indexes
190 */
191 inline T &operator()( int x, int y, int z );
192 /**
193 * return a const reference to the value at the given indexes
194 */
195 inline const T &operator()( int x, int y, int z ) const;
196 /**
197 * return a 2-dim array at the given index. This makes it behave like a 3-dim C-Array.
198 */
199 inline AliHLTArray<T, 2> operator[]( int x );
200 /**
201 * return a const 2-dim array at the given index. This makes it behave like a 3-dim C-Array.
202 */
203 inline const AliHLTArray<T, 2> operator[]( int x ) const;
204
205 protected:
206 T *fData;
207 int fStrideX;
208 int fStrideY;
209 inline void SetSize( int, int y, int z ) { fStrideX = y * z; fStrideY = z; }
210 };
211
212 // XXX AlignedData really is an internal struct, but the RuleChecker doesn't understand that
213 template<typename T, unsigned int Size, int alignment> class AlignedData;
214 template<typename T, unsigned int Size> class AlignedData<T, Size, 0>
215 {
216 protected:
217 T d[Size];
218 };
219#ifdef __GNUC__
220#define ALIGN(n) __attribute__((aligned(n)))
221#else
222#define ALIGN(n) __declspec(align(n))
223#endif
224 template<typename T, unsigned int Size> class AlignedData<T, Size, 4>
225 {
226 protected:
227 ALIGN( 4 ) T d[Size];
228 };
229 template<typename T, unsigned int Size> class AlignedData<T, Size, 8>
230 {
231 protected:
232 ALIGN( 8 ) T d[Size];
233 };
234 template<typename T, unsigned int Size> class AlignedData<T, Size, 16>
235 {
236 protected:
237 ALIGN( 16 ) T d[Size];
238 };
239 template<typename T, unsigned int Size> class AlignedData<T, Size, 32>
240 {
241 protected:
242 ALIGN( 32 ) T d[Size];
243 };
244 template<typename T, unsigned int Size> class AlignedData<T, Size, 64>
245 {
246 protected:
247 ALIGN( 64 ) T d[Size];
248 };
249 template<typename T, unsigned int Size> class AlignedData<T, Size, 128>
250 {
251 protected:
252 ALIGN( 128 ) T d[Size];
253 };
254#undef ALIGN
255} // namespace AliHLTInternal
256
257/**
258 * C-Array like class with the dimension dependent behavior defined in the ArrayBase class
259 */
260template < typename T, int Dim = 1 >
261class AliHLTArray : public AliHLTInternal::ArrayBase<T, Dim>
262{
263 public:
264 typedef AliHLTInternal::ArrayBase<T, Dim> Parent;
265 /**
266 * allows you to check for validity of the array by casting to bool
267 */
268 inline operator bool() const { return Parent::fData != 0; }
269 /**
270 * allows you to check for validity of the array
271 */
272 inline bool IsValid() const { return Parent::fData != 0; }
273
274 /**
275 * returns a reference to the data at index 0
276 */
277 inline T &operator*() { BOUNDS_CHECK( 0, Parent::fData[0] ); return *Parent::fData; }
278 /**
279 * returns a const reference to the data at index 0
280 */
281 inline const T &operator*() const { BOUNDS_CHECK( 0, Parent::fData[0] ); return *Parent::fData; }
282
283 /**
284 * returns a pointer to the data
285 * This circumvents bounds checking so it should not be used.
286 */
287 inline T *Data() { return Parent::fData; }
288 /**
289 * returns a const pointer to the data
290 * This circumvents bounds checking so it should not be used.
291 */
292 inline const T *Data() const { return Parent::fData; }
293
294 /**
295 * moves the array base pointer so that the data that was once at index 0 will then be at index -x
296 */
297 inline AliHLTArray operator+( int x ) const;
298 /**
299 * moves the array base pointer so that the data that was once at index 0 will then be at index x
300 */
301 inline AliHLTArray operator-( int x ) const;
302};
303
304/**
305 * Owns the data. When it goes out of scope the data is freed.
306 *
307 * The memory is allocated on the heap.
308 *
309 * Instantiate this class on the stack. Allocation on the heap is disallowed.
310 *
311 * \param T type of the entries in the array.
312 * \param Dim selects the operator[]/operator() behavior it should have. I.e. makes it behave like a
313 * 1-, 2- or 3-dim array. (defaults to 1)
314 * \param alignment Defaults to 0 (default alignment). Other valid values are any multiples of 2.
315 * This is especially useful for aligning data for SIMD vectors.
316 *
317 * \warning when using alignment the type T may not have a destructor (well it may, but it won't be
318 * called)
319 *
320 * Example:
321 * \code
322 * void init( AliHLTArray<int> a, int size )
323 * {
324 * for ( int i = 0; i < size; ++i ) {
325 * a[i] = i;
326 * }
327 * }
328 *
329 * int size = ...;
330 * AliHLTResizableArray<int> foo( size ); // notice that size doesn't have to be a constant like it
331 * // has to be for C-Arrays in ISO C++
332 * init( foo, size );
333 * // now foo[i] == i
334 *
335 * \endcode
336 */
337template < typename T, int Dim = 1, int alignment = 0 >
338class AliHLTResizableArray : public AliHLTArray<T, Dim>, public AliHLTInternal::Allocator<T, alignment>
339{
340 public:
341 typedef AliHLTInternal::ArrayBase<T, Dim> Parent;
342 /**
343 * does not allocate any memory
344 */
345 inline AliHLTResizableArray();
346 /**
347 * use for 1-dim arrays: allocates x * sizeof(T) bytes for the array
348 */
349 inline AliHLTResizableArray( int x );
350 /**
351 * use for 2-dim arrays: allocates x * y * sizeof(T) bytes for the array
352 */
353 inline AliHLTResizableArray( int x, int y );
354 /**
355 * use for 3-dim arrays: allocates x * y * z * sizeof(T) bytes for the array
356 */
357 inline AliHLTResizableArray( int x, int y, int z );
358
359 /**
360 * frees the data
361 */
362 inline ~AliHLTResizableArray() { AliHLTInternal::Allocator<T, alignment>::Free( Parent::fData ); }
363
364 /**
365 * use for 1-dim arrays: resizes the memory for the array to x * sizeof(T) bytes.
366 *
367 * \warning this does not keep your previous data. If you were looking for this you probably
368 * want to use std::vector instead.
369 */
370 inline void Resize( int x );
371 /**
372 * use for 2-dim arrays: resizes the memory for the array to x * y * sizeof(T) bytes.
373 *
374 * \warning this does not keep your previous data. If you were looking for this you probably
375 * want to use std::vector instead.
376 */
377 inline void Resize( int x, int y );
378 /**
379 * use for 3-dim arrays: resizes the memory for the array to x * y * z * sizeof(T) bytes.
380 *
381 * \warning this does not keep your previous data. If you were looking for this you probably
382 * want to use std::vector instead.
383 */
384 inline void Resize( int x, int y, int z );
385
386 private:
387 // disable allocation on the heap
388 void *operator new( size_t );
389
390 // disable copy
391 AliHLTResizableArray( const AliHLTResizableArray & );
392 AliHLTResizableArray &operator=( const AliHLTResizableArray & );
393};
394
395/**
396 * Owns the data. When it goes out of scope the data is freed.
397 *
398 * The memory is allocated on the stack.
399 *
400 * Instantiate this class on the stack.
401 *
402 * \param T type of the entries in the array.
403 * \param Size number of 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 */
407template < typename T, unsigned int Size, int Dim = 1, int alignment = 0 >
408class AliHLTFixedArray : public AliHLTArray<T, Dim>
409{
410 public:
411 typedef AliHLTInternal::ArrayBase<T, Dim> Parent;
412 inline AliHLTFixedArray() { Parent::fData = &fDataOnStack.d[0]; Parent::SetBounds( 0, Size - 1 ); }
413
414 private:
415 // disable allocation on the heap
416 void *operator new( size_t );
417
418 AliHLTInternal::AlignedData<T, Size, alignment> fDataOnStack;
419
420 // disable copy
421 AliHLTFixedArray( const AliHLTFixedArray & );
422 AliHLTFixedArray &operator=( const AliHLTFixedArray & );
423};
424
425
426
427
428
429////////////////////////
430//// implementation ////
431////////////////////////
432
433
434
435
436namespace AliHLTInternal
437{
438#ifdef ENABLE_ARRAY_BOUNDS_CHECKING
439 inline bool ArrayBoundsCheck::IsInBounds( int x ) const
440 {
441 assert( x >= fStart );
442 assert( x <= fEnd );
443 return ( x >= fStart && x <= fEnd );
444 }
445#endif
446
447 template<typename T>
448 inline AliHLTArray<T, 1> ArrayBase<T, 2>::operator[]( int x )
449 {
450 x *= fStride;
451 typedef AliHLTArray<T, 1> AT1;
452 BOUNDS_CHECK( x, AT1() );
453 AliHLTArray<T, 1> a;
454 a.fData = &fData[x];
455 a.ArrayBoundsCheck::operator=( *this );
456 a.MoveBounds( -x );
457 return a;
458 }
459
460 template<typename T>
461 inline const AliHLTArray<T, 1> ArrayBase<T, 2>::operator[]( int x ) const
462 {
463 x *= fStride;
464 typedef AliHLTArray<T, 1> AT1;
465 BOUNDS_CHECK( x, AT1() );
466 AliHLTArray<T, 1> a;
467 a.fData = &fData[x];
468 a.ArrayBoundsCheck::operator=( *this );
469 a.MoveBounds( -x );
470 return a;
471 }
472
473 template<typename T>
474 inline T &ArrayBase<T, 3>::operator()( int x, int y, int z )
475 {
476 BOUNDS_CHECK( x * fStrideX + y + fStrideY + z, fData[0] );
477 return fData[x * fStrideX + y + fStrideY + z];
478 }
479 template<typename T>
480 inline const T &ArrayBase<T, 3>::operator()( int x, int y, int z ) const
481 {
482 BOUNDS_CHECK( x * fStrideX + y + fStrideY + z, fData[0] );
483 return fData[x * fStrideX + y + fStrideY + z];
484 }
485 template<typename T>
486 inline AliHLTArray<T, 2> ArrayBase<T, 3>::operator[]( int x )
487 {
488 x *= fStrideX;
489 typedef AliHLTArray<T, 2> AT2;
490 BOUNDS_CHECK( x, AT2() );
491 AliHLTArray<T, 2> a;
492 a.fData = &fData[x];
493 a.fStride = fStrideY;
494 a.ArrayBoundsCheck::operator=( *this );
495 a.MoveBounds( -x );
496 return a;
497 }
498 template<typename T>
499 inline const AliHLTArray<T, 2> ArrayBase<T, 3>::operator[]( int x ) const
500 {
501 x *= fStrideX;
502 typedef AliHLTArray<T, 2> AT2;
503 BOUNDS_CHECK( x, AT2() );
504 AliHLTArray<T, 2> a;
505 a.fData = &fData[x];
506 a.fStride = fStrideY;
507 a.ArrayBoundsCheck::operator=( *this );
508 a.MoveBounds( -x );
509 return a;
510 }
511} // namespace AliHLTInternal
512
513
514template<typename T, int Dim>
515inline AliHLTArray<T, Dim> AliHLTArray<T, Dim>::operator+( int x ) const
516{
517 AliHLTArray<T, Dim> r( *this );
518 r.fData += x;
519 r.MoveBounds( -x );
520 return r;
521}
522template<typename T, int Dim>
523inline AliHLTArray<T, Dim> AliHLTArray<T, Dim>::operator-( int x ) const
524{
525 AliHLTArray<T, Dim> r( *this );
526 r.fData -= x;
527 r.MoveBounds( x );
528 return r;
529}
530
531template<typename T, int Dim, int alignment>
532inline AliHLTResizableArray<T, Dim, alignment>::AliHLTResizableArray()
533{
534 Parent::fData = 0;
535 Parent::SetBounds( 0, -1 );
536}
537template<typename T, int Dim, int alignment>
538inline AliHLTResizableArray<T, Dim, alignment>::AliHLTResizableArray( int x )
539{
540 ALIHLTARRAY_STATIC_ASSERT( Dim == 1, AliHLTResizableArray1_used_with_incorrect_dimension );
541 Parent::fData = AliHLTInternal::Allocator<T, alignment>::Alloc( x );
542 Parent::SetBounds( 0, x - 1 );
543}
544template<typename T, int Dim, int alignment>
545inline AliHLTResizableArray<T, Dim, alignment>::AliHLTResizableArray( int x, int y )
546{
547 ALIHLTARRAY_STATIC_ASSERT( Dim == 2, AliHLTResizableArray2_used_with_incorrect_dimension );
548 Parent::fData = AliHLTInternal::Allocator<T, alignment>::Alloc( x * y );
549 Parent::SetSize( x, y, 0 );
550 Parent::SetBounds( 0, x * y - 1 );
551}
552template<typename T, int Dim, int alignment>
553inline AliHLTResizableArray<T, Dim, alignment>::AliHLTResizableArray( int x, int y, int z )
554{
555 ALIHLTARRAY_STATIC_ASSERT( Dim == 3, AliHLTResizableArray3_used_with_incorrect_dimension );
556 Parent::fData = AliHLTInternal::Allocator<T, alignment>::Alloc( x * y * z );
557 Parent::SetSize( x, y, z );
558 Parent::SetBounds( 0, x * y * z - 1 );
559}
560template<typename T, int Dim, int alignment>
561inline void AliHLTResizableArray<T, Dim, alignment>::Resize( int x )
562{
563 ALIHLTARRAY_STATIC_ASSERT( Dim == 1, AliHLTResizableArray1_resize_used_with_incorrect_dimension );
564 AliHLTInternal::Allocator<T, alignment>::Free( Parent::fData );
565 Parent::fData = ( x == 0 ) ? 0 : AliHLTInternal::Allocator<T, alignment>::Alloc( x );
566 Parent::SetBounds( 0, x - 1 );
567}
568template<typename T, int Dim, int alignment>
569inline void AliHLTResizableArray<T, Dim, alignment>::Resize( int x, int y )
570{
571 ALIHLTARRAY_STATIC_ASSERT( Dim == 2, AliHLTResizableArray2_resize_used_with_incorrect_dimension );
572 AliHLTInternal::Allocator<T, alignment>::Free( Parent::fData );
573 Parent::fData = ( x == 0 ) ? 0 : AliHLTInternal::Allocator<T, alignment>::Alloc( x * y );
574 Parent::SetSize( x, y, 0 );
575 Parent::SetBounds( 0, x * y - 1 );
576}
577template<typename T, int Dim, int alignment>
578inline void AliHLTResizableArray<T, Dim, alignment>::Resize( int x, int y, int z )
579{
580 ALIHLTARRAY_STATIC_ASSERT( Dim == 3, AliHLTResizableArray3_resize_used_with_incorrect_dimension );
581 AliHLTInternal::Allocator<T, alignment>::Free( Parent::fData );
582 Parent::fData = ( x == 0 ) ? 0 : AliHLTInternal::Allocator<T, alignment>::Alloc( x * y * z );
583 Parent::SetSize( x, y, z );
584 Parent::SetBounds( 0, x * y * z - 1 );
585}
586
587#undef BOUNDS_CHECK
588
589#endif // ALIHLTARRAY_H