GeNN  3.3.0
GPU enhanced Neuronal Networks (GeNN)
codeGenUtils.h
Go to the documentation of this file.
1 #pragma once
2 
3 // Standard includes
4 #include <iomanip>
5 #include <limits>
6 #include <string>
7 #include <sstream>
8 #include <vector>
9 
10 // GeNN includes
11 #include "variableMode.h"
12 
13 using namespace std;
14 
15 // Forward declarations
16 class NNmodel;
17 class SynapseGroup;
18 
19 namespace NeuronModels
20 {
21  class Base;
22 }
23 
24 namespace NewModels
25 {
26  class VarInit;
27 }
28 
29 //--------------------------------------------------------------------------
30 // GenericFunction
31 //--------------------------------------------------------------------------
35 {
37  const std::string genericName;
38 
40  const unsigned int numArguments;
41 };
42 
43 //--------------------------------------------------------------------------
44 // FunctionTemplate
45 //--------------------------------------------------------------------------
48 
50 {
51  // **HACK** while GCC and CLang automatically generate this fine/don't require it, VS2013 seems to need it
52  FunctionTemplate operator = (const FunctionTemplate &o)
53  {
55  }
56 
58  const std::string genericName;
59 
61  const unsigned int numArguments;
62 
64  const std::string doublePrecisionTemplate;
65 
67  const std::string singlePrecisionTemplate;
68 };
69 
70 //--------------------------------------------------------------------------
71 // PairKeyConstIter
72 //--------------------------------------------------------------------------
74 template<typename BaseIter>
75 class PairKeyConstIter : public BaseIter
76 {
77 private:
78  //--------------------------------------------------------------------------
79  // Typedefines
80  //--------------------------------------------------------------------------
81  typedef typename BaseIter::value_type::first_type KeyType;
82 
83 public:
85  PairKeyConstIter(BaseIter iter) : BaseIter(iter) {}
86 
87  //--------------------------------------------------------------------------
88  // Operators
89  //--------------------------------------------------------------------------
90  const KeyType *operator -> () const
91  {
92  return (const KeyType *) &(BaseIter::operator -> ( )->first);
93  }
94 
95  const KeyType &operator * () const
96  {
97  return BaseIter::operator * ( ).first;
98  }
99 };
100 
102 template<typename BaseIter>
104 {
105  return iter;
106 }
107 
108 //--------------------------------------------------------------------------
110 //--------------------------------------------------------------------------
111 const std::vector<FunctionTemplate> cudaFunctions = {
112  {"gennrand_uniform", 0, "curand_uniform_double($(rng))", "curand_uniform($(rng))"},
113  {"gennrand_normal", 0, "curand_normal_double($(rng))", "curand_normal($(rng))"},
114  {"gennrand_exponential", 0, "exponentialDistDouble($(rng))", "exponentialDistFloat($(rng))"},
115  {"gennrand_log_normal", 2, "curand_log_normal_double($(rng), $(0), $(1))", "curand_log_normal_float($(rng), $(0), $(1))"},
116  {"gennrand_gamma", 1, "gammaDistDouble($(rng), $(0))", "gammaDistFloat($(rng), $(0))"}
117 };
118 
119 //--------------------------------------------------------------------------
121 //--------------------------------------------------------------------------
122 const std::vector<FunctionTemplate> cpuFunctions = {
123  {"gennrand_uniform", 0, "standardUniformDistribution($(rng))", "standardUniformDistribution($(rng))"},
124  {"gennrand_normal", 0, "standardNormalDistribution($(rng))", "standardNormalDistribution($(rng))"},
125  {"gennrand_exponential", 0, "standardExponentialDistribution($(rng))", "standardExponentialDistribution($(rng))"},
126  {"gennrand_log_normal", 2, "std::lognormal_distribution<double>($(0), $(1))($(rng))", "std::lognormal_distribution<float>($(0), $(1))($(rng))"},
127  {"gennrand_gamma", 1, "std::gamma_distribution<double>($(0), 1.0)($(rng))", "std::gamma_distribution<float>($(0), 1.0f)($(rng))"}
128 };
129 
130 //--------------------------------------------------------------------------
132 //--------------------------------------------------------------------------
133 void substitute(string &s, const string &trg, const string &rep);
134 
135 //--------------------------------------------------------------------------
137 //--------------------------------------------------------------------------
138 bool regexVarSubstitute(string &s, const string &trg, const string &rep);
139 
140 //--------------------------------------------------------------------------
142 //--------------------------------------------------------------------------
143 bool regexFuncSubstitute(string &s, const string &trg, const string &rep);
144 
145 //--------------------------------------------------------------------------
147 //--------------------------------------------------------------------------
148 bool isRNGRequired(const std::string &code);
149 
150 //--------------------------------------------------------------------------
152 //--------------------------------------------------------------------------
153 bool isInitRNGRequired(const std::vector<NewModels::VarInit> &varInitialisers, const std::vector<VarMode> &varModes,
154  VarInit initLocation);
155 
156 //--------------------------------------------------------------------------
166 //--------------------------------------------------------------------------
167 void functionSubstitute(std::string &code, const std::string &funcName,
168  unsigned int numParams, const std::string &replaceFuncTemplate);
169 
170 //--------------------------------------------------------------------------
172 //--------------------------------------------------------------------------
173 template<typename NameIter>
174 inline void name_substitutions(string &code, const string &prefix, NameIter namesBegin, NameIter namesEnd, const string &postfix= "", const string &ext = "")
175 {
176  for (NameIter n = namesBegin; n != namesEnd; n++) {
177  substitute(code,
178  "$(" + *n + ext + ")",
179  prefix + *n + postfix);
180  }
181 }
182 
183 //--------------------------------------------------------------------------
185 //--------------------------------------------------------------------------
186 inline void name_substitutions(string &code, const string &prefix, const vector<string> &names, const string &postfix= "", const string &ext = "")
187 {
188  name_substitutions(code, prefix, names.cbegin(), names.cend(), postfix, ext);
189 }
190 
191 //--------------------------------------------------------------------------
193 //--------------------------------------------------------------------------
194 template<class T, typename std::enable_if<std::is_floating_point<T>::value>::type* = nullptr>
195 void writePreciseString(std::ostream &os, T value)
196 {
197  // Cache previous precision
198  const std::streamsize previousPrecision = os.precision();
199 
200  // Set scientific formatting
201  os << std::scientific;
202 
203  // Set precision to what is required to fully represent T
204  os << std::setprecision(std::numeric_limits<T>::max_digits10);
205 
206  // Write value to stream
207  os << value;
208 
209  // Reset to default formatting
210  // **YUCK** GCC 4.8.X doesn't seem to include std::defaultfloat
211  os.unsetf(std::ios_base::floatfield);
212  //os << std::defaultfloat;
213 
214  // Restore previous precision
215  os << std::setprecision(previousPrecision);
216 }
217 
218 //--------------------------------------------------------------------------
220 //--------------------------------------------------------------------------
221 template<class T, typename std::enable_if<std::is_floating_point<T>::value>::type* = nullptr>
222 std::string writePreciseString(T value)
223 {
224  std::stringstream s;
225  writePreciseString(s, value);
226  return s.str();
227 }
228 
229 //--------------------------------------------------------------------------
231 //--------------------------------------------------------------------------
232 template<typename NameIter>
233 inline void value_substitutions(string &code, NameIter namesBegin, NameIter namesEnd, const vector<double> &values, const string &ext = "")
234 {
235  NameIter n = namesBegin;
236  auto v = values.cbegin();
237  for (;n != namesEnd && v != values.cend(); n++, v++) {
238  stringstream stream;
239  writePreciseString(stream, *v);
240  substitute(code,
241  "$(" + *n + ext + ")",
242  "(" + stream.str() + ")");
243  }
244 }
245 
246 //--------------------------------------------------------------------------
248 //--------------------------------------------------------------------------
249 inline void value_substitutions(string &code, const vector<string> &names, const vector<double> &values, const string &ext = "")
250 {
251  value_substitutions(code, names.cbegin(), names.cend(), values, ext);
252 }
253 
254 //--------------------------------------------------------------------------
256 //--------------------------------------------------------------------------
257 void functionSubstitutions(std::string &code, const std::string &ftype,
258  const std::vector<FunctionTemplate> functions);
259 
260 //--------------------------------------------------------------------------
263 //--------------------------------------------------------------------------
264 string ensureFtype(const string &oldcode, const string &type);
265 
266 
267 //--------------------------------------------------------------------------
270 //--------------------------------------------------------------------------
271 void checkUnreplacedVariables(const string &code, const string &codeName);
272 
273 //--------------------------------------------------------------------------
276 //--------------------------------------------------------------------------
277 uint32_t hashString(const std::string &string);
278 
279 
281  string &wCode,
282  const SynapseGroup *sg,
283  const string &offset,
284  const string &axonalDelayOffset,
285  const string &postIdx,
286  const string &devPrefix,
287  const string &preVarPrefix = "",
288  const string &preVarSuffix = "");
289 
291  string &wCode,
292  const SynapseGroup *sg,
293  const string &offset,
294  const string &backPropDelayOffset,
295  const string &preIdx,
296  const string &devPrefix,
297  const string &postVarPrefix = "",
298  const string &postVarSuffix = "");
299 
300 //-------------------------------------------------------------------------
304 //-------------------------------------------------------------------------
306  string &wCode,
307  const SynapseGroup *sg,
308  const string &preIdx,
309  const string &postIdx,
310  const string &devPrefix,
311  double dt,
312  const string &preVarPrefix = "",
313  const string &preVarSuffix = "",
314  const string &postVarPrefix = "",
315  const string &postVarSuffix = "");
bool isInitRNGRequired(const std::vector< NewModels::VarInit > &varInitialisers, const std::vector< VarMode > &varModes, VarInit initLocation)
Does the model with the vectors of variable initialisers and modes require an RNG for the specified i...
Definition: codeGenUtils.cc:305
void functionSubstitute(std::string &code, const std::string &funcName, unsigned int numParams, const std::string &replaceFuncTemplate)
This function substitutes function calls in the form:
Definition: codeGenUtils.cc:350
const std::string doublePrecisionTemplate
The function template (for use with functionSubstitute) used when model uses double precision...
Definition: codeGenUtils.h:64
Definition: modelSpec.h:132
const std::vector< FunctionTemplate > cpuFunctions
CPU implementations of standard functions.
Definition: codeGenUtils.h:122
Definition: newModels.h:36
void postNeuronSubstitutionsInSynapticCode(string &wCode, const SynapseGroup *sg, const string &offset, const string &backPropDelayOffset, const string &preIdx, const string &devPrefix, const string &postVarPrefix="", const string &postVarSuffix="")
suffix to be used for postsynaptic variable accesses - typically combined with prefix to wrap in func...
Definition: codeGenUtils.cc:664
void name_substitutions(string &code, const string &prefix, NameIter namesBegin, NameIter namesEnd, const string &postfix="", const string &ext="")
This function performs a list of name substitutions for variables in code snippets.
Definition: codeGenUtils.h:174
type
Definition: generate_swig_interfaces.py:680
uint32_t hashString(const std::string &string)
This function returns the 32-bit hash of a string - because these are used across MPI nodes which may...
Definition: codeGenUtils.cc:586
bool isRNGRequired(const std::string &code)
Does the code string contain any functions requiring random number generator.
Definition: codeGenUtils.cc:280
PairKeyConstIter< BaseIter > GetPairKeyConstIter(BaseIter iter)
Helper function for creating a PairKeyConstIter from an iterator.
Definition: codeGenUtils.h:103
void functionSubstitutions(std::string &code, const std::string &ftype, const std::vector< FunctionTemplate > functions)
This function performs a list of function substitutions in code snipped.
Definition: codeGenUtils.cc:443
Custom iterator for iterating through the keys of containers containing pairs.
Definition: codeGenUtils.h:75
Definition: codeGenUtils.h:49
bool regexVarSubstitute(string &s, const string &trg, const string &rep)
Tool for substituting variable names in the neuron code strings or other templates using regular expr...
Definition: codeGenUtils.cc:246
void writePreciseString(std::ostream &os, T value)
This function writes a floating point value to a stream -setting the precision so no digits are lost...
Definition: codeGenUtils.h:195
PairKeyConstIter(BaseIter iter)
Definition: codeGenUtils.h:85
Definition: synapseGroup.h:19
const std::string genericName
Generic name used to refer to function in user code.
Definition: codeGenUtils.h:37
void substitute(string &s, const string &trg, const string &rep)
Tool for substituting strings in the neuron code strings or other templates.
Definition: codeGenUtils.cc:234
Definition: codeGenUtils.h:34
PairKeyConstIter()
Definition: codeGenUtils.h:84
void neuron_substitutions_in_synaptic_code(string &wCode, const SynapseGroup *sg, const string &preIdx, const string &postIdx, const string &devPrefix, double dt, const string &preVarPrefix="", const string &preVarSuffix="", const string &postVarPrefix="", const string &postVarSuffix="")
Function for performing the code and value substitutions necessary to insert neuron related variables...
Definition: codeGenUtils.cc:678
const unsigned int numArguments
Number of function arguments.
Definition: codeGenUtils.h:61
string ensureFtype(const string &oldcode, const string &type)
This function implements a parser that converts any floating point constant in a code snippet to a fl...
Definition: codeGenUtils.cc:458
const std::string singlePrecisionTemplate
The function template (for use with functionSubstitute) used when model uses single precision...
Definition: codeGenUtils.h:67
Base class for all neuron models.
Definition: newNeuronModels.h:31
void checkUnreplacedVariables(const string &code, const string &codeName)
This function checks for unknown variable definitions and returns a gennError if any are found...
Definition: codeGenUtils.cc:560
Definition: codeGenUtils.h:19
Definition: codeGenUtils.h:24
bool regexFuncSubstitute(string &s, const string &trg, const string &rep)
Tool for substituting function names in the neuron code strings or other templates using regular expr...
Definition: codeGenUtils.cc:263
const unsigned int numArguments
Number of function arguments.
Definition: codeGenUtils.h:40
const std::vector< FunctionTemplate > cudaFunctions
CUDA implementations of standard functions.
Definition: codeGenUtils.h:111
void preNeuronSubstitutionsInSynapticCode(string &wCode, const SynapseGroup *sg, const string &offset, const string &axonalDelayOffset, const string &postIdx, const string &devPrefix, const string &preVarPrefix="", const string &preVarSuffix="")
suffix to be used for presynaptic variable accesses - typically combined with prefix to wrap in funct...
Definition: codeGenUtils.cc:645
void value_substitutions(string &code, NameIter namesBegin, NameIter namesEnd, const vector< double > &values, const string &ext="")
This function performs a list of value substitutions for parameters in code snippets.
Definition: codeGenUtils.h:233
VarInit
Definition: variableMode.h:18
const std::string genericName
Generic name used to refer to function in user code.
Definition: codeGenUtils.h:58