Browse Source
Use MurmurHash3_x64_128 (MMH3_HASH) for polygon checksum.
Use MurmurHash3_x64_128 (MMH3_HASH) for polygon checksum.
Improves performance when moving footprints. See https://gitlab.com/kicad/code/kicad/-/issues/18148jobs
10 changed files with 499 additions and 31 deletions
-
9libs/kimath/include/geometry/shape_poly_set.h
-
54libs/kimath/include/hash_128.h
-
196libs/kimath/include/mmh3_hash.h
-
49libs/kimath/src/geometry/shape_poly_set.cpp
-
4pcbnew/footprint.h
-
8pcbnew/specctra_import_export/specctra_export.cpp
-
2pcbnew/zone.cpp
-
4pcbnew/zone.h
-
2pcbnew/zone_filler.cpp
-
202qa/tests/libs/kimath/test_kimath.cpp
@ -0,0 +1,54 @@ |
|||
/* |
|||
* This program source code file is part of KiCad, a free EDA CAD application. |
|||
* |
|||
* Copyright (C) 2024 Alex Shvartzkop <dudesuchamazing@gmail.com> |
|||
* Copyright (C) 2024 Kicad Developers, see AUTHORS.txt for contributors. |
|||
* |
|||
* This program is free software; you can redistribute it and/or |
|||
* modify it under the terms of the GNU General Public License |
|||
* as published by the Free Software Foundation; either version 2 |
|||
* of the License, or (at your option) any later version. |
|||
* |
|||
* This program is distributed in the hope that it will be useful, |
|||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
* GNU General Public License for more details. |
|||
* |
|||
* You should have received a copy of the GNU General Public License |
|||
* along with this program; if not, you may find one here: |
|||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html |
|||
* or you may search the http://www.gnu.org website for the version 2 license, |
|||
* or you may write to the Free Software Foundation, Inc., |
|||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA |
|||
*/ |
|||
|
|||
#ifndef HASH_128_H_ |
|||
#define HASH_128_H_ |
|||
|
|||
#include <cstdint> |
|||
|
|||
/** |
|||
* A storage class for 128-bit hash value |
|||
*/ |
|||
struct HASH_128 |
|||
{ |
|||
void Clear() |
|||
{ |
|||
memset( Value64, 0, sizeof( Value64 ) ); // |
|||
} |
|||
|
|||
bool operator==( const HASH_128& aOther ) const |
|||
{ |
|||
return memcmp( Value64, aOther.Value64, sizeof( Value64 ) ) == 0; |
|||
} |
|||
|
|||
public: |
|||
union |
|||
{ |
|||
uint8_t Value8[16]{}; // Zero-initialized |
|||
uint32_t Value32[4]; |
|||
uint64_t Value64[2]; |
|||
}; |
|||
}; |
|||
|
|||
#endif // HASH_128_H_ |
|||
@ -0,0 +1,196 @@ |
|||
/* |
|||
* This program source code file is part of KiCad, a free EDA CAD application. |
|||
* |
|||
* Copyright (C) 2024 Alex Shvartzkop <dudesuchamazing@gmail.com> |
|||
* Copyright (C) 2024 Kicad Developers, see AUTHORS.txt for contributors. |
|||
* |
|||
* This program is free software; you can redistribute it and/or |
|||
* modify it under the terms of the GNU General Public License |
|||
* as published by the Free Software Foundation; either version 2 |
|||
* of the License, or (at your option) any later version. |
|||
* |
|||
* This program is distributed in the hope that it will be useful, |
|||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
* GNU General Public License for more details. |
|||
* |
|||
* You should have received a copy of the GNU General Public License |
|||
* along with this program; if not, you may find one here: |
|||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html |
|||
* or you may search the http://www.gnu.org website for the version 2 license, |
|||
* or you may write to the Free Software Foundation, Inc., |
|||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA |
|||
*/ |
|||
|
|||
// Based on https://github.com/aappleby/smhasher/blob/master/src/MurmurHash3.cpp |
|||
//----------------------------------------------------------------------------- |
|||
// MurmurHash3 was written by Austin Appleby, and is placed in the public |
|||
// domain. The author hereby disclaims copyright to this source code. |
|||
|
|||
#ifndef MMH3_HASH_H_ |
|||
#define MMH3_HASH_H_ |
|||
|
|||
#include <hash_128.h> |
|||
|
|||
//----------------------------------------------------------------------------- |
|||
// Platform-specific functions and macros |
|||
|
|||
// Microsoft Visual Studio |
|||
#if defined( _MSC_VER ) |
|||
#define FORCE_INLINE __forceinline |
|||
#include <stdlib.h> |
|||
#define ROTL64( x, y ) _rotl64( x, y ) |
|||
#define BIG_CONSTANT( x ) ( x ) |
|||
// Other compilers |
|||
#else // defined(_MSC_VER) |
|||
#define FORCE_INLINE inline __attribute__( ( always_inline ) ) |
|||
inline uint64_t rotl64( uint64_t x, int8_t r ) |
|||
{ |
|||
return ( x << r ) | ( x >> ( 64 - r ) ); |
|||
} |
|||
#define ROTL64( x, y ) rotl64( x, y ) |
|||
#define BIG_CONSTANT( x ) ( x##LLU ) |
|||
#endif // !defined(_MSC_VER) |
|||
|
|||
|
|||
/** |
|||
* A streaming C++ equivalent for MurmurHash3_x64_128. |
|||
*/ |
|||
class MMH3_HASH |
|||
{ |
|||
public: |
|||
MMH3_HASH( uint32_t aSeed = 0 ) { reset( aSeed ); } |
|||
|
|||
FORCE_INLINE void reset( uint32_t aSeed = 0 ) |
|||
{ |
|||
h1 = aSeed; |
|||
h2 = aSeed; |
|||
len = 0; |
|||
} |
|||
|
|||
FORCE_INLINE void add( int32_t input ) |
|||
{ |
|||
blocks[( len % 16 ) / 4] = input; |
|||
len += 4; |
|||
|
|||
if( len % 16 == 0 ) |
|||
hashBlock(); |
|||
} |
|||
|
|||
FORCE_INLINE HASH_128 digest() |
|||
{ |
|||
hashTail(); |
|||
|
|||
HASH_128 h128; |
|||
hashFinal( h128 ); |
|||
|
|||
return h128; |
|||
} |
|||
|
|||
private: |
|||
|
|||
// Block read - if your platform needs to do endian-swapping or can only |
|||
// handle aligned reads, do the conversion here |
|||
FORCE_INLINE uint64_t getblock64( int i ) |
|||
{ |
|||
return blocks64[i]; // |
|||
} |
|||
|
|||
FORCE_INLINE void hashBlock() |
|||
{ |
|||
static const uint64_t c1 = BIG_CONSTANT( 0x87c37b91114253d5 ); |
|||
static const uint64_t c2 = BIG_CONSTANT( 0x4cf5ad432745937f ); |
|||
|
|||
uint64_t k1 = getblock64( 0 ); |
|||
uint64_t k2 = getblock64( 1 ); |
|||
|
|||
k1 *= c1; k1 = ROTL64(k1,31); k1 *= c2; h1 ^= k1; |
|||
|
|||
h1 = ROTL64(h1,27); h1 += h2; h1 = h1*5+0x52dce729; |
|||
|
|||
k2 *= c2; k2 = ROTL64(k2,33); k2 *= c1; h2 ^= k2; |
|||
|
|||
h2 = ROTL64(h2,31); h2 += h1; h2 = h2*5+0x38495ab5; |
|||
} |
|||
|
|||
FORCE_INLINE void hashTail() |
|||
{ |
|||
const uint8_t * tail = (const uint8_t*)(blocks); |
|||
|
|||
static const uint64_t c1 = BIG_CONSTANT( 0x87c37b91114253d5 ); |
|||
static const uint64_t c2 = BIG_CONSTANT( 0x4cf5ad432745937f ); |
|||
|
|||
uint64_t k1 = 0; |
|||
uint64_t k2 = 0; |
|||
|
|||
switch( len & 15) |
|||
{ |
|||
case 15: k2 ^= ((uint64_t)tail[14]) << 48; |
|||
case 14: k2 ^= ((uint64_t)tail[13]) << 40; |
|||
case 13: k2 ^= ((uint64_t)tail[12]) << 32; |
|||
case 12: k2 ^= ((uint64_t)tail[11]) << 24; |
|||
case 11: k2 ^= ((uint64_t)tail[10]) << 16; |
|||
case 10: k2 ^= ((uint64_t)tail[ 9]) << 8; |
|||
case 9: k2 ^= ((uint64_t)tail[ 8]) << 0; |
|||
k2 *= c2; k2 = ROTL64(k2,33); k2 *= c1; h2 ^= k2; |
|||
|
|||
case 8: k1 ^= ((uint64_t)tail[ 7]) << 56; |
|||
case 7: k1 ^= ((uint64_t)tail[ 6]) << 48; |
|||
case 6: k1 ^= ((uint64_t)tail[ 5]) << 40; |
|||
case 5: k1 ^= ((uint64_t)tail[ 4]) << 32; |
|||
case 4: k1 ^= ((uint64_t)tail[ 3]) << 24; |
|||
case 3: k1 ^= ((uint64_t)tail[ 2]) << 16; |
|||
case 2: k1 ^= ((uint64_t)tail[ 1]) << 8; |
|||
case 1: k1 ^= ((uint64_t)tail[ 0]) << 0; |
|||
k1 *= c1; k1 = ROTL64(k1,31); k1 *= c2; h1 ^= k1; |
|||
}; |
|||
} |
|||
|
|||
// Finalization mix - force all bits of a hash block to avalanche |
|||
static FORCE_INLINE uint64_t fmix64( uint64_t k ) |
|||
{ |
|||
k ^= k >> 33; |
|||
k *= BIG_CONSTANT( 0xff51afd7ed558ccd ); |
|||
k ^= k >> 33; |
|||
k *= BIG_CONSTANT( 0xc4ceb9fe1a85ec53 ); |
|||
k ^= k >> 33; |
|||
|
|||
return k; |
|||
} |
|||
|
|||
FORCE_INLINE void hashFinal( HASH_128& out ) |
|||
{ |
|||
h1 ^= len; |
|||
h2 ^= len; |
|||
|
|||
h1 += h2; |
|||
h2 += h1; |
|||
|
|||
h1 = fmix64( h1 ); |
|||
h2 = fmix64( h2 ); |
|||
|
|||
h1 += h2; |
|||
h2 += h1; |
|||
|
|||
out.Value64[0] = h1; |
|||
out.Value64[1] = h2; |
|||
} |
|||
|
|||
private: |
|||
uint64_t h1; |
|||
uint64_t h2; |
|||
union |
|||
{ |
|||
uint32_t blocks[4]; |
|||
uint64_t blocks64[2]; |
|||
}; |
|||
uint32_t len; |
|||
}; |
|||
|
|||
|
|||
#undef FORCE_INLINE |
|||
#undef ROTL64 |
|||
#undef BIG_CONSTANT |
|||
|
|||
|
|||
#endif // MMH3_HASH_H_ |
|||
Write
Preview
Loading…
Cancel
Save
Reference in new issue