/********************************  regenphf.c *****************************

   Purpose:	Routines to regenerate and use a previously-computed
   		minimal perfect hashing function.

   Provenance:	Written and tested by Q. Chen and E. Fox, March 1991.
   		Edited and tested by S. Wartik, April 1991.

   Notes:	None.
**/

#include <stdio.h>

#include "types.h"
#include "rantab.h"
#include "regenphf.h"
#include "comphfns.h"


/*************************************************************************

	regen_mphf( mphfType*, char* )

   Return:	int -- NORM if the MPHF could be reconstructed,
   		ABNORM if it couldn't.

   Purpose:	Regenerate a MPHF from a specification file.

   Notes:	What is regenerated is the table of random numbers.  The
   		retrieve() procedure can use these numbers to re-create
		the h0, h1 and h2 values, and from that, the hash value.

		If the specification file doesn't seem to correspond
		to the expected format, ABNORM is returned.  However,
		there is no way to tell what caused the error.
**/

int regen_mphf( mphf, spec_file_name )
    mphfType	*mphf;              /* out: the regenerated MPHF structure. */ 
    char	*spec_file_name;    /* in: MPHF specification file.	    */
{
    int		i;		    /* Iterator through vertices.	    */
    FILE	*spec_file;

    if ( (spec_file = fopen(spec_file_name, "r")) == NULL ) return ABNORM;

    if ( fscanf(spec_file, "%d\n%d\n%d\n", 
	   &mphf->no_arcs, &mphf->no_vertices, &mphf->seed) != 3 ) {
	fclose(spec_file);
	return ABNORM;		/* File is improperly formatted. */
    }

    mphf->gArray = (int*) owncalloc( mphf->no_vertices, sizeof(int) );

    for ( i = 0; i < mphf->no_vertices; i++ ) 
	if ( fscanf(spec_file, "%d\n", &mphf->gArray[i] ) != 1 ) {
	    fclose(spec_file);
	    return ABNORM;	/* File is improperly formatted. */
	}

    if ( ! feof(spec_file) ) {
	fclose(spec_file);
	return ABNORM;		/* File is improperly formatted. */
    }

    initialize_randomTable( mphf->tables, &mphf->seed );

    fclose(spec_file);

    return NORM;
}


/*************************************************************************

	release_mphf( mphfType*, char* )

   Return:	void

   Purpose:	Release the dynamically-allocated storage associated with
   		an MPHF.

**/

void release_mphf( mphf )
    mphfType *mphf;          /* in out: pointer to the MPHF structure.  */ 
{
    free( (char *)mphf->gArray );
}


/*************************************************************************

       retrieve( mphfType*, char* )

   Return:	int -- a value in the range 0..mphf->no_arcs-1.

   Purpose:	Given an MPHF and a key, return the key's hash value.

**/

int retrieve( mphf, key )
    mphfType	*mphf;      /* in: the mphf specification.                  */
    char	*key;       /* in: the key, terminated by a null character. */
{
    int		hash;       /* The computed hash value.                     */
    arcType	arc;	    /* Storage used to hold the h0, h1 and h2 values. */

    compute_h012(mphf->no_arcs, (mphf->no_vertices) / 2, 
		 mphf->tables, key, &arc);
    hash = abs(arc.h0 +                
	       mphf->gArray[arc.h12[0]] + 
	       mphf->gArray[arc.h12[1]] 
	       ) % mphf->no_arcs;
    return hash;
}
