/***********************************
  (C) Copyright 1992-1993; dit/upm
   Distributed under the conditions stated in the
   TOPO General Public License (see file LICENSE)
 ***********************************
 $Log: offers.c,v $
 * Revision 2.5  1993/06/23  15:44:45  lotos
 * modify kaos drawing interface
 *
 * Revision 2.4  1993/01/18  18:25:53  lotos
 * distribution issues
 *
 * Revision 2.3  1993/01/12  14:38:35  lotos
 * minor bug fixing
 *
 * Revision 2.2  1992/11/17  17:27:06  lotos
 * var -> rav
 * success -> xto
 * distinguish kdatum / udatum
 *
 * Revision 2.1  1992/10/20  17:49:56  lotos
 * new KT evaluation algorithm
 * new Lbeta interface
 * cleaning, code optimization, space saving, bugs, ...
 *
 * Revision 1.9  1992/09/02  17:38:31  lotos
 * uses sort list id
 *
 * Revision 1.8  1992/05/07  19:53:10  lotos
 * initialization of structures revisited for completeness
 *
 * Revision 1.7  92/05/06  18:55:00  lotos
 * send traces to stderr
 * make min-delay functionality upward compatible
 * 
 * Revision 1.6  92/03/05  17:37:12  lotos
 * just a few more bugs went to the hell
 * 
 * Revision 1.5  92/03/04  14:52:58  lotos
 * 100 minor bugettes
 * 
 * Revision 1.4  92/03/03  19:55:33  lotos
 * minor bug fixing
 * 
 * Revision 1.3  92/02/29  13:26:16  lotos
 * miscellaneous bug fixing
 * 
 * Revision 1.2  92/02/12  18:47:51  lotos
 * ni idea, era una version que andaba por ahi ...
 * 
 * Revision 1.1  92/01/14  19:26:46  lotos
 * Initial revision
 * 
 ***********************************/

#ifndef lint
static char rcsid[]= "$Id: offers.c,v 2.5 1993/06/23 15:44:45 lotos Exp $";
#endif

#include "swbus.h"
/* LINTLIBRARY */

PRIVATE offert  andf      ();
PRIVATE int     prd_test  ();

#define new_arena() (arena) my_malloc (sizeof (st_arena))

  /*------------------------------------------------
    ------------------------------------------------
    --           OBJECT MANAGEMENT                --
    ------------------------------------------------
    ------------------------------------------------*/
  
PUBLIC void 
  or_off (b,o1)
board b;
offert  o1;
{
   offert o2;
   offert o3;
  
  if (o1 == NULL)
    return;

  for(o3 = b->offer;o1 != NULL; o1=o1->next) {
    o2= a_cpoff (o1);
    o2->next = o3;
    o3 = o2;
  }
  b->offer= o3;
}

 /* ------------------------ */
 
PUBLIC offert
  and_off (off1, off2)
offert off1;
offert off2;

{
    offert  offert4 = NULL;
    offert  offert3;
    register  offert  ioff1;
    register  offert  ioff2;
 
  if (off1 == NULL || off2 == NULL)
    return NULL;

  for (ioff1=off1; ioff1 != NULL; ioff1 = ioff1->next) {
    for (ioff2=off2; ioff2 != NULL; ioff2 = ioff2->next) {
      offert3=  andf (ioff1,ioff2);
      if (offert3 != NULL) {      
	offert3->next = offert4;
	offert4       = offert3;
      }
    }
  }
  return offert4;
}

 /* ------------------------ */

PRIVATE offert
  andf (ioff1, ioff2)
offert ioff1;
offert ioff2;

{
  offert  offert3;
  register  int i1;
  register  int i;
  int       expcnt = TSsizes[ioff1->sort_id];
  int res1;
  int res2;
  int srt;

  if ((ioff1->adg != ioff2->adg) || (ioff1->sort_id != ioff2->sort_id)) 
    return NULL;

  for (i=0; i< expcnt; i++) {
    srt = TSsbes[ioff1->sort_id][i];
    if ( (ioff1->exp[i]->class == '!') && (ioff2->exp[i]->class == '!')) 
      if ( !( (ioff1->exp[i]->val ==   ioff2->exp[i]->val  ) ||
	     (ud_equal (srt, ioff1->exp[i]->val,
			ioff2->exp[i]->val))))
	return NULL;
  }

  for (i=0; i< expcnt; i++) {
   if(ioff1->exp[i]->class == '!')
     xto[i]=ioff1->exp[i]->val;
   else
     if(ioff2->exp[i]->class == '!')
       xto[i]=ioff2->exp[i]->val;
   else
     xto[i] = NULL;
  }

  res1 = prd_test (ioff1);
  res2 = prd_test (ioff2);

  if (res1 == FALSE || res2 == FALSE)
    return NULL;


  /* ------ build  a new  offert  ------ */

  offert3         = a_newoff ();

  offert3->adg     = ioff1->adg;
  offert3->sort_id = ioff1->sort_id;
  offert3->exp     = a_newexpa ();
 if (abs(ioff1->prior) > abs(ioff2->prior))
   offert3->prior = ioff1->prior;
 else
   offert3->prior = ioff2->prior;
  
  for (i=0;i< expcnt;i++) { 
    if (ioff1->exp[i]->class == '!') 
      offert3->exp[i]= ioff1->exp[i]; 
    else {
      if (ioff2->exp[i]->class == '!') 
	offert3->exp[i]= ioff2->exp[i]; 
      else {
	if (ioff1->exp[i]->class == 'd') 
	  offert3->exp[i]= ioff1->exp[i]; 
	else {
	  if (ioff2->exp[i]->class == 'd') 
	    offert3->exp[i]= ioff2->exp[i]; 
	  else {
	    offert3->exp[i] = a_newexp (); /* */
	    offert3->exp[i]->class= '*';
	  }
	}
      } 
    }
  }
  
  
  offert3->f_eval    =  ioff1->f_eval    || ioff2->f_eval;
  offert3->f_prd     =  ioff1->f_prd     || ioff2->f_prd;

  offert3->f_prd_ok  = ((res1 == TRUE) && (res2 == TRUE));
  
  offert3->actn = ioff1->actn + ioff2->actn;
  offert3->act  = a_newbar (offert3->actn);
  
  for(i1=0; i1 < ioff1->actn; i1 ++) 
    offert3->act[i1]=ioff1->act[i1];	
  for(i1=0; i1 < ioff2->actn; i1 ++) 
    offert3->act[i1+ioff1->actn]=ioff2->act[i1];
  
  return offert3;
  
}      

  /*------------------------------------------------
    ------------------------------------------------
    --             MEMORY MANAGEMENT             --
    ------------------------------------------------
    ------------------------------------------------*/
PUBLIC int max_exp;


PRIVATE offert free_offert = NULL;
PRIVATE experiment free_experiment = NULL;
PRIVATE exp_list  free_expa = NULL;
PRIVATE board_list  free_bar = NULL;

PRIVATE int max_board = 1;

#define OFF_BUCK   200
#define EXP_BUCK   200
#define EXPA_BUCK  200
#define BAR_BUCK   200

       /*  --         CREATE        -- */

offert  
newoff ()
{
  register  offert f;
  register  int  i;

  if (free_offert == NULL)  {
    f =(offert)my_malloc(sizeof(st_offert)* OFF_BUCK);
    free_offert = f;
    for (i=0;i < (OFF_BUCK -1);i++)
      f[i].mmg= &f[i+1];
    f[OFF_BUCK -1].mmg= NULL;
  }
  f= free_offert;
  free_offert = f->mmg;

  f->next     = NULL;
  f->mmg      = NULL;
  f->prior    = 0;
  f->f_eval   = FALSE;
  f->f_prd    = FALSE;
  f->f_prd_ok = FALSE;
  f->but      = 0;
  f->enable   = NULL;
  f->exp      = NULL;
  f->adg      = NO_GTE;
  f->prior    = 0;
  f->act      = newbar();
  f->actn     = 1;

  return f;
}

/***************  experiment  ******************/

experiment 
  newexp ()
{
   experiment e;
  register int i;
  
  if (free_experiment == NULL)  {
    e =(experiment)my_malloc(sizeof(st_experiment)* EXP_BUCK);
    free_experiment = e;
    for (i=0;i < (EXP_BUCK -1);i++)
      e[i].mmg= &e[i+1];
    e[EXP_BUCK -1].mmg= NULL;
  }
  e= free_experiment;
  free_experiment = e->mmg;
  
  return e;
 }

/* experiment list */

exp_list
  newexpa ()

{
   exp_list  e;
  register int i; 

  if (free_expa == NULL ) {
    e = (exp_list)my_malloc (EXPA_BUCK * max_exp * sizeof(experiment));
    free_expa    = e;
    for (i=0; i< EXPA_BUCK; i ++) 
      e[i * max_exp] = (experiment) & e[ (i+1) * max_exp];
    e[(EXPA_BUCK -1)* max_exp] = (experiment) NULL;
  }
  e = free_expa;
  free_expa = (exp_list) e[0];

  return e;
}

       /*  --         DESTROY       -- */

void 
  freeoff (o)
offert o;

{
  freeexpa (o->exp, o->sort_id);
  o->exp = NULL;
  o->act[0]= (board) free_bar;
  free_bar = o->act;
  o->act = NULL;
  o->mmg = free_offert;
  free_offert = o;

}

/* experiment list */

void 
  freeexpa (ea,s_id)
exp_list ea; 
int s_id;
{
  register  int i;

  if (ea == NULL)
    return;

  for(i=0;i<TSsizes[s_id];i++) {
    if (ea[i]->class == '!') 
      ud_free (TSsbes[s_id][i], ea[i]->val);
    ea[i]->mmg         = free_experiment;
    free_experiment = ea[i];
  }
  ea[0]= (experiment) free_expa;
  free_expa = ea;
}

 
board_list  
  newbar ()
{
  
   board_list  b;
  register int i; 
  
  if (free_bar == NULL ) {
    b = (board_list)my_malloc (BAR_BUCK * max_board * sizeof(board));
    free_bar    = b;
    for (i=0; i< BAR_BUCK; i ++) 
      b[i * max_board] = (board) & b[ (i+1) * max_board];
    b[(BAR_BUCK -1)* max_board] = (board) NULL;
  }
  
  b = free_bar;
  free_bar = (board_list) b[0];
  
  return b;
}



       /*  --        COPY         -- */

PUBLIC offert 
a_cpoff (o)
offert o;
{
  register offert off= a_newoff ();

  off->adg      =  o->adg;
  off->sort_id  =  o->sort_id;
  off->exp      =  o->exp;
  off->prd      =  o->prd;
  off->f_eval   =  o->f_eval;
  off->f_prd    =  o->f_prd;
  off->f_prd_ok =  o->f_prd_ok;
  off->prior    =  o->prior;
  off->act      =  o->act; 
  off->actn     =  o->actn; 
  off->enable   =  o->enable;
  off->next     =  NULL;
  return off; 
}
       /*  --        OTHERS         -- */

PRIVATE arena init_aoff = NULL;
PRIVATE arena a_off     = NULL;
PRIVATE int   a_off_index = 0;
#define OFF_A_SIZE 50


PRIVATE arena init_aexp = NULL;
PRIVATE arena a_exp     = NULL;
PRIVATE int   a_exp_index = 0;
#define EXP_A_SIZE 50


PRIVATE arena init_aexpa = NULL;
PRIVATE arena a_expa     = NULL;
PRIVATE int   a_expa_index = 0;
#define EXPA_A_SIZE 50



PRIVATE arena init_abar = NULL;
PRIVATE arena a_bar     = NULL;
PRIVATE int   a_bar_index = 0;
#define BAR_A_SIZE 1000

void 
  reset_mmg ()
{
  reset_freerqe   ();

  a_off = init_aoff;
  a_off_index = 0;

  a_exp = init_aexp;
  a_exp_index = 0;

  a_expa = init_aexpa;
  a_expa_index = 0;

  a_bar = init_abar;
  a_bar_index = 0;
}


PUBLIC
offert  
  a_newoff ()
{
  register  offert f;
  offert aux;

  if (a_off->counter < 1) {
    if (a_off->next != NULL) {
      a_off = a_off->next;
      a_off->counter = OFF_A_SIZE;
      a_off_index = 0;
    } else {
      a_off->next = new_arena();
      a_off = a_off->next;
      a_off->counter = OFF_A_SIZE;
      a_off->field   = (void *) my_malloc (OFF_A_SIZE * sizeof(st_offert));
      a_off->next    = NULL;
      a_off_index = 0;
    }      
  } 

  a_off->counter --;
  aux = (offert) a_off->field;
  f =(offert) ( & aux[a_off_index ++]);


  f->next     = NULL;
  f->mmg      = NULL;
  f->prior    = 0;
  f->f_eval   = FALSE;
  f->f_prd    = FALSE;
  f->f_prd_ok = FALSE;
  f->but      = 0;
  f->enable   = NULL;
  f->exp      = NULL;

  return f;
}


PUBLIC
experiment  
  a_newexp ()
{
  register  experiment f;
  experiment aux;

  if (a_exp->counter < 1) {
    if (a_exp->next != NULL) {
      a_exp = a_exp->next;
      a_exp->counter = EXP_A_SIZE;
      a_exp_index = 0;
    } else {
      a_exp->next = new_arena();
      a_exp = a_exp->next;
      a_exp->counter = EXP_A_SIZE;
      a_exp->field   = (void *) my_malloc (EXP_A_SIZE * sizeof(st_experiment));
      a_exp->next    = NULL;
      a_exp_index = 0;
    }      
  } 

  a_exp->counter --;
  aux = (experiment) a_exp->field;
  f =(experiment) ( & aux[a_exp_index ++]);
  
  return f;
}


PUBLIC exp_list  
  a_newexpa ()
{
  register  exp_list f;
  exp_list aux;

  if (a_expa->counter < max_exp) {
    if (a_expa->next != NULL) {
      a_expa = a_expa->next;
      a_expa->counter = EXPA_A_SIZE;
      a_expa_index = 0;
    } else {
      a_expa->next = new_arena();
      a_expa = a_expa->next;
      a_expa->counter = EXPA_A_SIZE;
      a_expa->field   = (void *) my_malloc (EXPA_A_SIZE * sizeof(experiment));
      a_expa->next    = NULL;
      a_expa_index = 0;
    }      
  } 

  a_expa->counter =   a_expa->counter - max_exp;
  aux = (exp_list) a_expa->field;
  f =(exp_list) ( & aux[a_expa_index]);
  a_expa_index = a_expa_index + max_exp;
  
  return f;
}


PUBLIC board_list  
  a_newbar (n)
int n;
{
  register  board_list f;
  board_list aux;
 
 if (n >= BAR_A_SIZE) {
   (void) fprintf (stderr, " arena overflow \n");
   exit (1);
 }

  if (a_bar->counter < n) {
    if (a_bar->next != NULL) {
      a_bar = a_bar->next;
      a_bar->counter = BAR_A_SIZE;
      a_bar_index = 0;
    } else {
      a_bar->next = new_arena();
      a_bar = a_bar->next;
      a_bar->counter = BAR_A_SIZE;
      a_bar->field   = (void *) my_malloc (BAR_A_SIZE * sizeof(board));
      a_bar->next    = NULL;
      a_bar_index = 0;
    }      
  } 

  a_bar->counter =   a_bar->counter - n;
  aux = (board_list) a_bar->field;
  f =(board_list) ( & aux[a_bar_index]);
  a_bar_index = a_bar_index +n;

  return f;
}
  
  /*------------------------------------------------
    ------------------------------------------------
    --                    DRAW                    --
    ------------------------------------------------
    ------------------------------------------------*/

  
void  
  dump_off (fp, o)
FILE * fp; 
offert o;
{
 int j;

 if (o != NULL) {
   (void) fprintf (fp, "offert= [ %d  ", o->adg);

   for (j=0; j< TSsizes[o->sort_id]; j++) {
     if (o->exp[j]->class == '!') 
	  (void) fprintf (fp, " ! %s", 
                  draw (TSsbes[o->sort_id][j], o->exp[j]->val)); 
     if (o->exp[j]->class == '?') 
       (void) fprintf (fp, "? %d", o->exp[j]->rav);
     if (o->exp[j]->class == '*') 
       (void) fprintf (fp, "*");
     
     if (o->prd != NO_PRD) 
       (void) fprintf (fp," [ %d ]", o->prd);
   }
   if (o->f_eval)   
     (void) fprintf (fp," eval");  	
   if (o->f_prd) 
     (void) fprintf (fp," pred"); 
   
   (void) fprintf (fp, " ]");
   
   (void) fprintf (fp, "\n");
   for (j=0; j<  o->actn; j++) 
     dump_node (fp, o->act[j]);
   (void) fprintf     (fp,"------------------\n");
   dump_off(fp, o->next);
 } 
}
  
void  
draw_off (o)
offert o;
{
  dump_off (stderr, o);
}

PUBLIC void 
arena_init ()
{
  if (a_off == NULL) {
    a_off = new_arena();
    a_off->next = NULL;
    a_off->counter = OFF_A_SIZE;
    a_off->field   = (void*) my_malloc (OFF_A_SIZE * sizeof(st_offert));
    a_off->next    = NULL;
    init_aoff = a_off;
    a_off_index = 0;
    
    a_exp = new_arena();
    a_exp->next = NULL;
    a_exp->counter = EXP_A_SIZE;
    a_exp->field   = (void *) my_malloc (EXP_A_SIZE * sizeof(st_experiment));
    a_exp->next    = NULL;
    init_aexp = a_exp;
    a_exp_index = 0;
    
    a_bar = new_arena();
    a_bar->next = NULL;
    a_bar->counter = BAR_A_SIZE;
    a_bar->field   = (void *) my_malloc (BAR_A_SIZE * sizeof(board));
    a_bar->next    = NULL;
    init_abar = a_bar;
    a_bar_index = 0;
    
    a_expa = new_arena();
    a_expa->next = NULL;
    a_expa->counter = EXPA_A_SIZE;
    a_expa->field   = (void*) my_malloc (EXPA_A_SIZE * sizeof(experiment));
    a_expa->next    = NULL;
    init_aexpa = a_expa;
    a_expa_index = 0;
  }
}

PRIVATE int
prd_test (o)
offert o;
{
  register int  i;
  int prd;
  int res;
  boolean not_ready = FALSE;

  if (o->f_prd) {
    if(o->f_prd_ok)
      return TRUE;
    for (i=0; i < o->actn; i++) {
      prd = o->act[i]->offer->prd;
      if  (prd != NO_PRD) {
	res = ftbl[prd](o->act[i]->frm);
	if (res == FALSE)
	  return FALSE;
	else if (res == PRD_NRDY)
	  not_ready = TRUE;
      }
    }
  }

  if (not_ready)
    return PRD_NRDY;
  else
    return TRUE;
}



PUBLIC void *
 my_malloc (n)
int n;
{
 void * v;
 assert (n >0);
 
 v = (void *) malloc(n);
 if (v == NULL) {
   fprintf(stderr,"Out of Memory\n");
   exit (1);
 }
 return v;
}

PUBLIC char * 
draw (s,n)
int s;
value n;
{
  char * aux;
  
  aux = ud_draw (s,n);
  if (aux == NULL)
    aux = "...";
  return aux;
}
