I\'ve read in other posts that this seems to be the best way to combine hash-values. Could somebody please break this down and explain why this is the best way to do it?
ROTL For VS studio (you can deduce ROTR easily). (This is actually in reply to @WolfgangBrehm.)
Reason: the standard trick to induce the compiler to emit ror and/or rol instructions gives an error in VS: error C4146: unary minus operator applied to unsigned type, result still unsigned.
So... I solved the compiler error by replacing (-c) by (T(0) -c) but that is not going to be optimized.
Adding (MS specific) specialisations solves that as inspection of the emitted optimised assembly will show.
#include // and some more includes, see above...
template // default template is not good for optimisation
typename std::enable_if::value, T>::type
constexpr rotl(const T n, const int i)
{
constexpr T m = (std::numeric_limits::digits - 1);
const T c = i & m;
//return (n << c) | (n >> (-c) & m);
return (n << c) | (n >> (T(0) - c) & m);
}
template<>
inline uint32_t rotl(const uint32_t n, const int i)
{
constexpr int m = (std::numeric_limits::digits - 1);
const int c = i & m;
return _rotl(n, c);
}
template<>
inline uchar rotl(const uchar n, const int i)
{
constexpr uchar m = (std::numeric_limits::digits - 1);
const uchar c = i & m;
return _rotl8(n, c);
}
template<>
inline ushort rotl(const ushort n, const int i)
{
constexpr uchar m = (std::numeric_limits::digits - 1);
const uchar c = i & m;
return _rotl16(n, c);
}
template<>
inline uint64_t rotl(const uint64_t n, const int i)
{
constexpr int m = (std::numeric_limits::digits - 1);
const int c = i & m;
return _rotl64(n, c);
}