#include <stdio.h>
#include <math.h>
#include <string.h>
#include <ctype.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/time.h>
#include </mit/cds/languages/elk/src/scheme.h>
#define HANDLE_PMF_CHAR_PER_ENTRY 10
#define HANDLE_PMF_INITIAL_CHAR 32

int T_Queue;

Object handle_queue_list(Object list, Object list2, Object list3)

int experiment, int curlength1, int curlength2,
			 int curtrials, long prevtotrials, int listlength,
			 int maxlength, float birthprob, float deathprob,
			 float varimult, char* oldlist1, char* oldlist2)
			 

{
int experiment, curlength1, curlength2, curtrials, listlength, maxlength;
long prevtottrials;
float birthprob, deathprob, varimult;
 /* input declarations */
 /* Note: 1 = birth/death ratio
    2 = service time variance   */
 /* internal declarations */
 float birth1prob, birth2prob;
 int i = 0;
 int true = 0;
 int totbirth1 = 0; 
 int totdeath1 = 0;
 int totbirth2 = 0;
 int totdeath2 = 0;
 long int totlength1 = 0;
 long int totlength2 = 0;
 int tottrials = 0;
 long int newtottrials;
 int strspc = 200;
 int totbalk1 = 0;
 int totbalk2 = 0;
 int servsomeone = 0; /* 0 = yes, 1 = no */
 int servtype = 0;   /* 1 = type A, 2 = type B  (see Jeff Turcotte's '91    */ 
 float floatmax = 0.0;                       /*      bachelor's thesis      */
 float trial, typeserv;
 float nextelement, fltnewtottrials, oneplusdeath, oneminusdeath;
 float maxm = 0.0;
 float maxr = 0.0; 
 float kval = 0.0;
 float bval = 0.0;
 float mval = 1.0;
 float probserved = 0.0;
 float probA, probB;
/*
int queuelist1[listlength];
int queuelist2[listlength];
*/
  
/* get the inputs */
 
 if (experiment == 1)
    {birth1prob = birthprob;
     birth2prob = deathprob;
     deathprob = 1.0 - varimult;
    }

/* char* oldlist1 = new char[strlen(arg[10]) + 4];
 char* oldlist2 = new char[strlen(arg[11]) + 4];
 strcpy(oldlist1, arg[10]);
 strcpy(oldlist2, arg[11]);
*/

/* transport the oldlists into arrays */
/*
char* anchor = new char[10];
char* nextval = new char[10];

i = 0;
while (i < listlength)
   {   
   while ( isdigit(*oldlist1) == 0 )
     oldlist1++;                         
   nextval = anchor;
   *nextval++ = *oldlist1++;
   while ( isdigit(*oldlist1) )
     *nextval++ = *oldlist1++;
   *nextval = '\0';
   queuelist1[i] = atoi(anchor);
   i++;
   }
i = 0;
while (i < listlength)
   {   
   while ( isdigit(*oldlist2) == 0 )
     oldlist2++;                         
   nextval = anchor;
   *nextval++ = *oldlist2++;
   while ( isdigit(*oldlist2) )
     *nextval++ = *oldlist2++;
   *nextval = '\0';
   queuelist2[i] = atoi(anchor);
   i++;
   }
*/
                          

/* check to see if birth/death ratio experiment is selected and do
   necessary processing  */

if (experiment == 1)
 {                       
   
floatmax = 2^31 -1;
i = 0;
while (i < curtrials)
  {
   trial = (float) random() / floatmax;
   tottrials++;
   if ( (trial < birth1prob) && (curlength1 == maxlength))
      {
       totbalk1++;
      }      
       else if (trial < birth1prob)
	 {
	   totbirth1++;
	   curlength1++;
	 } else
           {
             if ( (trial > deathprob) && (curlength1 > 0))
               {
                totdeath1++;
	        curlength1--;
               }
           }
   if (curlength1 <= listlength) queuelist1[curlength1]++;
   totlength1 = totlength1 + curlength1;
   if ( (trial < birth2prob) && (curlength2 == maxlength))
      {
       totbalk2++;
      }      
       else if (trial < birth2prob)
	 {
	   totbirth2++;
	   curlength2++;
	 } else
           {
             if ( (trial > deathprob) && (curlength2 > 0))
               {
                totdeath2++;
	        curlength2--;
               }
	    }
   if (curlength2 <= listlength) queuelist2[curlength2]++;
   totlength2 = totlength2 + curlength2;
   i++;
   }
}
 

/* check to see if service time variance experiment is selected and do
   necessary processing */

if (experiment == 2)
 {
floatmax = float(MAXLONG);
oneplusdeath = 1.0 + deathprob;
oneminusdeath = 1.0 - deathprob;
maxm = (1.0 - birthprob) / deathprob;
maxr =(2.0 * maxm * maxm * maxm) - ((maxm * maxm + maxm) * oneplusdeath) + 2.0;
maxr = maxr / ( (maxm + 1) * maxm * oneminusdeath);
if (varimult > maxr) varimult = maxr;
kval = oneplusdeath + (varimult * oneminusdeath);
bval = 1.0 + ( kval / 2.0);
mval = (bval + sqrt(bval * bval - 4.0)) / 2.0;
if (varimult == 1.0) mval = 1.0;
probA = mval / (1 + mval);
probB = 1.0 - probA;
servsomeone = 0;
i = 0;
while (i < curtrials)
  {
   trial = float(rand()) / floatmax;
   typeserv = float(rand()) / floatmax;
   tottrials++;
   if ( (trial < birthprob) && (curlength1 == maxlength))
      {
       totbalk1++;
      }      
       else if (trial < birthprob)
	 {
	   totbirth1++;
	   curlength1++;
	 } else
           {
             if ( (trial > oneminusdeath) && (curlength1 > 0))
               {
                totdeath1++;
	        curlength1--;
               }
	   }
   if (curlength1 <= listlength) queuelist1[curlength1]++;
   totlength1 = totlength1 + curlength1;


/* see if a service type has to be determined because a new customer has
   approached the server      */

   if (servsomeone == 0) 
     {
       if (typeserv < probA) servtype = 0;
          else servtype = 1;
       if (servtype == 0) probserved = deathprob * mval;
         else probserved = deathprob / mval;
       probserved = 1.0 - probserved;
       servsomeone = 1;
     }

   if ( (trial < birthprob) && (curlength2 == maxlength))
      {
       totbalk2++;
      }      
       else if (trial < birthprob)
	 {
	   totbirth2++;
	   curlength2++;
	 } else
          {
          if ( (trial > probserved) && (curlength2 > 0))
             {
               totdeath2++;
	       curlength2--;
	       servsomeone = 0;
              } 
	   }
   if (curlength2 <= listlength) queuelist2[curlength2]++;
   totlength2 = totlength2 + curlength2;
   i++;
   }

}


/* construct output list */

newtottrials = tottrials + prevtottrials;
fltnewtottrials = float(newtottrials);
strspc = listlength * 50 + 200;
char* ans = new char[strspc];
char nextstring[16];
strcpy(ans,"( ");
sprintf(nextstring, "%f", maxr);
strcat(ans, nextstring);
strcat(ans, " ");
sprintf(nextstring, "%ld", newtottrials);
strcat(ans, nextstring);
strcat(ans, " ( ");
sprintf(nextstring, "%d", totbirth1);
strcat(ans, nextstring);
strcat(ans, " ");
sprintf(nextstring, "%d", totdeath1);
strcat(ans, nextstring);
strcat(ans, " ");
sprintf(nextstring, "%d", totlength1);
strcat(ans, nextstring);
strcat(ans, " ");
sprintf(nextstring, "%d", curlength1);
strcat(ans, nextstring);
strcat(ans, " ");
sprintf(nextstring, "%d", totbalk1);
strcat(ans, nextstring);
strcat(ans, " ) ( ");
sprintf(nextstring, "%d", totbirth2);
strcat(ans, nextstring);
strcat(ans, " ");
sprintf(nextstring, "%d", totdeath2);
strcat(ans, nextstring);
strcat(ans, " ");
sprintf(nextstring, "%d", totlength2);
strcat(ans, nextstring);
strcat(ans, " ");
sprintf(nextstring, "%d", curlength2);
strcat(ans, nextstring);
strcat(ans, " ");
sprintf(nextstring, "%d", totbalk2);
strcat(ans, nextstring);
strcat(ans, " ) ( ");

i = 0;
while (i < listlength)
   {
    sprintf(nextstring, "%d", queuelist1[i]);                           
    strcat(ans, nextstring);
    strcat(ans, " ");
    i++;
    }  
strcat(ans, ") ( ");
i = 0;
while (i < listlength)
   {
    sprintf(nextstring, "%d", queuelist2[i]);                           
    strcat(ans, nextstring);
    strcat(ans, " ");
    i++;
    }  
strcat(ans, ") ( ");
i = 0;
while (i < listlength)
   {nextelement = float(queuelist1[i]) / fltnewtottrials;
    sprintf(nextstring, "%f", nextelement);                           
    strcat(ans, nextstring);
    strcat(ans, " ");
    i++;
    }  
strcat(ans, ") ( ");
i = 0;
while (i < listlength)
   {nextelement = float(queuelist2[i]) / fltnewtottrials;
    sprintf(nextstring, "%f", nextelement);                           
    strcat(ans, nextstring);
    strcat(ans, " ");
    i++;
    } 
strcat(ans, ") )");
return store(ans);
 

}  


void init_queue()
{
  Define_Primitive(handle_queue_list, "queue_list", 12, 12, EVAL); 
}
