#include <stdlib.h>
#include <fcntl.h>
#include <io.h>
#include <sys\stat.h>
#include <malloc.h>
#include "unh_cmac.h"
#define TRUE 1
#define FALSE 0
#define NUM_CMACS 8
#define MAX_STATE_SIZE 64
#define MAX_RESPONSE_SIZE 8
#define MAX_GEN_SIZE 256
#define RF_TABLE_SIZE 128
static int first_call=TRUE; /* is set to FALSE after init */
static int in_learn=FALSE; /* is set to TRUE while in learn */
static int *ap_a[NUM_CMACS+1]; /* pointers to all cmac memories */
static int *ap; /* pointer to current cmac memory */
static int ap_size[NUM_CMACS+1]; /* sizes in bytes of cmac memories */
static int rsp_size; /* dimension of response vector */
static int gen_size; /* generalization parameter */
static int st_size; /* dimension of input state vector */
static int mem_size; /* # of response vectors in memory */
static int rf_shape; /* code for the receptive field shape */
static int collide; /* TRUE/FALSE control of hash collisions */
static int *qnt; /* pointer to input quantization */
static int *disp; /* pointer to the displacement vector */
static int *rfieldt; /* pointer to the rfield function table */
static unsigned int rndseq[2048]; /* Random number table for hashing */
static unsigned int rndseq2[2048]; /* Random number table for hashing */
static int indexes[MAX_GEN_SIZE]; /* CMAC mapping indexes */
static long rfield[MAX_GEN_SIZE]; /* RF function magnitudes */
static long sum_rfield = 0; /* summed RF function magnitudes */
static long sum2_rfield = 0; /* summed squared RF function magnitudes */
static void stoap(int *state)
{
int i,j,k;
long index,min_d,test_d,rf_index;
long sum;
int hash_tag;
static long base[MAX_STATE_SIZE],qstate[MAX_STATE_SIZE];
if((rf_shape==ALBUS)||(rf_shape==RECTANGULAR))
{
for(i=0;i<st_size;i++)
{
if(state[i]>=0)
{
qstate[i]=state[i]/qnt[i];
}
else
{
qstate[i]=(state[i]-qnt[i]+1)/qnt[i];
}
base[i]=0;
}
for(j=0;j<gen_size;j++)
{
sum = 0;
hash_tag = 0;
for(i=0;i<st_size;i++)
{
if(qstate[i]>=base[i])
index=qstate[i]-((qstate[i]-base[i])%gen_size);
else
index=(qstate[i]+1)+((base[i]-(qstate[i]+1))%gen_size)-gen_size;
index+=(449*i);
index%=2048;
while(index<0)
index+=2048;
sum+=(long)rndseq[(int)index];
if(!collide)
hash_tag+=(int)rndseq2[(int)index];
base[i]+=disp[i];
}
if(hash_tag==0)
hash_tag=1;
indexes[j]=(int)(sum%mem_size);
while(indexes[j]<0)
indexes[j]+=mem_size;
if(!collide)
{
--indexes[j];
k=0;
i=(indexes[j]*(rsp_size+1))+rsp_size;
do
{
if(++indexes[j]>=mem_size)
{
indexes[j]=0;
i=rsp_size;
}
else
{
i+=rsp_size+1;
}
}while((ap[i]!=hash_tag)&&(ap[i]!=0)&&(++k<mem_size));
}
else
{
i=(indexes[j]*(rsp_size+1))+rsp_size;
}
if((in_learn)&&(ap[i]==0))
ap[i]=hash_tag;
}
return;
}
for(i = 0; i < st_size; i++)
{
if(state[i]>=0)
{
qstate[i]=(long)(state[i] / qnt[i]);
}
else
{
qstate[i] = (long)((state[i] - qnt[i] + 1) / qnt[i]);
}
base[i] = 0; /* first RF layer aligned with origen */
}
/* init RF function sums */
sum_rfield = 0;
sum2_rfield = 0;
/* compute a new hashed RF index for each RF layer */
for (j = 0; j < gen_size; j++)
{
sum = 0;
hash_tag = 0;
min_d = (long)1 << ((8 * sizeof(long)) - 2);
/* loop over all dimensions of this RF */
for (i = 0; i < st_size; i++)
{
/* find corner coordinate of excited RF in quantized space */
if (qstate[i] >= base[i])
index = qstate[i] - ((qstate[i] - base[i]) % gen_size);
else
index = (qstate[i] + 1) + ((base[i] - (qstate[i] + 1)) % gen_size) - gen_size;
/* update physical distance to closest side of RF,
and index into RF function table */
test_d = (long)state[i] - (index * (long)qnt[i]);
if (test_d < min_d)
{
min_d = test_d;
rf_index = (RF_TABLE_SIZE * min_d) / ((gen_size * qnt[i]) >> 1);
}
test_d = (((long)gen_size + index) * (long)qnt[i]) - state[i] - 1;
if (test_d < min_d)
{
min_d = test_d;
rf_index = (RF_TABLE_SIZE * min_d) / ((gen_size * qnt[i]) >> 1);
}
/* add table offset for this dimension and wrap around */
index += (449 * i);
index %= 2048;
while (index < 0)
index += 2048;
/* add selected random number to sum */
sum += (long)rndseq[(int)index];
if (!collide)
hash_tag += (int)rndseq2[(int)index];
/* compute displacement of next RF layer in quantized space */
base[i] += disp[i];
}
if (hash_tag == 0) hash_tag = 1;
/* compute psuedo-random index */
indexes[j] = (int)(sum % mem_size);
while (indexes[j] < 0)
indexes[j] += mem_size;
/* now search for hash tag match or open slot */
if (!collide)
{
--indexes[j];
k = 0;
i = (indexes[j] * (rsp_size + 1)) + rsp_size;
do
{
if (++indexes[j] >= mem_size)
{
indexes[j] = 0;
i = rsp_size;
}
else
{
i += rsp_size + 1;
}
} while ((ap[i] != hash_tag) && (ap[i] != 0) && (++k < mem_size));
}
else
{
i = (indexes[j] * (rsp_size + 1)) + rsp_size;
}
/* mark used memory location */
if ((in_learn) && (ap[i] == 0))
ap[i] = hash_tag;
/* update RF function parameters */
if (rf_index >= RF_TABLE_SIZE)
rf_index = RF_TABLE_SIZE - 1;
rfield[j] = rfieldt[rf_index];
sum_rfield += rfieldt[rf_index];
sum2_rfield += ((long)rfieldt[rf_index] * (long)rfieldt[rf_index]);
}
}
static void setup(int cmac_id)
{
ap=ap_a[cmac_id]; /* pointer to cmac storage */
st_size=*ap++; /* size of input state vector */
rsp_size=*ap++; /* dimension of response vector */
gen_size=*ap++; /* generalization parameter */
mem_size=*ap++; /* # of response vectors in memory */
rf_shape=*ap++; /* receptive field code */
collide=*ap++; /* allow hashing collisions ??? */
qnt=ap; /* pointer to quantization vector */
ap+=st_size;
disp=ap; /* pointer to displacement vector */
ap+=st_size;
rfieldt=ap; /* pointer to rf function table */
ap+=RF_TABLE_SIZE; /* pointer to CMAC weights */
}
static void genmap(void)
{
int i, k;
srand(1);
for(k=0;k<2048;k++)
{
rndseq[k]=0;
for(i=0;i<sizeof(int);++i)
rndseq[k]=(rndseq[k]<<8)|(rand()&0xff);
}
for(k=0;k<2048;k++)
{
rndseq2[k] = 0;
for(i=0;i<sizeof(int);++i)
rndseq2[k]=(rndseq2[k]<<8)|(rand()&0xff);
}
}
/***************************************************************************
* Purpose: Initialize lattice displacement vector *
***************************************************************************/
static void init_disp_vector(int dv[],int num_state,int field_shape)
{
int i;
if(field_shape==ALBUS)
{
for(i=0;i<num_state;++i)
dv[i]=1;
}
else
{
for(i=0;i<num_state;++i)
dv[i]=1+(2*i);
}
}
static void init_rfield_table(int rf[],int table_size,int field_shape)
{
int i;
long il;
/* set default constant field magnitude */
for (i=0; i<table_size; ++i) rf[i] = 1;
/* now handle special non-constant cases */
if (field_shape == LINEAR)
{
for (i