StRoot  1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
AliHLTTPCCAMath.h
1 //-*- Mode: C++ -*-
2 // ************************************************************************
3 // This file is property of and copyright by the ALICE HLT Project *
4 // ALICE Experiment at CERN, All rights reserved. *
5 // See cxx source for full Copyright notice *
6 // *
7 //*************************************************************************
8 
9 #ifndef ALIHLTTPCCAMATH_H
10 #define ALIHLTTPCCAMATH_H
11 
12 #include "AliHLTTPCCADef.h"
13 
14 #include <cstdlib>
15 #include <cmath>
16 #include <algorithm>
17 
18 #if defined(HLTCA_STANDALONE)
19 #include <limits>
20 #else
21 #include "TMath.h"
22 #endif
23 
24 #ifdef __SSE__
25 #include <xmmintrin.h>
26 #endif
27 
33 namespace CAMath
34 {
35  template<typename T> static inline T Min ( const T &x, const T &y ) { return std::min( x, y ); }
36  template<typename T> static inline T Max ( const T &x, const T &y ) { return std::max( x, y ); }
37  template<typename T> static inline T Sqrt( const T &x ) { return std::sqrt( x ); }
38  template<typename T> static inline T RSqrt( const T &x ) { const T one = 1.; return one / std::sqrt( x ); }
39  template<typename T> typename Vc::Vector<T> RSqrt(const Vc::Vector<T> &x) { return Vc::rsqrt( x ); }
40  template<typename T> static inline T Abs ( const T &x ) { return std::abs( x ); }
41  template<typename T> static inline T Log ( const T &x ) { return std::log( x ); }
42  template<typename T> static inline T Log10( const T &x ) { return std::log10( x ); }
43  template<typename T> static inline T Sin ( const T &x ) { return std::sin( x ); }
44  template<typename T> static inline T Cos ( const T &x ) { return std::cos( x ); }
45  template<typename T> static T Reciprocal( const T &x );
46  template<typename T> typename Vc::Vector<T> Reciprocal(const Vc::Vector<T> &x) { return Vc::reciprocal( x ); }
47  template<typename T> static T ApproxSqrt( const T &x );
48 #ifdef USE_TBB
49  template<typename T> static T AtomicMax( T volatile *addr, T val );
50 #endif //USE_TBB
51 
52  template<typename T> struct FiniteReturnTypeHelper { typedef bool R; };
53  template<typename T> static typename FiniteReturnTypeHelper<T>::R Finite( const T &x );
54  template<typename T> typename Vc::Vector<T>::Mask Finite(const Vc::Vector<T> &x) { return Vc::isfinite( x ); }
55 
56  template<typename T> static T Round( const T &x ) { return round( x ); }
57 
58  template<typename T> static inline T Recip( const T &x ) { return T( 1 ) / x; }
59  template<typename T> static T ATan2( const T &y, const T &x ) { return atan2( y, x ); }
60  template<typename T> static T ASin( const T &x ) { return asin( x ); }
61 
62  float Tan( float x );
63  float Copysign( float x, float y );
64  static inline float TwoPi() { return 6.283185307179586f; }
65  static inline float Pi() { return 3.1415926535897f; }
66  int Nint( float x );
67 
68  template<typename T> static T ACos( const T &x ) { return (Pi()/2.f - asin( x )); }
69 
70 #ifdef USE_TBB
71  int AtomicExch( int volatile *addr, int val );
72  int AtomicAdd ( int volatile *addr, int val );
73  int AtomicMin ( int volatile *addr, int val );
74 #endif //USE_TBB
75 }
76 
77 #if defined( HLTCA_STANDALONE )
78 #define choice(c1,c2,c3) c2
79 #else
80 #define choice(c1,c2,c3) c3
81 #endif
82 
83 namespace CAMath
84 {
85 
86  template<> inline float Reciprocal<float>( const float &x )
87  {
88  return 1.f / x;
89  }
90 
91  template<> inline double Reciprocal<double>( const double &x )
92  {
93  return 1. / x;
94  }
95 
96 #ifdef __SSE__
97  template<> inline float RSqrt<float>( const float &x )
98  {
99  float r = x;
100  __m128 tmp;
101  asm(
102  "rsqrtss %0,%1\n\t"
103  "movss %1,%0\n\t"
104  : "+m"( r ), "=x"( tmp )
105  );
106  return r;
107  }
108 #endif // __SSE__
109 
110  template<> inline float ApproxSqrt<float>( const float &x )
111  {
112  float r = x;
113  asm(
114  "shr %0\n\t"
115  "add $0x1fc00000,%0\n\t"
116  : "+r"( r )
117  );
118  return r;
119  }
120 }
121 
122 inline int CAMath::Nint( float x )
123 {
124  int i;
125  if ( x >= 0 ) {
126  i = int( x + 0.5f );
127  if ( x + 0.5f == float( i ) && i & 1 ) i--;
128  } else {
129  i = int( x - 0.5f );
130  if ( x - 0.5f == float( i ) && i & 1 ) i++;
131  }
132  return i;
133 }
134 
135 namespace CAMath
136 {
137 template<> inline bool Finite<float>( const float &x )
138 {
139  return choice( 1,
140  x < std::numeric_limits<float>::infinity() && -x < std::numeric_limits<float>::infinity(),
141  finite( x ) );
142 }
143 
144 template<> inline bool Finite<double>( const double &x )
145 {
146  return choice( 1,
147  x < std::numeric_limits<double>::infinity() && -x < std::numeric_limits<double>::infinity(),
148  finite( x ) );
149 }
150 
151 template<> inline float Round<float>( const float &x ) { return static_cast<float>( Nint( x ) ); }
152 
153 template<> inline float ATan2<float>( const float &y, const float &x )
154 {
155  return choice( atan2f( y, x ), atan2( y, x ), TMath::ATan2( y, x ) );
156 }
157 
158 template<> inline float ASin( const float &x )
159 {
160  return choice( asinf( x ), asin( x ), TMath::ASin( x ) );
161 }
162 
163 
164 } // namespace CAMath
165 
166 inline float CAMath::Copysign( float x, float y )
167 {
168  x = CAMath::Abs( x );
169  return ( y >= 0 ) ? x : -x;
170 }
171 
172 
173 inline float CAMath::Tan( float x )
174 {
175  return choice( tanf( x ), tan( x ), TMath::Tan( x ) );
176 }
177 
178 #ifdef USE_TBB
179 
180 #include <tbb/atomic.h>
181 
182 inline int CAMath::AtomicExch( int volatile *addr, int val )
183 {
184  tbb::atomic<int> &a = *reinterpret_cast<tbb::atomic<int> *>( const_cast<int *>( addr ) );
185  return a.fetch_and_store( val );
186 }
187 
188 inline int CAMath::AtomicAdd ( int volatile *addr, int val )
189 {
190  tbb::atomic<int> &a = *reinterpret_cast<tbb::atomic<int> *>( const_cast<int *>( addr ) );
191  return a.fetch_and_add( val );
192 }
193 
194 namespace CAMath
195 {
196 template<> inline int AtomicMax<int>( int volatile *addr, int val )
197 {
198  tbb::atomic<int> &a = *reinterpret_cast<tbb::atomic<int> *>( const_cast<int *>( addr ) );
199  int old = a;
200  if ( old < val ) {
201  while ( old != a.compare_and_swap( val, old ) ) {
202  old = a;
203  if ( old >= val ) {
204  break;
205  }
206  }
207  }
208  return old;
209 }
210 
211 template<> inline unsigned int AtomicMax<unsigned int>( unsigned int volatile *addr, unsigned int val )
212 {
213  tbb::atomic<unsigned int> &a = *reinterpret_cast<tbb::atomic<unsigned int> *>( const_cast<unsigned int *>( addr ) );
214  unsigned int old = a;
215  if ( old < val ) {
216  while ( old != a.compare_and_swap( val, old ) ) {
217  old = a;
218  if ( old >= val ) {
219  break;
220  }
221  }
222  }
223  return old;
224 }
225 } // namespace CAMath
226 
227 inline int CAMath::AtomicMin ( int volatile *addr, int val )
228 {
229  tbb::atomic<int> &a = *reinterpret_cast<tbb::atomic<int> *>( const_cast<int *>( addr ) );
230  int old = a;
231  if ( old > val ) {
232  while ( old != a.compare_and_swap( val, old ) ) {
233  old = a;
234  if ( old <= val ) {
235  break;
236  }
237  }
238  }
239  return old;
240 }
241 #endif //USE_TBB
242 
243 #undef choice
244 
245 #endif