NAMD
TupleString.h
Go to the documentation of this file.
1 #ifndef TUPLESTRING_H
2 #define TUPLESTRING_H
3  /*
4  * Classes to manage the parameters that are built from tuples of strings.
5  *
6  * To avoid ever calling strcasecmp, we upcase on input.
7  *
8  * For performance reasons, we make a hash key of the tuple for faster
9  * search times in structures like unordered_map
10  *
11  */
12 
13 #include <string>
14 #include <unordered_map>
15 #include <vector>
16 #include <algorithm>
17 #include "xxh3.h"
18 
56 // this is the value we inherit from Parameter.h
57 // it may be overkill, but we're dealing with defacto standards
58 static const short ParamNameMaxLen=11;
59 
60 // this gives us a fixed length base
63 };
64 
65 
66 // these make the compiler do our indexing for us
67 template <short NumStrings>
68 struct TupleStrider {
69  union{
70  MStringStrider stride[NumStrings];
71  char mString[ParamNameMaxLen*NumStrings];
72  };
73 };
74 
75 // We build up our MultiString Template here
76 template <short NumStrings>
78 {
79  public:
82 
84  memcpy(multiString.mString, rhs.getMString(), getMStringLen());
85  }
86  // we only bother with constructors for 1,2,3,4,8 as those are what we use
87 
88  MultiString(const char *t1)
89  {
90  memset(multiString.mString, 0, getMStringLen());
91  strncpy(multiString.mString, t1, getTupleMaxLen());
92  }
93 
94  MultiString(const char *t1, const char *t2)
95  {
96  memset(multiString.mString, 0, getMStringLen());
97  strncpy(multiString.mString, t1, getTupleMaxLen());
98  strncpy(getTuplePtr(1), t2, getTupleMaxLen());
99  }
100 
101  MultiString(const char *t1, const char *t2, const char *t3)
102  {
103  memset(multiString.mString, 0, getMStringLen());
104  strncpy(multiString.mString, t1, getTupleMaxLen());
105  strncpy(getTuplePtr(1), t2, getTupleMaxLen());
106  strncpy(getTuplePtr(2), t3, getTupleMaxLen());
107  }
108  MultiString(const char *t1, const char *t2, const char *t3, const char *t4)
109  {
110  memset(multiString.mString, 0, getMStringLen());
111  strncpy(multiString.mString, t1, getTupleMaxLen());
112  strncpy(getTuplePtr(1), t2, getTupleMaxLen());
113  strncpy(getTuplePtr(2), t3, getTupleMaxLen());
114  strncpy(getTuplePtr(3), t4, getTupleMaxLen());
115  }
116 
117  MultiString(const char *t1, const char *t2, const char *t3, const char *t4,
118  const char *t5, const char *t6, const char *t7, const char *t8
119  )
120  {
121  memset(multiString.mString, 0, getMStringLen());
122  strncpy(multiString.mString, t1, getTupleMaxLen());
123  strncpy(getTuplePtr(1), t2, getTupleMaxLen());
124  strncpy(getTuplePtr(2), t3, getTupleMaxLen());
125  strncpy(getTuplePtr(3), t4, getTupleMaxLen());
126  strncpy(getTuplePtr(4), t5, getTupleMaxLen());
127  strncpy(getTuplePtr(5), t6, getTupleMaxLen());
128  strncpy(getTuplePtr(6), t7, getTupleMaxLen());
129  strncpy(getTuplePtr(7), t8, getTupleMaxLen());
130  }
131 
132  inline char *getTuplePtr(short index) {
133  return (char *) &(multiString.stride[index]); }
134 
135  inline void upcase()
136  {
137  for(int i=0; i < mStringLen ;i++)
138  {
139  multiString.mString[i] = std::toupper(multiString.mString[i]);
140  }
141  }
142 
143  inline short length() const { return mStringLen;}
144 
145  inline bool operator== (const MultiString& rhs) const
146  {
147  return memcmp(multiString.mString, rhs.getMString(), mStringCmpLen)==0;
148  }
149  inline bool operator< (const MultiString& rhs) const
150  {
151  return memcmp(multiString.mString, rhs.getMString(), mStringCmpLen) < 0 ;
152  }
153  inline const char *getMString() const {return multiString.mString;}
154  inline const short getMStringLen() const {return mStringLen;}
155  inline const short getTupleMaxLen() const {return ParamNameMaxLen;}
156 
157  private:
158  static const short mStringLen=NumStrings*ParamNameMaxLen;
159  static const short mStringCmpLen=NumStrings*ParamNameMaxLen-1; // last one will always be null
160 };
161 
162 // TupleString is just the MultiString with hashkeys built in
163 template <short NumStrings>
165 {
166  public:
169  {}
170  TupleString(const char* key1)
171  {
173  tupleCat.upcase();
174  makeHash();
175  }
176 
177  TupleString(const char* key1, const char* key2)
178  {
179  tupleCat = MultiString <NumStrings>(key1, key2);
180  tupleCat.upcase();
181  makeHash();
182  }
183 
184  TupleString(const char* key1, const char* key2, const char* key3)
185  {
186  tupleCat = MultiString <NumStrings>(key1, key2, key3);
187  tupleCat.upcase();
188  makeHash();
189  }
190 
191  TupleString(const char* key1, const char* key2, const char* key3,
192  const char* key4)
193  {
194  tupleCat = MultiString <NumStrings>(key1, key2, key3, key4);
195  tupleCat.upcase();
196  makeHash();
197  }
198 
199  TupleString(const char* key1, const char* key2, const char* key3,
200  const char* key4, const char* key5, const char* key6,
201  const char* key7, const char* key8)
202  {
203  tupleCat = MultiString <NumStrings>(key1, key2, key3, key4,
204  key5, key6, key7, key8);
205  tupleCat.upcase();
206  makeHash();
207  }
208 
209  inline void makeHash()
210  {
211  hashKey = XXH3_64bits(tupleCat.getMString(), tupleCat.length());
212  }
213 
214  // if the hashkeys are equal, check the string
215  inline bool operator== (const TupleString& rhs) const
216  {
217  if(hashKey == rhs.getHashKey())
218  {
219  return tupleCat == rhs.tupleCat;
220  }
221  return false;
222  }
223 
224  // if the hashkeys are equal, check the string
225  inline bool operator<(const TupleString& rhs) const
226  {
227  if(hashKey == rhs.getHashKey())
228  return(tupleCat < rhs.tupleCat);
229  return hashKey < rhs.getHashKey();
230  }
231 
232  inline const uint64_t getHashKey() const {return hashKey;}
233  inline const char* getCatKey() const {return tupleCat.getMString();}
234 
235  inline char *getTuplePtr(short index) { return tupleCat.getTuplePtr(index); }
236  private:
237  uint64_t hashKey;
238 };
239 
240 
241 template <short NumStrings>
243 {
244  size_t operator() (const TupleString <NumStrings>& k) const
245  {
246  return k.getHashKey();
247  }
248  static_assert((NumStrings==1) || (NumStrings==2) || (NumStrings==3)
249  || (NumStrings==4) || (NumStrings==8),
250  "invalid NumStrings must be: [1,2,3,4,8]");
251 };
252 
253 
254 /* convenience typedefs */
260 
261 
262 /*
263  combine a map with key(tuple) and value(index) with a vector of
264  record types for the map to index into. We enforce uniqueness on the
265  map and only append a new value for a unique key.
266 */
267 
268 
269 //templating a template is tricky with only c++11
270 //this looks a little weird, but avoids code replication
271 
272 template <short NumStrings, class ParamValue>
274 {
275  public:
276  std::vector<ParamValue> paramVector;
277  std::unordered_map<TupleString<NumStrings>, size_t, TupleStringHash<NumStrings>> tupleMap;
278  inline TwoLevelParam()
279  {
280  }
281  inline ParamValue* get_param(const size_t &index)
282  {
283  return &(paramVector[index]);
284  }
285 
286  inline ParamValue* get_param_by_key(const TupleString<NumStrings> &findKey)
287  {
288  auto ret = tupleMap.find(findKey);
289  if(ret!=tupleMap.end())
290  {
291  return &paramVector[ret->second];
292  }
293  else
294  {
295  return NULL;
296  }
297  }
298 
299  inline bool insert(const TupleString<NumStrings> &tKey,
300  const ParamValue &mValue)
301  {
302  size_t newPlace = paramVector.size();
303  const auto ret = tupleMap.emplace(std::make_pair(tKey,newPlace));
304  if(ret.second)
305  {
306 
307  paramVector.push_back(mValue);
308  }
309  return ret.second;
310  }
311 
312  // return whether it was newly inserted and the pointer to the value
313  inline std::pair<bool, ParamValue*> insert_check(const TupleString<NumStrings> &tKey,
314  const ParamValue &mValue)
315  {
316  size_t newPlace = paramVector.size();
317  auto ret = tupleMap.emplace(std::make_pair(tKey,newPlace));
318  if(ret.second)
319  {
320  paramVector.push_back(mValue);
321  }
322  return std::make_pair(ret.second, &paramVector[ret.first->second]);
323  }
324 
325  // underscore naming inherited from original Parameter.[hC]
326  inline std::pair<bool, size_t> const index_param(const TupleString<NumStrings> &findKey) const
327  {
328  const auto ret = tupleMap.find(findKey);
329  if(ret!=tupleMap.end())
330  {
331  return std::make_pair(true, ret->second);
332  }
333  else
334  {
335  return std::make_pair(false, paramVector.size());
336  }
337  }
338 
339  // possibly faster
340  inline int64_t const index(const TupleString<NumStrings> &findKey) const
341  {
342  const auto ret = tupleMap.find(findKey);
343  if(ret!=tupleMap.end())
344  {
345  return ret->second;
346  }
347  return -1;
348  }
349 
350  void clear()
351  {
352  tupleMap.clear();
353  paramVector.clear();
354  }
355 
356  // mem_opt relies on strict ordering by name for indices to match up.
357  // Sort the key strings alphanumerically and reset the indices
358  // to have an in order param vector.
359  // This is not within an #ifdef MEM_OPT_VERSION so it can be used
360  // during genCompressedPsf
361  void sort()
362  {
363  typedef std::pair<TupleString<NumStrings>, size_t> TSKeypair;
364  std::vector <TSKeypair> sortVector;
365  std::vector <ParamValue> sortValues;
366  for(auto apair : tupleMap)
367  {
368  sortVector.push_back(apair);
369  }
370  std::sort(sortVector.begin(), sortVector.end(),
371  [] (TSKeypair a, TSKeypair b)
372  {
373  return a.first.tupleCat<b.first.tupleCat;
374  });
375  for(int newIndex=0; newIndex < sortVector.size(); ++newIndex)
376  {
377  sortValues.push_back(paramVector[sortVector[newIndex].second]);
378  tupleMap[sortVector[newIndex].first]=newIndex;
379  }
380  paramVector=sortValues;
381  }
382 
383 };
384 
385 #endif
386 
ParamValue * get_param(const size_t &index)
Definition: TupleString.h:281
bool operator<(const MultiString &rhs) const
Definition: TupleString.h:149
std::pair< bool, size_t > const index_param(const TupleString< NumStrings > &findKey) const
Definition: TupleString.h:326
void makeHash()
Definition: TupleString.h:209
TupleString< 1 > TupleString1
Definition: TupleString.h:255
MultiString(const MultiString< NumStrings > &rhs)
Definition: TupleString.h:83
MultiString(const char *t1, const char *t2, const char *t3, const char *t4)
Definition: TupleString.h:108
TupleString(const char *key1, const char *key2, const char *key3, const char *key4)
Definition: TupleString.h:191
bool operator==(const TupleString &rhs) const
Definition: TupleString.h:215
size_t operator()(const TupleString< NumStrings > &k) const
Definition: TupleString.h:244
TupleString(const char *key1, const char *key2, const char *key3, const char *key4, const char *key5, const char *key6, const char *key7, const char *key8)
Definition: TupleString.h:199
TupleString< 2 > TupleString2
Definition: TupleString.h:256
char * getTuplePtr(short index)
Definition: TupleString.h:235
TupleString< 8 > TupleString8
Definition: TupleString.h:259
std::unordered_map< TupleString< NumStrings >, size_t, TupleStringHash< NumStrings > > tupleMap
Definition: TupleString.h:277
const char * getCatKey() const
Definition: TupleString.h:233
char mStride[ParamNameMaxLen]
Definition: TupleString.h:62
MultiString(const char *t1, const char *t2, const char *t3, const char *t4, const char *t5, const char *t6, const char *t7, const char *t8)
Definition: TupleString.h:117
TupleString(const char *key1, const char *key2, const char *key3)
Definition: TupleString.h:184
ParamValue * get_param_by_key(const TupleString< NumStrings > &findKey)
Definition: TupleString.h:286
const short getMStringLen() const
Definition: TupleString.h:154
MStringStrider stride[NumStrings]
Definition: TupleString.h:70
char * getTuplePtr(short index)
Definition: TupleString.h:132
MultiString(const char *t1)
Definition: TupleString.h:88
MultiString(const char *t1, const char *t2, const char *t3)
Definition: TupleString.h:101
MultiString< NumStrings > tupleCat
Definition: TupleString.h:167
const short getTupleMaxLen() const
Definition: TupleString.h:155
static const short ParamNameMaxLen
Definition: TupleString.h:58
bool operator<(const TupleString &rhs) const
Definition: TupleString.h:225
TupleString< 3 > TupleString3
Definition: TupleString.h:257
TupleString(const char *key1)
Definition: TupleString.h:170
std::vector< ParamValue > paramVector
Definition: TupleString.h:276
TupleStrider< NumStrings > multiString
Definition: TupleString.h:80
short length() const
Definition: TupleString.h:143
const char * getMString() const
Definition: TupleString.h:153
bool insert(const TupleString< NumStrings > &tKey, const ParamValue &mValue)
Definition: TupleString.h:299
XXH_PUBLIC_API XXH64_hash_t XXH3_64bits(const void *input, size_t len)
Definition: xxh3.h:1430
const uint64_t getHashKey() const
Definition: TupleString.h:232
bool operator==(const MultiString &rhs) const
Definition: TupleString.h:145
int64_t const index(const TupleString< NumStrings > &findKey) const
Definition: TupleString.h:340
char mString[ParamNameMaxLen *NumStrings]
Definition: TupleString.h:71
TupleString< 4 > TupleString4
Definition: TupleString.h:258
MultiString(const char *t1, const char *t2)
Definition: TupleString.h:94
TupleString(const char *key1, const char *key2)
Definition: TupleString.h:177
std::pair< bool, ParamValue * > insert_check(const TupleString< NumStrings > &tKey, const ParamValue &mValue)
Definition: TupleString.h:313
void upcase()
Definition: TupleString.h:135