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

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

fixes #421

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