Geant4  10.01.p03
CexmcAST.cc
Go to the documentation of this file.
1 //
2 // ********************************************************************
3 // * License and Disclaimer *
4 // * *
5 // * The Geant4 software is copyright of the Copyright Holders of *
6 // * the Geant4 Collaboration. It is provided under the terms and *
7 // * conditions of the Geant4 Software License, included in the file *
8 // * LICENSE and available at http://cern.ch/geant4/license . These *
9 // * include a list of copyright holders. *
10 // * *
11 // * Neither the authors of this software system, nor their employing *
12 // * institutes,nor the agencies providing financial support for this *
13 // * work make any representation or warranty, express or implied, *
14 // * regarding this software system or assume any liability for its *
15 // * use. Please see the license in the file LICENSE and URL above *
16 // * for the full disclaimer and the limitation of liability. *
17 // * *
18 // * This code implementation is the result of the scientific and *
19 // * technical work of the GEANT4 collaboration. *
20 // * By using, copying, modifying or distributing the software (or *
21 // * any work based on the software) you agree to acknowledge its *
22 // * use in resulting scientific publications, and indicate your *
23 // * acceptance of all terms of the Geant4 Software license. *
24 // ********************************************************************
25 //
26 /*
27  * =============================================================================
28  *
29  * Filename: CexmcAST.cc
30  *
31  * Description: abstract syntax tree for custom filter scripting language
32  *
33  * Version: 1.0
34  * Created: 17.07.2010 14:45:14
35  * Revision: none
36  * Compiler: gcc
37  *
38  * Author: Alexey Radkov (),
39  * Company: PNPI
40  *
41  * =============================================================================
42  */
43 
44 #ifdef CEXMC_USE_CUSTOM_FILTER
45 
46 #include <iostream>
47 #include <sstream>
48 #include <string>
49 #include <cmath>
50 #include <boost/variant/get.hpp>
51 #include <boost/format.hpp>
52 #include "CexmcAST.hh"
53 #include "CexmcException.hh"
54 
55 
56 namespace CexmcAST
57 {
58  void Subtree::Print( int level ) const
59  {
60  static const std::string opId[] =
61  { "UNINITIALIZED", "TOP", "u -", "!", "*", "/", "+", "-", "<", "<=",
62  ">", ">=", "=", "!=", "&", "|" };
63 
64  std::stringstream value;
65  const Operator * op( boost::get< Operator >( &type ) );
66 
67  if ( op )
68  {
69  value << "-op- " << opId[ op->type ];
70  }
71  else
72  {
73  const Function * fun( boost::get< Function >( &type ) );
74  value << "-fun- " << *fun;
75  }
76 
77  std::stringstream format;
78  format << "%|" << level * printIndent << "t|";
79  std::cout << boost::format( format.str() ) << value.str() << std::endl;
80 
81  for ( std::vector< Node >::const_iterator k( children.begin() );
82  k != children.end(); ++k )
83  {
84  const Subtree * subtree( boost::get< Subtree >( &*k ) );
85 
86  if ( subtree )
87  {
88  subtree->Print( level + 1 );
89  }
90  else
91  {
92  const Leaf * leaf( boost::get< Leaf >( &*k ) );
93  if ( leaf )
94  PrintLeaf( leaf, level + 1 );
95  }
96  }
97  }
98 
99 
100  void Subtree::PrintLeaf( const Leaf * leaf, int level ) const
101  {
102  const Variable * variable( NULL );
103  std::stringstream value;
104 
105  if ( ( variable = boost::get< Variable >( leaf ) ) )
106  {
107  value << variable->name;
108  if ( variable->index1 > 0 )
109  {
110  value << "[" << variable->index1;
111  if ( variable->index2 > 0 )
112  value << "," << variable->index2;
113  value << "]";
114  }
115  }
116  else
117  {
118  const Constant * constant( boost::get< Constant >( leaf ) );
119  const int * intConstant( boost::get< int >( constant ) );
120  const double * doubleConstant( boost::get< double >(
121  constant ) );
122 
123  value << ( intConstant ? *intConstant : *doubleConstant );
124  }
125 
126  std::stringstream format;
127  format << "%|" << level * printIndent << "t|";
128  std::cout << boost::format( format.str() ) << value.str() << std::endl;
129  }
130 
131 
132  BasicEval::~BasicEval()
133  {
134  }
135 
136 
137  bool BasicEval::operator()( const Subtree & ast ) const
138  {
139  ScalarValueType retval( GetScalarValue( ast ) );
140  int * intRetval( NULL );
141  double * doubleRetval( NULL );
142 
143  intRetval = boost::get< int >( &retval );
144 
145  if ( ! intRetval )
146  doubleRetval = boost::get< double >( &retval );
147 
148  return doubleRetval ? bool( *doubleRetval ) : bool( *intRetval );
149  }
150 
151 
152  BasicEval::ScalarValueType BasicEval::GetScalarValue(
153  const Node & node ) const
154  {
155  const Subtree * ast( boost::get< Subtree >( &node ) );
156 
157  if ( ast )
158  {
159  const Operator * op( boost::get< Operator >( &ast->type ) );
160  if ( op )
161  {
162  ScalarValueType left( 0 );
163  ScalarValueType right( 0 );
164  int * intLeft( NULL );
165  double * doubleLeft( NULL );
166  int * intRight( NULL );
167  double * doubleRight( NULL );
168  bool isDoubleRetval( false );
169 
170  if ( ast->children.size() > 0 )
171  {
172  left = GetScalarValue( ast->children[ 0 ] );
173  intLeft = boost::get< int >( &left );
174  if ( ! intLeft )
175  {
176  doubleLeft = boost::get< double >( &left );
177  if ( ! doubleLeft )
178  throw CexmcException( CexmcCFUnexpectedContext );
179  }
180  }
181 
182  switch ( op->type )
183  {
184  case And :
185  case Or :
186  break;
187  default :
188  if ( ast->children.size() > 1 )
189  {
190  right = GetScalarValue( ast->children[ 1 ] );
191  intRight = boost::get< int >( &right );
192  if ( ! intRight )
193  {
194  doubleRight = boost::get< double >( &right );
195  if ( ! doubleRight )
196  throw CexmcException(
197  CexmcCFUnexpectedContext );
198  }
199  }
200  isDoubleRetval = doubleLeft || doubleRight;
201  break;
202  }
203 
204  switch ( op->type )
205  {
206  case Uninitialized :
207  return 1;
208  case Top :
209  return left;
210  case UMinus :
211  if ( doubleLeft )
212  return - *doubleLeft;
213  else
214  return - *intLeft;
215  case Not :
216  if ( doubleLeft )
217  return ! *doubleLeft;
218  else
219  return ! *intLeft;
220  case Mult :
221  if ( isDoubleRetval )
222  return ( doubleLeft ? *doubleLeft : *intLeft ) *
223  ( doubleRight ? *doubleRight : *intRight );
224  else
225  return *intLeft * *intRight;
226  case Div :
227  if ( isDoubleRetval )
228  return ( doubleLeft ? *doubleLeft : *intLeft ) /
229  ( doubleRight ? *doubleRight : *intRight );
230  else
231  return *intLeft / *intRight;
232  case Plus :
233  if ( isDoubleRetval )
234  return ( doubleLeft ? *doubleLeft : *intLeft ) +
235  ( doubleRight ? *doubleRight : *intRight );
236  else
237  return *intLeft + *intRight;
238  case Minus :
239  if ( isDoubleRetval )
240  return ( doubleLeft ? *doubleLeft : *intLeft ) -
241  ( doubleRight ? *doubleRight : *intRight );
242  else
243  return *intLeft - *intRight;
244  case Less :
245  if ( isDoubleRetval )
246  return ( doubleLeft ? *doubleLeft : *intLeft ) <
247  ( doubleRight ? *doubleRight : *intRight );
248  else
249  return *intLeft < *intRight;
250  case LessEq :
251  if ( isDoubleRetval )
252  return ( doubleLeft ? *doubleLeft : *intLeft ) <=
253  ( doubleRight ? *doubleRight : *intRight );
254  else
255  return *intLeft <= *intRight;
256  case More :
257  if ( isDoubleRetval )
258  return ( doubleLeft ? *doubleLeft : *intLeft ) >
259  ( doubleRight ? *doubleRight : *intRight );
260  else
261  return *intLeft > *intRight;
262  case MoreEq :
263  if ( isDoubleRetval )
264  return ( doubleLeft ? *doubleLeft : *intLeft ) >=
265  ( doubleRight ? *doubleRight : *intRight );
266  else
267  return *intLeft >= *intRight;
268  case Eq :
269  if ( isDoubleRetval )
270  return ( doubleLeft ? *doubleLeft : *intLeft ) ==
271  ( doubleRight ? *doubleRight : *intRight );
272  else
273  return *intLeft == *intRight;
274  case NotEq :
275  if ( isDoubleRetval )
276  return ( doubleLeft ? *doubleLeft : *intLeft ) !=
277  ( doubleRight ? *doubleRight : *intRight );
278  else
279  return *intLeft != *intRight;
280  case And :
281  if ( doubleLeft )
282  {
283  if ( ! *doubleLeft )
284  return 0;
285  }
286  else
287  {
288  if ( ! *intLeft )
289  return 0;
290  }
291  right = GetScalarValue( ast->children[ 1 ] );
292  intRight = boost::get< int >( &right );
293  if ( ! intRight )
294  {
295  doubleRight = boost::get< double >( &right );
296  if ( ! doubleRight )
297  throw CexmcException( CexmcCFUnexpectedContext );
298  }
299  if ( doubleRight )
300  {
301  if ( *doubleRight )
302  return 1;
303  }
304  else
305  {
306  if ( *intRight )
307  return 1;
308  }
309  return 0;
310  case Or :
311  if ( doubleLeft )
312  {
313  if ( *doubleLeft )
314  return 1;
315  }
316  else
317  {
318  if ( *intLeft )
319  return 1;
320  }
321  right = GetScalarValue( ast->children[ 1 ] );
322  intRight = boost::get< int >( &right );
323  if ( ! intRight )
324  {
325  doubleRight = boost::get< double >( &right );
326  if ( ! doubleRight )
327  throw CexmcException( CexmcCFUnexpectedContext );
328  }
329  if ( doubleRight )
330  {
331  if ( *doubleRight )
332  return 1;
333  }
334  else
335  {
336  if ( *intRight )
337  return 1;
338  }
339  return 0;
340  default :
341  return 0;
342  }
343  }
344  else
345  {
346  return GetFunScalarValue( *ast );
347  }
348  }
349  else
350  {
351  const Leaf & leaf( boost::get< Leaf >( node ) );
352  const Constant * constant( boost::get< Constant >( &leaf ) );
353 
354  if ( constant )
355  {
356  return *constant;
357  }
358  else
359  {
360  const Variable & variable( boost::get< Variable >( leaf ) );
361  return GetVarScalarValue( variable );
362  }
363  }
364 
365  return 0;
366  }
367 
368 
369  BasicEval::ScalarValueType BasicEval::GetFunScalarValue(
370  const Subtree & ast ) const
371  {
372  bool evalResult( false );
373  ScalarValueType result( GetBasicFunScalarValue( ast, evalResult ) );
374 
375  if ( evalResult )
376  return result;
377 
378  throw CexmcException( CexmcCFUnexpectedFunction );
379 
380  return 0;
381  }
382 
383 
384  BasicEval::ScalarValueType BasicEval::GetVarScalarValue(
385  const Variable & ) const
386  {
387  throw CexmcException( CexmcCFUnexpectedVariable );
388 
389  return 0;
390  }
391 
392 
393  BasicEval::ScalarValueType BasicEval::GetBasicFunScalarValue(
394  const Subtree & ast, bool & result ) const
395  {
396  const Function & fun( boost::get< Function >( ast.type ) );
397 
398  result = true;
399 
400  ScalarValueType arg( GetScalarValue( ast.children[ 0 ] ) );
401  int * intArg( NULL );
402  double * doubleArg( NULL );
403 
404  intArg = boost::get< int >( &arg );
405  if ( ! intArg )
406  doubleArg = boost::get< double >( &arg );
407 
408  if ( fun == "Sqr" )
409  {
410  if ( doubleArg )
411  return *doubleArg * *doubleArg;
412  else
413  return *intArg * *intArg;
414  }
415  if ( fun == "Sqrt" )
416  {
417  if ( doubleArg )
418  return std::sqrt( *doubleArg );
419  else
420  return std::sqrt( *intArg );
421  }
422 
423  result = false;
424 
425  return 0;
426  }
427 }
428 
429 #endif
430 
static int variable(const string &name, double &result, const dic_type &dictionary)
Definition: Evaluator.cc:71
void Print(G4Element &ele)
Definition: pyG4Element.cc:56