/*++ Copyright (c) 2020 Microsoft Corporation Module Name: bit_matrix.cpp Author: Nikolaj Bjorner (nbjorner) 2020-01-1 Notes: --*/ #include "math/simplex/bit_matrix.h" #include "util/stopwatch.h" #include bit_matrix::col_iterator bit_matrix::row::begin() const { return bit_matrix::col_iterator(*this, true); } bit_matrix::col_iterator bit_matrix::row::end() const { return bit_matrix::col_iterator(*this, false); } void bit_matrix::col_iterator::next() { ++m_column; while (m_column < r.m.m_num_columns && !r[m_column]) { while ((m_column % 64) == 0 && m_column + 64 < r.m.m_num_columns && !r.r[m_column >> 6]) { m_column += 64; } ++m_column; } } bool bit_matrix::row::operator[](unsigned i) const { SASSERT((i >> 6) < m.m_num_chunks); return (r[i >> 6] & (1ull << static_cast(i & 63))) != 0; } std::ostream& bit_matrix::row::display(std::ostream& out) const { for (unsigned i = 0; i < m.m_num_columns; ++i) { out << ((*this)[i]?"1":"0"); } return out << "\n"; } void bit_matrix::reset(unsigned num_columns) { m_region.reset(); m_rows.reset(); m_num_columns = num_columns; m_num_chunks = (num_columns + 63)/64; } bit_matrix::row bit_matrix::add_row() { uint64_t* r = new (m_region) uint64_t[m_num_chunks]; m_rows.push_back(r); memset(r, 0, sizeof(uint64_t)*m_num_chunks); return row(*this, r); } bit_matrix::row& bit_matrix::row::operator+=(row const& other) { for (unsigned i = 0; i < m.m_num_chunks; ++i) { r[i] ^= other.r[i]; } return *this; } struct bit_matrix::report { bit_matrix& b; stopwatch m_watch; report(bit_matrix& b) : b(b) { m_watch.start(); } ~report() { m_watch.stop(); IF_VERBOSE(10, verbose_stream() << "solve " << b.m_rows.size() << " " << b.m_num_columns << " " << m_watch << "\n"); } }; void bit_matrix::solve() { basic_solve(); } void bit_matrix::basic_solve() { report _report(*this); for (row& r : *this) { auto ci = r.begin(); if (ci != r.end()) { unsigned c = *ci; for (row& r2 : *this) { if (r2 != r && r2[c]) r2 += r; } } } } std::ostream& bit_matrix::display(std::ostream& out) { for (row& r : *this) { out << r; } return out; } /* produce a sequence of bits forming a Gray code. - All 2^n bit-sequences are covered. - The Hamming distance between two entries it one. */ unsigned_vector bit_matrix::gray(unsigned n) { SASSERT(n < 32); if (n == 0) { return unsigned_vector(); } else if (n == 1) { unsigned_vector v; v.push_back(0); v.push_back(1); return v; } else { auto v = gray(n-1); auto w = v; w.reverse(); for (auto & u : v) u |= (1 << (n-1)); v.append(w); return v; } }