|
1 | 1 | use once_cell::sync::Lazy;
|
2 | 2 |
|
3 | 3 | use super::{PositionIterInternal, PyGenericAlias, PyType, PyTypeRef};
|
4 |
| -use crate::common::{hash::PyHash, lock::PyMutex}; |
| 4 | +use crate::common::{ |
| 5 | + hash::{PyHash, PyUHash}, |
| 6 | + lock::PyMutex, |
| 7 | +}; |
5 | 8 | use crate::{
|
6 | 9 | atomic_func,
|
7 | 10 | class::PyClassImpl,
|
@@ -525,7 +528,38 @@ impl<T: TransmuteFromObject> ToPyObject for PyTupleTyped<T> {
|
525 | 528 | }
|
526 | 529 |
|
527 | 530 | pub(super) fn tuple_hash(elements: &[PyObjectRef], vm: &VirtualMachine) -> PyResult<PyHash> {
|
528 |
| - // TODO: See #3460 for the correct implementation. |
529 |
| - // https://github.com/RustPython/RustPython/pull/3460 |
530 |
| - crate::utils::hash_iter(elements.iter(), vm) |
| 531 | + #[cfg(target_pointer_width = "64")] |
| 532 | + const PRIME1: PyUHash = 11400714785074694791; |
| 533 | + #[cfg(target_pointer_width = "64")] |
| 534 | + const PRIME2: PyUHash = 14029467366897019727; |
| 535 | + #[cfg(target_pointer_width = "64")] |
| 536 | + const PRIME5: PyUHash = 2870177450012600261; |
| 537 | + #[cfg(target_pointer_width = "64")] |
| 538 | + const ROTATE: u32 = 31; |
| 539 | + |
| 540 | + #[cfg(target_pointer_width = "32")] |
| 541 | + const PRIME1: PyUHash = 2654435761; |
| 542 | + #[cfg(target_pointer_width = "32")] |
| 543 | + const PRIME2: PyUHash = 2246822519; |
| 544 | + #[cfg(target_pointer_width = "32")] |
| 545 | + const PRIME5: PyUHash = 374761393; |
| 546 | + #[cfg(target_pointer_width = "32")] |
| 547 | + const ROTATE: u32 = 13; |
| 548 | + |
| 549 | + let mut acc = PRIME5; |
| 550 | + let len = elements.len() as PyUHash; |
| 551 | + |
| 552 | + for val in elements { |
| 553 | + let lane = val.hash(vm)? as PyUHash; |
| 554 | + acc = acc.wrapping_add(lane.wrapping_mul(PRIME2)); |
| 555 | + acc = acc.rotate_left(ROTATE); |
| 556 | + acc = acc.wrapping_mul(PRIME1); |
| 557 | + } |
| 558 | + |
| 559 | + acc = acc.wrapping_add(len ^ (PRIME5 ^ 3527539)); |
| 560 | + |
| 561 | + if acc as PyHash == -1 { |
| 562 | + return Ok(1546275796); |
| 563 | + } |
| 564 | + Ok(acc as PyHash) |
531 | 565 | }
|
0 commit comments