
/* modified on 3 February 2001 by Peter Hakel */
/* modified by Manolo Sherrill */

#include <stdio.h>
#include "const.h"
#include "type.h"
#include "extern.h"
#include "exfunc.h"
#include <stdlib.h>
#include <math.h>

/*==================================================================*/
/*                      Parameter queue                             */

/* This is an array-based queue of size popsize, where each queue
   element is an array (of double's) of size nvars. The purpose of
   this queue is to calculate and store the variable portion of the
   plistin array for each individual in a given generation.

   This queue requires popsize enqueues followed by popsize dequeues.
   This cycle is executed once for each generation.                 */

double **paramin;
/* 2-D array, dynamically allocated only once (at the beginning),
   updated once for each generation with values of plistin.
   1st index: individual index (range: 0 through popsize-1)
   2nd index: variable parameter index (range: 0 through nvars-1)   */

int cursor;
/* cursor points at the processed individual ON ENTRY to enqueue
   and dequeue (range: 0 through popsize-1).                        */
/*==================================================================*/

void initqueue()
/* constructor, creates empty queue */
{
  int i;

  cursor = 0;
  paramin = malloc(popsize*sizeof(double *));
  if ( paramin == NULL )
  {
     printf("error in memory allocation for paramin");
     exit(1);
  }

  for ( i=0; i<popsize; i++ )
  {
    paramin[i] = (double *)malloc(nvars*sizeof(double));
    if ( paramin[i] == NULL )
    {
       printf("error in memory allocation for paramin [%d]",&i);
       exit(1);
    }
  }
}

void enqueue(int *pj)
/* calculates and stores the variable portion of the plistin array based on chromosome pj */
{
  int i;       /* variable parameter index (range: 0 through nvars-1)               */
  int ist;     /* starting position (bit) of a chromosome section for i-th variable */
  double val1; /* decimal value of a chromosome section for i-th variable           */

  ist = 0;
  for ( i=0; i<nvars; i++ )
  {
    val1 = decode(pj,ist,lchrom[i]);
    ist += lchrom[i];
    switch ( grid[i] )
    { /* convert val1 to actual variable parameter value plistin[i] */
    case 'i':
      plistin[i] = plower[i] + (pupper[i]-plower[i])*val1/(pow((double)2.0,(double)lchrom[i]) - (double)1.0);
      break;
    case 'o':
      plistin[i] = exp(plower[i] + (pupper[i]-plower[i])*val1/(pow((double)2.0,(double)lchrom[i]) - (double)1.0));
      break;
    case 't':
      plistin[i] = other(i,val1);
      break;
    default:    /* this branch should never be reached */
      plistin[i] = plower[i];
      break;
    }

    paramin[cursor][i] = plistin[i];   /* put plistin[i] on the queue */
  }

  cursor++;
  if ( cursor == popsize ) cursor = 0; /* queue is full, reset cursor for dequeueing */
}

void p_dequeue()
{
  int i,j;
  int ii;
  double paraminlin[10000];
  double paraminlout[10000];
  j=0;
  for ( ii=0; ii<popsize; ii++ )
  {
     for ( i=0; i<nvars; i++ ) {
         plistin[i] = paramin[cursor][i];
     }
     cursor++; if ( cursor == popsize ) cursor = 0;
     for ( i=0; i<nin; i++ ) {
         paraminlin[j] = plistin[i];
         j++;
     } 
  }
  subfort_(&maxgen,&popsize,&nin,&nout,paraminlin,paraminlout);
  for (ii=0; ii<popsize; ii++) { fitarray[ii]=paraminlout[(ii*nout)]; } 
   
}

double other(int i, double val1)
/* other than linear or logarithmic mapping of val1 to variable parameter value */
{
/* switch (i) {code here the special mapping of val1 into plistin[i] for i-th variable} */
  return 0.0;
}

double decode(int *pj, int i, int size)
{
double vald;
vald=(double) bin_to_dec(pj+i, size);
  return vald;
}

double bin_to_dec(int *chrom, int l)
{
  int i;
  double prod;

  prod = 0.0;

  for(i = 0; i < l; i++){
    prod += (chrom[i] == 0 ? 0.0 : pow((double)2.0, (double) i));
  }
  return prod;
}

void dec_to_bin(int ad, int *barray, int size)
{
  int i, t;

  t = ad;
  for(i = 0; i < size; i++){
    barray[i] = t%2;
    t = t/2;
  }
}

