aimstil  5.0.5
misc_utils.tpp
Go to the documentation of this file.
1 
2 #include <cmath>
3 
4 namespace til
5 {
6  //---------------------------------------------------------------------------
7 
8  /// Computes the centroid of a list of vertices.
9  template < typename TRes, typename TIterator >
10  void mean(TIterator begin, TIterator end, TRes & res)
11  {
12  res = TRes();
13  // TODO: OK, counting is not necessary for random access iterators. Maybe some partial specialization could help.
14  std::size_t count = 0;
15  for (; begin != end; ++begin)
16  {
17  res += *begin;
18  ++count;
19  }
20  // Can't use accumulate because I can't force my functors to cast to othr type
21  // there is another reason: a = a + x is inefficient for classes.
22  //res = std::accumulate(c.begin(), c.end(), TPoint3D());
23 
24  //mul(res, static_cast<typename value_type<TRes>::type>(1.0/size(c)));
25  res *= static_cast<typename value_type_of<TRes>::type>(1.0/count);
26  }
27 
28  //---------------------------------------------------------------------------
29 
30  template < typename TPoint, typename TPointCollection >
31  void stdev(const TPointCollection & c, TPoint & res)
32  {
33  res = TPoint();
34  {
35  typename TPointCollection::const_iterator iPoint = c.begin();
36  for (; iPoint != c.end(); ++iPoint)
37  {
38  typename TPoint::iterator i = res.begin();
39  typename TPointCollection::value_type::const_iterator j = iPoint->begin();
40  for (; i != res.end(); ++i, ++j)
41  {
42  *i += square(*j);
43  }
44  }
45  }
46  {
47  typename TPoint::iterator i = res.begin();
48  for (; i != res.end(); ++i)
49  {
50  *i *= 1.0/size(c);
51  }
52  }
53  //mul(res, 1.0/size(c));
54  //res.data() *= 1.0/size(c);
55  TPoint center;
56  centroid(c, center);
57  res[0] = std::sqrt(res[0] - square(center[0]));
58  res[1] = std::sqrt(res[1] - square(center[1]));
59  res[2] = std::sqrt(res[2] - square(center[2]));
60  }
61 
62  //---------------------------------------------------------------------------
63 
64  // TODO: add a test so that it works only for signed integers... or is >> working only on signed integers anyway?
65  template < typename T >
66  bool is_dyadic(T n)
67  {
68  if (n < 2) return false;
69  while (n >>= 1)
70  {
71  if (n%2 == 1 && n != 1) return false;
72  }
73  return true;
74  };
75 
76  //---------------------------------------------------------------------------
77 
78  /// Returns the largest m so that n >= 2^m.
79  /// Only for signed integer... TODO: add a check for that.
80  // NB: reason for using int: well, because int is largely sufficient to cover all possible
81  // exponent, so I don't want to put extra computing e.g log2(i)-2.
82  template < typename T >
83  inline int log2(T n)
84  {
85  int res = 0;
86  for (; n > 0; n >>= 1) ++res;
87  return res;
88  }
89 
90  //---------------------------------------------------------------------------
91 
92  // TODO: problem is, if an int is passed, it is converted silently into an unsigned int... so the security
93  // of using an unsigned argument is kind of lost... Better accept signed input and check for sign explicitely
94  // inside the function it seems :/
95  template < typename T >
96  inline T exp2(unsigned int n)
97  {
98  T res = 1;
99  for (; n > 0; --n) res *= 2;
100  return res;
101  }
102  /*
103  {
104  int res = 1;
105  while (--n) res <<= 1;
106  return res;
107  }
108  */
109 
110  //---------------------------------------------------------------------------
111 
112  template < typename TIndexCollection >
113  //typename boost::enable_if<boost::is_same<typename TIndexCollection::value_type::value_type, std::size_t>,
114  std::vector<std::list<std::size_t> >
115  //>::type
116  invertIndices(const std::vector<TIndexCollection> & c)
117  {
118  // Do a first pass to get maximum index
119  std::size_t mx = 0;
120  for (std::size_t i = 0; i < size(c); ++i)
121  for (std::size_t j = 0; j < size(c[i]); ++j)
122  mx = max(c[i][j], mx);
123 
124  // allocate result
125  std::vector<std::list<std::size_t> > res(mx+1);
126 
127  // Fill result
128  for (std::size_t i = 0; i < size(c); ++i)
129  for (std::size_t j = 0; j < size(c[i]); ++j)
130  res[c[i][j]].push_back(i);
131 
132  return res;
133  }
134 
135  //---------------------------------------------------------------------------
136 
137  template < typename T >
138  inline std::size_t max_index(T x0, T x1, T x2)
139  {
140  if (x0>=x1) {
141  if (x0>=x2)
142  return 0;
143  else
144  return 2;
145  } else {
146  if (x1>=x2)
147  return 1;
148  else
149  return 2;
150  }
151  }
152 
153  //---------------------------------------------------------------------------
154 
155  template < typename T >
156  inline std::size_t min_index(T x0, T x1, T x2)
157  {
158  if (x0<=x1) {
159  if (x0<=x2)
160  return 0;
161  else
162  return 2;
163  } else {
164  if (x1<=x2)
165  return 1;
166  else
167  return 2;
168  }
169  }
170 
171  //---------------------------------------------------------------------------
172 
173  template < typename T >
174  inline bool is_nan(T x)
175  {
176  // TODO: COMPILER_MAINTENANCE : this has to be regularly checked for compilers :(
177 #ifdef __GNUC__
178  // GNU has its own implementation
179  return std::isnan(x);
180 #else
181  // The IEEE-compliant way -- but I guess it is compiler-dependant.
182  return x != x;
183 #endif
184  }
185 
186  //---------------------------------------------------------------------------
187 
188  template < typename T >
189  inline T lower_dyadic(T n)
190  {
191  T res = 1;
192  while (res <= n) res *= 2;
193  return res /= 2;
194  };
195 
196 
197 
198 } // namespace til
199