From b779794f9f9b7c789fa6a6cd546676160373038c Mon Sep 17 00:00:00 2001 From: Robert O'Callahan Date: Wed, 3 Jul 2024 01:59:41 +0000 Subject: [PATCH] Use `std::stable_sort` instead of `std::sort` everywhere Test results currently depend on how compare-equal elements are sorted by `std::sort`'s`unstable sort. Defaulting to `std::stable_sort` avoids that problem and generally increases the determinism of the code, which is good. If there are specific cases where the (fairly small) performance overhead of stable sorting is a concern, those can be switched back to unstable sorting as an optimization, but first one would need to verify that that doesn't break the tests (e.g., by running the tests with a shuffle before each call to unstable sort). Resolves #654 --- .../mockturtle/algorithms/aig_balancing.hpp | 2 +- .../mockturtle/algorithms/akers_synthesis.hpp | 2 +- .../mockturtle/algorithms/aqfp/aqfp_db.hpp | 2 +- .../algorithms/aqfp/aqfp_fanout_resyn.hpp | 2 +- .../algorithms/aqfp/aqfp_retiming.hpp | 2 +- .../algorithms/aqfp/buffer_insertion.hpp | 4 ++-- .../mockturtle/algorithms/aqfp/detail/dag.hpp | 8 ++++---- .../algorithms/aqfp/detail/dag_cost.hpp | 2 +- .../algorithms/aqfp/detail/dag_gen.hpp | 2 +- .../algorithms/aqfp/detail/dag_util.hpp | 2 +- .../algorithms/aqfp/detail/db_builder.hpp | 2 +- .../mig_algebraic_rewriting_splitters.hpp | 2 +- .../algorithms/cut_enumeration/spectr_cut.hpp | 2 +- include/mockturtle/algorithms/emap.hpp | 4 ++-- .../algorithms/experimental/cost_resyn.hpp | 4 ++-- include/mockturtle/algorithms/lut_mapper.hpp | 2 +- .../algorithms/mig_algebraic_rewriting.hpp | 2 +- include/mockturtle/algorithms/reconv_cut.hpp | 2 +- .../algorithms/resyn_engines/xag_resyn.hpp | 4 ++-- .../mockturtle/algorithms/xag_balancing.hpp | 2 +- .../algorithms/xmg_algebraic_rewriting.hpp | 2 +- include/mockturtle/algorithms/xmg_resub.hpp | 2 +- .../mockturtle/generators/self_dualize.hpp | 2 +- include/mockturtle/networks/aqfp.hpp | 2 +- include/mockturtle/properties/aqfpcost.hpp | 4 ++-- include/mockturtle/utils/struct_library.hpp | 2 +- include/mockturtle/utils/tech_library.hpp | 8 ++++---- include/mockturtle/utils/window_utils.hpp | 12 +++++------ include/mockturtle/views/mffc_view.hpp | 4 ++-- include/mockturtle/views/rank_view.hpp | 4 ++-- lib/percy/percy/fence.hpp | 4 ++-- test/utils/struct_library.cpp | 10 +++++----- test/utils/window_utils.cpp | 20 +++++++++---------- 33 files changed, 65 insertions(+), 65 deletions(-) diff --git a/include/mockturtle/algorithms/aig_balancing.hpp b/include/mockturtle/algorithms/aig_balancing.hpp index f782514f7..cf5a47530 100644 --- a/include/mockturtle/algorithms/aig_balancing.hpp +++ b/include/mockturtle/algorithms/aig_balancing.hpp @@ -122,7 +122,7 @@ class aig_balance_impl assert( storage[level].size() > 1 ); /* sort by decreasing level */ - std::sort( storage[level].begin(), storage[level].end(), [this]( auto const& a, auto const& b ) { + std::stable_sort( storage[level].begin(), storage[level].end(), [this]( auto const& a, auto const& b ) { return ntk.level( ntk.get_node( a ) ) > ntk.level( ntk.get_node( b ) ); } ); diff --git a/include/mockturtle/algorithms/akers_synthesis.hpp b/include/mockturtle/algorithms/akers_synthesis.hpp index 7ac9c6f06..187d92426 100644 --- a/include/mockturtle/algorithms/akers_synthesis.hpp +++ b/include/mockturtle/algorithms/akers_synthesis.hpp @@ -269,7 +269,7 @@ class unitized_table } } - std::sort( to_be_removed.begin(), to_be_removed.end() ); + std::stable_sort( to_be_removed.begin(), to_be_removed.end() ); to_be_removed.erase( std::unique( to_be_removed.begin(), to_be_removed.end() ), to_be_removed.end() ); std::reverse( std::begin( to_be_removed ), std::end( to_be_removed ) ); diff --git a/include/mockturtle/algorithms/aqfp/aqfp_db.hpp b/include/mockturtle/algorithms/aqfp/aqfp_db.hpp index 359118f1f..301800ee5 100644 --- a/include/mockturtle/algorithms/aqfp/aqfp_db.hpp +++ b/include/mockturtle/algorithms/aqfp/aqfp_db.hpp @@ -286,7 +286,7 @@ class aqfp_db auto input_ind = 1u; auto tmp_input_slots = net.input_slots; - std::sort( tmp_input_slots.begin(), tmp_input_slots.end() ); + std::stable_sort( tmp_input_slots.begin(), tmp_input_slots.end() ); assert( tmp_input_slots == net.input_slots ); for ( auto i : net.input_slots ) diff --git a/include/mockturtle/algorithms/aqfp/aqfp_fanout_resyn.hpp b/include/mockturtle/algorithms/aqfp/aqfp_fanout_resyn.hpp index 001d8221f..d9b41d24e 100644 --- a/include/mockturtle/algorithms/aqfp/aqfp_fanout_resyn.hpp +++ b/include/mockturtle/algorithms/aqfp/aqfp_fanout_resyn.hpp @@ -108,7 +108,7 @@ struct aqfp_fanout_resyn auto offsets = balanced_splitter_tree_offsets( ntk_src.fanout_size( n ) ); - std::sort( fanouts_n.begin(), fanouts_n.end(), [&]( auto f1, auto f2 ) { return ( ntk_src.depth() - ntk_src.level( f1 ) ) > ( ntk_src.depth() - ntk_src.level( f2 ) ) || + std::stable_sort( fanouts_n.begin(), fanouts_n.end(), [&]( auto f1, auto f2 ) { return ( ntk_src.depth() - ntk_src.level( f1 ) ) > ( ntk_src.depth() - ntk_src.level( f2 ) ) || ( ( ntk_src.depth() - ntk_src.level( f1 ) ) == ( ntk_src.depth() - ntk_src.level( f2 ) ) && ( f1 < f2 ) ); } ); auto n_dest = ntk_dest.get_node( f ); diff --git a/include/mockturtle/algorithms/aqfp/aqfp_retiming.hpp b/include/mockturtle/algorithms/aqfp/aqfp_retiming.hpp index b7ff4ef94..65abffb66 100644 --- a/include/mockturtle/algorithms/aqfp/aqfp_retiming.hpp +++ b/include/mockturtle/algorithms/aqfp/aqfp_retiming.hpp @@ -527,7 +527,7 @@ class aqfp_retiming_impl } } ); - std::sort( classes.begin(), classes.end(), [&]( std::vector const& a, std::vector const& b ) { return a.size() > b.size(); } ); + std::stable_sort( classes.begin(), classes.end(), [&]( std::vector const& a, std::vector const& b ) { return a.size() > b.size(); } ); return classes; } diff --git a/include/mockturtle/algorithms/aqfp/buffer_insertion.hpp b/include/mockturtle/algorithms/aqfp/buffer_insertion.hpp index 5f3e608b4..3251aa88b 100644 --- a/include/mockturtle/algorithms/aqfp/buffer_insertion.hpp +++ b/include/mockturtle/algorithms/aqfp/buffer_insertion.hpp @@ -979,7 +979,7 @@ class buffer_insertion } ); /* sort by descending order of levels */ - std::sort( level_assignment.begin(), level_assignment.end(), std::greater() ); + std::stable_sort( level_assignment.begin(), level_assignment.end(), std::greater() ); /* simulate splitter tree reconstruction */ uint32_t nodes_in_level = 0; @@ -1076,7 +1076,7 @@ class buffer_insertion } /* sort by descending order of levels */ - std::sort( level_assignment.begin(), level_assignment.end(), []( auto const& a, auto const& b ) { + std::stable_sort( level_assignment.begin(), level_assignment.end(), []( auto const& a, auto const& b ) { return a[1] > b[1]; } ); diff --git a/include/mockturtle/algorithms/aqfp/detail/dag.hpp b/include/mockturtle/algorithms/aqfp/detail/dag.hpp index 1ffe4771d..e35bc9d44 100644 --- a/include/mockturtle/algorithms/aqfp/detail/dag.hpp +++ b/include/mockturtle/algorithms/aqfp/detail/dag.hpp @@ -75,16 +75,16 @@ struct aqfp_dag { auto x1 = nodes[i]; auto x2 = rhs.nodes[i]; - std::sort( x1.begin(), x1.end() ); - std::sort( x2.begin(), x2.end() ); + std::stable_sort( x1.begin(), x1.end() ); + std::stable_sort( x2.begin(), x2.end() ); if ( x1 != x2 ) return false; } auto y1 = input_slots; auto y2 = rhs.input_slots; - std::sort( y1.begin(), y1.end() ); - std::sort( y2.begin(), y2.end() ); + std::stable_sort( y1.begin(), y1.end() ); + std::stable_sort( y2.begin(), y2.end() ); if ( y1 != y2 ) return false; diff --git a/include/mockturtle/algorithms/aqfp/detail/dag_cost.hpp b/include/mockturtle/algorithms/aqfp/detail/dag_cost.hpp index 3d732721b..7c9de614c 100644 --- a/include/mockturtle/algorithms/aqfp/detail/dag_cost.hpp +++ b/include/mockturtle/algorithms/aqfp/detail/dag_cost.hpp @@ -211,7 +211,7 @@ class dag_aqfp_cost { rellev.push_back( lev - curlev[fo] ); } - std::sort( rellev.begin(), rellev.end() ); + std::stable_sort( rellev.begin(), rellev.end() ); return fanout_cc( rellev ); } diff --git a/include/mockturtle/algorithms/aqfp/detail/dag_gen.hpp b/include/mockturtle/algorithms/aqfp/detail/dag_gen.hpp index a19c21764..4ad384e66 100644 --- a/include/mockturtle/algorithms/aqfp/detail/dag_gen.hpp +++ b/include/mockturtle/algorithms/aqfp/detail/dag_gen.hpp @@ -93,7 +93,7 @@ class dags_from_partial_dag { std::vector leaves = net.last_layer_leaves; leaves.insert( leaves.end(), net.other_leaves.begin(), net.other_leaves.end() ); - std::sort( leaves.begin(), leaves.end() ); + std::stable_sort( leaves.begin(), leaves.end() ); auto max_counts = net.max_equal_fanins(); diff --git a/include/mockturtle/algorithms/aqfp/detail/dag_util.hpp b/include/mockturtle/algorithms/aqfp/detail/dag_util.hpp index 93368625d..ec4b95c80 100644 --- a/include/mockturtle/algorithms/aqfp/detail/dag_util.hpp +++ b/include/mockturtle/algorithms/aqfp/detail/dag_util.hpp @@ -299,7 +299,7 @@ struct sublist_generator for ( auto i = last_count; i > 0; --i ) { t.push_back( last_elem ); - std::sort( t.begin(), t.end() ); + std::stable_sort( t.begin(), t.end() ); result.insert( t ); } } diff --git a/include/mockturtle/algorithms/aqfp/detail/db_builder.hpp b/include/mockturtle/algorithms/aqfp/detail/db_builder.hpp index b5d56afe4..7676d1fb6 100644 --- a/include/mockturtle/algorithms/aqfp/detail/db_builder.hpp +++ b/include/mockturtle/algorithms/aqfp/detail/db_builder.hpp @@ -257,7 +257,7 @@ class aqfp_db_builder auto input_ind = 1u; auto tmp_input_slots = net.input_slots; - std::sort( tmp_input_slots.begin(), tmp_input_slots.end() ); + std::stable_sort( tmp_input_slots.begin(), tmp_input_slots.end() ); assert( tmp_input_slots == net.input_slots ); for ( auto i : net.input_slots ) diff --git a/include/mockturtle/algorithms/aqfp/mig_algebraic_rewriting_splitters.hpp b/include/mockturtle/algorithms/aqfp/mig_algebraic_rewriting_splitters.hpp index 974bf6f70..cb4ca4948 100644 --- a/include/mockturtle/algorithms/aqfp/mig_algebraic_rewriting_splitters.hpp +++ b/include/mockturtle/algorithms/aqfp/mig_algebraic_rewriting_splitters.hpp @@ -305,7 +305,7 @@ class mig_algebraic_depth_rewriting_splitter_impl { std::array, 3> children; ntk.foreach_fanin( n, [&children]( auto const& f, auto i ) { children[i] = f; } ); - std::sort( children.begin(), children.end(), [this]( auto const& c1, auto const& c2 ) { + std::stable_sort( children.begin(), children.end(), [this]( auto const& c1, auto const& c2 ) { return ntk.level( ntk.get_node( c1 ) ) < ntk.level( ntk.get_node( c2 ) ); } ); return children; diff --git a/include/mockturtle/algorithms/cut_enumeration/spectr_cut.hpp b/include/mockturtle/algorithms/cut_enumeration/spectr_cut.hpp index 63a0043d1..d14dfac91 100644 --- a/include/mockturtle/algorithms/cut_enumeration/spectr_cut.hpp +++ b/include/mockturtle/algorithms/cut_enumeration/spectr_cut.hpp @@ -123,7 +123,7 @@ struct lut_mapping_update_cuts } } ); - std::sort( node_to_cut[n].begin(), node_to_cut[n].end() ); + std::stable_sort( node_to_cut[n].begin(), node_to_cut[n].end() ); node_to_cut[n].erase( unique( node_to_cut[n].begin(), node_to_cut[n].end() ), node_to_cut[n].end() ); } diff --git a/include/mockturtle/algorithms/emap.hpp b/include/mockturtle/algorithms/emap.hpp index b3f041c35..813797590 100644 --- a/include/mockturtle/algorithms/emap.hpp +++ b/include/mockturtle/algorithms/emap.hpp @@ -5157,7 +5157,7 @@ class emap_impl class_list.push_back( it ); } - std::sort( class_list.begin(), class_list.end(), [&]( auto const& a, auto const& b ) { + std::stable_sort( class_list.begin(), class_list.end(), [&]( auto const& a, auto const& b ) { return a.first[2] > b.first[2]; } ); @@ -5300,7 +5300,7 @@ class emap_impl } } - std::sort( order.begin(), order.end(), [&]( size_t a, size_t b ) { + std::stable_sort( order.begin(), order.end(), [&]( size_t a, size_t b ) { return tts[a] < tts[b]; } ); diff --git a/include/mockturtle/algorithms/experimental/cost_resyn.hpp b/include/mockturtle/algorithms/experimental/cost_resyn.hpp index a637c2422..54035f10a 100644 --- a/include/mockturtle/algorithms/experimental/cost_resyn.hpp +++ b/include/mockturtle/algorithms/experimental/cost_resyn.hpp @@ -209,7 +209,7 @@ class cost_resyn { l.score = kitty::count_ones( ( l.lit & 0x1 ? ~get_div( l.lit >> 1 ) : get_div( l.lit >> 1 ) ) & on_off_sets[on_off] ); } - std::sort( pos_unate_lits.begin(), pos_unate_lits.end(), [&]( unate_lit const& l1, unate_lit const& l2 ) { + std::stable_sort( pos_unate_lits.begin(), pos_unate_lits.end(), [&]( unate_lit const& l1, unate_lit const& l2 ) { return l1.score > l2.score; // descending order } ); } @@ -221,7 +221,7 @@ class cost_resyn p.score = ( p.lit1 > p.lit2 ) ? kitty::count_ones( ( ( p.lit1 & 0x1 ? ~get_div( p.lit1 >> 1 ) : get_div( p.lit1 >> 1 ) ) ^ ( p.lit2 & 0x1 ? ~get_div( p.lit2 >> 1 ) : get_div( p.lit2 >> 1 ) ) ) & on_off_sets[on_off] ) : kitty::count_ones( ( p.lit1 & 0x1 ? ~get_div( p.lit1 >> 1 ) : get_div( p.lit1 >> 1 ) ) & ( p.lit2 & 0x1 ? ~get_div( p.lit2 >> 1 ) : get_div( p.lit2 >> 1 ) ) & on_off_sets[on_off] ); } - std::sort( unate_pairs.begin(), unate_pairs.end(), [&]( fanin_pair const& p1, fanin_pair const& p2 ) { + std::stable_sort( unate_pairs.begin(), unate_pairs.end(), [&]( fanin_pair const& p1, fanin_pair const& p2 ) { return p1.score > p2.score; // descending order } ); } diff --git a/include/mockturtle/algorithms/lut_mapper.hpp b/include/mockturtle/algorithms/lut_mapper.hpp index fba44e4a1..57659041d 100644 --- a/include/mockturtle/algorithms/lut_mapper.hpp +++ b/include/mockturtle/algorithms/lut_mapper.hpp @@ -2172,7 +2172,7 @@ class lut_map_impl } /* sort leaves in topo order */ - std::sort( leaves.begin(), leaves.end() ); + std::stable_sort( leaves.begin(), leaves.end() ); ntk.add_to_mapping( n, leaves.begin(), leaves.end() ); diff --git a/include/mockturtle/algorithms/mig_algebraic_rewriting.hpp b/include/mockturtle/algorithms/mig_algebraic_rewriting.hpp index 57c849ffb..9aa2fce7a 100644 --- a/include/mockturtle/algorithms/mig_algebraic_rewriting.hpp +++ b/include/mockturtle/algorithms/mig_algebraic_rewriting.hpp @@ -274,7 +274,7 @@ class mig_algebraic_depth_rewriting_impl { std::array, 3> children; ntk.foreach_fanin( n, [&children]( auto const& f, auto i ) { children[i] = f; } ); - std::sort( children.begin(), children.end(), [this]( auto const& c1, auto const& c2 ) { + std::stable_sort( children.begin(), children.end(), [this]( auto const& c1, auto const& c2 ) { return ntk.level( ntk.get_node( c1 ) ) < ntk.level( ntk.get_node( c2 ) ); } ); return children; diff --git a/include/mockturtle/algorithms/reconv_cut.hpp b/include/mockturtle/algorithms/reconv_cut.hpp index 359d16226..3c7e5fe9b 100644 --- a/include/mockturtle/algorithms/reconv_cut.hpp +++ b/include/mockturtle/algorithms/reconv_cut.hpp @@ -303,7 +303,7 @@ class reconvergence_driven_cut_impl2 bool construct_cut() { assert( leaves.size() <= ps.max_leaves && "cut-size overflow" ); - std::sort( std::begin( leaves ), std::end( leaves ), + std::stable_sort( std::begin( leaves ), std::end( leaves ), [this]( node const& a, node const& b ) { return cost( a ) < cost( b ); } ); diff --git a/include/mockturtle/algorithms/resyn_engines/xag_resyn.hpp b/include/mockturtle/algorithms/resyn_engines/xag_resyn.hpp index a7c3628e5..ad39d8431 100644 --- a/include/mockturtle/algorithms/resyn_engines/xag_resyn.hpp +++ b/include/mockturtle/algorithms/resyn_engines/xag_resyn.hpp @@ -576,7 +576,7 @@ class xag_resyn_decompose { l.score = kitty::count_ones( ( l.lit & 0x1 ? ~get_div( l.lit >> 1 ) : get_div( l.lit >> 1 ) ) & on_off_sets[on_off] ); } - std::sort( unate_lits.begin(), unate_lits.end(), [&]( unate_lit const& l1, unate_lit const& l2 ) { + std::stable_sort( unate_lits.begin(), unate_lits.end(), [&]( unate_lit const& l1, unate_lit const& l2 ) { return l1.score > l2.score; // descending order } ); } @@ -595,7 +595,7 @@ class xag_resyn_decompose p.score = kitty::count_ones( ( p.lit1 & 0x1 ? ~get_div( p.lit1 >> 1 ) : get_div( p.lit1 >> 1 ) ) & ( p.lit2 & 0x1 ? ~get_div( p.lit2 >> 1 ) : get_div( p.lit2 >> 1 ) ) & on_off_sets[on_off] ); } } - std::sort( unate_pairs.begin(), unate_pairs.end(), [&]( fanin_pair const& p1, fanin_pair const& p2 ) { + std::stable_sort( unate_pairs.begin(), unate_pairs.end(), [&]( fanin_pair const& p1, fanin_pair const& p2 ) { return p1.score > p2.score; // descending order } ); } diff --git a/include/mockturtle/algorithms/xag_balancing.hpp b/include/mockturtle/algorithms/xag_balancing.hpp index 0b109e90e..e3e6cfcd9 100644 --- a/include/mockturtle/algorithms/xag_balancing.hpp +++ b/include/mockturtle/algorithms/xag_balancing.hpp @@ -139,7 +139,7 @@ class xag_balance_impl assert( storage[level].size() > 1 ); /* sort by decreasing level */ - std::sort( storage[level].begin(), storage[level].end(), [this]( auto const& a, auto const& b ) { + std::stable_sort( storage[level].begin(), storage[level].end(), [this]( auto const& a, auto const& b ) { return ntk.level( ntk.get_node( a ) ) > ntk.level( ntk.get_node( b ) ); } ); diff --git a/include/mockturtle/algorithms/xmg_algebraic_rewriting.hpp b/include/mockturtle/algorithms/xmg_algebraic_rewriting.hpp index 98b576b61..7b8640ed0 100644 --- a/include/mockturtle/algorithms/xmg_algebraic_rewriting.hpp +++ b/include/mockturtle/algorithms/xmg_algebraic_rewriting.hpp @@ -421,7 +421,7 @@ class xmg_algebraic_depth_rewriting_impl { std::array, 3> children; ntk.foreach_fanin( n, [&children]( auto const& f, auto i ) { children[i] = f; } ); - std::sort( children.begin(), children.end(), [this]( auto const& c1, auto const& c2 ) { + std::stable_sort( children.begin(), children.end(), [this]( auto const& c1, auto const& c2 ) { return ntk.level( ntk.get_node( c1 ) ) < ntk.level( ntk.get_node( c2 ) ); } ); return children; diff --git a/include/mockturtle/algorithms/xmg_resub.hpp b/include/mockturtle/algorithms/xmg_resub.hpp index 11cf7c97e..44690e032 100644 --- a/include/mockturtle/algorithms/xmg_resub.hpp +++ b/include/mockturtle/algorithms/xmg_resub.hpp @@ -214,7 +214,7 @@ struct xmg_resub_functor auto const& tt_s = sim.get_tt( s ); sorted_divs.emplace_back( static_cast( *it ), static_cast( relative_distinguishing_power( tt_s, tt ) ) ); } - std::sort( std::rbegin( sorted_divs ), std::rend( sorted_divs ), + std::stable_sort( std::rbegin( sorted_divs ), std::rend( sorted_divs ), [&]( auto const& u, auto const& v ) { if ( u.entropy == v.entropy ) return u.node < v.node; diff --git a/include/mockturtle/generators/self_dualize.hpp b/include/mockturtle/generators/self_dualize.hpp index 72068f996..837df18a9 100644 --- a/include/mockturtle/generators/self_dualize.hpp +++ b/include/mockturtle/generators/self_dualize.hpp @@ -79,7 +79,7 @@ inline aig_network self_dualize_aig( aig_network const& src_aig ) src_aig.foreach_po( [&]( const auto& f ) { auto leaves = cut_generator.run( { src_aig.get_node( f ) } ).first; - std::sort( std::begin( leaves ), std::end( leaves ) ); + std::stable_sort( std::begin( leaves ), std::end( leaves ) ); /* check if all leaves are pis */ for ( const auto& l : leaves ) diff --git a/include/mockturtle/networks/aqfp.hpp b/include/mockturtle/networks/aqfp.hpp index e4b2d6dd8..e739860ac 100644 --- a/include/mockturtle/networks/aqfp.hpp +++ b/include/mockturtle/networks/aqfp.hpp @@ -310,7 +310,7 @@ class aqfp_network return children[0u]; } - std::sort( children.begin(), children.end(), []( auto f, auto s ) { return f.index < s.index; } ); + std::stable_sort( children.begin(), children.end(), []( auto f, auto s ) { return f.index < s.index; } ); for ( auto i = 1u; i < children.size(); i++ ) { diff --git a/include/mockturtle/properties/aqfpcost.hpp b/include/mockturtle/properties/aqfpcost.hpp index 9d36a95eb..dd1503ad6 100644 --- a/include/mockturtle/properties/aqfpcost.hpp +++ b/include/mockturtle/properties/aqfpcost.hpp @@ -121,7 +121,7 @@ class fanout_net_cost std::vector new_config( config.begin(), config.begin() + ( config.size() - size ) ); new_config.push_back( sp_lev ); - std::sort( new_config.begin(), new_config.end() ); + std::stable_sort( new_config.begin(), new_config.end() ); temp += cost_for_config( new_config, ignore_initial_buffers ); @@ -209,7 +209,7 @@ struct aqfp_network_cost if ( rellev.size() > 1u || ( rellev.size() == 1u && rellev[0] > 0 ) ) { - std::sort( rellev.begin(), rellev.end() ); + std::stable_sort( rellev.begin(), rellev.end() ); auto net_cost = fanout_cc( rellev, ntk.is_ci( n ) && !assume.balance_pis ); if ( net_cost == std::numeric_limits::infinity() ) { diff --git a/include/mockturtle/utils/struct_library.hpp b/include/mockturtle/utils/struct_library.hpp index c239ca946..165e9eb9c 100644 --- a/include/mockturtle/utils/struct_library.hpp +++ b/include/mockturtle/utils/struct_library.hpp @@ -295,7 +295,7 @@ class struct_library uint32_t shift = 0; /* sort cells by increasing order of area */ - std::sort( indexes.begin(), indexes.end(), + std::stable_sort( indexes.begin(), indexes.end(), [&]( auto const& a, auto const& b ) -> bool { return _supergates[a].area < _supergates[b].area; } ); diff --git a/include/mockturtle/utils/tech_library.hpp b/include/mockturtle/utils/tech_library.hpp index cb3c83e33..b22d574bc 100644 --- a/include/mockturtle/utils/tech_library.hpp +++ b/include/mockturtle/utils/tech_library.hpp @@ -816,7 +816,7 @@ class tech_library std::iota( order.begin(), order.end(), 0 ); - std::sort( order.begin(), order.end(), [&]( size_t a, size_t b ) { + std::stable_sort( order.begin(), order.end(), [&]( size_t a, size_t b ) { return static_tts[a] < static_tts[b]; } ); @@ -824,7 +824,7 @@ class tech_library return static_tts[a]; } ); - // std::sort( static_tts.begin(), static_tts.end() ); + // std::stable_sort( static_tts.begin(), static_tts.end() ); auto& v = _multi_lib[sorted_tts]; @@ -1406,14 +1406,14 @@ class exact_library rewriting_fn( _database, function, pis.begin(), pis.end(), add_supergate ); if ( supergates_pos.size() > 0 ) { - std::sort( supergates_pos.begin(), supergates_pos.end(), [&]( auto const& a, auto const& b ) { + std::stable_sort( supergates_pos.begin(), supergates_pos.end(), [&]( auto const& a, auto const& b ) { return a.area < b.area; } ); _super_lib.insert( { entry, supergates_pos } ); } if ( _ps.np_classification && supergates_neg.size() > 0 ) { - std::sort( supergates_neg.begin(), supergates_neg.end(), [&]( auto const& a, auto const& b ) { + std::stable_sort( supergates_neg.begin(), supergates_neg.end(), [&]( auto const& a, auto const& b ) { return a.area < b.area; } ); _super_lib.insert( { not_entry, supergates_neg } ); diff --git a/include/mockturtle/utils/window_utils.hpp b/include/mockturtle/utils/window_utils.hpp index d23636c3e..6fce12d57 100644 --- a/include/mockturtle/utils/window_utils.hpp +++ b/include/mockturtle/utils/window_utils.hpp @@ -721,7 +721,7 @@ void levelized_expand_towards_tfo( Ntk const& ntk, std::vector cover( Ntk const& ntk, typename Ntk::node const& detail::cover_recursive( ntk, root, nodes ); /* remove duplicates */ - std::sort( std::begin( nodes ), std::end( nodes ) ); + std::stable_sort( std::begin( nodes ), std::end( nodes ) ); auto last = std::unique( std::begin( nodes ), std::end( nodes ) ); nodes.erase( last, std::end( nodes ) ); @@ -923,7 +923,7 @@ class create_window_impl *nodes = cover( ntk, pivot, inputs ); /* expand the nodes towards the TFO */ - std::sort( std::begin( inputs ), std::end( inputs ) ); + std::stable_sort( std::begin( inputs ), std::end( inputs ) ); detail::levelized_expand_towards_tfo( ntk, inputs, *nodes, levels ); } @@ -933,8 +933,8 @@ class create_window_impl } /* top. sort nodes */ - std::sort( std::begin( inputs ), std::end( inputs ) ); - std::sort( std::begin( *nodes ), std::end( *nodes ) ); + std::stable_sort( std::begin( inputs ), std::end( inputs ) ); + std::stable_sort( std::begin( *nodes ), std::end( *nodes ) ); /* collect the nodes with fanout outside of nodes */ std::vector outputs = collect_outputs( ntk, inputs, *nodes, refs ); diff --git a/include/mockturtle/views/mffc_view.hpp b/include/mockturtle/views/mffc_view.hpp index dd811bba9..8ab26395c 100644 --- a/include/mockturtle/views/mffc_view.hpp +++ b/include/mockturtle/views/mffc_view.hpp @@ -217,9 +217,9 @@ class mffc_view : public immutable_view void compute_sets() { - // std::sort( _nodes.begin(), _nodes.end(), + // std::stable_sort( _nodes.begin(), _nodes.end(), // [&]( auto const& n1, auto const& n2 ) { return static_cast( this )->node_to_index( n1 ) < static_cast( this )->node_to_index( n2 ); } ); - std::sort( _nodes.begin(), _nodes.end() ); + std::stable_sort( _nodes.begin(), _nodes.end() ); for ( auto const& n : _nodes ) { diff --git a/include/mockturtle/views/rank_view.hpp b/include/mockturtle/views/rank_view.hpp index da1e258a9..ecfef633f 100644 --- a/include/mockturtle/views/rank_view.hpp +++ b/include/mockturtle/views/rank_view.hpp @@ -235,7 +235,7 @@ class rank_view : public depth_view { auto& rank = ranks[level]; - std::sort( rank.begin(), rank.end(), cmp ); + std::stable_sort( rank.begin(), rank.end(), cmp ); std::for_each( rank.cbegin(), rank.cend(), [this, i = 0u]( auto const& n ) mutable { rank_pos[n] = i++; } ); } } @@ -323,7 +323,7 @@ class rank_view : public depth_view pis.reserve( this->num_pis() ); depth_view::foreach_pi( [&pis]( auto const& pi ) { pis.push_back( pi ); } ); - std::sort( pis.begin(), pis.end(), [this]( auto const& n1, auto const& n2 ) { return rank_pos[n1] < rank_pos[n2]; } ); + std::stable_sort( pis.begin(), pis.end(), [this]( auto const& n1, auto const& n2 ) { return rank_pos[n1] < rank_pos[n2]; } ); detail::foreach_element( pis.cbegin(), pis.cend(), std::forward( fn ) ); } /** diff --git a/lib/percy/percy/fence.hpp b/lib/percy/percy/fence.hpp index 2b990727a..77f2f055c 100644 --- a/lib/percy/percy/fence.hpp +++ b/lib/percy/percy/fence.hpp @@ -192,7 +192,7 @@ namespace percy } if (!std::next_permutation(_fence.begin(), _fence.end())) { if (next_partition(_fence)) { - std::sort(_fence.begin(), _fence.end()); + std::stable_sort(_fence.begin(), _fence.end()); } else { _fences_finished = true; } @@ -216,7 +216,7 @@ namespace percy _fence.resize(nlevels); if (next_partition(_fence)) { - std::sort(_fence.begin(), _fence.end()); + std::stable_sort(_fence.begin(), _fence.end()); } else { _fences_finished = true; } diff --git a/test/utils/struct_library.cpp b/test/utils/struct_library.cpp index 30a664801..f7e8e8df8 100644 --- a/test/utils/struct_library.cpp +++ b/test/utils/struct_library.cpp @@ -68,7 +68,7 @@ TEST_CASE( "Struct library creation", "[struct_library]" ) /* translate to sorted vector */ std::vector entry_ids; std::for_each( library_map.begin(), library_map.end(), [&]( auto const& pair ) { entry_ids.push_back( pair.first ); return; } ); - std::sort( entry_ids.begin(), entry_ids.end() ); + std::stable_sort( entry_ids.begin(), entry_ids.end() ); CHECK( entry_ids.size() == 8 ); @@ -172,7 +172,7 @@ TEST_CASE( "Struct library creation min sizes", "[struct_library]" ) /* translate to sorted vector */ std::vector entry_ids; std::for_each( library_map.begin(), library_map.end(), [&]( auto const& pair ) { entry_ids.push_back( pair.first ); return; } ); - std::sort( entry_ids.begin(), entry_ids.end() ); + std::stable_sort( entry_ids.begin(), entry_ids.end() ); CHECK( entry_ids.size() == 1 ); @@ -206,7 +206,7 @@ TEST_CASE( "Struct library creation dominated sizes", "[struct_library]" ) /* translate to sorted vector */ std::vector entry_ids; std::for_each( library_map.begin(), library_map.end(), [&]( auto const& pair ) { entry_ids.push_back( pair.first ); return; } ); - std::sort( entry_ids.begin(), entry_ids.end() ); + std::stable_sort( entry_ids.begin(), entry_ids.end() ); CHECK( entry_ids.size() == 1 ); @@ -246,7 +246,7 @@ TEST_CASE( "Struct library creation ignore reconvergence", "[struct_library]" ) /* translate to sorted vector */ std::vector entry_ids; std::for_each( library_map.begin(), library_map.end(), [&]( auto const& pair ) { entry_ids.push_back( pair.first ); return; } ); - std::sort( entry_ids.begin(), entry_ids.end() ); + std::stable_sort( entry_ids.begin(), entry_ids.end() ); CHECK( entry_ids.size() == 1 ); CHECK( entry_ids[0] % 2 == 1 ); @@ -276,7 +276,7 @@ TEST_CASE( "Struct library creation large rules", "[struct_library]" ) /* translate to sorted vector */ std::vector entry_ids; std::for_each( library_map.begin(), library_map.end(), [&]( auto const& pair ) { entry_ids.push_back( pair.first ); return; } ); - std::sort( entry_ids.begin(), entry_ids.end() ); + std::stable_sort( entry_ids.begin(), entry_ids.end() ); CHECK( entry_ids.size() == 2 ); diff --git a/test/utils/window_utils.cpp b/test/utils/window_utils.cpp index 6c140012e..b1e82a775 100644 --- a/test/utils/window_utils.cpp +++ b/test/utils/window_utils.cpp @@ -40,7 +40,7 @@ TEST_CASE( "expand node set towards TFI without cut-size", "[window_utils]" ) bool const trivial_cut = expand0_towards_tfi( aig, inputs ); CHECK( trivial_cut ); - std::sort( std::begin( inputs ), std::end( inputs ) ); + std::stable_sort( std::begin( inputs ), std::end( inputs ) ); CHECK( inputs == std::vector{ aig.get_node( a ), aig.get_node( b ), aig.get_node( c ), aig.get_node( d ) } ); } @@ -57,7 +57,7 @@ TEST_CASE( "expand node set towards TFI without cut-size", "[window_utils]" ) bool const trivial_cut = expand0_towards_tfi( aig, inputs ); CHECK( !trivial_cut ); - std::sort( std::begin( inputs ), std::end( inputs ) ); + std::stable_sort( std::begin( inputs ), std::end( inputs ) ); CHECK( inputs == std::vector{ aig.get_node( f3 ), aig.get_node( f4 ) } ); } @@ -74,7 +74,7 @@ TEST_CASE( "expand node set towards TFI without cut-size", "[window_utils]" ) bool const trivial_cut = expand0_towards_tfi( aig, inputs ); CHECK( !trivial_cut ); - std::sort( std::begin( inputs ), std::end( inputs ) ); + std::stable_sort( std::begin( inputs ), std::end( inputs ) ); CHECK( inputs == std::vector{ aig.get_node( a ), aig.get_node( d ), aig.get_node( f2 ) } ); } @@ -91,7 +91,7 @@ TEST_CASE( "expand node set towards TFI without cut-size", "[window_utils]" ) bool const trivial_cut = expand0_towards_tfi( aig, inputs ); CHECK( !trivial_cut ); - std::sort( std::begin( inputs ), std::end( inputs ) ); + std::stable_sort( std::begin( inputs ), std::end( inputs ) ); CHECK( inputs == std::vector{ aig.get_node( f3 ), aig.get_node( f4 ) } ); } @@ -108,7 +108,7 @@ TEST_CASE( "expand node set towards TFI without cut-size", "[window_utils]" ) bool const trivial_cut = expand0_towards_tfi( aig, inputs ); CHECK( !trivial_cut ); - std::sort( std::begin( inputs ), std::end( inputs ) ); + std::stable_sort( std::begin( inputs ), std::end( inputs ) ); CHECK( inputs == std::vector{ aig.get_node( f3 ), aig.get_node( f4 ) } ); } } @@ -143,7 +143,7 @@ TEST_CASE( "expand node set towards TFI", "[window_utils]" ) expand_towards_tfi( aig, inputs, 4u ); - std::sort( std::begin( inputs ), std::end( inputs ) ); + std::stable_sort( std::begin( inputs ), std::end( inputs ) ); CHECK( inputs == std::vector{ aig.get_node( a ), aig.get_node( b ), aig.get_node( c ), aig.get_node( d ) } ); } @@ -159,7 +159,7 @@ TEST_CASE( "expand node set towards TFI", "[window_utils]" ) expand_towards_tfi( aig, inputs, 3u ); - std::sort( std::begin( inputs ), std::end( inputs ) ); + std::stable_sort( std::begin( inputs ), std::end( inputs ) ); CHECK( inputs == std::vector{ aig.get_node( a ), aig.get_node( d ), aig.get_node( f2 ) } ); } @@ -175,7 +175,7 @@ TEST_CASE( "expand node set towards TFI", "[window_utils]" ) expand_towards_tfi( aig, inputs, 3u ); - std::sort( std::begin( inputs ), std::end( inputs ) ); + std::stable_sort( std::begin( inputs ), std::end( inputs ) ); CHECK( inputs == std::vector{ aig.get_node( a ), aig.get_node( d ), aig.get_node( f2 ) } ); } } @@ -206,7 +206,7 @@ TEST_CASE( "expand node set towards TFO", "[window_utils]" ) std::vector nodes; expand_towards_tfo( aig, inputs, nodes ); - std::sort( std::begin( nodes ), std::end( nodes ) ); + std::stable_sort( std::begin( nodes ), std::end( nodes ) ); CHECK( nodes == std::vector{ aig.get_node( f1 ), aig.get_node( f2 ), aig.get_node( f3 ), aig.get_node( f4 ), aig.get_node( f5 ) } ); } @@ -215,7 +215,7 @@ TEST_CASE( "expand node set towards TFO", "[window_utils]" ) std::vector nodes; levelized_expand_towards_tfo( aig, inputs, nodes ); - std::sort( std::begin( nodes ), std::end( nodes ) ); + std::stable_sort( std::begin( nodes ), std::end( nodes ) ); CHECK( nodes == std::vector{ aig.get_node( f1 ), aig.get_node( f2 ), aig.get_node( f3 ), aig.get_node( f4 ), aig.get_node( f5 ) } ); }