|
1 | 1 | use super::{PositionIterInternal, PyGenericAlias, 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::{
|
4 | 7 | class::PyClassImpl,
|
5 | 8 | convert::{ToPyObject, TransmuteFromObject},
|
@@ -371,7 +374,7 @@ impl AsSequence for PyTuple {
|
371 | 374 | impl Hashable for PyTuple {
|
372 | 375 | #[inline]
|
373 | 376 | fn hash(zelf: &crate::Py<Self>, vm: &VirtualMachine) -> PyResult<PyHash> {
|
374 |
| - crate::utils::hash_iter(zelf.elements.iter(), vm) |
| 377 | + tuple_hash(zelf.as_slice(), vm) |
375 | 378 | }
|
376 | 379 | }
|
377 | 380 |
|
@@ -522,3 +525,40 @@ impl<T: TransmuteFromObject> ToPyObject for PyTupleTyped<T> {
|
522 | 525 | self.tuple.into()
|
523 | 526 | }
|
524 | 527 | }
|
| 528 | + |
| 529 | +pub fn tuple_hash(elements: &[PyObjectRef], vm: &VirtualMachine) -> PyResult<PyHash> { |
| 530 | + #[cfg(target_pointer_width = "64")] |
| 531 | + const PRIME1: PyUHash = 11400714785074694791; |
| 532 | + #[cfg(target_pointer_width = "64")] |
| 533 | + const PRIME2: PyUHash = 14029467366897019727; |
| 534 | + #[cfg(target_pointer_width = "64")] |
| 535 | + const PRIME5: PyUHash = 2870177450012600261; |
| 536 | + #[cfg(target_pointer_width = "64")] |
| 537 | + const ROTATE: u32 = 31; |
| 538 | + |
| 539 | + #[cfg(target_pointer_width = "32")] |
| 540 | + const PRIME1: PyUHash = 2654435761; |
| 541 | + #[cfg(target_pointer_width = "32")] |
| 542 | + const PRIME2: PyUHash = 2246822519; |
| 543 | + #[cfg(target_pointer_width = "32")] |
| 544 | + const PRIME5: PyUHash = 374761393; |
| 545 | + #[cfg(target_pointer_width = "32")] |
| 546 | + const ROTATE: u32 = 13; |
| 547 | + |
| 548 | + let mut acc = PRIME5; |
| 549 | + let len = elements.len() as PyUHash; |
| 550 | + |
| 551 | + for val in elements { |
| 552 | + let lane = val.hash(vm)? as PyUHash; |
| 553 | + acc = acc.wrapping_add(lane.wrapping_mul(PRIME2)); |
| 554 | + acc = acc.rotate_left(ROTATE); |
| 555 | + acc = acc.wrapping_mul(PRIME1); |
| 556 | + } |
| 557 | + |
| 558 | + acc = acc.wrapping_add(len ^ (PRIME5 ^ 3527539)); |
| 559 | + |
| 560 | + if acc as PyHash == -1 { |
| 561 | + return Ok(1546275796); |
| 562 | + } |
| 563 | + Ok(acc as PyHash) |
| 564 | +} |
0 commit comments