/* hashtable.c -- (C) Geoffrey Reynolds, April 2006.

   Hash table implementation of the baby steps giant steps lookup table.

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2 of the License, or
   (at your option) any later version.
*/

#include <assert.h>
#include <stdlib.h>
#include "sr5sieve.h"
#include "hashtable.h"

HASH_T *htable;
HASH_T *olist;
uint32_t hsize;
uint32_t hsize_minus1;
uint64_t *BJ64;
HASH_T empty_slot;

void init_hashtable(uint32_t M)
{
  uint32_t shifts;

  assert(hsize == 0);
  assert(M <= HASH_MAX_ELTS);

  M = MAX(M,HASH_MINIMUM_SIZE);
  for (hsize = 1, shifts = 0; hsize < M/HASH_MAX_DENSITY; shifts++)
    hsize <<= 1;
  hsize_minus1 = hsize - 1;
  
  htable = xmalloc(hsize*sizeof(HASH_T));
  olist = xmalloc(M*sizeof(HASH_T));

  /* The j values are all in the range 0 <= j < M, so we can use M as an
     empty slot marker as long as we fill BJ[M] with a value that will never
     match a real b^j value. Since b^j is always in the range 0 <= b^j < p
     for some prime p, any value larger than all 32/64 bit primes will do.

     TODO: It would be nice if empty_slot could be a compile-time constant.
  */
  empty_slot = M;
  BJ64 = xmalloc((M+1)*sizeof(uint64_t));
  BJ64[empty_slot] = UINT64_MAX;
}

void fini_hashtable(void)
{
  assert (hsize > 0);

  free(BJ64);
  free(olist);
  free(htable);
  hsize = 0;
}
