static char *SccsId = "@(#)getsig.c 4.1 (TU-Delft) 05/24/90";
/**********************************************************

Name/Version      : sls/4.1

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

Author(s)         : A.C. de Graaf, A.J. van Genderen
Creation date     : 10-Jul-1986
Modified by       : S. de Graaf
Modification date : 10-Jul-1986


        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 "extern.h"

warningdone = FALSE;

getsignal (n, t, sigev)
NODE * n;
int t;
SIGNALEVENT * sigev;
{
    int t_s;
    int tevent_s;
    int tnextevent_s;
    int tev;
    int tnev;
    int first;
    double flo_to_doub ();

    first = TRUE;
    if (t < 0) {
        sigev -> time = 0;    /* the first event has to be get */
        sigev -> val = getsigval (n -> forcedinfo -> insignal, 0);
        return;
    }

    t_s = d_round ((double)t / 
	           flo_to_doub (n -> forcedinfo -> sigmult * sigtoint));

    getsigev (n -> forcedinfo -> insignal, t_s, &tnextevent_s);
    do {
	if (!first && !warningdone) {
	    slserror (NULL, 0, WARNING, 
	    "multiple signal change within simulation time accurracy", NULL);
	    warningdone = TRUE;
	}
	first = FALSE;
	tevent_s = tnextevent_s;
	if (tevent_s >= 0)
            getsigev (n -> forcedinfo -> insignal, tevent_s, &tnextevent_s);
        tev = d_round ((double)tevent_s *
		       flo_to_doub (n -> forcedinfo -> sigmult * sigtoint));
        tnev = d_round ((double)tnextevent_s * 
			flo_to_doub (n -> forcedinfo -> sigmult * sigtoint));
    }
    while ((tev == tnev || tev <= t) && tevent_s >= 0 && tnextevent_s >= 0);

    if (tevent_s < 0 || tev == t) {
	sigev -> time = -1;
    }
    else {
        sigev -> time = tev;
        sigev -> val = getsigval (n -> forcedinfo -> insignal, tevent_s);
    }
}

getsigev (head, t, tevent)
SIGNALELEMENT * head;
int t;
int * tevent;
{
    SIGNALELEMENT * sgn_ptr = head;

    t += sig_toffset;

    *tevent = 0;

    if (t >= 0) {
	if (t >= sgn_ptr -> len && sgn_ptr -> len > 0) {
	    *tevent = -1;
	}
	else {
	    getsigev1 (sgn_ptr -> sibling, t, tevent);
	    if (*tevent >= 0)
		*tevent += t;
	}
    }
    
    *tevent -= sig_toffset;
}

getsigev1 (head, t, tevent)
SIGNALELEMENT * head;
int t;
int * tevent;
{
    SIGNALELEMENT * sgn_ptr = head;

    if (t < sgn_ptr -> len || sgn_ptr -> len < 0) {
	if (sgn_ptr -> child) {
	    getsigev1 (sgn_ptr -> child -> sibling, 
	    t % sgn_ptr -> child -> len, tevent);
	}
	else {
	    *tevent += sgn_ptr -> len - t;
	}
    }
    else
	if (t >= sgn_ptr -> len) {
	    getsigev1 (sgn_ptr -> sibling, t - sgn_ptr -> len, tevent);
	}
}

getsigval (head, t)
SIGNALELEMENT * head;
int     t;
{
    SIGNALELEMENT * sgn_ptr = head;

    t += sig_toffset;

    if (t < 0)
	return (sgn_ptr -> sibling -> val);
    else {
	if (t >= sgn_ptr -> len && sgn_ptr -> len > 0)
	    return (sgn_ptr -> val);
	else
	    return (getsigval1 (sgn_ptr -> sibling, t));
    }
}

getsigval1 (head, t)
SIGNALELEMENT * head;
int     t;
{
    SIGNALELEMENT * sgn_ptr = head;

    if (t < sgn_ptr -> len || sgn_ptr -> len < 0) {
	if (sgn_ptr -> child)
	    return (getsigval1 (sgn_ptr -> child -> sibling, 
                                t % sgn_ptr -> child -> len));
	else
	    return (sgn_ptr -> val);
    }

    return (getsigval1 (sgn_ptr -> sibling, t - sgn_ptr -> len));
}

double flo_to_doub (f)  /* converts the first 6 decimals of a float */
float f;                /* to a double and fills the rest with 0's  */
{
    int i;
    int h;
    double d;

    i = initconv (f);
    if (i < 0) {
	h = d_round ((double)f * (double)(-i) * 100000);
	d = (double) h / (double) (-i) / 100000;
    }
    else {
	h = d_round (((double)f / (double)i) * 100000);
	d = (double) h * (double)i / 100000;
    }

    return (d);
}
