Skip to content

Commit b65ec83

Browse files
committed
New type hashing
Fixes an error where different hashes were obtained in different libraries, see also: pybind/pybind11#915
1 parent 93768c1 commit b65ec83

File tree

2 files changed

+31
-10
lines changed

2 files changed

+31
-10
lines changed

include/jlcxx/jlcxx_config.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@
1414
#endif
1515

1616
#define JLCXX_VERSION_MAJOR 0
17-
#define JLCXX_VERSION_MINOR 12
18-
#define JLCXX_VERSION_PATCH 5
17+
#define JLCXX_VERSION_MINOR 13
18+
#define JLCXX_VERSION_PATCH 0
1919

2020
// From https://stackoverflow.com/questions/5459868/concatenate-int-to-string-using-c-preprocessor
2121
#define __JLCXX_STR_HELPER(x) #x

include/jlcxx/type_conversion.hpp

Lines changed: 29 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -349,7 +349,28 @@ struct CachedDatatype
349349
};
350350

351351
// Work around the fact that references aren't part of the typeid result
352-
using type_hash_t = std::pair<std::type_index, std::size_t>;
352+
using type_hash_t = std::pair<std::size_t, std::size_t>;
353+
354+
namespace detail
355+
{
356+
// See http://www.cse.yorku.ca/~oz/hash.html
357+
inline std::size_t djb2_hash(const char* str)
358+
{
359+
std::size_t hash = 5381;
360+
while(auto c = static_cast<unsigned char>(*str++))
361+
{
362+
hash = ((hash << 5) + hash) ^ c; /* hash * 33 ^ c */
363+
}
364+
365+
return hash;
366+
}
367+
368+
template<typename T>
369+
inline std::size_t type_hash()
370+
{
371+
return djb2_hash(typeid(T).name());
372+
}
373+
}
353374

354375
} // namespace jlcxx
355376

@@ -361,7 +382,7 @@ struct hash<jlcxx::type_hash_t>
361382
{
362383
std::size_t operator()(const jlcxx::type_hash_t& h) const noexcept
363384
{
364-
std::size_t h1 = std::hash<std::type_index>{}(h.first);
385+
std::size_t h1 = std::hash<std::size_t>{}(h.first);
365386
std::size_t h2 = std::hash<std::size_t>{}(h.second);
366387
return h1 ^ (h2 << 1);
367388
}
@@ -380,7 +401,7 @@ struct TypeHash
380401
{
381402
static inline type_hash_t value()
382403
{
383-
return std::make_pair(std::type_index(typeid(T)), std::size_t(0));
404+
return std::make_pair(detail::type_hash<T>(), std::size_t(0));
384405
}
385406
};
386407

@@ -389,7 +410,7 @@ struct TypeHash<T&>
389410
{
390411
static inline type_hash_t value()
391412
{
392-
return std::make_pair(std::type_index(typeid(T)), std::size_t(1));
413+
return std::make_pair(detail::type_hash<T>(), std::size_t(1));
393414
}
394415
};
395416

@@ -398,7 +419,7 @@ struct TypeHash<const T&>
398419
{
399420
static inline type_hash_t value()
400421
{
401-
return std::make_pair(std::type_index(typeid(T)), std::size_t(2));
422+
return std::make_pair(detail::type_hash<T>(), std::size_t(2));
402423
}
403424
};
404425

@@ -435,9 +456,9 @@ class JuliaTypeCache
435456
if(!insert_success)
436457
{
437458
type_hash_t old_hash = inserted_it->first;
438-
std::cout << "Warning: Type " << new_hash.first.name() << " already had a mapped type set as "
439-
<< julia_type_name(inserted_it->second.get_dt()) << " and const-ref indicator " << old_hash.second << " and C++ type name " << old_hash.first.name()
440-
<< ". Hash comparison: old(" << old_hash.first.hash_code() << "," << old_hash.second << ") == new(" << old_hash.first.hash_code() << "," << old_hash.second << ") == "
459+
std::cout << "Warning: Type " << typeid(SourceT).name() << " already had a mapped type set as "
460+
<< julia_type_name(inserted_it->second.get_dt()) << " and const-ref indicator " << old_hash.second
461+
<< ". Hash comparison: old(" << old_hash.first << "," << old_hash.second << ") == new(" << old_hash.first << "," << old_hash.second << ") == "
441462
<< std::boolalpha << (old_hash == new_hash) << std::endl;
442463
return;
443464
}

0 commit comments

Comments
 (0)