yat
0.8.3pre
|
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