GeNN  4.9.0
GPU enhanced Neuronal Networks (GeNN)
substitutions.h
Go to the documentation of this file.
1 #pragma once
2 
3 // Standard C++ includes
4 #include <map>
5 #include <stdexcept>
6 #include <string>
7 
8 // Standard C includes
9 #include <cassert>
10 
11 // GeNN includes
12 #include "gennExport.h"
13 #include "gennUtils.h"
14 #include "logging.h"
15 
16 //--------------------------------------------------------------------------
17 // Substitutions
18 //--------------------------------------------------------------------------
19 namespace CodeGenerator
20 {
22 {
23 public:
26 
28  {
29  // **HACK** while GCC and CLang automatically generate this fine/don't require it, VS2013 seems to need it
30  FunctionTemplate operator = (const FunctionTemplate &o)
31  {
33  }
34 
36  const std::string genericName;
37 
39  const unsigned int numArguments;
40 
42  const std::string funcTemplate;
43  };
44 
45  Substitutions(const Substitutions *parent = nullptr) : m_Parent(parent)
46  {
47  assert(m_Parent != this);
48  }
49 
50  Substitutions(const std::vector<FunctionTemplate> &functions) : m_Parent(nullptr)
51  {
52  // Loop through functions and add as substitutions
53  for(const auto &f: functions) {
54  addFuncSubstitution(f.genericName, f.numArguments, f.funcTemplate);
55  }
56  }
57 
58  //--------------------------------------------------------------------------
59  // Public API
60  //--------------------------------------------------------------------------
61  template<typename T>
62  void addVarNameSubstitution(const std::vector<T> &variables, const std::string &sourceSuffix = "",
63  const std::string &destPrefix = "", const std::string &destSuffix = "")
64  {
65  for(const auto &v : variables) {
66  addVarSubstitution(v.name + sourceSuffix,
67  destPrefix + v.name + destSuffix);
68  }
69  }
70 
71  template<typename T, typename S>
72  void addVarNameSubstitution(const std::vector<T> &variables, const std::string &sourceSuffix,
73  const std::string &destPrefix, S getDestSuffixFn)
74  {
75  for(const auto &v : variables) {
76  addVarSubstitution(v.name + sourceSuffix,
77  destPrefix + v.name + getDestSuffixFn(v.access));
78  }
79  }
80 
81  template<typename T>
82  void addVarValueSubstitution(const std::vector<T> &variables, const std::vector<double> &values,
83  const std::string &sourceSuffix = "")
84  {
85  if(variables.size() != values.size()) {
86  throw std::runtime_error("Number of variables does not match number of values");
87  }
88 
89  auto var = variables.cbegin();
90  auto val = values.cbegin();
91  for (;var != variables.cend() && val != values.cend(); var++, val++) {
92  addVarSubstitution(var->name + sourceSuffix,
93  "(" + Utils::writePreciseString(*val) + ")");
94  }
95  }
96 
97  void addParamValueSubstitution(const std::vector<std::string> &paramNames, const std::vector<double> &values,
98  const std::string &sourceSuffix = "");
99 
100  template<typename G>
101  void addParamValueSubstitution(const std::vector<std::string> &paramNames, const std::vector<double> &values, G isHeterogeneousFn,
102  const std::string &sourceSuffix = "", const std::string &destPrefix = "", const std::string &destSuffix = "")
103  {
104  if(paramNames.size() != values.size()) {
105  throw std::runtime_error("Number of parameters does not match number of values");
106  }
107 
108  for(size_t i = 0; i < paramNames.size(); i++) {
109  if(isHeterogeneousFn(i)) {
110  addVarSubstitution(paramNames[i] + sourceSuffix,
111  destPrefix + paramNames[i] + destSuffix);
112  }
113  else {
114  addVarSubstitution(paramNames[i] + sourceSuffix,
115  "(" + Utils::writePreciseString(values[i]) + ")");
116  }
117  }
118  }
119 
120  template<typename T, typename G>
121  void addVarValueSubstitution(const std::vector<T> &variables, const std::vector<double> &values, G isHeterogeneousFn,
122  const std::string &sourceSuffix = "", const std::string &destPrefix = "", const std::string &destSuffix = "")
123  {
124  if(variables.size() != values.size()) {
125  throw std::runtime_error("Number of variables does not match number of values");
126  }
127 
128  for(size_t i = 0; i < variables.size(); i++) {
129  if(isHeterogeneousFn(i)) {
130  addVarSubstitution(variables[i].name + sourceSuffix,
131  destPrefix + variables[i].name + destSuffix);
132  }
133  else {
134  addVarSubstitution(variables[i].name + sourceSuffix,
135  "(" + Utils::writePreciseString(values[i]) + ")");
136  }
137  }
138  }
139 
140  void addVarSubstitution(const std::string &source, const std::string &destionation, bool allowOverride = false);
141  void addFuncSubstitution(const std::string &source, unsigned int numArguments, const std::string &funcTemplate, bool allowOverride = false);
142  bool hasVarSubstitution(const std::string &source) const;
143 
144  const std::string &getVarSubstitution(const std::string &source) const;
145 
146  void apply(std::string &code) const;
147  void applyCheckUnreplaced(std::string &code, const std::string &context) const;
148 
149  //--------------------------------------------------------------------------
150  // Public API
151  //--------------------------------------------------------------------------
152  const std::string operator[] (const std::string &source) const
153  {
154  return getVarSubstitution(source);
155  }
156 
157 private:
158  //--------------------------------------------------------------------------
159  // Private API
160  //--------------------------------------------------------------------------
161  void applyFuncs(std::string &code) const;
162  void applyVars(std::string &code) const;
163 
164  //--------------------------------------------------------------------------
165  // Members
166  //--------------------------------------------------------------------------
167  std::map<std::string, std::string> m_VarSubstitutions;
168  std::map<std::string, std::pair<unsigned int, std::string>> m_FuncSubstitutions;
169  const Substitutions *m_Parent;
170 };
171 } // namespace CodeGenerator
Substitutions(const Substitutions *parent=nullptr)
Definition: substitutions.h:45
const unsigned int numArguments
Number of function arguments.
Definition: substitutions.h:39
#define GENN_EXPORT
Definition: gennExport.h:13
void addParamValueSubstitution(const std::vector< std::string > &paramNames, const std::vector< double > &values, G isHeterogeneousFn, const std::string &sourceSuffix="", const std::string &destPrefix="", const std::string &destSuffix="")
Definition: substitutions.h:101
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: gennUtils.h:92
Helper class for generating code - automatically inserts brackets, indents etc.
Definition: backendBase.h:30
Definition: substitutions.h:21
const std::string funcTemplate
The function template (for use with functionSubstitute) used when model uses double precision...
Definition: substitutions.h:42
void addVarValueSubstitution(const std::vector< T > &variables, const std::vector< double > &values, const std::string &sourceSuffix="")
Definition: substitutions.h:82
void addVarNameSubstitution(const std::vector< T > &variables, const std::string &sourceSuffix, const std::string &destPrefix, S getDestSuffixFn)
Definition: substitutions.h:72
Substitutions(const std::vector< FunctionTemplate > &functions)
Definition: substitutions.h:50
void addVarNameSubstitution(const std::vector< T > &variables, const std::string &sourceSuffix="", const std::string &destPrefix="", const std::string &destSuffix="")
Definition: substitutions.h:62
void addVarValueSubstitution(const std::vector< T > &variables, const std::vector< double > &values, G isHeterogeneousFn, const std::string &sourceSuffix="", const std::string &destPrefix="", const std::string &destSuffix="")
Definition: substitutions.h:121
const std::string genericName
Generic name used to refer to function in user code.
Definition: substitutions.h:36