#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <limits.h>
#include <float.h>

#include <time.h>


/* context descriptor linear combination */
#define MIX_CONTEXT_WEIGHT(NEURON,INDEX) \
 (mix_c_w * (NEURON) -> context[INDEX] + (1-mix_c_w) * (NEURON) -> coord[INDEX])

/* exponential histogram decrement time */
#define HISTDEC 1000

/* for entropy-based context influence param control */
#define CONTEXT_ETA_MUL_INC 1.025
#define CONTEXT_ETA_MUL_SUB 0.9

/* minimum neighborhood size */
#define NEIGEPS 1e-5

/* Ignore-less-than-speedup - exp(-NST) - threshold */
#define NEIGSPEEDTHRESH 30



/************** the following is of minor interest ****************************/

#define inline __inline

#define error(X) fprintf(stderr, (X)), exit(1)
#define panic(X) neuronsfree(), error((X))
#define frand() ((double) rand() / ((double)RAND_MAX + 1.0))
#define irand(X) ((int)((double)(X) * frand()))

typedef struct NEURON_TYPE *NEURON;

typedef struct NEURON_TYPE {
  int      idx;                   /* neuron index */
  double   dist;                  /* distance to pattern */
  double   activation;            /* activation for this neuron */
  double   *context;              /* representing compressed context */
  double   *coord;                /* codebook-coordinates */
} NEURON_TYPE;

NEURON *neurons,
       lastwinner;                /* for handling the last winner (context) */

double **pattern,                 /* contains float data from STDIN */
       inc_activation,            /* increment of activation counter */
       inc_activation_inc,        /* increment of activation counter increment */
       total_activation;          /* sum of all activations */


int pattern_dimension;            /* dimension of data set */


int training_cycles,     /* training_cycles so far */
    total_iterations,    /* total number of cycles */
    phase;               /* phase 0: training weight, phase 1 train context */

double rate_eta,                       /* coordinate adaptation rate */
       rate_neighborhood_annealing,    /* about 0.9x decay rate */
       context_eta,                    /* control: context_eta * context */
       mix_c_w,                        /* mixer for compound context/weight */
       rate_context;                   /* context * adaptation rate */

int moduloprint;         /* if > 0 : print learning trace */

unsigned randseed;

double neighborhood_size;


int neurons_no,
    neurons_lastindex;



/******************************************************************************/

unsigned randomize();

void pattern_free(int);

/******************************************************************************/



unsigned randomize() {

  int srd, tmp;  /* auto-variable: not initialized -> random */
                 /* Compiler Warnings are welcome here ! */
  time_t t;
  struct tm *ts;

  time(&t);
  ts = localtime(&t);

  tmp = ts->tm_mday | (ts->tm_min << 6) | (ts->tm_sec << 12);

  if(srd == 0)
    srd |= tmp;
  else
    srd *= tmp;

  srand((unsigned)srd);

  return (unsigned)srd;
}
/******************************************************************************/
