// File: /workspace/github_cpp_makefile_star2_O2/BU-DiSC[P]BF-Shared-Hashing/hash/city.cc
// Function: CityHash64(char const*, unsigned long)
uint64 CityHash64(const char *s, size_t len) {
  if (len <= 32) {
    if (len <= 16) {
      return HashLen0to16(s, len);
    } else {
      return HashLen17to32(s, len);
    }
  } else if (len <= 64) {
    return HashLen33to64(s, len);
  }

  // For strings over 64 bytes we hash the end first, and then as we
  // loop we keep 56 bytes of state: v, w, x, y, and z.
  uint64 x = Fetch64(s + len - 40);
  uint64 y = Fetch64(s + len - 16) + Fetch64(s + len - 56);
  uint64 z = HashLen16(Fetch64(s + len - 48) + len, Fetch64(s + len - 24));
  pair<uint64, uint64> v = WeakHashLen32WithSeeds(s + len - 64, len, z);
  pair<uint64, uint64> w = WeakHashLen32WithSeeds(s + len - 32, y + k1, x);
  x = x * k1 + Fetch64(s);

  // Decrease len to the nearest multiple of 64, and operate on 64-byte chunks.
  len = (len - 1) & ~static_cast<size_t>(63);
  do {
    x = Rotate(x + y + v.first + Fetch64(s + 8), 37) * k1;
    y = Rotate(y + v.second + Fetch64(s + 48), 42) * k1;
    x ^= w.second;
    y += v.first + Fetch64(s + 40);
    z = Rotate(z + w.first, 33) * k1;
    v = WeakHashLen32WithSeeds(s, v.second * k1, x + w.first);
    w = WeakHashLen32WithSeeds(s + 32, z + w.second, y + Fetch64(s + 16));
    std::swap(z, x);
    s += 64;
    len -= 64;
  } while (len != 0);
  return HashLen16(HashLen16(v.first, w.first) + ShiftMix(y) * k1 + z,
                   HashLen16(v.second, w.second) + x);
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x18, %rsp
movq %rsi, %r13
movq %rdi, %r12
cmpq $0x20, %rsi
ja 0x216f2
cmpq $0x10, %r13
ja 0x217be
movq %r12, %rdi
movq %r13, %rsi
addq $0x18, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
jmp 0x219ba
cmpq $0x40, %r13
ja 0x21843
movabsq $-0x651e95c4d06fbfb1, %rax # imm = 0x9AE16A3B2F90404F
leaq (%rax,%r13,2), %rcx
movq (%r12), %r8
imulq %rax, %r8
movq 0x8(%r12), %rbx
movq -0x20(%r12,%r13), %rdx
imulq 0x10(%r12), %rax
imulq $0x9, 0x18(%r12), %r10
movq -0x18(%r12,%r13), %r9
movq -0x8(%r12,%r13), %rdi
movq -0x10(%r12,%r13), %rsi
imulq %rcx, %rsi
addq %rdi, %r8
movq %r8, %r14
rolq $0x15, %r14
addq %r10, %rax
movq %rax, %r11
addq %r9, %rax
addq %rax, %rdi
addq %rbx, %rax
rolq $0x22, %rbx
addq %r9, %rbx
leaq (%rbx,%rbx,8), %rbx
addq %r14, %rbx
xorq %rdx, %r8
leaq (%r10,%r8), %r14
addq %r10, %r8
incq %r8
addq %rbx, %r8
imulq %rcx, %r8
bswapq %r8
rolq $0x16, %r11
addq %r9, %r11
leaq (%rsi,%r14), %r9
incq %r9
addq %r8, %r9
imulq %rcx, %r9
bswapq %r9
addq %r11, %rdi
addq %r9, %rdi
imulq %rcx, %rdi
bswapq %rdi
addq %rdi, %rax
imulq %rcx, %rax
addq %rdx, %rsi
addq %rax, %rsi
movq %rsi, %rax
shrq $0x2f, %rax
xorq %rsi, %rax
imulq %rcx, %rax
addq %r11, %rax
jmp 0x21834
movabsq $-0x651e95c4d06fbfb1, %rdx # imm = 0x9AE16A3B2F90404F
leaq (%rdx,%r13,2), %rcx
movabsq $-0x4b6d499041670d8d, %rsi # imm = 0xB492B66FBE98F273
imulq (%r12), %rsi
movq 0x8(%r12), %rax
movq -0x8(%r12,%r13), %rdi
imulq %rcx, %rdi
movq -0x10(%r12,%r13), %r8
imulq %rdx, %r8
leaq (%rsi,%rax), %r9
rolq $0x15, %r9
addq %rdx, %rax
rolq $0x2e, %rax
addq %rsi, %rax
addq %rdi, %rax
rolq $0x22, %rdi
addq %r9, %rdi
addq %r8, %rdi
xorq %rax, %rdi
imulq %rcx, %rdi
xorq %rdi, %rax
shrq $0x2f, %rdi
xorq %rax, %rdi
imulq %rcx, %rdi
movq %rdi, %rax
shrq $0x2f, %rax
xorq %rdi, %rax
imulq %rcx, %rax
addq $0x18, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
leaq (%r12,%r13), %r14
addq $-0x40, %r14
movq 0x8(%r14), %rbx
addq 0x30(%r14), %rbx
movq 0x18(%r14), %r15
movq 0x10(%r14), %rdi
addq %r13, %rdi
movq 0x28(%r14), %rsi
callq 0x21a8f
movq %rax, %rbp
movq %r14, %rdi
movq %r13, %rsi
movq %rax, %rdx
callq 0x21aac
movq %rax, %r14
movq %rdx, 0x8(%rsp)
leaq (%r12,%r13), %rdi
addq $-0x20, %rdi
movabsq $-0x4b6d499041670d8d, %rax # imm = 0xB492B66FBE98F273
leaq (%rbx,%rax), %rsi
movq %r15, %rdx
callq 0x21aac
movq %r13, %rcx
movq %rdx, %r13
movabsq $-0x4b6d499041670d8d, %rdx # imm = 0xB492B66FBE98F273
imulq %rdx, %r15
addq (%r12), %r15
decq %rcx
addq $0x20, %r12
andq $-0x40, %rcx
negq %rcx
movq %rcx, 0x10(%rsp)
movq %rbp, %rcx
addq %r14, %r15
addq %rbx, %r15
addq -0x18(%r12), %r15
leaq -0x20(%r12), %rdi
rolq $0x1b, %r15
movq 0x8(%rsp), %rsi
addq %rsi, %rbx
addq 0x10(%r12), %rbx
rolq $0x16, %rbx
movabsq $-0x4b6d499041670d8d, %r8 # imm = 0xB492B66FBE98F273
imulq %r8, %r15
movq %rbx, %rdx
imulq %r8, %rdx
movq %r15, %rbp
xorq %r13, %rbp
addq 0x8(%r12), %r14
movq %r14, %rbx
addq %rdx, %rbx
addq %rax, %rcx
rolq $0x1f, %rcx
movq %rcx, %r15
imulq %r8, %r15
imulq %r8, %rsi
addq %rbp, %rax
movq %rax, %rdx
callq 0x21aac
movq %rax, %r14
movq %rdx, 0x8(%rsp)
addq %r15, %r13
movq -0x10(%r12), %rdx
addq %rbx, %rdx
movq %r12, %rdi
movq %r13, %rsi
callq 0x21aac
movq 0x10(%rsp), %rcx
movq %rdx, %r13
addq $0x40, %r12
addq $0x40, %rcx
jne 0x218c4
movq %r14, %rdi
movq %rax, %rsi
callq 0x21a8f
movq %rbx, %r14
shrq $0x2f, %r14
xorq %rbx, %r14
movabsq $-0x4b6d499041670d8d, %rcx # imm = 0xB492B66FBE98F273
imulq %rcx, %r14
addq %rbp, %r14
addq %rax, %r14
movq 0x8(%rsp), %rdi
movq %r13, %rsi
callq 0x21a8f
addq %rax, %r15
movq %r14, %rdi
movq %r15, %rsi
addq $0x18, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
jmp 0x21a8f