Add missing qHash(qu/int128) overloads
If we add the typedefs, we also need to add the qHash() overloads. See
code comments for the explanation of how it works. I chose to use an
addition to merge the upper and lower parts because of the comment in
QHashCombineCommutative's operator(), introduced by commit
91b44afdcb.
Found in 6.6 API-review, but didn't make the cut and then was
forgotten.
Drive-by fix long line nearby.
[ChangeLog][QtCore] Added qHash() overloads for quint128 and qint128.
Fixes: QTBUG-116054
Task-number: QTBUG-116080
Change-Id: If484aed08ba476e0eace800b719f435203100f3e
Reviewed-by: Ivan Solovev <ivan.solovev@qt.io>
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
bb10
parent
1845d43327
commit
1d7950c946
|
|
@ -1379,6 +1379,26 @@ uint qt_hash(QStringView key, uint chained) noexcept
|
|||
Returns the hash value for the \a key, using \a seed to seed the calculation.
|
||||
*/
|
||||
|
||||
/*! \fn size_t qHash(quint128 key, size_t seed = 0)
|
||||
\relates QHash
|
||||
\since 6.8
|
||||
|
||||
Returns the hash value for the \a key, using \a seed to seed the calculation.
|
||||
|
||||
\note This function is only available on platforms that support a native
|
||||
128-bit integer type.
|
||||
*/
|
||||
|
||||
/*! \fn size_t qHash(qint128 key, size_t seed = 0)
|
||||
\relates QHash
|
||||
\since 6.8
|
||||
|
||||
Returns the hash value for the \a key, using \a seed to seed the calculation.
|
||||
|
||||
\note This function is only available on platforms that support a native
|
||||
128-bit integer type.
|
||||
*/
|
||||
|
||||
/*! \fn size_t qHash(char8_t key, size_t seed = 0)
|
||||
\relates QHash
|
||||
\since 6.0
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
// Copyright (C) 2016 The Qt Company Ltd.
|
||||
// Copyright (C) 2015 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Marc Mutz <marc.mutz@kdab.com>
|
||||
// Copyright (C) 2024 Intel Corporation.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
|
||||
|
||||
#ifndef QHASHFUNCTIONS_H
|
||||
|
|
@ -102,7 +103,26 @@ Q_DECL_CONST_FUNCTION constexpr inline size_t qHash(quint64 key, size_t seed = 0
|
|||
key ^= (key >> 32);
|
||||
return QHashPrivate::hash(size_t(key), seed);
|
||||
}
|
||||
Q_DECL_CONST_FUNCTION constexpr inline size_t qHash(qint64 key, size_t seed = 0) noexcept { return qHash(quint64(key), seed); }
|
||||
Q_DECL_CONST_FUNCTION constexpr inline size_t qHash(qint64 key, size_t seed = 0) noexcept
|
||||
{ return qHash(quint64(key), seed); }
|
||||
#if QT_SUPPORTS_INT128
|
||||
constexpr size_t qHash(quint128 key, size_t seed = 0) noexcept
|
||||
{
|
||||
return qHash(quint64(key + (key >> 64)), seed);
|
||||
}
|
||||
constexpr size_t qHash(qint128 key, size_t seed = 0) noexcept
|
||||
{
|
||||
// Avoid QTBUG-116080: we XOR the top half with its own sign bit:
|
||||
// - if the qint128 is in range of qint64, then signmask ^ high == 0
|
||||
// - if the qint128 is in range of quint64, then signmask == 0 and we
|
||||
// do the same as the quint128 overload above
|
||||
quint64 high = quint64(quint128(key) >> 64);
|
||||
quint64 low = quint64(quint128(key));
|
||||
quint64 signmask = qint64(high) >> 63; // all zeroes or all ones
|
||||
low += signmask ^ high;
|
||||
return qHash(low, seed);
|
||||
}
|
||||
#endif // QT_SUPPORTS_INT128
|
||||
Q_DECL_CONST_FUNCTION inline size_t qHash(float key, size_t seed = 0) noexcept
|
||||
{
|
||||
// ensure -0 gets mapped to 0
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@ private Q_SLOTS:
|
|||
void unsignedIntegerConsistency();
|
||||
void signedIntegerConsistency_data();
|
||||
void signedIntegerConsistency();
|
||||
void extendedIntegerConsistency();
|
||||
void floatingPointConsistency_data();
|
||||
void floatingPointConsistency();
|
||||
void stringConsistency_data();
|
||||
|
|
@ -151,6 +152,11 @@ static void unsignedIntegerConsistency(quint64 value, size_t seed)
|
|||
if (v32 == value)
|
||||
QCOMPARE(hu64, hu32);
|
||||
|
||||
#if QT_SUPPORTS_INT128
|
||||
const auto hu128 = qHash(quint128(value), seed);
|
||||
QCOMPARE(hu128, hu64);
|
||||
#endif
|
||||
|
||||
// there are a few more unsigned types:
|
||||
#ifdef __cpp_char8_t
|
||||
const auto hc8 = qHash(char8_t(value), seed);
|
||||
|
|
@ -193,6 +199,11 @@ void tst_QHashFunctions::signedIntegerConsistency()
|
|||
QCOMPARE(hs64, hs32);
|
||||
}
|
||||
|
||||
#if QT_SUPPORTS_INT128
|
||||
const auto hs128 = qHash(qint128(value), seed);
|
||||
QCOMPARE(hs128, hs64);
|
||||
#endif
|
||||
|
||||
if (value > 0) {
|
||||
quint64 u64 = quint64(value);
|
||||
const auto hu64 = qHash(u64, seed);
|
||||
|
|
@ -202,6 +213,20 @@ void tst_QHashFunctions::signedIntegerConsistency()
|
|||
}
|
||||
}
|
||||
|
||||
void tst_QHashFunctions::extendedIntegerConsistency()
|
||||
{
|
||||
#ifdef QT_SUPPORTS_INT128
|
||||
// We only need to check qint128 and quint128 consistency here.
|
||||
qint128 v65bit = Q_INT128_C(0x1'abea'06b7'dcf5'106a);
|
||||
qint128 v127bit = Q_INT128_C(0x387c'ac7a'22a0'5242'9ee9'bcaa'6a53'13af);
|
||||
|
||||
QCOMPARE(qHash(quint128(v65bit), seed), qHash(v65bit, seed));
|
||||
QCOMPARE(qHash(quint128(v127bit), seed), qHash(v127bit, seed));
|
||||
#else
|
||||
QSKIP("This platform does not support extended integer types.");
|
||||
#endif
|
||||
}
|
||||
|
||||
void tst_QHashFunctions::floatingPointConsistency_data()
|
||||
{
|
||||
QTest::addColumn<double>("value");
|
||||
|
|
|
|||
Loading…
Reference in New Issue