alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

Java example source code file (SipHashFunction.java)

This example Java source code file (SipHashFunction.java) is included in the alvinalexander.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Learn more about this Java project at its project page.

Java - Java tags/keywords

abstractstreaminghasher, abstractstreaminghashfunction, annotation, chunk_size, compression, finalization, hashcode, nio, object, override, serializable, siphasher, siphashfunction, sipround, string, the

The SipHashFunction.java Java example source code

/*
 * Copyright (C) 2012 The Guava Authors
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
 * in compliance with the License. You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software distributed under the License
 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
 * or implied. See the License for the specific language governing permissions and limitations under
 * the License.
 */

/*
 * SipHash-c-d was designed by Jean-Philippe Aumasson and Daniel J. Bernstein and is described in
 * "SipHash: a fast short-input PRF" (available at https://131002.net/siphash/siphash.pdf).
 */

package com.google.common.hash;

import static com.google.common.base.Preconditions.checkArgument;

import java.io.Serializable;
import java.nio.ByteBuffer;

import javax.annotation.Nullable;

/**
 * {@link HashFunction} implementation of SipHash-c-d.
 *
 * @author Kurt Alfred Kluever
 * @author Jean-Philippe Aumasson
 * @author Daniel J. Bernstein
 */
final class SipHashFunction extends AbstractStreamingHashFunction implements Serializable {

  // The number of compression rounds.
  private final int c;
  // The number of finalization rounds.
  private final int d;
  // Two 64-bit keys (represent a single 128-bit key).
  private final long k0;
  private final long k1;

  /**
   * @param c the number of compression rounds (must be positive)
   * @param d the number of finalization rounds (must be positive)
   * @param k0 the first half of the key
   * @param k1 the second half of the key
   */
  SipHashFunction(int c, int d, long k0, long k1) {
    checkArgument(
        c > 0, "The number of SipRound iterations (c=%s) during Compression must be positive.", c);
    checkArgument(
        d > 0, "The number of SipRound iterations (d=%s) during Finalization must be positive.", d);
    this.c = c;
    this.d = d;
    this.k0 = k0;
    this.k1 = k1;
  }

  @Override
  public int bits() {
    return 64;
  }

  @Override
  public Hasher newHasher() {
    return new SipHasher(c, d, k0, k1);
  }

  // TODO(kak): Implement and benchmark the hashFoo() shortcuts.

  @Override
  public String toString() {
    return "Hashing.sipHash" + c + "" + d + "(" + k0 + ", " + k1 + ")";
  }

  @Override
  public boolean equals(@Nullable Object object) {
    if (object instanceof SipHashFunction) {
      SipHashFunction other = (SipHashFunction) object;
      return (c == other.c)
          && (d == other.d)
          && (k0 == other.k0)
          && (k1 == other.k1);
    }
    return false;
  }

  @Override
  public int hashCode() {
    return (int) (getClass().hashCode() ^ c ^ d ^ k0 ^ k1);
  }

  private static final class SipHasher extends AbstractStreamingHasher {
    private static final int CHUNK_SIZE = 8;

    // The number of compression rounds.
    private final int c;
    // The number of finalization rounds.
    private final int d;

    // Four 64-bit words of internal state.
    // The initial state corresponds to the ASCII string "somepseudorandomlygeneratedbytes",
    // big-endian encoded. There is nothing special about this value; the only requirement
    // was some asymmetry so that the initial v0 and v1 differ from v2 and v3.
    private long v0 = 0x736f6d6570736575L;
    private long v1 = 0x646f72616e646f6dL;
    private long v2 = 0x6c7967656e657261L;
    private long v3 = 0x7465646279746573L;

    // The number of bytes in the input.
    private long b = 0;

    // The final 64-bit chunk includes the last 0 through 7 bytes of m followed by null bytes
    // and ending with a byte encoding the positive integer b mod 256.
    private long finalM = 0;

    SipHasher(int c, int d, long k0, long k1) {
      super(CHUNK_SIZE);
      this.c = c;
      this.d = d;
      this.v0 ^= k0;
      this.v1 ^= k1;
      this.v2 ^= k0;
      this.v3 ^= k1;
    }

    @Override
    protected void process(ByteBuffer buffer) {
      b += CHUNK_SIZE;
      processM(buffer.getLong());
    }

    @Override
    protected void processRemaining(ByteBuffer buffer) {
      b += buffer.remaining();
      for (int i = 0; buffer.hasRemaining(); i += 8) {
        finalM ^= (buffer.get() & 0xFFL) << i;
      }
    }

    @Override
    public HashCode makeHash() {
      // End with a byte encoding the positive integer b mod 256.
      finalM ^= b << 56;
      processM(finalM);

      // Finalization
      v2 ^= 0xFFL;
      sipRound(d);
      return HashCode.fromLong(v0 ^ v1 ^ v2 ^ v3);
    }

    private void processM(long m) {
      v3 ^= m;
      sipRound(c);
      v0 ^= m;
    }

    private void sipRound(int iterations) {
      for (int i = 0; i < iterations; i++) {
        v0 += v1;
        v2 += v3;
        v1 = Long.rotateLeft(v1, 13);
        v3 = Long.rotateLeft(v3, 16);
        v1 ^= v0;
        v3 ^= v2;
        v0 = Long.rotateLeft(v0, 32);
        v2 += v1;
        v0 += v3;
        v1 = Long.rotateLeft(v1, 17);
        v3 = Long.rotateLeft(v3, 21);
        v1 ^= v2;
        v3 ^= v0;
        v2 = Long.rotateLeft(v2, 32);
      }
    }
  }

  private static final long serialVersionUID = 0L;
}

Other Java examples (source code examples)

Here is a short list of links related to this Java SipHashFunction.java source code file:

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.