source: trunk/yat/utility/stl_utility.h @ 2010

Last change on this file since 2010 was 2010, checked in by Peter, 12 years ago

let user turn off yat's declaread function in std (which is not documented btw).

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 11.6 KB
Line 
1#ifndef _theplu_yat_utility_stl_utility_
2#define _theplu_yat_utility_stl_utility_
3
4// $Id: stl_utility.h 2010 2009-06-27 00:41:22Z peter $
5
6/*
7  Copyright (C) 2004 Jari Häkkinen
8  Copyright (C) 2005 Jari Häkkinen, Peter Johansson, Markus Ringnér
9  Copyright (C) 2006 Jari Häkkinen
10  Copyright (C) 2007, 2008 Jari Häkkinen, Peter Johansson
11  Copyright (C) 2009 Peter Johansson
12
13  This file is part of the yat library, http://dev.thep.lu.se/yat
14
15  The yat library is free software; you can redistribute it and/or
16  modify it under the terms of the GNU General Public License as
17  published by the Free Software Foundation; either version 3 of the
18  License, or (at your option) any later version.
19
20  The yat library is distributed in the hope that it will be useful,
21  but WITHOUT ANY WARRANTY; without even the implied warranty of
22  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
23  General Public License for more details.
24
25  You should have received a copy of the GNU General Public License
26  along with yat. If not, see <http://www.gnu.org/licenses/>.
27*/
28
29///
30/// \file stl_utility.h
31///
32/// There are a number of useful functionality missing in the Standard
33/// Template Library, STL. This file is an effort to provide
34/// extensions to STL functionality.
35///
36
37#include "DataWeight.h"
38
39#include <boost/iterator/transform_iterator.hpp>
40#include <boost/mpl/if.hpp>
41#include <boost/type_traits/is_const.hpp>
42#include <boost/type_traits/add_const.hpp>
43
44#include <algorithm>
45#include <cmath>
46#include <functional>
47#include <map>
48#include <ostream>
49#include <string>
50#include <utility>
51#include <vector>
52
53// We are intruding standard namespace, which might cause
54// conflicts. Let the user turn off these declarations by defining
55// YAT_STD_DISABE
56#ifndef YAT_STD_DISABLE
57namespace std {
58
59  ///
60  /// Print out a pair
61  ///
62  // This is in namespace std because we have not figured out how to have
63  // pair and its operator<< in different namespaces
64  template <class T1, class T2> 
65  std::ostream& operator<<(std::ostream& out, const std::pair<T1,T2>& p) 
66  { out << p.first << "\t" << p.second; return out; }
67
68}
69#endif
70
71namespace theplu {
72namespace yat {
73namespace utility {
74
75  /**
76     Functor class taking absolute value
77  */
78  template<typename T>
79  struct abs : std::unary_function<T, T>
80  {
81    /**
82       \return absolute value
83     */
84    inline T operator()(T x) const
85    { return std::abs(x); }
86  };
87
88
89  /**
90     See The C++ Standard Library - A Tutorial and Reference by
91     Nicolai M. Josuttis
92
93     If f is a binary functor, both g and h are unary functors, and
94     return type of g (and h) is convertible to F's argument type,
95     then compose_f_gx_hy can be used to create a functor equivalent
96     to \f$ f(g(x), h(y)) \f$
97
98     F must be an adaptable binary functor
99     G must be an adaptable unary functor
100     H must be an adaptable unary functor
101   */
102  template<class F, class G, class H>
103  class compose_f_gx_hy : std::binary_function<typename G::argument_type,
104                                               typename H::argument_type,
105                                               typename F::result_type>
106  {
107  public:
108    /**
109       \brief Constructor
110     */
111    compose_f_gx_hy(F f, G g, H h)
112      : f_(f), g_(g), h_(h) {}
113
114    /**
115       \brief Does the work
116     */
117    typename F::result_type
118    operator()(typename G::argument_type x, 
119               typename H::argument_type y) const
120    {
121      return f_(g_(x), h_(y));
122    }
123
124  private:
125    F f_;
126    G g_;
127    H h_;
128  };
129
130  /**
131     Convenient function to create a compose_f_gx_hy.
132
133     \see std::make_pair
134  */
135  template<class F, class G, class H>
136  compose_f_gx_hy<F, G, H> make_compose_f_gx_hy(F f, G g, H h)
137  {
138    return compose_f_gx_hy<F,G,H>(f,g,h);
139  } 
140
141  /**
142     Functor class to exponentiate values using std::exp
143
144     T should be either \c float, \c double, or \c long \c double
145
146     \since New in yat 0.5
147  */
148  template<typename T>
149  struct Exp : std::unary_function<T, T>
150  {
151    /**
152       \return exponentiated value
153     */
154    inline T operator()(T x) const
155    { return std::exp(x); }
156  };
157
158  /**
159     Creating a map from a range [first, last) such that m[key]
160     returns a vector with indices of which element in [first, last)
161     that is equal to \a key, or more technically: m[element].size()
162     returns number of elements equal to \a element, and
163     m[*element][i] = distance(first, element) for every \a element in
164     [first, last) and \a i smaller than m[element].size().
165
166     Requirement: InputIterator's value type is assignable to Key
167
168     \since New in yat 0.5
169   */
170  template<typename InputIterator, typename Key>
171  void inverse(InputIterator first, InputIterator last,
172               std::map<Key, std::vector<size_t> >& m)
173  {
174    m.clear();
175    for (size_t i=0; first!=last; ++i, ++first)
176      m[*first].push_back(i);
177  }
178
179  /**
180     In the created multimap each element e will fulfill: \f$ *(first
181     + e->second) == e->first \f$
182
183     Requirement: InputIterator's value type is assignable to Key
184
185     \since New in yat 0.5
186   */
187  template<typename Key, typename InputIterator>
188  void inverse(InputIterator first, InputIterator last, 
189               std::multimap<Key, size_t>& m)
190  {
191    m.clear();
192    for (size_t i=0; first!=last; ++i, ++first)
193      m.insert(std::make_pair(*first, i));
194  }
195
196
197  /**
198     \brief Functor that behaves like std::less with the exception
199     that it treates NaN as a number larger than infinity.
200
201     This functor is useful when sorting ranges with NaNs. The problem
202     with NaNs is that std::less always returns \c false when one of
203     the arguments is NaN. That together with the fact that std::sort
204     only guarantees that an element \c i is never less than previous
205     element \c --i. Therefore {10, NaN, 2} is sorted according to
206     this definition, but most often it is desired that the 2 is
207     located before the 10 in the range. Using this functor, less_nan,
208     this can easily be achieved as std::sort(first, last, less_nan)
209
210     The default implementation uses std::isnan(T), which consequently
211     must be supported.
212
213     There is a specialization less_nan<DataWeight>
214
215     \since New in yat 0.6
216  */
217  template<typename T>
218  struct less_nan : std::binary_function<T, T, bool>
219  {
220    /**
221       \return \c true if x is less than y. NaNs are treated as a number
222       larger than infinity, which implies \c true is returned if y is
223       NaN and x is not.
224     */
225    inline bool operator()(T x, T y) const
226    { 
227      if (std::isnan(x))
228        return false;
229      if (std::isnan(y))
230        return true;
231      return x<y;
232    }
233  };
234
235
236  /**
237     \brief Specialization for DataWeight.
238   */
239  template<>
240  struct less_nan<DataWeight> 
241    : std::binary_function<DataWeight, DataWeight, bool>
242  {
243    /**
244       \return less_nan<double>(x.data(), y.data())
245     */
246    inline bool operator()(const DataWeight& x, const DataWeight& y) const
247    { 
248      less_nan<double> compare;
249      return compare(x.data(), y.data());
250    }
251  };
252
253
254  /**
255     Functor class to take logarithm
256
257     T should be either \c float, \c double, or \c long \c double
258
259     \since New in yat 0.5
260  */
261  template<typename T>
262  class Log : std::unary_function<T, T>
263  {
264  public:
265    /**
266       Default constructor using natural base \f$ e \f$
267     */
268    Log(void)
269      : log_base_(1.0) {}
270
271    /**
272       \param base Taking logarithm in which base, e.g. 2 or 10.
273    */
274    explicit Log(double base) : log_base_(std::log(base)) {}
275
276    /**
277       \return logarithm
278     */
279    inline T operator()(T x) const
280    { return std::log(x)/log_base_; }
281
282  private:
283    double log_base_;
284  };
285
286  /**
287     \return max of values
288   */
289  template <typename T>
290  T max(const T& a, const T& b, const T& c)
291  {
292    return std::max(std::max(a,b),c);
293  }
294
295
296  /**
297     \return max of values
298   */
299  template <typename T>
300  T max(const T& a, const T& b, const T& c, const T& d)
301  {
302    return std::max(std::max(a,b), std::max(c,d));
303  }
304
305
306  /**
307     \return max of values
308   */
309  template <typename T>
310  T max(const T& a, const T& b, const T& c, const T& d, const T& e)
311  {
312    return std::max(max(a,b,c,d), e);
313  }
314
315
316  /**
317     \return max of values
318   */
319  template <typename T>
320  T max(const T& a, const T& b, const T& c, const T& d, const T& e, const T& f)
321  {
322    return std::max(max(a,b,c,d), std::max(e,f));
323  }
324
325
326  ///
327  /// @brief Functor comparing pairs using second.
328  ///
329  /// STL provides operator< for the pair.first element, but none for
330  /// pair.second. This template provides this and can be used as the
331  /// comparison object in generic functions such as the STL sort.
332  ///
333  template <class T1,class T2>
334  struct pair_value_compare
335  {
336    ///
337    /// @return true if x.second<y.second or (!(y.second<y.second) and
338    /// x.first<y.first)
339    ///
340    inline bool operator()(const std::pair<T1,T2>& x,
341                           const std::pair<T1,T2>& y) {
342      return ((x.second<y.second) ||
343              (!(y.second<x.second) && (x.first<y.first))); 
344    }
345  };
346
347  /**
348     \brief Functor that return std::pair.first
349
350     \see pair_first_iterator
351
352     \since New in yat 0.5
353   */
354  template <class Pair>
355  struct PairFirst
356  {
357    /**
358       The type returned is Pair::first_type& with the exception when
359       Pair is const and Pair::first_type is non-const, in which case
360       const Pair::first_type& is return type.
361     */
362    typedef typename boost::mpl::if_<
363                  typename boost::is_const<Pair>::type, 
364                  typename boost::add_const<typename Pair::first_type>::type&,
365                  typename Pair::first_type&>::type result_type;
366   
367    /**
368       The argument type is Pair&.
369     */
370    typedef Pair& argument_type;
371
372    /**
373       \return p.first
374     */
375    inline result_type operator()(argument_type p) const
376    { return p.first; }
377
378  };
379
380
381  /**
382     \brief Functor that return std::pair.second
383
384     \see pair_second_iterator
385
386     \since New in yat 0.5
387   */
388  template <class Pair>
389  struct PairSecond
390  {
391    /**
392       The type returned is Pair::second_type& with the exception when
393       Pair is const and Pair::second_type is non-const, in which case
394       const Pair::first_type& is return type.
395     */
396    typedef typename boost::mpl::if_<
397                  typename boost::is_const<Pair>::type, 
398                  typename boost::add_const<typename Pair::second_type>::type&,
399                  typename Pair::second_type&>::type result_type;
400   
401    /**
402       The argument type is Pair&.
403     */
404    typedef Pair& argument_type;
405
406    /**
407       \return p.first
408     */
409    inline result_type operator()(argument_type p) const
410    { return p.second; }
411
412  };
413
414
415  /**
416     Creates a transform_iterator that transforms an iterator with
417     value type std::pair to an iterator with value type
418     std::pair::first_type. This can be used, for example, to
419     communicate between a std::map and std::vector
420
421     \code
422     std::map<std::string, int> map;
423     ...
424     std::vector<std::string> vec;
425     vec.resize(map.size());
426     std::copy(pair_first_iterator(map.begin()), pair_first_iterator(map.end()),
427               vec.begin());
428     \endcode
429
430     \since New in yat 0.5
431   */
432  template<class Iter>
433  boost::transform_iterator<
434    PairFirst<typename std::iterator_traits<Iter>::value_type>, 
435    Iter> pair_first_iterator(Iter i)
436  {
437    typedef PairFirst<typename std::iterator_traits<Iter>::value_type> PF; 
438    return boost::transform_iterator<PF, Iter>(i, PF());
439  }
440
441
442  /**
443     Creates a transform_iterator that transforms an iterator with
444     value type std::pair to an iterator with value type
445     std::pair::second_type. This can be used, for example, to
446     communicate between a std::map and std::vector
447
448     \code
449     std::map<std::string, int> map;
450     ...
451     std::vector<int> vec(map.size(),0);
452     std::copy(vec.begin(), vec.end(), pair_second_iterator(map.begin()));
453     \endcode
454
455     \since New in yat 0.5
456   */
457  template<class Iter>
458  boost::transform_iterator<
459    PairSecond<typename std::iterator_traits<Iter>::value_type>, 
460    Iter> pair_second_iterator(Iter i)
461  {
462    typedef PairSecond<typename std::iterator_traits<Iter>::value_type> PF; 
463    return boost::transform_iterator<PF, Iter>(i, PF());
464  }
465
466
467
468
469  ///
470  /// @brief Function converting a string to lower case
471  ///
472  std::string& to_lower(std::string& s);
473
474  ///
475  /// @brief Function converting a string to upper case
476  ///
477  std::string& to_upper(std::string& s);
478
479}}} // of namespace utility, yat, and theplu
480
481#endif
Note: See TracBrowser for help on using the repository browser.