COMP: resolve label 64 compilation ambiguity for Mingw (fixes #3390)

COMP: restrict HashTable maxTableSize to int32 range

- avoids compiler warning about possible overflow (left-shift
  operation) for label 64 compilations and we don't need anything
  larger than int32 HashTable capacity anyhow.

ENH: make nearest power-of-two non-branching (previously brute-force)
This commit is contained in:
Mark Olesen
2025-07-30 12:45:16 +02:00
parent 95a5dfacc7
commit d2c145d7a4
5 changed files with 72 additions and 38 deletions

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation
Copyright (C) 2017-2023 OpenCFD Ltd.
Copyright (C) 2017-2025 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -37,11 +37,30 @@ License
using namespace Foam;
void checkCanonicalSize(label size)
{
const auto n = HashTableCore::canonicalSize(size);
std::ostringstream buf;
buf.setf(std::ios_base::hex, std::ios_base::basefield);
buf << n;
Info<< "hash-table size of " << size
<< " = " << n << " (0x" << buf.str().c_str() << ')' << nl;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// Main program:
int main()
{
for (label size : { -1, 0, 1, 7, 500, 1024, 1025, 10000, (labelMax-1)} )
{
checkCanonicalSize(size);
}
Info<< nl;
HashTable<scalar> table1
{
{"aaa", 1.0},

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2012 OpenFOAM Foundation
Copyright (C) 2017-2019 OpenCFD Ltd.
Copyright (C) 2017-2025 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -27,7 +27,6 @@ License
\*---------------------------------------------------------------------------*/
#include "HashTableCore.H"
#include "uLabel.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
@ -36,51 +35,66 @@ namespace Foam
defineTypeNameAndDebug(HashTableCore, 0);
}
// Approximately labelMax/4
const Foam::label Foam::HashTableCore::maxTableSize(1L << (sizeof(label)*8-3));
// file-scope:
// Minimum internal table size (must be a power of two!)
constexpr int32_t minTableSize = 8;
// * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * //
Foam::label Foam::HashTableCore::canonicalSize(const label requested_size)
Foam::label Foam::HashTableCore::canonicalSize(const label size) noexcept
{
if (requested_size < 1)
{
return 0;
}
else if (requested_size >= maxTableSize)
{
return maxTableSize;
}
// Enforce power of two for fast modulus in hash index calculations.
// Use unsigned for these calculations.
//
// - The lower limit (8) is somewhat arbitrary, but if the hash table
// is too small, there will be many direct table collisions.
// - The upper limit (approx. labelMax/4) must be a power of two,
// - The upper limit (approx. INT32_MAX/4) must be a power of two,
// need not be extremely large for hashing.
uLabel powerOfTwo = 8u; // lower-limit
const uLabel size = requested_size;
if (size <= powerOfTwo)
if (size <= minTableSize)
{
return powerOfTwo;
return (size < 1 ? 0 : minTableSize);
}
else if (size > maxTableSize/2)
{
return maxTableSize;
}
if (size & (size-1)) // <- Modulus of i^2
{
// Determine power-of-two. Brute-force is fast enough.
while (powerOfTwo < size)
{
powerOfTwo <<= 1;
}
// Determine power-of-two with glibc (may or may not be faster):
//
// return (1 << (32-__builtin_clz(int32_t(size-1))));
return powerOfTwo;
if (!(size & (size-1)))
{
// Already a power-of-two...
return size;
}
return size;
// Non-branching for 32-bit
// [https://graphics.stanford.edu/~seander/bithacks.html]
{
uint32_t n(size);
--n;
n |= n >> 1;
n |= n >> 2;
n |= n >> 4;
n |= n >> 8;
n |= n >> 16;
++n;
return n;
}
// OLD:
// Brute-force method
//
// uint32_t n(minTableSize);
// while (n < uint32_t(size))
// {
// n <<= 1;
// }
// return n;
}

View File

@ -39,7 +39,6 @@ SourceFiles
#define Foam_HashTableCore_H
#include "label.H"
#include "uLabel.H"
#include "className.H"
#include "nullObject.H"
@ -55,11 +54,13 @@ namespace Foam
//- Bits that are independent of HashTable template parameters.
struct HashTableCore
{
//- Maximum allowable internal table size. Approximately labelMax/4
static const label maxTableSize;
//- Maximum allowable internal table size (must be a power of two!).
// - approximately (INT32_MAX/4) => 0x20000000
// - don't need an int64 version
static constexpr int32_t maxTableSize = (1 << (32-3));
//- Return a canonical (power-of-two) of the requested size.
static label canonicalSize(const label requested_size);
static label canonicalSize(const label size) noexcept;
//- Declare type-name (with debug switch)
ClassName("HashTable");

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011 OpenFOAM Foundation
Copyright (C) 2018-2021 OpenCFD Ltd.
Copyright (C) 2018-2025 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -64,7 +64,7 @@ MAXMINPOW(float, float, int)
MAXMINPOW(float, int, float)
MAXMINPOW(float, float, long)
MAXMINPOW(float, long, float)
#if defined(__APPLE__) && WM_LABEL_SIZE == 64
#if (WM_LABEL_SIZE == 64) && (defined(__APPLE__) || defined(_WIN32))
MAXMINPOW(double, double, int64_t)
MAXMINPOW(double, int64_t, double)
MAXMINPOW(float, float, int64_t)

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2014 OpenFOAM Foundation
Copyright (C) 2019-2023 OpenCFD Ltd.
Copyright (C) 2019-2025 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -433,7 +433,7 @@ inline complex pow(const complex& x, const complex& y)
powFuncs(int)
powFuncs(long)
#if defined(__APPLE__) && WM_LABEL_SIZE == 64
#if (WM_LABEL_SIZE == 64) && (defined(__APPLE__) || defined(_WIN32))
powFuncs(int64_t)
#endif
powFuncs(float)