LCOV - code coverage report
Current view: top level - atermpp/include/mcrl2/atermpp - algorithm.h (source / functions) Hit Total Coverage
Test: mcrl2_coverage.info.cleaned Lines: 77 83 92.8 %
Date: 2024-04-19 03:43:27 Functions: 59 63 93.7 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : // Author(s): Wieger Wesselink
       2             : // Copyright: see the accompanying file COPYING or copy at
       3             : // https://github.com/mCRL2org/mCRL2/blob/master/COPYING
       4             : //
       5             : // Distributed under the Boost Software License, Version 1.0.
       6             : // (See accompanying file LICENSE_1_0.txt or copy at
       7             : // http://www.boost.org/LICENSE_1_0.txt)
       8             : //
       9             : /// \file mcrl2/atermpp/algorithm.h
      10             : /// \brief Algorithms for ATerms.
      11             : 
      12             : #ifndef MCRL2_ATERMPP_ALGORITHM_H
      13             : #define MCRL2_ATERMPP_ALGORITHM_H
      14             : 
      15             : #include <unordered_map>
      16             : 
      17             : #include "mcrl2/atermpp/builder.h"
      18             : #include "mcrl2/atermpp/detail/algorithm_impl.h"
      19             : 
      20             : namespace atermpp
      21             : {
      22             : 
      23             : namespace detail
      24             : {
      25             : 
      26             : template <template <class> class Builder, class ReplaceFunction>
      27             : struct replace_aterm_builder: public Builder<replace_aterm_builder<Builder, ReplaceFunction> >
      28             : {
      29             :   typedef Builder<replace_aterm_builder<Builder, ReplaceFunction> > super;
      30             :   using super::enter;
      31             :   using super::leave;
      32             :   using super::apply;
      33             :   using super::derived;
      34             : 
      35             :   ReplaceFunction f;
      36             : 
      37           9 :   replace_aterm_builder(ReplaceFunction f_)
      38           5 :     : f(f_)
      39           9 :   {}
      40             : 
      41             :   template <class T>
      42          18 :   void apply(T& result, const aterm_appl& x)
      43             :   {
      44          18 :     const T fx(f(x));
      45          18 :     if (x == fx) 
      46             :     {
      47          10 :       super::apply(result, x); 
      48             :     }
      49             :     else 
      50             :     {
      51           8 :       result = fx;
      52             :     }
      53          18 :   }
      54             : };
      55             : 
      56             : template <template <class> class Builder, class ReplaceFunction>
      57             : replace_aterm_builder<Builder, ReplaceFunction>
      58           9 : make_replace_aterm_builder(ReplaceFunction f)
      59             : {
      60           9 :   return replace_aterm_builder<Builder, ReplaceFunction>(f);
      61             : }
      62             : 
      63             : template <template <class> class Builder, class ReplaceFunction>
      64             : struct partial_replace_aterm_builder: public Builder<partial_replace_aterm_builder<Builder, ReplaceFunction> >
      65             : {
      66             :   typedef Builder<partial_replace_aterm_builder<Builder, ReplaceFunction> > super;
      67             :   using super::enter;
      68             :   using super::leave;
      69             :   using super::apply;
      70             :   using super::derived;
      71             : 
      72             :   ReplaceFunction f;
      73             : 
      74           1 :   partial_replace_aterm_builder(ReplaceFunction f_)
      75             :     : f(f_)
      76           1 :   {}
      77             : 
      78             :   template <class T>
      79           1 :   void apply(T& result, const aterm_appl& x)
      80             :   {
      81           1 :     std::pair<aterm_appl, bool> p = f(x);
      82           1 :     if (p.second)
      83             :     { 
      84           0 :       super::apply(result, x);
      85             :     } 
      86             :     else 
      87             :     {
      88           1 :       result = p.first;
      89             :     }
      90           1 :   }
      91             : };
      92             : 
      93             : template <template <class> class Builder, class ReplaceFunction>
      94             : partial_replace_aterm_builder<Builder, ReplaceFunction>
      95           1 : make_partial_replace_aterm_builder(ReplaceFunction f)
      96             : {
      97           1 :   return partial_replace_aterm_builder<Builder, ReplaceFunction>(f);
      98             : }
      99             : 
     100             : template <template <class> class Builder, class ReplaceFunction>
     101             : struct bottom_up_replace_aterm_builder: public Builder<bottom_up_replace_aterm_builder<Builder, ReplaceFunction> >
     102             : {
     103             :   typedef Builder<bottom_up_replace_aterm_builder<Builder, ReplaceFunction> > super;
     104             :   using super::enter;
     105             :   using super::leave;
     106             :   using super::apply;
     107             :   using super::derived;
     108             : 
     109             :   ReplaceFunction f;
     110             : 
     111       20010 :   bottom_up_replace_aterm_builder(ReplaceFunction f_)
     112       20009 :     : f(f_)
     113       20010 :   {}
     114             : 
     115             :   template <class T>
     116      423463 :   void apply(T& result, const aterm_appl& x)
     117             :   {
     118      423463 :     aterm_appl t;
     119      423463 :     super::apply(t, x);
     120      423463 :     result = static_cast<T>(f(t));
     121      423463 :   }
     122             : };
     123             : 
     124             : template <template <class> class Builder, class ReplaceFunction>
     125             : bottom_up_replace_aterm_builder<Builder, ReplaceFunction>
     126       20010 : make_bottom_up_replace_aterm_builder(ReplaceFunction f)
     127             : {
     128       20010 :   return bottom_up_replace_aterm_builder<Builder, ReplaceFunction>(f);
     129             : }
     130             : 
     131             : template <template <class> class Builder, class ReplaceFunction>
     132             : struct cached_bottom_up_replace_aterm_builder: public Builder<cached_bottom_up_replace_aterm_builder<Builder, ReplaceFunction> >
     133             : {
     134             :   typedef Builder<cached_bottom_up_replace_aterm_builder<Builder, ReplaceFunction> > super;
     135             :   using super::enter;
     136             :   using super::leave;
     137             :   using super::apply;
     138             :   using super::derived;
     139             : 
     140             :   ReplaceFunction f;
     141             :   std::unordered_map<aterm_appl, aterm>& cache;
     142             : 
     143           1 :   cached_bottom_up_replace_aterm_builder(ReplaceFunction f_, std::unordered_map<aterm_appl, aterm>& cache_)
     144           1 :     : f(f_), cache(cache_)
     145           1 :   {}
     146             : 
     147             :   template <class T>
     148           6 :   void apply(T& result, const aterm_appl& x)
     149             :   {
     150           6 :     auto i = cache.find(x);
     151           6 :     if (i != cache.end())
     152             :     {
     153           2 :       result = i->second;
     154           2 :       return;
     155             :     }
     156           4 :     aterm t;
     157           4 :     super::apply(t, x);
     158           4 :     result = f(down_cast<aterm_appl>(t));
     159           4 :     cache[x] = result;
     160           4 :   }
     161             : };
     162             : 
     163             : template <template <class> class Builder, class ReplaceFunction>
     164             : cached_bottom_up_replace_aterm_builder<Builder, ReplaceFunction>
     165           1 : make_cached_bottom_up_replace_aterm_builder(ReplaceFunction f, std::unordered_map<aterm_appl, aterm>& cache)
     166             : {
     167           1 :   return cached_bottom_up_replace_aterm_builder<Builder, ReplaceFunction>(f, cache);
     168             : }
     169             : 
     170             : } // namespace detail
     171             : 
     172             : /// \brief Calls op(elem) for subterms of the term t.
     173             : /// \param t A term
     174             : /// \param op The operation that is applied to subterms
     175             : /// \return a copy of the (internally modified) op.
     176             : /// The function op must have the signature bool op(aterm_appl t).
     177             : /// When op(t) is false, the children of t are skipped.
     178             : template <typename UnaryFunction, typename Term>
     179           1 : UnaryFunction for_each(Term t, UnaryFunction op)
     180             : {
     181           1 :   return detail::for_each_impl< typename std::add_lvalue_reference< UnaryFunction >::type >(t, op);
     182             : }
     183             : 
     184             : /// \brief Finds a subterm of t that matches a given predicate.
     185             : /// \param t A term
     186             : /// \param match The predicate that determines if a subterm is a match
     187             : /// \return A subterm that matches the given predicate, or aterm_appl() if none was found.
     188             : template <typename Term, typename MatchPredicate>
     189        1845 : aterm_appl find_if(const Term& t, MatchPredicate match)
     190             : {
     191        1845 :   aterm_appl output;
     192        1845 :   detail::find_if_impl< typename std::add_lvalue_reference< MatchPredicate >::type >(t, match, output);
     193        1845 :   return output;
     194           0 : }
     195             : 
     196             : /// \brief Finds a subterm of t that matches a given predicate.
     197             : /// The term is only partially traversed. If the stop predicate
     198             : /// returns true in a subterm, the recursion is not continued.
     199             : /// \param t A term
     200             : /// \param match The predicate that determines if a subterm is a match
     201             : /// \param stop The predicate that determines if the recursion should not be continued in a subterm
     202             : /// \return A subterm that matches the given predicate, or aterm_appl() if none was found.
     203             : template <typename Term, typename MatchPredicate, typename StopPredicate>
     204           2 : aterm_appl partial_find_if(Term t, MatchPredicate match, StopPredicate stop)
     205             : {
     206           2 :   return detail::partial_find_if_impl<typename std::add_lvalue_reference<MatchPredicate>::type>(t, match, stop);
     207             : }
     208             : 
     209             : /// \brief Finds all subterms of t that match a given predicate, and writes the found terms
     210             : /// to the destination range starting with destBegin.
     211             : /// \param t A term
     212             : /// \param match The predicate that determines if a subterm is a match
     213             : /// \param destBegin The iterator range to which output is written.
     214             : template <typename Term, typename MatchPredicate, typename OutputIterator>
     215           2 : void find_all_if(const Term& t, MatchPredicate match, OutputIterator destBegin)
     216             : {
     217           2 :   OutputIterator i = destBegin; // we make a copy, since a reference to an iterator is needed
     218           2 :   detail::find_all_if_impl< typename std::add_lvalue_reference< MatchPredicate >::type >(t, match, i);
     219           2 : }
     220             : 
     221             : /// \brief Finds all subterms of t that match a given predicate, and writes the found terms
     222             : /// to the destination range starting with destBegin.
     223             : /// The term is only partially traversed. If the stop predicate
     224             : /// returns true in a subterm, the recursion is not continued.
     225             : /// \param t A term
     226             : /// \param match The predicate that determines if a subterm is a match
     227             : /// \param stop The predicate that determines if the recursion should not be continued in a subterm
     228             : /// \param destBegin The iterator range to which output is written.
     229             : template <typename Term, typename MatchPredicate, typename StopPredicate, typename OutputIterator>
     230             : void partial_find_all_if(Term t, MatchPredicate match, StopPredicate stop, OutputIterator destBegin)
     231             : {
     232             :   OutputIterator i = destBegin; // we make a copy, since a reference to an iterator is needed
     233             :   detail::partial_find_all_if_impl< typename std::add_lvalue_reference< MatchPredicate >::type,
     234             :          typename std::add_lvalue_reference< StopPredicate >::type >(t, match, stop, i);
     235             : }
     236             : 
     237             : /// \brief Replaces each subterm x of t by r(x). The ReplaceFunction r has
     238             : /// the following signature:
     239             : /// aterm_appl x;
     240             : /// aterm_appl result = r(x);
     241             : /// The replacements are performed in top down order.
     242             : /// \param t A term
     243             : /// \param r The replace function that is applied to subterms.
     244             : /// \return The result of the replacement.
     245             : template <typename Term, typename ReplaceFunction>
     246           9 : Term replace(const Term& t, ReplaceFunction r)
     247             : {
     248           9 :   Term result;
     249           9 :   detail::make_replace_aterm_builder<atermpp::builder>(r).apply(result,t);
     250           9 :   return result;
     251           0 : }
     252             : 
     253             : /// \brief Replaces each subterm in t that is equal to old_value with new_value.
     254             : /// The replacements are performed in top down order. For example,
     255             : /// replace(f(f(x)), f(x), x) returns f(x) and not x.
     256             : /// \param t A term
     257             : /// \param old_value The subterm that will be replaced.
     258             : /// \param new_value The value that will be substituted.
     259             : /// \return The result of the replacement.
     260             : template <typename Term>
     261           5 : Term replace(const Term& t, const aterm& old_value, const aterm& new_value)
     262             : {
     263          10 :   return replace(t, [&](const aterm& t) { return t == old_value ? new_value : t; });
     264             : }
     265             : 
     266             : /// \brief Replaces each subterm x of t by r(x). The ReplaceFunction r has
     267             : /// the following signature:
     268             : /// aterm_appl x;
     269             : /// aterm_appl result = r(x);
     270             : /// The replacements are performed in bottom up order. For example,
     271             : /// replace(f(f(x)), f(x), x) returns x.
     272             : /// \param t A term
     273             : /// \param r The replace function that is applied to subterms.
     274             : /// \return The result of the replacement.
     275             : template <typename Term, typename ReplaceFunction>
     276       20010 : Term bottom_up_replace(Term t, ReplaceFunction r)
     277             : {
     278       20010 :   Term result;
     279       20010 :   detail::make_bottom_up_replace_aterm_builder<atermpp::builder>(r).apply(result, t);
     280       20010 :   return result;
     281           0 : }
     282             : 
     283             : /// \brief Replaces each subterm in t that is equal to old_value with new_value.
     284             : /// The replacements are performed in top down order. For example,
     285             : /// replace(f(f(x)), f(x), x) returns f(x) and not x.
     286             : /// \param t A term
     287             : /// \param old_value The value of the subterm that is replaced.
     288             : /// \param new_value The value that is substituted.
     289             : /// \return The result of the replacement.
     290             : template <typename Term>
     291           1 : Term bottom_up_replace(Term t, const aterm_appl& old_value, const aterm_appl& new_value)
     292             : {
     293           4 :   return bottom_up_replace(t, [&](const aterm& t) { return t == old_value ? new_value : t; });
     294             : }
     295             : 
     296             : /// \brief Replaces subterms x of t by r(x). The replace function r returns an
     297             : /// additional boolean value. This value is used to prevent further recursion.
     298             : /// The ReplaceFunction r has the following signature:
     299             : /// aterm_appl x;
     300             : /// std::pair<aterm_appl, bool> result = r(x);
     301             : /// result.first  is the result r(x) of the replacement
     302             : /// result.second denotes if the recursion should be continued
     303             : /// The replacements are performed in top down order.
     304             : /// \param t A term
     305             : /// \param r The replace function that is applied to subterms.
     306             : /// \return The result of the replacement.
     307             : template <typename Term, typename ReplaceFunction>
     308           1 : Term partial_replace(Term t, ReplaceFunction r)
     309             : {
     310           1 :   Term result;
     311           1 :   detail::make_partial_replace_aterm_builder<atermpp::builder>(r).apply(result, t);
     312           1 :   return result;
     313           0 : }
     314             : 
     315             : /// \brief Replaces each subterm x of t by r(x). The ReplaceFunction r has
     316             : /// the following signature:
     317             : /// aterm_appl x;
     318             : /// aterm_appl result = r(x);
     319             : /// The replacements are performed in bottom up order. For example,
     320             : /// replace(f(f(x)), f(x), x) returns x.
     321             : /// \param t A term
     322             : /// \param r The replace function that is applied to subterms.
     323             : /// \param cache A cache for the result of aterm_appl terms.
     324             : /// \return The result of the replacement.
     325             : template <typename Term, typename ReplaceFunction>
     326           1 : Term bottom_up_replace(Term t, ReplaceFunction r, std::unordered_map<aterm_appl, aterm>& cache)
     327             : {
     328           1 :   Term result;
     329           1 :   detail::make_cached_bottom_up_replace_aterm_builder<atermpp::builder>(r, cache).apply(result, t);
     330           1 :   return result;
     331           0 : }
     332             : 
     333             : } // namespace atermpp
     334             : 
     335             : #endif // MCRL2_ATERMPP_ALGORITHM_H

Generated by: LCOV version 1.14