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

Last change on this file since 1566 was 1487, checked in by Jari Häkkinen, 13 years ago

Addresses #436. GPL license copy reference should also be updated.

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