gambit is hosted by Hepforge, IPPP Durham
GAMBIT  v1.5.0-252-gf9a3f78
a Global And Modular Bsm Inference Tool
functor_definitions.hpp
Go to the documentation of this file.
1 // GAMBIT: Global and Modular BSM Inference Tool
2 // *********************************************
35 
36 #ifndef __functor_definitions_hpp__
37 #define __functor_definitions_hpp__
38 
39 #include <chrono>
40 
43 #include "gambit/Models/models.hpp"
44 #include "gambit/Logs/logger.hpp"
45 #ifndef NO_PRINTERS
47 #endif
48 
49 #include <boost/preprocessor/seq/for_each.hpp>
50 #include <boost/io/ios_state.hpp>
51 
52 namespace Gambit
53 {
54  using namespace LogTags;
55 
57 
58  template <typename TYPE>
59  module_functor<TYPE>::module_functor(void (*inputFunction)(TYPE &),
60  str func_name,
61  str func_capability,
62  str result_type,
63  str origin_name,
65  : module_functor_common(func_name, func_capability, result_type, origin_name, claw),
66  myFunction (inputFunction),
67  myValue (NULL),
68  myPrintFlag (false)
69  {}
70 
72  template <typename TYPE>
74  {
75  if (myValue != NULL) delete [] myValue;
76  }
77 
79  template <typename TYPE>
80  void module_functor<TYPE>::setPrintRequirement(bool flag) { myPrintFlag = flag;}
81 
83  template <typename TYPE>
84  bool module_functor<TYPE>::requiresPrinting() const { return myPrintFlag; }
85 
88  template <typename TYPE>
90  {
91  if (myStatus == -3) // Do an explicit status check to hold standalone writers' hands
92  {
93  std::ostringstream ss;
94  ss << "Sorry, the function " << origin() << "::" << name()
95  << " cannot be used" << endl << "because it requires classes from a backend that you do not have installed."
96  << endl << "Missing backends: ";
97  for (auto it = missing_backends.begin(); it != missing_backends.end(); ++it) ss << endl << " " << *it;
98  backend_error().raise(LOCAL_INFO, ss.str());
99  }
100  boost::io::ios_flags_saver ifs(cout); // Don't allow module functions to change the output precision of cout
101  int thread_num = omp_get_thread_num();
102  init_memory(); // Init memory if this is the first run through.
103  if (needs_recalculating[thread_num]) // Do the actual calculation if required.
104  {
105  logger().entering_module(myLogTag);
106  this->startTiming(thread_num); //Begin timing function evaluation
107  try
108  {
109  this->myFunction(myValue[thread_num]); //Run and place result in the appropriate slot in myValue
110  }
111  catch (invalid_point_exception& e)
112  {
113  if (not point_exception_raised) acknowledgeInvalidation(e);
114  if (omp_get_level()==0) // If not in an OpenMP parallel block, throw onwards
115  {
116  this->finishTiming(thread_num); //Stop timing function evaluation
117  throw(e);
118  }
119  }
120  this->finishTiming(thread_num); //Stop timing function evaluation
122  }
123  }
124 
126  template <typename TYPE>
128  {
129  this->module_functor_common::init_memory();
130  if(myValue==NULL)
131  {
132  #pragma omp critical(module_functor_init_memory)
133  {
134  // Reserve enough space to hold as many results as there are slots (threads) allowed
135  if(myValue==NULL) myValue = new TYPE[(iRunNested ? globlMaxThreads : 1)];
136  }
137  }
138  }
139 
141  template <typename TYPE>
143  {
144  init_memory(); // Init memory if this is the first run through.
145  return (iRunNested ? myValue[index] : myValue[0]);
146  }
147 
149  template <typename TYPE>
151  {
152  init_memory(); // Init memory if this is the first run through.
153  return safe_ptr<TYPE>(myValue);
154  }
155 
156  #ifndef NO_PRINTERS
157  template <typename TYPE>
159  void module_functor<TYPE>::print(Printers::BasePrinter* printer, const int pointID, int thread_num)
160  {
161  // Only try to print if print flag set to true, and if this functor(+thread) hasn't already been printed
162  // TODO: though actually the printer system will probably cark it if printing from multiple threads is
163  // attempted, because it uses the VertexID to differentiate print streams, and this is shared among threads.
164  // Can fix by requiring a VertexID+thread_num pair, but I am leaving this for later.
165  init_memory(); // Init memory if this is the first run through.
166  if(myPrintFlag and not already_printed[thread_num] and type()!="void") // myPrintFlag should anyway not be true for void result types
167  {
168  if (not iRunNested) thread_num = 0; // Force printing of thread_num=0 if this functor cannot run nested.
169  int rank = printer->getRank(); // This is "first pass" printing, so use the actual rank of this process.
170  // In the auxilliary printing system we may tell the printer to overwrite
171  // the output of other ranks.
172  logger() << LogTags::debug << "Printing "<<myLabel<<" (vID="<<myVertexID<<", rank="<<rank<<", pID="<<pointID<<")" << EOM;
173  printer->print(myValue[thread_num],myLabel,myVertexID,rank,pointID);
174  already_printed[thread_num] = true;
175  }
176 
177  // Print timing info if requested (independent of whether printing actual result)
178  if(myTimingPrintFlag and not already_printed_timing[thread_num])
179  {
180  if (not iRunNested) thread_num = 0; // Force printing of thread_num=0 if this functor cannot run nested.
181  int rank = printer->getRank();
182  std::chrono::duration<double> runtime = end[thread_num] - start[thread_num];
183  logger() << LogTags::debug << "Printing "<<myTimingLabel<<" (vID="<<myTimingVertexID<<", rank="<<rank<<", pID="<<pointID<<")" << EOM;
184  printer->print(runtime.count(),myTimingLabel,myTimingVertexID,rank,pointID);
185  already_printed_timing[thread_num] = true;
186  }
187  }
188 
190  template <typename TYPE>
191  void module_functor<TYPE>::print(Printers::BasePrinter* printer, const int pointID) { print(printer,pointID,0); }
192  #endif
193 
194  // Backend_functor_common class method definitions
195 
197  template <typename PTR_TYPE, typename TYPE, typename... ARGS>
199  str func_name,
200  str func_capability,
201  str result_type,
202  str origin_name,
203  str origin_version,
204  str origin_safe_version,
206  : functor (func_name, func_capability, result_type, origin_name, claw),
207  myFunction (inputFunction),
208  myLogTag(-1),
209  inUse(false)
210  {
211  myVersion = origin_version;
212  mySafeVersion = origin_safe_version;
213  // Determine LogTag number
214  myLogTag = Logging::str2tag(myOrigin);
215  // Or in the case where we prefer to include the version number in the LogTag too
216  //myLogTag = Logging::str2tag(myOrigin+"v"+myVersion);
217  // Check for failure
218  if(myLogTag==-1)
219  {
220  std::ostringstream ss;
221  ss << "Error retrieving LogTag number (in functors.hpp, constructor for "
222  "backend_functor_common)! No match for backend name in tag2str map! "
223  "This is supposed to be a backend functor, so this is a fatal error. "
224  "(myOrigin=" << myOrigin << ", myName=" << myName << ")";
225  utils_error().raise(LOCAL_INFO,ss.str());
226  }
227  }
228 
230  template <typename PTR_TYPE, typename TYPE, typename... ARGS>
232  {
233  myFunction = inputFunction;
234  }
235 
237  template <typename PTR_TYPE, typename TYPE, typename... ARGS>
239  {
240  return myFunction;
241  }
242 
244  template <typename PTR_TYPE, typename TYPE, typename... ARGS>
246 
248  template <typename PTR_TYPE, typename TYPE, typename... ARGS>
250 
252  template <typename PTR_TYPE, typename TYPE, typename... ARGS>
254  {
255  return safe_ptr<bool>(&inUse);
256  }
257 
258 
259  // Actual non-variadic backend functor class method definitions for TYPE != void
260 
262  template <typename TYPE, typename... ARGS>
263  backend_functor<TYPE(*)(ARGS...), TYPE, ARGS...>::backend_functor (TYPE (*inputFunction)(ARGS...),
264  str func_name,
265  str func_capability,
266  str result_type,
267  str origin_name,
268  str origin_version,
269  str safe_version,
271  : backend_functor_common<TYPE(*)(ARGS...), TYPE, ARGS...>(inputFunction, func_name,
272  func_capability, result_type, origin_name, origin_version, safe_version, claw) {}
273 
275  template <typename TYPE, typename... ARGS>
276  TYPE backend_functor<TYPE(*)(ARGS...), TYPE, ARGS...>::operator()(ARGS&&... args)
277  {
278  logger().entering_backend(this->myLogTag);
279  TYPE tmp = this->myFunction(std::forward<ARGS>(args)...);
281  return tmp;
282  }
283 
284 
285  // Actual non-variadic backend functor class method definitions for TYPE=void
286 
288  template <typename... ARGS>
289  backend_functor<void(*)(ARGS...), void, ARGS...>::backend_functor (void (*inputFunction)(ARGS...),
290  str func_name,
291  str func_capability,
292  str result_type,
293  str origin_name,
294  str origin_version,
295  str safe_version,
297  : backend_functor_common<void(*)(ARGS...), void, ARGS...>(inputFunction, func_name,
298  func_capability, result_type, origin_name, origin_version, safe_version, claw) {}
299 
301  template <typename... ARGS>
302  void backend_functor<void(*)(ARGS...), void, ARGS...>::operator()(ARGS&&... args)
303  {
304  logger().entering_backend(this->myLogTag);
305  this->myFunction(std::forward<ARGS>(args)...);
307  }
308 
309  // Actual variadic backend functor class method definitions for TYPE != void
310 
312  template <typename TYPE, typename... ARGS>
313  backend_functor<typename variadic_ptr<TYPE,ARGS...>::type, TYPE, ARGS...>::backend_functor
314  (typename variadic_ptr<TYPE,ARGS...>::type inputFunction, str func_name, str func_capability, str result_type,
315  str origin_name, str origin_version, str safe_version, Models::ModelFunctorClaw &claw)
316  : backend_functor_common<typename variadic_ptr<TYPE,ARGS...>::type, TYPE, ARGS...>(inputFunction, func_name,
317  func_capability, result_type, origin_name, origin_version, safe_version, claw) {}
318 
319  // Actual variadic backend functor class method definitions for TYPE=void
320 
322  template <typename... ARGS>
324  (typename variadic_ptr<void,ARGS...>::type inputFunction, str func_name, str func_capability, str result_type,
325  str origin_name, str origin_version, str safe_version, Models::ModelFunctorClaw &claw)
326  : backend_functor_common<typename variadic_ptr<void,ARGS...>::type, void, ARGS...>(inputFunction, func_name,
327  func_capability, result_type, origin_name, origin_version, safe_version, claw) {}
328 
329 }
330 
331 #endif /* defined(__functor_definitions_hpp__) */
void print(MixMatrix A)
Helper function to print a matrix.
Backend functor class for functions with result type TYPE and argumentlist ARGS.
Definition: functors.hpp:833
Model helper declarations.
EXPORT_SYMBOLS error & utils_error()
Utility errors.
A safe pointer that throws an informative error if you try to dereference it when nullified...
Definition: util_types.hpp:167
Actual module functor type for all but TYPE=void.
Definition: functors.hpp:745
#define LOCAL_INFO
Definition: local_info.hpp:34
Function wrapper (functor) base class.
Definition: functors.hpp:87
void entering_module(int)
Set the internal variables tracking which module and/or backend is currently running.
Definition: logmaster.cpp:616
int str2tag(const std::string &)
Definition: logging.cpp:152
Logging access header for GAMBIT.
module_functor(void(*)(TYPE &), str, str, str, str, Models::ModelFunctorClaw &)
Constructor.
Gambit invalid point exception class.
Definition: exceptions.hpp:226
Functor derived class for module functions.
Definition: functors.hpp:399
Models object that performs initialisation and checking operations on a primary_model_functor list...
Definition: models.hpp:55
error & backend_error()
Backend errors.
Functor class definitions.
const Logging::endofmessage EOM
Explicit const instance of the end of message struct in Gambit namespace.
Definition: logger.hpp:99
Logging::LogMaster & logger()
Function to retrieve a reference to the Gambit global log object.
Definition: logger.cpp:95
Printers::BaseBasePrinter printer
Type of the printer objects.
Declaration and definition of printer base class.
hb_ModelParameters void
Actual backend functor type.
Definition: functors.hpp:880
std::string str
Shorthand for a standard string.
Definition: Analysis.hpp:35
Type redefinition to get around icc compiler bugs.
Definition: functors.hpp:73
Exception objects required for standalone compilation.
TYPE(*)(ARGS...) funcPtrType
Type of the function pointer being encapsulated.
Definition: functors.hpp:842
TODO: see if we can use this one:
Definition: Analysis.hpp:33