/*++ Copyright (c) 2006 Microsoft Corporation Module Name: dl_table.cpp Abstract: Author: Krystof Hoder (t-khoder) 2010-09-01. Revision History: --*/ #include "muz/base/dl_context.h" #include "muz/base/dl_util.h" #include "muz/rel/dl_table.h" #include "muz/rel/dl_relation_manager.h" namespace datalog { // ----------------------------------- // // hashtable_table // // ----------------------------------- table_base * hashtable_table_plugin::mk_empty(const table_signature & s) { SASSERT(can_handle_signature(s)); return alloc(hashtable_table, *this, s); } class hashtable_table_plugin::join_fn : public convenient_table_join_fn { unsigned m_joined_col_cnt; public: join_fn(const table_signature & t1_sig, const table_signature & t2_sig, unsigned col_cnt, const unsigned * cols1, const unsigned * cols2) : convenient_table_join_fn(t1_sig, t2_sig, col_cnt, cols1, cols2), m_joined_col_cnt(col_cnt) {} table_base * operator()(const table_base & t1, const table_base & t2) override { const hashtable_table & ht1 = static_cast(t1); const hashtable_table & ht2 = static_cast(t2); hashtable_table_plugin & plugin = ht1.get_plugin(); hashtable_table * res = static_cast(plugin.mk_empty(get_result_signature())); hashtable_table::storage::iterator els1it = ht1.m_data.begin(); hashtable_table::storage::iterator els1end = ht1.m_data.end(); hashtable_table::storage::iterator els2end = ht2.m_data.end(); table_fact acc; for(; els1it!=els1end; ++els1it) { const table_fact & row1 = *els1it; hashtable_table::storage::iterator els2it = ht2.m_data.begin(); for(; els2it!=els2end; ++els2it) { const table_fact & row2 = *els2it; bool match=true; for(unsigned i=0; im_data.insert(acc); } } return res; } }; table_join_fn * hashtable_table_plugin::mk_join_fn(const table_base & t1, const table_base & t2, unsigned col_cnt, const unsigned * cols1, const unsigned * cols2) { if(t1.get_kind()!=get_kind() || t2.get_kind()!=get_kind()) { return nullptr; } return alloc(join_fn, t1.get_signature(), t2.get_signature(), col_cnt, cols1, cols2); } class hashtable_table::our_iterator_core : public iterator_core { const hashtable_table & m_parent; storage::iterator m_inner; storage::iterator m_end; class our_row : public row_interface { const our_iterator_core & m_parent; public: our_row(const our_iterator_core & parent) : row_interface(parent.m_parent), m_parent(parent) {} void get_fact(table_fact & result) const override { result = *m_parent.m_inner; } table_element operator[](unsigned col) const override { return (*m_parent.m_inner)[col]; } }; our_row m_row_obj; public: our_iterator_core(const hashtable_table & t, bool finished) : m_parent(t), m_inner(finished ? t.m_data.end() : t.m_data.begin()), m_end(t.m_data.end()), m_row_obj(*this) {} bool is_finished() const override { return m_inner==m_end; } row_interface & operator*() override { SASSERT(!is_finished()); return m_row_obj; } void operator++() override { SASSERT(!is_finished()); ++m_inner; } }; table_base::iterator hashtable_table::begin() const { return mk_iterator(alloc(our_iterator_core, *this, false)); } table_base::iterator hashtable_table::end() const { return mk_iterator(alloc(our_iterator_core, *this, true)); } // ----------------------------------- // // bitvector_table // // ----------------------------------- bool bitvector_table_plugin::can_handle_signature(const table_signature & sig) { if(sig.functional_columns()!=0) { return false; } unsigned cols = sig.size(); unsigned shift = 0; for (unsigned i = 0; i < cols; ++i) { unsigned s = static_cast(sig[i]); if (s != sig[i] || !is_power_of_two(s)) { return false; } unsigned num_bits = 0; unsigned bit_pos = 1; for (num_bits = 1; num_bits < 32; ++num_bits) { if (bit_pos & s) { break; } bit_pos <<= 1; } shift += num_bits; if (shift >= 32) { return false; } } return true; } table_base * bitvector_table_plugin::mk_empty(const table_signature & s) { SASSERT(can_handle_signature(s)); return alloc(bitvector_table, *this, s); } class bitvector_table::bv_iterator : public iterator_core { bitvector_table const& m_bv; unsigned m_offset; class our_row : public caching_row_interface { const bv_iterator& m_parent; public: our_row(const bv_iterator & p) : caching_row_interface(p.m_bv), m_parent(p) {} void get_fact(table_fact& result) const override { if (result.size() < size()) { result.resize(size(), 0); } m_parent.m_bv.offset2fact(m_parent.m_offset, result); } }; our_row m_row_obj; public: bv_iterator(const bitvector_table& bv, bool end): m_bv(bv), m_offset(end?m_bv.m_bv.size():0), m_row_obj(*this) { if (!is_finished() && !m_bv.m_bv.get(m_offset)) { ++(*this); } } bool is_finished() const override { return m_offset == m_bv.m_bv.size(); } row_interface & operator*() override { SASSERT(!is_finished()); return m_row_obj; } void operator++() override { SASSERT(!is_finished()); ++m_offset; while (!is_finished() && !m_bv.m_bv.get(m_offset)) { ++m_offset; } m_row_obj.reset(); } }; bitvector_table::bitvector_table(bitvector_table_plugin & plugin, const table_signature & sig) : table_base(plugin, sig){ SASSERT(plugin.can_handle_signature(sig)); m_num_cols = sig.size(); unsigned shift = 0; for (unsigned i = 0; i < m_num_cols; ++i) { unsigned s = static_cast(sig[i]); if (s != sig[i] || !is_power_of_two(s)) { throw default_exception("bit-vector table is specialized to small domains that are powers of two"); } m_shift.push_back(shift); m_mask.push_back(s - 1); unsigned num_bits = 0; unsigned bit_pos = 1; for (num_bits = 1; num_bits < 32; ++num_bits) { if (bit_pos & s) { break; } bit_pos <<= 1; } shift += num_bits; if (shift >= 32) { throw default_exception("bit-vector table is specialized to small domains that are powers of two"); } } m_bv.reserve(1 << shift); } unsigned bitvector_table::fact2offset(const table_element* f) const { unsigned result = 0; for (unsigned i = 0; i < m_num_cols; ++i) { SASSERT(f[i] < get_signature()[i]); result += ((unsigned)f[i]) << m_shift[i]; } return result; } void bitvector_table::offset2fact(unsigned offset, table_fact& f) const { SASSERT(m_num_cols == f.size()); for (unsigned i = 0; i < m_num_cols; ++i) { f[i] = m_mask[i] & (offset >> m_shift[i]); } } void bitvector_table::add_fact(const table_fact & f) { m_bv.set(fact2offset(f.data())); } void bitvector_table::remove_fact(const table_element* fact) { m_bv.unset(fact2offset(fact)); } bool bitvector_table::contains_fact(const table_fact & f) const { return m_bv.get(fact2offset(f.data())); } table_base::iterator bitvector_table::begin() const { return mk_iterator(alloc(bv_iterator, *this, false)); } table_base::iterator bitvector_table::end() const { return mk_iterator(alloc(bv_iterator, *this, true)); } };