32b057fba4671090624e81432ed9b7d44bbda447
[ginac.git] / ginac / hash_seed.h
1 #ifndef GINAC_HASH_SEED_H
2 #define GINAC_HASH_SEED_H
3 /**
4  * We need a hash function which gives different values for objects of
5  * different types. Hence we need some unique integer for each type.
6  * Fortunately, standard C++ RTTI class `type_info' stores a pointer to
7  * mangled type name. Normally this pointer is the same for all objects
8  * of the same type (although it changes from run to run), so it can be
9  * used for computing hashes. However, on some platforms (such as woe32)
10  * the pointer returned by type_info::name() might be different even for
11  * objects of the same type! Hence we need to resort to comparing string
12  * representation of the (mangled) type names. This is quite expensive,
13  * so we compare crc32 hashes of those strings. We might got more hash
14  * collisions (and slower evaluation as a result), but being a bit slower
15  * is much better than being wrong.
16  */
17 #include <typeinfo>
18 #include <cstring>
19 #include "crc32.h"
20 #include "utils.h"
21 #ifdef _WIN32
22 #define GINAC_HASH_USE_MANGLED_NAME 1
23 #endif
24 namespace GiNaC
25 {
26 #ifndef GINAC_HASH_USE_MANGLED_NAME
27 static inline unsigned make_hash_seed(const std::type_info& tinfo)
28 {
29         // this pointer is the same for all objects of the same type.
30         // Hence we can use that pointer 
31         const void* mangled_name_ptr = (const void*)tinfo.name();
32         unsigned v = golden_ratio_hash((p_int)mangled_name_ptr);
33         return v;
34 }
35 #else
36 static unsigned make_hash_seed(const std::type_info& tinfo)
37 {
38         const char* mangled_name = tinfo.name();
39         return crc32(mangled_name, std::strlen(mangled_name), 0);
40 }
41 #endif
42 } // namespace GiNaC
43 #endif /* GINAC_HASH_SEED_H */
44
45