ch_cityhash102/
lib.rs

1/*
2Copyright (c) 2021 Ivan Boldyrev
3Copyright (c) 2011 Google, Inc.
4
5Permission is hereby granted, free of charge, to any person obtaining a copy
6of this software and associated documentation files (the "Software"), to deal
7in the Software without restriction, including without limitation the rights
8to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9copies of the Software, and to permit persons to whom the Software is
10furnished to do so, subject to the following conditions:
11
12The above copyright notice and this permission notice shall be included in
13all copies or substantial portions of the Software.
14
15THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21THE SOFTWARE.
22 */
23
24/*!
25# Features
26
27This crate has only single feature used exclusively for testing/benchmarking.
28
29* **test_with_clickhouse_driver** -
30  Test and benchmark against
31  <https://github.com/ddulesov/clickhouse_driver/>, both native and
32  C++ implementations.
33*/
34#![no_std]
35#![allow(clippy::many_single_char_names)]
36use core::num::Wrapping;
37
38type W64 = Wrapping<u64>;
39type W32 = Wrapping<u32>;
40
41/** C++ CityHash-compatible `uint128` type.
42
43While Rust has native `u128` type, we've decided to use compatible type
44of two `u64` fields.  The `From<u128>` and `Into<u128>` are implemented
45for this type for your convenience.
46*/
47#[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    /** Lower half of the `U128`. */
60    #[inline]
61    pub const fn lo(&self) -> u64 {
62        self.first
63    }
64
65    /** Higher half of the `U128`. */
66    #[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
104// Some primes between 2^63 and 2^64 for various uses.
105const K0: W64 = w64(0xc3a5c85c97cb3127u64);
106const K1: W64 = w64(0xb492b66fbe98f273u64);
107const K2: W64 = w64(0x9ae16a3b2f90404fu64);
108const K3: W64 = w64(0xc949d7c7509e6557u64);
109
110/**
111# Safety
112`s` has to point to at least 8 bytes of available data.
113*/
114#[inline]
115unsafe fn fetch64(s: *const u8) -> W64 {
116    w64((s as *const u64).read_unaligned().to_le())
117}
118
119/**
120# Safety
121`s` has to point to at least 4 bytes of available data.
122*/
123#[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    // Look, ma, I have real rotate!
132    // rotate_right for Wrapping is yet unstable, so we unwrap and wrap it back.
133    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// Hash 128 input bits down to 64 bits of output.
141// This is intended to be a reasonably good hash function.
142#[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        // It is ok as len > 8.
158        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        // It is ok as len > 4.
165        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        // TODO make sure checks are eliminated by the compiler.
175        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
187/*
188This function is unsafe because it will read incorrect memory when data.len() < 17.
189*/
190unsafe 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
205/*
206This function is unsafe because it will read incorrect memory when data.len() < 33.
207*/
208unsafe 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
236/* This function is unsafe because it reads 32 bytes starting from s. */
237unsafe 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
268/**
269ClickHouse's version of the CityHash64 hash.  It is used in the
270query language to process user data.
271*/
272pub 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        // For strings over 64 bytes we hash the end first, and then as we
288        // loop we keep 56 bytes of state: v, w, x, y, and z.
289        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        } { /* EMPTY */ }
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        // len <= 16
339        a = shift_mix(a * K1) * K1;
340        c = b * K1 + hash_len0to16(data);
341        // It is safe as read of 8 bytes is guarded by `len >= 8` condition.
342        d = unsafe { shift_mix(a + (if len >= 8 { fetch64(s) } else { c })) };
343    } else {
344        // len > 16
345        // It is safe because len > 16 and that's enough
346        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            } { /* EMPTY */ }
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        // TODO: it may be inlined to the cityhash128
374        if len < 128 {
375            return city_murmur(data, seed);
376        }
377
378        // We expect len >= 128 to be the common case.  Keep 56 bytes of state:
379        // v, w, x, y, and z.
380        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        } { /* EMPTY */ }
414
415        y += rotate(w.0, 37) * K0 + z;
416        x += rotate(v.0 + z, 49) * K0;
417
418        // If 0 < len < 128, hash up to 4 chunks of 32 bytes each from the end of s.
419        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        // At this point our 48 bytes of state should contain more than
429        // enough information for a strong 128-bit hash.  We use two
430        // different 48-byte-to-8-byte hashes to get a 16-byte final result.
431        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
438/**
439ClickHouse's version of the CityHash128 hash.  It is used in the
440ClickHouse protocol.
441
442## Returned value
443This function returns the [`U128`] struct that follows the
444original C++ version, even though Rust has native `u128` type.
445`From<u128>` and `Into<u128>` are implemented for this type.
446*/
447pub 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); // test validity
576        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); // test validity
583        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); // test validity
591        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    /*
614     * The test_128_* numbers are generated by a custom binary calling CityHash128.
615     */
616    #[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}