diff options
| author | Paul Eggert | 2024-05-19 08:42:57 -0700 |
|---|---|---|
| committer | Paul Eggert | 2024-05-19 08:58:14 -0700 |
| commit | 9bcd644408367b1d57e62a7f73b4ef4a3cd366b4 (patch) | |
| tree | 3872ce5db729ba26cd747bece714e6a2a1302ce7 /src/lisp.h | |
| parent | c07160b8df4e9f795dd73f08a3399ccef465c898 (diff) | |
| download | emacs-9bcd644408367b1d57e62a7f73b4ef4a3cd366b4.tar.gz emacs-9bcd644408367b1d57e62a7f73b4ef4a3cd366b4.zip | |
Port knuth_hash to odd platforms
* src/lisp.h (hash_hash_t, knuth_hash): Use unsigned int and
unsigned long long int rather than uint32_t and uint64_t, as POSIX
does not guarantee the presence of uint64_t, and uint32_t and
uint64_t both in theory have problems with undefined behavior on
integer overflow. This doesn’t affect behavior (or even machine
code) on typical platforms.
Diffstat (limited to 'src/lisp.h')
| -rw-r--r-- | src/lisp.h | 14 |
1 files changed, 9 insertions, 5 deletions
diff --git a/src/lisp.h b/src/lisp.h index d61a4d5c982..4b4ff2a2c60 100644 --- a/src/lisp.h +++ b/src/lisp.h | |||
| @@ -2534,7 +2534,7 @@ struct Lisp_Hash_Table; | |||
| 2534 | 2534 | ||
| 2535 | /* The type of a hash value stored in the table. | 2535 | /* The type of a hash value stored in the table. |
| 2536 | It's unsigned and a subtype of EMACS_UINT. */ | 2536 | It's unsigned and a subtype of EMACS_UINT. */ |
| 2537 | typedef uint32_t hash_hash_t; | 2537 | typedef unsigned int hash_hash_t; |
| 2538 | 2538 | ||
| 2539 | typedef enum { | 2539 | typedef enum { |
| 2540 | Test_eql, | 2540 | Test_eql, |
| @@ -2818,10 +2818,14 @@ INLINE ptrdiff_t | |||
| 2818 | knuth_hash (hash_hash_t hash, unsigned bits) | 2818 | knuth_hash (hash_hash_t hash, unsigned bits) |
| 2819 | { | 2819 | { |
| 2820 | /* Knuth multiplicative hashing, tailored for 32-bit indices | 2820 | /* Knuth multiplicative hashing, tailored for 32-bit indices |
| 2821 | (avoiding a 64-bit multiply). */ | 2821 | (avoiding a 64-bit multiply on typical platforms). */ |
| 2822 | uint32_t alpha = 2654435769; /* 2**32/phi */ | 2822 | unsigned int h = hash; |
| 2823 | /* Note the cast to uint64_t, to make it work for bits=0. */ | 2823 | unsigned int alpha = 2654435769; /* 2**32/phi */ |
| 2824 | return (uint64_t)((uint32_t)hash * alpha) >> (32 - bits); | 2824 | /* Multiply with unsigned int, ANDing in case UINT_WIDTH exceeds 32. */ |
| 2825 | unsigned int product = (h * alpha) & 0xffffffffu; | ||
| 2826 | /* Convert to a wider type, so that the shift works when BITS == 0. */ | ||
| 2827 | unsigned long long int wide_product = product; | ||
| 2828 | return wide_product >> (32 - bits); | ||
| 2825 | } | 2829 | } |
| 2826 | 2830 | ||
| 2827 | 2831 | ||