Skip to content

Commit

Permalink
Adds foreach_minterm method in cube (#134)
Browse files Browse the repository at this point in the history
* cube::foreach_minterm

* update file authors

* fix issues

* remove tests for intersection_is_empty of TTT and QTT

* fix warnings

* update submodules
  • Loading branch information
lee30sonia committed Jan 5, 2023
1 parent 57c6112 commit 1b2f49f
Show file tree
Hide file tree
Showing 10 changed files with 92 additions and 183 deletions.
2 changes: 1 addition & 1 deletion bench/benchmark
Submodule benchmark updated 171 files
7 changes: 7 additions & 0 deletions include/kitty/bit_operations.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,8 @@ bool is_dont_care( const quaternary_truth_table<TT>& tt, uint64_t index )
template<typename TT>
bool is_dont_care( const TT& tt, uint64_t index )
{
(void)tt;
(void)index;
return false;
}

Expand Down Expand Up @@ -263,6 +265,8 @@ bool is_dont_know( const quaternary_truth_table<TT>& tt, uint64_t index )
template<typename TT>
bool is_dont_know( const TT& tt, uint64_t index )
{
(void)tt;
(void)index;
return false;
}

Expand All @@ -278,12 +282,15 @@ void set_dont_know( quaternary_truth_table<TT>& tt, uint64_t index )
template<typename TT>
uint64_t get_block( const TT& tt, uint64_t block_index )
{
assert( block_index < tt.num_blocks() );
return tt._bits[block_index];
}

template<uint32_t NumVars>
uint64_t get_block( const static_truth_table<NumVars, true>& tt, uint64_t block_index )
{
assert( block_index == 0 );
(void)block_index;
return tt._bits;
}

Expand Down
41 changes: 41 additions & 0 deletions include/kitty/cube.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,47 @@ class cube
_mask ^= ( 1 << index );
}

/*! \brief Iterates over all minterms in the cube
*
* The callback function takes a cube as input, which is actually
* a minterm (i.e., all variables are set), and returns a boolean.
* The loop terminates when the callback returns false.
*
* \param length Number of variables in the cube
* \param fn Callback function on each minterm
*/
template<class Fn>
void foreach_minterm( uint8_t length, Fn&& fn ) const
{
foreach_minterm_rec( *this, length, fn );
}

template<class Fn>
bool foreach_minterm_rec( cube const& c, uint8_t prev_index, Fn&& fn ) const
{
if ( prev_index == 0 )
{
return fn( c );
}

uint8_t index = prev_index - 1;
if ( !get_mask( index ) )
{
cube c0 = c;
c0.set_mask( index );
if ( !foreach_minterm_rec( c0, index, fn ) )
{
return false;
}
c0.set_bit( index );
return foreach_minterm_rec( c0, index, fn );
}
else
{
return foreach_minterm_rec( c, index, fn );
}
}

/* cube data */
union
{
Expand Down
132 changes: 19 additions & 113 deletions include/kitty/operations.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,8 @@ inline ternary_truth_table<TT> binary_and( const ternary_truth_table<TT>& first,
{
auto const op_bits = []( auto b1, auto c1, auto b2, auto c2 )
{
(void)c1;
(void)c2;
return b1 & b2;
};
auto const op_care = []( auto b1, auto c1, auto b2, auto c2 )
Expand Down Expand Up @@ -173,6 +175,8 @@ inline ternary_truth_table<TT> binary_or( const ternary_truth_table<TT>& first,
{
auto const op_bits = []( auto b1, auto c1, auto b2, auto c2 )
{
(void)c1;
(void)c2;
return b1 | b2;
};
auto const op_care = []( auto b1, auto c1, auto b2, auto c2 )
Expand Down Expand Up @@ -232,6 +236,8 @@ inline ternary_truth_table<TT> binary_xor( const ternary_truth_table<TT>& first,
};
auto const op_care = []( auto b1, auto c1, auto b2, auto c2 )
{
(void)b1;
(void)b2;
return c1 & c2;
};

Expand Down Expand Up @@ -664,7 +670,7 @@ inline bool is_const0( const quaternary_truth_table<TT>& tt )
\param polarity1 Polarity of the first truth table
\param polarity2 Polarity of the second truth table
*/
template<typename TT, bool polarity1 = true, bool polarity2 = true>
template<typename TT, bool polarity1 = true, bool polarity2 = true, typename = std::enable_if_t<is_completely_specified_truth_table<TT>::value>>
bool intersection_is_empty( const TT& first, const TT& second )
{
if constexpr ( polarity1 && polarity2 )
Expand All @@ -681,46 +687,6 @@ bool intersection_is_empty( const TT& first, const TT& second )
{ return ( ~a & ~b ) == 0u; } );
}

/*! \brief Checks whether the intersection of two ternary truth tables is empty
\param first First truth table
\param second Second truth table
\param polarity1 Polarity of the first truth table
\param polarity2 Polarity of the second truth table
*/
template<typename TT, bool polarity1 = true, bool polarity2 = true>
bool intersection_is_empty( const ternary_truth_table<TT>& a, const ternary_truth_table<TT>& b )
{
if constexpr ( polarity1 && polarity2 )
return is_const0( a & b );
else if constexpr ( !polarity1 && polarity2 )
return is_const0( ~a & b );
else if constexpr ( polarity1 && !polarity2 )
return is_const0( a & ~b );
else // !polarity1 && !polarity2
return is_const0( ~a & ~b );
}

/*! \brief Checks whether the intersection of two quaternary truth tables is empty
\param first First truth table
\param second Second truth table
\param polarity1 Polarity of the first truth table
\param polarity2 Polarity of the second truth table
*/
template<typename TT, bool polarity1 = true, bool polarity2 = true>
bool intersection_is_empty( const quaternary_truth_table<TT>& a, const quaternary_truth_table<TT>& b )
{
if constexpr ( polarity1 && polarity2 )
return is_const0( a & b );
else if constexpr ( !polarity1 && polarity2 )
return is_const0( ~a & b );
else if constexpr ( polarity1 && !polarity2 )
return is_const0( a & ~b );
else // !polarity1 && !polarity2
return is_const0( ~a & ~b );
}

/*! \brief Checks whether the intersection of three truth tables is empty
\param first First truth table
Expand All @@ -730,7 +696,7 @@ bool intersection_is_empty( const quaternary_truth_table<TT>& a, const quaternar
\param polarity2 Polarity of the second truth table
\param polarity3 Polarity of the first truth table
*/
template<typename TT, bool polarity1 = true, bool polarity2 = true, bool polarity3 = true>
template<typename TT, bool polarity1 = true, bool polarity2 = true, bool polarity3 = true, typename = std::enable_if_t<is_completely_specified_truth_table<TT>::value>>
bool intersection_is_empty( const TT& first, const TT& second, const TT& third )
{
if constexpr ( polarity1 && polarity2 && polarity3 )
Expand Down Expand Up @@ -759,66 +725,6 @@ bool intersection_is_empty( const TT& first, const TT& second, const TT& third )
{ return ( ~a & ~b & ~c ) == 0u; } );
}

/*! \brief Checks whether the intersection of three ternary truth tables is empty
\param first First truth table
\param second Second truth table
\param third Third truth table
\param polarity1 Polarity of the first truth table
\param polarity2 Polarity of the second truth table
\param polarity3 Polarity of the first truth table
*/
template<typename TT, bool polarity1 = true, bool polarity2 = true, bool polarity3 = true>
bool intersection_is_empty( const ternary_truth_table<TT>& a, const ternary_truth_table<TT>& b, const ternary_truth_table<TT>& c )
{
if constexpr ( polarity1 && polarity2 && polarity3 )
return is_const0( a & b & c );
else if constexpr ( !polarity1 && polarity2 && polarity3 )
return is_const0( ~a & b & c );
else if constexpr ( polarity1 && !polarity2 && polarity3 )
return is_const0( a & ~b & c );
else if constexpr ( polarity1 && polarity2 && !polarity3 )
return is_const0( a & b & ~c );
else if constexpr ( !polarity1 && !polarity2 && polarity3 )
return is_const0( ~a & ~b & c );
else if constexpr ( polarity1 && !polarity2 && !polarity3 )
return is_const0( a & ~b & ~c );
else if constexpr ( !polarity1 && polarity2 && !polarity3 )
return is_const0( ~a & b & ~c );
else // !polarity1 && !polarity2 && !polarity3
return is_const0( ~a & ~b & ~c );
}

/*! \brief Checks whether the intersection of three quaternary truth tables is empty
\param first First truth table
\param second Second truth table
\param third Third truth table
\param polarity1 Polarity of the first truth table
\param polarity2 Polarity of the second truth table
\param polarity3 Polarity of the first truth table
*/
template<typename TT, bool polarity1 = true, bool polarity2 = true, bool polarity3 = true>
bool intersection_is_empty( const quaternary_truth_table<TT>& a, const quaternary_truth_table<TT>& b, const quaternary_truth_table<TT>& c )
{
if constexpr ( polarity1 && polarity2 && polarity3 )
return is_const0( a & b & c );
else if constexpr ( !polarity1 && polarity2 && polarity3 )
return is_const0( ~a & b & c );
else if constexpr ( polarity1 && !polarity2 && polarity3 )
return is_const0( a & ~b & c );
else if constexpr ( polarity1 && polarity2 && !polarity3 )
return is_const0( a & b & ~c );
else if constexpr ( !polarity1 && !polarity2 && polarity3 )
return is_const0( ~a & ~b & c );
else if constexpr ( polarity1 && !polarity2 && !polarity3 )
return is_const0( a & ~b & ~c );
else if constexpr ( !polarity1 && polarity2 && !polarity3 )
return is_const0( ~a & b & ~c );
else // !polarity1 && !polarity2 && !polarity3
return is_const0( ~a & ~b & ~c );
}

/*! \brief Checks whether truth table depends on given variable index
\param tt Truth table
Expand Down Expand Up @@ -1030,8 +936,8 @@ template<typename TT>
void next_inplace( quaternary_truth_table<TT>& tt )
{
auto copy = tt;
auto first_bit_on = find_first_one_bit( tt._onset );
auto first_bit_of = find_first_one_bit( tt._offset );
int64_t first_bit_on = find_first_one_bit( tt._onset );
int64_t first_bit_of = find_first_one_bit( tt._offset );
if ( first_bit_on == -1 )
first_bit_on = tt._onset.num_bits();
if ( first_bit_of == -1 )
Expand All @@ -1040,7 +946,7 @@ void next_inplace( quaternary_truth_table<TT>& tt )
{
clear_bit( tt._offset, first_bit_of );
set_bit( tt._onset, first_bit_of );
for ( uint64_t i = 0; i < first_bit_of; i++ )
for ( int64_t i = 0; i < first_bit_of; i++ )
{
set_bit( tt._offset, i );
clear_bit( tt._onset, i );
Expand All @@ -1051,22 +957,22 @@ void next_inplace( quaternary_truth_table<TT>& tt )
if ( first_bit_of > first_bit_on )
{
set_bit( tt._offset, first_bit_on );
for ( uint64_t i = 0; i < first_bit_on; i++ )
for ( int64_t i = 0; i < first_bit_on; i++ )
{
set_bit( tt._offset, i );
clear_bit( tt._onset, i );
}
}
else
{
if ( first_bit_of == tt._offset.num_bits() && first_bit_on == tt._onset.num_bits() )
if ( uint64_t( first_bit_of ) == tt._offset.num_bits() && uint64_t( first_bit_on ) == tt._onset.num_bits() )
set_bit( tt._offset, first_bit_of - 1 );
else
{
clear_bit( tt._onset, first_bit_on );
clear_bit( tt._offset, first_bit_on );
}
for ( uint64_t i = 0; i < first_bit_of; i++ )
for ( int64_t i = 0; i < first_bit_of; i++ )
{
set_bit( tt._offset, i );
clear_bit( tt._onset, i );
Expand Down Expand Up @@ -2495,16 +2401,16 @@ inline void shift_with_mask_inplace( quaternary_truth_table<TT>& f, uint8_t mask
}
assert( mask_to.size() == mask_from.size() );
std::vector<uint8_t> index_remove = {};
for ( auto i = 0; i < mask_from.size(); i++ )
for ( auto i = 0u; i < mask_from.size(); i++ )
{
int index = std::find( begin( mask_to ), end( mask_to ), mask_from[i] ) - mask_to.begin();
if ( index < mask_to.size() )
auto it = std::find( mask_to.begin(), mask_to.end(), mask_from[i] );
if ( it != mask_to.end() )
{
mask_to.erase( mask_to.begin() + index );
mask_to.erase( it );
mask_from.erase( mask_from.begin() + i );
}
}
for ( auto i = 0; i < mask_from.size(); i++ )
for ( auto i = 0u; i < mask_from.size(); i++ )
{
swap_inplace( f, mask_from[i], mask_to[i] );
}
Expand Down
8 changes: 4 additions & 4 deletions include/kitty/print.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ void print_binary( const ternary_truth_table<TT>& tt, std::ostream& os = std::co
{
auto const chunk_size = std::min<uint64_t>( tt.num_bits(), 64 );
std::string tt_string = "";
for_each_block_reversed( tt._bits, [&os, &tt_string, chunk_size]( auto word )
for_each_block_reversed( tt._bits, [&tt_string, chunk_size]( auto word )
{
std::string chunk( chunk_size, '0' );
auto it = chunk.rbegin();
Expand All @@ -200,7 +200,7 @@ void print_binary( const ternary_truth_table<TT>& tt, std::ostream& os = std::co
word >>= 1;
}
tt_string += chunk; } );
for ( auto i = 0; i < tt.num_bits(); i++ )
for ( auto i = 0u; i < tt.num_bits(); i++ )
{
if ( is_dont_care( tt, tt.num_bits() - 1 - i ) )
{
Expand All @@ -215,7 +215,7 @@ void print_binary( const quaternary_truth_table<TT>& tt, std::ostream& os = std:
{
auto const chunk_size = std::min<uint64_t>( tt.num_bits(), 64 );
std::string tt_string = "";
for_each_block_reversed( tt._onset, [&os, &tt_string, chunk_size]( auto word )
for_each_block_reversed( tt._onset, [&tt_string, chunk_size]( auto word )
{
std::string chunk( chunk_size, '0' );
auto it = chunk.rbegin();
Expand All @@ -229,7 +229,7 @@ void print_binary( const quaternary_truth_table<TT>& tt, std::ostream& os = std:
word >>= 1;
}
tt_string += chunk; } );
for ( auto i = 0; i < tt.num_bits(); i++ )
for ( auto i = 0u; i < tt.num_bits(); i++ )
{
if ( is_dont_care( tt, tt.num_bits() - 1 - i ) )
tt_string[i] = '-';
Expand Down
1 change: 1 addition & 0 deletions include/kitty/quaternary_truth_table.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
\brief Implements quaternary_truth_table
\author Siang-Yun Lee
\author Gianluca Radi
*/

#pragma once
Expand Down
3 changes: 2 additions & 1 deletion include/kitty/ternary_truth_table.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
\brief Implements ternary_truth_table
\author Siang-Yun Lee
\author Gianluca Radi
*/

#pragma once
Expand Down Expand Up @@ -74,7 +75,7 @@ struct ternary_truth_table
\param care Care truth table.
*/
ternary_truth_table( TT const& bits, TT const& care )
: _bits( bits ), _care( care )
: _care( care ), _bits( bits )
{
}

Expand Down
16 changes: 16 additions & 0 deletions test/cube.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -128,3 +128,19 @@ TEST_F( CubeTest, negate_cube )
EXPECT_EQ( to_string( ~cube( "-1-" ), 3 ), "-0-" );
EXPECT_EQ( to_string( ~cube( "*00" ), 3 ), "-11" );
}

TEST_F( CubeTest, foreach_minterm )
{
cube c( "-1-" );
std::vector<cube> minterms;
c.foreach_minterm( 3, [&]( cube const& m ){
minterms.emplace_back( m );
return true;
} );

EXPECT_EQ( minterms.size(), 4 );
EXPECT_EQ( to_string( minterms.at( 0 ), 3 ), "010" );
EXPECT_EQ( to_string( minterms.at( 1 ), 3 ), "110" );
EXPECT_EQ( to_string( minterms.at( 2 ), 3 ), "011" );
EXPECT_EQ( to_string( minterms.at( 3 ), 3 ), "111" );
}
2 changes: 1 addition & 1 deletion test/googletest
Submodule googletest updated 288 files

0 comments on commit 1b2f49f

Please sign in to comment.