Skip to content

Commit 37b47b0

Browse files
Fix: uint32_t to uint40_t cast (#404)
Co-authored-by: Ash Vardanian <1983160+ashvardanian@users.noreply.github.com>
1 parent 30a490b commit 37b47b0

File tree

2 files changed

+36
-2
lines changed

2 files changed

+36
-2
lines changed

cpp/test.cpp

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,39 @@ template <typename index_at> struct aligned_wrapper_gt {
5757
}
5858
};
5959

60+
/**
61+
* Tests the functionality of the custom uint40_t type ensuring consistent
62+
* behavior across various constructors from uint32_t, uint64_t, and size_t types.
63+
*/
64+
void test_uint40() {
65+
// Constants for tests
66+
std::uint64_t max_uint40_k = (1ULL << 40) - 1;
67+
68+
for (std::uint64_t original_value : {
69+
42ull, // Typical small number
70+
4242ull, // Larger number still within uint40 range
71+
1ull << 40, // Exactly at the boundary of uint40
72+
(1ull << 40) + 1, // Just beyond the boundary of uint40
73+
1ull << 63 // Well beyond the uint40 boundary, tests masking
74+
}) {
75+
std::uint32_t v_32 = static_cast<std::uint32_t>(original_value);
76+
std::uint64_t v_64 = original_value;
77+
std::size_t v_size = static_cast<std::size_t>(original_value);
78+
79+
// Create uint40_t instances from different types
80+
uint40_t n_40_from_32(v_32);
81+
uint40_t n_40_from_64(v_64);
82+
uint40_t n_40_from_size(v_size);
83+
84+
// Expected value after masking
85+
std::uint64_t expected_value = original_value & max_uint40_k;
86+
87+
// Check if all conversions are equal to the masked value
88+
expect(n_40_from_32 == expected_value);
89+
expect(n_40_from_64 == expected_value);
90+
expect(n_40_from_size == expected_value);
91+
}
92+
}
6093
/**
6194
* Tests the behavior of various move-constructors and move-assignment operators for the index.
6295
*
@@ -700,6 +733,7 @@ template <typename key_at, typename slot_at> void test_replacing_update() {
700733
}
701734

702735
int main(int, char**) {
736+
test_uint40();
703737

704738
// Weird corner cases
705739
test_replacing_update<std::int64_t, std::uint32_t>();

include/usearch/index.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -785,7 +785,7 @@ class usearch_pack_m uint40_t {
785785

786786
public:
787787
inline uint40_t() noexcept { broadcast(0); }
788-
inline uint40_t(std::uint32_t n) noexcept { std::memcpy(&octets[1], &n, 4); }
788+
inline uint40_t(std::uint32_t n) noexcept { std::memcpy(&octets, &n, 4); }
789789

790790
#ifdef USEARCH_64BIT_ENV
791791
inline uint40_t(std::uint64_t n) noexcept { std::memcpy(octets, &n, 5); }
@@ -811,7 +811,7 @@ class usearch_pack_m uint40_t {
811811
#ifdef USEARCH_64BIT_ENV
812812
std::memcpy(&result, octets, 5);
813813
#else
814-
std::memcpy(&result, octets + 1, 4);
814+
std::memcpy(&result, octets, 4);
815815
#endif
816816
return result;
817817
}

0 commit comments

Comments
 (0)