********************************************************************
function: train a VQ codebook
- last mod: $Id: vqgen.c,v 1.33 2000/07/17 12:55:37 xiphmont Exp $
+ last mod: $Id: vqgen.c,v 1.34 2000/10/12 03:13:02 xiphmont Exp $
********************************************************************/
#define vN(data,i) (data+v->elements*i)
/* default metric; squared 'distance' from desired value. */
-double _dist(vqgen *v,double *a, double *b){
+float _dist(vqgen *v,float *a, float *b){
int i;
int el=v->elements;
- double acc=0.;
+ float acc=0.;
for(i=0;i<el;i++){
- double val=(a[i]-b[i]);
+ float val=(a[i]-b[i]);
acc+=val*val;
}
return sqrt(acc);
}
-double *_weight_null(vqgen *v,double *a){
+float *_weight_null(vqgen *v,float *a){
return a;
}
void _vqgen_seed(vqgen *v){
long i;
for(i=0;i<v->entries;i++)
- memcpy(_now(v,i),_point(v,i),sizeof(double)*v->elements);
+ memcpy(_now(v,i),_point(v,i),sizeof(float)*v->elements);
v->seeded=1;
}
int directdsort(const void *a, const void *b){
- double av=*((double *)a);
- double bv=*((double *)b);
+ float av=*((float *)a);
+ float bv=*((float *)b);
if(av>bv)return(-1);
return(1);
}
void vqgen_cellmetric(vqgen *v){
int j,k;
- double min=-1.,max=-1.,mean=0.,acc=0.;
+ float min=-1.,max=-1.,mean=0.,acc=0.;
long dup=0,unused=0;
#ifdef NOISY
int i;
char buff[80];
- double spacings[v->entries];
+ float spacings[v->entries];
int count=0;
FILE *cells;
sprintf(buff,"cellspace%d.m",v->it);
/* minimum, maximum, cell spacing */
for(j=0;j<v->entries;j++){
- double localmin=-1.;
+ float localmin=-1.;
for(k=0;k<v->entries;k++){
if(j!=k){
- double this=_dist(v,_now(v,j),_now(v,k));
+ float this=_dist(v,_now(v,j),_now(v,k));
if(this>0){
if(v->assigned[k] && (localmin==-1 || this<localmin))
localmin=this;
min,mean/acc,max,unused,dup);
#ifdef NOISY
- qsort(spacings,count,sizeof(double),directdsort);
+ qsort(spacings,count,sizeof(float),directdsort);
for(i=0;i<count;i++)
fprintf(cells,"%g\n",spacings[i]);
fclose(cells);
void vqgen_quantize(vqgen *v,quant_meta *q){
- double maxdel;
- double mindel;
+ float maxdel;
+ float mindel;
- double delta;
- double maxquant=((1<<q->quant)-1);
+ float delta;
+ float maxquant=((1<<q->quant)-1);
int j,k;
mindel=maxdel=_now(v,0)[0];
for(j=0;j<v->entries;j++){
- double last=0.;
+ float last=0.;
for(k=0;k<v->elements;k++){
if(mindel>_now(v,j)[k]-last)mindel=_now(v,j)[k]-last;
if(maxdel<_now(v,j)[k]-last)maxdel=_now(v,j)[k]-last;
delta=_float32_unpack(q->delta);
for(j=0;j<v->entries;j++){
- double last=0;
+ float last=0;
for(k=0;k<v->elements;k++){
- double val=_now(v,j)[k];
- double now=rint((val-last-mindel)/delta);
+ float val=_now(v,j)[k];
+ float now=rint((val-last-mindel)/delta);
_now(v,j)[k]=now;
if(now<0){
scales; we just make sure they're properly offset. */
void vqgen_unquantize(vqgen *v,quant_meta *q){
long j,k;
- double mindel=_float32_unpack(q->min);
- double delta=_float32_unpack(q->delta);
+ float mindel=_float32_unpack(q->min);
+ float delta=_float32_unpack(q->delta);
for(j=0;j<v->entries;j++){
- double last=0.;
+ float last=0.;
for(k=0;k<v->elements;k++){
- double now=_now(v,j)[k];
+ float now=_now(v,j)[k];
now=fabs(now)*delta+last+mindel;
if(q->sequencep)last=now;
_now(v,j)[k]=now;
}
}
-void vqgen_init(vqgen *v,int elements,int aux,int entries,double mindist,
- double (*metric)(vqgen *,double *, double *),
- double *(*weight)(vqgen *,double *),int centroid){
+void vqgen_init(vqgen *v,int elements,int aux,int entries,float mindist,
+ float (*metric)(vqgen *,float *, float *),
+ float *(*weight)(vqgen *,float *),int centroid){
memset(v,0,sizeof(vqgen));
v->centroid=centroid;
v->aux=aux;
v->mindist=mindist;
v->allocated=32768;
- v->pointlist=malloc(v->allocated*(v->elements+v->aux)*sizeof(double));
+ v->pointlist=malloc(v->allocated*(v->elements+v->aux)*sizeof(float));
v->entries=entries;
- v->entrylist=malloc(v->entries*v->elements*sizeof(double));
+ v->entrylist=malloc(v->entries*v->elements*sizeof(float));
v->assigned=malloc(v->entries*sizeof(long));
- v->bias=calloc(v->entries,sizeof(double));
- v->max=calloc(v->entries,sizeof(double));
+ v->bias=calloc(v->entries,sizeof(float));
+ v->max=calloc(v->entries,sizeof(float));
if(metric)
v->metric_func=metric;
else
}
-void vqgen_addpoint(vqgen *v, double *p,double *a){
+void vqgen_addpoint(vqgen *v, float *p,float *a){
int k;
for(k=0;k<v->elements;k++)
fprintf(v->asciipoints,"%.12g\n",p[k]);
if(v->points>=v->allocated){
v->allocated*=2;
v->pointlist=realloc(v->pointlist,v->allocated*(v->elements+v->aux)*
- sizeof(double));
+ sizeof(float));
}
- memcpy(_point(v,v->points),p,sizeof(double)*v->elements);
- if(v->aux)memcpy(_point(v,v->points)+v->elements,a,sizeof(double)*v->aux);
+ memcpy(_point(v,v->points),p,sizeof(float)*v->elements);
+ if(v->aux)memcpy(_point(v,v->points)+v->elements,a,sizeof(float)*v->aux);
/* quantize to the density mesh if it's selected */
if(v->mindist>0.){
long i,march=1;
/* sort to make uniqueness detection trivial */
- sortsize=(v->elements+v->aux)*sizeof(double);
+ sortsize=(v->elements+v->aux)*sizeof(float);
qsort(v->pointlist,v->points,sortsize,meshcomp);
/* now march through and eliminate dupes */
v->sorted=1;
}
-double vqgen_iterate(vqgen *v,int biasp){
+float vqgen_iterate(vqgen *v,int biasp){
long i,j,k;
- double fdesired;
+ float fdesired;
long desired;
long desired2;
- double asserror=0.;
- double meterror=0.;
- double *new;
- double *new2;
+ float asserror=0.;
+ float meterror=0.;
+ float *new;
+ float *new2;
long *nearcount;
- double *nearbias;
+ float *nearbias;
#ifdef NOISY
char buff[80];
FILE *assig;
if(!v->sorted)vqgen_sortmesh(v);
if(!v->seeded)_vqgen_seed(v);
- fdesired=(double)v->points/v->entries;
+ fdesired=(float)v->points/v->entries;
desired=fdesired;
desired2=desired*2;
- new=malloc(sizeof(double)*v->entries*v->elements);
- new2=malloc(sizeof(double)*v->entries*v->elements);
+ new=malloc(sizeof(float)*v->entries*v->elements);
+ new2=malloc(sizeof(float)*v->entries*v->elements);
nearcount=malloc(v->entries*sizeof(long));
- nearbias=malloc(v->entries*desired2*sizeof(double));
+ nearbias=malloc(v->entries*desired2*sizeof(float));
/* fill in nearest points for entry biasing */
- /*memset(v->bias,0,sizeof(double)*v->entries);*/
+ /*memset(v->bias,0,sizeof(float)*v->entries);*/
memset(nearcount,0,sizeof(long)*v->entries);
memset(v->assigned,0,sizeof(long)*v->entries);
if(biasp){
for(i=0;i<v->points;i++){
- double *ppt=v->weight_func(v,_point(v,i));
- double firstmetric=v->metric_func(v,_now(v,0),ppt)+v->bias[0];
- double secondmetric=v->metric_func(v,_now(v,1),ppt)+v->bias[1];
+ float *ppt=v->weight_func(v,_point(v,i));
+ float firstmetric=v->metric_func(v,_now(v,0),ppt)+v->bias[0];
+ float secondmetric=v->metric_func(v,_now(v,1),ppt)+v->bias[1];
long firstentry=0;
long secondentry=1;
if(!(i&0xff))spinnit("biasing... ",v->points+v->points+v->entries-i);
if(firstmetric>secondmetric){
- double temp=firstmetric;
+ float temp=firstmetric;
firstmetric=secondmetric;
secondmetric=temp;
firstentry=1;
}
for(j=2;j<v->entries;j++){
- double thismetric=v->metric_func(v,_now(v,j),ppt)+v->bias[j];
+ float thismetric=v->metric_func(v,_now(v,j),ppt)+v->bias[j];
if(thismetric<secondmetric){
if(thismetric<firstmetric){
secondmetric=firstmetric;
j=firstentry;
for(j=0;j<v->entries;j++){
- double thismetric,localmetric;
- double *nearbiasptr=nearbias+desired2*j;
+ float thismetric,localmetric;
+ float *nearbiasptr=nearbias+desired2*j;
long k=nearcount[j];
localmetric=v->metric_func(v,_now(v,j),ppt);
k++;
if(k==desired){
spinnit("biasing... ",v->points+v->points+v->entries-i);
- qsort(nearbiasptr,desired,sizeof(double),directdsort);
+ qsort(nearbiasptr,desired,sizeof(float),directdsort);
}
}else if(thismetric>nearbiasptr[desired-1]){
k++;
if(k==desired2){
spinnit("biasing... ",v->points+v->points+v->entries-i);
- qsort(nearbiasptr,desired2,sizeof(double),directdsort);
+ qsort(nearbiasptr,desired2,sizeof(float),directdsort);
k=desired;
}
}
/* inflate/deflate */
for(i=0;i<v->entries;i++){
- double *nearbiasptr=nearbias+desired2*i;
+ float *nearbiasptr=nearbias+desired2*i;
spinnit("biasing... ",v->points+v->entries-i);
/* due to the delayed sorting, we likely need to finish it off....*/
if(nearcount[i]>desired)
- qsort(nearbiasptr,nearcount[i],sizeof(double),directdsort);
+ qsort(nearbiasptr,nearcount[i],sizeof(float),directdsort);
v->bias[i]=nearbiasptr[desired-1];
}
}else{
- memset(v->bias,0,v->entries*sizeof(double));
+ memset(v->bias,0,v->entries*sizeof(float));
}
/* Now assign with new bias and find new midpoints */
for(i=0;i<v->points;i++){
- double *ppt=v->weight_func(v,_point(v,i));
- double firstmetric=v->metric_func(v,_now(v,0),ppt)+v->bias[0];
+ float *ppt=v->weight_func(v,_point(v,i));
+ float firstmetric=v->metric_func(v,_now(v,0),ppt)+v->bias[0];
long firstentry=0;
if(!(i&0xff))spinnit("centering... ",v->points-i);
for(j=0;j<v->entries;j++){
- double thismetric=v->metric_func(v,_now(v,j),ppt)+v->bias[j];
+ float thismetric=v->metric_func(v,_now(v,j),ppt)+v->bias[j];
if(thismetric<firstmetric){
firstmetric=thismetric;
firstentry=j;