mirror of
https://github.com/pocketpy/pocketpy
synced 2025-10-20 03:20:18 +00:00
add cpy310_tuplehash
This commit is contained in:
parent
63f2198ed1
commit
b03feb0294
@ -1,6 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
#define c11__less(a, b) ((a) < (b))
|
#define c11__less(a, b) ((a) < (b))
|
||||||
|
|
||||||
@ -38,3 +39,5 @@ bool c11__stable_sort(void* ptr,
|
|||||||
int elem_size,
|
int elem_size,
|
||||||
int (*f_lt)(const void* a, const void* b, void* extra),
|
int (*f_lt)(const void* a, const void* b, void* extra),
|
||||||
void* extra);
|
void* extra);
|
||||||
|
|
||||||
|
uint64_t cpy310_tuplehash(uint64_t* p, int len);
|
@ -54,3 +54,42 @@ bool c11__stable_sort(void* ptr_,
|
|||||||
free(tmp);
|
free(tmp);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Hash Functions */
|
||||||
|
|
||||||
|
// https://github.com/python/cpython/blob/v3.10.15/Objects/tupleobject.c#L406
|
||||||
|
#define SIZEOF_PY_UHASH_T 8
|
||||||
|
typedef uint64_t Py_uhash_t;
|
||||||
|
|
||||||
|
#if SIZEOF_PY_UHASH_T > 4
|
||||||
|
#define _PyHASH_XXPRIME_1 ((Py_uhash_t)11400714785074694791ULL)
|
||||||
|
#define _PyHASH_XXPRIME_2 ((Py_uhash_t)14029467366897019727ULL)
|
||||||
|
#define _PyHASH_XXPRIME_5 ((Py_uhash_t)2870177450012600261ULL)
|
||||||
|
#define _PyHASH_XXROTATE(x) ((x << 31) | (x >> 33)) /* Rotate left 31 bits */
|
||||||
|
#else
|
||||||
|
#define _PyHASH_XXPRIME_1 ((Py_uhash_t)2654435761UL)
|
||||||
|
#define _PyHASH_XXPRIME_2 ((Py_uhash_t)2246822519UL)
|
||||||
|
#define _PyHASH_XXPRIME_5 ((Py_uhash_t)374761393UL)
|
||||||
|
#define _PyHASH_XXROTATE(x) ((x << 13) | (x >> 19)) /* Rotate left 13 bits */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
uint64_t cpy310_tuplehash(uint64_t* p, int len){
|
||||||
|
Py_uhash_t acc = _PyHASH_XXPRIME_5;
|
||||||
|
for (int i = 0; i < len; i++) {
|
||||||
|
Py_uhash_t lane = p[i];
|
||||||
|
if (lane == (Py_uhash_t)-1) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
acc += lane * _PyHASH_XXPRIME_2;
|
||||||
|
acc = _PyHASH_XXROTATE(acc);
|
||||||
|
acc *= _PyHASH_XXPRIME_1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Add input length, mangled to keep the historical value of hash(()). */
|
||||||
|
acc += len ^ (_PyHASH_XXPRIME_5 ^ 3527539UL);
|
||||||
|
|
||||||
|
if (acc == (Py_uhash_t)-1) {
|
||||||
|
return 1546275796;
|
||||||
|
}
|
||||||
|
return acc;
|
||||||
|
}
|
||||||
|
@ -306,7 +306,8 @@ DEF_VECTOR_INT_OPS(3)
|
|||||||
static bool vec2i__hash__(int argc, py_Ref argv) {
|
static bool vec2i__hash__(int argc, py_Ref argv) {
|
||||||
PY_CHECK_ARGC(1);
|
PY_CHECK_ARGC(1);
|
||||||
c11_vec2i v = py_tovec2i(argv);
|
c11_vec2i v = py_tovec2i(argv);
|
||||||
uint64_t hash = ((uint64_t)v.x << 32) | (uint64_t)v.y;
|
uint64_t values[2] = {v.x, v.y};
|
||||||
|
uint64_t hash = cpy310_tuplehash(values, 2);
|
||||||
py_newint(py_retval(), (py_i64)hash);
|
py_newint(py_retval(), (py_i64)hash);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -314,10 +315,8 @@ static bool vec2i__hash__(int argc, py_Ref argv) {
|
|||||||
static bool vec3i__hash__(int argc, py_Ref argv) {
|
static bool vec3i__hash__(int argc, py_Ref argv) {
|
||||||
PY_CHECK_ARGC(1);
|
PY_CHECK_ARGC(1);
|
||||||
c11_vec3i v = py_tovec3i(argv);
|
c11_vec3i v = py_tovec3i(argv);
|
||||||
uint64_t x_part = (uint64_t)(v.x & 0xFFFFFF);
|
uint64_t values[3] = {v.x, v.y, v.z};
|
||||||
uint64_t y_part = (uint64_t)(v.y & 0xFFFFFF);
|
uint64_t hash = cpy310_tuplehash(values, 3);
|
||||||
uint64_t z_part = (uint64_t)(v.z & 0xFFFF);
|
|
||||||
uint64_t hash = (x_part << 40) | (y_part << 16) | z_part;
|
|
||||||
py_newint(py_retval(), (py_i64)hash);
|
py_newint(py_retval(), (py_i64)hash);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -155,14 +155,19 @@ static bool tuple__hash__(int argc, py_Ref argv) {
|
|||||||
PY_CHECK_ARGC(1);
|
PY_CHECK_ARGC(1);
|
||||||
int length = py_tuple_len(argv);
|
int length = py_tuple_len(argv);
|
||||||
py_TValue* data = py_tuple_data(argv);
|
py_TValue* data = py_tuple_data(argv);
|
||||||
uint64_t x = 1000003;
|
uint64_t __buffer[8];
|
||||||
|
uint64_t* p = length <= 8 ? __buffer : malloc(sizeof(uint64_t) * length);
|
||||||
for(int i = 0; i < length; i++) {
|
for(int i = 0; i < length; i++) {
|
||||||
py_i64 y;
|
py_i64 x;
|
||||||
if(!py_hash(&data[i], &y)) return false;
|
if(!py_hash(&data[i], &x)) {
|
||||||
// recommended by Github Copilot
|
if(p != __buffer) free(p);
|
||||||
x = x ^ (y + 0x9e3779b9 + (x << 6) + (x >> 2));
|
return false;
|
||||||
|
}
|
||||||
|
p[i] = x;
|
||||||
}
|
}
|
||||||
py_newint(py_retval(), x);
|
uint64_t hash = cpy310_tuplehash(p, length);
|
||||||
|
if(p != __buffer) free(p);
|
||||||
|
py_newint(py_retval(), (py_i64)hash);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user