Blacklist hashes for 2d integer elements
The hash table for integer hashes is extremely limited and places most elements in the same buckets. This leads to a linear search time for structures built on this. This blocks hashes, directing the coder to utilize std::set or std::map structures instead of hash tables for implementing integer-based lookups.
This commit is contained in:
parent
ed02d7c974
commit
06786c34d7
|
@ -112,7 +112,7 @@ void VIEW_GROUP::ViewDraw( int aLayer, VIEW* aView ) const
|
|||
|
||||
const std::vector<VIEW_ITEM*> drawList = updateDrawList();
|
||||
|
||||
std::unordered_map<int, std::vector<VIEW_ITEM*>> layer_item_map;
|
||||
std::map<int, std::vector<VIEW_ITEM*>> layer_item_map;
|
||||
|
||||
// Build a list of layers used by the items in the group
|
||||
for( VIEW_ITEM* item : drawList )
|
||||
|
@ -123,13 +123,6 @@ void VIEW_GROUP::ViewDraw( int aLayer, VIEW* aView ) const
|
|||
for( int i = 0; i < item_layers_count; i++ )
|
||||
{
|
||||
wxCHECK2_MSG( item_layers[i] <= LAYER_ID_COUNT, continue, wxT( "Invalid item layer" ) );
|
||||
|
||||
if( layer_item_map.count( item_layers[i] ) == 0 )
|
||||
{
|
||||
layer_item_map.emplace( std::make_pair( item_layers[i],
|
||||
std::vector<VIEW_ITEM*>() ) );
|
||||
}
|
||||
|
||||
layer_item_map[ item_layers[i] ].push_back( item );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,16 +29,6 @@ size_t std::hash<wxString>::operator()( const wxString& s ) const
|
|||
#endif
|
||||
|
||||
#ifdef USE_KICAD_WXPOINT_LESS_AND_HASH
|
||||
size_t std::hash<wxPoint>::operator() ( const wxPoint& k ) const
|
||||
{
|
||||
auto xhash = std::hash<int>()( k.x );
|
||||
|
||||
// 0x9e3779b9 is 2^33 / ( 1 + sqrt(5) )
|
||||
// Adding this value ensures that consecutive bits of y will not be close to each other
|
||||
// decreasing the likelihood of hash collision in similar values of x and y
|
||||
return xhash ^ ( std::hash<int>()( k.y ) + 0x9e3779b9 + ( xhash << 6 ) + ( xhash >> 2 ) );
|
||||
}
|
||||
|
||||
bool std::less<wxPoint>::operator()( const wxPoint& aA, const wxPoint& aB ) const
|
||||
{
|
||||
if( aA.x == aB.x )
|
||||
|
|
|
@ -411,7 +411,7 @@ int ERC_TESTER::TestNoConnectPins()
|
|||
|
||||
for( const SCH_SHEET_PATH& sheet : m_schematic->GetSheets() )
|
||||
{
|
||||
std::unordered_map<VECTOR2I, std::vector<SCH_PIN*>> pinMap;
|
||||
std::map<VECTOR2I, std::vector<SCH_PIN*>> pinMap;
|
||||
|
||||
for( SCH_ITEM* item : sheet.LastScreen()->Items().OfType( SCH_SYMBOL_T ) )
|
||||
{
|
||||
|
@ -863,4 +863,4 @@ int ERC_TESTER::TestOffGridEndpoints( int aGridSize )
|
|||
}
|
||||
|
||||
return err_count;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -43,7 +43,7 @@ namespace std
|
|||
{
|
||||
template <> struct hash<wxPoint>
|
||||
{
|
||||
size_t operator() ( const wxPoint& k ) const;
|
||||
size_t operator() ( const wxPoint& k ) const = delete;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -611,13 +611,17 @@ typedef VECTOR2<unsigned int> VECTOR2U;
|
|||
namespace std
|
||||
{
|
||||
// Required to enable correct use in std::map/unordered_map
|
||||
// DO NOT USE hash tables with VECTOR2 elements. It is inefficient
|
||||
// and degenerates to a linear search. Use the std::map/std::set
|
||||
// trees instead that utilize the less operator below
|
||||
// This function is purposely deleted after substantial testing
|
||||
template <>
|
||||
struct hash<VECTOR2I>
|
||||
{
|
||||
size_t operator()( const VECTOR2I& k ) const;
|
||||
size_t operator()( const VECTOR2I& k ) const = delete;
|
||||
};
|
||||
|
||||
// Required to enable use of std::hash with maps
|
||||
// Required to enable use of std::hash with maps.
|
||||
template <>
|
||||
struct less<VECTOR2I>
|
||||
{
|
||||
|
|
|
@ -19,22 +19,10 @@
|
|||
|
||||
#include <math/vector2d.h>
|
||||
|
||||
|
||||
size_t std::hash<VECTOR2I>::operator()( const VECTOR2I& k ) const
|
||||
{
|
||||
auto xhash = std::hash<int>()( k.x );
|
||||
|
||||
// 0x9e3779b9 is 2^33 / ( 1 + sqrt(5) )
|
||||
// Adding this value ensures that consecutive bits of y will not be close to each other
|
||||
// decreasing the likelihood of hash collision in similar values of x and y
|
||||
return xhash ^ ( std::hash<int>()( k.y ) + 0x9e3779b9 + ( xhash << 6 ) + ( xhash >> 2 ) );
|
||||
}
|
||||
|
||||
|
||||
bool std::less<VECTOR2I>::operator()( const VECTOR2I& aA, const VECTOR2I& aB ) const
|
||||
{
|
||||
if( aA.x == aB.x )
|
||||
return aA.y < aB.y;
|
||||
|
||||
return aA.x < aB.x;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -243,7 +243,7 @@ protected:
|
|||
bool m_testFootprints;
|
||||
|
||||
// constraint -> rule -> provider
|
||||
std::unordered_map<DRC_CONSTRAINT_T, std::vector<DRC_ENGINE_CONSTRAINT*>*> m_constraintMap;
|
||||
std::map<DRC_CONSTRAINT_T, std::vector<DRC_ENGINE_CONSTRAINT*>*> m_constraintMap;
|
||||
|
||||
DRC_VIOLATION_HANDLER m_violationHandler;
|
||||
REPORTER* m_reporter;
|
||||
|
|
|
@ -854,7 +854,7 @@ void DRC_TEST_PROVIDER_COPPER_CLEARANCE::testZonesToZones()
|
|||
}
|
||||
|
||||
// Iterate through all the segments of refSmoothedPoly
|
||||
std::unordered_map<VECTOR2I, int> conflictPoints;
|
||||
std::map<VECTOR2I, int> conflictPoints;
|
||||
|
||||
for( auto refIt = smoothed_polys[ia].IterateSegmentsWithHoles(); refIt; refIt++ )
|
||||
{
|
||||
|
|
|
@ -1140,12 +1140,12 @@ void PCB_SELECTION_TOOL::selectAllConnectedTracks(
|
|||
|
||||
auto connectivity = board()->GetConnectivity();
|
||||
|
||||
std::unordered_map<VECTOR2I, std::vector<PCB_TRACK*>> trackMap;
|
||||
std::unordered_map<VECTOR2I, PCB_VIA*> viaMap;
|
||||
std::unordered_map<VECTOR2I, PAD*> padMap;
|
||||
std::set<PAD*> startPadSet;
|
||||
std::vector<BOARD_CONNECTED_ITEM*> cleanupItems;
|
||||
std::vector<std::pair<VECTOR2I, LSET>> activePts;
|
||||
std::map<VECTOR2I, std::vector<PCB_TRACK*>> trackMap;
|
||||
std::map<VECTOR2I, PCB_VIA*> viaMap;
|
||||
std::map<VECTOR2I, PAD*> padMap;
|
||||
std::set<PAD*> startPadSet;
|
||||
std::vector<BOARD_CONNECTED_ITEM*> cleanupItems;
|
||||
std::vector<std::pair<VECTOR2I, LSET>> activePts;
|
||||
|
||||
for( BOARD_CONNECTED_ITEM* startItem : aStartItems )
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue