/* 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   */

/****** AUXILIAR DEFINES, VARIABLES AND FUNCTIONS *****/
#define Polynomial 0xF10EB
#define PolyDegree  19
#define  MaxSymOrd   256

//const unsigned long int p=2147483647;   // = 2^31-1
//const long int y = 16807;
#define CONSTP 2147483647
#define CONSTY 16807
long int *A, *A2;
long int *B, *B2;
long int *MA, *MA2;
int primdiv_tab[256];
int MAX_INSTANCES;

/* Hash Functions */
unsigned long int THLmod(unsigned long int x, int j)         // a mod (2^j-1)
{
   unsigned long int tmp;

   tmp=(x>>j) + (x&((1<<j)-1));                   // was soll das !
   tmp=(tmp>>j) + tmp;
   tmp=(tmp>>j) + tmp;
   return(tmp);

} 

long int hModSpec2(long int  a, long int  b)
{
  // Task: Compute (a*b)%m for huge long ints (used in Lehmers algorithm)
  // Requirements: a,b<modul
  long int q,r,tmp;

  if(!(a) || !(b)) return 0;

  q=((long int)CONSTP)/(a);
  r=((long int)CONSTP)%(a);
  tmp=(a)*((b)%q)-r*((b)/q);

  if(tmp<0) return tmp+CONSTP;
  else return tmp;

};
/***** END AUXILIAR DEFINES, VARIABLES AND FUNCTIONS *****/


/****** ORIGINAL HOLZMANN *****/

int Holz_hash_nr;
int Holz_hash_index;
unsigned int HOLZMANN_HASH_CONST[32];

/* Holzmann's init function */
void Holz_original_init(int max_instances)
{
  if(max_instances>32){
    printf("Error! With Original Holzmann's Hashing, max_instances must be<32\n");
    exit(0);
  }
  Holz_hash_index=0;
  HOLZMANN_HASH_CONST[Holz_hash_index]=0x88888EEF; Holz_hash_index++;
  HOLZMANN_HASH_CONST[Holz_hash_index]=0x00400007; Holz_hash_index++;
  HOLZMANN_HASH_CONST[Holz_hash_index]=0x04c11db7; Holz_hash_index++;
  HOLZMANN_HASH_CONST[Holz_hash_index]=0x100d4e63; Holz_hash_index++;
  HOLZMANN_HASH_CONST[Holz_hash_index]=0x0fc22f87; Holz_hash_index++;
  HOLZMANN_HASH_CONST[Holz_hash_index]=0x3ff0c3ff; Holz_hash_index++;
  HOLZMANN_HASH_CONST[Holz_hash_index]=0x38e84cd7; Holz_hash_index++;
  HOLZMANN_HASH_CONST[Holz_hash_index]=0x02b148e9; Holz_hash_index++;
  HOLZMANN_HASH_CONST[Holz_hash_index]=0x98b2e49d; Holz_hash_index++;
  HOLZMANN_HASH_CONST[Holz_hash_index]=0xb616d379; Holz_hash_index++;
  HOLZMANN_HASH_CONST[Holz_hash_index]=0xa5247fd9; Holz_hash_index++;
  HOLZMANN_HASH_CONST[Holz_hash_index]=0xbae92a15; Holz_hash_index++;
  HOLZMANN_HASH_CONST[Holz_hash_index]=0xb91c8bc5; Holz_hash_index++;
  HOLZMANN_HASH_CONST[Holz_hash_index]=0x8e5880f3; Holz_hash_index++;
  HOLZMANN_HASH_CONST[Holz_hash_index]=0xacd7c069; Holz_hash_index++;
  HOLZMANN_HASH_CONST[Holz_hash_index]=0xb4c44bb3; Holz_hash_index++;
  HOLZMANN_HASH_CONST[Holz_hash_index]=0x2ead1fb7; Holz_hash_index++;
  HOLZMANN_HASH_CONST[Holz_hash_index]=0x8e428171; Holz_hash_index++;
  HOLZMANN_HASH_CONST[Holz_hash_index]=0xdbebd459; Holz_hash_index++;
  HOLZMANN_HASH_CONST[Holz_hash_index]=0x828ae611; Holz_hash_index++;
  HOLZMANN_HASH_CONST[Holz_hash_index]=0x6cb25933; Holz_hash_index++;
  HOLZMANN_HASH_CONST[Holz_hash_index]=0x86cdd651; Holz_hash_index++;
  HOLZMANN_HASH_CONST[Holz_hash_index]=0x9e8f5f21; Holz_hash_index++;
  HOLZMANN_HASH_CONST[Holz_hash_index]=0xd5f8d8e7; Holz_hash_index++;
  HOLZMANN_HASH_CONST[Holz_hash_index]=0x9c4e956f; Holz_hash_index++;
  HOLZMANN_HASH_CONST[Holz_hash_index]=0xb5cf2c71; Holz_hash_index++;
  HOLZMANN_HASH_CONST[Holz_hash_index]=0x2e805a6d; Holz_hash_index++;
  HOLZMANN_HASH_CONST[Holz_hash_index]=0x33fc3a55; Holz_hash_index++;
  HOLZMANN_HASH_CONST[Holz_hash_index]=0xaf203ed1; Holz_hash_index++;
  HOLZMANN_HASH_CONST[Holz_hash_index]=0xe31f5909; Holz_hash_index++;
  HOLZMANN_HASH_CONST[Holz_hash_index]=0x5276db35; Holz_hash_index++;
  HOLZMANN_HASH_CONST[Holz_hash_index]=0x0c565ef7; Holz_hash_index++;
  HOLZMANN_HASH_CONST[Holz_hash_index]=0x273d1aa5; Holz_hash_index++;
  HOLZMANN_HASH_CONST[Holz_hash_index]=0x8923b1dd; Holz_hash_index++;
  Holz_hash_index=0;
}

/* This function instances a new hash function */
void Holz_original_rand()
{
  Holz_hash_nr=HOLZMANN_HASH_CONST[Holz_hash_index];
  Holz_hash_index++;
}
 
void Holz_original_hash(unsigned char *vector, int length, unsigned int *h1)
{       long z = (long) Holz_hash_nr;
	long *q;
	long h;
	long m = -1;
	h = (length+sizeof(long)-1)/sizeof(long);
	q = (long *) vector;
	do {
		if (m < 0)
		{	m += m;
			m ^= z;
		} else
			m += m;
		m ^= *q++;
	} while (--h > 0);
	(*h1)=m;
}

/* Holzmann's Double Hash Function */
void Holz_original_d_hash(unsigned char *vector, int length, unsigned int *h1, unsigned int *h2)
{       long z = (long) Holz_hash_nr;
	long *q, *r, h;
	long m, n;
	unsigned char	*cp = vector;
	long	om = (long) length;

	h = (om+sizeof(long)-1)/sizeof(long);
	m = n = -1;
	q = r = (long *) cp;
	r += (long) h;
	do {
		if (m < 0)
		{	m += m;
			m ^= z;
		} else
			m += m;
		m ^= *q++;
		if (n < 0)
		{	n += n;
			n ^= z;
		} else
			n += n;
		n ^= *--r;
	} while (--h > 0);
	(*h1)=m;
	(*h2)=n;
}
/***** END ORIGINAL HOLZMANN *****/


/****** NEW HOLZMANN *****/

/* Holzmann's init function */
void Holz_new_init(int dummy)
{
}

/* This function instances a new hash function */
void Holz_new_rand()
{
  do{
    Holz_hash_nr=random();
  }while (Holz_hash_nr==0);
}
 
void Holz_new_hash(unsigned char *vector, int length, unsigned int *h1)
{       long z = (long) Holz_hash_nr;
	long *q;
	long h;
	long m = -1;
	h = (length+sizeof(long)-1)/sizeof(long);
	q = (long *) vector;
	do {
		if (m < 0)
		{	m += m;
			m ^= z;
		} else
			m += m;
		m ^= *q++;
	} while (--h > 0);
	(*h1)=m;
}

/* Holzmann's Double Hash Function */
void Holz_new_d_hash(unsigned char *vector, int length, unsigned int *h1, unsigned int *h2)
{       long z = (long) Holz_hash_nr;
	long *q, *r, h;
	long m, n;
	unsigned char	*cp = vector;
	long	om = (long) length;

	h = (om+sizeof(long)-1)/sizeof(long);
	m = n = -1;
	q = r = (long *) cp;
	r += (long) h;
	do {
		if (m < 0)
		{	m += m;
			m ^= z;
		} else
			m += m;
		m ^= *q++;
		if (n < 0)
		{	n += n;
			n ^= z;
		} else
			n += n;
		n ^= *--r;
	} while (--h > 0);
	(*h1)=m;
	(*h2)=n;
}
/***** END NEW HOLZMANN *****/


/***** UNIVERSAL HASHING *****/
void universalH2_init(int max_instances)
{  
    long int n; 
     //bestimme die Werte a, b, und Primzahl p
    MAX_INSTANCES=max_instances;
    n = (MAX_INSTANCES+sizeof(int)-1)/sizeof(int);

    A = (long int*)calloc(sizeof(long int),n+2);
    if (!A) printf("no space for array of long int A\n");

    B = (long int*)calloc(sizeof(long int),n+2);
    if (!B) printf("no space for array of long int B\n");
    
    A2 = (long int*)calloc(sizeof(long int),n+2);
    if (!A2) printf("no space for array of long int A\n");

    B2 = (long int*)calloc(sizeof(long int),n+2);
    if (!B2) printf("no space for array of long int B\n");

    // A2[n]=17; B2[n]=524287;
}

/* This function instances a new hash function */
void universalH2_rand(void)
{
    long int n;
    long int *x;
    int i;
    long int *a, *b;

    //bestimme die Werte a, b, und Primzahl p
    n = (MAX_INSTANCES+sizeof(int)-1)/sizeof(int);

    a = (long int*) A;
    b = (long int*) B;

    for (i=0;i<=n+1;i++)
    {
       *a=random();
       a++;
       *b=random();
       b++;
    }
       
    a = (long int*) A2;
    b = (long int*) B2;

    for (i=0;i<=n;i++)
    {
        *a=random();
        a++;
        *b=random();
        b++;
    }
}

/* Universal Single H2 Function */
void universalH2_hash(unsigned char *vector, int length, unsigned int *h1)
{
        int *q;
        int h;
        unsigned int m = 0;
        long int* a, *b;

        h = (length+sizeof(int)-1)/sizeof(int);
        a = A;
        a = a+(h+1);
        b = B;
        b = b+(h+1);
        q = (int *) vector;
        q = q+h;

        m = (hModSpec2(*a,*q)+(*b))%CONSTP;
        while (--h >= 0)
        {
            //berechne (ax+b) mod p fuer h-tes Feld
            //printf("Hashwert: %8X\n",m);
            m = m ^ (THLmod(hModSpec2(*(--a),*(--q))+*(--b),31));
            // m = m ^ (hModSpec2(*(--a),*(--q))+*(--b));
        }
	(*h1)=m;
}

/* Universal Double H2 Function */
void universalH2_d_hash(unsigned char *vector, int length, unsigned int *h1, unsigned int *h2)
{
        int *q,*q2;
        int h;
        unsigned int m= 0,n = 0;
        long int* a, *b, *a2, *b2;

        h = (length+sizeof(int)-1)/sizeof(int);
        a = A+(h+1);
        b = B+(h+1);
        q = ((int *) vector)+h;
       
        a2=A2+(h+1);
        b2=B2+(h+1);
        q2= ((int*) vector)+h; 
        
        m = (hModSpec2(*a,*q)+(*b))%CONSTP;
        n = (hModSpec2(*a2,*q2)+(*b2))%CONSTP;
        while (--h >= 0)
        {
            //berechne (ax+b) mod p fuer h-tes Feld
            //printf("Hashwert: %8X\n",m);
            m = m ^ (THLmod(hModSpec2(*(--a),*(--q))+*(--b),31));
            // m = m ^ (hModSpec2(*(--a),*(--q))+*(--b));
            n = n ^ (THLmod(hModSpec2(*(--a2),*(--q2))+*(--b2),31)); 
        }
	(*h1)=m;
	(*h2)=n;
}
/***** END UNIVERSAL H2 HASHING *****/


/***** UNIVERSAL H3 HASHING *****/

/* Universal H3 Init */
void universalH3_init(int max_instances)
{
    long int n;

    //bestimme die Werte a, b, und Primzahl p
    MAX_INSTANCES=max_instances;
    n = (MAX_INSTANCES+sizeof(int)-1)/sizeof(int);

    //printf("n %d  anz %d\n",n,32*n+1);
    MA = (long int*)calloc(sizeof(long int),32*n+1);
    if (!MA) printf("no space for array of long int A\n");
    MA2 = (long int*)calloc(sizeof(long int),32*n+1);
    if (!MA2) printf("no space for array of long int A2\n");
}

/* This function instances a new hash function */
void universalH3_rand(void)
{
    long int n;
    int i,j;
    long int *a, *a2;
    unsigned int hashWord, hashWord2;

   n = (MAX_INSTANCES+sizeof(int)-1)/sizeof(int); 
   
   a = (long int*) MA;
   a2 = (long int*) MA2;
   /*hashWord = -1;*/
   for (i=0; i<32*n; i++)
   {
      hashWord = random();
      hashWord = ( hashWord<<16);
      hashWord2 = random();
      hashWord = hashWord | (((1<<16)-1)&hashWord2);
      *a = hashWord;
      hashWord = random();
      hashWord = ( hashWord<<16);
      hashWord2 = random();
      hashWord = hashWord | (((1<<16)-1)&hashWord2);
      *a2 = hashWord;
      a2++;
      a++;
   }
}

/* Universal Single H3 Function */
void universalH3_hash(unsigned char *vector, int length, unsigned int *h1)
{
        int *q;
        int i,j;
        int h;
        unsigned int m;

        //printf("hash\n");
        h = (length+sizeof(int)-1)/sizeof(int);
        q = (int *) vector;

        m = 0;
        for (i=0;i<h;i++)
        {
            for (j=0;j<32;j++)
            {
                //printf("Hashwert: %8X\n",m);
                if ((*q)&(1<<(32-j)))
                {
                    m = m ^ (MA[32*i+j]);
                // printf("Multi: %8X %d %d %d %8X %8X\n",*q,i,j,32*i+j,MA[32*i+j],m);
                }
            }
            vector++;
        }
	(*h1)=m;
}

/* Universal Double H3 hash */
void universalH3_d_hash(unsigned char *vector, int length, unsigned int *h1, unsigned int *h2)
{
        int *q;
        int i,j;
        int h;
        unsigned int m,n;

        // printf("hash\n");
        h = (length+sizeof(int)-1)/sizeof(int);
        q = (int *) vector;

        m = 0;  n = 0;
        for (i=0;i<h;i++)
        {
            for (j=0;j<32;j++)
            {
                //printf("Hashwert: %8X\n",m);
                if ((*q)&(1<<(31-j)))
                {
                    m = m ^ (MA[32*i+j]);
                // printf("Multi: %8X %d %d %d %8X %8X\n",*q,i,j,32*i+j,MA[32*i+j],m);
                    n = n ^ (MA2[32*i+j]);
                }
            }
            q++;
	}
        // printf("Hashwert %8X\n",m);
	(*h1)=m;
	(*h2)=n;
}
/***** END UNIVERSAL H3 HASHING *****/


/***** CYCLIC POLYNOMS HASHING *****/
#define       word    32 
#define      delta     1 

unsigned long int  TransformationT[MaxSymOrd],TransformationT2[MaxSymOrd];
unsigned long int  rT[MaxSymOrd];
int THLcycrand_a;

/* Cyclic Polinoms Init */
void cyclicpoly_init(int dummy)
{
    int i,j,dup,a,a2,a1;
    a=THLcycrand_a=1;
    for (i=0;i<MaxSymOrd;i++)
    {
        a=hModSpec2(CONSTY,a);
        a1=a;
        a=hModSpec2(CONSTY,a);
        TransformationT[i]=(a<<16)|(a1&((1<<16)-1)); 
        // printf("Trans %3d :  %8X \n",i,TransformationT[i]);
    }
     for (i=0;i<MaxSymOrd;i++)
    {
        a=hModSpec2(CONSTY,a);
        a1=a;
        a=hModSpec2(CONSTY,a);
        TransformationT2[i]=(a<<16)|(a1&((1<<16)-1));
        // printf("Trans %3d :  %8X \n",i,TransformationT2[i]);
    }
    THLcycrand_a=a;
}

/* This function instances a new hash function */
void cyclicpoly_rand(void)
{
    int i,j,dup,a,a2,a1;
    unsigned int hashWord, hashWord2;
    
    for(i=0;i<MaxSymOrd;i++)
    {
      // dup=0;
      // while (dup==0)
      // {
          // TransformationT[i]=rand();  // &((1<<word)-1);
          //TransformationT[i]=lrand48();  // &((1<<word)-1);
          hashWord = random();
          hashWord = ( hashWord<<16);
          hashWord2 = random();
          hashWord = hashWord | (((1<<16)-1)&hashWord2);
          TransformationT[i]=hashWord;
          hashWord = random();
          hashWord = ( hashWord<<16);
          hashWord2 = random();
          hashWord = hashWord | (((1<<16)-1)&hashWord2);
          TransformationT2[i]=hashWord;
         // dup=1;j=0;
         // while((dup==1)&(j<i-1))
         // {
         //    if (TransformationT[j]==TransformationT[i])
         //       dup=0;
         //     if (TransformationT2[j]==TransformationT2[i])
         //       dup=0;
         //    j=j+1;
         // }
      // }
      // printf("Trans %3d :  %8X \n",i,TransformationT[i]);
    }
}

/* Cyclic Polynoms Single Hash Function */ 
void cyclicpoly_hash(unsigned char *vector, int length, unsigned int *h1)
{
    // int prime = 2^31-1;
   unsigned int i;
   unsigned char *q;
   int h;
   unsigned int m;

   // h = (length+sizeof(int)-1)/sizeof(int);
   h=length;
   q=vector;
   m=0;
   for(i=0;i<h;i++)
   {
      m=(m<<delta)|(m>>(word-delta));
      // printf("m : %8X\n",m);
      m=m^TransformationT[*q];
      // printf("m : %8X\n",m); 
      q=q+1;
   }
   (*h1)=m;
}

/* Cyclic Polynoms Double Hash Function */ 
void cyclicpoly_d_hash(unsigned char *vector, int length, unsigned int *h1, unsigned int *h2)
{
    // int prime = 2^31-1;
   unsigned int i;
   unsigned char *q,*q2;
   int h;
   unsigned int m,n;

   // h = (om+sizeof(int)-1)/sizeof(int);
   h=length;
   q=vector;
   q2=vector;
   m=0;n=0;
   for(i=0;i<h;i++)
   {
      m=(m<<delta)|(m>>(word-delta));
      // printf("m : %8X\n",m);
      m=m^TransformationT[*q];
      // printf("m : %8X\n",m);
      q=q+1;
     
      n=(n<<delta)|(n>>(word-delta));
      // printf("n : %8X\n",n);
      n=n^TransformationT2[*q];
      // printf("n : %8X\n",n);
      q2=q2+1;
   }
   (*h1)=m;
   (*h2)=n;
}
/***** END CYCLIC POLYNOMS HASHING*****/


/***** GENERAL POLYNOMS HASHING*****/
unsigned int THLhashWord; 

/* General Polynoms Init */
void generalpoly_init(int max_instances)
{
  int i,j;
  unsigned int hashWord;
 
  MAX_INSTANCES=max_instances;
  hashWord = THLhashWord=(unsigned int)-1; 
  for (i=0; i<MaxSymOrd; i++)
  {
     for(j=0; j <=MAX_INSTANCES; j++)
     {
        hashWord = (hashWord << 1); // &((1<<PolyDegree)-1);
        if((hashWord&(1<<PolyDegree))!=0)
           hashWord = hashWord^Polynomial;
        if (j==1)
           TransformationT[i]= hashWord;
        //else
        //   if (j==Nlength-1)
        //      rT[i]=hashWord;
     }
  }    
  for (i=0; i<MaxSymOrd; i++)
  {
     for(j=0; j <= MAX_INSTANCES; j++)
     {
        hashWord = (hashWord << 1); // &((1<<PolyDegree)-1);
        if((hashWord&(1<<PolyDegree))!=0)
           hashWord = hashWord^Polynomial;
        if (j==1)
           TransformationT2[i]= hashWord;
        //else
        //   if (j==length-1)
        //      rT[i]=hashWord;
     }
  }
  THLhashWord=hashWord;
}

/* This function instances a new hash function */
void generalpoly_rand(void)
{
  int i;
  unsigned int hashWord, hashWord2;
 
  for (i=0; i<MaxSymOrd; i++)
  {
     hashWord = random();
     hashWord = ( hashWord<<16);
     hashWord2 = random();
     hashWord = hashWord | (((1<<16)-1)&hashWord2); 
     hashWord = hashWord^Polynomial;
     TransformationT[i]= hashWord;
  }
  for (i=0; i<MaxSymOrd; i++)
  {
     hashWord = random(); 
     hashWord = ( hashWord<<16);
     hashWord2 = random();
     hashWord = hashWord | (((1<<16)-1)&hashWord2);
     hashWord = hashWord^Polynomial; 
     TransformationT2[i]= hashWord;
  }
}

/* General Polynoms Single Hash Function */
void generalpoly_hash(unsigned char *vector, int length, unsigned int *h1)
{
    // int prime = 2^31-1;
   unsigned int i;
   unsigned char *q;
   int h;
   unsigned int m;
   
   // h = (length+sizeof(int)-1)/sizeof(int);
   h=length;
   q=vector;
   m=0;
   for(i=0;i<h;i++)
   {
      m=(m<<1);
      if((m&(1<<PolyDegree))!=0)
        m=m^Polynomial;
      // printf("m : %8X\n",m);
      m=m^TransformationT[*q];
      // printf("m : %8X\n",m);
      q=q+1;
   }
   (*h1)=m;
}

void generalpoly_d_hash(unsigned char *vector, int length, unsigned int *h1, unsigned int *h2)
{
    // int prime = 2^31-1;
   unsigned int i;
   unsigned char *q,*q2;
   int h;
   unsigned int m,n;
 
   // h = (om+sizeof(int)-1)/sizeof(int);
   h=length;
   q=vector;
   q2=vector;
   m=0;n=0;
   for(i=0;i<h;i++)
   {
      m=(m<<1);
      if((m&(1<<PolyDegree))!=0)
        m=m^Polynomial;
      // printf("m : %8X\n",m);
      m=m^TransformationT[*q];
      // printf("m : %8X\n",m);
      q=q+1;
       
      n=(n<<1);
      if((n&(1<<PolyDegree))!=0)
        n=n^Polynomial;
      // printf("n : %8X\n",n);
      n=n^TransformationT2[*q];
      // printf("n : %8X\n",n);
      q2=q2+1; 
   }
   (*h1)=m;
   (*h2)=n;
}
/***** END GENERAL POLYNOMS HASHING*****/


/***** DIVISION REST HASHING */
int primdiv1_hash(unsigned char *vector ,int length, unsigned int *h1)
{     
   // int prime = 2^31-1;
   unsigned int i,radix = 257 ;// 257; //259 , 27, 256
   unsigned char *q;
   int h= length;
   unsigned int m;
 
   // h = (length+sizeof(int)-1)/sizeof(int);
   h=h-1;
   q = vector;
   m = *q;

   for(i=0;i<h;i++)
   {
      q=q+1;
      m = THLmod(*q+hModSpec2(radix,m),31);    
      //m = m &((1<<ssize)-1);                    // m mod B ! 
   } 
   (*h1)=m;
   return(length);
}


/* Faster Division Rest Hashing */
void primdiv_init()
{
    int i;
    //die berechnung hModSpec2(m,(1<<31)) wird durch ein
    //spaeterer table-lookup beschleunigt

    for (i=0;i<256;i++)
    {
         primdiv_tab[i] = hModSpec2((i<<1),(1<<31));
    }                            // was ist das !!

}

int primdiv_hash(unsigned char *vector ,int length, unsigned int *h1)
{
   // int prime = 2^31-1;
   unsigned int i, radix = 256;
   unsigned char *q;
   int h= length;
   unsigned int m, m1;
 
   // h = (length+sizeof(int)-1)/sizeof(int);
   h=h-1;
   q = vector;
   m =  *q;
  // m1 = *q;
   for(i=0;i<h;i++)
   {
      q=q+1;
      // m1 = THLmod(*q+hModSpec2(radix,m1),31);  // radix = 256
      m = THLmod((*q)+THLmod(((m&((1<<24)-1))<<8)+((m>>24)<<1),31),31);
      // if (m != m1) 
      //     printf("Warning m <> m1\n");
      // m = m &((1<<ssize)-1);                    // m mod B !
       
   } 
   (*h1)=m;
   return(length);
}

/* 2nd Power Division Rest Hashing */
int intdiv_hash(unsigned char *vector ,int length, unsigned int *h1)
{
   // int prime = 2^31-1;
   unsigned int i,radix = 256; // 257, 259 ,256, 27
   unsigned char *q;
   int h= length;
   unsigned int m;
   
   // h = (length+sizeof(int)-1)/sizeof(int);
   h=h-1;
   q = vector;
   m = *q; 
   for(i=0;i<h;i++)
   {
      q=q+1;
      m = (*q+radix*m)&((1<<(length))-1);   
      //m = ((*q) +  hModSpec2(radix,m))&((1<<(ssize))-1);  
   }
   (*h1)=m;
   return length;
}

/***** END DIVISION REST HASHING *****/
