static char *SccsId = "@(#)simple.cls 4.7 (TU-Delft) 12/15/92";
/**********************************************************

Name/Version      : sls_mkdb/4.7

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

Author(s)         : A.J. van Genderen
Creation date     : 23-Jan-1989
Modified by       : 
Modification date :


        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) 1986 , All rights reserved
**********************************************************/
#include "sys_incl.h"
#class
#include "class.h"
#include "mkdbdefs.h"
#include "mkdbincl.h"

extern Netelem *notconnected;
extern DM_STREAM *dsp_net;
extern Network *curr_ntw;

class simpleNet * snetQueue = NULL;
int intNetCnt = 0;

class netMember * newNetMems ();
void initCi ();
void fillArrNet ();

void joinSimple (dnet, dnet_xs, inst, inst_xs, net, net_xs)
Netelem *dnet;
Stack *dnet_xs;
class ntwinst *inst;
Stack *inst_xs;
Netelem *net;
Stack *net_xs;
{
    int j;
    int nbr;
    Netelem *pterm;
    Queue *termq;
    int termq_len;
    int dnet_off, inst_off, net_off;
    class netMember *net1mem, *net2mem;
    class netMember *net1memlast;
    class simpleNet *snet1, *snet2;
    int dnet_ci[XSTACK_SIZE];
    int inst_ci[XSTACK_SIZE];
    int net_ci[XSTACK_SIZE];

    if (dnet -> nmem == NULL) {
	dnet -> nmem = newNetMems (-1, (class ntwinst *)NULL, dnet);
    };

    if (inst != NULL && inst -> inst_struct -> nmem == NULL) {

	termq = inst -> ntw -> termq;
	termq_len = termq -> length ();

	inst -> inst_struct -> termCnt = 0;

	for (j = 0, pterm = (Netelem *) termq -> first_elem ();
	     j < termq_len;
	     j++, pterm = (Netelem *) termq -> next_elem ((Link *)pterm)) {

	    pterm -> nmem = inst -> inst_struct -> termCnt;

	    inst -> inst_struct -> termCnt += getxslength (pterm -> xs);
	}

	nbr = (inst -> inst_struct -> termCnt) 
	        * getxslength (inst -> inst_struct -> inst_construct);

	inst -> inst_struct -> nmem = newNetMems (nbr, inst, NULL);
    }

    if (inst == NULL && net -> nmem == NULL) {
	net -> nmem = newNetMems (-1, (class ntwinst *)NULL, net);
    }

    /* now, perform the joining */

    initCi (dnet_xs, dnet_ci);
    initCi (inst_xs, inst_ci);
    initCi (net_xs, net_ci);

    do {
        dnet_off = findOffset (dnet -> xs, dnet_ci);
	net_off = findOffset (net -> xs, net_ci);
	if (inst)
	    inst_off = findOffset (inst -> inst_struct -> inst_construct, 
				   inst_ci);

        net1mem = (dnet -> nmem) + dnet_off;
	if (inst)
	    net2mem = (inst -> inst_struct -> nmem) 
		      + inst_off * inst -> inst_struct -> termCnt
		      + (int)(net -> nmem) + net_off;
	else
	    net2mem = (net -> nmem) + net_off;
	
	snet1 = net1mem -> snet;
	snet2 = net2mem -> snet;

        if (snet1 == snet2)
	    continue;       /* already joined */

	net1memlast = net1mem;
	while (net1memlast -> next)
	    net1memlast = net1memlast -> next;

        if (snet2) {
	    net1memlast -> next = snet2 -> nmem;   /* join lists */
	    net1memlast = net1memlast -> next;
	    while (net1memlast) {
		net1memlast -> snet = snet1;
		net1memlast = net1memlast -> next;
	    }
	    
	    if (snet2 -> prev)
		snet2 -> prev -> next = snet2 -> next;
	    else
		snetQueue = snet2 -> next;
	    if (snet2 -> next)
		snet2 -> next -> prev = snet2 -> prev;
	}
	else {
	    net1memlast -> next = net2mem;
	    net2mem -> snet = snet1;
	}

	if (snet2)
	    delete snet2;
    }
    while (incrCi (dnet_xs, dnet_ci)
	   && (incrCi (net_xs, net_ci) || incrCi (inst_xs, inst_ci)));

}

class netMember *newNetMems (nr, inst, net)
int nr;
class ntwinst * inst;
Netelem * net;
{
    int i;
    class netMember *ret;
    class netMember *r;
    Queue *termq;
    int termq_len;
    int tlen;
    int ilen;
    int i_termNext;
    Netelem *pterm;
    Netelem *ptermNext;

    if (inst) {
	termq = inst -> ntw -> termq;
	termq_len = termq -> length ();
	if (termq_len > 0) {
	    pterm = (Netelem *) termq -> first_elem ();
	}
	else {
	    pterm = NULL;
	}
	tlen = 1;
	if (termq_len > 1) {
	    ptermNext = (Netelem *) termq -> next_elem ((Link *)pterm);
	    i_termNext = (int)(ptermNext -> nmem);
	    tlen++;
	}
	else {
	    ptermNext = NULL;
	    i_termNext = inst -> inst_struct -> termCnt;
	}
	ilen = 0;
    }
    else {
	nr = getxslength (net -> xs);
    }

    ret = new class netMember [nr];
    for (i = 0; i < nr; i++) {
	r = ret + i;
	r -> inst = inst;
	r -> next = NULL;
	r -> snet = new class simpleNet;
	r -> snet -> nmem = r;
	r -> snet -> next = snetQueue;
	if (snetQueue) {
	    snetQueue -> prev = r -> snet;
	}
	snetQueue = r -> snet;
	r -> snet -> prev = NULL;

	if (inst) {
	    if (i >= i_termNext) {
		pterm = ptermNext;
		if (tlen >= termq_len) {
		    ptermNext = (Netelem *) termq -> first_elem ();
		    tlen = 1;
		    ilen++;
		    i_termNext = ilen * inst -> inst_struct -> termCnt;
		}
		else {
		    ptermNext = (Netelem *) termq 
				             -> next_elem ((Link *)ptermNext);
		    i_termNext = ilen * inst -> inst_struct -> termCnt
				 + (int)(ptermNext -> nmem);
		    tlen++;
		}
	    }
	    r -> net = pterm;
	}
	else
	    r -> net = net;
    }

    return (ret);
}

void initCi (xs, ci)
Stack *xs;
int *ci;
{
    int i;
    char **pxs;
    int lb, rb;

    if (xs) {
	i = xs -> limit () - xs -> base ();
	pxs = xs -> limit ();

        i--;
	pxs--;
	for ( ; i >= 0; i--) {
	    lb = ((Xelem *) * pxs) -> left_bound;
	    rb = ((Xelem *) * pxs) -> right_bound;
	    if (lb > rb)
		ci[i] = rb;
	    else
		ci[i] = lb;
	    if (i > 0) pxs--;
	}    
    }
}

int incrCi (xs, ci)
Stack *xs;
int *ci;
{
    int i;
    int n;
    int offset;
    int goOn;
    char **pxs;
    int lb, rb;

    if (xs) {
	i = xs -> limit () - xs -> base ();
	pxs = xs -> limit ();

        i--;
	pxs--;
	goOn = 1;
	for ( ; i >= 0 && goOn; i--) {
	    lb = ((Xelem *) * pxs) -> left_bound;
	    rb = ((Xelem *) * pxs) -> right_bound;
	    if (rb > lb) {
		ci[i]++;
		if (ci[i] > rb)
		    ci[i] = lb;
		else
		    goOn = 0;
	    }
	    else {
		ci[i]--;
		if (ci[i] < lb)
		    ci[i] = rb;
		else
		    goOn = 0;
	    }
	    if (i > 0) pxs--;
	}    
	if (goOn)
	    return (0);  /* all values have been reset */
	else
	    return (1);
    }
    else
	return (0);
}

int findOffset (xsdef, ci)
Stack *xsdef;
int *ci;
{
    int i;
    int n;
    int offset;
    int weight;
    char **pxs;
    int lb, rb;

    offset = 0;

    if (xsdef) {
	i = xsdef -> limit () - xsdef -> base ();
	pxs = xsdef -> limit ();

        i--;
	pxs--;
	weight = 1;
	for ( ; i >= 0; i--) {
	    lb = ((Xelem *) * pxs) -> left_bound;
	    rb = ((Xelem *) * pxs) -> right_bound;
	    if (rb > lb) {
		offset += (ci[i] - lb) * weight;
		weight = weight * (rb - lb + 1);
	    }
	    else {
		offset += (ci[i] - rb) * weight;
		weight = weight * (lb - rb + 1);
	    }
	    if (i > 0) pxs--;
	}
    }

    return (offset);
}

void outSimple (q)
Queue *q;
{
    int i,
        j;
    int nr;
    int k;
    class simpleNet * snet;
    class simpleNet * snetOld;
    class netMember * otherMem;
    class netMember * eqvMem;
    Netelem *pnet;
    char **pxs;

    if (!q -> empty ()) {
	for (i = 0, pnet = (Netelem *) q -> first_elem ();
	     i < q -> length ();
	     i++, pnet = (Netelem *) q -> next_elem ((Link *) pnet)) {

	    if (!noWarnings && pnet != notconnected && pnet -> nmem == NULL 
		&& (pnet -> type & N_TERMINAL) && !(pnet -> type & N_GLOBADDED))
		fprintf (stderr, 
			 "Warning: network %s, unconnected terminal %s\n",
			 curr_ntw -> ntw_name, pnet -> name);

	    if (pnet == notconnected || pnet -> xs == NULL)
		continue;

	    strcpy (cnet.net_name, pnet -> name); 

	    if (cnet.net_dim > 0) {
		delete cnet.net_lower;
		delete cnet.net_upper;
	    }
			
	    cnet.net_dim = pnet -> xs -> limit () - pnet -> xs -> base ();

	    cnet.net_lower = new long [cnet.net_dim];
	    cnet.net_upper = new long [cnet.net_dim];

	    for (j = 0, pxs = pnet -> xs -> base (); 
		 pxs < pnet -> xs -> limit (); 
		 j++, pxs++) {

		cnet.net_lower[j] = ((Xelem *) * pxs) -> left_bound;
		cnet.net_upper[j] = ((Xelem *) * pxs) -> right_bound;
	    }

	    cnet.net_neqv = 0;

	    dmPutDesignData (dsp_net, CIR_NET);
	}
    }

    snet = snetQueue; 
    while (snet != NULL) {

	if (snet -> nmem -> net != notconnected) {

	    if (genIntNet && snet -> nmem -> net -> xs) {
		sprintf (cnet.net_name, "_N%d", ++intNetCnt); 
		if (cnet.net_dim > 0) {
		    delete cnet.net_lower;
		    delete cnet.net_upper;
		}
		cnet.net_dim = 0;
		eqvMem = snet -> nmem;
	    }
	    else {
		strcpy (cnet.net_name, snet -> nmem -> net -> name); 
		fillArrNet (&cnet, snet -> nmem, NULL);
		eqvMem = snet -> nmem -> next;
	    }

	    otherMem = eqvMem;
	    nr = 0;
	    while (otherMem) {
		if (otherMem -> net != notconnected)
		    nr++;
		otherMem = otherMem -> next;
	    }

	    if (cnet.net_neqv > 0)
		delete cnet.net_eqv;

	    cnet.net_neqv = nr;
	    cnet.net_eqv = new struct cir_net [cnet.net_neqv];

	    otherMem = eqvMem;
	    i = 0;
	    while (otherMem) {

		if (otherMem -> net == notconnected) {
		    otherMem = otherMem -> next;
		    continue;
		}

		strcpy (cnet.net_eqv[i].net_name, otherMem -> net -> name);
		if (otherMem -> inst) {
		    strcpy (cnet.net_eqv[i].inst_name, 
			    otherMem -> inst -> inst_struct -> inst_name);
		}
		else {
		    strcpy (cnet.net_eqv[i].inst_name, "");
		}
		fillArrNet (&cnet.net_eqv[i], otherMem, &cnet);

		otherMem = otherMem -> next;

		i++;
	    }

	    if (!noWarnings && i < 1) {
		fprintf (stderr, 
			 "Warning: network %s, unconnected terminal %s",
			 curr_ntw -> ntw_name, cnet.net_name);
		if (cnet.net_dim > 0) {
		    fprintf (stderr, "[");
		    for (k = 0; k < cnet.net_dim; k++) {
			if (k != 0)
			    fprintf (stderr, ", ");
			fprintf (stderr, "%ld", cnet.net_lower[k]);
		    }
		    fprintf (stderr, "]");
		}
		fprintf (stderr, "\n");
	    }

	    dmPutDesignData (dsp_net, CIR_NET);

	}

        snetOld = snet;

	snet = snet -> next;

	delete snetOld;
    }

    snetQueue = NULL;
    intNetCnt = 0;

    while(!q -> empty()) { 
	pnet = (Netelem *) q -> get(); 
	if (pnet -> nmem)
	    delete pnet -> nmem;
	delete pnet;
    }
    delete q;
}

int cis[XSTACK_SIZE];

void fillArrNet (pcnet, nmem, prefcnet)
struct cir_net *pcnet;
class netMember *nmem;
struct cir_net *prefcnet;
{
    int i;
    int offs;
    int i_offs;
    class netMember *help;

    if (nmem -> inst) {

	if (pcnet -> inst_dim > 0) {
	    delete pcnet -> inst_lower;
	    delete pcnet -> inst_upper;
	}

        help = nmem - nmem -> inst -> inst_struct -> nmem;
	i_offs = (int)help;
	i_offs = i_offs / nmem -> inst -> inst_struct -> termCnt;

	pcnet -> inst_dim = findCi 
	   (nmem -> inst -> inst_struct -> inst_construct, i_offs);

	if (pcnet -> inst_dim > 0) {
	    pcnet -> inst_lower = new long [ pcnet -> inst_dim ];
	    pcnet -> inst_upper = new long [ pcnet -> inst_dim ];
	}

	for (i = 0; i < pcnet -> inst_dim; i++) {
	    pcnet -> inst_lower[i] = cis[i];
	    pcnet -> inst_upper[i] = cis[i];
	}
    }

    if (pcnet -> net_dim > 0) {
	delete pcnet -> net_lower;
	delete pcnet -> net_upper;
    }

    if (nmem -> inst) {
        help = nmem - (nmem -> inst -> inst_struct -> nmem 
		       + (i_offs * nmem -> inst -> inst_struct -> termCnt)
		       + (int)(nmem -> net -> nmem));
	offs = (int)help;
    }
    else {
        help = nmem - nmem -> net -> nmem;
	offs = (int)help;
    }

    pcnet -> net_dim = findCi (nmem -> net -> xs, offs);

    if (pcnet -> net_dim > 0) {
	pcnet -> net_lower = new long [ pcnet -> net_dim ];
	pcnet -> net_upper = new long [ pcnet -> net_dim ];
    }

    for (i = 0; i < pcnet -> net_dim; i++) {
	pcnet -> net_lower[i] = cis[i];
	pcnet -> net_upper[i] = cis[i];
    }

    if (prefcnet) {
	if (pcnet -> ref_dim > 0) {
	    delete pcnet -> ref_lower;
	    delete pcnet -> ref_upper;
	}

        pcnet -> ref_dim = prefcnet -> net_dim;

	if (pcnet -> ref_dim > 0) {
	    pcnet -> ref_lower = new long [ pcnet -> ref_dim ];
	    pcnet -> ref_upper = new long [ pcnet -> ref_dim ];
	}

	for (i = 0; i < pcnet -> ref_dim; i++) {
	    pcnet -> ref_lower[i] = prefcnet -> net_lower[i];
	    pcnet -> ref_upper[i] = prefcnet -> net_upper[i];
	}
    }
}

int findCi (xs, offset)
Stack *xs;
int offset;
{
    int i;
    int dim;
    int v;
    int weight;
    int lb, rb;
    char **pxs;

    int w[XSTACK_SIZE];

    if (xs) {
	dim = i = xs -> limit () - xs -> base ();
	pxs = xs -> limit ();

        i--;
	pxs--;
	weight = 1;
	for ( ; i >= 0; i--) {
	    rb = ((Xelem *) * pxs) -> right_bound;
	    lb = ((Xelem *) * pxs) -> left_bound;
	    w[i] = weight;
	    if (rb > lb) {
		weight = weight * (rb - lb + 1);
	    }
	    else {
		weight = weight * (lb - rb + 1);
	    }
	    if (i > 0) pxs--;
	}

        i = 0;
	for ( ; i < dim; i++) {
	    v = offset / w[i];
	    offset = offset % w[i];
	    rb = ((Xelem *) * pxs) -> right_bound;
	    lb = ((Xelem *) * pxs) -> left_bound;
	    if (lb < rb)
		cis[i] = lb + v;
	    else
		cis[i] = rb + v;
	    pxs++;
	}
    }
    else
	dim = 0;

    return (dim);
}
