hash.cpp (1655B)
1 #include "all_includes.hh" 2 3 int random_seed() { 4 static bool initialized = false; 5 if (!initialized) { 6 initialized = true; 7 srand(time(NULL)); 8 } 9 return rand(); 10 } 11 12 // Ce hash donne des bons résultats sur tous les bits de l'entier 13 // généré (pas d'artefacts, répartition homogène des 0 et des 1). 14 unsigned int hash2(unsigned int a, unsigned int b) { 15 unsigned int h = 1; 16 int i; 17 for (i = 0; i < 32; i+=8) { 18 a = a*h + 1; 19 b = b*h + 1; 20 // marche aussi avec 65521. 21 h = (h << 6) + (h << 16) - h + ((a >> i) & 0xff); // h * 65599 + ieme octet de a 22 h = (h << 6) + (h << 16) - h + ((b >> i) & 0xff); // h * 65599 + ieme octet de b 23 } 24 return h; 25 } 26 27 float floatInRange(int seed, int n, float a, float b) { 28 // 24 bits de précision, ça devrait suffire pour la plupart des utilisations. 29 return (float)(hash2(seed, n) & 0xffffff) / (float)(0x1000000) * (b-a) + a; 30 } 31 32 bool proba(int seed, int n, float proba) { 33 return floatInRange(seed, n, 0, 1) < proba; 34 } 35 36 unsigned int float2uint(float f) { 37 // TODO : il y a plein de problèmes avec cette conversion : 38 // 1) Il y a plusieurs représentations possibles pour le même float, 39 // donc si on re-split un objet 10 minutes après et qu'on n'a pas 40 // la même représentation, on n'aura pas la même entropie pour les hash. 41 // 2) On ne peut pas faire juste fi.f = f; return fi.ui; car si 42 // sizeof(int) > sizeof(float), on lira des saletés. 43 // 3) De toute façon, tout ça est principalement du "undefined behaviour". 44 FloatUIntUnion fi; 45 for (unsigned int i = 0; i < sizeof(fi); i++) { 46 // effacer la structure. 47 reinterpret_cast<char*>(&fi)[i] = 0; 48 } 49 fi.f = f; 50 return fi.ui; 51 }