LCOV - code coverage report
Current view: top level - lts/source - tree_set.cpp (source / functions) Hit Total Coverage
Test: mcrl2_coverage.info.cleaned Lines: 86 104 82.7 %
Date: 2024-04-19 03:43:27 Functions: 13 14 92.9 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : // Author(s): Bas Ploeger
       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 tree_set.cpp
      10             : 
      11             : #include "mcrl2/utilities/detail/memory_utility.h"
      12             : #include "mcrl2/utilities/logger.h"
      13             : #include "mcrl2/lts/detail/tree_set.h"
      14             : #include "mcrl2/utilities/exception.h"
      15             : 
      16             : #define EMPTY_SET (-1)
      17             : #define EMPTY_LIST (-1)
      18             : #define EMPTY_TAG (-1)
      19             : #define HASH_CLASS 16
      20             : #define TAGS_BLOCK 15000
      21             : #define BUCKETS_BLOCK 25000
      22             : // simple hash function; uses two large primes
      23             : #define hash(l,r,m) (36425657*l + 77673689*r) & m
      24             : 
      25             : namespace mcrl2
      26             : {
      27             : namespace lts
      28             : {
      29             : 
      30          75 : tree_set_store::tree_set_store()
      31             : {
      32          75 :   buckets = nullptr;
      33          75 :   buckets_size = 0;
      34          75 :   buckets_next = 0;
      35             : 
      36          75 :   tags = nullptr;
      37          75 :   tags_size = 0;
      38          75 :   tags_next = 0;
      39             : 
      40          75 :   hashmask = (1 << HASH_CLASS) - 1;
      41          75 :   hashtable = (ptrdiff_t*)malloc((hashmask+1)*sizeof(ptrdiff_t));
      42          75 :   if (hashtable == nullptr)
      43             :   {
      44           0 :     throw mcrl2::runtime_error("Out of memory.");
      45             :   }
      46     4915275 :   for (ptrdiff_t i=0; i<=hashmask; ++i)
      47             :   {
      48     4915200 :     hashtable[i] = EMPTY_LIST;
      49             :   }
      50          75 : }
      51             : 
      52          75 : tree_set_store::~tree_set_store()
      53             : {
      54          75 :   if (tags != nullptr)
      55             :   {
      56          75 :     free(tags);
      57          75 :     tags = nullptr;
      58             :   }
      59          75 :   if (buckets != nullptr)
      60             :   {
      61          75 :     free(buckets);
      62          75 :     buckets = nullptr;
      63             :   }
      64          75 :   free(hashtable);
      65          75 :   hashtable = nullptr;
      66          75 : }
      67             : 
      68         372 : void tree_set_store::check_tags()
      69             : {
      70         372 :   if (tags_next >= tags_size)
      71             :   {
      72          75 :     tags_size += TAGS_BLOCK;
      73          75 :     tags = (ptrdiff_t*)realloc(tags,tags_size*sizeof(ptrdiff_t));
      74          75 :     if (tags == nullptr)
      75             :     {
      76           0 :       throw mcrl2::runtime_error("Out of memory.");
      77             :     }
      78             :   }
      79         372 : }
      80             : 
      81         515 : void tree_set_store::check_buckets()
      82             : {
      83         515 :   if (buckets_next >= buckets_size)
      84             :   {
      85          75 :     buckets_size += BUCKETS_BLOCK;
      86          75 :     buckets = (bucket*)realloc(buckets,buckets_size*sizeof(bucket));
      87          75 :     if (buckets == nullptr)
      88             :     {
      89           0 :       throw mcrl2::runtime_error("Out of memory.");
      90             :     }
      91             :   }
      92         515 :   if (buckets_next*4 >= hashmask*3)
      93             :   {
      94           0 :     hashmask = hashmask + hashmask + 1;
      95           0 :     hashtable = (ptrdiff_t*)realloc(hashtable,(hashmask+1)*sizeof(ptrdiff_t));
      96           0 :     if (hashtable == nullptr)
      97             :     {
      98           0 :       throw mcrl2::runtime_error("Out of memory.");
      99             :     }
     100             :     ptrdiff_t i,hc;
     101           0 :     for (i=0; i<=hashmask; ++i)
     102             :     {
     103           0 :       hashtable[i] = EMPTY_LIST;
     104             :     }
     105           0 :     for (i=0; i<buckets_next; ++i)
     106             :     {
     107           0 :       hc = hash(buckets[i].child_l,buckets[i].child_r,hashmask);
     108           0 :       buckets[i].next = hashtable[hc];
     109           0 :       hashtable[hc] = i;
     110             :     }
     111             :   }
     112         515 : }
     113             : 
     114         515 : ptrdiff_t tree_set_store::build_set(ptrdiff_t child_l,ptrdiff_t child_r)
     115             : {
     116         515 :   check_buckets();
     117         515 :   ptrdiff_t hc = hash(child_l,child_r,hashmask);
     118         515 :   buckets[buckets_next].child_l = child_l;
     119         515 :   buckets[buckets_next].child_r = child_r;
     120         515 :   buckets[buckets_next].tag     = EMPTY_TAG;
     121         515 :   buckets[buckets_next].next    = hashtable[hc];
     122         515 :   hashtable[hc] = buckets_next;
     123         515 :   return buckets_next++;
     124             : }
     125             : 
     126         749 : ptrdiff_t tree_set_store::find_set(ptrdiff_t child_l,ptrdiff_t child_r)
     127             : {
     128         749 :   ptrdiff_t hc = hash(child_l,child_r,hashmask);
     129         749 :   for (ptrdiff_t i=hashtable[hc]; i!=EMPTY_LIST; i=buckets[i].next)
     130             :   {
     131         234 :     if (buckets[i].child_l==child_l && buckets[i].child_r==child_r)
     132             :     {
     133         234 :       return i;
     134             :     }
     135             :   }
     136         515 :   return build_set(child_l,child_r);
     137             : }
     138             : 
     139        1966 : ptrdiff_t tree_set_store::create_set(std::vector<ptrdiff_t> &elems)
     140             : {
     141        1966 :   if (elems.size() == 0)
     142             :   {
     143        1421 :     return EMPTY_SET;
     144             :   }
     145             : 
     146         545 :   ptrdiff_t* nodes = MCRL2_SPECIFIC_STACK_ALLOCATOR(ptrdiff_t,elems.size());
     147         545 :   std::size_t node_size = 0;
     148             :   std::size_t i,j;
     149        1192 :   for (i=0; i < elems.size(); ++i)
     150             :   {
     151         647 :     nodes[i]=find_set(elems[i],EMPTY_SET);
     152             :   }
     153         545 :   node_size = i;
     154         647 :   while (node_size > 1)
     155             :   {
     156         102 :     j = 0;
     157         216 :     for (i=0; i<node_size; i+=2)
     158             :     {
     159         114 :       if (i == node_size-1)
     160             :       {
     161          12 :         nodes[j] = nodes[i];
     162             :       }
     163             :       else
     164             :       {
     165         102 :         nodes[j] = find_set(nodes[i],nodes[i+1]);
     166             :       }
     167         114 :       ++j;
     168             :     }
     169         102 :     node_size = j;
     170             :   }
     171         545 :   ptrdiff_t r = nodes[0];
     172         545 :   return r;
     173             : }
     174             : 
     175         447 : ptrdiff_t tree_set_store::get_next_tag()
     176             : {
     177         447 :   return tags_next;
     178             : }
     179             : 
     180         372 : ptrdiff_t tree_set_store::get_set(ptrdiff_t tag)
     181             : {
     182         372 :   return tags[tag];
     183             : }
     184             : 
     185         558 : ptrdiff_t tree_set_store::get_set_child_left(ptrdiff_t set)
     186             : {
     187         558 :   return buckets[set].child_l;
     188             : }
     189             : 
     190         651 : ptrdiff_t tree_set_store::get_set_child_right(ptrdiff_t set)
     191             : {
     192         651 :   return buckets[set].child_r;
     193             : }
     194             : 
     195           0 : ptrdiff_t tree_set_store::get_set_size(ptrdiff_t set)
     196             : {
     197           0 :   if (buckets[set].child_r == EMPTY_SET)
     198             :   {
     199           0 :     return 1;
     200             :   }
     201           0 :   return get_set_size(buckets[set].child_l) +
     202           0 :          get_set_size(buckets[set].child_r);
     203             : }
     204             : 
     205        3007 : bool tree_set_store::is_set_empty(ptrdiff_t set)
     206             : {
     207        3007 :   return (set == EMPTY_SET);
     208             : }
     209             : 
     210         545 : ptrdiff_t tree_set_store::set_set_tag(ptrdiff_t set)
     211             : {
     212         545 :   if (buckets[set].tag != EMPTY_TAG)
     213             :   {
     214         173 :     return buckets[set].tag;
     215             :   }
     216         372 :   check_tags();
     217         372 :   tags[tags_next] = set;
     218         372 :   buckets[set].tag = tags_next;
     219         372 :   return tags_next++;
     220             : }
     221             : 
     222             : }
     223             : }

Generated by: LCOV version 1.14