/* Copyright (c) 2001 by the Institute for Computer Science,               */
/* Alberts-Ludwigs-University of Freiburg, Germany.                        */
/* All Rights Reserved.  This software is for educational purposes only.   */
/* Permission is given to distribute this code provided that this intro-   */
/* ductory message is not removed and no monies are exchanged.             */
/* No guarantee is expressed or implied by the distribution of this code.  */
/* Software written by Alberto Lluch Lafuente and Stefan Edelkamp.         */
/* References:                                                             */
/* - Stefan Edelkamp, Alberto Lluch Lafuente and Stefan Leue,              */
/*   Directed Explicit Model Checking with HSF-SPIN, to appear in:         */
/*   Proc. 8th International SPIN Workshop on Model Checking Software,     */
/*   Springer LNCS 2057, Toronto, May 2001                                 */
/* - Stefan Edelkamp, Alberto Lluch Lafuente and Stefan Leue,              */
/*   Protocol Verification with Heuristic Search,                          */
/*   Proc. AAAI Spring Symposium on Model-Based Validation of Inteligence, */
/*   AAAI, Stanford, April 2001.                                           */
/* Send bug-reports or questions to: lafuente@informatik.uni-freiburg.de   */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#ifndef __UNIVERSAL_HASHING_CLASS_H__
#define __UNIVERSAL_HASHING_CLASS_H__

#define HOLZMANN_ORIGINAL 0       /* Holzmann's Original Hashing. */
#define HOLZMANN_NEW 1            /* Holzmann's New Hashing (random values instead of tables.) */
#define UNIVERSAL_H2 2            /* Universal H2 Hashing. */
#define UNIVERSAL_H3 3            /* Universal H3 Hashing. */
#define CYCLIC_POLYNOMIAL_HASH 4  /* Hashing by Cyclic Polynomial Division. */
#define GENERAL_POLYNOMIAL_HASH 5 /* Hashing by General Polynomial Division. */

class Hash_Function{
 public:
  int which_hashing;
  Hash_Function(int which, int max_instances);
  void rand();
  unsigned int hash(unsigned char *vector, int length);
  void double_hash(unsigned char *vector, int length, unsigned int *h1, unsigned int *h2);
 private:
#include "universal_hashing.c"
};

Hash_Function::Hash_Function(int which, int max_instances){
  which_hashing=which;
  switch(which_hashing){
  case HOLZMANN_ORIGINAL: Holz_original_init(max_instances); break;
  case HOLZMANN_NEW: Holz_new_init(max_instances); break;
  case UNIVERSAL_H2: universalH2_init(max_instances); break;
  case UNIVERSAL_H3: universalH3_init(max_instances); break;
  case CYCLIC_POLYNOMIAL_HASH: cyclicpoly_init(max_instances);  break;
  case GENERAL_POLYNOMIAL_HASH: generalpoly_init(max_instances); break;
  default: printf("Error: Undefined Hash Function\n"); exit(0);
  }
}

void Hash_Function::rand(){
  switch(which_hashing){
  case HOLZMANN_ORIGINAL: Holz_original_rand(); break;
  case HOLZMANN_NEW: Holz_new_rand(); break;
  case UNIVERSAL_H2: universalH2_rand(); break;
  case UNIVERSAL_H3: universalH3_rand(); break;
  case CYCLIC_POLYNOMIAL_HASH: cyclicpoly_rand();  break;
  case GENERAL_POLYNOMIAL_HASH: generalpoly_rand(); break;
  default: printf("Error: Undefined Hash Function\n"); exit(0);
  }
}

unsigned int Hash_Function::hash(unsigned char *vector, int length){
  unsigned int h;
  switch(which_hashing){
  case HOLZMANN_ORIGINAL: Holz_original_hash(vector,length,&h); break;
  case HOLZMANN_NEW: Holz_new_hash(vector,length,&h); break;
  case UNIVERSAL_H2: universalH2_hash(vector,length,&h); break;
  case UNIVERSAL_H3: universalH3_hash(vector,length,&h); break;
  case CYCLIC_POLYNOMIAL_HASH: cyclicpoly_hash(vector,length,&h);  break;
  case GENERAL_POLYNOMIAL_HASH: generalpoly_hash(vector,length,&h); break;
  default: printf("Error: Undefined Hash Function\n"); exit(0);
  }
  return h;
}

void Hash_Function::double_hash(unsigned char *vector, int length, unsigned int *h1, unsigned int *h2){
  switch(which_hashing){
  case HOLZMANN_ORIGINAL: Holz_original_d_hash(vector,length,h1,h2); break;
  case HOLZMANN_NEW: Holz_new_d_hash(vector,length,h1,h2); break;
  case UNIVERSAL_H2: universalH2_d_hash(vector,length,h1,h2); break;
  case UNIVERSAL_H3: universalH3_d_hash(vector,length,h1,h2); break;
  case CYCLIC_POLYNOMIAL_HASH: cyclicpoly_d_hash(vector,length,h1,h2);  break;
  case GENERAL_POLYNOMIAL_HASH: generalpoly_d_hash(vector,length,h1,h2); break;
  default: printf("Error: Undefined Hash Function\n"); exit(0);
  }
}

#endif //
