1#![no_std]
35#![allow(clippy::many_single_char_names)]
36use core::num::Wrapping;
37
38type W64 = Wrapping<u64>;
39type W32 = Wrapping<u32>;
40
41#[derive(Clone, Copy, Debug, PartialEq, Eq)]
48pub struct U128 {
49 pub first: u64,
50 pub second: u64,
51}
52
53impl U128 {
54 #[inline]
55 pub const fn new(first: u64, second: u64) -> Self {
56 Self { first, second }
57 }
58
59 #[inline]
61 pub const fn lo(&self) -> u64 {
62 self.first
63 }
64
65 #[inline]
67 pub const fn hi(&self) -> u64 {
68 self.second
69 }
70
71 const fn from_w64(first: W64, second: W64) -> Self {
72 Self {
73 first: first.0,
74 second: second.0,
75 }
76 }
77}
78
79impl From<u128> for U128 {
80 #[inline]
81 fn from(source: u128) -> Self {
82 Self {
83 first: source as u64,
84 second: (source >> 64) as u64,
85 }
86 }
87}
88
89impl From<U128> for u128 {
90 #[inline]
91 fn from(val: U128) -> Self {
92 (val.first as u128) | ((val.second as u128) << 64)
93 }
94}
95
96const fn w64(v: u64) -> W64 {
97 Wrapping(v)
98}
99
100const fn w32(v: u32) -> W32 {
101 Wrapping(v)
102}
103
104const K0: W64 = w64(0xc3a5c85c97cb3127u64);
106const K1: W64 = w64(0xb492b66fbe98f273u64);
107const K2: W64 = w64(0x9ae16a3b2f90404fu64);
108const K3: W64 = w64(0xc949d7c7509e6557u64);
109
110#[inline]
115unsafe fn fetch64(s: *const u8) -> W64 {
116 w64((s as *const u64).read_unaligned().to_le())
117}
118
119#[inline]
124unsafe fn fetch32(s: *const u8) -> W32 {
125 w32((s as *const u32).read_unaligned().to_le())
126}
127
128#[inline]
129fn rotate(v: W64, n: u32) -> W64 {
130 debug_assert!(n > 0);
131 w64(v.0.rotate_right(n))
134}
135
136fn hash_len16(u: W64, v: W64) -> W64 {
137 hash128_to_64(u, v)
138}
139
140#[inline]
143fn hash128_to_64(l: W64, h: W64) -> W64 {
144 const K_MUL: W64 = w64(0x9ddfea08eb382d69u64);
145 let mut a = (h ^ l) * K_MUL;
146 a ^= a >> 47;
147 let mut b = (h ^ a) * K_MUL;
148 b ^= b >> 47;
149 b * K_MUL
150}
151
152fn hash_len0to16(data: &[u8]) -> W64 {
153 let len = data.len();
154 let s = data.as_ptr();
155
156 if len > 8 {
157 unsafe {
159 let a = fetch64(s);
160 let b = fetch64(s.add(len).sub(8));
161 b ^ hash_len16(a, rotate(b + w64(len as u64), len as u32))
162 }
163 } else if len >= 4 {
164 unsafe {
166 let a = fetch32(s).0 as u64;
167
168 hash_len16(
169 w64((len as u64) + (a << 3)),
170 w64(fetch32(s.add(len).sub(4)).0.into()),
171 )
172 }
173 } else if len > 0 {
174 let a: u8 = data[0];
176 let b: u8 = data[len >> 1];
177 let c: u8 = data[len - 1];
178 let y = w64(a as u64) + w64((b as u64) << 8);
179 let z = w64(((len as u32) + ((c as u32) << 2)) as u64);
180
181 shift_mix((y * K2) ^ (z * K3)) * K2
182 } else {
183 K2
184 }
185}
186
187unsafe fn hash_len17to32(data: &[u8]) -> W64 {
191 let s = data.as_ptr();
192 let len = data.len();
193 debug_assert!(len > 16);
194
195 let a = fetch64(s) * K1;
196 let b = fetch64(s.add(8));
197 let c = fetch64(s.add(len).sub(8)) * K2;
198 let d = fetch64(s.add(len).sub(16)) * K0;
199 hash_len16(
200 rotate(a - b, 43) + rotate(c, 30) + d,
201 a + rotate(b ^ K3, 20) - c + w64(len as u64),
202 )
203}
204
205unsafe fn hash_len33to64(data: &[u8]) -> W64 {
209 let s = data.as_ptr();
210 let len = data.len();
211 debug_assert!(len > 32);
212
213 let mut z = fetch64(s.add(24));
214 let mut a = fetch64(s) + K0 * (w64(len as u64) + fetch64(s.add(len).sub(16)));
215 let mut b = rotate(a + z, 52);
216 let mut c = rotate(a, 37);
217 a += fetch64(s.add(8));
218 c += rotate(a, 7);
219 a += fetch64(s.add(16));
220
221 let vf = a + z;
222 let vs = b + rotate(a, 31) + c;
223 a = fetch64(s.add(16)) + fetch64(s.add(len).sub(32));
224 z = fetch64(s.add(len).sub(8));
225 b = rotate(a + z, 52);
226 c = rotate(a, 37);
227 a += fetch64(s.add(len).sub(24));
228 c += rotate(a, 7);
229 a += fetch64(s.add(len).sub(16));
230 let wf = a + z;
231 let ws = b + rotate(a, 31) + c;
232 let r = shift_mix(K2 * (vf + ws) + K0 * (wf + vs));
233 shift_mix(vs + r * K0) * K2
234}
235
236unsafe fn weak_hash_len32_with_seeds(s: *const u8, a: W64, b: W64) -> (W64, W64) {
238 weak_hash_len32_with_seeds_(
239 fetch64(s),
240 fetch64(s.add(8)),
241 fetch64(s.add(16)),
242 fetch64(s.add(24)),
243 a,
244 b,
245 )
246}
247
248fn weak_hash_len32_with_seeds_(
249 w: W64,
250 x: W64,
251 y: W64,
252 z: W64,
253 mut a: W64,
254 mut b: W64,
255) -> (W64, W64) {
256 a += w;
257 b = rotate(b + a + z, 21);
258 let c = a;
259 a += x + y;
260 b += rotate(a, 44);
261 (a + z, b + c)
262}
263
264fn shift_mix(val: W64) -> W64 {
265 val ^ (val >> 47)
266}
267
268pub fn cityhash64(data: &[u8]) -> u64 {
273 unsafe {
274 if data.len() <= 32 {
275 if data.len() <= 16 {
276 return hash_len0to16(data).0;
277 } else {
278 return hash_len17to32(data).0;
279 }
280 } else if data.len() <= 64 {
281 return hash_len33to64(data).0;
282 }
283
284 let mut s = data.as_ptr();
285 let mut len = data.len();
286
287 let mut x = fetch64(s);
290 let mut y = fetch64(s.add(len).sub(16)) ^ K1;
291 let mut z = fetch64(s.add(len).sub(56)) ^ K0;
292
293 let mut v: (W64, W64) = weak_hash_len32_with_seeds(s.add(len).sub(64), w64(len as u64), y);
294 let mut w: (W64, W64) =
295 weak_hash_len32_with_seeds(s.add(len).sub(32), K1 * w64(len as u64), K0);
296
297 z += shift_mix(v.1) * K1;
298 x = rotate(z + x, 39) * K1;
299 y = rotate(y, 33) * K1;
300
301 len = (len - 1) & !63;
302
303 while {
304 x = rotate(x + y + v.0 + fetch64(s.add(16)), 37) * K1;
305 y = rotate(y + v.1 + fetch64(s.add(48)), 42) * K1;
306 x ^= w.1;
307 y ^= v.0;
308 z = rotate(z ^ w.0, 33);
309 v = weak_hash_len32_with_seeds(s, v.1 * K1, x + w.0);
310 w = weak_hash_len32_with_seeds(s.add(32), z + w.1, y);
311 core::mem::swap(&mut z, &mut x);
312
313 s = s.add(64);
314 len -= 64;
315
316 len != 0
317 } { }
318
319 hash_len16(
320 hash_len16(v.0, w.0) + shift_mix(y) * K1 + z,
321 hash_len16(v.1, w.1) + x,
322 )
323 .0
324 }
325}
326
327fn city_murmur(data: &[u8], seed: U128) -> U128 {
328 let mut s = data.as_ptr();
329 let len = data.len();
330
331 let mut a = w64(seed.first);
332 let mut b = w64(seed.second);
333 let mut c: W64;
334 let mut d: W64;
335 let mut l = (len as isize) - 16;
336
337 if l <= 0 {
338 a = shift_mix(a * K1) * K1;
340 c = b * K1 + hash_len0to16(data);
341 d = unsafe { shift_mix(a + (if len >= 8 { fetch64(s) } else { c })) };
343 } else {
344 unsafe {
347 c = hash_len16(fetch64(s.add(len).sub(8)) + K1, a);
348 d = hash_len16(b + w64(len as u64), c + fetch64(s.add(len).sub(16)));
349 a += d;
350 while {
351 a ^= shift_mix(fetch64(s) * K1) * K1;
352 a *= K1;
353 b ^= a;
354 c ^= shift_mix(fetch64(s.add(8)) * K1) * K1;
355 c *= K1;
356 d ^= c;
357 s = s.add(16);
358 l -= 16;
359 l > 0
360 } { }
361 }
362 }
363 a = hash_len16(a, c);
364 b = hash_len16(d, b);
365 U128::from_w64(a ^ b, hash_len16(b, a))
366}
367
368fn cityhash128_with_seed(data: &[u8], seed: U128) -> U128 {
369 let mut s = data.as_ptr();
370 let mut len = data.len();
371
372 unsafe {
373 if len < 128 {
375 return city_murmur(data, seed);
376 }
377
378 let mut x = w64(seed.first);
381 let mut y = w64(seed.second);
382 let mut z = w64(len as u64) * K1;
383 let mut v = (w64(0), w64(0));
384 v.0 = rotate(y ^ K1, 49) * K1 + fetch64(s);
385 v.1 = rotate(v.0, 42) * K1 + fetch64(s.add(8));
386 let mut w = (
387 rotate(y + z, 35) * K1 + x,
388 rotate(x + fetch64(s.add(88)), 53) * K1,
389 );
390
391 while {
392 x = rotate(x + y + v.0 + fetch64(s.add(16)), 37) * K1;
393 y = rotate(y + v.1 + fetch64(s.add(48)), 42) * K1;
394 x ^= w.1;
395 y ^= v.0;
396 z = rotate(z ^ w.0, 33);
397 v = weak_hash_len32_with_seeds(s, v.1 * K1, x + w.0);
398 w = weak_hash_len32_with_seeds(s.add(32), z + w.1, y);
399 core::mem::swap(&mut z, &mut x);
400 s = s.add(64);
401 x = rotate(x + y + v.0 + fetch64(s.add(16)), 37) * K1;
402 y = rotate(y + v.1 + fetch64(s.add(48)), 42) * K1;
403 x ^= w.1;
404 y ^= v.0;
405 z = rotate(z ^ w.0, 33);
406 v = weak_hash_len32_with_seeds(s, v.1 * K1, x + w.0);
407 w = weak_hash_len32_with_seeds(s.add(32), z + w.1, y);
408 core::mem::swap(&mut z, &mut x);
409 s = s.add(64);
410 len -= 128;
411
412 len >= 128
413 } { }
414
415 y += rotate(w.0, 37) * K0 + z;
416 x += rotate(v.0 + z, 49) * K0;
417
418 let mut tail_done: usize = 0;
420 while tail_done < len {
421 tail_done += 32;
422 y = rotate(y - x, 42) * K0 + v.1;
423 w.0 += fetch64(s.add(len).sub(tail_done).add(16));
424 x = rotate(x, 49) * K0 + w.0;
425 w.0 += v.0;
426 v = weak_hash_len32_with_seeds(s.add(len).sub(tail_done), v.0, v.1);
427 }
428 x = hash_len16(x, v.0);
432 y = hash_len16(y, w.0);
433
434 U128::from_w64(hash_len16(x + v.1, w.1) + y, hash_len16(x + w.1, y + v.1))
435 }
436}
437
438pub fn cityhash128(data: &[u8]) -> U128 {
448 let s = data.as_ptr();
449 let len = data.len();
450 unsafe {
451 if len >= 16 {
452 cityhash128_with_seed(
453 &data[16..],
454 U128::from_w64(fetch64(s) ^ K3, fetch64(s.add(8))),
455 )
456 } else if data.len() >= 8 {
457 cityhash128_with_seed(
458 b"",
459 U128::from_w64(
460 fetch64(s) ^ (w64(len as u64) * K0),
461 fetch64(s.add(len).sub(8)) ^ K1,
462 ),
463 )
464 } else {
465 cityhash128_with_seed(data, U128::from_w64(K0, K1))
466 }
467 }
468}
469
470#[cfg(test)]
471mod tests {
472 use crate::{cityhash128, cityhash64, U128};
473
474 #[test]
475 fn test_64_len0() {
476 assert_eq!(cityhash64(b""), 11160318154034397263);
477 }
478
479 #[test]
480 fn test_64_len1() {
481 assert_eq!(cityhash64(b"1"), 11413460447292444913);
482 }
483
484 #[test]
485 fn test_64_len2() {
486 assert_eq!(cityhash64(b"12"), 12074748272894662792);
487 }
488
489 #[test]
490 fn test_64_len3() {
491 assert_eq!(cityhash64(b"abc"), 4220206313085259313);
492 }
493
494 #[test]
495 fn test_64_len4() {
496 assert_eq!(cityhash64(b"1234"), 11914632649014994877);
497 }
498
499 #[test]
500 fn test_64_len5() {
501 assert_eq!(cityhash64(b"12345"), 16429329056539592968);
502 }
503
504 #[test]
505 fn test_64_len6() {
506 assert_eq!(cityhash64(b"123456"), 9260297286307356373);
507 }
508
509 #[test]
510 fn test_64_len7() {
511 assert_eq!(cityhash64(b"1234567"), 11025202622668490255);
512 }
513
514 #[test]
515 fn test_64_len8() {
516 assert_eq!(cityhash64(b"12345678"), 7177601938557627951);
517 }
518
519 #[test]
520 fn test_64_len9() {
521 assert_eq!(cityhash64(b"123456789"), 12390271160407166709);
522 }
523
524 #[test]
525 fn test_64_len10() {
526 assert_eq!(cityhash64(b"1234567890"), 11159486737701695049);
527 }
528
529 #[test]
530 fn test_64_len11() {
531 assert_eq!(cityhash64(b"1234567890A"), 12461606063103015484);
532 }
533
534 #[test]
535 fn test_64_len12() {
536 assert_eq!(cityhash64(b"1234567890Ab"), 3962957222420222636);
537 }
538
539 #[test]
540 fn test_64_len13() {
541 assert_eq!(cityhash64(b"1234567890Abc"), 10943934074830884361);
542 }
543
544 #[test]
545 fn test_64_len14() {
546 assert_eq!(cityhash64(b"1234567890AbcD"), 14566583638543629997);
547 }
548
549 #[test]
550 fn test_64_len15() {
551 assert_eq!(cityhash64(b"1234567890AbcDE"), 1470766631700230904);
552 }
553
554 #[test]
555 fn test_64_len16() {
556 assert_eq!(cityhash64(b"1234567890abcdef"), 10283158570132023530);
557 }
558
559 #[test]
560 fn test_64_len17() {
561 assert_eq!(cityhash64(b"4RNfAbDSysH78xK5s"), 16686325262955297357);
562 }
563
564 #[test]
565 fn test_64_longer() {
566 assert_eq!(
567 cityhash64(b"1234567890abcdefghijklmnopqrstuvwxyz"),
568 6062807976406716385
569 );
570 }
571
572 #[test]
573 fn test_64_len64() {
574 let data = &b"7zxsqkZNsEoNfRz83hct4HH5ytE3SFvx0MX9ACbDDBZhtUcR30pGvmJIPAoXwJCq"[..];
575 assert_eq!(data.len(), 64); assert_eq!(cityhash64(&data), 12341453991847893643);
577 }
578
579 #[test]
580 fn test_64_len65() {
581 let data = &b"DSDXf2J5gvPZWtzo4qdrdbXw6qGKkVuzrV7zEZA3x6xNnGdQdSTr7YocaJWpgDgzq"[..];
582 assert_eq!(data.len(), 65); assert_eq!(cityhash64(data), 12363235829494951337);
584 }
585
586 #[test]
587 fn test_64_verylong() {
588 let data =
589 &b"DMqhuXQxgAmJ9EOkT1n2lpzu7YD6zKc6ESSDWfJfohaQDwu0ba61bfGMiuS5GXpr0bIVcCtLwRtIVGmK"[..];
590 assert_eq!(data.len(), 80); assert_eq!(cityhash64(data), 12512298373611890505);
592 }
593
594 #[test]
595 fn test_64_binary() {
596 let data = b"\xe4x\x98\xa4*\xd7\xdc\x02p.\xdeI$\x9fp\xd4\xe3\xd7\xe7L\x86<5h75\xdf0B\x16\xe0\x86\xbeP\xb1rL\x8b\x07\x14!\x9e\xf5\xe0\x9cN\xa5\xfdJ]\xd8J\xc1\xc2.\xe6\xae\x14\xad^sW\x15&";
597 assert_eq!(cityhash64(data.as_ref()), 5932484233276644677);
598 }
599
600 #[test]
601 fn test_from_u128() {
602 let v = U128::from(0x11212312341234512345612345671234u128);
603 assert_eq!(v.first, 0x2345612345671234u64);
604 assert_eq!(v.second, 0x1121231234123451u64);
605 }
606
607 #[test]
608 fn test_into_u128() {
609 let v: u128 = U128::new(0x2345612345671234u64, 0x1121231234123451u64).into();
610 assert_eq!(v, 0x11212312341234512345612345671234u128);
611 }
612
613 #[test]
617 fn test_128_len0() {
618 assert_eq!(
619 cityhash128(b""),
620 U128::new(4463240938071824939, 4374473821787594281)
621 );
622 }
623
624 #[test]
625 fn test_128_len1() {
626 assert_eq!(
627 cityhash128(b"1"),
628 U128::new(6359294370932160835, 9352172043616825891)
629 );
630 }
631
632 #[test]
633 fn test_128_len2() {
634 assert_eq!(
635 cityhash128(b"12"),
636 U128::new(16369832005849840265, 11285803613326688650)
637 );
638 }
639
640 #[test]
641 fn test_128_len3() {
642 assert_eq!(
643 cityhash128(b"123"),
644 U128::new(11385344155619871181, 565130349297615695)
645 );
646 }
647
648 #[test]
649 fn test_128_len4() {
650 assert_eq!(
651 cityhash128(b"1234"),
652 U128::new(2764810728135862028, 5901424084875196719)
653 );
654 }
655
656 #[test]
657 fn test_128_len5() {
658 assert_eq!(
659 cityhash128(b"12345"),
660 U128::new(11980518989907363833, 93456746504981291)
661 );
662 }
663
664 #[test]
665 fn test_128_len6() {
666 assert_eq!(
667 cityhash128(b"123456"),
668 U128::new(2350911489181485812, 12095241732236332703)
669 );
670 }
671
672 #[test]
673 fn test_128_len7() {
674 assert_eq!(
675 cityhash128(b"1234567"),
676 U128::new(10270309315532912023, 9823143772454143291)
677 );
678 }
679
680 #[test]
681 fn test_128_len8() {
682 assert_eq!(
683 cityhash128(b"12345678"),
684 U128::new(2123262123519760883, 8251334461883709976)
685 );
686 }
687
688 #[test]
689 fn test_128_len9() {
690 assert_eq!(
691 cityhash128(b"123456789"),
692 U128::new(14140762465907274276, 13893707330375041594)
693 );
694 }
695
696 #[test]
697 fn test_128_len10() {
698 assert_eq!(
699 cityhash128(b"1234567890"),
700 U128::new(8211333661328737896, 17823093577549856754)
701 );
702 }
703
704 #[test]
705 fn test_128_len11() {
706 assert_eq!(
707 cityhash128(b"1234567890A"),
708 U128::new(1841684041954399514, 6623964278873157363)
709 );
710 }
711
712 #[test]
713 fn test_128_len12() {
714 assert_eq!(
715 cityhash128(b"1234567890Ab"),
716 U128::new(3349064628685767173, 12952593207096460945)
717 );
718 }
719
720 #[test]
721 fn test_128_len13() {
722 assert_eq!(
723 cityhash128(b"1234567890Abc"),
724 U128::new(6572961695122645386, 13774858861848724400)
725 );
726 }
727
728 #[test]
729 fn test_128_len14() {
730 assert_eq!(
731 cityhash128(b"1234567890AbcD"),
732 U128::new(18041930573402443112, 5778672772533284640)
733 );
734 }
735
736 #[test]
737 fn test_128_len15() {
738 assert_eq!(
739 cityhash128(b"1234567890AbcDE"),
740 U128::new(11266190325599732773, 348002394938205539)
741 );
742 }
743
744 #[test]
745 fn test_128_len16() {
746 assert_eq!(
747 cityhash128(b"1234567890AbcDEF"),
748 U128::new(15073733098592741404, 5913034415582713572)
749 );
750 }
751
752 #[test]
753 fn test_128_long() {
754 assert_eq!(
755 cityhash128(b"this is somewhat long string"),
756 U128::new(2957911805285034456, 6923665615086076251)
757 );
758 }
759
760 #[test]
761 fn test_128_longer() {
762 assert_eq!(
763 cityhash128(
764 b"DMqhuXQxgAmJ9EOkT1n2lpzu7YD6zKc6ESSDWfJfohaQDwu0ba61bfGMiuS5GXpr0bIVcCtLwRtIVGmK"
765 ),
766 U128::new(9681404383092874918, 15631953994107571989)
767 );
768 }
769
770 #[test]
771 fn test_128_binary() {
772 let data = b"\xe4x\x98\xa4*\xd7\xdc\x02p.\xdeI$\x9fp\xd4\xe3\xd7\xe7L\x86<5h75\xdf0B\x16\xe0\x86\xbeP\xb1rL\x8b\x07\x14!\x9e\xf5\xe0\x9cN\xa5\xfdJ]\xd8J\xc1\xc2.\xe6\xae\x14\xad^sW\x15&";
773 assert_eq!(
774 cityhash128(data.as_ref()),
775 U128::new(5907140908903622203, 10088853506155899265)
776 );
777 }
778}