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