Sun, 23 Nov 2025 13:15:19 +0100
optimize sorted insertion by using the infimum instead of the supremum
The reason is that the supremum returns the equal element with the smallest index, and we want the largest.
Therefore, we use the infimum, which already gives us the largest index when there are equal elements, and increase the index by one. The infimum is also guaranteed to exist in that case.
| 563 | 1 | /* |
| 2 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. | |
| 3 | * | |
| 4 | * Copyright 2021 Mike Becker, Olaf Wintermann All rights reserved. | |
| 5 | * | |
| 6 | * Redistribution and use in source and binary forms, with or without | |
| 7 | * modification, are permitted provided that the following conditions are met: | |
| 8 | * | |
| 9 | * 1. Redistributions of source code must retain the above copyright | |
| 10 | * notice, this list of conditions and the following disclaimer. | |
| 11 | * | |
| 12 | * 2. Redistributions in binary form must reproduce the above copyright | |
| 13 | * notice, this list of conditions and the following disclaimer in the | |
| 14 | * documentation and/or other materials provided with the distribution. | |
| 15 | * | |
| 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | |
| 17 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
| 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
| 19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE | |
| 20 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |
| 21 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |
| 22 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |
| 23 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |
| 24 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
| 25 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
| 26 | * POSSIBILITY OF SUCH DAMAGE. | |
| 27 | */ | |
| 28 | ||
| 29 | #include "cx/hash_key.h" | |
|
1400
7bc88ae62755
add support for integer keys - resolves #720
Mike Becker <universe@uap-core.de>
parents:
1364
diff
changeset
|
30 | #include "cx/compare.h" |
| 563 | 31 | #include <string.h> |
| 32 | ||
| 33 | void cx_hash_murmur(CxHashKey *key) { | |
|
890
54565fd74e74
move all const keywords to the west - fixes #426
Mike Becker <universe@uap-core.de>
parents:
690
diff
changeset
|
34 | const unsigned char *data = key->data; |
| 604 | 35 | if (data == NULL) { |
|
628
1e2be40f0cb5
use //-style single line comments everywhere
Mike Becker <universe@uap-core.de>
parents:
604
diff
changeset
|
36 | // extension: special value for NULL |
| 604 | 37 | key->hash = 1574210520u; |
| 38 | return; | |
| 39 | } | |
| 563 | 40 | size_t len = key->len; |
| 41 | ||
| 42 | unsigned m = 0x5bd1e995; | |
| 43 | unsigned r = 24; | |
|
949
c2ba65ea8d31
add cast from size_t to unsigned to avoid warnings from certain compilers
Mike Becker <universe@uap-core.de>
parents:
890
diff
changeset
|
44 | unsigned h = 25 ^ (unsigned) len; |
| 563 | 45 | unsigned i = 0; |
| 46 | while (len >= 4) { | |
| 47 | unsigned k = data[i + 0] & 0xFF; | |
| 48 | k |= (data[i + 1] & 0xFF) << 8; | |
| 49 | k |= (data[i + 2] & 0xFF) << 16; | |
| 50 | k |= (data[i + 3] & 0xFF) << 24; | |
| 51 | ||
| 52 | k *= m; | |
| 53 | k ^= k >> r; | |
| 54 | k *= m; | |
| 55 | ||
| 56 | h *= m; | |
| 57 | h ^= k; | |
| 58 | ||
| 59 | i += 4; | |
| 60 | len -= 4; | |
| 61 | } | |
| 62 | ||
| 63 | switch (len) { | |
| 64 | case 3: | |
| 65 | h ^= (data[i + 2] & 0xFF) << 16; | |
|
1364
556e4e7608b1
fix that the fallthrough attributes were not abstracted by the cx_attr macros
Mike Becker <universe@uap-core.de>
parents:
949
diff
changeset
|
66 | cx_attr_fallthrough; |
| 563 | 67 | case 2: |
| 68 | h ^= (data[i + 1] & 0xFF) << 8; | |
|
1364
556e4e7608b1
fix that the fallthrough attributes were not abstracted by the cx_attr macros
Mike Becker <universe@uap-core.de>
parents:
949
diff
changeset
|
69 | cx_attr_fallthrough; |
| 563 | 70 | case 1: |
| 71 | h ^= (data[i + 0] & 0xFF); | |
| 72 | h *= m; | |
|
1364
556e4e7608b1
fix that the fallthrough attributes were not abstracted by the cx_attr macros
Mike Becker <universe@uap-core.de>
parents:
949
diff
changeset
|
73 | cx_attr_fallthrough; |
|
628
1e2be40f0cb5
use //-style single line comments everywhere
Mike Becker <universe@uap-core.de>
parents:
604
diff
changeset
|
74 | default: // do nothing |
| 678 | 75 | ; |
| 563 | 76 | } |
| 77 | ||
| 78 | h ^= h >> 13; | |
| 79 | h *= m; | |
| 80 | h ^= h >> 15; | |
| 81 | ||
| 82 | key->hash = h; | |
| 83 | } | |
| 84 | ||
|
1400
7bc88ae62755
add support for integer keys - resolves #720
Mike Becker <universe@uap-core.de>
parents:
1364
diff
changeset
|
85 | |
|
7bc88ae62755
add support for integer keys - resolves #720
Mike Becker <universe@uap-core.de>
parents:
1364
diff
changeset
|
86 | uint32_t cx_hash_u32(uint32_t x) { |
|
7bc88ae62755
add support for integer keys - resolves #720
Mike Becker <universe@uap-core.de>
parents:
1364
diff
changeset
|
87 | x = ((x >> 16) ^ x) * 0x45d9f3bu; |
|
7bc88ae62755
add support for integer keys - resolves #720
Mike Becker <universe@uap-core.de>
parents:
1364
diff
changeset
|
88 | x = ((x >> 16) ^ x) * 0x45d9f3bu; |
|
7bc88ae62755
add support for integer keys - resolves #720
Mike Becker <universe@uap-core.de>
parents:
1364
diff
changeset
|
89 | x = (x >> 16) ^ x; |
|
7bc88ae62755
add support for integer keys - resolves #720
Mike Becker <universe@uap-core.de>
parents:
1364
diff
changeset
|
90 | return x; |
|
7bc88ae62755
add support for integer keys - resolves #720
Mike Becker <universe@uap-core.de>
parents:
1364
diff
changeset
|
91 | } |
|
7bc88ae62755
add support for integer keys - resolves #720
Mike Becker <universe@uap-core.de>
parents:
1364
diff
changeset
|
92 | |
|
7bc88ae62755
add support for integer keys - resolves #720
Mike Becker <universe@uap-core.de>
parents:
1364
diff
changeset
|
93 | uint64_t cx_hash_u64(uint64_t x) { |
|
7bc88ae62755
add support for integer keys - resolves #720
Mike Becker <universe@uap-core.de>
parents:
1364
diff
changeset
|
94 | x = (x ^ (x >> 30)) * UINT64_C(0xbf58476d1ce4e5b9); |
|
7bc88ae62755
add support for integer keys - resolves #720
Mike Becker <universe@uap-core.de>
parents:
1364
diff
changeset
|
95 | x = (x ^ (x >> 27)) * UINT64_C(0x94d049bb133111eb); |
|
7bc88ae62755
add support for integer keys - resolves #720
Mike Becker <universe@uap-core.de>
parents:
1364
diff
changeset
|
96 | x = x ^ (x >> 31); |
|
7bc88ae62755
add support for integer keys - resolves #720
Mike Becker <universe@uap-core.de>
parents:
1364
diff
changeset
|
97 | return x; |
|
7bc88ae62755
add support for integer keys - resolves #720
Mike Becker <universe@uap-core.de>
parents:
1364
diff
changeset
|
98 | } |
|
7bc88ae62755
add support for integer keys - resolves #720
Mike Becker <universe@uap-core.de>
parents:
1364
diff
changeset
|
99 | |
|
890
54565fd74e74
move all const keywords to the west - fixes #426
Mike Becker <universe@uap-core.de>
parents:
690
diff
changeset
|
100 | CxHashKey cx_hash_key_str(const char *str) { |
| 563 | 101 | CxHashKey key; |
| 690 | 102 | key.data = str; |
| 604 | 103 | key.len = str == NULL ? 0 : strlen(str); |
| 563 | 104 | cx_hash_murmur(&key); |
| 105 | return key; | |
| 106 | } | |
| 107 | ||
|
1426
3a89b31f0724
clean up header files and adds support for comparing arbitrary strings with string.h functions
Mike Becker <universe@uap-core.de>
parents:
1400
diff
changeset
|
108 | CxHashKey cx_hash_key_ustr(unsigned const char *str) { |
|
3a89b31f0724
clean up header files and adds support for comparing arbitrary strings with string.h functions
Mike Becker <universe@uap-core.de>
parents:
1400
diff
changeset
|
109 | CxHashKey key; |
|
3a89b31f0724
clean up header files and adds support for comparing arbitrary strings with string.h functions
Mike Becker <universe@uap-core.de>
parents:
1400
diff
changeset
|
110 | key.data = str; |
|
3a89b31f0724
clean up header files and adds support for comparing arbitrary strings with string.h functions
Mike Becker <universe@uap-core.de>
parents:
1400
diff
changeset
|
111 | key.len = str == NULL ? 0 : strlen((const char*)str); |
|
3a89b31f0724
clean up header files and adds support for comparing arbitrary strings with string.h functions
Mike Becker <universe@uap-core.de>
parents:
1400
diff
changeset
|
112 | cx_hash_murmur(&key); |
|
3a89b31f0724
clean up header files and adds support for comparing arbitrary strings with string.h functions
Mike Becker <universe@uap-core.de>
parents:
1400
diff
changeset
|
113 | return key; |
|
3a89b31f0724
clean up header files and adds support for comparing arbitrary strings with string.h functions
Mike Becker <universe@uap-core.de>
parents:
1400
diff
changeset
|
114 | } |
|
3a89b31f0724
clean up header files and adds support for comparing arbitrary strings with string.h functions
Mike Becker <universe@uap-core.de>
parents:
1400
diff
changeset
|
115 | |
|
3a89b31f0724
clean up header files and adds support for comparing arbitrary strings with string.h functions
Mike Becker <universe@uap-core.de>
parents:
1400
diff
changeset
|
116 | CxHashKey cx_hash_key_cxstr(cxstring str) { |
|
3a89b31f0724
clean up header files and adds support for comparing arbitrary strings with string.h functions
Mike Becker <universe@uap-core.de>
parents:
1400
diff
changeset
|
117 | return cx_hash_key(str.ptr, str.length); |
|
3a89b31f0724
clean up header files and adds support for comparing arbitrary strings with string.h functions
Mike Becker <universe@uap-core.de>
parents:
1400
diff
changeset
|
118 | } |
|
3a89b31f0724
clean up header files and adds support for comparing arbitrary strings with string.h functions
Mike Becker <universe@uap-core.de>
parents:
1400
diff
changeset
|
119 | |
|
3a89b31f0724
clean up header files and adds support for comparing arbitrary strings with string.h functions
Mike Becker <universe@uap-core.de>
parents:
1400
diff
changeset
|
120 | CxHashKey cx_hash_key_mutstr(cxmutstr str) { |
|
3a89b31f0724
clean up header files and adds support for comparing arbitrary strings with string.h functions
Mike Becker <universe@uap-core.de>
parents:
1400
diff
changeset
|
121 | return cx_hash_key(str.ptr, str.length); |
|
3a89b31f0724
clean up header files and adds support for comparing arbitrary strings with string.h functions
Mike Becker <universe@uap-core.de>
parents:
1400
diff
changeset
|
122 | } |
|
3a89b31f0724
clean up header files and adds support for comparing arbitrary strings with string.h functions
Mike Becker <universe@uap-core.de>
parents:
1400
diff
changeset
|
123 | |
| 563 | 124 | CxHashKey cx_hash_key_bytes( |
|
890
54565fd74e74
move all const keywords to the west - fixes #426
Mike Becker <universe@uap-core.de>
parents:
690
diff
changeset
|
125 | const unsigned char *bytes, |
| 563 | 126 | size_t len |
| 127 | ) { | |
| 128 | CxHashKey key; | |
| 690 | 129 | key.data = bytes; |
| 563 | 130 | key.len = len; |
| 131 | cx_hash_murmur(&key); | |
| 132 | return key; | |
| 133 | } | |
| 134 | ||
| 135 | CxHashKey cx_hash_key( | |
|
890
54565fd74e74
move all const keywords to the west - fixes #426
Mike Becker <universe@uap-core.de>
parents:
690
diff
changeset
|
136 | const void *obj, |
| 563 | 137 | size_t len |
| 138 | ) { | |
| 139 | CxHashKey key; | |
| 690 | 140 | key.data = obj; |
| 563 | 141 | key.len = len; |
| 142 | cx_hash_murmur(&key); | |
| 143 | return key; | |
| 144 | } | |
|
1400
7bc88ae62755
add support for integer keys - resolves #720
Mike Becker <universe@uap-core.de>
parents:
1364
diff
changeset
|
145 | |
|
7bc88ae62755
add support for integer keys - resolves #720
Mike Becker <universe@uap-core.de>
parents:
1364
diff
changeset
|
146 | CxHashKey cx_hash_key_u32(uint32_t x) { |
|
7bc88ae62755
add support for integer keys - resolves #720
Mike Becker <universe@uap-core.de>
parents:
1364
diff
changeset
|
147 | CxHashKey key; |
|
7bc88ae62755
add support for integer keys - resolves #720
Mike Becker <universe@uap-core.de>
parents:
1364
diff
changeset
|
148 | key.data = NULL; |
|
7bc88ae62755
add support for integer keys - resolves #720
Mike Becker <universe@uap-core.de>
parents:
1364
diff
changeset
|
149 | key.len = 0; |
|
7bc88ae62755
add support for integer keys - resolves #720
Mike Becker <universe@uap-core.de>
parents:
1364
diff
changeset
|
150 | key.hash = cx_hash_u32(x); |
|
7bc88ae62755
add support for integer keys - resolves #720
Mike Becker <universe@uap-core.de>
parents:
1364
diff
changeset
|
151 | return key; |
|
7bc88ae62755
add support for integer keys - resolves #720
Mike Becker <universe@uap-core.de>
parents:
1364
diff
changeset
|
152 | } |
|
7bc88ae62755
add support for integer keys - resolves #720
Mike Becker <universe@uap-core.de>
parents:
1364
diff
changeset
|
153 | |
|
7bc88ae62755
add support for integer keys - resolves #720
Mike Becker <universe@uap-core.de>
parents:
1364
diff
changeset
|
154 | CxHashKey cx_hash_key_u64(uint64_t x) { |
|
7bc88ae62755
add support for integer keys - resolves #720
Mike Becker <universe@uap-core.de>
parents:
1364
diff
changeset
|
155 | CxHashKey key; |
|
7bc88ae62755
add support for integer keys - resolves #720
Mike Becker <universe@uap-core.de>
parents:
1364
diff
changeset
|
156 | key.data = NULL; |
|
7bc88ae62755
add support for integer keys - resolves #720
Mike Becker <universe@uap-core.de>
parents:
1364
diff
changeset
|
157 | key.len = 0; |
|
7bc88ae62755
add support for integer keys - resolves #720
Mike Becker <universe@uap-core.de>
parents:
1364
diff
changeset
|
158 | key.hash = cx_hash_u64(x); |
|
7bc88ae62755
add support for integer keys - resolves #720
Mike Becker <universe@uap-core.de>
parents:
1364
diff
changeset
|
159 | return key; |
|
7bc88ae62755
add support for integer keys - resolves #720
Mike Becker <universe@uap-core.de>
parents:
1364
diff
changeset
|
160 | } |
|
7bc88ae62755
add support for integer keys - resolves #720
Mike Becker <universe@uap-core.de>
parents:
1364
diff
changeset
|
161 | |
|
1448
0f0fe7311b76
add tests for cxMapDifference() and cxMapListDifference()
Mike Becker <universe@uap-core.de>
parents:
1426
diff
changeset
|
162 | int cx_hash_key_cmp(const void *l, const void *r) { |
|
0f0fe7311b76
add tests for cxMapDifference() and cxMapListDifference()
Mike Becker <universe@uap-core.de>
parents:
1426
diff
changeset
|
163 | const CxHashKey *left = l; |
|
0f0fe7311b76
add tests for cxMapDifference() and cxMapListDifference()
Mike Becker <universe@uap-core.de>
parents:
1426
diff
changeset
|
164 | const CxHashKey *right = r; |
|
1400
7bc88ae62755
add support for integer keys - resolves #720
Mike Becker <universe@uap-core.de>
parents:
1364
diff
changeset
|
165 | int d; |
|
7bc88ae62755
add support for integer keys - resolves #720
Mike Becker <universe@uap-core.de>
parents:
1364
diff
changeset
|
166 | d = cx_vcmp_uint64(left->hash, right->hash); |
|
7bc88ae62755
add support for integer keys - resolves #720
Mike Becker <universe@uap-core.de>
parents:
1364
diff
changeset
|
167 | if (d != 0) return d; |
|
7bc88ae62755
add support for integer keys - resolves #720
Mike Becker <universe@uap-core.de>
parents:
1364
diff
changeset
|
168 | d = cx_vcmp_size(left->len, right->len); |
|
7bc88ae62755
add support for integer keys - resolves #720
Mike Becker <universe@uap-core.de>
parents:
1364
diff
changeset
|
169 | if (d != 0) return d; |
|
7bc88ae62755
add support for integer keys - resolves #720
Mike Becker <universe@uap-core.de>
parents:
1364
diff
changeset
|
170 | if (left->len == 0) return 0; |
|
7bc88ae62755
add support for integer keys - resolves #720
Mike Becker <universe@uap-core.de>
parents:
1364
diff
changeset
|
171 | return memcmp(left->data, right->data, left->len); |
|
7bc88ae62755
add support for integer keys - resolves #720
Mike Becker <universe@uap-core.de>
parents:
1364
diff
changeset
|
172 | } |