static char *SccsId = "@(#)findNet.c 4.5 (TU-Delft) 07/22/92";
/**********************************************************

Name/Version      : xsls/4.5

Language          : C
Operating system  : UNIX SYSTEM V
Host machine      : HP9000

Author(s)         : A.J. van Genderen
Creation date     : 16-Feb-1987
Modified by       : A.J. van Genderen
Modification date : 16-Feb-1987


        Delft University of Technology
        Department of Electrical Engineering
        Network Theory Section
        Mekelweg 4 - P.O.Box 5031
        2600 GA DELFT
        The Netherlands

        Phone : 015 - 786234

        COPYRIGHT (C) 1987 , All rights reserved
**********************************************************/
#include "incl.h"

extern int netCounter;

struct hash_ref {
    struct cir_net *n;
    struct cir_net *headn;
    struct hash_ref *next;
};

static struct hash_ref **hashtab;
static int hashSize;
static struct cir_net netelem;

int hashval ();

findNetInit (nets)
struct net_ref *nets;
{
    int nbr;
    int i;
    struct net_ref *nr;
    struct cir_net *eqv;
    struct hash_ref *href;
    struct hash_ref **hteladdr;

    hashSize = netCounter * 5;

    PALLOC (hashtab, hashSize, struct hash_ref *);
    for (i = 0; i < hashSize; i++) {
	hashtab[i] = NULL;
    }

    for (nr = nets; nr != NULL; nr = nr -> next) {
	eqv = nr -> n -> net_eqv;
	for (nbr = nr -> n -> net_neqv; nbr > 0; nbr--) {
	    PALLOC (href, 1, struct hash_ref);
	    href -> n = eqv;
	    href -> headn = nr -> n;
	    hteladdr = hashtab + hashval (eqv);
	    href -> next = *hteladdr;
	    *hteladdr = href;
	    eqv++;
	}
    }
}

static struct cir_net *fnet;

struct cir_net *findNet (eqv)
struct cir_net *eqv;
{
    int i;
    int found;
    int wrong;
    int nbr;
    int weight;
    struct hash_ref *href;
    struct cir_net *feqv;
    struct cir_net *retnet;

    /* NOTE it must hold that 
	  eqv -> inst_lower == eqv -> inst_upper
          and eqv -> net_lower == eqv -> net_upper ! 
    */

    href = hashtab[ hashval (eqv) ];

    found = 0;
    while (href != NULL && ! found) {
	if (strcmp (href -> n -> inst_name, eqv -> inst_name) == 0 
	 && strcmp (href -> n -> net_name, eqv -> net_name) == 0
	 && href -> n -> inst_dim == eqv -> inst_dim
	 && href -> n -> net_dim == eqv -> net_dim) {
	    wrong = 0;
	    for (i = 0; i < eqv -> inst_dim && ! wrong; i++) {
		if (eqv -> inst_lower[i] < href -> n -> inst_lower[i]
		 || eqv -> inst_upper[i] > href -> n -> inst_upper[i]) {
		    wrong = 1;
		}
	    }
	    for (i = 0; i < eqv -> net_dim && ! wrong; i++) {
		if (eqv -> net_lower[i] < href -> n -> net_lower[i]
		 || eqv -> net_upper[i] > href -> n -> net_upper[i]) {
		    wrong = 1;
		}
	    }
	    if (! wrong)
		found = 1;
	    else
		href = href -> next;
	}
	else
	    href = href -> next;
    }

    if (! found)
	return (NULL);

    fnet = href -> headn;
    feqv = href -> n;
    retnet = &netelem;

    strcpy (retnet -> inst_name, "");
    strcpy (retnet -> net_name, fnet -> net_name);
    retnet -> net_dim = fnet -> net_dim;
    FREE (retnet -> net_lower);
    FREE (retnet -> net_upper);
    if (retnet -> net_dim > 0) {
	PALLOC (retnet -> net_lower, retnet -> net_dim, long);
	PALLOC (retnet -> net_upper, retnet -> net_dim, long);
    }
    else {
	retnet -> net_lower = NULL;
	retnet -> net_upper = NULL;
    }

    nbr = 0;
    weight = 1;
    for (i = eqv -> net_dim - 1; i >= 0; i--) {
	nbr += (eqv -> net_lower[i] - feqv -> net_lower[i]) * weight;
	weight = (feqv -> net_upper[i] - feqv -> net_lower[i] + 1) * weight;
    }
    for (i = eqv -> inst_dim - 1; i >= 0; i--) {
	nbr += (eqv -> inst_lower[i] - feqv -> inst_lower[i]) * weight;
	weight = (feqv -> inst_upper[i] - feqv -> inst_lower[i] + 1) * weight;
    }

    weight = 1;
    for (i = fnet -> net_dim - 1; i >= 0; i--) {
	weight = (feqv -> ref_upper[i] - feqv -> ref_lower[i] + 1) * weight;
    }

    for (i = 0; i < fnet -> net_dim; i++) {
	weight = weight / (feqv -> ref_upper[i] - feqv -> ref_lower[i] + 1);
	retnet -> net_upper[i] = retnet -> net_lower[i] =
	    feqv -> ref_lower[i] + nbr / weight;
	nbr = nbr % weight;
    }

    if (nbr != 0) {
	fprintf (stderr, "Internal error\n");
	die ();
    }

    retnet -> net_neqv = fnet -> net_neqv;
    retnet -> net_eqv = fnet -> net_eqv;

    return (retnet);
}

struct cir_net *actNetFound ()
{
    /* This function may be called after findNet to get access to
       the actual net structure that is found by findNet */

    return (fnet);
}

int hashval (eqv)
struct cir_net *eqv;
{
    char *s;
    long val = 0;
    int i = 0;

    for (s = eqv -> inst_name; *s != '\0'; s++) {
	val += i * (int)*s;
	i++;
    }

    for (s = eqv -> net_name; *s != '\0'; s++) {
	val += i * (int)*s;
	i++;
    }

    val = val % hashSize;

    return ((int)val);
}

findNetEnd ()
{
    int i;
    struct hash_ref *href;
    struct hash_ref *help;

    for (i = 0; i < hashSize; i++) {
	href = hashtab[i];
	while (href != NULL) {
	    help = href;
	    href = href -> next;
	    FREE (help);
	}
    }

    FREE (hashtab);
}
