Home | History | Annotate | Download | only in experimental
      1 // -*- C++ -*-
      2 //===-------------------------- functional --------------------------------===//
      3 //
      4 //                     The LLVM Compiler Infrastructure
      5 //
      6 // This file is dual licensed under the MIT and the University of Illinois Open
      7 // Source Licenses. See LICENSE.TXT for details.
      8 //
      9 //===----------------------------------------------------------------------===//
     10 
     11 #ifndef _LIBCPP_EXPERIMENTAL_FUNCTIONAL
     12 #define _LIBCPP_EXPERIMENTAL_FUNCTIONAL
     13 
     14 /*
     15    experimental/functional synopsis
     16 
     17 #include <algorithm>
     18 
     19 namespace std {
     20 namespace experimental {
     21 inline namespace fundamentals_v1 {
     22 
     23     // See C++14 20.9.9, Function object binders
     24     template <class T> constexpr bool is_bind_expression_v
     25       = is_bind_expression<T>::value;
     26     template <class T> constexpr int is_placeholder_v
     27       = is_placeholder<T>::value;
     28 
     29     // 4.2, Class template function
     30     template<class> class function; // undefined
     31     template<class R, class... ArgTypes> class function<R(ArgTypes...)>;
     32 
     33     template<class R, class... ArgTypes>
     34     void swap(function<R(ArgTypes...)>&, function<R(ArgTypes...)>&);
     35 
     36     template<class R, class... ArgTypes>
     37     bool operator==(const function<R(ArgTypes...)>&, nullptr_t) noexcept;
     38     template<class R, class... ArgTypes>
     39     bool operator==(nullptr_t, const function<R(ArgTypes...)>&) noexcept;
     40     template<class R, class... ArgTypes>
     41     bool operator!=(const function<R(ArgTypes...)>&, nullptr_t) noexcept;
     42     template<class R, class... ArgTypes>
     43     bool operator!=(nullptr_t, const function<R(ArgTypes...)>&) noexcept;
     44 
     45     // 4.3, Searchers
     46     template<class ForwardIterator, class BinaryPredicate = equal_to<>>
     47       class default_searcher;
     48 
     49     template<class RandomAccessIterator,
     50              class Hash = hash<typename iterator_traits<RandomAccessIterator>::value_type>,
     51              class BinaryPredicate = equal_to<>>
     52       class boyer_moore_searcher;
     53 
     54     template<class RandomAccessIterator,
     55              class Hash = hash<typename iterator_traits<RandomAccessIterator>::value_type>,
     56              class BinaryPredicate = equal_to<>>
     57       class boyer_moore_horspool_searcher;
     58 
     59     template<class ForwardIterator, class BinaryPredicate = equal_to<>>
     60     default_searcher<ForwardIterator, BinaryPredicate>
     61     make_default_searcher(ForwardIterator pat_first, ForwardIterator pat_last,
     62                           BinaryPredicate pred = BinaryPredicate());
     63 
     64     template<class RandomAccessIterator,
     65              class Hash = hash<typename iterator_traits<RandomAccessIterator>::value_type>,
     66              class BinaryPredicate = equal_to<>>
     67     boyer_moore_searcher<RandomAccessIterator, Hash, BinaryPredicate>
     68     make_boyer_moore_searcher(
     69         RandomAccessIterator pat_first, RandomAccessIterator pat_last,
     70         Hash hf = Hash(), BinaryPredicate pred = BinaryPredicate());
     71 
     72     template<class RandomAccessIterator,
     73              class Hash = hash<typename iterator_traits<RandomAccessIterator>::value_type>,
     74              class BinaryPredicate = equal_to<>>
     75     boyer_moore_horspool_searcher<RandomAccessIterator, Hash, BinaryPredicate>
     76     make_boyer_moore_horspool_searcher(
     77         RandomAccessIterator pat_first, RandomAccessIterator pat_last,
     78         Hash hf = Hash(), BinaryPredicate pred = BinaryPredicate());
     79 
     80   } // namespace fundamentals_v1
     81   } // namespace experimental
     82 
     83   template<class R, class... ArgTypes, class Alloc>
     84   struct uses_allocator<experimental::function<R(ArgTypes...)>, Alloc>;
     85 
     86 } // namespace std
     87 
     88 */
     89 
     90 #include <experimental/__config>
     91 #include <functional>
     92 
     93 #include <algorithm>
     94 #include <type_traits>
     95 #include <vector>
     96 #include <array>
     97 #include <unordered_map>
     98 
     99 #include <__undef_min_max>
    100 
    101 #include <__debug>
    102 
    103 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
    104 #pragma GCC system_header
    105 #endif
    106 
    107 _LIBCPP_BEGIN_NAMESPACE_LFTS
    108 
    109 #if _LIBCPP_STD_VER > 11
    110 // default searcher
    111 template<class _ForwardIterator, class _BinaryPredicate = equal_to<>>
    112 _LIBCPP_TYPE_VIS
    113 class default_searcher {
    114 public:
    115     _LIBCPP_INLINE_VISIBILITY
    116     default_searcher(_ForwardIterator __f, _ForwardIterator __l, 
    117                        _BinaryPredicate __p = _BinaryPredicate())
    118         : __first_(__f), __last_(__l), __pred_(__p) {}
    119 
    120     template <typename _ForwardIterator2>
    121     _LIBCPP_INLINE_VISIBILITY
    122     pair<_ForwardIterator2, _ForwardIterator2>
    123     operator () (_ForwardIterator2 __f, _ForwardIterator2 __l) const
    124     {
    125         return _VSTD::__search(__f, __l, __first_, __last_, __pred_,
    126             typename _VSTD::iterator_traits<_ForwardIterator>::iterator_category(),
    127             typename _VSTD::iterator_traits<_ForwardIterator2>::iterator_category());
    128     }
    129 
    130 private:
    131     _ForwardIterator __first_;
    132     _ForwardIterator __last_;
    133     _BinaryPredicate __pred_;
    134     };
    135 
    136 template<class _ForwardIterator, class _BinaryPredicate = equal_to<>>
    137 _LIBCPP_INLINE_VISIBILITY
    138 default_searcher<_ForwardIterator, _BinaryPredicate>
    139 make_default_searcher( _ForwardIterator __f, _ForwardIterator __l, _BinaryPredicate __p = _BinaryPredicate ())
    140 {
    141     return default_searcher<_ForwardIterator, _BinaryPredicate>(__f, __l, __p);
    142 }
    143 
    144 template<class _Key, class _Value, class _Hash, class _BinaryPredicate, bool /*useArray*/> class _BMSkipTable;
    145 
    146 //  General case for BM data searching; use a map
    147 template<class _Key, typename _Value, class _Hash, class _BinaryPredicate>
    148 class _BMSkipTable<_Key, _Value, _Hash, _BinaryPredicate, false> {
    149 public: // TODO private:
    150     typedef _Value value_type;
    151     typedef _Key   key_type;
    152 
    153     const _Value __default_value_;
    154     std::unordered_map<_Key, _Value, _Hash, _BinaryPredicate> __table;
    155     
    156 public:
    157     _LIBCPP_INLINE_VISIBILITY
    158     _BMSkipTable(std::size_t __sz, _Value __default, _Hash __hf, _BinaryPredicate __pred)
    159         : __default_value_(__default), __table(__sz, __hf, __pred) {}
    160     
    161     _LIBCPP_INLINE_VISIBILITY
    162     void insert(const key_type &__key, value_type __val)
    163     {
    164         __table [__key] = __val;    // Would skip_.insert (val) be better here?
    165     }
    166 
    167     _LIBCPP_INLINE_VISIBILITY
    168     value_type operator [](const key_type & __key) const
    169     {
    170         auto __it = __table.find (__key);
    171         return __it == __table.end() ? __default_value_ : __it->second;
    172     }
    173 };
    174     
    175 
    176 //  Special case small numeric values; use an array
    177 template<class _Key, typename _Value, class _Hash, class _BinaryPredicate>
    178 class _BMSkipTable<_Key, _Value, _Hash, _BinaryPredicate, true> {
    179 private:
    180     typedef _Value value_type;
    181     typedef _Key   key_type;
    182 
    183     typedef typename std::make_unsigned<key_type>::type unsigned_key_type;
    184     typedef std::array<value_type, _VSTD::numeric_limits<unsigned_key_type>::max()> skip_map;
    185     skip_map __table;
    186 
    187 public:
    188     _LIBCPP_INLINE_VISIBILITY
    189     _BMSkipTable(std::size_t /*__sz*/, _Value __default, _Hash /*__hf*/, _BinaryPredicate /*__pred*/)
    190     {
    191         std::fill_n(__table.begin(), __table.size(), __default);
    192     }
    193     
    194     _LIBCPP_INLINE_VISIBILITY
    195     void insert(key_type __key, value_type __val)
    196     {
    197         __table[static_cast<unsigned_key_type>(__key)] = __val;
    198     }
    199 
    200     _LIBCPP_INLINE_VISIBILITY
    201     value_type operator [](key_type __key) const
    202     {
    203         return __table[static_cast<unsigned_key_type>(__key)];
    204     }
    205 };
    206 
    207 
    208 template <class _RandomAccessIterator1, 
    209           class _Hash = hash<typename iterator_traits<_RandomAccessIterator1>::value_type>, 
    210           class _BinaryPredicate = equal_to<>>
    211 _LIBCPP_TYPE_VIS
    212 class boyer_moore_searcher {
    213 private:
    214     typedef typename std::iterator_traits<_RandomAccessIterator1>::difference_type difference_type;
    215     typedef typename std::iterator_traits<_RandomAccessIterator1>::value_type      value_type;
    216     typedef _BMSkipTable<value_type, difference_type, _Hash, _BinaryPredicate,
    217                     _VSTD::is_integral<value_type>::value && // what about enums?
    218                     sizeof(value_type) == 1 &&
    219                     is_same<_Hash, hash<value_type>>::value &&
    220                     is_same<_BinaryPredicate, equal_to<>>::value
    221             > skip_table_type;
    222     
    223 public:
    224     boyer_moore_searcher(_RandomAccessIterator1 __f, _RandomAccessIterator1 __l, 
    225                 _Hash __hf = _Hash(), _BinaryPredicate __pred = _BinaryPredicate())
    226             : __first_(__f), __last_(__l), __pred_(__pred),
    227               __pattern_length_(_VSTD::distance(__first_, __last_)),
    228               __skip_{make_shared<skip_table_type>(__pattern_length_, -1, __hf, __pred_)},
    229               __suffix_{make_shared<vector<difference_type>>(__pattern_length_ + 1)}
    230         {
    231     //  build the skip table
    232         for ( difference_type __i = 0; __f != __l; ++__f, (void) ++__i )
    233             __skip_->insert(*__f, __i);
    234 
    235         this->__build_suffix_table ( __first_, __last_, __pred_ );
    236         }
    237         
    238     template <typename _RandomAccessIterator2>
    239     pair<_RandomAccessIterator2, _RandomAccessIterator2>
    240     operator ()(_RandomAccessIterator2 __f, _RandomAccessIterator2 __l) const
    241     {
    242         static_assert ( std::is_same<
    243                 typename std::decay<typename std::iterator_traits<_RandomAccessIterator1>::value_type>::type, 
    244                 typename std::decay<typename std::iterator_traits<_RandomAccessIterator2>::value_type>::type
    245                     >::value,
    246                 "Corpus and Pattern iterators must point to the same type" );
    247 
    248         if (__f      == __l )    return make_pair(__l, __l); // empty corpus
    249         if (__first_ == __last_) return make_pair(__f, __f); // empty pattern
    250 
    251     //  If the pattern is larger than the corpus, we can't find it!
    252         if ( __pattern_length_ > _VSTD::distance (__f, __l)) 
    253             return make_pair(__l, __l);
    254 
    255     //  Do the search 
    256         return this->__search(__f, __l);
    257     }
    258         
    259 public: // TODO private:
    260     _RandomAccessIterator1               __first_;
    261     _RandomAccessIterator1               __last_;
    262     _BinaryPredicate                     __pred_;
    263     difference_type                      __pattern_length_;
    264     shared_ptr<skip_table_type>          __skip_;
    265     shared_ptr<vector<difference_type>>  __suffix_;
    266 
    267     template <typename _RandomAccessIterator2>
    268     pair<_RandomAccessIterator2, _RandomAccessIterator2>
    269     __search(_RandomAccessIterator2 __f, _RandomAccessIterator2 __l) const
    270     {
    271         _RandomAccessIterator2 __cur = __f;
    272         const _RandomAccessIterator2 __last = __l - __pattern_length_;
    273         const skip_table_type &         __skip   = *__skip_.get();
    274         const vector<difference_type> & __suffix = *__suffix_.get();
    275         
    276         while (__cur <= __last)
    277         {
    278 
    279         //  Do we match right where we are?
    280             difference_type __j = __pattern_length_;
    281             while (__pred_(__first_ [__j-1], __cur [__j-1])) {
    282                 __j--;
    283             //  We matched - we're done!
    284                 if ( __j == 0 )
    285                     return make_pair(__cur, __cur + __pattern_length_);
    286                 }
    287             
    288         //  Since we didn't match, figure out how far to skip forward
    289             difference_type __k = __skip[__cur [ __j - 1 ]];
    290             difference_type __m = __j - __k - 1;
    291             if (__k < __j && __m > __suffix[ __j ])
    292                 __cur += __m;
    293             else
    294                 __cur += __suffix[ __j ];
    295         }
    296     
    297         return make_pair(__l, __l);     // We didn't find anything
    298     }
    299 
    300 
    301     template<typename _Iterator, typename _Container>
    302     void __compute_bm_prefix ( _Iterator __f, _Iterator __l, _BinaryPredicate __pred, _Container &__prefix )
    303     {
    304         const std::size_t __count = _VSTD::distance(__f, __l);
    305                         
    306         __prefix[0] = 0;
    307         std::size_t __k = 0;
    308         for ( std::size_t __i = 1; __i < __count; ++__i )
    309         {
    310             while ( __k > 0 && !__pred ( __f[__k], __f[__i] ))
    311                 __k = __prefix [ __k - 1 ];
    312                 
    313             if ( __pred ( __f[__k], __f[__i] ))
    314                 __k++;
    315             __prefix [ __i ] = __k;
    316         }
    317     }
    318 
    319     void __build_suffix_table(_RandomAccessIterator1 __f, _RandomAccessIterator1 __l, 
    320                                                     _BinaryPredicate __pred)
    321     {
    322         const std::size_t __count = _VSTD::distance(__f, __l);
    323         vector<difference_type> & __suffix = *__suffix_.get();
    324         if (__count > 0)
    325         {
    326             _VSTD::vector<value_type> __scratch(__count);
    327             
    328             __compute_bm_prefix(__f, __l, __pred, __scratch);
    329             for ( std::size_t __i = 0; __i <= __count; __i++ )
    330                 __suffix[__i] = __count - __scratch[__count-1];
    331     
    332             typedef _VSTD::reverse_iterator<_RandomAccessIterator1> _RevIter;
    333             __compute_bm_prefix(_RevIter(__l), _RevIter(__f), __pred, __scratch);
    334      
    335             for ( std::size_t __i = 0; __i < __count; __i++ )
    336             {
    337                 const std::size_t     __j = __count - __scratch[__i];
    338                 const difference_type __k = __i     - __scratch[__i] + 1;
    339      
    340                 if (__suffix[__j] > __k)
    341                     __suffix[__j] = __k;
    342             }
    343         }
    344     }
    345 
    346 };
    347 
    348 template<class _RandomAccessIterator, 
    349          class _Hash = hash<typename iterator_traits<_RandomAccessIterator>::value_type>, 
    350          class _BinaryPredicate = equal_to<>>
    351 _LIBCPP_INLINE_VISIBILITY
    352 boyer_moore_searcher<_RandomAccessIterator, _Hash, _BinaryPredicate>
    353 make_boyer_moore_searcher( _RandomAccessIterator __f, _RandomAccessIterator __l, 
    354                     _Hash __hf = _Hash(), _BinaryPredicate __p = _BinaryPredicate ())
    355 {
    356     return boyer_moore_searcher<_RandomAccessIterator, _Hash, _BinaryPredicate>(__f, __l, __hf, __p);
    357 }
    358 
    359 // boyer-moore-horspool
    360 template <class _RandomAccessIterator1, 
    361           class _Hash = hash<typename iterator_traits<_RandomAccessIterator1>::value_type>, 
    362           class _BinaryPredicate = equal_to<>>
    363 _LIBCPP_TYPE_VIS
    364 class boyer_moore_horspool_searcher {
    365 private:
    366     typedef typename std::iterator_traits<_RandomAccessIterator1>::difference_type difference_type;
    367     typedef typename std::iterator_traits<_RandomAccessIterator1>::value_type      value_type;
    368     typedef _BMSkipTable<value_type, difference_type, _Hash, _BinaryPredicate,
    369                     _VSTD::is_integral<value_type>::value && // what about enums?
    370                     sizeof(value_type) == 1 &&
    371                     is_same<_Hash, hash<value_type>>::value &&
    372                     is_same<_BinaryPredicate, equal_to<>>::value
    373             > skip_table_type;
    374 
    375 public:
    376     boyer_moore_horspool_searcher(_RandomAccessIterator1 __f, _RandomAccessIterator1 __l, 
    377                 _Hash __hf = _Hash(), _BinaryPredicate __pred = _BinaryPredicate())
    378             : __first_(__f), __last_(__l), __pred_(__pred),
    379               __pattern_length_(_VSTD::distance(__first_, __last_)),
    380               __skip_{_VSTD::make_shared<skip_table_type>(__pattern_length_, __pattern_length_, __hf, __pred_)}
    381         {
    382     //  build the skip table
    383             if ( __f != __l )
    384             {
    385                 __l = __l - 1;
    386                 for ( difference_type __i = 0; __f != __l; ++__f, (void) ++__i )
    387                     __skip_->insert(*__f, __pattern_length_ - 1 - __i);
    388             }
    389         }
    390             
    391     template <typename _RandomAccessIterator2>
    392     pair<_RandomAccessIterator2, _RandomAccessIterator2>
    393     operator ()(_RandomAccessIterator2 __f, _RandomAccessIterator2 __l) const
    394     {
    395         static_assert ( std::is_same<
    396                 typename std::decay<typename std::iterator_traits<_RandomAccessIterator1>::value_type>::type, 
    397                 typename std::decay<typename std::iterator_traits<_RandomAccessIterator2>::value_type>::type
    398                     >::value,
    399                 "Corpus and Pattern iterators must point to the same type" );
    400 
    401         if (__f      == __l )    return make_pair(__l, __l); // empty corpus
    402         if (__first_ == __last_) return make_pair(__f, __f); // empty pattern
    403 
    404     //  If the pattern is larger than the corpus, we can't find it!
    405         if ( __pattern_length_ > _VSTD::distance (__f, __l)) 
    406             return make_pair(__l, __l);
    407 
    408     //  Do the search 
    409         return this->__search(__f, __l);
    410     }
    411         
    412 private:
    413     _RandomAccessIterator1      __first_;
    414     _RandomAccessIterator1      __last_;
    415     _BinaryPredicate            __pred_;
    416     difference_type             __pattern_length_;
    417     shared_ptr<skip_table_type> __skip_;
    418 
    419     template <typename _RandomAccessIterator2>
    420     pair<_RandomAccessIterator2, _RandomAccessIterator2>
    421     __search ( _RandomAccessIterator2 __f, _RandomAccessIterator2 __l ) const {
    422         _RandomAccessIterator2 __cur = __f;
    423         const _RandomAccessIterator2 __last = __l - __pattern_length_;
    424         const skip_table_type & __skip = *__skip_.get();
    425 
    426         while (__cur <= __last)
    427         {
    428         //  Do we match right where we are?
    429             difference_type __j = __pattern_length_;
    430             while (__pred_(__first_[__j-1], __cur[__j-1]))
    431             {
    432                 __j--;
    433             //  We matched - we're done!
    434                 if ( __j == 0 )
    435                     return make_pair(__cur, __cur + __pattern_length_);
    436             }
    437             __cur += __skip[__cur[__pattern_length_-1]];
    438         }
    439         
    440         return make_pair(__l, __l);
    441     }
    442 };
    443 
    444 template<class _RandomAccessIterator, 
    445          class _Hash = hash<typename iterator_traits<_RandomAccessIterator>::value_type>, 
    446          class _BinaryPredicate = equal_to<>>
    447 _LIBCPP_INLINE_VISIBILITY
    448 boyer_moore_horspool_searcher<_RandomAccessIterator, _Hash, _BinaryPredicate>
    449 make_boyer_moore_horspool_searcher( _RandomAccessIterator __f, _RandomAccessIterator __l, 
    450                     _Hash __hf = _Hash(), _BinaryPredicate __p = _BinaryPredicate ())
    451 {
    452     return boyer_moore_horspool_searcher<_RandomAccessIterator, _Hash, _BinaryPredicate>(__f, __l, __hf, __p);
    453 }
    454 
    455 #endif // _LIBCPP_STD_VER > 11
    456 
    457 _LIBCPP_END_NAMESPACE_LFTS
    458 
    459 #endif /* _LIBCPP_EXPERIMENTAL_FUNCTIONAL */
    460