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

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

refs #536. changed DataWeight? comparison operators to be based on less_nan. Corrected template arguments in binary_function for less_nan

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