ATLAS Offline Software
StackElement.icc
Go to the documentation of this file.
1 // Dear emacs, this is -*- c++ -*-
2 
3 /*
4  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
5 */
6 
7 // $Id$
8 #ifndef EXPRESSIONEVALUATION_STACKELEMENT_ICC
9 #define EXPRESSIONEVALUATION_STACKELEMENT_ICC
10 
11 // System include(s):
12 #include <cmath>
13 #include <stdexcept>
14 
15 namespace ExpressionParsing {
16  inline StackElement::StackElement(const StackElement &a)
17  : m_type(a.m_type),
18  m_intVal(a.m_intVal),
19  m_doubleVal(a.m_doubleVal),
20  m_vecIntVal(a.m_vecIntVal),
21  m_vecDoubleVal(a.m_vecDoubleVal),
22  m_varName(a.m_varName),
23  m_proxyLoader(a.m_proxyLoader),
24  m_variableType(static_cast<IProxyLoader::VariableType>(a.m_variableType)),
25  m_determinedVariableType(a.m_determinedVariableType ? true : false)
26  {
27  if (a.m_moved) throw std::logic_error("Content already moved"); \
28  }
29  inline StackElement::StackElement(StackElement &&a)
30  : m_type(a.m_type),
31  m_intVal(a.m_intVal),
32  m_doubleVal(a.m_doubleVal),
33  m_vecIntVal(std::move(a.m_vecIntVal)),
34  m_vecDoubleVal(std::move(a.m_vecDoubleVal)),
35  m_varName(std::move(a.m_varName)),
36  m_proxyLoader(a.m_proxyLoader),
37  m_variableType(static_cast<IProxyLoader::VariableType>(a.m_variableType)),
38  m_determinedVariableType(a.m_determinedVariableType ? true : false)
39  {
40  if (a.m_moved) throw std::logic_error("Content already moved");
41  }
42 
43  inline StackElement &StackElement::operator=(StackElement &&a) {
44  if (&a != this) {
45  if (a.m_moved) throw std::logic_error("Content already moved");
46  m_type = a.m_type;
47  m_intVal = a.m_intVal;
48  m_doubleVal = a.m_doubleVal;
49  m_vecIntVal = std::move(a.m_vecIntVal);
50  m_vecDoubleVal = std::move(a.m_vecDoubleVal);
51  m_varName = std::move(a.m_varName);
52  m_proxyLoader = a.m_proxyLoader;
53  m_variableType = static_cast<IProxyLoader::VariableType>(a.m_variableType);
54  m_determinedVariableType = a.m_determinedVariableType ? true : false;
55  m_moved = false;
56  }
57  return *this;
58  }
59 
60  inline size_t StackElement::size() const {
61  switch( m_type ) {
62 
63  case SE_VECINT:
64  return m_vecIntVal.size();
65  break;
66 
67  case SE_VECDOUBLE:
68  return m_vecDoubleVal.size();
69  break;
70 
71  case SE_INT: [[fallthrough]] ;
72  case SE_DOUBLE:
73  return 1; // @TOOD 0?
74  break;
75 
76  default:
77  throw std::runtime_error( "size(): Unsupported StackElement" );
78  break;
79  }
80  }
81 
82  /// Declare specialisations required in subsequent code
83  template<>
84  std::vector< int >
85  StackElement::vectorValue( std::size_t sizeIfScalar ) ;
86  template<>
87  std::vector< double >
88  StackElement::vectorValue( std::size_t sizeIfScalar ) ;
89 
90 
91 
92 #define ASSIGN_OP( OP ) \
93  template< typename T > \
94  StackElement& StackElement::operator OP( const T& rhs ) { \
95  makeDoubleIfNecessary( rhs ); \
96  switch( m_type ) { \
97  case SE_INT: \
98  m_intVal OP rhs; \
99  break; \
100  case SE_DOUBLE: \
101  m_doubleVal OP rhs; \
102  break; \
103  case SE_VECINT: \
104  for( int& value : m_vecIntVal ) { \
105  value OP rhs; \
106  } \
107  break; \
108  case SE_VECDOUBLE: \
109  for( double& value : m_vecDoubleVal ) { \
110  value OP rhs; \
111  } \
112  break; \
113  default: \
114  throw std::runtime_error( "StackElement ill-defined in " \
115  "scalar " #OP ); \
116  break; \
117  } \
118  return *this; \
119  } \
120  template< typename T > \
121  StackElement& \
122  StackElement::operator OP( const std::vector< T >& rhs ) { \
123  makeVectorIfNecessary( rhs ); \
124  makeDoubleIfNecessary( rhs ); \
125  ensureCompatibleVectors( rhs ); \
126  switch( m_type ) { \
127  case SE_VECINT: \
128  for( std::size_t i = 0; i < rhs.size(); ++i ) { \
129  m_vecIntVal[ i ] OP rhs[ i ]; \
130  } \
131  break; \
132  case SE_VECDOUBLE: \
133  for( std::size_t i = 0; i < rhs.size(); ++i ) { \
134  m_vecDoubleVal[i] OP rhs[ i ]; \
135  } \
136  break; \
137  default: \
138  throw std::runtime_error( "StackElement ill-defined in " \
139  "vector " #OP ); \
140  break; \
141  } \
142  return *this; \
143  } \
144 
145  ASSIGN_OP( -= )
146  ASSIGN_OP( += )
147  ASSIGN_OP( *= )
148  ASSIGN_OP( /= )
149 
150 #undef ASSIGN_OP
151 
152 #define BINARY_MUTING_OP( OP ) \
153  template< typename T > \
154  StackElement StackElement::operator OP( const T& rhs ) { \
155  if (this->m_moved) throw std::logic_error("Content already moved");\
156  StackElement temp( std::move(*this) ); \
157  this->m_moved=true; \
158  temp OP ## = rhs; \
159  return temp; \
160  }
161 
162  BINARY_MUTING_OP( - )
163  BINARY_MUTING_OP( + )
164  BINARY_MUTING_OP( * )
165  BINARY_MUTING_OP( / )
166 
167 #undef BINARY_MUTING_OP
168 
169  template< typename T >
170  std::vector< T > StackElement::vectorValue( std::size_t ) {
171 
172  throw std::runtime_error( "Unsupported vector type requested" );
173  }
174 
175  template< typename T >
176  StackElement StackElement::_pow( const T& n ) {
177 
178  if (this->m_moved) throw std::logic_error("Content already moved");
179  StackElement temp( std::move(*this) );
180  this->m_moved=true;
181  temp.makeDouble();
182 
183  switch( temp.m_type ) {
184 
185  case SE_DOUBLE:
186  temp.m_doubleVal = std::pow( temp.m_doubleVal, n );
187  return temp;
188  break;
189 
190  case SE_VECDOUBLE:
191  for( std::size_t i = 0; i < temp.m_vecDoubleVal.size(); ++i ) {
192  temp.m_vecDoubleVal[ i ] = std::pow( temp.m_vecDoubleVal[ i ], n );
193  }
194  return temp;
195  break;
196 
197  default:
198  return 0;
199  break;
200  }
201  }
202 
203  template<>
204  StackElement StackElement::_pow( const StackElement& n );
205 
206  template< typename T >
207  T StackElement::scalarValue() const {
208 
209  switch( m_type ) {
210 
211  case SE_INT:
212  return m_intVal;
213  break;
214 
215  case SE_DOUBLE:
216  return m_doubleVal;
217  break;
218 
219  case SE_VECINT:
220  case SE_VECDOUBLE:
221  case SE_UNK:
222  default:
223  throw std::runtime_error( "Trying to cast vector to scalar!" );
224  break;
225  }
226  }
227 
228  template< typename T >
229  void StackElement::ensureCompatibleVectors( const T& ) const {
230 
231  throw std::runtime_error( "Can't compare vector to arbitrary type!" );
232  }
233 
234  template< typename T >
235  void StackElement::
236  ensureCompatibleVectors( const std::vector< T >& other ) const {
237 
238  if( isScalar() ) {
239  return;
240  }
241 
242  const std::size_t ourlen = this->size();
243  if( ourlen != other.size() ) {
244  throw std::runtime_error( "Incompatible vectors - different length" );
245  }
246  }
247 
248 } // namespace ExpressionParsing
249 
250 #endif // EXPRESSIONEVALUATION_STACKELEMENT_ICC