|
1 | 1 | use super::{PositionIterInternal, PyGenericAlias, PyStrRef, PyType, PyTypeRef};
|
2 |
| -use crate::common::{hash::PyHash, lock::PyMutex}; |
| 2 | +use crate::common::{ |
| 3 | + hash::{PyHash, PyUHash}, |
| 4 | + lock::PyMutex, |
| 5 | +}; |
3 | 6 | use crate::object::{Traverse, TraverseFn};
|
4 | 7 | use crate::{
|
5 | 8 | AsObject, Context, Py, PyObject, PyObjectRef, PyPayload, PyRef, PyResult, TryFromObject,
|
@@ -589,7 +592,38 @@ impl<T: TransmuteFromObject> ToPyObject for PyTupleTyped<T> {
|
589 | 592 | }
|
590 | 593 |
|
591 | 594 | pub(super) fn tuple_hash(elements: &[PyObjectRef], vm: &VirtualMachine) -> PyResult<PyHash> {
|
592 |
| - // TODO: See #3460 for the correct implementation. |
593 |
| - // https://github.com/RustPython/RustPython/pull/3460 |
594 |
| - crate::utils::hash_iter(elements.iter(), vm) |
| 595 | + #[cfg(target_pointer_width = "64")] |
| 596 | + const PRIME1: PyUHash = 11400714785074694791; |
| 597 | + #[cfg(target_pointer_width = "64")] |
| 598 | + const PRIME2: PyUHash = 14029467366897019727; |
| 599 | + #[cfg(target_pointer_width = "64")] |
| 600 | + const PRIME5: PyUHash = 2870177450012600261; |
| 601 | + #[cfg(target_pointer_width = "64")] |
| 602 | + const ROTATE: u32 = 31; |
| 603 | + |
| 604 | + #[cfg(target_pointer_width = "32")] |
| 605 | + const PRIME1: PyUHash = 2654435761; |
| 606 | + #[cfg(target_pointer_width = "32")] |
| 607 | + const PRIME2: PyUHash = 2246822519; |
| 608 | + #[cfg(target_pointer_width = "32")] |
| 609 | + const PRIME5: PyUHash = 374761393; |
| 610 | + #[cfg(target_pointer_width = "32")] |
| 611 | + const ROTATE: u32 = 13; |
| 612 | + |
| 613 | + let mut acc = PRIME5; |
| 614 | + let len = elements.len() as PyUHash; |
| 615 | + |
| 616 | + for val in elements { |
| 617 | + let lane = val.hash(vm)? as PyUHash; |
| 618 | + acc = acc.wrapping_add(lane.wrapping_mul(PRIME2)); |
| 619 | + acc = acc.rotate_left(ROTATE); |
| 620 | + acc = acc.wrapping_mul(PRIME1); |
| 621 | + } |
| 622 | + |
| 623 | + acc = acc.wrapping_add(len ^ (PRIME5 ^ 3527539)); |
| 624 | + |
| 625 | + if acc as PyHash == -1 { |
| 626 | + return Ok(1546275796); |
| 627 | + } |
| 628 | + Ok(acc as PyHash) |
595 | 629 | }
|
0 commit comments