LCOV - code coverage report
Current view: top level - symbolic/source - ldd_stream.cpp (source / functions) Hit Total Coverage
Test: mcrl2_coverage.info.cleaned Lines: 63 84 75.0 %
Date: 2024-05-04 03:44:52 Functions: 13 14 92.9 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : // Author(s): Maurice Laveaux
       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             : 
      10             : #ifdef MCRL2_ENABLE_SYLVAN
      11             : 
      12             : #include "mcrl2/symbolic/ldd_stream.h"
      13             : 
      14             : #include "mcrl2/utilities/exception.h"
      15             : 
      16             : #include <stack>
      17             : #include <optional>
      18             : 
      19             : using namespace sylvan::ldds;
      20             : using namespace mcrl2::symbolic;
      21             : 
      22             : /// Iterates over all nodes in the given LDD. The LDDs in nodes will not be traversed.
      23             : struct node_iterator
      24             : {
      25             : public:
      26           2 :   node_iterator(const ldd& U, mcrl2::utilities::indexed_set<sylvan::ldds::ldd>& nodes)
      27           2 :    : m_nodes(nodes)
      28             :   {    
      29           2 :     m_stack.emplace(std::make_pair(U, false));
      30           2 :     this->operator++();
      31           2 :   }
      32             : 
      33           4 :   void operator++()
      34             :   {
      35           6 :     while (!m_stack.empty())
      36             :     {    
      37           4 :       auto& current = m_stack.top();
      38             : 
      39           4 :       if (current.second)
      40             :       {
      41           2 :         m_current = current.first;
      42           2 :         m_stack.pop();
      43           2 :         return; // Top of the stack is the current item.        
      44             :       }
      45             :       else
      46             :       {
      47             :         // Add children and continue.        
      48           2 :         if (m_nodes.find(current.first.down()) == m_nodes.end())
      49             :         {
      50           0 :           m_stack.push(std::make_pair(current.first.down(), false));
      51             :         }
      52           2 :         if (m_nodes.find(current.first.right()) == m_nodes.end())
      53             :         {
      54           0 :           m_stack.push(std::make_pair(current.first.right(), false));
      55             :         }
      56           2 :         current.second = true; // Next time, we can actually process current.
      57             :       }
      58             :     }
      59             : 
      60           2 :     m_current.reset();
      61             :   }
      62             : 
      63           0 :   ldd* operator->()
      64             :   {
      65           0 :     assert(m_current);
      66           0 :     return &m_current.value();
      67             :   }
      68             : 
      69             :   const ldd* operator->() const
      70             :   {
      71             :     assert(m_current);
      72             :     return &m_current.value();
      73             :   }
      74             : 
      75           4 :   ldd& operator*()
      76             :   {
      77           4 :     assert(m_current);
      78           4 :     return m_current.value();
      79             :   }
      80             : 
      81             :   const ldd& operator*() const
      82             :   {
      83             :     assert(m_current);
      84             :     return m_current.value();
      85             :   }
      86             : 
      87           4 :   operator bool() const
      88             :   {
      89           4 :     return m_current.has_value();
      90             :   }
      91             : 
      92             : private:
      93             :   // Traverse the ldd bottom up, where the boolean indicates all children have been returned.
      94             :   std::stack<std::pair<ldd, bool>> m_stack;
      95             :   
      96             :   mcrl2::utilities::indexed_set<sylvan::ldds::ldd>& m_nodes;
      97             : 
      98             :   std::optional<ldd> m_current;
      99             : };
     100             : 
     101             : /// \brief The magic value for a binary LDD format stream.
     102             : static constexpr std::uint16_t BLF_MAGIC = 0x8baf;
     103             : static constexpr std::uint16_t BLF_VERSION = 0x8306;
     104             : 
     105           1 : binary_ldd_ostream::binary_ldd_ostream(std::shared_ptr<mcrl2::utilities::obitstream> stream)
     106           1 :   : m_stream(stream)
     107             : {
     108             :   // Write the header of the binary LDD format.
     109           1 :   m_stream->write_bits(BLF_MAGIC, 16);
     110           1 :   m_stream->write_bits(BLF_VERSION, 16);
     111             : 
     112             :   // Add the true and false constants.
     113           1 :   m_nodes.insert(false_());
     114           1 :   m_nodes.insert(true_());
     115           1 : }
     116             : 
     117           1 : binary_ldd_ostream::binary_ldd_ostream(std::ostream& is)
     118           1 :   : binary_ldd_ostream(std::make_shared<mcrl2::utilities::obitstream>(is))
     119           1 : {}
     120             : 
     121           1 : binary_ldd_ostream::~binary_ldd_ostream()
     122           1 : {}
     123             : 
     124           2 : void binary_ldd_ostream::put(const ldd& U)
     125             : {
     126             :   // Write all children of U.
     127           2 :   node_iterator it(U, m_nodes);
     128             : 
     129           4 :   while (it)
     130             :   {
     131           2 :     const auto& [index, inserted] = m_nodes.insert(*it);
     132           2 :     if (inserted)
     133             :     {
     134             :       // New LDD that must be written to stream.
     135           0 :       m_stream->write_bits(0, 1);
     136           0 :       m_stream->write_integer(it->value());
     137           0 :       m_stream->write_bits(m_nodes.index(it->down()), ldd_index_width());
     138           0 :       m_stream->write_bits(m_nodes.index(it->right()), ldd_index_width());
     139             :     }
     140             : 
     141           2 :     if (*it == U)
     142             :     {       
     143           2 :       m_stream->write_bits(1, 1); // Is output.
     144           2 :       m_stream->write_bits(index, ldd_index_width());
     145             :     }
     146             : 
     147           2 :     ++it;
     148             :   }
     149           2 : }
     150             : 
     151           2 : unsigned int binary_ldd_ostream::ldd_index_width()
     152             : {
     153           2 :   return std::log2(m_nodes.size()) + 1;
     154             : }
     155             : 
     156           1 : binary_ldd_istream::binary_ldd_istream(std::shared_ptr<mcrl2::utilities::ibitstream> stream)
     157           1 :   : m_stream(stream)
     158             : {  
     159             :   // The term with function symbol index 0 indicates the end of the stream.
     160           1 :   m_nodes.emplace_back(false_());
     161           1 :   m_nodes.emplace_back(true_());
     162             : 
     163             :   // Read the binary aterm format header.
     164           1 :   if (m_stream->read_bits(16) != BLF_MAGIC)
     165             :   {
     166           0 :     throw mcrl2::runtime_error("Error while reading: missing the BLF_MAGIC control sequence.");
     167             :   }
     168             : 
     169           1 :   std::size_t version = m_stream->read_bits(16);
     170           1 :   if (version != BLF_VERSION)
     171             :   {
     172           0 :     throw mcrl2::runtime_error("The BLF version (" + std::to_string(version) + ") of the input file is incompatible with the version (" + std::to_string(BLF_VERSION) +
     173           0 :                                ") of this tool. The input file must be regenerated. ");
     174             :   }
     175           1 : }
     176             : 
     177           1 : binary_ldd_istream::binary_ldd_istream(std::istream& is)
     178           1 :   : binary_ldd_istream(std::make_shared<mcrl2::utilities::ibitstream>(is))
     179           1 : {}
     180             : 
     181           2 : ldd binary_ldd_istream::get()
     182             : {
     183             :   while (true)
     184             :   {
     185           2 :     bool is_output = m_stream->read_bits(1);
     186             : 
     187           2 :     if (is_output)
     188             :     {
     189             :       // The output is simply an index of the LDD.
     190           2 :       std::size_t index = m_stream->read_bits(ldd_index_width());
     191           2 :       return m_nodes[index];
     192             :     }
     193             :     else
     194             :     {
     195           0 :       std::size_t value = m_stream->read_integer();
     196           0 :       std::size_t down_index = m_stream->read_bits(ldd_index_width(true));
     197           0 :       std::size_t right_index = m_stream->read_bits(ldd_index_width(true));
     198             : 
     199           0 :       ldd down = m_nodes[down_index];
     200           0 :       ldd right = m_nodes[right_index];
     201             : 
     202           0 :       ldd result = ldd(sylvan::lddmc_makenode(value, down.get(), right.get()));
     203           0 :       m_nodes.emplace_back(result);
     204           0 :     }
     205           0 :   }
     206             : }
     207             : 
     208           2 : unsigned int binary_ldd_istream::ldd_index_width(bool input)
     209             : {
     210           2 :   return std::log2(m_nodes.size() + input) + 1; // Assume that size is one larger to contain the input ldd.
     211             : }
     212             : 
     213             : #endif // MCRL2_ENABLE_SYLVAN

Generated by: LCOV version 1.14