Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/Common/utility.h

    r9feb34b r7491f97  
    55// file "LICENCE" distributed with Cforall.
    66//
    7 // utility.h -- General utilities used across the compiler.
     7// utility.h --
    88//
    99// Author           : Richard C. Bilson
    1010// Created On       : Mon May 18 07:44:20 2015
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Fri Feb 17 15:25:00 2023
    13 // Update Count     : 53
     12// Last Modified On : Mon Apr 25 14:26:00 2022
     13// Update Count     : 51
    1414//
    1515
     
    1919#include <cctype>
    2020#include <algorithm>
     21#include <functional>
    2122#include <iostream>
     23#include <iterator>
    2224#include <list>
    2325#include <memory>
     26#include <sstream>
    2427#include <string>
    2528#include <type_traits>
     29#include <utility>
    2630#include <vector>
    2731#include <cstring>                                                                              // memcmp
     
    4549                return 0;
    4650        } // if
     51}
     52
     53template< typename T, typename U >
     54struct maybeBuild_t {
     55        static T * doit( const U *orig ) {
     56                if ( orig ) {
     57                        return orig->build();
     58                } else {
     59                        return 0;
     60                } // if
     61        }
     62};
     63
     64template< typename T, typename U >
     65static inline T * maybeBuild( const U *orig ) {
     66        return maybeBuild_t<T,U>::doit(orig);
     67}
     68
     69template< typename T, typename U >
     70static inline T * maybeMoveBuild( const U *orig ) {
     71        T* ret = maybeBuild<T>(orig);
     72        delete orig;
     73        return ret;
    4774}
    4875
     
    141168        splice( src, dst );
    142169        dst.swap( src );
     170}
     171
     172template < typename T >
     173void toString_single( std::ostream & os, const T & value ) {
     174        os << value;
     175}
     176
     177template < typename T, typename... Params >
     178void toString_single( std::ostream & os, const T & value, const Params & ... params ) {
     179        os << value;
     180        toString_single( os, params ... );
     181}
     182
     183template < typename ... Params >
     184std::string toString( const Params & ... params ) {
     185        std::ostringstream os;
     186        toString_single( os, params... );
     187        return os.str();
     188}
     189
     190#define toCString( ... ) toString( __VA_ARGS__ ).c_str()
     191
     192// replace element of list with all elements of another list
     193template< typename T >
     194void replace( std::list< T > &org, typename std::list< T >::iterator pos, std::list< T > &with ) {
     195        typename std::list< T >::iterator next = pos; advance( next, 1 );
     196
     197        //if ( next != org.end() ) {
     198        org.erase( pos );
     199        org.splice( next, with );
     200        //}
     201
     202        return;
     203}
     204
     205// replace range of a list with a single element
     206template< typename T >
     207void replace( std::list< T > &org, typename std::list< T >::iterator begin, typename std::list< T >::iterator end, const T & with ) {
     208        org.insert( begin, with );
     209        org.erase( begin, end );
    143210}
    144211
     
    169236}
    170237
     238template< typename... Args >
     239auto zip(Args&&... args) -> decltype(zipWith(std::forward<Args>(args)..., std::make_pair)) {
     240  return zipWith(std::forward<Args>(args)..., std::make_pair);
     241}
     242
     243template< class InputIterator1, class InputIterator2, class OutputIterator, class BinFunction >
     244void zipWith( InputIterator1 b1, InputIterator1 e1, InputIterator2 b2, InputIterator2 e2, OutputIterator out, BinFunction func ) {
     245        while ( b1 != e1 && b2 != e2 )
     246                *out++ = func(*b1++, *b2++);
     247}
     248
     249// it's nice to actually be able to increment iterators by an arbitrary amount
     250template< class InputIt, class Distance >
     251InputIt operator+( InputIt it, Distance n ) {
     252        advance(it, n);
     253        return it;
     254}
     255
     256template< typename T >
     257void warn_single( const T & arg ) {
     258        std::cerr << arg << std::endl;
     259}
     260
     261template< typename T, typename... Params >
     262void warn_single(const T & arg, const Params & ... params ) {
     263        std::cerr << arg;
     264        warn_single( params... );
     265}
     266
     267template< typename... Params >
     268void warn( const Params & ... params ) {
     269        std::cerr << "Warning: ";
     270        warn_single( params... );
     271}
     272
    171273// determines if pref is a prefix of str
    172274static inline bool isPrefix( const std::string & str, const std::string & pref, unsigned int start = 0 ) {
    173275        if ( pref.size() > str.size() ) return false;
    174         return pref == str.substr(start, pref.size());
    175 }
     276    return 0 == memcmp( str.c_str() + start, pref.c_str(), pref.size() );
     277        // return prefix == full.substr(0, prefix.size()); // for future, requires c++17
     278}
     279
     280// -----------------------------------------------------------------------------
     281// Ref Counted Singleton class
     282// Objects that inherit from this class will have at most one reference to it
     283// but if all references die, the object will be deleted.
     284
     285template< typename ThisType >
     286class RefCountSingleton {
     287  public:
     288        static std::shared_ptr<ThisType> get() {
     289                if( global_instance.expired() ) {
     290                        std::shared_ptr<ThisType> new_instance = std::make_shared<ThisType>();
     291                        global_instance = new_instance;
     292                        return std::move(new_instance);
     293                }
     294                return global_instance.lock();
     295        }
     296  private:
     297        static std::weak_ptr<ThisType> global_instance;
     298};
     299
     300template< typename ThisType >
     301std::weak_ptr<ThisType> RefCountSingleton<ThisType>::global_instance;
    176302
    177303// -----------------------------------------------------------------------------
     
    230356        ~ValueGuardPtr() { if( ref ) { swap( *ref, old ); } }
    231357};
     358
     359// -----------------------------------------------------------------------------
     360// Helper struct and function to support
     361// for ( val : reverseIterate( container ) ) {}
     362// syntax to have a for each that iterates backwards
     363
     364template< typename T >
     365struct reverse_iterate_t {
     366        T& ref;
     367
     368        reverse_iterate_t( T & ref ) : ref(ref) {}
     369
     370        // this does NOT work on const T!!!
     371        // typedef typename T::reverse_iterator iterator;
     372        auto begin() { return ref.rbegin(); }
     373        auto end() { return ref.rend(); }
     374};
     375
     376template< typename T >
     377reverse_iterate_t< T > reverseIterate( T & ref ) {
     378        return reverse_iterate_t< T >( ref );
     379}
     380
     381template< typename T >
     382struct enumerate_t {
     383        template<typename val_t>
     384        struct value_t {
     385                val_t & val;
     386                size_t idx;
     387        };
     388
     389        template< typename iter_t, typename val_t >
     390        struct iterator_t {
     391                iter_t it;
     392                size_t idx;
     393
     394                iterator_t( iter_t _it, size_t _idx ) : it(_it), idx(_idx) {}
     395
     396                value_t<val_t> operator*() const { return value_t<val_t>{ *it, idx }; }
     397
     398                bool operator==(const iterator_t & o) const { return o.it == it; }
     399                bool operator!=(const iterator_t & o) const { return o.it != it; }
     400
     401                iterator_t & operator++() {
     402                        it++;
     403                        idx++;
     404                        return *this;
     405                }
     406
     407                using difference_type   = typename std::iterator_traits< iter_t >::difference_type;
     408                using value_type        = value_t<val_t>;
     409                using pointer           = value_t<val_t> *;
     410                using reference         = value_t<val_t> &;
     411                using iterator_category = std::forward_iterator_tag;
     412        };
     413
     414        T & ref;
     415
     416        using iterator = iterator_t< typename T::iterator, typename T::value_type >;
     417        using const_iterator = iterator_t< typename T::const_iterator, const typename T::value_type >;
     418
     419        iterator begin() { return iterator( ref.begin(), 0 ); }
     420        iterator end()   { return iterator( ref.end(), ref.size() ); }
     421
     422        const_iterator begin() const { return const_iterator( ref.cbegin(), 0 ); }
     423        const_iterator end()   const { return const_iterator( ref.cend(), ref.size() ); }
     424
     425        const_iterator cbegin() const { return const_iterator( ref.cbegin(), 0 ); }
     426        const_iterator cend()   const { return const_iterator( ref.cend(), ref.size() ); }
     427};
     428
     429template< typename T >
     430enumerate_t<T> enumerate( T & ref ) {
     431        return enumerate_t< T >{ ref };
     432}
     433
     434template< typename T >
     435const enumerate_t< const T > enumerate( const T & ref ) {
     436        return enumerate_t< const T >{ ref };
     437}
     438
     439template< typename OutType, typename Range, typename Functor >
     440OutType map_range( const Range& range, Functor&& functor ) {
     441        OutType out;
     442
     443        std::transform(
     444                begin( range ),
     445                end( range ),
     446                std::back_inserter( out ),
     447                std::forward< Functor >( functor )
     448        );
     449
     450        return out;
     451}
     452
     453// -----------------------------------------------------------------------------
     454// Helper struct and function to support:
     455// for ( auto val : group_iterate( container1, container2, ... ) ) { ... }
     456// This iteraters through multiple containers of the same size.
     457
     458template<typename... Args>
     459class group_iterate_t {
     460        using Iterables = std::tuple<Args...>;
     461        Iterables iterables;
     462
     463        // Getting the iterator and value types this way preserves const.
     464        template<size_t I> using Iter = decltype(std::get<I>(iterables).begin());
     465        template<size_t I> using Data = decltype(*std::get<I>(iterables).begin());
     466        template<typename> struct base_iterator;
     467
     468        // This inner template puts the sequence of `0, 1, ... sizeof...(Args)-1`
     469        // into a pack. These are the indexes into the tuples, so unpacking can
     470        // go over each element of the tuple.
     471        // The std::integer_sequence is just used to build that sequence.
     472        // A library reference will probably explain it better than I can.
     473        template<std::size_t... Indices>
     474        struct base_iterator<std::integer_sequence<std::size_t, Indices...>> {
     475                using value_type = std::tuple< Data<Indices>... >;
     476                std::tuple<Iter<Indices>...> iterators;
     477
     478                base_iterator( Iter<Indices>... is ) : iterators( is... ) {}
     479                base_iterator operator++() {
     480                        return base_iterator( ++std::get<Indices>( iterators )... );
     481                }
     482                bool operator!=( const base_iterator& other ) const {
     483                        return iterators != other.iterators;
     484                }
     485                value_type operator*() const {
     486                        return std::tie( *std::get<Indices>( iterators )... );
     487                }
     488
     489                static base_iterator make_begin( Iterables & data ) {
     490                        return base_iterator( std::get<Indices>( data ).begin()... );
     491                }
     492                static base_iterator make_end( Iterables & data ) {
     493                        return base_iterator( std::get<Indices>( data ).end()... );
     494                }
     495        };
     496
     497public:
     498        group_iterate_t( const Args &... args ) : iterables( args... ) {}
     499
     500        using iterator = base_iterator<decltype(
     501                std::make_integer_sequence<std::size_t, sizeof...(Args)>())>;
     502
     503        iterator begin() { return iterator::make_begin( iterables ); }
     504        iterator end() { return iterator::make_end( iterables ); }
     505};
     506
     507// Helpers for the bounds checks (the non-varatic part of group_iterate):
     508static inline void runGroupBoundsCheck(size_t size0, size_t size1) {
     509        assertf( size0 == size1,
     510                "group iteration requires containers of the same size: <%zd, %zd>.",
     511                size0, size1 );
     512}
     513
     514static inline void runGroupBoundsCheck(size_t size0, size_t size1, size_t size2) {
     515        assertf( size0 == size1 && size1 == size2,
     516                "group iteration requires containers of the same size: <%zd, %zd, %zd>.",
     517                size0, size1, size2 );
     518}
     519
     520/// Performs bounds check to ensure that all arguments are of the same length.
     521template< typename... Args >
     522group_iterate_t<Args...> group_iterate( Args &&... args ) {
     523        runGroupBoundsCheck( args.size()... );
     524        return group_iterate_t<Args...>( std::forward<Args>( args )... );
     525}
     526
     527/// Does not perform a bounds check - requires user to ensure that iteration terminates when appropriate.
     528template< typename... Args >
     529group_iterate_t<Args...> unsafe_group_iterate( Args &&... args ) {
     530        return group_iterate_t<Args...>( std::forward<Args>( args )... );
     531}
     532
     533// -----------------------------------------------------------------------------
     534// Helper struct and function to support
     535// for ( val : lazy_map( container1, f ) ) {}
     536// syntax to have a for each that iterates a container, mapping each element by applying f
     537template< typename T, typename Func >
     538struct lambda_iterate_t {
     539        const T & ref;
     540        std::function<Func> f;
     541
     542        struct iterator {
     543                typedef decltype(begin(ref)) Iter;
     544                Iter it;
     545                std::function<Func> f;
     546                iterator( Iter it, std::function<Func> f ) : it(it), f(f) {}
     547                iterator & operator++() {
     548                        ++it; return *this;
     549                }
     550                bool operator!=( const iterator &other ) const { return it != other.it; }
     551                auto operator*() const -> decltype(f(*it)) { return f(*it); }
     552        };
     553
     554        lambda_iterate_t( const T & ref, std::function<Func> f ) : ref(ref), f(f) {}
     555
     556        auto begin() const -> decltype(iterator(std::begin(ref), f)) { return iterator(std::begin(ref), f); }
     557        auto end() const   -> decltype(iterator(std::end(ref), f)) { return iterator(std::end(ref), f); }
     558};
     559
     560template< typename... Args >
     561lambda_iterate_t<Args...> lazy_map( const Args &... args ) {
     562        return lambda_iterate_t<Args...>( args...);
     563}
    232564
    233565// -----------------------------------------------------------------------------
     
    251583} // ilog2
    252584
     585// -----------------------------------------------------------------------------
     586/// evaluates expr as a long long int. If second is false, expr could not be evaluated
     587std::pair<long long int, bool> eval(const Expression * expr);
     588
     589namespace ast {
     590        class Expr;
     591}
     592
     593std::pair<long long int, bool> eval(const ast::Expr * expr);
     594
     595// -----------------------------------------------------------------------------
     596/// Reorders the input range in-place so that the minimal-value elements according to the
     597/// comparator are in front;
     598/// returns the iterator after the last minimal-value element.
     599template<typename Iter, typename Compare>
     600Iter sort_mins( Iter begin, Iter end, Compare& lt ) {
     601        if ( begin == end ) return end;
     602
     603        Iter min_pos = begin;
     604        for ( Iter i = begin + 1; i != end; ++i ) {
     605                if ( lt( *i, *min_pos ) ) {
     606                        // new minimum cost; swap into first position
     607                        min_pos = begin;
     608                        std::iter_swap( min_pos, i );
     609                } else if ( ! lt( *min_pos, *i ) ) {
     610                        // duplicate minimum cost; swap into next minimum position
     611                        ++min_pos;
     612                        std::iter_swap( min_pos, i );
     613                }
     614        }
     615        return ++min_pos;
     616}
     617
     618template<typename Iter, typename Compare>
     619inline Iter sort_mins( Iter begin, Iter end, Compare&& lt ) {
     620        return sort_mins( begin, end, lt );
     621}
     622
     623/// sort_mins defaulted to use std::less
     624template<typename Iter>
     625inline Iter sort_mins( Iter begin, Iter end ) {
     626        return sort_mins( begin, end, std::less<typename std::iterator_traits<Iter>::value_type>{} );
     627}
     628
    253629// Local Variables: //
    254630// tab-width: 4 //
Note: See TracChangeset for help on using the changeset viewer.