source: XIOS3/trunk/src/utils.hpp @ 2433

Last change on this file since 2433 was 2177, checked in by ymipsl, 3 years ago

Correct problem in hash methods for vector.
Implement hash combine.
YM

File size: 9.7 KB
Line 
1/*!
2   \file utils.hpp
3   \author Ha NGUYEN
4   \since 06 Oct 2014
5   \date 10 Feb 2015
6
7
8   \brief Some utils for Xios
9 */
10
11#ifndef __XIOS_UTILS_HPP__
12#define __XIOS_UTILS_HPP__
13
14#include <vector>
15#include <limits>
16#include "array_new.hpp"
17#include "exception.hpp"
18
19namespace xios
20{
21  template<typename K>
22  struct CArrayTraits {
23    typedef K ArrayType;
24  };
25
26  template<typename K>
27  struct CArrayBoolTraits : public CArrayTraits<K> {
28    typedef bool Type;
29  };
30
31  template<>
32  struct CArrayBoolTraits<CArray<bool,1> >
33  {
34    static inline void resizeArray(CArray<bool,1>& boolArray, const std::vector<int>& dimensionSize)
35    {
36      if (1 != dimensionSize.size())
37        ERROR("utils::CArrayBoolTraits",
38                <<"Dimension of resized array mismatch"<<endl
39                <<"Dimension of resized is 1 "<<endl
40                <<"Dimension of vetor resizing is "<< dimensionSize.size());
41      boolArray.resize(dimensionSize[0]);
42    }
43  };
44
45  template<>
46  struct CArrayBoolTraits<CArray<bool,2> >
47  {
48    static inline void resizeArray(CArray<bool,2>& boolArray, const std::vector<int>& dimensionSize)
49    {
50      if (2 != dimensionSize.size())
51        ERROR("utils::CArrayBoolTraits",
52                <<"Dimension of resized array mismatch"<<endl
53                <<"Dimension of resized is 2 "<<endl
54                <<"Dimension of vetor resizing is "<< dimensionSize.size());
55      boolArray.resize(dimensionSize[0], dimensionSize[1]);
56    }
57  };
58
59  template<>
60  struct CArrayBoolTraits<CArray<bool,3> >
61  {
62    static inline void resizeArray(CArray<bool,3>& boolArray, const std::vector<int>& dimensionSize)
63    {
64      if (3 != dimensionSize.size())
65        ERROR("utils::CArrayBoolTraits",
66                <<"Dimension of resized array mismatch"<<endl
67                <<"Dimension of resized is 3 "<<endl
68                <<"Dimension of vetor resizing is "<< dimensionSize.size());
69      boolArray.resize(dimensionSize[0], dimensionSize[1], dimensionSize[2]);
70    }
71  };
72
73  template<>
74  struct CArrayBoolTraits<CArray<bool,4> >
75  {
76    static inline void resizeArray(CArray<bool,4>& boolArray, const std::vector<int>& dimensionSize)
77    {
78      if (4 != dimensionSize.size())
79        ERROR("utils::CArrayBoolTraits",
80                <<"Dimension of resized array mismatch"<<endl
81                <<"Dimension of resized is 4 "<<endl
82                <<"Dimension of vetor resizing is "<< dimensionSize.size());
83      boolArray.resize(dimensionSize[0], dimensionSize[1], dimensionSize[2], dimensionSize[3]);
84    }
85  };
86
87  template<>
88  struct CArrayBoolTraits<CArray<bool,5> >
89  {
90    static inline void resizeArray(CArray<bool,5>& boolArray, const std::vector<int>& dimensionSize)
91    {
92      if (5 != dimensionSize.size())
93        ERROR("utils::CArrayBoolTraits",
94                <<"Dimension of resized array mismatch"<<endl
95                <<"Dimension of resized is 5 "<<endl
96                <<"Dimension of vetor resizing is "<< dimensionSize.size());
97      boolArray.resize(dimensionSize[0], dimensionSize[1],
98                       dimensionSize[2], dimensionSize[3], dimensionSize[4]);
99    }
100  };
101
102  template<>
103  struct CArrayBoolTraits<CArray<bool,6> >
104  {
105    static inline void resizeArray(CArray<bool,6>& boolArray, const std::vector<int>& dimensionSize)
106    {
107      if (6 != dimensionSize.size())
108        ERROR("utils::CArrayBoolTraits",
109                <<"Dimension of resized array mismatch"<<endl
110                <<"Dimension of resized is 6 "<<endl
111                <<"Dimension of vetor resizing is "<< dimensionSize.size());
112      boolArray.resize(dimensionSize[0], dimensionSize[1],
113                       dimensionSize[2], dimensionSize[3],
114                       dimensionSize[4], dimensionSize[5]);
115    }
116  };
117
118  template<>
119  struct CArrayBoolTraits<CArray<bool,7> >
120  {
121    static inline void resizeArray(CArray<bool,7>& boolArray, const std::vector<int>& dimensionSize)
122    {
123      if (7 != dimensionSize.size())
124        ERROR("utils::CArrayBoolTraits",
125                <<"Dimension of resized array mismatch"<<endl
126                <<"Dimension of resized is 7 "<<endl
127                <<"Dimension of vetor resizing is "<< dimensionSize.size());
128      boolArray.resize(dimensionSize[0], dimensionSize[1],
129                       dimensionSize[2], dimensionSize[3],
130                       dimensionSize[4], dimensionSize[5], dimensionSize[6]);
131    }
132  };
133
134  template <int v>
135  struct Int2Type
136  {
137  enum { value = v };
138  };
139
140  template<typename T>
141  union TypeToBytes {
142    T value;
143    unsigned char bytes[sizeof(T)];
144  };
145
146  template<typename T>
147  struct HashAlgorithm
148  {
149    /*!
150      Adapted version of one-at-a-time hash by Bob Jenkins,
151      which is an expanded version of his Dr. Dobbs article.
152    */
153    static inline size_t jenkins_hash(const T& value)
154    {
155      TypeToBytes<T> u;
156      (u.value) = value;
157
158      size_t hash = 0;
159      size_t length = sizeof(value);
160
161      for (size_t i = 0; i < length; ++i)
162      {
163          hash += u.bytes[i];
164          hash += (hash << 10);
165          hash ^= (hash >> 6);
166      }
167      hash += (hash << 3);
168      hash ^= (hash >> 11);
169      hash += (hash << 15);
170
171      return hash;
172    }
173
174    /*!
175      Adatped version of (stupid) boost hash (but working)
176    */
177    static inline size_t boost_hash(const std::vector<T>& vec)
178    {
179      size_t hash = 0;
180      int sizeVec = vec.size();
181      for(int i = 0; i < sizeVec; ++i)
182      {
183        hash ^= jenkins_hash(vec[i]) + 0x9e3779b9 + (hash << 6) + (hash >> 2);
184      }
185      return hash;
186    }
187
188    static inline size_t hash_combine(size_t seed, const T& value)
189    {
190      seed ^= jenkins_hash(value) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
191      return seed;
192    }
193
194  };
195
196  template<typename T, typename Algo = Int2Type<0> >
197  struct HashXIOS
198  {
199    std::size_t operator()(const T& val)
200    {
201      Algo al;
202      return hash_value(val, al);
203    }
204
205    std::size_t hashVec(const std::vector<T>& vec)
206    {
207      return HashAlgorithm<T>::boost_hash(vec);
208    }
209   
210    std::size_t hashCombine(size_t seed, const T& val)
211    {
212      return HashAlgorithm<T>::hash_combine(seed, val);
213    }
214  private:
215    size_t hash_value(const T& val, Int2Type<0>)
216    {
217      return HashAlgorithm<T>::jenkins_hash(val);
218    }
219  };
220
221template<typename K>
222struct NumTraits {
223    typedef K Type;
224};
225
226template<>
227struct NumTraits<unsigned long>
228{
229  typedef unsigned long Scalar;
230  typedef Scalar magnitudeType;
231
232  static inline Scalar sfmin() {
233    return std::numeric_limits<Scalar>::min();
234  }
235  static inline Scalar sfmax() {
236    return std::numeric_limits<Scalar>::max();
237  }
238  static inline Scalar sflowest() {
239    return -(std::numeric_limits<Scalar>::max());
240  }
241  static inline Scalar epsilon() {
242    return std::numeric_limits<Scalar>::epsilon();
243  }
244  static inline Scalar dummy_precision() {
245    return 0;
246  }
247};
248
249template<>
250struct NumTraits<double>
251{
252  typedef double Scalar;
253  typedef Scalar magnitudeType;
254
255  static inline Scalar sfmin() {
256    return std::numeric_limits<Scalar>::min();
257  }
258  static inline Scalar sfmax() {
259    return std::numeric_limits<Scalar>::max();
260  }
261  static inline Scalar sflowest() {
262    return -(std::numeric_limits<Scalar>::max());
263  }
264  static inline Scalar epsilon() {
265    return std::numeric_limits<Scalar>::epsilon();
266  }
267  static inline Scalar dummy_precision() {
268    return 1e-12;
269  }
270  static inline bool isNan(const Scalar& v) {
271    return (v != v);
272  }
273};
274
275template<typename T>
276class CArrayStorage
277{
278public:
279  typedef CArray<T,1> StorageType;
280
281public:
282  CArrayStorage(const CArray<T,1>& arr) : values(arr) {}
283
284protected:
285  const T& atIndex(int idx) const { return values(idx); }
286  const StorageType& values;
287};
288
289template<typename T>
290class CVectorStorage
291{
292public:
293  typedef std::vector<T> StorageType;
294
295public:
296  CVectorStorage(const std::vector<T>& vec) : values(vec) {}
297
298protected:
299  const T& atIndex(int idx) const { return values[idx]; }
300  const StorageType& values;
301};
302
303
304template<
305  typename T,
306  template <class> class StoragePolicy = CVectorStorage
307  >
308class XIOSComparatorWithIndex :
309  public StoragePolicy<T>
310{
311public:
312  typedef typename  StoragePolicy<T>::StorageType StorageType;
313
314public:
315  XIOSComparatorWithIndex(const StorageType& v) : StoragePolicy<T>(v) {}
316  bool operator()(int a, int b) { return this->atIndex(a) < this->atIndex(b); }
317};
318
319template<
320  typename T,
321  template <class> class StoragePolicy = CVectorStorage
322  >
323class XIOSLowerBoundWithIndex :
324  public StoragePolicy<T>
325{
326public:
327  typedef typename  StoragePolicy<T>::StorageType StorageType;
328
329public:
330  XIOSLowerBoundWithIndex(const StorageType &v) : StoragePolicy<T>(v) {}
331  bool operator()(const int a, const T& b) { return this->atIndex(a) < b; }
332};
333
334template<
335  typename T,
336  template <class> class StoragePolicy = CVectorStorage
337  >
338class XIOSBinarySearchWithIndex :
339  public StoragePolicy<T>
340{
341public:
342  typedef typename  StoragePolicy<T>::StorageType StorageType;
343
344public:
345  XIOSBinarySearchWithIndex(const StorageType& v) : StoragePolicy<T>(v) {}
346
347  template<typename ForwardIterator>
348  bool search(ForwardIterator first, ForwardIterator last, const T& val, ForwardIterator& position)
349  {
350    first = std::lower_bound(first, last, val, XIOSLowerBoundWithIndex<T, StoragePolicy>(this->values));
351    position = first;
352    return (first!=last && !(val<this->atIndex(*first)));
353  }
354};
355
356
357struct XIOSAlgorithms
358{
359public:
360  template<typename T, template <class> class StoragePolicy>
361  static void sortWithIndex(const typename StoragePolicy<T>::StorageType& values, std::vector<int>& rv)
362  {
363    std::sort(rv.begin(), rv.end(), XIOSComparatorWithIndex<T, StoragePolicy>(values));
364  }
365
366  //! Fill in an vector with index begin at 0
367  static void fillInIndex(int nbIndex, std::vector<int>& rvIndex)
368  {
369    if ((0 < nbIndex) && (nbIndex != rvIndex.size())) rvIndex.resize(nbIndex);
370    for (int idx = 0; idx < nbIndex; ++idx) rvIndex[idx] = idx;
371  }
372};
373
374}
375
376#endif // __UTILS_HPP__
Note: See TracBrowser for help on using the repository browser.