yat  0.8.3pre
stl_utility.h
Go to the documentation of this file.
00001 #ifndef _theplu_yat_utility_stl_utility_
00002 #define _theplu_yat_utility_stl_utility_ 
00003 
00004 // $Id: stl_utility.h 2530 2011-07-28 19:04:25Z peter $
00005 
00006 /*
00007   Copyright (C) 2004 Jari Häkkinen
00008   Copyright (C) 2005 Jari Häkkinen, Peter Johansson, Markus Ringnér
00009   Copyright (C) 2006 Jari Häkkinen
00010   Copyright (C) 2007, 2008 Jari Häkkinen, Peter Johansson
00011   Copyright (C) 2009, 2010, 2011 Peter Johansson
00012 
00013   This file is part of the yat library, http://dev.thep.lu.se/yat
00014 
00015   The yat library is free software; you can redistribute it and/or
00016   modify it under the terms of the GNU General Public License as
00017   published by the Free Software Foundation; either version 3 of the
00018   License, or (at your option) any later version.
00019 
00020   The yat library is distributed in the hope that it will be useful,
00021   but WITHOUT ANY WARRANTY; without even the implied warranty of
00022   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00023   General Public License for more details.
00024 
00025   You should have received a copy of the GNU General Public License
00026   along with yat. If not, see <http://www.gnu.org/licenses/>.
00027 */
00028 
00036 
00037 #include "concept_check.h"
00038 #include "DataWeight.h"
00039 #include "Exception.h"
00040 
00041 #include <boost/concept_check.hpp>
00042 #include <boost/iterator/transform_iterator.hpp>
00043 #include <boost/mpl/if.hpp>
00044 #include <boost/type_traits/add_const.hpp>
00045 #include <boost/type_traits/is_const.hpp>
00046 #include <boost/type_traits/remove_reference.hpp>
00047 
00048 #include <algorithm>
00049 #include <cmath>
00050 #include <exception>
00051 #include <functional>
00052 #include <iterator>
00053 #include <map>
00054 #include <ostream>
00055 #include <sstream>
00056 #include <string>
00057 #include <utility>
00058 #include <vector>
00059 
00060 // We are intruding standard namespace, which might cause
00061 // conflicts. Let the user turn off these declarations by defining
00062 // YAT_STD_DISABE
00063 #ifndef YAT_STD_DISABLE
00064 namespace std {
00065 
00069   // This is in namespace std because we have not figured out how to have
00070   // pair and its operator<< in different namespaces
00071   template <class T1, class T2>  
00072   std::ostream& operator<<(std::ostream& out, const std::pair<T1,T2>& p) 
00073   { out << p.first << "\t" << p.second; return out; }
00074 
00075 }
00076 #endif
00077 
00078 namespace theplu {
00079 namespace yat {
00080 namespace utility {
00081 
00085   template<typename T>
00086   struct abs : std::unary_function<T, T>
00087   {
00091     inline T operator()(T x) const
00092     { return std::abs(x); }
00093   };
00094 
00095 
00106   template<typename Pointer>
00107   struct Dereferencer : 
00108     public std::unary_function<Pointer, 
00109                                typename std::iterator_traits<Pointer>::reference>
00110   {
00114     Dereferencer(void) 
00115     { BOOST_CONCEPT_ASSERT((TrivialIterator<Pointer>)); }
00116 
00120     typename std::iterator_traits<Pointer>::reference
00121     operator()(Pointer ti) const { return *ti; }
00122   };
00123 
00124 
00148   template<class F, class G, class H>
00149   class compose_f_gx_hy : 
00150     public std::binary_function<typename G::argument_type,
00151                                 typename H::argument_type,
00152                                 typename F::result_type>
00153   {
00154   public:
00158     compose_f_gx_hy(F f, G g, H h)
00159       : f_(f), g_(g), h_(h) 
00160     {
00161       BOOST_CONCEPT_ASSERT((boost::Convertible<typename G::result_type
00162                             , typename F::first_argument_type>));
00163       BOOST_CONCEPT_ASSERT((boost::Convertible<typename H::result_type
00164                             , typename F::second_argument_type>));
00165 
00166     }
00167 
00171     typename F::result_type
00172     operator()(typename G::argument_type x, 
00173                typename H::argument_type y) const
00174     {
00175       return f_(g_(x), h_(y));
00176     }
00177 
00178   private:
00179     F f_;
00180     G g_;
00181     H h_;
00182   };
00183 
00191   template<class F, class G, class H>
00192   compose_f_gx_hy<F, G, H> make_compose_f_gx_hy(F f, G g, H h)
00193   {
00194     return compose_f_gx_hy<F,G,H>(f,g,h);
00195   }  
00196 
00197 
00219   template<class F, class G>
00220   class compose_f_gxy : 
00221     public std::binary_function<typename G::first_argument_type,
00222                                 typename G::second_argument_type,
00223                                 typename F::result_type>
00224   {
00225   public:
00229     compose_f_gxy(F f, G g)
00230       : f_(f), g_(g) 
00231     {
00232       BOOST_CONCEPT_ASSERT((boost::Convertible<typename G::result_type
00233                             , typename F::argument_type>));
00234     }
00235 
00239     typename F::result_type
00240     operator()(typename G::first_argument_type x, 
00241                typename G::second_argument_type y) const
00242     {
00243       return f_(g_(x,y));
00244     }
00245 
00246   private:
00247     F f_;
00248     G g_;
00249   };
00250 
00260   template<class F, class G>
00261   compose_f_gxy<F, G> make_compose_f_gxy(F f, G g)
00262   {
00263     return compose_f_gxy<F,G>(f,g);
00264   }  
00265 
00266 
00287   template<class F, class G>
00288   class compose_f_gx : public std::unary_function<typename G::argument_type,
00289                                                   typename F::result_type>
00290   {
00291   public:
00295     compose_f_gx(F f, G g)
00296       : f_(f), g_(g) 
00297     {
00298       BOOST_CONCEPT_ASSERT((boost::Convertible<typename G::result_type
00299                             , typename F::argument_type>));
00300     }
00301 
00305     typename F::result_type
00306     operator()(typename G::argument_type x) const
00307     {
00308       return f_(g_(x));
00309     }
00310 
00311   private:
00312     F f_;
00313     G g_;
00314   };
00315 
00325   template<class F, class G>
00326   compose_f_gx<F, G> make_compose_f_gx(F f, G g)
00327   {
00328     return compose_f_gx<F,G>(f,g);
00329   }  
00330 
00331 
00339   template<typename T>
00340   struct Exp : std::unary_function<T, T>
00341   {
00345     inline T operator()(T x) const
00346     { return std::exp(x); }
00347   };
00348 
00354   template<typename T>
00355   struct Identity : public std::unary_function<T, T>
00356   {
00358     T operator()(T arg) const { return arg; }
00359   };
00360 
00361 
00371   template <typename Key, typename Tp, typename Compare, typename Alloc>
00372   const Tp& get(const std::map<Key, Tp, Compare, Alloc>& m, const Key& k);
00373 
00374 
00387   template<typename InputIterator, typename Key, typename Comp>
00388   void inverse(InputIterator first, InputIterator last,
00389                std::map<Key, std::vector<size_t>, Comp >& m)
00390   {
00391     BOOST_CONCEPT_ASSERT((boost::InputIterator<InputIterator>));
00392     BOOST_CONCEPT_ASSERT((boost::Convertible<typename std::iterator_traits<InputIterator>::value_type, Key>));
00393     m.clear();
00394     for (size_t i=0; first!=last; ++i, ++first)
00395       m[*first].push_back(i);
00396   }
00397 
00406   template<typename Key, typename InputIterator, typename Comp>
00407   void inverse(InputIterator first, InputIterator last, 
00408                std::multimap<Key, size_t, Comp>& m)
00409   {
00410     BOOST_CONCEPT_ASSERT((boost::InputIterator<InputIterator>));
00411     BOOST_CONCEPT_ASSERT((boost::Convertible<typename std::iterator_traits<InputIterator>::value_type, Key>));
00412     m.clear();
00413     for (size_t i=0; first!=last; ++i, ++first)
00414       m.insert(std::make_pair(*first, i));
00415   }
00416 
00417 
00438   template<typename T>
00439   struct less_nan : std::binary_function<T, T, bool>
00440   {
00446     inline bool operator()(T x, T y) const
00447     { 
00448       if (std::isnan(x))
00449         return false;
00450       if (std::isnan(y))
00451         return true;
00452       return x<y;
00453     }
00454   };
00455 
00456 
00460   template<>
00461   struct less_nan<DataWeight> 
00462     : std::binary_function<DataWeight, DataWeight, bool>
00463   {
00467     inline bool operator()(const DataWeight& x, const DataWeight& y) const
00468     { 
00469       less_nan<double> compare;
00470       return compare(x.data(), y.data());
00471     }
00472   };
00473 
00474 
00482   template<typename T>
00483   class Log : std::unary_function<T, T>
00484   {
00485   public:
00489     Log(void)
00490       : log_base_(1.0) {}
00491 
00495     explicit Log(double base) : log_base_(std::log(base)) {}
00496 
00500     inline T operator()(T x) const
00501     { return std::log(x)/log_base_; }
00502 
00503   private:
00504     double log_base_;
00505   };
00506 
00510   template <typename T>
00511   T max(const T& a, const T& b, const T& c)
00512   {
00513     return std::max(std::max(a,b),c);
00514   }
00515 
00516 
00520   template <typename T>
00521   T max(const T& a, const T& b, const T& c, const T& d)
00522   {
00523     return std::max(std::max(a,b), std::max(c,d));
00524   }
00525 
00526 
00530   template <typename T>
00531   T max(const T& a, const T& b, const T& c, const T& d, const T& e)
00532   {
00533     return std::max(max(a,b,c,d), e);
00534   }
00535 
00536 
00540   template <typename T>
00541   T max(const T& a, const T& b, const T& c, const T& d, const T& e, const T& f)
00542   {
00543     return std::max(max(a,b,c,d), std::max(e,f));
00544   }
00545 
00546 
00554   template <class T1,class T2>
00555   struct pair_value_compare
00556   {
00561     inline bool operator()(const std::pair<T1,T2>& x,
00562                            const std::pair<T1,T2>& y) {
00563       return ((x.second<y.second) ||
00564               (!(y.second<x.second) && (x.first<y.first))); 
00565     }
00566   };
00567 
00575   template <class Pair>
00576   struct PairFirst 
00577   {
00583     typedef typename boost::mpl::if_<
00584                   typename boost::is_const<Pair>::type, 
00585                   typename boost::add_const<typename Pair::first_type>::type&,
00586                   typename Pair::first_type&>::type result_type;
00587     
00591     typedef Pair& argument_type;
00592 
00596     inline result_type operator()(argument_type p) const
00597     { return p.first; }
00598 
00599   };
00600 
00601 
00609   template <class Pair>
00610   struct PairSecond 
00611   {
00617     typedef typename boost::mpl::if_<
00618                   typename boost::is_const<Pair>::type, 
00619                   typename boost::add_const<typename Pair::second_type>::type&,
00620                   typename Pair::second_type&>::type result_type;
00621     
00625     typedef Pair& argument_type;
00626 
00630     inline result_type operator()(argument_type p) const
00631     { return p.second; }
00632 
00633   };
00634 
00635 
00653   template<class Iter>
00654   boost::transform_iterator<
00655     PairFirst<typename boost::remove_reference<
00656                  typename std::iterator_traits<Iter>::reference
00657                  >::type>,
00658     Iter> pair_first_iterator(Iter i)
00659   {
00660     // We are going via ::reference in order to remain const info;
00661     // ::value_type does not contain const information.
00662     typedef typename std::iterator_traits<Iter>::reference ref_type;
00663     typedef typename boost::remove_reference<ref_type>::type val_type;
00664     typedef PairFirst<val_type> PF; 
00665     return boost::transform_iterator<PF, Iter>(i, PF());
00666   }
00667 
00668 
00684   template<class Iter>
00685   boost::transform_iterator<
00686     PairSecond<typename boost::remove_reference<
00687                  typename std::iterator_traits<Iter>::reference
00688                  >::type>,
00689     Iter> pair_second_iterator(Iter i)
00690   {
00691     // We are going via ::reference in order to remain const info;
00692     // ::value_type does not contain const information.
00693     typedef typename std::iterator_traits<Iter>::reference ref_type;
00694     typedef typename boost::remove_reference<ref_type>::type val_type;
00695     typedef PairSecond<val_type> PS; 
00696     return boost::transform_iterator<PS, Iter>(i, PS());
00697   }
00698 
00699 
00728   template<typename Pointer, class Compare>
00729   compose_f_gx_hy<Compare, Dereferencer<Pointer>, Dereferencer<Pointer> >
00730   make_ptr_compare(Pointer p, Compare compare)
00731   {
00732     return make_compose_f_gx_hy(compare, Dereferencer<Pointer>(),
00733                                 Dereferencer<Pointer>());
00734   }
00735 
00742   template<typename Pointer>
00743   compose_f_gx_hy<std::less<typename std::iterator_traits<Pointer>::value_type>,
00744                   Dereferencer<Pointer>, Dereferencer<Pointer> >
00745   make_ptr_compare(Pointer p)
00746   {
00747     typedef typename std::iterator_traits<Pointer>::value_type value_type;
00748     BOOST_CONCEPT_ASSERT((boost::LessThanComparable<value_type>));
00749     std::less<value_type> compare;
00750     return make_ptr_compare(p, compare);
00751   }
00752 
00753 
00757   std::string& to_lower(std::string& s);
00758 
00762   std::string& to_upper(std::string& s);
00763 
00764 
00765   // template implementations
00766 
00767   template <typename Key, typename Tp, typename Compare, typename Alloc>
00768   const Tp& get(const std::map<Key, Tp, Compare, Alloc>& m, const Key& key)
00769   {
00770     typename std::map<Key, Tp, Compare,Alloc>::const_iterator iter(m.find(key));
00771     if (iter==m.end()) {
00772       std::stringstream ss;
00773       ss << "utility::get(const Map&, const Key&): `" 
00774          << key << "' not found in map\n";
00775       throw runtime_error(ss.str());
00776     }
00777     return iter->second;
00778   }
00779 
00780 }}} // of namespace utility, yat, and theplu
00781 #endif

Generated on Thu Dec 20 2012 03:12:58 for yat by  doxygen 1.8.0-20120409